Numerous performance fixes.

This commit is contained in:
Justin Marshall
2026-05-21 15:36:02 -07:00
parent 2e4265f5a1
commit a89d43628c
29 changed files with 1632 additions and 636 deletions
+147
View File
@@ -49,6 +49,8 @@ If you have questions concerning this license or the applicable additional terms
using Microsoft::WRL::ComPtr;
extern float com_pathTracingGpuMsec;
// ============================================================
// Logging / checks
// ============================================================
@@ -407,6 +409,10 @@ struct glRaytracingCmdContext_t
ComPtr<ID3D12Fence> fence;
HANDLE fenceEvent;
UINT64 nextFenceValue;
ComPtr<ID3D12QueryHeap> pathTracingTimestampHeap;
glRaytracingBuffer_t pathTracingTimestampReadback;
UINT64 pathTracingTimestampFrequency;
UINT64 pathTracingTimestampFenceRing[GL_RAYTRACING_CMD_RING_SIZE];
bool initialized;
glRaytracingCmdContext_t()
@@ -425,9 +431,11 @@ struct glRaytracingCmdContext_t
cmdFenceValueRing[i] = 0;
blasFenceValueRing[i] = 0;
tlasFenceValueRing[i] = 0;
pathTracingTimestampFenceRing[i] = 0;
}
fenceEvent = nullptr;
nextFenceValue = 0;
pathTracingTimestampFrequency = 0;
initialized = false;
}
};
@@ -463,6 +471,66 @@ static void glRaytracingWaitIdle(void)
glRaytracingWaitFenceValue(value);
}
static void glRaytracingPollPathTracingTimestamp(UINT slot)
{
if (!g_glRaytracingCmd.pathTracingTimestampReadback.resource ||
!g_glRaytracingCmd.pathTracingTimestampFrequency ||
slot >= GL_RAYTRACING_CMD_RING_SIZE)
{
return;
}
const UINT64 fenceValue = g_glRaytracingCmd.pathTracingTimestampFenceRing[slot];
if (!fenceValue || !g_glRaytracingCmd.fence || g_glRaytracingCmd.fence->GetCompletedValue() < fenceValue)
return;
const UINT64 offset = sizeof(UINT64) * 2ull * slot;
D3D12_RANGE readRange = { offset, offset + sizeof(UINT64) * 2ull };
UINT64* timestamps = nullptr;
if (SUCCEEDED(g_glRaytracingCmd.pathTracingTimestampReadback.resource->Map(0, &readRange, reinterpret_cast<void**>(&timestamps))) && timestamps != nullptr)
{
const UINT64 begin = timestamps[slot * 2 + 0];
const UINT64 end = timestamps[slot * 2 + 1];
if (end >= begin)
{
com_pathTracingGpuMsec = (float)((double)(end - begin) * 1000.0 / (double)g_glRaytracingCmd.pathTracingTimestampFrequency);
}
D3D12_RANGE writeRange = { 0, 0 };
g_glRaytracingCmd.pathTracingTimestampReadback.resource->Unmap(0, &writeRange);
}
g_glRaytracingCmd.pathTracingTimestampFenceRing[slot] = 0;
}
static int glRaytracingCreatePathTracingTimestamps(void)
{
D3D12_QUERY_HEAP_DESC qh = {};
qh.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP;
qh.Count = GL_RAYTRACING_CMD_RING_SIZE * 2;
if (FAILED(g_glRaytracingCmd.device->CreateQueryHeap(&qh, IID_PPV_ARGS(&g_glRaytracingCmd.pathTracingTimestampHeap))))
return 0;
g_glRaytracingCmd.pathTracingTimestampReadback = glRaytracingCreateBuffer(
g_glRaytracingCmd.device.Get(),
sizeof(UINT64) * GL_RAYTRACING_CMD_RING_SIZE * 2ull,
D3D12_HEAP_TYPE_READBACK,
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_FLAG_NONE);
if (!g_glRaytracingCmd.pathTracingTimestampReadback.resource)
return 0;
g_glRaytracingCmd.pathTracingTimestampFrequency = 0;
if (FAILED(g_glRaytracingCmd.queue->GetTimestampFrequency(&g_glRaytracingCmd.pathTracingTimestampFrequency)) ||
g_glRaytracingCmd.pathTracingTimestampFrequency == 0)
{
g_glRaytracingCmd.pathTracingTimestampHeap.Reset();
g_glRaytracingCmd.pathTracingTimestampReadback = glRaytracingBuffer_t();
return 0;
}
return 1;
}
static int glRaytracingCreateDirectCommandListPair(
ID3D12Device5* device,
ComPtr<ID3D12CommandAllocator>& allocator,
@@ -562,6 +630,11 @@ static int glRaytracingInitCmdContext(void)
return 0;
}
if (!glRaytracingCreatePathTracingTimestamps())
{
glRaytracingLog("path tracing timestamp queries unavailable");
}
g_glRaytracingCmd.initialized = true;
return 1;
}
@@ -586,6 +659,7 @@ static int glRaytracingBeginCmd(void)
{
const UINT slot = (g_glRaytracingCmd.cmdRingIndex + 1u) % GL_RAYTRACING_CMD_RING_SIZE;
glRaytracingWaitFenceValue(g_glRaytracingCmd.cmdFenceValueRing[slot]);
glRaytracingPollPathTracingTimestamp(slot);
g_glRaytracingCmd.cmdRingIndex = slot;
g_glRaytracingCmd.cmdCurrentSlot = slot;
@@ -1965,12 +2039,52 @@ int glRaytracingUpdateMesh(glRaytracingMeshHandle_t meshHandle, const glRaytraci
if (!desc->vertices || !desc->indices || desc->vertexCount == 0 || desc->indexCount == 0)
return 0;
const UINT64 vbBytes = UINT64(desc->vertexCount) * sizeof(glRaytracingVertex_t);
const UINT64 ibBytes = UINT64(desc->indexCount) * sizeof(uint32_t);
const bool sameVertexData =
mesh->verticesCpu.size() == desc->vertexCount &&
memcmp(mesh->verticesCpu.data(), desc->vertices, (size_t)vbBytes) == 0;
const bool sameIndexData =
mesh->indicesCpu.size() == desc->indexCount &&
memcmp(mesh->indicesCpu.data(), desc->indices, (size_t)ibBytes) == 0;
const bool sameDesc =
mesh->descCpu.vertexCount == desc->vertexCount &&
mesh->descCpu.indexCount == desc->indexCount &&
mesh->descCpu.allowUpdate == desc->allowUpdate &&
mesh->descCpu.opaque == desc->opaque;
if (sameDesc && sameVertexData && sameIndexData)
return 1;
const bool canUpdateExistingBuffers =
desc->allowUpdate != 0 &&
mesh->descCpu.allowUpdate != 0 &&
mesh->descCpu.opaque == desc->opaque &&
mesh->blasBuilt != 0 &&
mesh->vertexBuffer.resource &&
mesh->indexBuffer.resource &&
mesh->vertexBuffer.size >= vbBytes &&
mesh->indexBuffer.size >= ibBytes &&
mesh->verticesCpu.size() == desc->vertexCount &&
mesh->indicesCpu.size() == desc->indexCount;
mesh->descCpu = *desc;
mesh->verticesCpu.assign(desc->vertices, desc->vertices + desc->vertexCount);
mesh->indicesCpu.assign(desc->indices, desc->indices + desc->indexCount);
mesh->descCpu.vertices = nullptr;
mesh->descCpu.indices = nullptr;
if (canUpdateExistingBuffers)
{
glRaytracingMapCopy(mesh->vertexBuffer.resource.Get(), mesh->verticesCpu.data(), (size_t)vbBytes);
if (!sameIndexData)
glRaytracingMapCopy(mesh->indexBuffer.resource.Get(), mesh->indicesCpu.data(), (size_t)ibBytes);
mesh->dirty = 1;
glRaytracingInvalidateInstancesForMesh(meshHandle, 0);
return 1;
}
// Updating a mesh destroys/replaces resources that an already submitted frame
// may still reference. Wait only for this destructive path; steady-state
// rendering remains asynchronous.
@@ -2132,6 +2246,9 @@ int glRaytracingUpdateInstanceInScene(glRaytracingSceneHandle_t worldHandle, glR
? 0u
: glRaytracingNormalizeVisibleInstanceMask(newDesc.mask);
if (memcmp(&inst->descCpu, &newDesc, sizeof(newDesc)) == 0)
return 1;
inst->descCpu = newDesc;
inst->dirty = 1;
@@ -6440,6 +6557,18 @@ static bool glRaytracingLightingExecuteInternal(
g_glRaytracingCmd.cmdList->SetComputeRootConstantBufferView(2, g_glRaytracingLighting.constantBuffer.gpuVA);
g_glRaytracingCmd.cmdList->SetPipelineState1(g_glRaytracingLighting.rtStateObject.Get());
const UINT timestampBase = g_glRaytracingCmd.cmdCurrentSlot * 2u;
const bool writeTimestamp =
g_glRaytracingCmd.pathTracingTimestampHeap.Get() != nullptr &&
g_glRaytracingCmd.pathTracingTimestampReadback.resource.Get() != nullptr;
if (writeTimestamp)
{
g_glRaytracingCmd.cmdList->EndQuery(
g_glRaytracingCmd.pathTracingTimestampHeap.Get(),
D3D12_QUERY_TYPE_TIMESTAMP,
timestampBase + 0u);
}
const UINT shaderRecordSize = (UINT)glRaytracingAlignUp(
D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES,
D3D12_RAYTRACING_SHADER_RECORD_BYTE_ALIGNMENT);
@@ -6586,9 +6715,27 @@ static bool glRaytracingLightingExecuteInternal(
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
if (writeTimestamp)
{
g_glRaytracingCmd.cmdList->EndQuery(
g_glRaytracingCmd.pathTracingTimestampHeap.Get(),
D3D12_QUERY_TYPE_TIMESTAMP,
timestampBase + 1u);
g_glRaytracingCmd.cmdList->ResolveQueryData(
g_glRaytracingCmd.pathTracingTimestampHeap.Get(),
D3D12_QUERY_TYPE_TIMESTAMP,
timestampBase,
2,
g_glRaytracingCmd.pathTracingTimestampReadback.resource.Get(),
sizeof(UINT64) * timestampBase);
}
if (!glRaytracingEndCmd())
return false;
if (writeTimestamp)
g_glRaytracingCmd.pathTracingTimestampFenceRing[g_glRaytracingCmd.cmdCurrentSlot] = g_glRaytracingCmd.cmdLastFenceValue;
if (useInternalDenoiser)
g_glRaytracingLighting.currentHistoryIndex = historyWriteIndex;