Limit the number of lights per trace to 50

This commit is contained in:
Magnus Norddahl 2021-11-16 02:15:14 +01:00
parent 95232aedf4
commit 583f720007
5 changed files with 60 additions and 21 deletions

View file

@ -22,7 +22,7 @@ layout(set = 0, binding = 4) uniform Uniforms
uint SampleIndex;
uint SampleCount;
uint PassType;
uint LightCount;
uint Padding0;
vec3 SunDir;
float SampleDistance;
vec3 SunColor;
@ -43,6 +43,13 @@ struct SurfaceInfo
layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
layout(push_constant) uniform PushConstants
{
uint LightStart;
uint LightEnd;
ivec2 pushPadding;
};
vec3 ImportanceSample(vec3 N);
void main()

View file

@ -22,7 +22,7 @@ layout(set = 0, binding = 4) uniform Uniforms
uint SampleIndex;
uint SampleCount;
uint PassType;
uint LightCount;
uint Padding0;
vec3 SunDir;
float SampleDistance;
vec3 SunColor;
@ -58,6 +58,13 @@ struct LightInfo
layout(set = 0, binding = 6) buffer SurfaceBuffer { SurfaceInfo surfaces[]; };
layout(set = 0, binding = 7) buffer LightBuffer { LightInfo lights[]; };
layout(push_constant) uniform PushConstants
{
uint LightStart;
uint LightEnd;
ivec2 pushPadding;
};
vec2 Hammersley(uint i, uint N);
float RadicalInverse_VdC(uint bits);
@ -80,7 +87,7 @@ void main()
const float minDistance = 0.01;
// Sun light
if (LightStart == 0) // Sun light
{
const float dist = 32768.0;
@ -109,7 +116,7 @@ void main()
incoming.rgb += SunColor * (attenuation * SunIntensity * incoming.w);
}
for (uint j = 0; j < LightCount; j++)
for (uint j = LightStart; j < LightEnd; j++)
{
LightInfo light = lights[j];

View file

@ -99,7 +99,6 @@ void GPURaytracer::Raytrace(LevelMesh* level)
Uniforms uniforms = {};
uniforms.SampleDistance = (float)mesh->samples;
uniforms.LightCount = mesh->map->ThingLights.Size();
uniforms.SunDir = mesh->map->GetSunDirection();
uniforms.SunColor = mesh->map->GetSunColor();
uniforms.SunIntensity = 1.0f;
@ -110,7 +109,7 @@ void GPURaytracer::Raytrace(LevelMesh* level)
RunTrace(uniforms, rgenBounceRegion);
uniforms.SampleCount = coverageSampleCount;
RunTrace(uniforms, rgenLightRegion);
RunTrace(uniforms, rgenLightRegion, 0, mesh->map->ThingLights.Size());
for (uint32_t i = 0; i < (uint32_t)bounceSampleCount; i++)
{
@ -123,7 +122,7 @@ void GPURaytracer::Raytrace(LevelMesh* level)
for (int bounce = 0; bounce < mesh->map->LightBounce; bounce++)
{
uniforms.SampleCount = coverageSampleCount;
RunTrace(uniforms, rgenLightRegion);
RunTrace(uniforms, rgenLightRegion, 0, mesh->map->ThingLights.Size());
uniforms.PassType = 2;
uniforms.SampleIndex = (i + bounce) % uniforms.SampleCount;
@ -230,7 +229,7 @@ void GPURaytracer::BeginTracing()
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipeline.get());
}
void GPURaytracer::RunTrace(const Uniforms& uniforms, const VkStridedDeviceAddressRegionKHR& rgenShader)
void GPURaytracer::RunTrace(const Uniforms& uniforms, const VkStridedDeviceAddressRegionKHR& rgenShader, int lightStart, int lightEnd)
{
if (uniformsIndex == uniformStructs)
{
@ -240,25 +239,42 @@ void GPURaytracer::RunTrace(const Uniforms& uniforms, const VkStridedDeviceAddre
*reinterpret_cast<Uniforms*>(mappedUniforms + uniformStructStride * uniformsIndex) = uniforms;
uint32_t offset = (uint32_t)(uniformsIndex * uniformStructStride);
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0, descriptorSet.get(), 1, &offset);
bool needbarrier = true;
if (uniformsIndex == 0)
{
PipelineBarrier barrier;
barrier.addBuffer(uniformBuffer.get(), VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT);
barrier.addImage(positionsImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
barrier.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
needbarrier = false;
}
else
{
PipelineBarrier barrier;
barrier.addImage(positionsImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
barrier.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
}
uint32_t offset = (uint32_t)(uniformsIndex * uniformStructStride);
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, pipelineLayout.get(), 0, descriptorSet.get(), 1, &offset);
cmdbuffer->traceRays(&rgenShader, &missRegion, &hitRegion, &callRegion, rayTraceImageSize, rayTraceImageSize, 1);
uniformsIndex++;
const int maxLights = 50;
do
{
int count = std::min(lightEnd - lightStart, maxLights);
if (needbarrier)
{
PipelineBarrier barrier;
barrier.addImage(positionsImage.get(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT);
barrier.execute(cmdbuffer.get(), VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR, VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
}
PushConstants constants = {};
constants.LightStart = lightStart;
constants.LightEnd = lightStart + count;
cmdbuffer->pushConstants(pipelineLayout.get(), VK_SHADER_STAGE_RAYGEN_BIT_KHR, 0, (uint32_t)sizeof(PushConstants), &constants);
cmdbuffer->traceRays(&rgenShader, &missRegion, &hitRegion, &callRegion, rayTraceImageSize, rayTraceImageSize, 1);
needbarrier = true;
lightStart += count;
} while (lightStart < lightEnd);
}
void GPURaytracer::EndTracing()
@ -708,6 +724,7 @@ void GPURaytracer::CreatePipeline()
PipelineLayoutBuilder layoutbuilder;
layoutbuilder.addSetLayout(descriptorSetLayout.get());
layoutbuilder.addPushConstantRange(VK_SHADER_STAGE_RAYGEN_BIT_KHR, 0, sizeof(PushConstants));
pipelineLayout = layoutbuilder.create(device.get());
pipelineLayout->SetDebugName("pipelineLayout");

View file

@ -11,7 +11,7 @@ struct Uniforms
uint32_t SampleIndex;
uint32_t SampleCount;
uint32_t PassType;
uint32_t LightCount;
uint32_t Padding0;
vec3 SunDir;
float SampleDistance;
vec3 SunColor;
@ -20,6 +20,13 @@ struct Uniforms
float Padding1;
};
struct PushConstants
{
uint32_t LightStart;
uint32_t LightEnd;
ivec2 pushPadding;
};
struct SurfaceInfo
{
vec3 Normal;
@ -71,7 +78,7 @@ private:
void UploadTasks(const TraceTask* tasks, size_t size);
void BeginTracing();
void RunTrace(const Uniforms& uniforms, const VkStridedDeviceAddressRegionKHR& rgenShader);
void RunTrace(const Uniforms& uniforms, const VkStridedDeviceAddressRegionKHR& rgenShader, int lightStart = 0, int lightEnd = 0);
void EndTracing();
void DownloadTasks(const TraceTask* tasks, size_t size);
void SubmitCommands();

View file

@ -1,5 +1,6 @@
#include "lightmaptexture.h"
#include "framework/halffloat.h"
#include <algorithm>
LightmapTexture::LightmapTexture(int width, int height) : textureWidth(width), textureHeight(height)