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;
339 context_->GetPipelineLibrary()->LogPipelineUsage(pipeline->GetDescriptor());
341 pipeline_uses_input_attachments_ =
342 pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttacments();
344 if (pipeline_uses_input_attachments_) {
345 if (bound_image_offset_ >= kMaxBindings) {
349 vk::DescriptorImageInfo image_info;
350 image_info.imageLayout = vk::ImageLayout::eGeneral;
351 image_info.sampler = VK_NULL_HANDLE;
352 image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView();
353 image_workspace_[bound_image_offset_++] = image_info;
355 vk::WriteDescriptorSet write_set;
357 write_set.descriptorCount = 1u;
358 write_set.descriptorType = vk::DescriptorType::eInputAttachment;
359 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
361 write_workspace_[descriptor_write_offset_++] = write_set;
366void RenderPassVK::SetCommandLabel(std::string_view label) {
368 command_buffer_->PushDebugGroup(label);
374void RenderPassVK::SetStencilReference(uint32_t value) {
375 if (current_stencil_ == value) {
378 current_stencil_ =
value;
379 command_buffer_vk_.setStencilReference(
380 vk::StencilFaceFlagBits::eVkStencilFrontAndBack, value);
384void RenderPassVK::SetBaseVertex(uint64_t value) {
385 base_vertex_ =
value;
389void RenderPassVK::SetViewport(Viewport viewport) {
390 vk::Viewport viewport_vk = vk::Viewport()
391 .setWidth(viewport.rect.GetWidth())
392 .setHeight(-viewport.rect.GetHeight())
393 .setY(viewport.rect.GetHeight())
396 command_buffer_vk_.setViewport(0, 1, &viewport_vk);
400void RenderPassVK::SetScissor(IRect32 scissor) {
401 vk::Rect2D scissor_vk =
403 .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY()))
404 .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight()));
405 command_buffer_vk_.setScissor(0, 1, &scissor_vk);
409void RenderPassVK::SetElementCount(
size_t count) {
410 element_count_ = count;
414void RenderPassVK::SetInstanceCount(
size_t count) {
415 instance_count_ = count;
419bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[],
420 size_t vertex_buffer_count) {
421 if (!ValidateVertexBuffers(vertex_buffers, vertex_buffer_count)) {
427 for (
size_t i = 0;
i < vertex_buffer_count;
i++) {
429 DeviceBufferVK::Cast(*vertex_buffers[
i].GetBuffer()).GetBuffer();
430 vertex_buffer_offsets[
i] = vertex_buffers[
i].GetRange().offset;
431 std::shared_ptr<const DeviceBuffer> device_buffer =
432 vertex_buffers[
i].TakeBuffer();
434 command_buffer_->Track(device_buffer);
439 command_buffer_vk_.bindVertexBuffers(0u, vertex_buffer_count, buffers,
440 vertex_buffer_offsets);
446bool RenderPassVK::SetIndexBuffer(BufferView index_buffer,
447 IndexType index_type) {
448 if (!ValidateIndexBuffer(index_buffer, index_type)) {
452 if (index_type != IndexType::kNone) {
453 has_index_buffer_ =
true;
455 BufferView index_buffer_view = std::move(index_buffer);
456 if (!index_buffer_view) {
460 if (!index_buffer_view.GetBuffer()) {
462 <<
" for index buffer view";
466 std::shared_ptr<const DeviceBuffer> index_buffer =
467 index_buffer_view.TakeBuffer();
468 if (index_buffer && !command_buffer_->Track(index_buffer)) {
472 vk::Buffer index_buffer_handle =
473 DeviceBufferVK::Cast(*index_buffer_view.GetBuffer()).GetBuffer();
474 command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
475 index_buffer_view.GetRange().offset,
478 has_index_buffer_ =
false;
488 "No valid pipeline is bound to the RenderPass.");
508 if (immutable_sampler_) {
509 std::shared_ptr<Pipeline<PipelineDescriptor>> pipeline_variant =
510 PipelineVK::Cast(*pipeline_)
511 .CreateVariantForImmutableSamplers(immutable_sampler_);
512 if (!pipeline_variant) {
515 "Could not create pipeline variant with immutable sampler.");
517 pipeline_ = raw_ptr(pipeline_variant);
520 const auto& context_vk = ContextVK::Cast(*context_);
521 const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
523 auto descriptor_result = command_buffer_->AllocateDescriptorSets(
524 pipeline_vk.GetDescriptorSetLayout(), pipeline_vk.GetPipelineKey(),
526 if (!descriptor_result.ok()) {
528 "Could not allocate descriptor sets.");
530 const auto descriptor_set = descriptor_result.value();
531 const auto pipeline_layout = pipeline_vk.GetPipelineLayout();
532 command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics,
533 pipeline_vk.GetPipeline());
535 for (
auto i = 0u;
i < descriptor_write_offset_;
i++) {
536 write_workspace_[
i].dstSet = descriptor_set;
539 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
540 write_workspace_.data(), 0u, {});
542 command_buffer_vk_.bindDescriptorSets(
543 vk::PipelineBindPoint::eGraphics,
552 if (pipeline_uses_input_attachments_) {
554 command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
557 if (has_index_buffer_) {
558 command_buffer_vk_.drawIndexed(element_count_,
565 command_buffer_vk_.draw(element_count_,
574 command_buffer_->PopDebugGroup();
578 has_index_buffer_ =
false;
579 bound_image_offset_ = 0u;
580 bound_buffer_offset_ = 0u;
581 descriptor_write_offset_ = 0u;
582 instance_count_ = 1u;
586 pipeline_uses_input_attachments_ =
false;
587 immutable_sampler_ =
nullptr;
593bool RenderPassVK::BindResource(ShaderStage stage,
595 const ShaderUniformSlot& slot,
596 const ShaderMetadata* metadata,
598 return BindResource(slot.binding,
type,
view);
601bool RenderPassVK::BindDynamicResource(ShaderStage stage,
603 const ShaderUniformSlot& slot,
604 std::unique_ptr<ShaderMetadata> metadata,
606 return BindResource(slot.binding,
type,
view);
609bool RenderPassVK::BindResource(
size_t binding,
612 if (bound_buffer_offset_ >= kMaxBindings) {
616 auto buffer = DeviceBufferVK::Cast(*
view.GetBuffer()).GetBuffer();
621 std::shared_ptr<const DeviceBuffer> device_buffer =
view.TakeBuffer();
622 if (device_buffer && !command_buffer_->Track(device_buffer)) {
626 uint32_t offset =
view.GetRange().offset;
628 vk::DescriptorBufferInfo buffer_info;
629 buffer_info.buffer =
buffer;
630 buffer_info.offset = offset;
631 buffer_info.range =
view.GetRange().length;
632 buffer_workspace_[bound_buffer_offset_++] = buffer_info;
634 vk::WriteDescriptorSet write_set;
635 write_set.dstBinding = binding;
636 write_set.descriptorCount = 1u;
638 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
640 write_workspace_[descriptor_write_offset_++] = write_set;
644bool RenderPassVK::BindDynamicResource(ShaderStage stage,
646 const SampledImageSlot& slot,
647 std::unique_ptr<ShaderMetadata> metadata,
648 std::shared_ptr<const Texture>
texture,
649 raw_ptr<const Sampler> sampler) {
650 return BindResource(stage,
type, slot,
nullptr,
texture, sampler);
653bool RenderPassVK::BindResource(ShaderStage stage,
655 const SampledImageSlot& slot,
656 const ShaderMetadata* metadata,
657 std::shared_ptr<const Texture>
texture,
658 raw_ptr<const Sampler> sampler) {
659 if (bound_buffer_offset_ >= kMaxBindings) {
665 const TextureVK& texture_vk = TextureVK::Cast(*
texture);
666 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
668 if (!command_buffer_->Track(
texture)) {
672 if (!immutable_sampler_) {
673 immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
676 vk::DescriptorImageInfo image_info;
677 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
678 image_info.sampler = sampler_vk.GetSampler();
679 image_info.imageView = texture_vk.GetImageView();
680 image_workspace_[bound_image_offset_++] = image_info;
682 vk::WriteDescriptorSet write_set;
683 write_set.dstBinding = slot.binding;
684 write_set.descriptorCount = 1u;
685 write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
686 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
688 write_workspace_[descriptor_write_offset_++] = write_set;
692bool RenderPassVK::OnEncodeCommands(
const Context& context)
const {
693 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)