Fixing Depth culling out of bounds errors
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
struct DepthDebugData
|
||||
{
|
||||
uint mipLevel;
|
||||
uint mipOffset;
|
||||
int2 mipDimensions;
|
||||
int2 screenCornerMin;
|
||||
int2 screenCornerMax;
|
||||
int2 origScreenMin;
|
||||
int2 origScreenMax;
|
||||
};
|
||||
|
||||
struct DepthData
|
||||
{
|
||||
//uint bufferLength;
|
||||
Texture2D<float> texture;
|
||||
RWStructuredBuffer<float> buffer;
|
||||
//globallycoherent RWStructuredBuffer<uint> debugHead;
|
||||
//globallycoherent RWStructuredBuffer<DepthDebugData> debugData;
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import Common;
|
||||
import Scene;
|
||||
import Bounding;
|
||||
import DepthCommon;
|
||||
|
||||
groupshared MeshPayload p;
|
||||
groupshared uint head;
|
||||
@@ -10,37 +11,55 @@ groupshared Frustum viewFrustum;
|
||||
groupshared float4x4 modelViewProjection;
|
||||
groupshared bool meshVisible;
|
||||
|
||||
struct DepthData
|
||||
{
|
||||
Texture2D<float> texture;
|
||||
RWStructuredBuffer<float> buffer;
|
||||
}
|
||||
//void writeDebug(uint mipLevel, uint mipOffset, int2 mipDimensions, int2 screenMin, int2 screenMax, int2 origScreenMin, int2 origScreenMax)
|
||||
//{
|
||||
// uint index = 0;
|
||||
// InterlockedAdd(pDepthAttachment.debugHead[0], 1, index);
|
||||
// index = min(index, 10000);
|
||||
// {
|
||||
// pDepthAttachment.debugData[index].mipLevel = mipLevel;
|
||||
// pDepthAttachment.debugData[index].mipOffset = mipOffset;
|
||||
// pDepthAttachment.debugData[index].mipDimensions = mipDimensions;
|
||||
// pDepthAttachment.debugData[index].screenCornerMax = screenMax;
|
||||
// pDepthAttachment.debugData[index].screenCornerMin = screenMin;
|
||||
// pDepthAttachment.debugData[index].origScreenMax = origScreenMax;
|
||||
// pDepthAttachment.debugData[index].origScreenMin = origScreenMin;
|
||||
// }
|
||||
//}
|
||||
|
||||
ParameterBlock<DepthData> pDepthAttachment;
|
||||
|
||||
bool isBoxVisible(AABB bounding)
|
||||
{
|
||||
uint2 mipDimensions = uint2(uint(pViewParams.screenDimensions.x), uint(pViewParams.screenDimensions.y));
|
||||
int2 mipDimensions = uint2(uint(pViewParams.screenDimensions.x), uint(pViewParams.screenDimensions.y));
|
||||
// now we calculate what mip level we need to only sample up to 4 texels covering the entire meshlet
|
||||
uint2 screenCornerMin = mipDimensions;
|
||||
uint2 screenCornerMax = uint2(0, 0);
|
||||
int2 screenCornerMin = mipDimensions;
|
||||
int2 screenCornerMax = uint2(0, 0);
|
||||
// lower values are closer
|
||||
float maxDepth = bounding.projectScreenDepth(modelViewProjection, screenCornerMin, screenCornerMax);
|
||||
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
|
||||
while(screenCornerMax.x - screenCornerMin.x > 1 || screenCornerMax.y - screenCornerMin.y > 1)
|
||||
{
|
||||
// mipLevel++;
|
||||
mipOffset += mipDimensions.x * mipDimensions.y;
|
||||
mipDimensions = uint2(mipDimensions.x + 1, mipDimensions.y + 1) / 2;
|
||||
screenCornerMin = uint2(screenCornerMin.x + 1, screenCornerMin.y + 1) / 2;
|
||||
screenCornerMax = uint2(screenCornerMax.x, screenCornerMax.y) / 2;
|
||||
mipDimensions = int2(mipDimensions.x + 1, mipDimensions.y + 1) / 2;
|
||||
screenCornerMin = int2(screenCornerMin.x + 1, screenCornerMin.y + 1) / 2;
|
||||
screenCornerMax = int2(screenCornerMax.x, screenCornerMax.y) / 2;
|
||||
}
|
||||
|
||||
uint i0 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMin.x;
|
||||
uint i1 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x;
|
||||
uint i2 = mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMin.x;
|
||||
uint i3 = mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMax.x;
|
||||
|
||||
// now we sample 4 texels from the depth at the calculated mip level, this should give us the screen extent of the meshlet
|
||||
float d1 = pDepthAttachment.buffer[mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMin.x];
|
||||
float d2 = pDepthAttachment.buffer[mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x];
|
||||
float d3 = pDepthAttachment.buffer[mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMin.x];
|
||||
float d4 = pDepthAttachment.buffer[mipOffset + (screenCornerMax.y * mipDimensions.x) + screenCornerMax.x];
|
||||
float d1 = pDepthAttachment.buffer[i0];
|
||||
float d2 = pDepthAttachment.buffer[i1];
|
||||
float d3 = pDepthAttachment.buffer[i2];
|
||||
float d4 = pDepthAttachment.buffer[i3];
|
||||
|
||||
// we want to check if the minimum depth (the value farthest away) is smaller than the maximum bounding box depth
|
||||
// otherwise, there is no way for the meshlet to be visible
|
||||
@@ -102,7 +121,7 @@ void taskMain(
|
||||
{
|
||||
#ifdef DEPTH_CULLING
|
||||
// if the meshlet bounding box is behind the cached depth buffer, we skip
|
||||
//if(isBoxVisible(meshlet.bounding))
|
||||
if(isBoxVisible(meshlet.bounding))
|
||||
#endif
|
||||
{
|
||||
uint index;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import Common;
|
||||
import DepthCommon;
|
||||
|
||||
struct DepthData
|
||||
{
|
||||
Texture2D<float> texture;
|
||||
RWStructuredBuffer<float> buffer;
|
||||
}
|
||||
ParameterBlock<DepthData> pDepthAttachment;
|
||||
|
||||
struct MipParam
|
||||
|
||||
@@ -51,7 +51,7 @@ struct AABB
|
||||
}
|
||||
return result;
|
||||
}
|
||||
float projectScreenDepth(float4x4 mvp, inout uint2 screenCornerMin, inout uint2 screenCornerMax)
|
||||
float projectScreenDepth(float4x4 mvp, inout int2 screenCornerMin, inout int2 screenCornerMax)
|
||||
{
|
||||
float maxDepth = 0;
|
||||
float4 corners[8];
|
||||
@@ -67,8 +67,9 @@ struct AABB
|
||||
{
|
||||
float4 clipCorner = mul(mvp, corners[i]);
|
||||
float4 screenCorner = clipToScreen(clipCorner);
|
||||
screenCornerMin = uint2(min(screenCornerMin.x, uint(screenCorner.x)), min(screenCornerMin.y, uint(screenCorner.y)));
|
||||
screenCornerMax = uint2(max(screenCornerMax.x, uint(screenCorner.x)), max(screenCornerMax.y, uint(screenCorner.y)));
|
||||
int2 screenCoords = int2(clamp(int(screenCorner.x), 0, int(pViewParams.screenDimensions.x)), clamp(int(screenCorner.y), 0, int(pViewParams.screenDimensions.y)));
|
||||
screenCornerMin = int2(min(screenCornerMin.x, screenCoords.x), min(screenCornerMin.y, screenCoords.y));
|
||||
screenCornerMax = int2(max(screenCornerMax.x, screenCoords.x), max(screenCornerMax.y, screenCoords.y));
|
||||
maxDepth = max(maxDepth, screenCorner.z);
|
||||
}
|
||||
return maxDepth;
|
||||
|
||||
@@ -472,7 +472,7 @@ void BasePass::createRenderPass() {
|
||||
oLightGrid = resources->requestTexture("LIGHTCULLING_OLIGHTGRID");
|
||||
tLightGrid = resources->requestTexture("LIGHTCULLING_TLIGHTGRID");
|
||||
|
||||
waterRenderer->setViewport(viewport, renderPass);
|
||||
//waterRenderer->setViewport(viewport, renderPass);
|
||||
|
||||
// Debug rendering
|
||||
{
|
||||
|
||||
@@ -6,6 +6,10 @@ using namespace Seele;
|
||||
|
||||
DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics, scene) {
|
||||
depthAttachmentLayout = graphics->createDescriptorLayout("pDepthAttachment");
|
||||
//depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
// .binding = 0,
|
||||
// .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
//});
|
||||
depthAttachmentLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
@@ -16,6 +20,16 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
|
||||
.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 = 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();
|
||||
|
||||
depthCullingLayout = graphics->createPipelineLayout("DepthPrepassLayout");
|
||||
@@ -73,9 +87,15 @@ void DepthCullingPass::render() {
|
||||
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||
|
||||
//uint32 reset = 0;
|
||||
//debugHead->updateContents(0, sizeof(uint32), &reset);
|
||||
|
||||
Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet();
|
||||
//set->updateBuffer(0, debugUniform);
|
||||
set->updateTexture(0, Gfx::PTexture2D(depthAttachment.getTexture()));
|
||||
set->updateBuffer(1, depthMipBuffer);
|
||||
//set->updateBuffer(3, debugHead);
|
||||
//set->updateBuffer(4, debugData);
|
||||
set->writeChanges();
|
||||
|
||||
timestamps->begin();
|
||||
@@ -221,7 +241,33 @@ void DepthCullingPass::publishOutputs() {
|
||||
width = std::max((width + 1) / 2, 1u);
|
||||
height = std::max((height + 1) / 2, 1u);
|
||||
}
|
||||
ShaderBufferCreateInfo depthMipInfo = {
|
||||
|
||||
//debugUniform = graphics->createUniformBuffer(UniformBufferCreateInfo{
|
||||
// .sourceData =
|
||||
// {
|
||||
// .size = sizeof(uint32),
|
||||
// .data = (uint8*)&bufferSize,
|
||||
// },
|
||||
//});
|
||||
//uint32 reset = 0;
|
||||
//debugHead = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
// .sourceData =
|
||||
// {
|
||||
// .size = sizeof(uint32),
|
||||
// .data = (uint8*)&reset,
|
||||
// },
|
||||
//
|
||||
//});
|
||||
//debugData = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
// .sourceData =
|
||||
// {
|
||||
// .size = sizeof(DepthDebugData) * 10000,
|
||||
// .data = nullptr,
|
||||
// },
|
||||
//});
|
||||
//graphics->waitDeviceIdle();
|
||||
|
||||
depthMipBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = bufferSize * sizeof(uint32),
|
||||
@@ -229,17 +275,14 @@ void DepthCullingPass::publishOutputs() {
|
||||
},
|
||||
.numElements = bufferSize,
|
||||
.name = "DepthMipBuffer",
|
||||
};
|
||||
depthMipBuffer = graphics->createShaderBuffer(depthMipInfo);
|
||||
});
|
||||
|
||||
ShaderCompilationInfo mipComputeInfo = {
|
||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||
.name = "DepthMipCompute",
|
||||
.modules = {"DepthMipGen"},
|
||||
.entryPoints = {{"initialReduce", "DepthMipGen"}, {"reduceLevel", "DepthMipGen"}},
|
||||
.rootSignature = depthComputeLayout,
|
||||
};
|
||||
|
||||
graphics->beginShaderCompilation(mipComputeInfo);
|
||||
});
|
||||
depthInitialReduceShader = graphics->createComputeShader({0});
|
||||
depthComputeLayout->create();
|
||||
|
||||
|
||||
@@ -25,6 +25,15 @@ class DepthCullingPass : public RenderPass {
|
||||
UVector2 srcMipDim;
|
||||
UVector2 dstMipDim;
|
||||
};
|
||||
|
||||
struct DepthDebugData {
|
||||
uint32 mipLevel;
|
||||
uint32 mipOffset;
|
||||
UVector2 mipDimensions;
|
||||
UVector2 screenCornerMin;
|
||||
UVector2 screenCornerMax;
|
||||
};
|
||||
|
||||
Array<uint32> mipOffsets;
|
||||
Array<UVector2> mipDims;
|
||||
Gfx::OShaderBuffer depthMipBuffer;
|
||||
@@ -41,6 +50,10 @@ class DepthCullingPass : public RenderPass {
|
||||
Gfx::OComputeShader depthMipGenShader;
|
||||
Gfx::PComputePipeline depthMipGen;
|
||||
|
||||
//Gfx::OUniformBuffer debugUniform;
|
||||
//Gfx::OShaderBuffer debugHead;
|
||||
//Gfx::OShaderBuffer debugData;
|
||||
|
||||
Gfx::PShaderBuffer cullingBuffer;
|
||||
};
|
||||
DEFINE_REF(DepthCullingPass)
|
||||
|
||||
@@ -774,6 +774,7 @@ void Graphics::pickPhysicalDevice() {
|
||||
.pNext = &features11,
|
||||
.features =
|
||||
{
|
||||
//.robustBufferAccess = true,
|
||||
.geometryShader = true,
|
||||
.fillModeNonSolid = true,
|
||||
.wideLines = true,
|
||||
|
||||
@@ -37,25 +37,25 @@ void Material::init(Gfx::PGraphics graphics) {
|
||||
layout = graphics->createDescriptorLayout("pMaterial");
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
|
||||
});
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 1,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.descriptorCount = 512,
|
||||
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
|
||||
});
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 1,
|
||||
.binding = 2,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.descriptorCount = 512,
|
||||
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
|
||||
});
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 2,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
|
||||
});
|
||||
layout->create();
|
||||
floatBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.dynamic = true,
|
||||
@@ -76,17 +76,17 @@ void Material::updateDescriptor() {
|
||||
Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
layout->reset();
|
||||
set = layout->allocateDescriptorSet();
|
||||
set->updateBuffer(0, floatBuffer);
|
||||
for (uint32 i = 0; i < textures.size(); ++i) {
|
||||
if (textures[i] != nullptr) {
|
||||
set->updateTexture(0, i, textures[i]);
|
||||
set->updateTexture(1, i, textures[i]);
|
||||
}
|
||||
}
|
||||
for (uint32 i = 0; i < samplers.size(); ++i) {
|
||||
if (samplers[i] != nullptr) {
|
||||
set->updateSampler(1, i, samplers[i]);
|
||||
set->updateSampler(2, i, samplers[i]);
|
||||
}
|
||||
}
|
||||
set->updateBuffer(2, floatBuffer);
|
||||
set->writeChanges();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user