27#include "vulkan/vulkan_handles.hpp"
39 vk::ClearColorValue
value;
47 vk::ClearDepthStencilValue
value;
49 value.stencil = stencil;
55 std::vector<vk::ClearValue> clears;
57 for (
const auto& [_,
color] :
target.GetColorAttachments()) {
59 if (
color.resolve_texture) {
64 const auto& depth =
target.GetDepthAttachment();
65 const auto& stencil =
target.GetStencilAttachment();
67 if (depth.has_value()) {
69 stencil ? stencil->clear_stencil : 0u, depth->clear_depth));
70 }
else if (stencil.has_value()) {
72 stencil->clear_stencil, depth ? depth->clear_depth : 0.0f));
78SharedHandleVK<vk::RenderPass> RenderPassVK::CreateVKRenderPass(
79 const ContextVK& context,
80 const SharedHandleVK<vk::RenderPass>& recycled_renderpass,
81 const std::shared_ptr<CommandBufferVK>& command_buffer)
const {
83 barrier.new_layout = vk::ImageLayout::eGeneral;
84 barrier.cmd_buffer = command_buffer->GetEncoder()->GetCommandBuffer();
85 barrier.src_access = vk::AccessFlagBits::eShaderRead;
86 barrier.src_stage = vk::PipelineStageFlagBits::eFragmentShader;
87 barrier.dst_access = vk::AccessFlagBits::eColorAttachmentWrite |
88 vk::AccessFlagBits::eTransferWrite;
89 barrier.dst_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
90 vk::PipelineStageFlagBits::eTransfer;
97 color.texture->GetTextureDescriptor().format,
98 color.texture->GetTextureDescriptor().sample_count,
103 if (
color.resolve_texture) {
109 builder.SetDepthStencilAttachment(
110 depth->texture->GetTextureDescriptor().format,
111 depth->texture->GetTextureDescriptor().sample_count,
116 stencil.has_value()) {
118 stencil->texture->GetTextureDescriptor().format,
119 stencil->texture->GetTextureDescriptor().sample_count,
120 stencil->load_action,
121 stencil->store_action
125 if (recycled_renderpass !=
nullptr) {
126 return recycled_renderpass;
129 auto pass =
builder.Build(context.GetDevice());
132 VALIDATION_LOG <<
"Failed to create render pass for framebuffer.";
136 context.SetDebugName(pass.get(), debug_label_.c_str());
141RenderPassVK::RenderPassVK(
const std::shared_ptr<const Context>& context,
143 std::shared_ptr<CommandBufferVK> command_buffer)
144 : RenderPass(context,
target), command_buffer_(
std::move(command_buffer)) {
146 render_target_.GetColorAttachments().find(0u)->second.texture;
148 render_target_.GetColorAttachments().find(0u)->second.resolve_texture;
151 const std::shared_ptr<CommandEncoderVK>&
encoder =
152 command_buffer_->GetEncoder();
153 command_buffer_vk_ =
encoder->GetCommandBuffer();
154 render_target_.IterateAllAttachments(
155 [&
encoder](
const auto& attachment) ->
bool {
156 encoder->Track(attachment.texture);
157 encoder->Track(attachment.resolve_texture);
161 SharedHandleVK<vk::RenderPass> recycled_render_pass;
162 SharedHandleVK<vk::Framebuffer> recycled_framebuffer;
163 if (resolve_image_vk_) {
164 recycled_render_pass =
166 recycled_framebuffer =
170 const auto& target_size = render_target_.GetRenderTargetSize();
173 CreateVKRenderPass(vk_context, recycled_render_pass, command_buffer_);
180 auto framebuffer = (recycled_framebuffer ==
nullptr)
181 ? CreateVKFramebuffer(vk_context, *render_pass_)
182 : recycled_framebuffer;
189 if (!
encoder->Track(framebuffer) || !
encoder->Track(render_pass_)) {
193 if (resolve_image_vk_) {
200 vk::RenderPassBeginInfo pass_info;
201 pass_info.renderPass = *render_pass_;
202 pass_info.framebuffer = *framebuffer;
203 pass_info.renderArea.extent.width =
static_cast<uint32_t
>(target_size.width);
204 pass_info.renderArea.extent.height =
205 static_cast<uint32_t
>(target_size.height);
206 pass_info.setClearValues(clear_values);
208 command_buffer_vk_.beginRenderPass(pass_info, vk::SubpassContents::eInline);
212 vk::Viewport viewport = vk::Viewport()
213 .setWidth(vp.rect.GetWidth())
214 .setHeight(-vp.rect.GetHeight())
215 .setY(vp.rect.GetHeight())
218 command_buffer_vk_.setViewport(0, 1, &viewport);
224 .setOffset(vk::Offset2D(sc.GetX(), sc.GetY()))
225 .setExtent(vk::Extent2D(sc.GetWidth(), sc.GetHeight()));
226 command_buffer_vk_.setScissor(0, 1, &scissor);
229 command_buffer_vk_.setStencilReference(
230 vk::StencilFaceFlagBits::eVkStencilFrontAndBack, 0u);
235RenderPassVK::~RenderPassVK() =
default;
237bool RenderPassVK::IsValid()
const {
241void RenderPassVK::OnSetLabel(std::string label) {
243 ContextVK::Cast(*context_).SetDebugName(render_pass_->Get(),
244 std::string(label).c_str());
248SharedHandleVK<vk::Framebuffer> RenderPassVK::CreateVKFramebuffer(
249 const ContextVK& context,
250 const vk::RenderPass& pass)
const {
251 vk::FramebufferCreateInfo fb_info;
253 fb_info.renderPass = pass;
255 const auto target_size = render_target_.GetRenderTargetSize();
256 fb_info.width = target_size.width;
257 fb_info.height = target_size.height;
260 std::vector<vk::ImageView> attachments;
265 for (
const auto& [_,
color] : render_target_.GetColorAttachments()) {
268 attachments.emplace_back(
269 TextureVK::Cast(*
color.texture).GetRenderTargetView());
270 if (
color.resolve_texture) {
271 attachments.emplace_back(
272 TextureVK::Cast(*
color.resolve_texture).GetRenderTargetView());
275 if (
auto depth = render_target_.GetDepthAttachment(); depth.has_value()) {
276 attachments.emplace_back(
277 TextureVK::Cast(*depth->texture).GetRenderTargetView());
278 }
else if (
auto stencil = render_target_.GetStencilAttachment();
279 stencil.has_value()) {
280 attachments.emplace_back(
281 TextureVK::Cast(*stencil->texture).GetRenderTargetView());
284 fb_info.setAttachments(attachments);
286 auto [
result, framebuffer] =
287 context.GetDevice().createFramebufferUnique(fb_info);
289 if (
result != vk::Result::eSuccess) {
298void RenderPassVK::SetPipeline(
299 const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline) {
300 pipeline_ = pipeline.get();
305 pipeline_uses_input_attachments_ =
306 pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttacments();
308 if (pipeline_uses_input_attachments_) {
313 vk::DescriptorImageInfo image_info;
314 image_info.imageLayout = vk::ImageLayout::eGeneral;
316 image_info.imageView = TextureVK::Cast(*color_image_vk_).GetImageView();
317 image_workspace_[bound_image_offset_++] = image_info;
319 vk::WriteDescriptorSet write_set;
321 write_set.descriptorCount = 1u;
322 write_set.descriptorType = vk::DescriptorType::eInputAttachment;
323 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
325 write_workspace_[descriptor_write_offset_++] = write_set;
330void RenderPassVK::SetCommandLabel(std::string_view label) {
332 command_buffer_->GetEncoder()->PushDebugGroup(label);
338void RenderPassVK::SetStencilReference(uint32_t
value) {
339 command_buffer_vk_.setStencilReference(
340 vk::StencilFaceFlagBits::eVkStencilFrontAndBack,
value);
344void RenderPassVK::SetBaseVertex(uint64_t
value) {
345 base_vertex_ =
value;
349void RenderPassVK::SetViewport(Viewport viewport) {
350 vk::Viewport viewport_vk = vk::Viewport()
351 .setWidth(viewport.rect.GetWidth())
352 .setHeight(-viewport.rect.GetHeight())
353 .setY(viewport.rect.GetHeight())
356 command_buffer_vk_.setViewport(0, 1, &viewport_vk);
360void RenderPassVK::SetScissor(
IRect scissor) {
361 vk::Rect2D scissor_vk =
363 .setOffset(vk::Offset2D(scissor.GetX(), scissor.GetY()))
364 .setExtent(vk::Extent2D(scissor.GetWidth(), scissor.GetHeight()));
365 command_buffer_vk_.setScissor(0, 1, &scissor_vk);
369void RenderPassVK::SetInstanceCount(
size_t count) {
370 instance_count_ =
count;
375 vertex_count_ =
buffer.vertex_count;
380 if (!command_buffer_->GetEncoder()->Track(
buffer.vertex_buffer.buffer)) {
385 vk::Buffer vertex_buffer_handle =
386 DeviceBufferVK::Cast(*
buffer.vertex_buffer.buffer).GetBuffer();
387 vk::Buffer vertex_buffers[] = {vertex_buffer_handle};
388 vk::DeviceSize vertex_buffer_offsets[] = {
buffer.vertex_buffer.range.offset};
390 command_buffer_vk_.bindVertexBuffers(0u, 1u, vertex_buffers,
391 vertex_buffer_offsets);
395 has_index_buffer_ =
true;
396 const BufferView& index_buffer_view =
buffer.index_buffer;
397 if (!index_buffer_view) {
401 const std::shared_ptr<const DeviceBuffer>& index_buffer =
402 index_buffer_view.buffer;
405 <<
" for index buffer view";
409 if (!command_buffer_->GetEncoder()->Track(index_buffer)) {
413 vk::Buffer index_buffer_handle =
414 DeviceBufferVK::Cast(*index_buffer).GetBuffer();
415 command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
416 index_buffer_view.range.offset,
419 has_index_buffer_ =
false;
428 "No valid pipeline is bound to the RenderPass.");
448 if (immutable_sampler_) {
449 std::shared_ptr<PipelineVK> pipeline_variant =
450 PipelineVK::Cast(*pipeline_)
451 .CreateVariantForImmutableSamplers(immutable_sampler_);
452 if (!pipeline_variant) {
455 "Could not create pipeline variant with immutable sampler.");
457 pipeline_ = pipeline_variant.get();
460 const auto& context_vk = ContextVK::Cast(*context_);
461 const auto& pipeline_vk = PipelineVK::Cast(*pipeline_);
463 auto descriptor_result =
464 command_buffer_->GetEncoder()->AllocateDescriptorSets(
465 pipeline_vk.GetDescriptorSetLayout(), context_vk);
466 if (!descriptor_result.ok()) {
468 "Could not allocate descriptor sets.");
470 const auto descriptor_set = descriptor_result.value();
471 const auto pipeline_layout = pipeline_vk.GetPipelineLayout();
472 command_buffer_vk_.bindPipeline(vk::PipelineBindPoint::eGraphics,
473 pipeline_vk.GetPipeline());
475 for (
auto i = 0u;
i < descriptor_write_offset_;
i++) {
476 write_workspace_[
i].dstSet = descriptor_set;
479 context_vk.GetDevice().updateDescriptorSets(descriptor_write_offset_,
480 write_workspace_.data(), 0u, {});
482 command_buffer_vk_.bindDescriptorSets(
483 vk::PipelineBindPoint::eGraphics,
492 if (pipeline_uses_input_attachments_) {
494 command_buffer_vk_, TextureVK::Cast(*color_image_vk_).GetImage());
497 if (has_index_buffer_) {
498 command_buffer_vk_.drawIndexed(vertex_count_,
505 command_buffer_vk_.draw(vertex_count_,
514 command_buffer_->GetEncoder()->PopDebugGroup();
518 has_index_buffer_ =
false;
519 bound_image_offset_ = 0u;
520 bound_buffer_offset_ = 0u;
521 descriptor_write_offset_ = 0u;
522 instance_count_ = 1u;
526 pipeline_uses_input_attachments_ =
false;
527 immutable_sampler_ =
nullptr;
535 const ShaderUniformSlot& slot,
536 const ShaderMetadata& metadata,
538 return BindResource(slot.binding,
type, view);
541bool RenderPassVK::BindResource(
544 const ShaderUniformSlot& slot,
545 const std::shared_ptr<const ShaderMetadata>& metadata,
547 return BindResource(slot.binding,
type, view);
550bool RenderPassVK::BindResource(
size_t binding,
552 const BufferView& view) {
557 const std::shared_ptr<const DeviceBuffer>& device_buffer = view.buffer;
558 auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer();
563 if (!command_buffer_->GetEncoder()->Track(device_buffer)) {
567 uint32_t
offset = view.range.offset;
569 vk::DescriptorBufferInfo buffer_info;
570 buffer_info.buffer =
buffer;
571 buffer_info.offset =
offset;
572 buffer_info.range = view.range.length;
573 buffer_workspace_[bound_buffer_offset_++] = buffer_info;
575 vk::WriteDescriptorSet write_set;
576 write_set.dstBinding = binding;
577 write_set.descriptorCount = 1u;
579 write_set.pBufferInfo = &buffer_workspace_[bound_buffer_offset_ - 1];
581 write_workspace_[descriptor_write_offset_++] = write_set;
587 const SampledImageSlot& slot,
588 const ShaderMetadata& metadata,
589 std::shared_ptr<const Texture>
texture,
590 const std::unique_ptr<const Sampler>& sampler) {
594 if (!
texture->IsValid() || !sampler) {
597 const TextureVK& texture_vk = TextureVK::Cast(*
texture);
598 const SamplerVK& sampler_vk = SamplerVK::Cast(*sampler);
600 if (!command_buffer_->GetEncoder()->Track(
texture)) {
604 if (!immutable_sampler_) {
605 immutable_sampler_ = texture_vk.GetImmutableSamplerVariant(sampler_vk);
608 vk::DescriptorImageInfo image_info;
609 image_info.imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;
610 image_info.sampler = sampler_vk.GetSampler();
611 image_info.imageView = texture_vk.GetImageView();
612 image_workspace_[bound_image_offset_++] = image_info;
614 vk::WriteDescriptorSet write_set;
615 write_set.dstBinding = slot.binding;
616 write_set.descriptorCount = 1u;
617 write_set.descriptorType = vk::DescriptorType::eCombinedImageSampler;
618 write_set.pImageInfo = &image_workspace_[bound_image_offset_ - 1];
620 write_workspace_[descriptor_write_offset_++] = write_set;
624bool RenderPassVK::OnEncodeCommands(
const Context& context)
const {
625 command_buffer_->GetEncoder()->GetCommandBuffer().endRenderPass();
629 const std::shared_ptr<Texture>& result_texture =
630 resolve_image_vk_ ? resolve_image_vk_ : color_image_vk_;
631 if (result_texture->GetTextureDescriptor().usage &
632 TextureUsage::kShaderRead) {
634 barrier.cmd_buffer = command_buffer_vk_;
635 barrier.src_access = vk::AccessFlagBits::eColorAttachmentWrite |
636 vk::AccessFlagBits::eTransferWrite;
637 barrier.src_stage = vk::PipelineStageFlagBits::eColorAttachmentOutput |
638 vk::PipelineStageFlagBits::eTransfer;
639 barrier.dst_access = vk::AccessFlagBits::eShaderRead;
640 barrier.dst_stage = vk::PipelineStageFlagBits::eFragmentShader;
642 barrier.new_layout = vk::ImageLayout::eShaderReadOnlyOptimal;
644 if (!TextureVK::Cast(*result_texture).SetLayout(barrier)) {
static TextureVK & Cast(Texture &base)
const RenderTarget render_target_
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
const std::optional< DepthAttachment > & GetDepthAttachment() const
const std::optional< StencilAttachment > & GetStencilAttachment() const
void SetCachedFramebuffer(const SharedHandleVK< vk::Framebuffer > &framebuffer)
SharedHandleVK< vk::RenderPass > GetCachedRenderPass() const
SharedHandleVK< vk::Framebuffer > GetCachedFramebuffer() const
bool SetLayout(const BarrierVK &barrier) const
void SetCachedRenderPass(const SharedHandleVK< vk::RenderPass > &render_pass)
static void Draw(SkCanvas *canvas, const SkRect &rect)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
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 vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
constexpr vk::IndexType ToVKIndexType(IndexType index_type)
constexpr vk::DescriptorType ToVKDescriptorType(DescriptorType type)
static constexpr size_t kMaxBindings
static constexpr size_t kMagicSubpassInputBinding
static vk::ClearDepthStencilValue VKClearValueFromDepthStencil(uint32_t stencil, Scalar depth)
static std::vector< vk::ClearValue > GetVKClearValues(const RenderTarget &target)
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 vk::ClearColorValue VKClearValueFromColor(Color color)
auto MakeSharedVK(vk::UniqueHandle< T, VULKAN_HPP_DEFAULT_DISPATCHER_TYPE > handle)
static SkString to_string(int n)
static constexpr TRect MakeSize(const TSize< U > &size)