[Impeller] Wire image sampler descriptors for Vulkan (flutter/engine#36641)

This commit is contained in:
Kaushik Iska 2022-10-06 15:25:22 -04:00 committed by GitHub
parent 56600abc8f
commit 0fd45d69a8
12 changed files with 171 additions and 58 deletions

View File

@ -107,6 +107,8 @@ struct {{camel_case(shader_name)}}{{camel_case(shader_stage)}}Shader {
"{{sampled_image.name}}", // name
{{sampled_image.ext_res_0}}u, // texture
{{sampled_image.ext_res_1}}u, // sampler
{{sampled_image.binding}}u, // binding
{{sampled_image.set}}u, // set
};
static ShaderMetadata kMetadata{{camel_case(sampled_image.name)}};
{% endfor %}

View File

@ -26,7 +26,7 @@ AllocatorVK::AllocatorVK(ContextVK& context,
const vk::Instance& instance,
PFN_vkGetInstanceProcAddr get_instance_proc_address,
PFN_vkGetDeviceProcAddr get_device_proc_address)
: context_(context) {
: context_(context), device_(logical_device) {
VmaVulkanFunctions proc_table = {};
proc_table.vkGetInstanceProcAddr = get_instance_proc_address;
proc_table.vkGetDeviceProcAddr = get_device_proc_address;
@ -100,6 +100,22 @@ std::shared_ptr<Texture> AllocatorVK::OnCreateTexture(
return nullptr;
}
vk::ImageViewCreateInfo view_create_info = {};
view_create_info.image = img;
view_create_info.viewType = vk::ImageViewType::e2D;
view_create_info.format = image_create_info.format;
view_create_info.subresourceRange.aspectMask =
vk::ImageAspectFlagBits::eColor;
view_create_info.subresourceRange.levelCount = image_create_info.mipLevels;
view_create_info.subresourceRange.layerCount = image_create_info.arrayLayers;
auto img_view_res = device_.createImageView(view_create_info);
if (img_view_res.result != vk::Result::eSuccess) {
VALIDATION_LOG << "Unable to create an image view: "
<< vk::to_string(img_view_res.result);
return nullptr;
}
auto texture_info = std::make_unique<TextureInfoVK>(TextureInfoVK{
.backing_type = TextureBackingTypeVK::kAllocatedTexture,
.allocated_texture =
@ -108,6 +124,7 @@ std::shared_ptr<Texture> AllocatorVK::OnCreateTexture(
.allocation = allocation,
.allocation_info = allocation_info,
.image = img,
.image_view = img_view_res.value,
},
});
return std::make_shared<TextureVK>(desc, &context_, std::move(texture_info));

View File

@ -23,6 +23,7 @@ class AllocatorVK final : public Allocator {
VmaAllocator allocator_ = {};
ContextVK& context_;
vk::Device device_;
bool is_valid_ = false;
AllocatorVK(ContextVK& context,

View File

@ -13,9 +13,13 @@
#include "impeller/renderer/backend/vulkan/device_buffer_vk.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"
#include "impeller/renderer/backend/vulkan/pipeline_vk.h"
#include "impeller/renderer/backend/vulkan/sampler_vk.h"
#include "impeller/renderer/backend/vulkan/surface_producer_vk.h"
#include "impeller/renderer/backend/vulkan/texture_vk.h"
#include "impeller/renderer/sampler.h"
#include "impeller/renderer/shader_types.h"
#include "vulkan/vulkan_enums.hpp"
#include "vulkan/vulkan_structs.hpp"
namespace impeller {
@ -77,52 +81,10 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const {
const uint32_t frame_num = tex_info.frame_num;
// layout transition.
{
auto pool = command_buffer_.getPool();
vk::CommandBufferAllocateInfo alloc_info =
vk::CommandBufferAllocateInfo()
.setCommandPool(pool)
.setLevel(vk::CommandBufferLevel::ePrimary)
.setCommandBufferCount(1);
auto cmd_buf_res = device_.allocateCommandBuffersUnique(alloc_info);
if (cmd_buf_res.result != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to allocate command buffer: "
<< vk::to_string(cmd_buf_res.result);
return false;
}
auto transition_cmd = std::move(cmd_buf_res.value[0]);
vk::CommandBufferBeginInfo begin_info;
auto res = transition_cmd->begin(begin_info);
vk::ImageMemoryBarrier barrier =
vk::ImageMemoryBarrier()
.setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentRead)
.setDstAccessMask(vk::AccessFlagBits::eColorAttachmentWrite)
.setOldLayout(vk::ImageLayout::eUndefined)
.setNewLayout(vk::ImageLayout::eColorAttachmentOptimal)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setImage(tex_info.swapchain_image->GetImage())
.setSubresourceRange(
vk::ImageSubresourceRange()
.setAspectMask(vk::ImageAspectFlagBits::eColor)
.setBaseMipLevel(0)
.setLevelCount(1)
.setBaseArrayLayer(0)
.setLayerCount(1));
transition_cmd->pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eColorAttachmentOutput, {}, nullptr, nullptr,
barrier);
res = transition_cmd->end();
if (res != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res);
return false;
}
surface_producer_->QueueCommandBuffer(frame_num, std::move(transition_cmd));
if (!TransitionImageLayout(frame_num, tex_info.swapchain_image->GetImage(),
vk::ImageLayout::eUndefined,
vk::ImageLayout::eColorAttachmentOptimal)) {
return false;
}
vk::ClearValue clear_value;
@ -162,7 +124,7 @@ bool RenderPassVK::OnEncodeCommands(const Context& context) const {
continue;
}
if (!EncodeCommand(context, command)) {
if (!EncodeCommand(frame_num, context, command)) {
return false;
}
}
@ -188,14 +150,16 @@ bool RenderPassVK::EndCommandBuffer(uint32_t frame_num) {
return false;
}
bool RenderPassVK::EncodeCommand(const Context& context,
bool RenderPassVK::EncodeCommand(uint32_t frame_num,
const Context& context,
const Command& command) const {
SetViewportAndScissor(command);
auto& pipeline_vk = PipelineVK::Cast(*command.pipeline);
PipelineCreateInfoVK* pipeline_create_info = pipeline_vk.GetCreateInfo();
if (!AllocateAndBindDescriptorSets(context, command, pipeline_create_info)) {
if (!AllocateAndBindDescriptorSets(frame_num, context, command,
pipeline_create_info)) {
return false;
}
@ -243,6 +207,7 @@ bool RenderPassVK::EncodeCommand(const Context& context,
}
bool RenderPassVK::AllocateAndBindDescriptorSets(
uint32_t frame_num,
const Context& context,
const Command& command,
PipelineCreateInfoVK* pipeline_create_info) const {
@ -269,13 +234,15 @@ bool RenderPassVK::AllocateAndBindDescriptorSets(
}
auto desc_sets = desc_sets_res.value;
bool update_vertex_descriptors = UpdateDescriptorSets(
"vertex_bindings", command.vertex_bindings, allocator, desc_sets[0]);
bool update_vertex_descriptors =
UpdateDescriptorSets(frame_num, "vertex_bindings",
command.vertex_bindings, allocator, desc_sets[0]);
if (!update_vertex_descriptors) {
return false;
}
bool update_frag_descriptors = UpdateDescriptorSets(
"fragment_bindings", command.fragment_bindings, allocator, desc_sets[0]);
bool update_frag_descriptors =
UpdateDescriptorSets(frame_num, "fragment_bindings",
command.fragment_bindings, allocator, desc_sets[0]);
if (!update_frag_descriptors) {
return false;
}
@ -285,12 +252,15 @@ bool RenderPassVK::AllocateAndBindDescriptorSets(
return true;
}
bool RenderPassVK::UpdateDescriptorSets(const char* label,
bool RenderPassVK::UpdateDescriptorSets(uint32_t frame_num,
const char* label,
const Bindings& bindings,
Allocator& allocator,
vk::DescriptorSet desc_set) const {
std::vector<vk::WriteDescriptorSet> writes;
std::vector<vk::DescriptorBufferInfo> buffer_infos;
std::vector<vk::DescriptorImageInfo> image_infos;
for (const auto& [buffer_index, view] : bindings.buffers) {
const auto& buffer_view = view.resource.buffer;
@ -330,6 +300,42 @@ bool RenderPassVK::UpdateDescriptorSets(const char* label,
writes.push_back(setWrite);
}
for (const auto& [index, sampler_handle] : bindings.samplers) {
if (bindings.textures.find(index) == bindings.textures.end()) {
VALIDATION_LOG << "Missing texture for sampler: " << index;
return false;
}
const auto& texture_vk =
TextureVK::Cast(*bindings.textures.at(index).resource);
const Sampler& sampler = *sampler_handle.resource;
const SamplerVK& sampler_vk = SamplerVK::Cast(sampler);
const SampledImageSlot& slot = bindings.sampled_images.at(index);
if (!TransitionImageLayout(frame_num, texture_vk.GetImage(),
vk::ImageLayout::eUndefined,
vk::ImageLayout::eGeneral)) {
return false;
}
vk::DescriptorImageInfo desc_image_info;
desc_image_info.setImageLayout(vk::ImageLayout::eGeneral);
desc_image_info.setSampler(sampler_vk.GetSamplerVK());
desc_image_info.setImageView(texture_vk.GetImageView());
image_infos.push_back(desc_image_info);
vk::WriteDescriptorSet setWrite;
setWrite.setDstSet(desc_set);
setWrite.setDstBinding(slot.binding);
setWrite.setDescriptorCount(1);
setWrite.setDescriptorType(vk::DescriptorType::eCombinedImageSampler);
setWrite.setPImageInfo(&image_infos.back());
writes.push_back(setWrite);
}
std::array<vk::CopyDescriptorSet, 0> copies;
device_.updateDescriptorSets(writes, copies);
@ -374,4 +380,56 @@ vk::Framebuffer RenderPassVK::CreateFrameBuffer(
return std::move(res.value);
}
bool RenderPassVK::TransitionImageLayout(uint32_t frame_num,
vk::Image image,
vk::ImageLayout layout_old,
vk::ImageLayout layout_new) const {
auto pool = command_buffer_.getPool();
vk::CommandBufferAllocateInfo alloc_info =
vk::CommandBufferAllocateInfo()
.setCommandPool(pool)
.setLevel(vk::CommandBufferLevel::ePrimary)
.setCommandBufferCount(1);
auto cmd_buf_res = device_.allocateCommandBuffersUnique(alloc_info);
if (cmd_buf_res.result != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to allocate command buffer: "
<< vk::to_string(cmd_buf_res.result);
return false;
}
auto transition_cmd = std::move(cmd_buf_res.value[0]);
vk::CommandBufferBeginInfo begin_info;
auto res = transition_cmd->begin(begin_info);
vk::ImageMemoryBarrier barrier =
vk::ImageMemoryBarrier()
.setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentRead)
.setDstAccessMask(vk::AccessFlagBits::eColorAttachmentWrite)
.setOldLayout(layout_old)
.setNewLayout(layout_new)
.setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
.setImage(image)
.setSubresourceRange(
vk::ImageSubresourceRange()
.setAspectMask(vk::ImageAspectFlagBits::eColor)
.setBaseMipLevel(0)
.setLevelCount(1)
.setBaseArrayLayer(0)
.setLayerCount(1));
transition_cmd->pipelineBarrier(
vk::PipelineStageFlagBits::eColorAttachmentOutput,
vk::PipelineStageFlagBits::eColorAttachmentOutput, {}, nullptr, nullptr,
barrier);
res = transition_cmd->end();
if (res != vk::Result::eSuccess) {
VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res);
return false;
}
surface_producer_->QueueCommandBuffer(frame_num, std::move(transition_cmd));
return true;
}
} // namespace impeller

View File

@ -12,6 +12,7 @@
#include "impeller/renderer/command.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/render_target.h"
#include "vulkan/vulkan_enums.hpp"
#include "vulkan/vulkan_structs.hpp"
namespace impeller {
@ -48,16 +49,20 @@ class RenderPassVK final : public RenderPass {
// |RenderPass|
bool OnEncodeCommands(const Context& context) const override;
bool EncodeCommand(const Context& context, const Command& command) const;
bool EncodeCommand(uint32_t frame_num,
const Context& context,
const Command& command) const;
bool AllocateAndBindDescriptorSets(
uint32_t frame_num,
const Context& context,
const Command& command,
PipelineCreateInfoVK* pipeline_create_info) const;
bool EndCommandBuffer(uint32_t frame_num);
bool UpdateDescriptorSets(const char* label,
bool UpdateDescriptorSets(uint32_t frame_num,
const char* label,
const Bindings& bindings,
Allocator& allocator,
vk::DescriptorSet desc_set) const;
@ -67,6 +72,11 @@ class RenderPassVK final : public RenderPass {
vk::Framebuffer CreateFrameBuffer(
const WrappedTextureInfoVK& wrapped_texture_info) const;
bool TransitionImageLayout(uint32_t frame_num,
vk::Image image,
vk::ImageLayout layout_old,
vk::ImageLayout layout_new) const;
FML_DISALLOW_COPY_AND_ASSIGN(RenderPassVK);
};

View File

@ -7,8 +7,12 @@
namespace impeller {
SamplerVK::~SamplerVK() {}
vk::Sampler SamplerVK::GetSamplerVK() const {
return sampler_.get();
}
SamplerVK::SamplerVK(SamplerDescriptor desc, vk::UniqueSampler sampler)
: Sampler(desc), sampler_(std::move(sampler)) {
: Sampler(std::move(desc)), sampler_(std::move(sampler)) {
is_valid_ = true;
}

View File

@ -21,6 +21,8 @@ class SamplerVK final : public Sampler, public BackendCast<SamplerVK, Sampler> {
// |Sampler|
~SamplerVK() override;
vk::Sampler GetSamplerVK() const;
private:
friend SamplerLibraryVK;

View File

@ -81,6 +81,17 @@ bool TextureVK::IsWrapped() const {
return texture_info_->backing_type == TextureBackingTypeVK::kWrappedTexture;
}
vk::ImageView TextureVK::GetImageView() const {
switch (texture_info_->backing_type) {
case TextureBackingTypeVK::kUnknownType:
return nullptr;
case TextureBackingTypeVK::kAllocatedTexture:
return texture_info_->allocated_texture.image_view;
case TextureBackingTypeVK::kWrappedTexture:
return texture_info_->wrapped_texture.swapchain_image->GetImageView();
}
}
vk::Image TextureVK::GetImage() const {
switch (texture_info_->backing_type) {
case TextureBackingTypeVK::kUnknownType:

View File

@ -29,6 +29,7 @@ struct AllocatedTextureInfoVK {
VmaAllocation allocation = nullptr;
VmaAllocationInfo allocation_info = {};
VkImage image = nullptr;
VkImageView image_view = nullptr;
};
struct TextureInfoVK {
@ -52,6 +53,8 @@ class TextureVK final : public Texture, public BackendCast<TextureVK, Texture> {
vk::Image GetImage() const;
vk::ImageView GetImageView() const;
TextureInfoVK* GetTextureInfo() const;
private:

View File

@ -108,9 +108,11 @@ bool Command::BindResource(ShaderStage stage,
switch (stage) {
case ShaderStage::kVertex:
vertex_bindings.samplers[slot.sampler_index] = {&metadata, sampler};
vertex_bindings.sampled_images[slot.sampler_index] = slot;
return true;
case ShaderStage::kFragment:
fragment_bindings.samplers[slot.sampler_index] = {&metadata, sampler};
fragment_bindings.sampled_images[slot.sampler_index] = slot;
return true;
case ShaderStage::kCompute:
VALIDATION_LOG << "Use ComputeCommands for compute shader stages.";

View File

@ -42,6 +42,7 @@ using SamplerResource = Resource<std::shared_ptr<const Sampler>>;
struct Bindings {
std::map<size_t, ShaderUniformSlot> uniforms;
std::map<size_t, SampledImageSlot> sampled_images;
std::map<size_t, BufferResource> buffers;
std::map<size_t, TextureResource> textures;
std::map<size_t, SamplerResource> samplers;

View File

@ -114,6 +114,8 @@ struct SampledImageSlot {
const char* name;
size_t texture_index;
size_t sampler_index;
size_t binding;
size_t set;
constexpr bool HasTexture() const { return texture_index < 32u; }