|
|
|
@ -20,6 +20,8 @@
|
|
|
|
|
|
|
|
|
|
namespace Vulkan {
|
|
|
|
|
|
|
|
|
|
constexpr size_t MAX_RESCALING_WORDS = 4;
|
|
|
|
|
|
|
|
|
|
class DescriptorLayoutBuilder {
|
|
|
|
|
public:
|
|
|
|
|
DescriptorLayoutBuilder(const Device& device_) : device{&device_} {}
|
|
|
|
@ -68,18 +70,26 @@ public:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vk::PipelineLayout CreatePipelineLayout(VkDescriptorSetLayout descriptor_set_layout) const {
|
|
|
|
|
const VkPushConstantRange range{
|
|
|
|
|
.stageFlags = static_cast<VkShaderStageFlags>(
|
|
|
|
|
is_compute ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_ALL_GRAPHICS),
|
|
|
|
|
.offset = 0,
|
|
|
|
|
.size = (is_compute ? 0 : sizeof(f32)) + sizeof(std::array<u32, MAX_RESCALING_WORDS>),
|
|
|
|
|
};
|
|
|
|
|
return device->GetLogical().CreatePipelineLayout({
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
|
|
|
.pNext = nullptr,
|
|
|
|
|
.flags = 0,
|
|
|
|
|
.setLayoutCount = descriptor_set_layout ? 1U : 0U,
|
|
|
|
|
.pSetLayouts = bindings.empty() ? nullptr : &descriptor_set_layout,
|
|
|
|
|
.pushConstantRangeCount = 0,
|
|
|
|
|
.pPushConstantRanges = nullptr,
|
|
|
|
|
.pushConstantRangeCount = 1,
|
|
|
|
|
.pPushConstantRanges = &range,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Add(const Shader::Info& info, VkShaderStageFlags stage) {
|
|
|
|
|
is_compute |= (stage & VK_SHADER_STAGE_COMPUTE_BIT) != 0;
|
|
|
|
|
|
|
|
|
|
Add(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, stage, info.constant_buffer_descriptors);
|
|
|
|
|
Add(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, stage, info.storage_buffers_descriptors);
|
|
|
|
|
Add(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, stage, info.texture_buffer_descriptors);
|
|
|
|
@ -115,6 +125,7 @@ private:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Device* device{};
|
|
|
|
|
bool is_compute{};
|
|
|
|
|
boost::container::small_vector<VkDescriptorSetLayoutBinding, 32> bindings;
|
|
|
|
|
boost::container::small_vector<VkDescriptorUpdateTemplateEntryKHR, 32> entries;
|
|
|
|
|
u32 binding{};
|
|
|
|
@ -122,21 +133,46 @@ private:
|
|
|
|
|
size_t offset{};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers,
|
|
|
|
|
const ImageId*& image_view_ids, TextureCache& texture_cache,
|
|
|
|
|
VKUpdateDescriptorQueue& update_descriptor_queue) {
|
|
|
|
|
for (const auto& desc : info.texture_buffer_descriptors) {
|
|
|
|
|
image_view_ids += desc.count;
|
|
|
|
|
class RescalingPushConstant {
|
|
|
|
|
public:
|
|
|
|
|
explicit RescalingPushConstant(u32 num_textures) noexcept {}
|
|
|
|
|
|
|
|
|
|
void PushTexture(bool is_rescaled) noexcept {
|
|
|
|
|
*texture_ptr |= is_rescaled ? texture_bit : 0;
|
|
|
|
|
texture_bit <<= 1;
|
|
|
|
|
if (texture_bit == 0) {
|
|
|
|
|
texture_bit = 1u;
|
|
|
|
|
++texture_ptr;
|
|
|
|
|
}
|
|
|
|
|
for (const auto& desc : info.image_buffer_descriptors) {
|
|
|
|
|
image_view_ids += desc.count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::array<u32, MAX_RESCALING_WORDS>& Data() const noexcept {
|
|
|
|
|
return words;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
std::array<u32, MAX_RESCALING_WORDS> words{};
|
|
|
|
|
u32* texture_ptr{words.data()};
|
|
|
|
|
u32 texture_bit{1u};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
inline void PushImageDescriptors(const Shader::Info& info, const VkSampler*& samplers,
|
|
|
|
|
const ImageId*& image_view_ids, TextureCache& texture_cache,
|
|
|
|
|
VKUpdateDescriptorQueue& update_descriptor_queue,
|
|
|
|
|
RescalingPushConstant& rescaling) {
|
|
|
|
|
static constexpr VideoCommon::ImageViewId NULL_IMAGE_VIEW_ID{0};
|
|
|
|
|
image_view_ids += Shader::NumDescriptors(info.texture_buffer_descriptors);
|
|
|
|
|
image_view_ids += Shader::NumDescriptors(info.image_buffer_descriptors);
|
|
|
|
|
for (const auto& desc : info.texture_descriptors) {
|
|
|
|
|
for (u32 index = 0; index < desc.count; ++index) {
|
|
|
|
|
const VideoCommon::ImageViewId image_view_id{*(image_view_ids++)};
|
|
|
|
|
const VkSampler sampler{*(samplers++)};
|
|
|
|
|
ImageView& image_view{texture_cache.GetImageView(*(image_view_ids++))};
|
|
|
|
|
ImageView& image_view{texture_cache.GetImageView(image_view_id)};
|
|
|
|
|
const Image& image{texture_cache.GetImage(image_view.image_id)};
|
|
|
|
|
const VkImageView vk_image_view{image_view.Handle(desc.type)};
|
|
|
|
|
update_descriptor_queue.AddSampledImage(vk_image_view, sampler);
|
|
|
|
|
rescaling.PushTexture(image_view_id != NULL_IMAGE_VIEW_ID &&
|
|
|
|
|
True(image.flags & VideoCommon::ImageFlagBits::Rescaled));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (const auto& desc : info.image_descriptors) {
|
|
|
|
|