vulkan: cache per-poly desc sets in map
avoid desc set pool exhaustion in per-triangle
This commit is contained in:
parent
53b5588bda
commit
ad08590197
|
@ -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());
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -75,7 +75,7 @@ protected:
|
|||
|
||||
void NewImage()
|
||||
{
|
||||
descriptorSets.reset();
|
||||
descriptorSets.nextFrame();
|
||||
imageIndex = (imageIndex + 1) % GetContext()->GetSwapChainSize();
|
||||
renderPass = 0;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue