vulkan: cache per-poly desc sets in map

avoid desc set pool exhaustion in per-triangle
This commit is contained in:
Flyinghead 2022-03-13 11:39:30 +01:00
parent 53b5588bda
commit ad08590197
6 changed files with 117 additions and 82 deletions

View File

@ -281,8 +281,8 @@ void Drawer::UploadMainBuffer(const VertexShaderUniforms& vertexUniforms, const
std::vector<u8> n2lights;
if (settings.platform.isNaomi2())
{
uploadNaomi2Uniforms(packer, offsets, n2uniforms, false);
offsets.lightsOffset = uploadNaomi2Lights(packer, n2lights);
packNaomi2Uniforms(packer, offsets, n2uniforms, false);
offsets.lightsOffset = packNaomi2Lights(packer, n2lights);
}
BufferData *buffer = GetMainBuffer(packer.size());

View File

@ -73,7 +73,7 @@ protected:
}
template<typename Offsets>
void uploadNaomi2Uniforms(BufferPacker& packer, Offsets& offsets, std::vector<u8>& n2uniforms, bool trModVolIncluded)
void packNaomi2Uniforms(BufferPacker& packer, Offsets& offsets, std::vector<u8>& n2uniforms, bool trModVolIncluded)
{
size_t n2UniformSize = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), GetContext()->GetUniformBufferAlignment());
int items = pvrrc.global_param_op.used() + pvrrc.global_param_pt.used() + pvrrc.global_param_tr.used() + pvrrc.global_param_mvo.used();
@ -139,7 +139,7 @@ protected:
offsets.naomi2TrModVolOffset = offsets.naomi2OpaqueOffset + trMvOffset;
}
vk::DeviceSize uploadNaomi2Lights(BufferPacker& packer, std::vector<u8>& n2lights)
vk::DeviceSize packNaomi2Lights(BufferPacker& packer, std::vector<u8>& n2lights)
{
size_t n2LightSize = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), GetContext()->GetUniformBufferAlignment());
n2lights.resize(pvrrc.lightModels.used() * n2LightSize);
@ -202,7 +202,7 @@ protected:
virtual vk::CommandBuffer BeginRenderPass() = 0;
void NewImage()
{
descriptorSets.reset();
descriptorSets.nextFrame();
imageIndex = (imageIndex + 1) % GetSwapChainSize();
if (perStripSorting != config::PerStripSorting)
{

View File

@ -241,8 +241,8 @@ void OITDrawer::UploadMainBuffer(const OITDescriptorSets::VertexShaderUniforms&
std::vector<u8> n2lights;
if (settings.platform.isNaomi2())
{
uploadNaomi2Uniforms(packer, offsets, n2uniforms, true);
offsets.lightsOffset = uploadNaomi2Lights(packer, n2lights);
packNaomi2Uniforms(packer, offsets, n2uniforms, true);
offsets.lightsOffset = packNaomi2Lights(packer, n2lights);
}
BufferData *buffer = GetMainBuffer(packer.size());

View File

@ -75,7 +75,7 @@ protected:
void NewImage()
{
descriptorSets.reset();
descriptorSets.nextFrame();
imageIndex = (imageIndex + 1) % GetContext()->GetSwapChainSize();
renderPass = 0;
}

View File

@ -27,6 +27,7 @@
#include "../desc_set.h"
#include <glm/glm.hpp>
#include <unordered_map>
class OITDescriptorSets
{
@ -154,44 +155,51 @@ public:
void bindPerPolyDescriptorSets(vk::CommandBuffer cmdBuffer, const PolyParam& poly, int polyNumber, vk::Buffer buffer,
vk::DeviceSize uniformOffset, vk::DeviceSize lightOffset)
{
vk::DescriptorSet perPolyDescSet = perPolyAlloc.alloc();
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
vk::DescriptorImageInfo imageInfo0;
if (poly.texture != nullptr)
vk::DescriptorSet perPolyDescSet;
auto it = perPolyDescSets.find(&poly);
if (it == perPolyDescSets.end())
{
imageInfo0 = vk::DescriptorImageInfo{ samplerManager->GetSampler(poly.tsp), ((Texture *)poly.texture)->GetReadOnlyImageView(),
vk::ImageLayout::eShaderReadOnlyOptimal };
writeDescriptorSets.emplace_back(perPolyDescSet, 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo0, nullptr, nullptr);
}
vk::DescriptorImageInfo imageInfo1;
if (poly.texture1 != nullptr)
{
imageInfo1 = vk::DescriptorImageInfo{ samplerManager->GetSampler(poly.tsp1), ((Texture *)poly.texture1)->GetReadOnlyImageView(),
vk::ImageLayout::eShaderReadOnlyOptimal };
writeDescriptorSets.emplace_back(perPolyDescSet, 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo1, nullptr, nullptr);
}
perPolyDescSet = perPolyAlloc.alloc();
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
vk::DescriptorBufferInfo uniBufferInfo;
vk::DescriptorBufferInfo lightBufferInfo;
if (poly.isNaomi2())
{
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
uniBufferInfo = vk::DescriptorBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
writeDescriptorSets.emplace_back(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
if (poly.lightModel != nullptr)
vk::DescriptorImageInfo imageInfo0;
if (poly.texture != nullptr)
{
size = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), uniformAlignment);
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(VkN2LightConstants) };
writeDescriptorSets.emplace_back(perPolyDescSet, 3, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &lightBufferInfo, nullptr);
imageInfo0 = vk::DescriptorImageInfo{ samplerManager->GetSampler(poly.tsp), ((Texture *)poly.texture)->GetReadOnlyImageView(),
vk::ImageLayout::eShaderReadOnlyOptimal };
writeDescriptorSets.emplace_back(perPolyDescSet, 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo0, nullptr, nullptr);
}
// TODO no light
vk::DescriptorImageInfo imageInfo1;
if (poly.texture1 != nullptr)
{
imageInfo1 = vk::DescriptorImageInfo{ samplerManager->GetSampler(poly.tsp1), ((Texture *)poly.texture1)->GetReadOnlyImageView(),
vk::ImageLayout::eShaderReadOnlyOptimal };
writeDescriptorSets.emplace_back(perPolyDescSet, 1, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo1, nullptr, nullptr);
}
vk::DescriptorBufferInfo uniBufferInfo;
vk::DescriptorBufferInfo lightBufferInfo;
if (poly.isNaomi2())
{
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
uniBufferInfo = vk::DescriptorBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
writeDescriptorSets.emplace_back(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
if (poly.lightModel != nullptr)
{
size = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), uniformAlignment);
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(VkN2LightConstants) };
writeDescriptorSets.emplace_back(perPolyDescSet, 3, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &lightBufferInfo, nullptr);
}
// TODO no light
}
getContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
perPolyDescSets[&poly] = perPolyDescSet;
}
getContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
else
perPolyDescSet = it->second;
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1, &perPolyDescSet, 0, nullptr);
}
@ -199,15 +207,22 @@ public:
{
if (!mvParam.isNaomi2())
return;
vk::DescriptorSet perPolyDescSet = perPolyAlloc.alloc();
vk::DescriptorSet perPolyDescSet;
auto it = perPolyDescSets.find(&mvParam);
if (it == perPolyDescSets.end())
{
perPolyDescSet = perPolyAlloc.alloc();
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
vk::DescriptorBufferInfo uniBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
vk::WriteDescriptorSet writeDescriptorSet(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
getContext()->GetDevice().updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
vk::DescriptorBufferInfo uniBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
vk::WriteDescriptorSet writeDescriptorSet(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
getContext()->GetDevice().updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
perPolyDescSets[&mvParam] = perPolyDescSet;
}
else
perPolyDescSet = it->second;
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1, &perPolyDescSet, 0, nullptr);
}
@ -221,11 +236,12 @@ public:
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 2, 1, &colorInputDescSets[index], 0, nullptr);
}
void reset()
void nextFrame()
{
perFrameDescSet = vk::DescriptorSet{};
colorInputDescSets[0] = vk::DescriptorSet{};
colorInputDescSets[1] = vk::DescriptorSet{};
perPolyDescSets.clear();
perFrameAlloc.nextFrame();
perPolyAlloc.nextFrame();
colorInputAlloc.nextFrame();
@ -248,6 +264,7 @@ private:
DynamicDescSetAlloc perPolyAlloc;
DynamicDescSetAlloc colorInputAlloc;
vk::DescriptorSet perFrameDescSet = {};
std::unordered_map<const void *, vk::DescriptorSet> perPolyDescSets;
SamplerManager* samplerManager;
};

View File

@ -26,6 +26,7 @@
#include "vulkan_context.h"
#include "desc_set.h"
#include <array>
#include <unordered_map>
class DescriptorSets
{
@ -78,36 +79,44 @@ public:
void bindPerPolyDescriptorSets(vk::CommandBuffer cmdBuffer, const PolyParam& poly, int polyNumber, vk::Buffer buffer,
vk::DeviceSize uniformOffset, vk::DeviceSize lightOffset)
{
vk::DescriptorSet perPolyDescSet = perPolyAlloc.alloc();
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
vk::DescriptorImageInfo imageInfo;
if (poly.texture != nullptr)
vk::DescriptorSet perPolyDescSet;
auto it = perPolyDescSets.find(&poly);
if (it == perPolyDescSets.end())
{
imageInfo = vk::DescriptorImageInfo(samplerManager->GetSampler(poly.tsp),
((Texture *)poly.texture)->GetReadOnlyImageView(), vk::ImageLayout::eShaderReadOnlyOptimal);
writeDescriptorSets.emplace_back(perPolyDescSet, 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr);
}
perPolyDescSet = perPolyAlloc.alloc();
std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
vk::DescriptorBufferInfo uniBufferInfo;
vk::DescriptorBufferInfo lightBufferInfo;
if (poly.isNaomi2())
{
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
uniBufferInfo = vk::DescriptorBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
writeDescriptorSets.emplace_back(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
if (poly.lightModel != nullptr)
vk::DescriptorImageInfo imageInfo;
if (poly.texture != nullptr)
{
size = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), uniformAlignment);
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(VkN2LightConstants) };
writeDescriptorSets.emplace_back(perPolyDescSet, 3, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &lightBufferInfo, nullptr);
imageInfo = vk::DescriptorImageInfo(samplerManager->GetSampler(poly.tsp),
((Texture *)poly.texture)->GetReadOnlyImageView(), vk::ImageLayout::eShaderReadOnlyOptimal);
writeDescriptorSets.emplace_back(perPolyDescSet, 0, 0, 1, vk::DescriptorType::eCombinedImageSampler, &imageInfo, nullptr, nullptr);
}
// TODO no light
}
getContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
vk::DescriptorBufferInfo uniBufferInfo;
vk::DescriptorBufferInfo lightBufferInfo;
if (poly.isNaomi2())
{
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
uniBufferInfo = vk::DescriptorBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
writeDescriptorSets.emplace_back(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
if (poly.lightModel != nullptr)
{
size = sizeof(VkN2LightConstants) + align(sizeof(VkN2LightConstants), uniformAlignment);
lightBufferInfo = vk::DescriptorBufferInfo{ buffer, lightOffset + (poly.lightModel - pvrrc.lightModels.head()) * size, sizeof(VkN2LightConstants) };
writeDescriptorSets.emplace_back(perPolyDescSet, 3, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &lightBufferInfo, nullptr);
}
// TODO no light
}
getContext()->GetDevice().updateDescriptorSets(writeDescriptorSets, nullptr);
perPolyDescSets[&poly] = perPolyDescSet;
}
else
perPolyDescSet = it->second;
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1, &perPolyDescSet, 0, nullptr);
}
@ -116,15 +125,22 @@ public:
{
if (!mvParam.isNaomi2())
return;
vk::DescriptorSet perPolyDescSet = perPolyAlloc.alloc();
vk::DescriptorSet perPolyDescSet;
auto it = perPolyDescSets.find(&mvParam);
if (it == perPolyDescSets.end())
{
perPolyDescSet = perPolyAlloc.alloc();
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
vk::DescriptorBufferInfo uniBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
vk::WriteDescriptorSet writeDescriptorSet(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
getContext()->GetDevice().updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
const vk::DeviceSize uniformAlignment = VulkanContext::Instance()->GetUniformBufferAlignment();
size_t size = sizeof(N2VertexShaderUniforms) + align(sizeof(N2VertexShaderUniforms), uniformAlignment);
vk::DescriptorBufferInfo uniBufferInfo{ buffer, uniformOffset + polyNumber * size, sizeof(N2VertexShaderUniforms) };
vk::WriteDescriptorSet writeDescriptorSet(perPolyDescSet, 2, 0, 1, vk::DescriptorType::eUniformBuffer, nullptr, &uniBufferInfo, nullptr);
getContext()->GetDevice().updateDescriptorSets(1, &writeDescriptorSet, 0, nullptr);
perPolyDescSets[&mvParam] = perPolyDescSet;
}
else
perPolyDescSet = it->second;
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 1, 1, &perPolyDescSet, 0, nullptr);
}
@ -133,11 +149,12 @@ public:
cmdBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout, 0, 1, &perFrameDescSet, 0, nullptr);
}
void reset()
void nextFrame()
{
perFrameAlloc.nextFrame();
perPolyAlloc.nextFrame();
perFrameDescSet = vk::DescriptorSet{};
perPolyDescSets.clear();
}
void term()
@ -153,6 +170,7 @@ private:
DynamicDescSetAlloc perFrameAlloc;
DynamicDescSetAlloc perPolyAlloc;
vk::DescriptorSet perFrameDescSet = {};
std::unordered_map<const void *, vk::DescriptorSet> perPolyDescSets;
SamplerManager* samplerManager = nullptr;
};