Finally fixing it for real for real
This commit is contained in:
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
subprocess.run(['build/Benchmark.exe'])
|
subprocess.run(['Benchmark.exe'])
|
||||||
subprocess.run(['build/Benchmark.exe', 'NOCULL'])
|
subprocess.run(['Benchmark.exe', 'NOCULL'])
|
||||||
@@ -30,25 +30,30 @@ groupshared bool meshVisible;
|
|||||||
ParameterBlock<DepthData> pDepthAttachment;
|
ParameterBlock<DepthData> pDepthAttachment;
|
||||||
bool isBoxVisible(AABB bounding)
|
bool isBoxVisible(AABB bounding)
|
||||||
{
|
{
|
||||||
int2 mipDimensions = uint2(uint(pViewParams.screenDimensions.x), uint(pViewParams.screenDimensions.y));
|
int2 mipDimensions = int2(int(pViewParams.screenDimensions.x), int(pViewParams.screenDimensions.y));
|
||||||
// now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet
|
// now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet
|
||||||
int2 screenCornerMin = mipDimensions;
|
int2 screenCornerMin = mipDimensions;
|
||||||
int2 screenCornerMax = uint2(0, 0);
|
int2 screenCornerMax = int2(0, 0);
|
||||||
// lower values are closer
|
// lower values are closer
|
||||||
float maxDepth = bounding.projectScreenDepth(modelViewProjection, screenCornerMin, screenCornerMax);
|
float maxDepth = bounding.projectScreenDepth(modelViewProjection, screenCornerMin, screenCornerMax);
|
||||||
uint mipOffset = 0;
|
uint mipOffset = 0;
|
||||||
// uint mipLevel = 0;
|
|
||||||
// int2 origScreenMin = screenCornerMin;
|
|
||||||
// int2 origScreenMax = screenCornerMax;
|
|
||||||
// in theory this wouldnt work if no corner was in screen, as min would be greater that max, however we verified that with view culling
|
// in theory this wouldnt work if no corner was in screen, as min would be greater that max, however we verified that with view culling
|
||||||
while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1)
|
while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1)
|
||||||
{
|
{
|
||||||
// mipLevel++;
|
|
||||||
mipOffset += mipDimensions.x * mipDimensions.y;
|
mipOffset += mipDimensions.x * mipDimensions.y;
|
||||||
mipDimensions = int2(mipDimensions.x + 1, mipDimensions.y + 1) / 2;
|
mipDimensions = int2(mipDimensions.x + 1, mipDimensions.y + 1) / 2;
|
||||||
screenCornerMin = int2(screenCornerMin.x + 1, screenCornerMin.y + 1) / 2;
|
screenCornerMin = int2(screenCornerMin.x, screenCornerMin.y) / 2;
|
||||||
screenCornerMax = int2(screenCornerMax.x, screenCornerMax.y) / 2;
|
screenCornerMax = int2(screenCornerMax.x, screenCornerMax.y) / 2;
|
||||||
}
|
}
|
||||||
|
//float d = 1;
|
||||||
|
//for(uint y = screenCornerMin.y; y <= screenCornerMax.y; y++)
|
||||||
|
//{
|
||||||
|
// for(uint x = screenCornerMin.x; x <= screenCornerMax.x; x++)
|
||||||
|
// {
|
||||||
|
// d = min(pDepthAttachment.buffer[mipOffset + (y * mipDimensions.x) + x], d);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
uint i0 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMin.x;
|
uint i0 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMin.x;
|
||||||
uint i1 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x;
|
uint i1 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x;
|
||||||
@@ -77,6 +82,8 @@ bool isBoxVisible(AABB bounding)
|
|||||||
void taskMain(
|
void taskMain(
|
||||||
uint threadID: SV_GroupThreadID,
|
uint threadID: SV_GroupThreadID,
|
||||||
uint groupID: SV_GroupID, )
|
uint groupID: SV_GroupID, )
|
||||||
|
{
|
||||||
|
if(threadID == 0)
|
||||||
{
|
{
|
||||||
head = 0;
|
head = 0;
|
||||||
instance = pScene.instances[pOffsets.instanceOffset + groupID];
|
instance = pScene.instances[pOffsets.instanceOffset + groupID];
|
||||||
@@ -97,9 +104,9 @@ void taskMain(
|
|||||||
viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]);
|
viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]);
|
||||||
viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]);
|
viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]);
|
||||||
viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]);
|
viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]);
|
||||||
meshVisible = mesh.bounding.insideFrustum(viewFrustum) && isBoxVisible(mesh.bounding);
|
//meshVisible = mesh.bounding.insideFrustum(viewFrustum) && isBoxVisible(mesh.bounding);
|
||||||
//meshVisible = true;
|
meshVisible = true;
|
||||||
|
}
|
||||||
GroupMemoryBarrierWithGroupSync();
|
GroupMemoryBarrierWithGroupSync();
|
||||||
if(!meshVisible)
|
if(!meshVisible)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,57 +5,51 @@ ParameterBlock<DepthData> pDepthAttachment;
|
|||||||
|
|
||||||
struct MipParam
|
struct MipParam
|
||||||
{
|
{
|
||||||
uint srcMipOffset;
|
uint sourceOffset;
|
||||||
uint dstMipOffset;
|
uint destOffset;
|
||||||
uint2 srcMipDim;
|
uint2 sourceDim;
|
||||||
uint2 dstMipDim;
|
uint2 destDim;
|
||||||
}
|
}
|
||||||
layout(push_constant)
|
layout(push_constant)
|
||||||
ConstantBuffer<MipParam> pMipParam;
|
ConstantBuffer<MipParam> pMipParam;
|
||||||
|
|
||||||
float getSrcDepth(uint2 pos)
|
float readBuffer(uint2 pos)
|
||||||
{
|
{
|
||||||
return pDepthAttachment.buffer[pMipParam.srcMipOffset + pos.x + (pos.y * pMipParam.srcMipDim.x)];
|
if(pos.x >= pMipParam.sourceDim.x || pos.y >= pMipParam.sourceDim.y)
|
||||||
|
{
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
return pDepthAttachment.buffer[pMipParam.sourceOffset + pos.x + (pos.y * pMipParam.sourceDim.x)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDstDepth(uint2 pos, float depth)
|
|
||||||
{
|
|
||||||
pDepthAttachment.buffer[pMipParam.dstMipOffset + pos.x + (pos.y * pMipParam.dstMipDim.x)] = depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
|
|
||||||
[shader("compute")]
|
[shader("compute")]
|
||||||
|
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
|
||||||
void reduceLevel(
|
void reduceLevel(
|
||||||
uint3 threadID: SV_GroupThreadID,
|
uint2 dispatchID: SV_DispatchThreadID,
|
||||||
uint3 groupID: SV_GroupID,
|
|
||||||
) {
|
) {
|
||||||
uint2 minCoords = (groupID.xy * BLOCK_SIZE + threadID.xy) * 2;
|
if(dispatchID.x >= pMipParam.destDim.x || dispatchID.y >= pMipParam.destDim.y)
|
||||||
|
|
||||||
if(minCoords.x >= pMipParam.srcMipDim.x || minCoords.y >= pMipParam.srcMipDim.y)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
uint2 readOffset = dispatchID * 2;
|
||||||
uint2 maxCoords = uint2(min(minCoords.x + 1, pMipParam.srcMipDim.x - 1), min(minCoords.y + 1, pMipParam.srcMipDim.y - 1));
|
float d0 = readBuffer(readOffset + uint2(0, 0));
|
||||||
|
float d1 = readBuffer(readOffset + uint2(0, 1));
|
||||||
float d0 = getSrcDepth(uint2(minCoords.x, minCoords.y));
|
float d2 = readBuffer(readOffset + uint2(1, 0));
|
||||||
float d1 = getSrcDepth(uint2(maxCoords.x, minCoords.y));
|
float d3 = readBuffer(readOffset + uint2(1, 1));
|
||||||
float d2 = getSrcDepth(uint2(minCoords.x, maxCoords.y));
|
pDepthAttachment.buffer[pMipParam.destOffset + dispatchID.x + (dispatchID.y * pMipParam.destDim.x)] = min(min(d0, d1), min(d2, d3));
|
||||||
float d3 = getSrcDepth(uint2(maxCoords.x, maxCoords.y));
|
|
||||||
|
|
||||||
float minDepth = min(min(d0, d1), min(d2, d3));
|
|
||||||
setDstDepth(minCoords / 2, minDepth);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
|
// each thread reduces the a pixel indivdually
|
||||||
|
// used for mip levels where the read size is smaller than
|
||||||
|
// the group dimensions
|
||||||
[shader("compute")]
|
[shader("compute")]
|
||||||
void initialReduce(
|
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
|
||||||
uint3 threadID: SV_GroupThreadID,
|
void sourceCopy(
|
||||||
uint3 groupID: SV_GroupID,
|
uint2 dispatchID: SV_DispatchThreadID
|
||||||
) {
|
) {
|
||||||
uint width = uint(pViewParams.screenDimensions.x);
|
if(dispatchID.x >= pViewParams.screenDimensions.x || dispatchID.y >= pViewParams.screenDimensions.y)
|
||||||
int2 groupOffset = groupID.xy * BLOCK_SIZE;
|
{
|
||||||
int2 texCoord = groupOffset + threadID.xy;
|
return;
|
||||||
float fDepth = pDepthAttachment.texture.Load(int3(texCoord, 0)).r;
|
}
|
||||||
pDepthAttachment.buffer[texCoord.x + (texCoord.y * width)] = fDepth;
|
pDepthAttachment.buffer[dispatchID.x + (dispatchID.y * uint(pViewParams.screenDimensions.x))] = pDepthAttachment.texture[uint2(dispatchID)];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ float4 clipToScreen(float4 clip)
|
|||||||
float oz = 1;
|
float oz = 1;
|
||||||
float pz = 0 - 1;
|
float pz = 0 - 1;
|
||||||
float zf = pz * ndc.z + oz;
|
float zf = pz * ndc.z + oz;
|
||||||
return float4(float2(texCoords.x, 1 - texCoords.y) * pViewParams.screenDimensions, 1 / zf, 1.0f);
|
return float4(float2(texCoords.x, 1 - texCoords.y) * pViewParams.screenDimensions, zf, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Plane
|
struct Plane
|
||||||
|
|||||||
+15
-10
@@ -8,6 +8,7 @@ using namespace Seele;
|
|||||||
PlayView::PlayView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo, std::string dllPath, bool useMeshCulling)
|
PlayView::PlayView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo& createInfo, std::string dllPath, bool useMeshCulling)
|
||||||
: GameView(graphics, window, createInfo, dllPath) {
|
: GameView(graphics, window, createInfo, dllPath) {
|
||||||
getGlobals().useDepthCulling = useMeshCulling;
|
getGlobals().useDepthCulling = useMeshCulling;
|
||||||
|
renderTimestamp = graphics->createTimestampQuery(2, "RenderTimestamp");
|
||||||
queryThread = std::thread([&]() {
|
queryThread = std::thread([&]() {
|
||||||
PRenderGraphResources res = renderGraph.getResources();
|
PRenderGraphResources res = renderGraph.getResources();
|
||||||
Gfx::PPipelineStatisticsQuery cachedQuery = res->requestQuery("CACHED_QUERY");
|
Gfx::PPipelineStatisticsQuery cachedQuery = res->requestQuery("CACHED_QUERY");
|
||||||
@@ -23,21 +24,23 @@ PlayView::PlayView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
|
|||||||
<< "DepthIAV,DepthIAP,DepthVS,DepthClipInv,DepthClipPrim,DepthFS,DepthCS,DepthTS,DepthMS,"
|
<< "DepthIAV,DepthIAP,DepthVS,DepthClipInv,DepthClipPrim,DepthFS,DepthCS,DepthTS,DepthMS,"
|
||||||
<< "BaseIAV,BaseIAP,BaseVS,BaseClipInv,BaseClipPrim,BaseFS,BaseCS,BaseTS,BaseMS,"
|
<< "BaseIAV,BaseIAP,BaseVS,BaseClipInv,BaseClipPrim,BaseFS,BaseCS,BaseTS,BaseMS,"
|
||||||
<< "LightCullIAV,LightCullIAP,LightCullVS,LightCullClipInv,LightCullClipPrim,LightCullFS,LightCullCS,LightCullTS,LightCullMS,"
|
<< "LightCullIAV,LightCullIAP,LightCullVS,LightCullClipInv,LightCullClipPrim,LightCullFS,LightCullCS,LightCullTS,LightCullMS,"
|
||||||
<< "VisibilityIAV,VisibilityIAP,VisibilityVS,VisibilityClipInv,VisibilityClipPrim,VisibilityFS,VisibilityCS,VisibilityMS,VisibilityMS," << std::endl;
|
<< "VisibilityIAV,VisibilityIAP,VisibilityVS,VisibilityClipInv,VisibilityClipPrim,VisibilityFS,VisibilityCS,VisibilityMS,"
|
||||||
|
"VisibilityMS,"
|
||||||
|
<< std::endl;
|
||||||
uint64 start = 0;
|
uint64 start = 0;
|
||||||
uint64 prevBegin = 0;
|
uint64 prevBegin = 0;
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
std::this_thread::sleep_for(std::chrono::milliseconds(500));
|
||||||
stats << std::fixed << std::setprecision(0);
|
stats << std::fixed << std::setprecision(0);
|
||||||
while (getGlobals().running) {
|
while (getGlobals().running) {
|
||||||
|
|
||||||
auto cachedResults = cachedQuery->getResults();
|
auto cachedResults = cachedQuery->getResults();
|
||||||
auto depthResults = depthQuery->getResults();
|
auto depthResults = depthQuery->getResults();
|
||||||
auto baseResults = baseQuery->getResults();
|
auto baseResults = baseQuery->getResults();
|
||||||
auto lightCullResults = lightCullQuery->getResults();
|
auto lightCullResults = lightCullQuery->getResults();
|
||||||
auto visiblityResults = visibilityQuery->getResults();
|
auto visiblityResults = visibilityQuery->getResults();
|
||||||
|
int64 renderBegin = renderTimestamp->getResult().time;
|
||||||
|
int64 renderEnd = renderTimestamp->getResult().time;
|
||||||
Map<std::string, uint64> results;
|
Map<std::string, uint64> results;
|
||||||
for (uint32 i = 0; i < 11; ++i)
|
for (uint32 i = 0; i < 11; ++i) {
|
||||||
{
|
|
||||||
auto ts = timestamps->getResult();
|
auto ts = timestamps->getResult();
|
||||||
results[ts.name] = ts.time;
|
results[ts.name] = ts.time;
|
||||||
}
|
}
|
||||||
@@ -53,12 +56,10 @@ PlayView::PlayView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
|
|||||||
int64 visibilityTime = results.at("VisibilityEnd") - results.at("VisibilityBegin");
|
int64 visibilityTime = results.at("VisibilityEnd") - results.at("VisibilityBegin");
|
||||||
int64 frameTime = cachedTime + mipTime + depthTime + baseTime + lightCullTime + visibilityTime;
|
int64 frameTime = cachedTime + mipTime + depthTime + baseTime + lightCullTime + visibilityTime;
|
||||||
|
|
||||||
stats << relTime << "," << cachedTime << "," << mipTime << "," << depthTime << ","
|
stats << relTime << "," << cachedTime << "," << mipTime << "," << depthTime << "," << visibilityTime << "," << lightCullTime
|
||||||
<< visibilityTime
|
<< "," << baseTime << "," << frameTime << "," << cachedResults << depthResults << baseResults << lightCullResults
|
||||||
<< "," << lightCullTime << "," << baseTime << ","
|
<< visiblityResults << std::endl;
|
||||||
<< frameTime << "," << cachedResults << depthResults << baseResults << lightCullResults << visiblityResults << std::endl;
|
|
||||||
stats.flush();
|
stats.flush();
|
||||||
// std::cout << "Writing " << timestamps[0].time << std::endl;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -73,6 +74,10 @@ void PlayView::commitUpdate() { GameView::commitUpdate(); }
|
|||||||
|
|
||||||
void PlayView::prepareRender() { GameView::prepareRender(); }
|
void PlayView::prepareRender() { GameView::prepareRender(); }
|
||||||
|
|
||||||
void PlayView::render() { GameView::render(); }
|
void PlayView::render() {
|
||||||
|
renderTimestamp->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "RenderBegin");
|
||||||
|
GameView::render();
|
||||||
|
renderTimestamp->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "RenderEnd");
|
||||||
|
}
|
||||||
|
|
||||||
void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) { GameView::keyCallback(code, action, modifier); }
|
void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) { GameView::keyCallback(code, action, modifier); }
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class PlayView : public GameView {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::thread queryThread;
|
std::thread queryThread;
|
||||||
|
Gfx::OTimestampQuery renderTimestamp;
|
||||||
};
|
};
|
||||||
DECLARE_REF(PlayView)
|
DECLARE_REF(PlayView)
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -45,4 +45,6 @@ void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifie
|
|||||||
std::cout << cam.getCameraPosition() << std::endl;
|
std::cout << cam.getCameraPosition() << std::endl;
|
||||||
std::cout << tra.getRotation() << std::endl;
|
std::cout << tra.getRotation() << std::endl;
|
||||||
}
|
}
|
||||||
|
if (code == KeyCode::KEY_R && action == InputAction::RELEASE) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-5
@@ -57,8 +57,11 @@ int main() {
|
|||||||
// AssetImporter::importFont(FontImportArgs{
|
// AssetImporter::importFont(FontImportArgs{
|
||||||
// .filePath = "./fonts/Calibri.ttf",
|
// .filePath = "./fonts/Calibri.ttf",
|
||||||
// });
|
// });
|
||||||
|
//AssetImporter::importMesh(MeshImportArgs{
|
||||||
|
// .filePath = sourcePath / "import/models/cube.fbx",
|
||||||
|
//});
|
||||||
AssetImporter::importMesh(MeshImportArgs{
|
AssetImporter::importMesh(MeshImportArgs{
|
||||||
.filePath = sourcePath / "import/models/cube.fbx",
|
.filePath = sourcePath / "import/models/culling.fbx",
|
||||||
});
|
});
|
||||||
AssetImporter::importTexture(TextureImportArgs{
|
AssetImporter::importTexture(TextureImportArgs{
|
||||||
.filePath = sourcePath / "import/textures/skyboxsun5deg_tn.jpg",
|
.filePath = sourcePath / "import/textures/skyboxsun5deg_tn.jpg",
|
||||||
@@ -72,10 +75,10 @@ int main() {
|
|||||||
.filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb",
|
.filePath = sourcePath / "import/models/after-the-rain-vr-sound/source/Whitechapel.glb",
|
||||||
.importPath = "Whitechapel",
|
.importPath = "Whitechapel",
|
||||||
});
|
});
|
||||||
AssetImporter::importMesh(MeshImportArgs{
|
//AssetImporter::importMesh(MeshImportArgs{
|
||||||
.filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj",
|
// .filePath = sourcePath / "import/models/city-suburbs/source/city-suburbs.obj",
|
||||||
.importPath = "suburbs",
|
// .importPath = "suburbs",
|
||||||
});
|
//});
|
||||||
getThreadPool().waitIdle();
|
getThreadPool().waitIdle();
|
||||||
vd->commitMeshes();
|
vd->commitMeshes();
|
||||||
WindowCreateInfo mainWindowInfo = {
|
WindowCreateInfo mainWindowInfo = {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace Seele {
|
|||||||
namespace Component {
|
namespace Component {
|
||||||
struct Mesh {
|
struct Mesh {
|
||||||
PMeshAsset asset;
|
PMeshAsset asset;
|
||||||
|
Array<uint32> meshletOffsets;
|
||||||
bool isStatic = true;
|
bool isStatic = true;
|
||||||
};
|
};
|
||||||
} // namespace Component
|
} // namespace Component
|
||||||
|
|||||||
@@ -6,10 +6,6 @@ using namespace Seele;
|
|||||||
|
|
||||||
DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
|
DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
|
||||||
depthAttachmentLayout = graphics->createDescriptorLayout("pDepthAttachment");
|
depthAttachmentLayout = graphics->createDescriptorLayout("pDepthAttachment");
|
||||||
//depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
// .binding = 0,
|
|
||||||
// .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
||||||
//});
|
|
||||||
depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
.binding = 0,
|
.binding = 0,
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
@@ -20,16 +16,6 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
|
|||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
.shaderStages = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_COMPUTE_BIT,
|
.shaderStages = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_COMPUTE_BIT,
|
||||||
});
|
});
|
||||||
//depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
// .binding = 3,
|
|
||||||
// .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
|
||||||
// .shaderStages = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_COMPUTE_BIT,
|
|
||||||
//});
|
|
||||||
//depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
// .binding = 4,
|
|
||||||
// .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
|
||||||
// .shaderStages = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_COMPUTE_BIT,
|
|
||||||
//});
|
|
||||||
depthAttachmentLayout->create();
|
depthAttachmentLayout->create();
|
||||||
|
|
||||||
depthCullingLayout = graphics->createPipelineLayout("DepthPrepassLayout");
|
depthCullingLayout = graphics->createPipelineLayout("DepthPrepassLayout");
|
||||||
@@ -94,33 +80,34 @@ void DepthCullingPass::render() {
|
|||||||
set->writeChanges();
|
set->writeChanges();
|
||||||
|
|
||||||
timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "MipBegin");
|
timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "MipBegin");
|
||||||
Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("InitialReduce");
|
// First we generate a pixel value per thread, while using a whole threadgroup
|
||||||
computeCommand->bindPipeline(depthInitialReduce);
|
// for a single one would be a waste
|
||||||
|
Gfx::OComputeCommand computeCommand = graphics->createComputeCommand("MipGen");
|
||||||
|
computeCommand->bindPipeline(depthSourceCopy);
|
||||||
computeCommand->bindDescriptor({viewParamsSet, set});
|
computeCommand->bindDescriptor({viewParamsSet, set});
|
||||||
UVector2 reduceDimensions = UVector2(viewport->getOwner()->getFramebufferWidth() + BLOCK_SIZE - 1,
|
computeCommand->dispatch((viewport->getWidth() + BLOCK_SIZE - 1) / BLOCK_SIZE, (viewport->getHeight() + BLOCK_SIZE - 1) / BLOCK_SIZE,
|
||||||
viewport->getOwner()->getFramebufferHeight() + BLOCK_SIZE - 1) /
|
1);
|
||||||
uint32(BLOCK_SIZE);
|
|
||||||
computeCommand->dispatch(reduceDimensions.x, reduceDimensions.y, 1);
|
|
||||||
graphics->executeCommands(std::move(computeCommand));
|
graphics->executeCommands(std::move(computeCommand));
|
||||||
|
for (uint32 i = 0; i < mipOffsets.size() - 1; ++i)
|
||||||
for (uint32 i = 0; i < mipOffsets.size() - 1; ++i) {
|
{
|
||||||
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
|
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT,
|
||||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
Gfx::OComputeCommand mipCommand = graphics->createComputeCommand(fmt::format("MipGenLevel{0}", i));
|
MipParam param = {
|
||||||
mipCommand->bindPipeline(depthMipGen);
|
.sourceOffset = mipOffsets[i],
|
||||||
mipCommand->bindDescriptor({viewParamsSet, set});
|
.destOffset = mipOffsets[i + 1],
|
||||||
MipParam params = {
|
.sourceDim = mipDims[i],
|
||||||
.srcMipOffset = mipOffsets[i],
|
.destDim = mipDims[i + 1],
|
||||||
.dstMipOffset = mipOffsets[i + 1],
|
|
||||||
.srcMipDim = mipDims[i],
|
|
||||||
.dstMipDim = mipDims[i + 1],
|
|
||||||
};
|
};
|
||||||
mipCommand->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(MipParam), ¶ms);
|
Gfx::OComputeCommand reduceCommand = graphics->createComputeCommand("ReduceCommand");
|
||||||
UVector2 threadGroups = (reduceDimensions + 1u) / 2u;
|
reduceCommand->bindPipeline(depthReduceLevel);
|
||||||
mipCommand->dispatch(threadGroups.x, threadGroups.y, 1);
|
reduceCommand->bindDescriptor({viewParamsSet, set});
|
||||||
graphics->executeCommands(std::move(mipCommand));
|
reduceCommand->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(MipParam), ¶m);
|
||||||
|
auto dispatchDim = (mipDims[i + 1] + uint32(BLOCK_SIZE) - 1u) / uint32(BLOCK_SIZE);
|
||||||
|
reduceCommand->dispatch(dispatchDim.x, dispatchDim.y, 1);
|
||||||
|
graphics->executeCommands(std::move(reduceCommand));
|
||||||
}
|
}
|
||||||
|
|
||||||
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
depthMipBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TASK_SHADER_BIT_EXT);
|
||||||
|
|
||||||
@@ -256,22 +243,21 @@ void DepthCullingPass::publishOutputs() {
|
|||||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||||
.name = "DepthMipCompute",
|
.name = "DepthMipCompute",
|
||||||
.modules = {"DepthMipGen"},
|
.modules = {"DepthMipGen"},
|
||||||
.entryPoints = {{"initialReduce", "DepthMipGen"}, {"reduceLevel", "DepthMipGen"}},
|
.entryPoints = {{"sourceCopy", "DepthMipGen"}, {"reduceLevel", "DepthMipGen"}},
|
||||||
.rootSignature = depthComputeLayout,
|
.rootSignature = depthComputeLayout,
|
||||||
});
|
});
|
||||||
depthInitialReduceShader = graphics->createComputeShader({0});
|
depthSourceCopyShader = graphics->createComputeShader({0});
|
||||||
depthComputeLayout->create();
|
depthComputeLayout->create();
|
||||||
|
|
||||||
Gfx::ComputePipelineCreateInfo pipelineCreateInfo = {
|
Gfx::ComputePipelineCreateInfo pipelineCreateInfo = {
|
||||||
.computeShader = depthInitialReduceShader,
|
.computeShader = depthSourceCopyShader,
|
||||||
.pipelineLayout = depthComputeLayout,
|
.pipelineLayout = depthComputeLayout,
|
||||||
};
|
};
|
||||||
depthInitialReduce = graphics->createComputePipeline(pipelineCreateInfo);
|
depthSourceCopy = graphics->createComputePipeline(pipelineCreateInfo);
|
||||||
depthMipGenShader = graphics->createComputeShader({1});
|
|
||||||
|
|
||||||
pipelineCreateInfo.computeShader = depthMipGenShader;
|
depthReduceLevelShader = graphics->createComputeShader({1});
|
||||||
|
pipelineCreateInfo.computeShader = depthReduceLevelShader;
|
||||||
depthMipGen = graphics->createComputePipeline(pipelineCreateInfo);
|
depthReduceLevel = graphics->createComputePipeline(pipelineCreateInfo);
|
||||||
|
|
||||||
query = graphics->createPipelineStatisticsQuery("DepthPipelineStatistics");
|
query = graphics->createPipelineStatisticsQuery("DepthPipelineStatistics");
|
||||||
resources->registerQueryOutput("DEPTH_QUERY", query);
|
resources->registerQueryOutput("DEPTH_QUERY", query);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "MinimalEngine.h"
|
|
||||||
#include "RenderPass.h"
|
|
||||||
#include "Graphics/Pipeline.h"
|
#include "Graphics/Pipeline.h"
|
||||||
#include "Graphics/Query.h"
|
#include "Graphics/Query.h"
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "RenderPass.h"
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
class DepthCullingPass : public RenderPass {
|
class DepthCullingPass : public RenderPass {
|
||||||
@@ -20,10 +20,10 @@ class DepthCullingPass : public RenderPass {
|
|||||||
private:
|
private:
|
||||||
constexpr static uint64 BLOCK_SIZE = 32;
|
constexpr static uint64 BLOCK_SIZE = 32;
|
||||||
struct MipParam {
|
struct MipParam {
|
||||||
uint32 srcMipOffset;
|
uint32 sourceOffset;
|
||||||
uint32 dstMipOffset;
|
uint32 destOffset;
|
||||||
UVector2 srcMipDim;
|
UVector2 sourceDim;
|
||||||
UVector2 dstMipDim;
|
UVector2 destDim;
|
||||||
};
|
};
|
||||||
|
|
||||||
Array<uint32> mipOffsets;
|
Array<uint32> mipOffsets;
|
||||||
@@ -38,10 +38,10 @@ class DepthCullingPass : public RenderPass {
|
|||||||
Gfx::PTimestampQuery timestamps;
|
Gfx::PTimestampQuery timestamps;
|
||||||
|
|
||||||
Gfx::OPipelineLayout depthComputeLayout;
|
Gfx::OPipelineLayout depthComputeLayout;
|
||||||
Gfx::OComputeShader depthInitialReduceShader;
|
Gfx::OComputeShader depthSourceCopyShader;
|
||||||
Gfx::PComputePipeline depthInitialReduce;
|
Gfx::PComputePipeline depthSourceCopy;
|
||||||
Gfx::OComputeShader depthMipGenShader;
|
Gfx::OComputeShader depthReduceLevelShader;
|
||||||
Gfx::PComputePipeline depthMipGen;
|
Gfx::PComputePipeline depthReduceLevel;
|
||||||
|
|
||||||
Gfx::PShaderBuffer cullingBuffer;
|
Gfx::PShaderBuffer cullingBuffer;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,8 +12,6 @@
|
|||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 17962284;
|
constexpr static uint64 NUM_DEFAULT_ELEMENTS = 17962284;
|
||||||
Map<VertexData::MeshMapping, VertexData::CullingMapping> VertexData::instanceIdMap;
|
|
||||||
uint64 VertexData::instanceCount = 0;
|
|
||||||
uint64 VertexData::meshletCount = 0;
|
uint64 VertexData::meshletCount = 0;
|
||||||
|
|
||||||
void VertexData::resetMeshData() {
|
void VertexData::resetMeshData() {
|
||||||
@@ -37,7 +35,7 @@ void VertexData::resetMeshData() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform& transform) {
|
void VertexData::updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transform& transform) {
|
||||||
std::unique_lock l(materialDataLock);
|
std::unique_lock l(materialDataLock);
|
||||||
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
|
PMaterialInstance referencedInstance = mesh->referencedMaterial->getHandle();
|
||||||
PMaterial mat = referencedInstance->getBaseMaterial();
|
PMaterial mat = referencedInstance->getBaseMaterial();
|
||||||
@@ -49,8 +47,6 @@ void VertexData::updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Compo
|
|||||||
.inverseTransformMatrix = glm::inverse(transformMatrix),
|
.inverseTransformMatrix = glm::inverse(transformMatrix),
|
||||||
};
|
};
|
||||||
|
|
||||||
auto [instanceId, meshletOffset] = getCullingMapping(id, meshIndex, data.numMeshlets);
|
|
||||||
|
|
||||||
referencedInstance->updateDescriptor();
|
referencedInstance->updateDescriptor();
|
||||||
if (mat->hasTransparency()) {
|
if (mat->hasTransparency()) {
|
||||||
auto params = referencedInstance->getMaterialOffsets();
|
auto params = referencedInstance->getMaterialOffsets();
|
||||||
@@ -282,8 +278,7 @@ void VertexData::serializeMesh(MeshId id, uint64 numVertices, ArchiveBuffer& buf
|
|||||||
std::unique_lock l(vertexDataLock);
|
std::unique_lock l(vertexDataLock);
|
||||||
Array<Meshlet> out;
|
Array<Meshlet> out;
|
||||||
MeshData data = meshData[id];
|
MeshData data = meshData[id];
|
||||||
for (size_t i = 0; i < data.numMeshlets; ++i)
|
for (size_t i = 0; i < data.numMeshlets; ++i) {
|
||||||
{
|
|
||||||
MeshletDescription& desc = meshlets[i + data.meshletOffset];
|
MeshletDescription& desc = meshlets[i + data.meshletOffset];
|
||||||
Meshlet m;
|
Meshlet m;
|
||||||
std::memcpy(m.uniqueVertices, &vertexIndices[desc.vertexOffset], desc.vertexCount * sizeof(uint32));
|
std::memcpy(m.uniqueVertices, &vertexIndices[desc.vertexOffset], desc.vertexCount * sizeof(uint32));
|
||||||
@@ -385,13 +380,10 @@ void VertexData::destroy() {
|
|||||||
materialData.clear();
|
materialData.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexData::CullingMapping VertexData::getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets) {
|
uint32 VertexData::addCullingMapping(MeshId id) {
|
||||||
MeshMapping key = MeshMapping{.id = id, .meshId = meshIndex};
|
uint32 result = meshletCount;
|
||||||
if (!instanceIdMap.contains(key)) {
|
meshletCount += getMeshData(id).numMeshlets;
|
||||||
instanceIdMap[key] = CullingMapping{.instanceId = instanceCount++, .cullingOffset = uint32(meshletCount)};
|
return result;
|
||||||
meshletCount += numMeshlets;
|
|
||||||
}
|
|
||||||
return instanceIdMap[key];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexData::VertexData() : idCounter(0), head(0), verticesAllocated(0), dirty(false) {}
|
VertexData::VertexData() : idCounter(0), head(0), verticesAllocated(0), dirty(false) {}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class VertexData {
|
|||||||
Gfx::PBottomLevelAS rayTracingScene;
|
Gfx::PBottomLevelAS rayTracingScene;
|
||||||
};
|
};
|
||||||
void resetMeshData();
|
void resetMeshData();
|
||||||
void updateMesh(entt::entity id, uint32 meshIndex, PMesh mesh, Component::Transform& transform);
|
void updateMesh(uint32 meshletOffset, PMesh mesh, Component::Transform& transform);
|
||||||
void createDescriptors();
|
void createDescriptors();
|
||||||
void loadMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets);
|
void loadMesh(MeshId id, Array<uint32> indices, Array<Meshlet> meshlets);
|
||||||
void commitMeshes();
|
void commitMeshes();
|
||||||
@@ -85,12 +85,7 @@ class VertexData {
|
|||||||
virtual void init(Gfx::PGraphics graphics);
|
virtual void init(Gfx::PGraphics graphics);
|
||||||
virtual void destroy();
|
virtual void destroy();
|
||||||
|
|
||||||
struct CullingMapping {
|
uint32 addCullingMapping(MeshId id);
|
||||||
uint64 instanceId;
|
|
||||||
uint32 cullingOffset;
|
|
||||||
};
|
|
||||||
static CullingMapping getCullingMapping(entt::entity id, uint32 meshIndex, uint32 numMeshlets);
|
|
||||||
static uint64 getInstanceCount() { return instanceCount; }
|
|
||||||
static uint64 getMeshletCount() { return meshletCount; }
|
static uint64 getMeshletCount() { return meshletCount; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -125,13 +120,6 @@ class VertexData {
|
|||||||
Array<uint32> vertexIndices;
|
Array<uint32> vertexIndices;
|
||||||
Array<uint32> indices;
|
Array<uint32> indices;
|
||||||
|
|
||||||
struct MeshMapping {
|
|
||||||
entt::entity id;
|
|
||||||
uint32 meshId;
|
|
||||||
auto operator<=>(const MeshMapping& other) const = default;
|
|
||||||
};
|
|
||||||
static Map<MeshMapping, CullingMapping> instanceIdMap;
|
|
||||||
static uint64 instanceCount;
|
|
||||||
static uint64 meshletCount;
|
static uint64 meshletCount;
|
||||||
|
|
||||||
Gfx::PGraphics graphics;
|
Gfx::PGraphics graphics;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
|
|||||||
option[1].value.intValue0 = 1;
|
option[1].value.intValue0 = 1;
|
||||||
option[2].name = slang::CompilerOptionName::DebugInformation;
|
option[2].name = slang::CompilerOptionName::DebugInformation;
|
||||||
option[2].value.kind = slang::CompilerOptionValueKind::Int;
|
option[2].value.kind = slang::CompilerOptionValueKind::Int;
|
||||||
option[2].value.intValue0 = SLANG_DEBUG_INFO_LEVEL_NONE;
|
option[2].value.intValue0 = SLANG_DEBUG_INFO_LEVEL_STANDARD;
|
||||||
option[3].name = slang::CompilerOptionName::DebugInformationFormat;
|
option[3].name = slang::CompilerOptionName::DebugInformationFormat;
|
||||||
option[3].value.kind = slang::CompilerOptionValueKind::Int;
|
option[3].value.kind = slang::CompilerOptionValueKind::Int;
|
||||||
option[3].value.intValue0 = SLANG_DEBUG_INFO_FORMAT_PDB;
|
option[3].value.intValue0 = SLANG_DEBUG_INFO_FORMAT_PDB;
|
||||||
|
|||||||
@@ -10,7 +10,12 @@ MeshUpdater::MeshUpdater(PScene scene) : ComponentSystem<Component::Transform, C
|
|||||||
MeshUpdater::~MeshUpdater() {}
|
MeshUpdater::~MeshUpdater() {}
|
||||||
|
|
||||||
void MeshUpdater::update(entt::entity id, Component::Transform& transform, Component::Mesh& comp) {
|
void MeshUpdater::update(entt::entity id, Component::Transform& transform, Component::Mesh& comp) {
|
||||||
|
if (comp.meshletOffsets.empty()) {
|
||||||
for (uint32 i = 0; i < comp.asset->meshes.size(); ++i) {
|
for (uint32 i = 0; i < comp.asset->meshes.size(); ++i) {
|
||||||
comp.asset->meshes[i]->vertexData->updateMesh(id, i, comp.asset->meshes[i], transform);
|
comp.meshletOffsets.add(comp.asset->meshes[i]->vertexData->addCullingMapping(comp.asset->meshes[i]->id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (uint32 i = 0; i < comp.asset->meshes.size(); ++i) {
|
||||||
|
comp.asset->meshes[i]->vertexData->updateMesh(comp.meshletOffsets[i], comp.asset->meshes[i], transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user