diff --git a/src/lightmap/glsl_rgen_bounce.h b/src/lightmap/glsl_rgen_bounce.h index 8fe9063..97ae3ac 100644 --- a/src/lightmap/glsl_rgen_bounce.h +++ b/src/lightmap/glsl_rgen_bounce.h @@ -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() diff --git a/src/lightmap/glsl_rgen_light.h b/src/lightmap/glsl_rgen_light.h index 19cfd51..29a539b 100644 --- a/src/lightmap/glsl_rgen_light.h +++ b/src/lightmap/glsl_rgen_light.h @@ -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]; diff --git a/src/lightmap/gpuraytracer.cpp b/src/lightmap/gpuraytracer.cpp index 277228a..ad99fe7 100644 --- a/src/lightmap/gpuraytracer.cpp +++ b/src/lightmap/gpuraytracer.cpp @@ -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(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"); diff --git a/src/lightmap/gpuraytracer.h b/src/lightmap/gpuraytracer.h index 7d58c38..5b57036 100644 --- a/src/lightmap/gpuraytracer.h +++ b/src/lightmap/gpuraytracer.h @@ -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(); diff --git a/src/lightmap/lightmaptexture.cpp b/src/lightmap/lightmaptexture.cpp index 6c9111a..dc2e33c 100644 --- a/src/lightmap/lightmaptexture.cpp +++ b/src/lightmap/lightmaptexture.cpp @@ -1,5 +1,6 @@ #include "lightmaptexture.h" +#include "framework/halffloat.h" #include LightmapTexture::LightmapTexture(int width, int height) : textureWidth(width), textureHeight(height)