Finally fixing it for real for real
This commit is contained in:
@@ -30,25 +30,30 @@ groupshared bool meshVisible;
|
||||
ParameterBlock<DepthData> pDepthAttachment;
|
||||
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
|
||||
int2 screenCornerMin = mipDimensions;
|
||||
int2 screenCornerMax = uint2(0, 0);
|
||||
int2 screenCornerMax = int2(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 = 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;
|
||||
}
|
||||
//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 i1 = mipOffset + (screenCornerMin.y * mipDimensions.x) + screenCornerMax.x;
|
||||
@@ -64,7 +69,7 @@ bool isBoxVisible(AABB bounding)
|
||||
// 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
|
||||
float d = min(min(d1, d2), min(d3, d4));
|
||||
|
||||
|
||||
if(d < maxDepth)
|
||||
{
|
||||
return true;
|
||||
@@ -78,28 +83,30 @@ void taskMain(
|
||||
uint threadID: SV_GroupThreadID,
|
||||
uint groupID: SV_GroupID, )
|
||||
{
|
||||
head = 0;
|
||||
instance = pScene.instances[pOffsets.instanceOffset + groupID];
|
||||
mesh = pScene.meshData[pOffsets.instanceOffset + groupID];
|
||||
p.instanceId = pOffsets.instanceOffset + groupID;
|
||||
p.meshletOffset = mesh.meshletOffset;
|
||||
p.cullingOffset = pScene.cullingOffsets[p.instanceId];
|
||||
modelViewProjection = mul(mul(pViewParams.projectionMatrix, pViewParams.viewMatrix), instance.transformMatrix);
|
||||
float3 origin = viewToModel(instance.inverseTransformMatrix, float4(0, 0, 0, 1)).xyz;
|
||||
const float offset = 0.0f;
|
||||
float3 corners[4] = {
|
||||
screenToModel(instance.inverseTransformMatrix, float4(offset, offset, -1.0f, 1.0f)).xyz,
|
||||
screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions.x - offset, offset, -1.0f, 1.0f)).xyz,
|
||||
screenToModel(instance.inverseTransformMatrix, float4(offset, pViewParams.screenDimensions.y - offset, -1.0f, 1.0f)).xyz,
|
||||
screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions - float2(offset, offset), -1.0f, 1.0f)).xyz
|
||||
};
|
||||
viewFrustum.sides[0] = computePlane(origin, corners[2], corners[0]);
|
||||
viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]);
|
||||
viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]);
|
||||
viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]);
|
||||
meshVisible = mesh.bounding.insideFrustum(viewFrustum) && isBoxVisible(mesh.bounding);
|
||||
//meshVisible = true;
|
||||
|
||||
if(threadID == 0)
|
||||
{
|
||||
head = 0;
|
||||
instance = pScene.instances[pOffsets.instanceOffset + groupID];
|
||||
mesh = pScene.meshData[pOffsets.instanceOffset + groupID];
|
||||
p.instanceId = pOffsets.instanceOffset + groupID;
|
||||
p.meshletOffset = mesh.meshletOffset;
|
||||
p.cullingOffset = pScene.cullingOffsets[p.instanceId];
|
||||
modelViewProjection = mul(mul(pViewParams.projectionMatrix, pViewParams.viewMatrix), instance.transformMatrix);
|
||||
float3 origin = viewToModel(instance.inverseTransformMatrix, float4(0, 0, 0, 1)).xyz;
|
||||
const float offset = 0.0f;
|
||||
float3 corners[4] = {
|
||||
screenToModel(instance.inverseTransformMatrix, float4(offset, offset, -1.0f, 1.0f)).xyz,
|
||||
screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions.x - offset, offset, -1.0f, 1.0f)).xyz,
|
||||
screenToModel(instance.inverseTransformMatrix, float4(offset, pViewParams.screenDimensions.y - offset, -1.0f, 1.0f)).xyz,
|
||||
screenToModel(instance.inverseTransformMatrix, float4(pViewParams.screenDimensions - float2(offset, offset), -1.0f, 1.0f)).xyz
|
||||
};
|
||||
viewFrustum.sides[0] = computePlane(origin, corners[2], corners[0]);
|
||||
viewFrustum.sides[1] = computePlane(origin, corners[1], corners[3]);
|
||||
viewFrustum.sides[2] = computePlane(origin, corners[0], corners[1]);
|
||||
viewFrustum.sides[3] = computePlane(origin, corners[3], corners[2]);
|
||||
//meshVisible = mesh.bounding.insideFrustum(viewFrustum) && isBoxVisible(mesh.bounding);
|
||||
meshVisible = true;
|
||||
}
|
||||
GroupMemoryBarrierWithGroupSync();
|
||||
if(!meshVisible)
|
||||
{
|
||||
|
||||
@@ -5,57 +5,51 @@ ParameterBlock<DepthData> pDepthAttachment;
|
||||
|
||||
struct MipParam
|
||||
{
|
||||
uint srcMipOffset;
|
||||
uint dstMipOffset;
|
||||
uint2 srcMipDim;
|
||||
uint2 dstMipDim;
|
||||
uint sourceOffset;
|
||||
uint destOffset;
|
||||
uint2 sourceDim;
|
||||
uint2 destDim;
|
||||
}
|
||||
layout(push_constant)
|
||||
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")]
|
||||
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
|
||||
void reduceLevel(
|
||||
uint3 threadID: SV_GroupThreadID,
|
||||
uint3 groupID: SV_GroupID,
|
||||
){
|
||||
uint2 minCoords = (groupID.xy * BLOCK_SIZE + threadID.xy) * 2;
|
||||
|
||||
if(minCoords.x >= pMipParam.srcMipDim.x || minCoords.y >= pMipParam.srcMipDim.y)
|
||||
uint2 dispatchID: SV_DispatchThreadID,
|
||||
) {
|
||||
if(dispatchID.x >= pMipParam.destDim.x || dispatchID.y >= pMipParam.destDim.y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
uint2 maxCoords = uint2(min(minCoords.x + 1, pMipParam.srcMipDim.x - 1), min(minCoords.y + 1, pMipParam.srcMipDim.y - 1));
|
||||
|
||||
float d0 = getSrcDepth(uint2(minCoords.x, minCoords.y));
|
||||
float d1 = getSrcDepth(uint2(maxCoords.x, minCoords.y));
|
||||
float d2 = getSrcDepth(uint2(minCoords.x, maxCoords.y));
|
||||
float d3 = getSrcDepth(uint2(maxCoords.x, maxCoords.y));
|
||||
|
||||
float minDepth = min(min(d0, d1), min(d2, d3));
|
||||
setDstDepth(minCoords / 2, minDepth);
|
||||
uint2 readOffset = dispatchID * 2;
|
||||
float d0 = readBuffer(readOffset + uint2(0, 0));
|
||||
float d1 = readBuffer(readOffset + uint2(0, 1));
|
||||
float d2 = readBuffer(readOffset + uint2(1, 0));
|
||||
float d3 = readBuffer(readOffset + uint2(1, 1));
|
||||
pDepthAttachment.buffer[pMipParam.destOffset + dispatchID.x + (dispatchID.y * pMipParam.destDim.x)] = min(min(d0, d1), min(d2, d3));
|
||||
}
|
||||
|
||||
[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")]
|
||||
void initialReduce(
|
||||
uint3 threadID: SV_GroupThreadID,
|
||||
uint3 groupID: SV_GroupID,
|
||||
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
|
||||
void sourceCopy(
|
||||
uint2 dispatchID: SV_DispatchThreadID
|
||||
) {
|
||||
uint width = uint(pViewParams.screenDimensions.x);
|
||||
int2 groupOffset = groupID.xy * BLOCK_SIZE;
|
||||
int2 texCoord = groupOffset + threadID.xy;
|
||||
float fDepth = pDepthAttachment.texture.Load(int3(texCoord, 0)).r;
|
||||
pDepthAttachment.buffer[texCoord.x + (texCoord.y * width)] = fDepth;
|
||||
if(dispatchID.x >= pViewParams.screenDimensions.x || dispatchID.y >= pViewParams.screenDimensions.y)
|
||||
{
|
||||
return;
|
||||
}
|
||||
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 pz = 0 - 1;
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user