dmap now contains path tracing optimizations stored in iceproc files.

This commit is contained in:
Justin Marshall
2026-05-26 12:14:39 -07:00
parent 754f5b4aa0
commit 41cbd5669b
50 changed files with 350449 additions and 624741 deletions
+214 -9
View File
@@ -43,6 +43,7 @@ If you have questions concerning this license or the applicable additional terms
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <math.h>
#pragma comment(lib, "dxcompiler.lib")
#pragma comment(lib, "d3dcompiler.lib")
@@ -2211,6 +2212,16 @@ void glRaytracingSetMeshAverageColor(glRaytracingMeshHandle_t meshHandle, float
glRaytracingLightingResetDenoiseHistory();
}
void glRaytracingSetMeshProcMetadata(glRaytracingMeshHandle_t meshHandle, uint32_t procFlags, float emissiveR, float emissiveG, float emissiveB, float emissivePower)
{
(void)meshHandle;
(void)procFlags;
(void)emissiveR;
(void)emissiveG;
(void)emissiveB;
(void)emissivePower;
}
void glRaytracingDeleteMesh(glRaytracingMeshHandle_t meshHandle)
{
std::lock_guard<std::mutex> lock(g_glRaytracingMutex);
@@ -2461,7 +2472,6 @@ struct glRaytracingLightingConstants_t
float denoisePhiNormal;
float denoisePhiPosition;
float bumpStrength;
};
struct glRaytracingMeshMetadata_t
@@ -2530,6 +2540,10 @@ struct glRaytracingLightingState_t
DXGI_FORMAT iesFormats[GL_RAYTRACING_MAX_IES_TEXTURES];
bool uploadToCurrentFrameResource;
bool initialized;
glRaytracingSceneHandle_t lastProfileSceneHandle;
uint32_t lastProfileInstanceCount;
uint32_t lastProfileWidth;
uint32_t lastProfileHeight;
glRaytracingLightingState_t()
{
@@ -2567,6 +2581,10 @@ struct glRaytracingLightingState_t
}
uploadToCurrentFrameResource = false;
initialized = false;
lastProfileSceneHandle = 0;
lastProfileInstanceCount = 0;
lastProfileWidth = 0;
lastProfileHeight = 0;
}
};
@@ -4787,6 +4805,29 @@ float3 EstimateFastBounceLight(float3 hitPos, float3 hitN, Light Lgt)
return 0.0;
}
uint GetSecondaryBounceFastLightBudget()
{
if (gLightCount > 16u)
return 8u;
if (gLightCount > 10u)
return 7u;
if (gLightCount > 6u)
return 6u;
return gLightCount;
}
float GetSecondaryBounceFastLightScale(uint fastBudget)
{
if (fastBudget == 0u || fastBudget >= gLightCount)
return 1.0;
// The uploaded light list is CPU-sorted by broad importance. Use a small
// energy compensation for skipped low-importance lights without pretending
// the top few lights represent the entire room perfectly.
float fullScale = (float)gLightCount / (float)fastBudget;
return lerp(1.0, fullScale, 0.18);
}
float3 EstimateUnresolvedBounceRadiance(float3 hitPos, float3 hitN, float3 albedo)
{
hitN = SafeNormalizeOr(hitN, float3(0.0, 0.0, 1.0));
@@ -4796,11 +4837,14 @@ float3 EstimateUnresolvedBounceRadiance(float3 hitPos, float3 hitN, float3 albed
float3 lighting = gAmbientColor.rgb * (gAmbientColor.a * 0.025);
lighting += GetSkyRadiance(hitN) * (0.035 + 0.035 * upness);
float3 fastAllLights = 0.0;
uint fastBudget = GetSecondaryBounceFastLightBudget();
[loop]
for (uint i = 0; i < gLightCount; ++i)
for (uint i = 0; i < fastBudget; ++i)
{
lighting += EstimateFastBounceLight(hitPos, hitN, gLights[i]) * 0.35;
fastAllLights += EstimateFastBounceLight(hitPos, hitN, gLights[i]);
}
lighting += fastAllLights * (0.35 * GetSecondaryBounceFastLightScale(fastBudget));
return clamp(albedo * max(lighting, 0.0), 0.0, 6.0);
}
@@ -4885,16 +4929,18 @@ float3 EstimateDirectLightingForBounceHit(uint2 hitPixel, float3 hitPos, float3
// direct visible/bloom-only effect until real material-space emissive lighting
// is implemented.
// Baseline: every light contributes to bounced radiance, so small dynamic
// lights do not vanish just because they were not chosen by the stochastic
// next-event-estimation budget.
// Baseline: secondary GI uses a capped important-light set. Primary direct
// lighting still evaluates every light, but bounce hits were multiplying the
// full light list by every stochastic path depth.
float3 fastAllLights = 0.0;
uint fastBudget = GetSecondaryBounceFastLightBudget();
[loop]
for (uint i = 0; i < gLightCount; ++i)
for (uint i = 0; i < fastBudget; ++i)
{
fastAllLights += EstimateFastBounceLight(hitPos, hitN, gLights[i]);
}
lighting += fastAllLights;
float fastLightScale = GetSecondaryBounceFastLightScale(fastBudget);
lighting += fastAllLights * fastLightScale;
// Visibility correction: replace a small stable subset of the unshadowed
// baseline with real shadowed direct lighting. Keying this to the hit
@@ -4919,7 +4965,9 @@ float3 EstimateDirectLightingForBounceHit(uint2 hitPixel, float3 hitPos, float3
{
uint lightIndex = (start + c * stride) % gLightCount;
Light Lgt = gLights[lightIndex];
float3 fast = EstimateFastBounceLight(hitPos, hitN, Lgt);
float3 fast = (lightIndex < fastBudget)
? EstimateFastBounceLight(hitPos, hitN, Lgt) * fastLightScale
: 0.0;
float3 shadowed = EstimateShadowedBounceLight(hitPixel, hitPos, hitN, hitV, hitAlbedo, hitIsSkeletal, Lgt, lightingRng);
lighting += shadowed - fast;
}
@@ -6584,6 +6632,38 @@ static void glRaytracingLightingUpdateConstants(void)
g_glRaytracingLighting.constants);
}
static float glRaytracingLightingEstimateLightImportance(const glRaytracingLight_t& light)
{
float colorPeak = light.color.x;
if (light.color.y > colorPeak) colorPeak = light.color.y;
if (light.color.z > colorPeak) colorPeak = light.color.z;
float radius = light.radius;
if (light.type == GL_RAYTRACING_LIGHT_TYPE_POINT)
{
radius = light.pointRadius.x;
if (light.pointRadius.y > radius) radius = light.pointRadius.y;
if (light.pointRadius.z > radius) radius = light.pointRadius.z;
}
else if (light.type == GL_RAYTRACING_LIGHT_TYPE_RECT)
{
radius = (light.halfWidth > light.halfHeight) ? light.halfWidth : light.halfHeight;
radius *= 6.0f;
}
if (radius < 1.0f)
radius = 1.0f;
float importance = colorPeak * light.intensity * sqrtf(radius);
if (light.samples != 0u)
importance *= 1.15f;
if (light.volumetricScattering > 0.0f)
importance *= 1.10f;
if (light.iesStrength > 0.0f)
importance *= 1.05f;
return importance;
}
static void glRaytracingLightingUpdateLights(void)
{
if (!g_glRaytracingLighting.uploadToCurrentFrameResource)
@@ -6597,6 +6677,11 @@ static void glRaytracingLightingUpdateLights(void)
std::vector<glRaytracingLight_t>& uploadLights = g_glRaytracingLighting.uploadLights;
uploadLights = g_glRaytracingLighting.cpuLights;
std::sort(uploadLights.begin(), uploadLights.end(),
[](const glRaytracingLight_t& a, const glRaytracingLight_t& b)
{
return glRaytracingLightingEstimateLightImportance(a) > glRaytracingLightingEstimateLightImportance(b);
});
for (size_t i = 0; i < uploadLights.size(); ++i)
{
@@ -7840,6 +7925,12 @@ void glRaytracingLightingSetPathTracingOptions(uint32_t samplesPerPixel, uint32_
glRaytracingLightingUpdateConstants();
}
void glRaytracingLightingSetSecondaryLightBudget(int budget, float compensation)
{
(void)budget;
(void)compensation;
}
void glRaytracingLightingSetDenoiseTuning(float phiColor, float phiNormal, float phiPosition)
{
std::lock_guard<std::mutex> lock(g_glRaytracingMutex);
@@ -7925,6 +8016,12 @@ bool glRaytracingLightingExecuteForScene(const glRaytracingLightingPassDesc_t* p
if (!topLevelAS)
return false;
const glRaytracingRenderWorld_t* world = glRaytracingFindWorldConst(worldHandle);
g_glRaytracingLighting.lastProfileSceneHandle = worldHandle;
g_glRaytracingLighting.lastProfileInstanceCount = glRaytracingCountAliveInstances(world);
g_glRaytracingLighting.lastProfileWidth = pass ? pass->width : 0;
g_glRaytracingLighting.lastProfileHeight = pass ? pass->height : 0;
return glRaytracingLightingExecuteInternal(pass, topLevelAS);
}
@@ -8169,6 +8266,114 @@ uint32_t glRaytracingLightingGetLightCount(void)
return (uint32_t)g_glRaytracingLighting.cpuLights.size();
}
bool glRaytracingLightingGetProfileCounters(glRaytracingProfileCounters_t* counters)
{
if (!counters)
return false;
std::lock_guard<std::mutex> lock(g_glRaytracingMutex);
memset(counters, 0, sizeof(*counters));
const glRaytracingLightingConstants_t& constants = g_glRaytracingLighting.constants;
const uint32_t lightCount = (uint32_t)g_glRaytracingLighting.cpuLights.size();
const uint32_t samplesPerPixel = constants.samplesPerPixel ? constants.samplesPerPixel : 1u;
const uint32_t maxBounces = constants.maxBounces ? constants.maxBounces : 1u;
uint32_t directLightSamples = 0;
uint32_t directShadowRays = 0;
uint32_t volumetricShadowRays = 0;
for (size_t i = 0; i < g_glRaytracingLighting.cpuLights.size(); ++i)
{
const glRaytracingLight_t& light = g_glRaytracingLighting.cpuLights[i];
const uint32_t sampleCount = glRaytracingClamp<uint32_t>(light.samples ? light.samples : 1u, 1u, 4u);
if (light.type == GL_RAYTRACING_LIGHT_TYPE_POINT)
++counters->pointLightCount;
else if (light.type == GL_RAYTRACING_LIGHT_TYPE_SPOT)
++counters->spotLightCount;
else if (light.type == GL_RAYTRACING_LIGHT_TYPE_RECT)
++counters->rectLightCount;
directLightSamples += sampleCount;
if (light.samples != 0u)
{
++counters->shadowCastingLightCount;
directShadowRays += sampleCount;
}
if (light.volumetricScattering > 0.0f &&
(light.type == GL_RAYTRACING_LIGHT_TYPE_POINT || light.type == GL_RAYTRACING_LIGHT_TYPE_SPOT))
{
++counters->volumetricLightCount;
volumetricShadowRays += glRaytracingClamp<uint32_t>(light.samples ? light.samples : 3u, 3u, 6u);
}
}
uint32_t meshCount = 0;
for (size_t i = 0; i < g_glRaytracingScene.meshes.size(); ++i)
{
if (g_glRaytracingScene.meshes[i].alive)
++meshCount;
}
uint32_t indirectDepth = 0;
if (maxBounces > 1u)
{
indirectDepth = glRaytracingClamp<uint32_t>(maxBounces - 1u, 0u, 3u);
if (samplesPerPixel <= 1u)
indirectDepth = glRaytracingClamp<uint32_t>(indirectDepth, 0u, 2u);
}
uint32_t correctionBudget = 0;
if (lightCount > 0u)
{
correctionBudget = (lightCount <= 3u) ? lightCount : 2u;
if (samplesPerPixel >= 4u)
correctionBudget = glRaytracingClamp<uint32_t>(correctionBudget + 1u, 0u, lightCount);
}
uint32_t fastBounceLightBudget = lightCount;
if (lightCount > 16u)
fastBounceLightBudget = 8u;
else if (lightCount > 10u)
fastBounceLightBudget = 7u;
else if (lightCount > 6u)
fastBounceLightBudget = 6u;
uint32_t gatherSamples = 0;
if (maxBounces > 1u)
{
gatherSamples = 3u;
if (lightCount > 4u)
gatherSamples = 2u;
if (lightCount > 10u)
gatherSamples = 1u;
if (samplesPerPixel >= 4u)
gatherSamples = glRaytracingClamp<uint32_t>(gatherSamples, 0u, 2u);
if (samplesPerPixel >= 6u)
gatherSamples = glRaytracingClamp<uint32_t>(gatherSamples, 0u, 1u);
}
counters->frameCounter = g_glRaytracingLighting.frameCounter;
counters->width = g_glRaytracingLighting.lastProfileWidth;
counters->height = g_glRaytracingLighting.lastProfileHeight;
counters->lightCount = lightCount;
counters->samplesPerPixel = samplesPerPixel;
counters->maxBounces = maxBounces;
counters->enableSpecular = constants.enableSpecular;
counters->enableDenoiser = constants.enableDenoiser;
counters->meshCount = meshCount;
counters->instanceCount = g_glRaytracingLighting.lastProfileInstanceCount;
counters->directLightSamplesPerPixel = directLightSamples;
counters->directShadowRaysPerPixel = directShadowRays;
counters->indirectBounceRaysPerPixel = samplesPerPixel * indirectDepth;
counters->indirectLightEvalsPerPixel = samplesPerPixel * indirectDepth * (fastBounceLightBudget + correctionBudget);
counters->finalGatherRaysPerPixel = gatherSamples;
counters->reflectionRaysPerPixel = (constants.enableSpecular != 0u && maxBounces > 1u) ? 1u : 0u;
counters->volumetricShadowRaysPerPixel = volumetricShadowRays;
counters->gpuMsec = com_pathTracingGpuMsec;
return true;
}
int glRaytracingSetInstanceVisibilityUnlocked(
glRaytracingRenderWorld_t* world,
glRaytracingInstanceHandle_t instanceHandle,