38 vk::ClearColorValue
value;
46 vk::ClearDepthStencilValue
value;
48 value.stencil = stencil;
58 const auto& rect = viewport.
rect;
61 .setY(rect.GetY() + rect.GetHeight())
62 .setWidth(rect.GetWidth())
63 .setHeight(-rect.GetHeight())
70 std::array<vk::ClearValue, kMaxAttachments>& values) {
72 target.IterateAllColorAttachments(
73 [&values, &offset](
size_t index,
82 const auto& depth =
target.GetDepthAttachment();
83 const auto& stencil =
target.GetStencilAttachment();
85 if (depth.has_value()) {
87 stencil ? stencil->clear_stencil : 0u, depth->clear_depth);
88 }
else if (stencil.has_value()) {
90 stencil->clear_stencil, depth ? depth->clear_depth : 0.0f);
95SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
96 const ContextVK& context,
97 const SharedHandleVK<vk::RenderPass>& recycled_renderpass,
98 const std::shared_ptr<CommandBufferVK>& command_buffer,
99 bool is_swapchain)
const {
100 if (recycled_renderpass !=
nullptr) {
101 return recycled_renderpass;
104 RenderPassBuilderVK builder;
106 const ColorAttachment&
107 attachment) ->
bool {
108 builder.SetColorAttachment(
110 attachment.texture->GetTextureDescriptor().format,
111 attachment.texture->GetTextureDescriptor().sample_count,
112 attachment.load_action,
113 attachment.store_action,
120 builder.SetDepthStencilAttachment(
121 depth->texture->GetTextureDescriptor().format,
122 depth->texture->GetTextureDescriptor().sample_count,
127 stencil.has_value()) {
128 builder.SetStencilAttachment(
129 stencil->texture->GetTextureDescriptor().format,
130 stencil->texture->GetTextureDescriptor().sample_count,
131 stencil->load_action,
132 stencil->store_action
136 auto pass = builder.Build(context.GetDevice());
139 VALIDATION_LOG <<
"Failed to create render pass for framebuffer.";
143 context.SetDebugName(pass.get(), debug_label_.c_str());
148RenderPassVK::RenderPassVK(
const std::shared_ptr<const Context>& context,
149 const RenderTarget&
target,
150 std::shared_ptr<CommandBufferVK> command_buffer)
151 : RenderPass(context,
target), command_buffer_(
std::move(command_buffer)) {
152 const ColorAttachment& color0 = render_target_.GetColorAttachment(0);
153 color_image_vk_ = color0.texture;
154 resolve_image_vk_ = color0.resolve_texture;
157 command_buffer_vk_ = command_buffer_->GetCommandBuffer();
158 render_target_.IterateAllAttachments([&](
const auto& attachment) ->
bool {
159 command_buffer_->Track(attachment.texture);
160 command_buffer_->Track(attachment.resolve_texture);
164 FramebufferAndRenderPass frame_data;
165 bool is_swapchain =
false;
167 color_image_vk_->GetTextureDescriptor().sample_count;
168 if (resolve_image_vk_) {
178 const auto& target_size = render_target_.GetRenderTargetSize();
180 render_pass_ = CreateVKRenderPass(vk_context, frame_data.render_pass,
181 command_buffer_, is_swapchain);
188 auto framebuffer = (frame_data.framebuffer ==
nullptr)
189 ? CreateVKFramebuffer(vk_context, *render_pass_)
190 : frame_data.framebuffer;
197 if (!command_buffer_->Track(framebuffer) ||
198 !command_buffer_->Track(render_pass_)) {
203 frame_data.framebuffer = framebuffer;
204 frame_data.render_pass = render_pass_;
206 if (resolve_image_vk_) {
216 if (resolve_image_vk_ &&
217 resolve_image_vk_->GetTextureDescriptor().mip_count > 1) {
219 vk::ImageLayout::eUndefined) {
221 barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
222 barrier.cmd_buffer = command_buffer_->GetCommandBuffer();
223 barrier.src_stage = vk::PipelineStageFlagBits::eBottomOfPipe;
224 barrier.src_access = {};
225 barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
226 barrier.dst_access = vk::AccessFlagBits::eShaderRead;
227 barrier.base_mip_level = 1;
232 std::array<vk::ClearValue, kMaxAttachments> clears;
235 vk::RenderPassBeginInfo pass_info;
236 pass_info.renderPass = *render_pass_;
237 pass_info.framebuffer = *framebuffer;
238 pass_info.renderArea.extent.width =
static_cast<uint32_t
>(target_size.width);
239 pass_info.renderArea.extent.height =
240 static_cast<uint32_t
>(target_size.height);
241 pass_info.setPClearValues(clears.data());
242 pass_info.setClearValueCount(clear_count);
244 command_buffer_vk_.beginRenderPass(pass_info, vk::SubpassContents::eInline);
246 if (resolve_image_vk_) {
249 is_swapchain ? vk::ImageLayout::eGeneral
250 : vk::ImageLayout::eShaderReadOnlyOptimal);
252 if (color_image_vk_) {
263 ? vk::ImageLayout::eGeneral
264 : vk::ImageLayout::eShaderReadOnlyOptimal);
270 command_buffer_vk_.setViewport(0, 1, &viewport);
276 .setOffset(vk::Offset2D(sc.GetX(), sc.GetY()))
277 .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight()));
278 command_buffer_vk_.setScissor(0, 1, &scissor);
281 command_buffer_vk_.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
287RenderPassVK::~RenderPassVK() =
default;
289bool RenderPassVK::IsValid()
const {
293void RenderPassVK::OnSetLabel(std::string_view label) {
295 ContextVK::Cast(*context_).SetDebugName(render_pass_->Get(), label.data());
299SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
300 const ContextVK& context,
301 const vk::RenderPass& pass)
const {
302 vk::FramebufferCreateInfo fb_info;
304 fb_info.renderPass = pass;
306 const auto target_size = render_target_.GetRenderTargetSize();
307 fb_info.width = target_size.width;
308 fb_info.height = target_size.height;
311 std::array<vk::ImageView, kMaxAttachments> attachments;
317 render_target_.IterateAllColorAttachments(
318 [&attachments, &count](
size_t index,
319 const ColorAttachment& attachment) ->
bool {
322 attachments[count++] =
323 TextureVK::Cast(*attachment.texture).GetRenderTargetView();
324 if (attachment.resolve_texture) {
325 attachments[count++] = TextureVK::Cast(*attachment.resolve_texture)
326 .GetRenderTargetView();
331 if (
auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
332 attachments[count++] =
333 TextureVK::Cast(*depth->texture).GetRenderTargetView();
334 }
else if (
auto stencil = render_target_.GetStencilAttachment();
335 stencil.has_value()) {
336 attachments[count++] =
337 TextureVK::Cast(*stencil->texture).GetRenderTargetView();
340 fb_info.setPAttachments(attachments.data());
341 fb_info.setAttachmentCount(count);
343 auto [result, framebuffer] =
344 context.GetDevice().createFramebufferUnique(fb_info);
346 if (result != vk::Result::eSuccess) {
347 VALIDATION_LOG <<
"Could not create framebuffer: " << vk::to_string(result);
355void RenderPassVK::SetPipeline(PipelineRef pipeline) {
356 pipeline_ = pipeline;
360 context_->GetPipelineLibrary()->LogPipelineUsage(pipeline->GetDescriptor());
362 pipeline_uses_input_attachments_ =
363 pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttachments();
365 if (pipeline_uses_input_attachments_) {
366 if (bound_image_offset_ >= kMaxBindings) {
370 vk::DescriptorImageInfo image_info;
371 image_info.imageLayout = vk::ImageLayout::eGeneral;
372 image_info.sampler = VK_NULL_HANDLE;
373 image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView();
374 image_workspace_[bound_image_offset_++] = image_info;
376 vk::WriteDescriptorSet write_set;
378 write_set.descriptorCount = 1u;
379 write_set.descriptorType = vk::DescriptorType::eInputAttachment;
380 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
382 write_workspace_[descriptor_write_offset_++] = write_set;
387void RenderPassVK::SetCommandLabel(std::string_view label) {
389 command_buffer_->PushDebugGroup(label);
395void RenderPassVK::SetStencilReference(uint32_t value) {
396 if (current_stencil_ == value) {
399 current_stencil_ =
value;
400 command_buffer_vk_.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
405void RenderPassVK::SetBaseVertex(uint64_t value) {
406 base_vertex_ =
value;
410void RenderPassVK::SetViewport(Viewport viewport) {
412 command_buffer_vk_.setViewport(0, 1, &viewport_vk);
416void RenderPassVK::SetScissor(IRect32 scissor) {
417 vk::Rect2D scissor_vk =
419 .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY()))
420 .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight()));
421 command_buffer_vk_.setScissor(0, 1, &scissor_vk);
425void RenderPassVK::SetElementCount(
size_t count) {
426 element_count_ = count;
430void RenderPassVK::SetInstanceCount(
size_t count) {
431 instance_count_ = count;
435bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[],
436 size_t vertex_buffer_count) {
437 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
443 for (
size_t i = 0;
i < vertex_buffer_count;
i++) {
445 DeviceBufferVK::Cast(*vertex_buffers[
i].GetBuffer()).GetBuffer();
446 vertex_buffer_offsets[
i] = vertex_buffers[
i].GetRange().offset;
447 std::shared_ptr<const DeviceBuffer> device_buffer =
448 vertex_buffers[
i].TakeBuffer();
450 command_buffer_->Track(device_buffer);
455 command_buffer_vk_.bindVertexBuffers(0u, vertex_buffer_count, buffers,
456 vertex_buffer_offsets);
462bool RenderPassVK::SetIndexBuffer(BufferView index_buffer,
463 IndexType index_type) {
464 if (!ValidateIndexBuffer(index_buffer, index_type)) {
468 if (index_type != IndexType::kNone) {
469 has_index_buffer_ =
true;
471 BufferView index_buffer_view = std::move(index_buffer);
472 if (!index_buffer_view) {
476 if (!index_buffer_view.GetBuffer()) {
478 <<
" for index buffer view";
482 std::shared_ptr<const DeviceBuffer> index_buffer =
483 index_buffer_view.TakeBuffer();
484 if (index_buffer && !command_buffer_->Track(index_buffer)) {
488 vk::Buffer index_buffer_handle =
489 DeviceBufferVK::Cast(*index_buffer_view.GetBuffer()).GetBuffer();
490 command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
491 index_buffer_view.GetRange().offset,
494 has_index_buffer_ =
false;
504 "No valid pipeline is bound to the RenderPass.");
524 if (immutable_sampler_) {
525 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_variant =
526 PipelineVK::Cast(*pipeline_)
527 .CreateVariantForImmutableSamplers(immutable_sampler_);
528 if (!pipeline_variant) {
531 "Could not create pipeline variant with immutable sampler.");
533 pipeline_ = raw_ptr(pipeline_variant);
536 const auto& context_vk = ContextVK::Cast(*context_);
537 const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
539 auto descriptor_result = command_buffer_->AllocateDescriptorSets(
540 pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
542 if (!descriptor_result.ok()) {
544 "Could not allocate descriptor sets.");
546 const auto descriptor_set = descriptor_result.value();
547 const auto pipeline_layout = pipeline_vk.GetPipelineLayout();
548 command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics,
549 pipeline_vk.GetPipeline());
551 for (
auto i = 0u;
i < descriptor_write_offset_;
i++) {
552 write_workspace_[
i].dstSet = descriptor_set;
555 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
556 write_workspace_.data(), 0u, {});
558 command_buffer_vk_.bindDescriptorSets(
559 vk::PipelineBindPoint::eGraphics,
568 if (pipeline_uses_input_attachments_) {
570 command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
573 if (has_index_buffer_) {
574 command_buffer_vk_.drawIndexed(element_count_,
581 command_buffer_vk_.draw(element_count_,
590 command_buffer_->PopDebugGroup();
594 has_index_buffer_ =
false;
595 bound_image_offset_ = 0u;
596 bound_buffer_offset_ = 0u;
597 descriptor_write_offset_ = 0u;
598 instance_count_ = 1u;
602 pipeline_uses_input_attachments_ =
false;
603 immutable_sampler_ =
nullptr;
609bool RenderPassVK::BindResource(ShaderStage stage,
611 const ShaderUniformSlot& slot,
612 const ShaderMetadata* metadata,
614 return BindResource(slot.binding,
type, view);
617bool RenderPassVK::BindDynamicResource(ShaderStage stage,
619 const ShaderUniformSlot& slot,
620 std::unique_ptr<ShaderMetadata> metadata,
622 return BindResource(slot.binding,
type, view);
625bool RenderPassVK::BindResource(
size_t binding,
628 if (bound_buffer_offset_ >= kMaxBindings) {
632 auto buffer = DeviceBufferVK::Cast(*
view.GetBuffer()).GetBuffer();
637 std::shared_ptr<const DeviceBuffer> device_buffer =
view.TakeBuffer();
638 if (device_buffer && !command_buffer_->Track(device_buffer)) {
642 uint32_t offset =
view.GetRange().offset;
644 vk::DescriptorBufferInfo buffer_info;
645 buffer_info.buffer =
buffer;
646 buffer_info.offset = offset;
647 buffer_info.range =
view.GetRange().length;
648 buffer_workspace_[bound_buffer_offset_++] = buffer_info;
650 vk::WriteDescriptorSet write_set;
651 write_set.dstBinding = binding;
652 write_set.descriptorCount = 1u;
654 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
656 write_workspace_[descriptor_write_offset_++] = write_set;
660bool RenderPassVK::BindDynamicResource(ShaderStage stage,
662 const SampledImageSlot& slot,
663 std::unique_ptr<ShaderMetadata> metadata,
664 std::shared_ptr<const Texture>
texture,
665 raw_ptr<const Sampler> sampler) {
666 return BindResource(stage,
type, slot,
nullptr,
texture, sampler);
669bool RenderPassVK::BindResource(ShaderStage stage,
671 const SampledImageSlot& slot,
672 const ShaderMetadata* metadata,
673 std::shared_ptr<const Texture>
texture,
674 raw_ptr<const Sampler> sampler) {
675 if (bound_buffer_offset_ >= kMaxBindings) {
681 const TextureVK& texture_vk = TextureVK::Cast(*
texture);
682 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
684 if (!command_buffer_->Track(
texture)) {
688 if (!immutable_sampler_) {
689 immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
692 vk::DescriptorImageInfo image_info;
693 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
694 image_info.sampler = sampler_vk.GetSampler();
695 image_info.imageView = texture_vk.GetImageView();
696 image_workspace_[bound_image_offset_++] = image_info;
698 vk::WriteDescriptorSet write_set;
699 write_set.dstBinding = slot.binding;
700 write_set.descriptorCount = 1u;
701 write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
702 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
704 write_workspace_[descriptor_write_offset_++] = write_set;
708bool RenderPassVK::OnEncodeCommands(
const Context& context)
const {
709 command_buffer_->GetCommandBuffer().endRenderPass();
static TextureVK & Cast(Texture &base)
const RenderTarget render_target_
bool IterateAllColorAttachments(const std::function< bool(size_t index, const ColorAttachment &attachment)> &iterator) const
const std::optional< DepthAttachment > & GetDepthAttachment() const
const std::optional< StencilAttachment > & GetStencilAttachment() const
bool IsSwapchainImage() const
const FramebufferAndRenderPass & GetCachedFrameData(SampleCount sample_count) const
vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const
bool SetLayout(const BarrierVK &barrier) const
vk::ImageLayout GetLayout() const
void SetCachedFrameData(const FramebufferAndRenderPass &data, SampleCount sample_count)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
static vk::Viewport ToVkViewport(const Viewport &viewport)
constexpr vk::IndexType ToVKIndexType(IndexType index_type)
raw_ptr< Pipeline< PipelineDescriptor > > PipelineRef
A raw ptr to a pipeline object.
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
constexpr size_t kMaxVertexBuffers
static constexpr size_t kMagicSubpassInputBinding
static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, Scalar depth)
void InsertBarrierForInputAttachmentRead(const vk::CommandBuffer &buffer, const vk::Image &image)
Inserts the appropriate barriers to ensure that subsequent commands can read from the specified image...
static size_t GetVKClearValues(const RenderTarget &target, std::array< vk::ClearValue, kMaxAttachments > &values)
static vk::ClearColorValue VKClearValueFromColor(Color color)
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
impeller::ShaderType type
std::shared_ptr< Texture > resolve_texture
static constexpr TRect MakeSize(const TSize< U > &size)