mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-03-13 22:42:07 +00:00
Use a uniform buffer for the light list
This commit is contained in:
parent
bc2105eab9
commit
795c0d90de
9 changed files with 46 additions and 45 deletions
|
@ -36,23 +36,6 @@ struct FDynLightData
|
|||
arrays[2].Clear();
|
||||
}
|
||||
|
||||
void Combine(int *siz, int max)
|
||||
{
|
||||
siz[0] = arrays[0].Size();
|
||||
siz[1] = siz[0] + arrays[1].Size();
|
||||
siz[2] = siz[1] + arrays[2].Size();
|
||||
arrays[0].Resize(arrays[0].Size() + arrays[1].Size() + arrays[2].Size());
|
||||
memcpy(&arrays[0][siz[0]], &arrays[1][0], arrays[1].Size() * sizeof(float));
|
||||
memcpy(&arrays[0][siz[1]], &arrays[2][0], arrays[2].Size() * sizeof(float));
|
||||
siz[0]>>=2;
|
||||
siz[1]>>=2;
|
||||
siz[2]>>=2;
|
||||
if (siz[0] > max) siz[0] = max;
|
||||
if (siz[1] > max) siz[1] = max;
|
||||
if (siz[2] > max) siz[2] = max;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
extern thread_local FDynLightData lightdata;
|
||||
|
|
|
@ -54,16 +54,16 @@ void VkBufferManager::Init()
|
|||
|
||||
Viewpoint.Data = Viewpoint.UBO->Map(0, Viewpoint.UBO->size);
|
||||
|
||||
Lightbuffer.SSO = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT)
|
||||
Lightbuffer.UBO = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT)
|
||||
.MemoryType(
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||
.Size(Lightbuffer.Count * 4 * sizeof(FVector4))
|
||||
.DebugName("Lightbuffer.SSO")
|
||||
.DebugName("Lightbuffer.UBO")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
Lightbuffer.Data = Lightbuffer.SSO->Map(0, Lightbuffer.SSO->size);
|
||||
Lightbuffer.Data = Lightbuffer.UBO->Map(0, Lightbuffer.UBO->size);
|
||||
|
||||
Bonebuffer.SSO = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VMA_MEMORY_USAGE_UNKNOWN, VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT)
|
||||
|
@ -89,9 +89,9 @@ void VkBufferManager::Deinit()
|
|||
Viewpoint.UBO->Unmap();
|
||||
Viewpoint.UBO.reset();
|
||||
|
||||
if (Lightbuffer.SSO)
|
||||
Lightbuffer.SSO->Unmap();
|
||||
Lightbuffer.SSO.reset();
|
||||
if (Lightbuffer.UBO)
|
||||
Lightbuffer.UBO->Unmap();
|
||||
Lightbuffer.UBO.reset();
|
||||
|
||||
if (Bonebuffer.SSO)
|
||||
Bonebuffer.SSO->Unmap();
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
{
|
||||
int UploadIndex = 0;
|
||||
int Count = 80000;
|
||||
std::unique_ptr<VulkanBuffer> SSO;
|
||||
std::unique_ptr<VulkanBuffer> UBO;
|
||||
void* Data = nullptr;
|
||||
} Lightbuffer;
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ void VkDescriptorSetManager::UpdateHWBufferSet()
|
|||
.AddBuffer(HWBufferSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->Viewpoint.UBO.get(), 0, sizeof(HWViewpointUniforms))
|
||||
.AddBuffer(HWBufferSet.get(), 1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->MatrixBuffer->UBO.get(), 0, sizeof(MatricesUBO))
|
||||
.AddBuffer(HWBufferSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->StreamBuffer->UBO.get(), 0, sizeof(StreamUBO))
|
||||
.AddBuffer(HWBufferSet.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->Lightbuffer.SSO.get())
|
||||
.AddBuffer(HWBufferSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->GetBufferManager()->Lightbuffer.UBO.get(), 0, sizeof(LightBufferUBO))
|
||||
.AddBuffer(HWBufferSet.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBufferManager()->Bonebuffer.SSO.get())
|
||||
.Execute(fb->GetDevice());
|
||||
}
|
||||
|
@ -260,7 +260,7 @@ void VkDescriptorSetManager::CreateHWBufferSetLayout()
|
|||
.AddBinding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(1, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
|
||||
.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT)
|
||||
.DebugName("VkDescriptorSetManager.HWBufferSetLayout")
|
||||
.Create(fb->GetDevice());
|
||||
|
@ -288,8 +288,8 @@ void VkDescriptorSetManager::CreateFixedSetLayout()
|
|||
void VkDescriptorSetManager::CreateHWBufferPool()
|
||||
{
|
||||
HWBufferDescriptorPool = DescriptorPoolBuilder()
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 3 * maxSets)
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2 * maxSets)
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 4 * maxSets)
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1 * maxSets)
|
||||
.MaxSets(maxSets)
|
||||
.DebugName("VkDescriptorSetManager.HWBufferDescriptorPool")
|
||||
.Create(fb->GetDevice());
|
||||
|
|
|
@ -131,8 +131,9 @@ VkShaderProgram* VkShaderManager::Get(const VkShaderKey& key)
|
|||
std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername, const char *vert_lump, const char *defines)
|
||||
{
|
||||
FString definesBlock;
|
||||
definesBlock << defines << "\n";
|
||||
definesBlock << "#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n";
|
||||
definesBlock << defines;
|
||||
definesBlock << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n";
|
||||
definesBlock << "#define MAX_LIGHT_DATA " << std::to_string(MAX_LIGHT_DATA).c_str() << "\n";
|
||||
#ifdef NPOT_EMULATION
|
||||
definesBlock << "#define NPOT_EMULATION\n";
|
||||
#endif
|
||||
|
@ -166,6 +167,7 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
|
|||
if (fb->GetDevice()->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME)) definesBlock << "\n#define SUPPORTS_RAYQUERY\n";
|
||||
definesBlock << defines;
|
||||
definesBlock << "\n#define MAX_STREAM_DATA " << std::to_string(MAX_STREAM_DATA).c_str() << "\n";
|
||||
definesBlock << "#define MAX_LIGHT_DATA " << std::to_string(MAX_LIGHT_DATA).c_str() << "\n";
|
||||
#ifdef NPOT_EMULATION
|
||||
definesBlock << "#define NPOT_EMULATION\n";
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,13 @@ struct StreamUBO
|
|||
StreamData data[MAX_STREAM_DATA];
|
||||
};
|
||||
|
||||
#define MAX_LIGHT_DATA ((int)(65536 / sizeof(FVector4)))
|
||||
|
||||
struct LightBufferUBO
|
||||
{
|
||||
FVector4 lights[MAX_LIGHT_DATA];
|
||||
};
|
||||
|
||||
struct PushConstants
|
||||
{
|
||||
int uDataIndex; // streamdata index
|
||||
|
|
|
@ -406,7 +406,7 @@ void VkRenderState::ApplyStreamData()
|
|||
void VkRenderState::ApplyPushConstants()
|
||||
{
|
||||
mPushConstants.uDataIndex = mStreamBufferWriter.DataIndex();
|
||||
mPushConstants.uLightIndex = mLightIndex;
|
||||
mPushConstants.uLightIndex = mLightIndex >= 0 ? (mLightIndex % MAX_LIGHT_DATA) : -1;
|
||||
mPushConstants.uBoneIndexBase = mBoneIndexBase;
|
||||
|
||||
auto passManager = fb->GetRenderPassManager();
|
||||
|
@ -468,18 +468,20 @@ void VkRenderState::ApplyHWBufferSet()
|
|||
{
|
||||
uint32_t matrixOffset = mMatrixBufferWriter.Offset();
|
||||
uint32_t streamDataOffset = mStreamBufferWriter.StreamDataOffset();
|
||||
if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || streamDataOffset != mLastStreamDataOffset)
|
||||
uint32_t lightsOffset = mLightIndex >= 0 ? (uint32_t)(mLightIndex / MAX_LIGHT_DATA) * sizeof(FVector4) : mLastLightsOffset;
|
||||
if (mViewpointOffset != mLastViewpointOffset || matrixOffset != mLastMatricesOffset || streamDataOffset != mLastStreamDataOffset || lightsOffset != mLastLightsOffset)
|
||||
{
|
||||
auto passManager = fb->GetRenderPassManager();
|
||||
auto descriptors = fb->GetDescriptorSetManager();
|
||||
|
||||
uint32_t offsets[3] = { mViewpointOffset, matrixOffset, streamDataOffset };
|
||||
uint32_t offsets[4] = { mViewpointOffset, matrixOffset, streamDataOffset, lightsOffset };
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, fb->GetDescriptorSetManager()->GetFixedDescriptorSet());
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptors->GetHWBufferDescriptorSet(), 3, offsets);
|
||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, descriptors->GetHWBufferDescriptorSet(), 4, offsets);
|
||||
|
||||
mLastViewpointOffset = mViewpointOffset;
|
||||
mLastMatricesOffset = matrixOffset;
|
||||
mLastStreamDataOffset = streamDataOffset;
|
||||
mLastLightsOffset = lightsOffset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -536,9 +538,10 @@ int VkRenderState::UploadLights(const FDynLightData& data)
|
|||
int size2 = data.arrays[2].Size() / 4;
|
||||
int totalsize = size0 + size1 + size2 + 1;
|
||||
|
||||
if (totalsize > buffers->Lightbuffer.Count)
|
||||
// Clamp lights so they aren't bigger than what fits into a single dynamic uniform buffer page
|
||||
if (totalsize > MAX_LIGHT_DATA)
|
||||
{
|
||||
int diff = totalsize - buffers->Lightbuffer.Count;
|
||||
int diff = totalsize - MAX_LIGHT_DATA;
|
||||
|
||||
size2 -= diff;
|
||||
if (size2 < 0)
|
||||
|
@ -554,17 +557,22 @@ int VkRenderState::UploadLights(const FDynLightData& data)
|
|||
totalsize = size0 + size1 + size2 + 1;
|
||||
}
|
||||
|
||||
if (totalsize <= 1) return -1; // there are no lights
|
||||
// Check if we still have any lights
|
||||
if (totalsize <= 1)
|
||||
return -1;
|
||||
|
||||
// Make sure the light list doesn't cross a page boundary
|
||||
if (buffers->Lightbuffer.UploadIndex % MAX_LIGHT_DATA + totalsize > MAX_LIGHT_DATA)
|
||||
buffers->Lightbuffer.UploadIndex = buffers->Lightbuffer.UploadIndex / MAX_LIGHT_DATA * MAX_LIGHT_DATA + 1;
|
||||
|
||||
int thisindex = buffers->Lightbuffer.UploadIndex;
|
||||
buffers->Lightbuffer.UploadIndex += totalsize;
|
||||
|
||||
float parmcnt[] = { 0, float(size0), float(size0 + size1), float(size0 + size1 + size2) };
|
||||
|
||||
if (thisindex + totalsize <= buffers->Lightbuffer.Count)
|
||||
{
|
||||
float* copyptr = (float*)buffers->Lightbuffer.Data + thisindex * 4;
|
||||
buffers->Lightbuffer.UploadIndex += totalsize;
|
||||
|
||||
float parmcnt[] = { 0, float(size0), float(size0 + size1), float(size0 + size1 + size2) };
|
||||
|
||||
float* copyptr = (float*)buffers->Lightbuffer.Data + thisindex * 4;
|
||||
memcpy(©ptr[0], parmcnt, sizeof(FVector4));
|
||||
memcpy(©ptr[4], &data.arrays[0][0], size0 * sizeof(FVector4));
|
||||
memcpy(©ptr[4 + 4 * size0], &data.arrays[1][0], size1 * sizeof(FVector4));
|
||||
|
|
|
@ -103,6 +103,7 @@ protected:
|
|||
uint32_t mLastViewpointOffset = 0xffffffff;
|
||||
uint32_t mLastMatricesOffset = 0xffffffff;
|
||||
uint32_t mLastStreamDataOffset = 0xffffffff;
|
||||
uint32_t mLastLightsOffset = 0;
|
||||
uint32_t mViewpointOffset = 0;
|
||||
|
||||
VkStreamBufferWriter mStreamBufferWriter;
|
||||
|
|
|
@ -108,9 +108,9 @@ layout(set = 1, binding = 2, std140) uniform StreamUBO
|
|||
};
|
||||
|
||||
// light buffers
|
||||
layout(set = 1, binding = 3, std430) buffer LightBufferSSO
|
||||
layout(set = 1, binding = 3, std140) uniform LightBufferUBO
|
||||
{
|
||||
vec4 lights[];
|
||||
vec4 lights[MAX_LIGHT_DATA];
|
||||
};
|
||||
|
||||
// bone matrix buffers
|
||||
|
|
Loading…
Reference in a new issue