mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] Wire image sampler descriptors for Vulkan (flutter/engine#36641)
This commit is contained in:
parent
56600abc8f
commit
0fd45d69a8
@ -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 %}
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -23,6 +23,7 @@ class AllocatorVK final : public Allocator {
|
||||
|
||||
VmaAllocator allocator_ = {};
|
||||
ContextVK& context_;
|
||||
vk::Device device_;
|
||||
bool is_valid_ = false;
|
||||
|
||||
AllocatorVK(ContextVK& context,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -21,6 +21,8 @@ class SamplerVK final : public Sampler, public BackendCast<SamplerVK, Sampler> {
|
||||
// |Sampler|
|
||||
~SamplerVK() override;
|
||||
|
||||
vk::Sampler GetSamplerVK() const;
|
||||
|
||||
private:
|
||||
friend SamplerLibraryVK;
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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.";
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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; }
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user