Merge pull request #4110 from ReinUsesLisp/direct-upload-sets
vk_update_descriptor: Upload descriptor sets data directly
This commit is contained in:
		@@ -1154,7 +1154,7 @@ void RasterizerVulkan::SetupTexture(const Tegra::Texture::FullTextureInfo& textu
 | 
			
		||||
    const auto sampler = sampler_cache.GetSampler(texture.tsc);
 | 
			
		||||
    update_descriptor_queue.AddSampledImage(sampler, image_view);
 | 
			
		||||
 | 
			
		||||
    const auto image_layout = update_descriptor_queue.GetLastImageLayout();
 | 
			
		||||
    VkImageLayout* const image_layout = update_descriptor_queue.LastImageLayout();
 | 
			
		||||
    *image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 | 
			
		||||
    sampled_views.push_back(ImageView{std::move(view), image_layout});
 | 
			
		||||
}
 | 
			
		||||
@@ -1180,7 +1180,7 @@ void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const Ima
 | 
			
		||||
        view->GetImageView(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
 | 
			
		||||
    update_descriptor_queue.AddImage(image_view);
 | 
			
		||||
 | 
			
		||||
    const auto image_layout = update_descriptor_queue.GetLastImageLayout();
 | 
			
		||||
    VkImageLayout* const image_layout = update_descriptor_queue.LastImageLayout();
 | 
			
		||||
    *image_layout = VK_IMAGE_LAYOUT_GENERAL;
 | 
			
		||||
    image_views.push_back(ImageView{std::move(view), image_layout});
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,35 +24,25 @@ void VKUpdateDescriptorQueue::TickFrame() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void VKUpdateDescriptorQueue::Acquire() {
 | 
			
		||||
    entries.clear();
 | 
			
		||||
}
 | 
			
		||||
    // Minimum number of entries required.
 | 
			
		||||
    // This is the maximum number of entries a single draw call migth use.
 | 
			
		||||
    static constexpr std::size_t MIN_ENTRIES = 0x400;
 | 
			
		||||
 | 
			
		||||
void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template,
 | 
			
		||||
                                   VkDescriptorSet set) {
 | 
			
		||||
    if (payload.size() + entries.size() >= payload.max_size()) {
 | 
			
		||||
    if (payload.size() + MIN_ENTRIES >= payload.max_size()) {
 | 
			
		||||
        LOG_WARNING(Render_Vulkan, "Payload overflow, waiting for worker thread");
 | 
			
		||||
        scheduler.WaitWorker();
 | 
			
		||||
        payload.clear();
 | 
			
		||||
    }
 | 
			
		||||
    upload_start = &*payload.end();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    // TODO(Rodrigo): Rework to write the payload directly
 | 
			
		||||
    const auto payload_start = payload.data() + payload.size();
 | 
			
		||||
    for (const auto& entry : entries) {
 | 
			
		||||
        if (const auto image = std::get_if<VkDescriptorImageInfo>(&entry)) {
 | 
			
		||||
            payload.push_back(*image);
 | 
			
		||||
        } else if (const auto buffer = std::get_if<VkDescriptorBufferInfo>(&entry)) {
 | 
			
		||||
            payload.push_back(*buffer);
 | 
			
		||||
        } else if (const auto texel = std::get_if<VkBufferView>(&entry)) {
 | 
			
		||||
            payload.push_back(*texel);
 | 
			
		||||
        } else {
 | 
			
		||||
            UNREACHABLE();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scheduler.Record(
 | 
			
		||||
        [payload_start, set, update_template, logical = &device.GetLogical()](vk::CommandBuffer) {
 | 
			
		||||
            logical->UpdateDescriptorSet(set, update_template, payload_start);
 | 
			
		||||
        });
 | 
			
		||||
void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template,
 | 
			
		||||
                                   VkDescriptorSet set) {
 | 
			
		||||
    const void* const data = upload_start;
 | 
			
		||||
    const vk::Device* const logical = &device.GetLogical();
 | 
			
		||||
    scheduler.Record([data, logical, set, update_template](vk::CommandBuffer) {
 | 
			
		||||
        logical->UpdateDescriptorSet(set, update_template, data);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Vulkan
 | 
			
		||||
 
 | 
			
		||||
@@ -15,17 +15,13 @@ namespace Vulkan {
 | 
			
		||||
class VKDevice;
 | 
			
		||||
class VKScheduler;
 | 
			
		||||
 | 
			
		||||
class DescriptorUpdateEntry {
 | 
			
		||||
public:
 | 
			
		||||
    explicit DescriptorUpdateEntry() {}
 | 
			
		||||
struct DescriptorUpdateEntry {
 | 
			
		||||
    DescriptorUpdateEntry(VkDescriptorImageInfo image_) : image{image_} {}
 | 
			
		||||
 | 
			
		||||
    DescriptorUpdateEntry(VkDescriptorImageInfo image) : image{image} {}
 | 
			
		||||
    DescriptorUpdateEntry(VkDescriptorBufferInfo buffer_) : buffer{buffer_} {}
 | 
			
		||||
 | 
			
		||||
    DescriptorUpdateEntry(VkDescriptorBufferInfo buffer) : buffer{buffer} {}
 | 
			
		||||
    DescriptorUpdateEntry(VkBufferView texel_buffer_) : texel_buffer{texel_buffer_} {}
 | 
			
		||||
 | 
			
		||||
    DescriptorUpdateEntry(VkBufferView texel_buffer) : texel_buffer{texel_buffer} {}
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    union {
 | 
			
		||||
        VkDescriptorImageInfo image;
 | 
			
		||||
        VkDescriptorBufferInfo buffer;
 | 
			
		||||
@@ -45,32 +41,34 @@ public:
 | 
			
		||||
    void Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set);
 | 
			
		||||
 | 
			
		||||
    void AddSampledImage(VkSampler sampler, VkImageView image_view) {
 | 
			
		||||
        entries.emplace_back(VkDescriptorImageInfo{sampler, image_view, {}});
 | 
			
		||||
        payload.emplace_back(VkDescriptorImageInfo{sampler, image_view, {}});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void AddImage(VkImageView image_view) {
 | 
			
		||||
        entries.emplace_back(VkDescriptorImageInfo{{}, image_view, {}});
 | 
			
		||||
        payload.emplace_back(VkDescriptorImageInfo{{}, image_view, {}});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void AddBuffer(VkBuffer buffer, u64 offset, std::size_t size) {
 | 
			
		||||
        entries.emplace_back(VkDescriptorBufferInfo{buffer, offset, size});
 | 
			
		||||
        payload.emplace_back(VkDescriptorBufferInfo{buffer, offset, size});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void AddTexelBuffer(VkBufferView texel_buffer) {
 | 
			
		||||
        entries.emplace_back(texel_buffer);
 | 
			
		||||
        payload.emplace_back(texel_buffer);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    VkImageLayout* GetLastImageLayout() {
 | 
			
		||||
        return &std::get<VkDescriptorImageInfo>(entries.back()).imageLayout;
 | 
			
		||||
    VkImageLayout* LastImageLayout() {
 | 
			
		||||
        return &payload.back().image.imageLayout;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const VkImageLayout* LastImageLayout() const {
 | 
			
		||||
        return &payload.back().image.imageLayout;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    using Variant = std::variant<VkDescriptorImageInfo, VkDescriptorBufferInfo, VkBufferView>;
 | 
			
		||||
 | 
			
		||||
    const VKDevice& device;
 | 
			
		||||
    VKScheduler& scheduler;
 | 
			
		||||
 | 
			
		||||
    boost::container::static_vector<Variant, 0x400> entries;
 | 
			
		||||
    const DescriptorUpdateEntry* upload_start = nullptr;
 | 
			
		||||
    boost::container::static_vector<DescriptorUpdateEntry, 0x10000> payload;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user