38 vk::ClearColorValue
value;
46 vk::ClearDepthStencilValue
value;
48 value.stencil = stencil;
54 std::array<vk::ClearValue, kMaxAttachments>& values) {
56 target.IterateAllColorAttachments(
57 [&values, &offset](
size_t index,
66 const auto& depth =
target.GetDepthAttachment();
67 const auto& stencil =
target.GetStencilAttachment();
69 if (depth.has_value()) {
71 stencil ? stencil->clear_stencil : 0u, depth->clear_depth);
72 }
else if (stencil.has_value()) {
74 stencil->clear_stencil, depth ? depth->clear_depth : 0.0f);
79SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
80 const ContextVK& context,
81 const SharedHandleVK<vk::RenderPass>& recycled_renderpass,
82 const std::shared_ptr<CommandBufferVK>& command_buffer,
83 bool is_swapchain)
const {
84 if (recycled_renderpass !=
nullptr) {
85 return recycled_renderpass;
88 RenderPassBuilderVK builder;
90 const ColorAttachment&
92 builder.SetColorAttachment(
94 attachment.texture->GetTextureDescriptor().format,
95 attachment.texture->GetTextureDescriptor().sample_count,
96 attachment.load_action,
97 attachment.store_action,
104 builder.SetDepthStencilAttachment(
105 depth->texture->GetTextureDescriptor().format,
106 depth->texture->GetTextureDescriptor().sample_count,
111 stencil.has_value()) {
112 builder.SetStencilAttachment(
113 stencil->texture->GetTextureDescriptor().format,
114 stencil->texture->GetTextureDescriptor().sample_count,
115 stencil->load_action,
116 stencil->store_action
120 auto pass = builder.Build(context.GetDevice());
123 VALIDATION_LOG <<
"Failed to create render pass for framebuffer.";
127 context.SetDebugName(pass.get(), debug_label_.c_str());
132RenderPassVK::RenderPassVK(
const std::shared_ptr<const Context>& context,
133 const RenderTarget&
target,
134 std::shared_ptr<CommandBufferVK> command_buffer)
135 : RenderPass(context,
target), command_buffer_(
std::move(command_buffer)) {
136 const ColorAttachment& color0 = render_target_.GetColorAttachment(0);
137 color_image_vk_ = color0.texture;
138 resolve_image_vk_ = color0.resolve_texture;
141 command_buffer_vk_ = command_buffer_->GetCommandBuffer();
142 render_target_.IterateAllAttachments([&](
const auto& attachment) ->
bool {
143 command_buffer_->Track(attachment.texture);
144 command_buffer_->Track(attachment.resolve_texture);
148 FramebufferAndRenderPass frame_data;
149 bool is_swapchain =
false;
151 color_image_vk_->GetTextureDescriptor().sample_count;
152 if (resolve_image_vk_) {
162 const auto& target_size = render_target_.GetRenderTargetSize();
164 render_pass_ = CreateVKRenderPass(vk_context, frame_data.render_pass,
165 command_buffer_, is_swapchain);
172 auto framebuffer = (frame_data.framebuffer ==
nullptr)
173 ? CreateVKFramebuffer(vk_context, *render_pass_)
174 : frame_data.framebuffer;
181 if (!command_buffer_->Track(framebuffer) ||
182 !command_buffer_->Track(render_pass_)) {
187 frame_data.framebuffer = framebuffer;
188 frame_data.render_pass = render_pass_;
190 if (resolve_image_vk_) {
200 if (resolve_image_vk_ &&
201 resolve_image_vk_->GetTextureDescriptor().mip_count > 1) {
203 vk::ImageLayout::eUndefined) {
205 barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
206 barrier.cmd_buffer = command_buffer_->GetCommandBuffer();
207 barrier.src_stage = vk::PipelineStageFlagBits::eBottomOfPipe;
208 barrier.src_access = {};
209 barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
210 barrier.dst_access = vk::AccessFlagBits::eShaderRead;
211 barrier.base_mip_level = 1;
216 std::array<vk::ClearValue, kMaxAttachments> clears;
219 vk::RenderPassBeginInfo pass_info;
220 pass_info.renderPass = *render_pass_;
221 pass_info.framebuffer = *framebuffer;
222 pass_info.renderArea.extent.width =
static_cast<uint32_t
>(target_size.width);
223 pass_info.renderArea.extent.height =
224 static_cast<uint32_t
>(target_size.height);
225 pass_info.setPClearValues(clears.data());
226 pass_info.setClearValueCount(clear_count);
228 command_buffer_vk_.beginRenderPass(pass_info, vk::SubpassContents::eInline);
230 if (resolve_image_vk_) {
233 is_swapchain ? vk::ImageLayout::eGeneral
234 : vk::ImageLayout::eShaderReadOnlyOptimal);
236 if (color_image_vk_) {
243 vk::Viewport viewport = vk::Viewport()
244 .setWidth(vp.rect.GetWidth())
245 .setHeight(-vp.rect.GetHeight())
246 .setY(vp.rect.GetHeight())
249 command_buffer_vk_.setViewport(0, 1, &viewport);
255 .setOffset(vk::Offset2D(sc.GetX(), sc.GetY()))
256 .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight()));
257 command_buffer_vk_.setScissor(0, 1, &scissor);
260 command_buffer_vk_.setStencilReference(
261 vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 0u);
266RenderPassVK::~RenderPassVK() =
default;
268bool RenderPassVK::IsValid()
const {
272void RenderPassVK::OnSetLabel(std::string_view label) {
274 ContextVK::Cast(*context_).SetDebugName(render_pass_->Get(), label.data());
278SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
279 const ContextVK& context,
280 const vk::RenderPass& pass)
const {
281 vk::FramebufferCreateInfo fb_info;
283 fb_info.renderPass = pass;
285 const auto target_size = render_target_.GetRenderTargetSize();
286 fb_info.width = target_size.width;
287 fb_info.height = target_size.height;
290 std::array<vk::ImageView, kMaxAttachments> attachments;
296 render_target_.IterateAllColorAttachments(
297 [&attachments, &count](
size_t index,
298 const ColorAttachment& attachment) ->
bool {
301 attachments[count++] =
302 TextureVK::Cast(*attachment.texture).GetRenderTargetView();
303 if (attachment.resolve_texture) {
304 attachments[count++] = TextureVK::Cast(*attachment.resolve_texture)
305 .GetRenderTargetView();
310 if (
auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
311 attachments[count++] =
312 TextureVK::Cast(*depth->texture).GetRenderTargetView();
313 }
else if (
auto stencil = render_target_.GetStencilAttachment();
314 stencil.has_value()) {
315 attachments[count++] =
316 TextureVK::Cast(*stencil->texture).GetRenderTargetView();
319 fb_info.setPAttachments(attachments.data());
320 fb_info.setAttachmentCount(count);
322 auto [result, framebuffer] =
323 context.GetDevice().createFramebufferUnique(fb_info);
325 if (result != vk::Result::eSuccess) {
326 VALIDATION_LOG <<
"Could not create framebuffer: " << vk::to_string(result);
334void RenderPassVK::SetPipeline(PipelineRef pipeline) {
335 pipeline_ = pipeline;
340 pipeline_uses_input_attachments_ =
341 pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttacments();
343 if (pipeline_uses_input_attachments_) {
344 if (bound_image_offset_ >= kMaxBindings) {
348 vk::DescriptorImageInfo image_info;
349 image_info.imageLayout = vk::ImageLayout::eGeneral;
350 image_info.sampler = VK_NULL_HANDLE;
351 image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView();
352 image_workspace_[bound_image_offset_++] = image_info;
354 vk::WriteDescriptorSet write_set;
356 write_set.descriptorCount = 1u;
357 write_set.descriptorType = vk::DescriptorType::eInputAttachment;
358 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
360 write_workspace_[descriptor_write_offset_++] = write_set;
365void RenderPassVK::SetCommandLabel(std::string_view label) {
367 command_buffer_->PushDebugGroup(label);
373void RenderPassVK::SetStencilReference(uint32_t value) {
374 if (current_stencil_ == value) {
377 current_stencil_ =
value;
378 command_buffer_vk_.setStencilReference(
379 vk::StencilFaceFlagBits::eVkStencilFrontAndBack, value);
383void RenderPassVK::SetBaseVertex(uint64_t value) {
384 base_vertex_ =
value;
388void RenderPassVK::SetViewport(Viewport viewport) {
389 vk::Viewport viewport_vk = vk::Viewport()
390 .setWidth(viewport.rect.GetWidth())
391 .setHeight(-viewport.rect.GetHeight())
392 .setY(viewport.rect.GetHeight())
395 command_buffer_vk_.setViewport(0, 1, &viewport_vk);
399void RenderPassVK::SetScissor(IRect32 scissor) {
400 vk::Rect2D scissor_vk =
402 .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY()))
403 .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight()));
404 command_buffer_vk_.setScissor(0, 1, &scissor_vk);
408void RenderPassVK::SetElementCount(
size_t count) {
409 element_count_ = count;
413void RenderPassVK::SetInstanceCount(
size_t count) {
414 instance_count_ = count;
418bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[],
419 size_t vertex_buffer_count) {
420 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
426 for (
size_t i = 0;
i < vertex_buffer_count;
i++) {
428 DeviceBufferVK::Cast(*vertex_buffers[
i].GetBuffer()).GetBuffer();
429 vertex_buffer_offsets[
i] = vertex_buffers[
i].GetRange().offset;
430 std::shared_ptr<const DeviceBuffer> device_buffer =
431 vertex_buffers[
i].TakeBuffer();
433 command_buffer_->Track(device_buffer);
438 command_buffer_vk_.bindVertexBuffers(0u, vertex_buffer_count, buffers,
439 vertex_buffer_offsets);
445bool RenderPassVK::SetIndexBuffer(BufferView index_buffer,
446 IndexType index_type) {
447 if (!ValidateIndexBuffer(index_buffer, index_type)) {
451 if (index_type != IndexType::kNone) {
452 has_index_buffer_ =
true;
454 BufferView index_buffer_view = std::move(index_buffer);
455 if (!index_buffer_view) {
459 if (!index_buffer_view.GetBuffer()) {
461 <<
" for index buffer view";
465 std::shared_ptr<const DeviceBuffer> index_buffer =
466 index_buffer_view.TakeBuffer();
467 if (index_buffer && !command_buffer_->Track(index_buffer)) {
471 vk::Buffer index_buffer_handle =
472 DeviceBufferVK::Cast(*index_buffer_view.GetBuffer()).GetBuffer();
473 command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
474 index_buffer_view.GetRange().offset,
477 has_index_buffer_ =
false;
487 "No valid pipeline is bound to the RenderPass.");
507 if (immutable_sampler_) {
508 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_variant =
509 PipelineVK::Cast(*pipeline_)
510 .CreateVariantForImmutableSamplers(immutable_sampler_);
511 if (!pipeline_variant) {
514 "Could not create pipeline variant with immutable sampler.");
516 pipeline_ = raw_ptr(pipeline_variant);
519 const auto& context_vk = ContextVK::Cast(*context_);
520 const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
522 auto descriptor_result = command_buffer_->AllocateDescriptorSets(
523 pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
525 if (!descriptor_result.ok()) {
527 "Could not allocate descriptor sets.");
529 const auto descriptor_set = descriptor_result.value();
530 const auto pipeline_layout = pipeline_vk.GetPipelineLayout();
531 command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics,
532 pipeline_vk.GetPipeline());
534 for (
auto i = 0u;
i < descriptor_write_offset_;
i++) {
535 write_workspace_[
i].dstSet = descriptor_set;
538 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
539 write_workspace_.data(), 0u, {});
541 command_buffer_vk_.bindDescriptorSets(
542 vk::PipelineBindPoint::eGraphics,
551 if (pipeline_uses_input_attachments_) {
553 command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
556 if (has_index_buffer_) {
557 command_buffer_vk_.drawIndexed(element_count_,
564 command_buffer_vk_.draw(element_count_,
573 command_buffer_->PopDebugGroup();
577 has_index_buffer_ =
false;
578 bound_image_offset_ = 0u;
579 bound_buffer_offset_ = 0u;
580 descriptor_write_offset_ = 0u;
581 instance_count_ = 1u;
585 pipeline_uses_input_attachments_ =
false;
586 immutable_sampler_ =
nullptr;
592bool RenderPassVK::BindResource(ShaderStage stage,
594 const ShaderUniformSlot& slot,
595 const ShaderMetadata* metadata,
597 return BindResource(slot.binding,
type,
view);
600bool RenderPassVK::BindDynamicResource(ShaderStage stage,
602 const ShaderUniformSlot& slot,
603 std::unique_ptr<ShaderMetadata> metadata,
605 return BindResource(slot.binding,
type,
view);
608bool RenderPassVK::BindResource(
size_t binding,
611 if (bound_buffer_offset_ >= kMaxBindings) {
615 auto buffer = DeviceBufferVK::Cast(*
view.GetBuffer()).GetBuffer();
620 std::shared_ptr<const DeviceBuffer> device_buffer =
view.TakeBuffer();
621 if (device_buffer && !command_buffer_->Track(device_buffer)) {
625 uint32_t offset =
view.GetRange().offset;
627 vk::DescriptorBufferInfo buffer_info;
628 buffer_info.buffer =
buffer;
629 buffer_info.offset = offset;
630 buffer_info.range =
view.GetRange().length;
631 buffer_workspace_[bound_buffer_offset_++] = buffer_info;
633 vk::WriteDescriptorSet write_set;
634 write_set.dstBinding = binding;
635 write_set.descriptorCount = 1u;
637 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
639 write_workspace_[descriptor_write_offset_++] = write_set;
643bool RenderPassVK::BindDynamicResource(ShaderStage stage,
645 const SampledImageSlot& slot,
646 std::unique_ptr<ShaderMetadata> metadata,
647 std::shared_ptr<const Texture>
texture,
648 raw_ptr<const Sampler> sampler) {
649 return BindResource(stage,
type, slot,
nullptr,
texture, sampler);
652bool RenderPassVK::BindResource(ShaderStage stage,
654 const SampledImageSlot& slot,
655 const ShaderMetadata* metadata,
656 std::shared_ptr<const Texture>
texture,
657 raw_ptr<const Sampler> sampler) {
658 if (bound_buffer_offset_ >= kMaxBindings) {
664 const TextureVK& texture_vk = TextureVK::Cast(*
texture);
665 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
667 if (!command_buffer_->Track(
texture)) {
671 if (!immutable_sampler_) {
672 immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
675 vk::DescriptorImageInfo image_info;
676 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
677 image_info.sampler = sampler_vk.GetSampler();
678 image_info.imageView = texture_vk.GetImageView();
679 image_workspace_[bound_image_offset_++] = image_info;
681 vk::WriteDescriptorSet write_set;
682 write_set.dstBinding = slot.binding;
683 write_set.descriptorCount = 1u;
684 write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
685 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
687 write_workspace_[descriptor_write_offset_++] = write_set;
691bool RenderPassVK::OnEncodeCommands(
const Context& context)
const {
692 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
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< Texture > resolve_texture
static constexpr TRect MakeSize(const TSize< U > &size)