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(
97 const SharedHandleVK<vk::RenderPass>& recycled_renderpass,
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,
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;
172 const uint32_t cache_mip_level = color0.mip_level;
173 const uint32_t cache_slice = color0.slice;
175 resolve_image_vk_ ? *resolve_image_vk_ : *color_image_vk_);
177 frame_data = frame_data_texture.GetCachedFrameData(
178 sample_count, cache_mip_level, cache_slice);
180 const auto& target_size = render_target_.GetRenderTargetSize();
182 render_pass_ = CreateVKRenderPass(vk_context, frame_data.render_pass,
183 command_buffer_, is_swapchain);
190 auto framebuffer = (frame_data.framebuffer ==
nullptr)
191 ? CreateVKFramebuffer(vk_context, *render_pass_)
192 : frame_data.framebuffer;
199 if (!command_buffer_->Track(framebuffer) ||
200 !command_buffer_->Track(render_pass_)) {
205 frame_data.framebuffer = framebuffer;
206 frame_data.render_pass = render_pass_;
208 frame_data_texture.SetCachedFrameData(frame_data, sample_count,
209 cache_mip_level, cache_slice);
213 if (resolve_image_vk_ &&
214 resolve_image_vk_->GetTextureDescriptor().mip_count > 1) {
216 vk::ImageLayout::eUndefined) {
218 barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
219 barrier.cmd_buffer = command_buffer_->GetCommandBuffer();
220 barrier.src_stage = vk::PipelineStageFlagBits::eBottomOfPipe;
221 barrier.src_access = {};
222 barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
223 barrier.dst_access = vk::AccessFlagBits::eShaderRead;
224 barrier.base_mip_level = 1;
229 std::array<vk::ClearValue, kMaxAttachments> clears;
232 vk::RenderPassBeginInfo pass_info;
233 pass_info.renderPass = *render_pass_;
234 pass_info.framebuffer = *framebuffer;
235 pass_info.renderArea.extent.width =
static_cast<uint32_t
>(target_size.width);
236 pass_info.renderArea.extent.height =
237 static_cast<uint32_t
>(target_size.height);
238 pass_info.setPClearValues(clears.data());
239 pass_info.setClearValueCount(clear_count);
241 command_buffer_vk_.beginRenderPass(pass_info, vk::SubpassContents::eInline);
243 if (resolve_image_vk_) {
246 is_swapchain ? vk::ImageLayout::eGeneral
247 : vk::ImageLayout::eShaderReadOnlyOptimal);
249 if (color_image_vk_) {
260 ? vk::ImageLayout::eGeneral
261 : vk::ImageLayout::eShaderReadOnlyOptimal);
267 command_buffer_vk_.setViewport(0, 1, &viewport);
273 .setOffset(vk::Offset2D(sc.GetX(), sc.GetY()))
274 .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight()));
275 command_buffer_vk_.setScissor(0, 1, &scissor);
278 command_buffer_vk_.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
284RenderPassVK::~RenderPassVK() =
default;
286bool RenderPassVK::IsValid()
const {
290void RenderPassVK::OnSetLabel(std::string_view label) {
292 ContextVK::Cast(*context_).SetDebugName(render_pass_->Get(), label.data());
296SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
298 const vk::RenderPass& pass)
const {
299 vk::FramebufferCreateInfo fb_info;
301 fb_info.renderPass = pass;
303 const auto target_size = render_target_.GetRenderTargetSize();
304 fb_info.width = target_size.width;
305 fb_info.height = target_size.height;
308 std::array<vk::ImageView, kMaxAttachments> attachments;
314 render_target_.IterateAllColorAttachments(
315 [&attachments, &count](
size_t index,
316 const ColorAttachment& attachment) ->
bool {
319 attachments[count++] =
320 TextureVK::Cast(*attachment.texture)
321 .GetRenderTargetView(attachment.mip_level, attachment.slice);
322 if (attachment.resolve_texture) {
324 attachments[count++] = TextureVK::Cast(*attachment.resolve_texture)
325 .GetRenderTargetView();
330 if (
auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
331 attachments[count++] =
332 TextureVK::Cast(*depth->texture)
333 .GetRenderTargetView(depth->mip_level, depth->slice);
334 }
else if (
auto stencil = render_target_.GetStencilAttachment();
335 stencil.has_value()) {
336 attachments[count++] =
337 TextureVK::Cast(*stencil->texture)
338 .GetRenderTargetView(stencil->mip_level, stencil->slice);
341 fb_info.setPAttachments(attachments.data());
342 fb_info.setAttachmentCount(count);
344 auto [result, framebuffer] =
345 context.GetDevice().createFramebufferUnique(fb_info);
347 if (result != vk::Result::eSuccess) {
348 VALIDATION_LOG <<
"Could not create framebuffer: " << vk::to_string(result);
356void RenderPassVK::SetPipeline(PipelineRef
pipeline) {
361 context_->GetPipelineLibrary()->LogPipelineUsage(
pipeline->GetDescriptor());
363 pipeline_uses_input_attachments_ =
364 pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttachments();
366 if (pipeline_uses_input_attachments_) {
367 if (bound_image_offset_ >= kMaxBindings) {
371 vk::DescriptorImageInfo image_info;
372 image_info.imageLayout = vk::ImageLayout::eGeneral;
373 image_info.sampler = VK_NULL_HANDLE;
374 image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView();
375 image_workspace_[bound_image_offset_++] = image_info;
377 vk::WriteDescriptorSet write_set;
379 write_set.descriptorCount = 1u;
380 write_set.descriptorType = vk::DescriptorType::eInputAttachment;
381 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
383 write_workspace_[descriptor_write_offset_++] = write_set;
388void RenderPassVK::SetCommandLabel(std::string_view label) {
390 command_buffer_->PushDebugGroup(label);
396void RenderPassVK::SetStencilReference(uint32_t value) {
397 if (current_stencil_ == value) {
400 current_stencil_ =
value;
401 command_buffer_vk_.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
406void RenderPassVK::SetBaseVertex(uint64_t value) {
407 base_vertex_ =
value;
411void RenderPassVK::SetViewport(Viewport viewport) {
413 command_buffer_vk_.setViewport(0, 1, &viewport_vk);
417void RenderPassVK::SetScissor(IRect32 scissor) {
418 vk::Rect2D scissor_vk =
420 .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY()))
421 .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight()));
422 command_buffer_vk_.setScissor(0, 1, &scissor_vk);
426void RenderPassVK::SetElementCount(
size_t count) {
427 element_count_ = count;
431void RenderPassVK::SetInstanceCount(
size_t count) {
432 instance_count_ = count;
436bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[],
437 size_t vertex_buffer_count) {
438 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
444 for (
size_t i = 0;
i < vertex_buffer_count;
i++) {
446 DeviceBufferVK::Cast(*vertex_buffers[
i].GetBuffer()).GetBuffer();
447 vertex_buffer_offsets[
i] = vertex_buffers[
i].GetRange().offset;
448 std::shared_ptr<const DeviceBuffer> device_buffer =
449 vertex_buffers[
i].TakeBuffer();
451 command_buffer_->Track(device_buffer);
456 command_buffer_vk_.bindVertexBuffers(0u, vertex_buffer_count, buffers,
457 vertex_buffer_offsets);
463bool RenderPassVK::SetIndexBuffer(BufferView index_buffer,
464 IndexType index_type) {
465 if (!ValidateIndexBuffer(index_buffer, index_type)) {
469 if (index_type != IndexType::kNone) {
470 has_index_buffer_ =
true;
472 BufferView index_buffer_view = std::move(index_buffer);
473 if (!index_buffer_view) {
477 if (!index_buffer_view.GetBuffer()) {
479 <<
" for index buffer view";
483 std::shared_ptr<const DeviceBuffer> index_buffer =
484 index_buffer_view.TakeBuffer();
485 if (index_buffer && !command_buffer_->Track(index_buffer)) {
489 vk::Buffer index_buffer_handle =
490 DeviceBufferVK::Cast(*index_buffer_view.GetBuffer()).GetBuffer();
491 command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
492 index_buffer_view.GetRange().offset,
495 has_index_buffer_ =
false;
505 "No valid pipeline is bound to the RenderPass.");
525 if (immutable_sampler_) {
526 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_variant =
527 PipelineVK::Cast(*pipeline_)
528 .CreateVariantForImmutableSamplers(immutable_sampler_);
529 if (!pipeline_variant) {
532 "Could not create pipeline variant with immutable sampler.");
534 pipeline_ = raw_ptr(pipeline_variant);
537 const auto& context_vk = ContextVK::Cast(*context_);
538 const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
540 auto descriptor_result = command_buffer_->AllocateDescriptorSets(
541 pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
543 if (!descriptor_result.ok()) {
545 "Could not allocate descriptor sets.");
547 const auto descriptor_set = descriptor_result.value();
548 const auto pipeline_layout = pipeline_vk.GetPipelineLayout();
549 command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics,
550 pipeline_vk.GetPipeline());
552 for (
auto i = 0u;
i < descriptor_write_offset_;
i++) {
553 write_workspace_[
i].dstSet = descriptor_set;
556 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
557 write_workspace_.data(), 0u, {});
559 command_buffer_vk_.bindDescriptorSets(
560 vk::PipelineBindPoint::eGraphics,
569 if (pipeline_uses_input_attachments_) {
571 command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
574 if (has_index_buffer_) {
575 command_buffer_vk_.drawIndexed(element_count_,
582 command_buffer_vk_.draw(element_count_,
591 command_buffer_->PopDebugGroup();
595 has_index_buffer_ =
false;
596 bound_image_offset_ = 0u;
597 bound_buffer_offset_ = 0u;
598 descriptor_write_offset_ = 0u;
599 instance_count_ = 1u;
603 pipeline_uses_input_attachments_ =
false;
604 immutable_sampler_ =
nullptr;
610bool RenderPassVK::BindResource(ShaderStage stage,
612 const ShaderUniformSlot& slot,
613 const ShaderMetadata* metadata,
615 return BindResource(slot.binding,
type, view);
618bool RenderPassVK::BindDynamicResource(ShaderStage stage,
620 const ShaderUniformSlot& slot,
621 std::unique_ptr<ShaderMetadata> metadata,
623 return BindResource(slot.binding,
type, view);
626bool RenderPassVK::BindResource(
size_t binding,
629 if (bound_buffer_offset_ >= kMaxBindings) {
633 auto buffer = DeviceBufferVK::Cast(*
view.GetBuffer()).GetBuffer();
638 std::shared_ptr<const DeviceBuffer> device_buffer =
view.TakeBuffer();
639 if (device_buffer && !command_buffer_->Track(device_buffer)) {
643 uint32_t offset =
view.GetRange().offset;
645 vk::DescriptorBufferInfo buffer_info;
646 buffer_info.buffer =
buffer;
647 buffer_info.offset = offset;
648 buffer_info.range =
view.GetRange().length;
649 buffer_workspace_[bound_buffer_offset_++] = buffer_info;
651 vk::WriteDescriptorSet write_set;
652 write_set.dstBinding = binding;
653 write_set.descriptorCount = 1u;
655 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
657 write_workspace_[descriptor_write_offset_++] = write_set;
661bool RenderPassVK::BindDynamicResource(ShaderStage stage,
663 const SampledImageSlot& slot,
664 std::unique_ptr<ShaderMetadata> metadata,
665 std::shared_ptr<const Texture>
texture,
666 raw_ptr<const Sampler> sampler) {
667 return BindResource(stage,
type, slot,
nullptr,
texture, sampler);
670bool RenderPassVK::BindResource(ShaderStage stage,
672 const SampledImageSlot& slot,
673 const ShaderMetadata* metadata,
674 std::shared_ptr<const Texture>
texture,
675 raw_ptr<const Sampler> sampler) {
676 if (bound_buffer_offset_ >= kMaxBindings) {
682 const TextureVK& texture_vk = TextureVK::Cast(*
texture);
683 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
685 if (!command_buffer_->Track(
texture)) {
689 if (!immutable_sampler_) {
690 immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
693 vk::DescriptorImageInfo image_info;
694 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
695 image_info.sampler = sampler_vk.GetSampler();
696 image_info.imageView = texture_vk.GetImageView();
697 image_workspace_[bound_image_offset_++] = image_info;
699 vk::WriteDescriptorSet write_set;
700 write_set.dstBinding = slot.binding;
701 write_set.descriptorCount = 1u;
702 write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
703 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
705 write_workspace_[descriptor_write_offset_++] = write_set;
709bool RenderPassVK::OnEncodeCommands(
const Context&
context)
const {
710 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
vk::ImageLayout SetLayoutWithoutEncoding(vk::ImageLayout layout) const
bool SetLayout(const BarrierVK &barrier) const
vk::ImageLayout GetLayout() const
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)
std::shared_ptr< ContextGLES > context
std::shared_ptr< PipelineGLES > pipeline
std::shared_ptr< CommandBuffer > command_buffer
impeller::ShaderType type
std::shared_ptr< Texture > resolve_texture
static constexpr TRect MakeSize(const TSize< U > &size)