Skip to content

Commit 2384385

Browse files
committed
fixed light probe on-terrain placement on DX12:
- implemented a delayed GPU readback via ReadbackPlacedPositionsOnInitEvent in ER_LightProbesManager::PlaceProbesOnTerrain() - split PlaceOnTerrainData cbuffer into 2: PlaceOnTerrainGlobalData and PlaceOnTerrainPropData (used as root constant) - fixed a crash in ER_RHI::BeginEventTag()/EndEventTag() bumped version name in ER_Utility.h to 1.1
1 parent bc31339 commit 2384385

File tree

7 files changed

+128
-62
lines changed

7 files changed

+128
-62
lines changed

content/shaders/Terrain/PlaceObjectsOnTerrain.hlsl

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@
1919
cbuffer CBufferTerrain : register(b0)
2020
{
2121
float HeightScale;
22-
float SplatChannel;
2322
float TerrainTileCount;
24-
float PlacementHeightDelta;
23+
}
24+
25+
cbuffer CBufferTerrainProps : register(b1)
26+
{
27+
uint SplatChannel;
28+
uint PlacementHeightDelta;
2529
}
2630

2731
struct TerrainTileData
@@ -237,21 +241,21 @@ float FindHeightFromHeightmap(float x, float z, int tileIndex)
237241
return height * HeightScale;
238242
}
239243

240-
bool IsOnSplatMap(float x, float z, int tileIndex, float channel)
244+
bool IsOnSplatMap(float x, float z, int tileIndex, uint channel)
241245
{
242246
float2 uv = GetTextureCoordinates(x, z, tileIndex);
243247
uv.y = 1.0f - uv.y;
244248

245249
float percentage = 0.2f;
246250

247251
float4 value = TerrainTilesSplatTextures.SampleLevel(LinearSampler, float3(uv, tileIndex), 0);
248-
if (channel == 0.0f && value.r > percentage)
252+
if (channel == 0 && value.r > percentage)
249253
return true;
250-
else if (channel == 1.0f && value.g > percentage)
254+
else if (channel == 1u && value.g > percentage)
251255
return true;
252-
else if (channel == 2.0f && value.b > percentage)
256+
else if (channel == 2u && value.b > percentage)
253257
return true;
254-
else if (channel == 3.0f && value.a > percentage)
258+
else if (channel == 3u && value.a > percentage)
255259
return true;
256260
else
257261
return false;
@@ -275,11 +279,11 @@ void CSMain(uint3 threadID : SV_DispatchThreadID, uint groupIndex : SV_GroupInde
275279

276280
if (tileIndex >= 0)
277281
{
278-
if (SplatChannel == -1.0f || IsOnSplatMap(x, z, tileIndex, SplatChannel))
282+
if (SplatChannel == 255 || IsOnSplatMap(x, z, tileIndex, SplatChannel))
279283
#if USE_RAYCASTING
280284
InputOutputPositions[threadID.x].y = FindHeightFromPosition(vertexCount, x, z);
281285
#else
282-
InputOutputPositions[threadID.x].y = FindHeightFromHeightmap(x, z, tileIndex) - PlacementHeightDelta;
286+
InputOutputPositions[threadID.x].y = FindHeightFromHeightmap(x, z, tileIndex) - asfloat(PlacementHeightDelta);
283287
#endif
284288
else
285289
InputOutputPositions[threadID.x].y = -999.0f; //culled

source/EveryRay_Core/ER_LightProbesManager.cpp

Lines changed: 58 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -241,33 +241,25 @@ namespace EveryRay_Core
241241

242242
// all probes positions GPU buffer
243243
{
244-
XMFLOAT4* diffuseProbesPositionsCPUBuffer = new XMFLOAT4[mDiffuseProbesCountTotal];
244+
assert(!mDiffuseProbesPositionsTempCPUBuffer);
245+
246+
mDiffuseProbesPositionsTempCPUBuffer = new XMFLOAT4[mDiffuseProbesCountTotal];
245247
for (int probeIndex = 0; probeIndex < mDiffuseProbesCountTotal; probeIndex++)
246-
diffuseProbesPositionsCPUBuffer[probeIndex] = XMFLOAT4(mDiffuseProbes[probeIndex].GetPosition().x, mDiffuseProbes[probeIndex].GetPosition().y, mDiffuseProbes[probeIndex].GetPosition().z, 1.0);
248+
mDiffuseProbesPositionsTempCPUBuffer[probeIndex] = XMFLOAT4(mDiffuseProbes[probeIndex].GetPosition().x, mDiffuseProbes[probeIndex].GetPosition().y, mDiffuseProbes[probeIndex].GetPosition().z, 1.0);
247249

248250
mDiffuseProbesPositionsGPUBuffer = rhi->CreateGPUBuffer("ER_RHI_GPUBuffer: diffuse probes positions buffer");
249-
mDiffuseProbesPositionsGPUBuffer->CreateGPUBufferResource(rhi, diffuseProbesPositionsCPUBuffer, mDiffuseProbesCountTotal, sizeof(XMFLOAT4), mIsPlacedOnTerrain, ER_BIND_SHADER_RESOURCE, 0, ER_RESOURCE_MISC_BUFFER_STRUCTURED);
251+
mDiffuseProbesPositionsGPUBuffer->CreateGPUBufferResource(rhi, mDiffuseProbesPositionsTempCPUBuffer, mDiffuseProbesCountTotal, sizeof(XMFLOAT4), mIsPlacedOnTerrain, ER_BIND_SHADER_RESOURCE, 0, ER_RESOURCE_MISC_BUFFER_STRUCTURED);
250252

251253
if (mIsPlacedOnTerrain)
252254
{
253255
mDiffuseInputPositionsOnTerrainBuffer = rhi->CreateGPUBuffer("ER_RHI_GPUBuffer: On-terrain placement input positions buffer (diffuse probes)");
254-
mDiffuseInputPositionsOnTerrainBuffer->CreateGPUBufferResource(rhi, diffuseProbesPositionsCPUBuffer, mDiffuseProbesCountTotal, sizeof(XMFLOAT4), false , ER_BIND_UNORDERED_ACCESS, 0, ER_RESOURCE_MISC_BUFFER_STRUCTURED);
256+
mDiffuseInputPositionsOnTerrainBuffer->CreateGPUBufferResource(rhi, mDiffuseProbesPositionsTempCPUBuffer, mDiffuseProbesCountTotal, sizeof(XMFLOAT4), false , ER_BIND_UNORDERED_ACCESS, 0, ER_RESOURCE_MISC_BUFFER_STRUCTURED);
255257

256258
mDiffuseOutputPositionsOnTerrainBuffer = rhi->CreateGPUBuffer("ER_RHI_GPUBuffer: On-terrain placement output positions buffer (diffuse probes)");
257-
mDiffuseOutputPositionsOnTerrainBuffer->CreateGPUBufferResource(rhi, diffuseProbesPositionsCPUBuffer, mDiffuseProbesCountTotal, sizeof(XMFLOAT4), false, ER_BIND_NONE, 0x10000L | 0x20000L /*legacy from DX11*/, ER_RESOURCE_MISC_BUFFER_STRUCTURED); //should be STAGING
258-
259-
PlaceProbesOnTerrain(core, mDiffuseOutputPositionsOnTerrainBuffer, mDiffuseInputPositionsOnTerrainBuffer, diffuseProbesPositionsCPUBuffer, mDiffuseProbesCountTotal, mTerrainPlacementHeightDeltaDiffuseProbes);
260-
261-
rhi->UpdateBuffer(mDiffuseProbesPositionsGPUBuffer, (void*)diffuseProbesPositionsCPUBuffer, mDiffuseProbesCountTotal * sizeof(XMFLOAT4));
259+
mDiffuseOutputPositionsOnTerrainBuffer->CreateGPUBufferResource(rhi, mDiffuseProbesPositionsTempCPUBuffer, mDiffuseProbesCountTotal, sizeof(XMFLOAT4), false, ER_BIND_NONE, 0x10000L | 0x20000L /*legacy from DX11*/, ER_RESOURCE_MISC_BUFFER_STRUCTURED); //should be STAGING
262260

263-
for (int i = 0; i < mDiffuseProbesCountTotal; i++)
264-
mDiffuseProbes[i].SetPosition(XMFLOAT3(diffuseProbesPositionsCPUBuffer[i].x, diffuseProbesPositionsCPUBuffer[i].y, diffuseProbesPositionsCPUBuffer[i].z));
265-
266-
DeleteObject(mDiffuseInputPositionsOnTerrainBuffer);
267-
DeleteObject(mDiffuseOutputPositionsOnTerrainBuffer);
261+
PlaceProbesOnTerrain(core, DIFFUSE_PROBE, mDiffuseOutputPositionsOnTerrainBuffer, mDiffuseInputPositionsOnTerrainBuffer, mDiffuseProbesPositionsTempCPUBuffer, mDiffuseProbesCountTotal, mTerrainPlacementHeightDeltaDiffuseProbes);
268262
}
269-
270-
DeleteObjects(diffuseProbesPositionsCPUBuffer);
271263
}
272264

273265
// probe cell's indices GPU buffer, tex. array indices GPU/CPU buffers
@@ -396,33 +388,24 @@ namespace EveryRay_Core
396388

397389
// all probes positions GPU buffer
398390
{
399-
XMFLOAT4* specularProbesPositionsCPUBuffer = new XMFLOAT4[mSpecularProbesCountTotal];
391+
assert(!mSpecularProbesPositionsTempCPUBuffer);
392+
mSpecularProbesPositionsTempCPUBuffer = new XMFLOAT4[mSpecularProbesCountTotal];
400393

401394
for (int probeIndex = 0; probeIndex < mSpecularProbesCountTotal; probeIndex++)
402-
specularProbesPositionsCPUBuffer[probeIndex] = XMFLOAT4(mSpecularProbes[probeIndex].GetPosition().x,mSpecularProbes[probeIndex].GetPosition().y,mSpecularProbes[probeIndex].GetPosition().z, 1.0);
395+
mSpecularProbesPositionsTempCPUBuffer[probeIndex] = XMFLOAT4(mSpecularProbes[probeIndex].GetPosition().x,mSpecularProbes[probeIndex].GetPosition().y,mSpecularProbes[probeIndex].GetPosition().z, 1.0);
403396
mSpecularProbesPositionsGPUBuffer = rhi->CreateGPUBuffer("ER_RHI_GPUBuffer: specular probes positions buffer");
404-
mSpecularProbesPositionsGPUBuffer->CreateGPUBufferResource(rhi, specularProbesPositionsCPUBuffer, mSpecularProbesCountTotal, sizeof(XMFLOAT4), mIsPlacedOnTerrain, ER_BIND_SHADER_RESOURCE, 0, ER_RESOURCE_MISC_BUFFER_STRUCTURED);
397+
mSpecularProbesPositionsGPUBuffer->CreateGPUBufferResource(rhi, mSpecularProbesPositionsTempCPUBuffer, mSpecularProbesCountTotal, sizeof(XMFLOAT4), mIsPlacedOnTerrain, ER_BIND_SHADER_RESOURCE, 0, ER_RESOURCE_MISC_BUFFER_STRUCTURED);
405398

406399
if (mIsPlacedOnTerrain)
407400
{
408401
mSpecularInputPositionsOnTerrainBuffer = rhi->CreateGPUBuffer("ER_RHI_GPUBuffer: On-terrain placement input positions buffer (specular probes)");
409-
mSpecularInputPositionsOnTerrainBuffer->CreateGPUBufferResource(rhi, specularProbesPositionsCPUBuffer, mSpecularProbesCountTotal, sizeof(XMFLOAT4), false, ER_BIND_UNORDERED_ACCESS, 0, ER_RESOURCE_MISC_BUFFER_STRUCTURED);
402+
mSpecularInputPositionsOnTerrainBuffer->CreateGPUBufferResource(rhi, mSpecularProbesPositionsTempCPUBuffer, mSpecularProbesCountTotal, sizeof(XMFLOAT4), false, ER_BIND_UNORDERED_ACCESS, 0, ER_RESOURCE_MISC_BUFFER_STRUCTURED);
410403

411404
mSpecularOutputPositionsOnTerrainBuffer = rhi->CreateGPUBuffer("ER_RHI_GPUBuffer: On-terrain placement output positions buffer (specular probes)");
412-
mSpecularOutputPositionsOnTerrainBuffer->CreateGPUBufferResource(rhi, specularProbesPositionsCPUBuffer, mSpecularProbesCountTotal, sizeof(XMFLOAT4), false, ER_BIND_NONE, 0x10000L | 0x20000L /*legacy from DX11*/, ER_RESOURCE_MISC_BUFFER_STRUCTURED); //should be STAGING
413-
414-
PlaceProbesOnTerrain(game, mSpecularOutputPositionsOnTerrainBuffer, mSpecularInputPositionsOnTerrainBuffer, specularProbesPositionsCPUBuffer, mSpecularProbesCountTotal, mTerrainPlacementHeightDeltaSpecularProbes);
405+
mSpecularOutputPositionsOnTerrainBuffer->CreateGPUBufferResource(rhi, mSpecularProbesPositionsTempCPUBuffer, mSpecularProbesCountTotal, sizeof(XMFLOAT4), false, ER_BIND_NONE, 0x10000L | 0x20000L /*legacy from DX11*/, ER_RESOURCE_MISC_BUFFER_STRUCTURED); //should be STAGING
415406

416-
rhi->UpdateBuffer(mSpecularProbesPositionsGPUBuffer, (void*)specularProbesPositionsCPUBuffer, mSpecularProbesCountTotal * sizeof(XMFLOAT4));
417-
418-
for (int i = 0; i < mSpecularProbesCountTotal; i++)
419-
mSpecularProbes[i].SetPosition(XMFLOAT3(specularProbesPositionsCPUBuffer[i].x, specularProbesPositionsCPUBuffer[i].y, specularProbesPositionsCPUBuffer[i].z));
420-
421-
DeleteObject(mSpecularInputPositionsOnTerrainBuffer);
422-
DeleteObject(mSpecularOutputPositionsOnTerrainBuffer);
407+
PlaceProbesOnTerrain(game, SPECULAR_PROBE, mSpecularOutputPositionsOnTerrainBuffer, mSpecularInputPositionsOnTerrainBuffer, mSpecularProbesPositionsTempCPUBuffer, mSpecularProbesCountTotal, mTerrainPlacementHeightDeltaSpecularProbes);
423408
}
424-
425-
DeleteObjects(specularProbesPositionsCPUBuffer);
426409
}
427410

428411
// probe cell's indices GPU buffer, tex. array indices GPU/CPU buffers
@@ -834,6 +817,12 @@ namespace EveryRay_Core
834817
oldInstancedData[i].World._44 = isCulled ? 1.0f : 0.0f;
835818
//writing cubemap index to [0][0] of world instanced matrix (since we don't need scale)
836819
oldInstancedData[i].World._11 = -1.0f;
820+
//updating position
821+
const XMFLOAT3& pos = probes[i].GetPosition();
822+
oldInstancedData[i].World._41 = pos.x;
823+
oldInstancedData[i].World._42 = pos.y;
824+
oldInstancedData[i].World._43 = pos.z;
825+
837826
if (!isCulled)
838827
{
839828
if (aType == DIFFUSE_PROBE)
@@ -885,6 +874,12 @@ namespace EveryRay_Core
885874

886875
void ER_LightProbesManager::UpdateProbes(ER_Core& game)
887876
{
877+
// delete temp CPU buffers in the first frame (we should have the positions in probes already)
878+
if (mDiffuseProbesPositionsTempCPUBuffer)
879+
DeleteObjects(mDiffuseProbesPositionsTempCPUBuffer);
880+
if (mSpecularProbesPositionsTempCPUBuffer)
881+
DeleteObjects(mSpecularProbesPositionsTempCPUBuffer);
882+
888883
//int difProbeCellIndexCamera = GetCellIndex(mMainCamera.Position(), DIFFUSE_PROBE);
889884
if (mDistanceBetweenSpecularProbes > 0)
890885
assert(mMaxSpecularProbesInVolumeCount > 0);
@@ -893,7 +888,7 @@ namespace EveryRay_Core
893888
UpdateProbesByType(game, SPECULAR_PROBE);
894889
}
895890

896-
void ER_LightProbesManager::PlaceProbesOnTerrain(ER_Core& game, ER_RHI_GPUBuffer* outputBuffer, ER_RHI_GPUBuffer* inputBuffer, XMFLOAT4* positions, int positionsCount, float customDampDelta /*= FLT_MAX*/)
891+
void ER_LightProbesManager::PlaceProbesOnTerrain(ER_Core& game, ER_ProbeType aType, ER_RHI_GPUBuffer* outputBuffer, ER_RHI_GPUBuffer* inputBuffer, XMFLOAT4* positions, int positionsCount, float customDampDelta /*= FLT_MAX*/)
897892
{
898893
assert(mIsPlacedOnTerrain);
899894

@@ -902,5 +897,35 @@ namespace EveryRay_Core
902897
throw ER_CoreException("You want to place light probes on terrain but terrain is not found in the scene!");
903898

904899
terrain->PlaceOnTerrain(outputBuffer, inputBuffer, positions, positionsCount, TerrainSplatChannels::NONE, nullptr, 0, customDampDelta);
900+
901+
ER_RHI_GPUBuffer* finalGPUBuffer = (aType == DIFFUSE_PROBE) ? mDiffuseProbesPositionsGPUBuffer : mSpecularProbesPositionsGPUBuffer;
902+
903+
#ifndef ER_PLATFORM_WIN64_DX11
904+
const std::string probeTypeName = (aType == DIFFUSE_PROBE) ? "diffuse" : "specular";
905+
const std::string eventName = "On-terrain placement callback - placement of probes: " + probeTypeName;
906+
terrain->ReadbackPlacedPositionsOnInitEvent->AddListener(eventName,
907+
[&, aType, finalGPUBuffer, outputBuffer, inputBuffer, positions, positionsCount, rhi = game.GetRHI(), sandbox = game.GetLevel()](ER_Terrain* aTerrain)
908+
{
909+
assert(aTerrain);
910+
aTerrain->ReadbackPlacedPositions(outputBuffer, inputBuffer, positions, positionsCount);
911+
912+
rhi->UpdateBuffer(finalGPUBuffer, (void*)positions, positionsCount * sizeof(XMFLOAT4), true);
913+
914+
if (aType == DIFFUSE_PROBE)
915+
for (int i = 0; i < positionsCount; i++)
916+
sandbox->mLightProbesManager->SetDiffuseProbePosition(i, XMFLOAT3(positions[i].x, positions[i].y, positions[i].z));
917+
else
918+
for (int i = 0; i < positionsCount; i++)
919+
sandbox->mLightProbesManager->SetSpecularProbePosition(i, XMFLOAT3(positions[i].x, positions[i].y, positions[i].z));
920+
}
921+
);
922+
#else
923+
std::vector<ER_LightProbe>& probes = (aType == DIFFUSE_PROBE) ? mDiffuseProbes : mSpecularProbes;
924+
925+
game.GetRHI()->UpdateBuffer(finalGPUBuffer, (void*)positions, positionsCount * sizeof(XMFLOAT4));
926+
927+
for (int i = 0; i < positionsCount; i++)
928+
probes[i].SetPosition(XMFLOAT3(positions[i].x, positions[i].y, positions[i].z));
929+
#endif
905930
}
906931
}

source/EveryRay_Core/ER_LightProbesManager.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ namespace EveryRay_Core
8484
bool IsEnabled() { return mEnabled; }
8585
bool AreGlobalProbesReady() { return mGlobalDiffuseProbeReady && mGlobalSpecularProbeReady; }
8686

87+
void SetDiffuseProbePosition(int index, const XMFLOAT3& pos) { mDiffuseProbes[index].SetPosition(pos); }
88+
void SetSpecularProbePosition(int index, const XMFLOAT3& pos) { mSpecularProbes[index].SetPosition(pos); }
89+
8790
bool mDebugDiscardCulledProbes = false;//used in DebugLightProbeMaterial
8891
private:
8992
void SetupGlobalDiffuseProbe(ER_Core& game, ER_Camera& camera, ER_Scene* scene, ER_DirectionalLight* light, ER_ShadowMapper* shadowMapper);
@@ -93,7 +96,8 @@ namespace EveryRay_Core
9396
void AddProbeToCells(ER_LightProbe& aProbe, ER_ProbeType aType, const XMFLOAT3& minBounds, const XMFLOAT3& maxBounds);
9497
bool IsProbeInCell(ER_LightProbe& aProbe, ER_LightProbeCell& aCell, ER_AABB& aCellBounds);
9598
void UpdateProbesByType(ER_Core& game, ER_ProbeType aType);
96-
void PlaceProbesOnTerrain(ER_Core& game, ER_RHI_GPUBuffer* outputBuffer, ER_RHI_GPUBuffer* inputBuffer, XMFLOAT4* positions, int positionsCount, float customDampDelta = FLT_MAX);
99+
void PlaceProbesOnTerrain(ER_Core& game, ER_ProbeType aType, ER_RHI_GPUBuffer* outputBuffer, ER_RHI_GPUBuffer* inputBuffer,
100+
XMFLOAT4* positions, int positionsCount, float customDampDelta = FLT_MAX);
97101

98102
ER_QuadRenderer* mQuadRenderer = nullptr;
99103
ER_Camera& mMainCamera;
@@ -111,6 +115,7 @@ namespace EveryRay_Core
111115
std::string mDiffuseDebugLightProbePassPSOName = "ER_RHI_GPUPipelineStateObject: Light Probes Manager - Diffuse Debug Probe Pass";
112116
ER_RHI_GPUBuffer* mDiffuseProbesCellsIndicesGPUBuffer = nullptr;
113117
ER_RHI_GPUBuffer* mDiffuseProbesPositionsGPUBuffer = nullptr;
118+
XMFLOAT4* mDiffuseProbesPositionsTempCPUBuffer = nullptr;
114119
ER_RHI_GPUBuffer* mDiffuseInputPositionsOnTerrainBuffer = nullptr;
115120
ER_RHI_GPUBuffer* mDiffuseOutputPositionsOnTerrainBuffer = nullptr;
116121
ER_RHI_GPUBuffer* mDiffuseProbesSphericalHarmonicsGPUBuffer = nullptr;
@@ -140,6 +145,7 @@ namespace EveryRay_Core
140145
ER_RHI_GPUBuffer* mSpecularProbesTexArrayIndicesGPUBuffer = nullptr;
141146
ER_RHI_GPUBuffer* mSpecularProbesCellsIndicesGPUBuffer = nullptr;
142147
ER_RHI_GPUBuffer* mSpecularProbesPositionsGPUBuffer = nullptr;
148+
XMFLOAT4* mSpecularProbesPositionsTempCPUBuffer = nullptr;
143149
ER_RHI_GPUBuffer* mSpecularInputPositionsOnTerrainBuffer = nullptr;
144150
ER_RHI_GPUBuffer* mSpecularOutputPositionsOnTerrainBuffer = nullptr;
145151
ER_RHI_GPUTexture* mTempSpecularCubemapFacesRT = nullptr;

0 commit comments

Comments
 (0)