Trying to fix everything
This commit is contained in:
@@ -31,7 +31,7 @@ VertexOutput vert(VertexInput input)
|
|||||||
|
|
||||||
// Which vertex should be read?
|
// Which vertex should be read?
|
||||||
local_vert_id = local_vert_id == 0 ? 2 : (local_vert_id == 2 ? 0 : 1);
|
local_vert_id = local_vert_id == 0 ? 2 : (local_vert_id == 2 ? 0 : 1);
|
||||||
float3 positionRWS = pParams.currentVertexBuffer[output.triangleID * 3 + local_vert_id];
|
float3 positionRWS = pParams.currentVertexBuffer[output.triangleID * 3 + local_vert_id].xyz;
|
||||||
|
|
||||||
// Apply the view projection
|
// Apply the view projection
|
||||||
output.positionCS = mul(pViewParams.projectionMatrix, mul(pViewParams.viewMatrix, float4(positionRWS, 1.0)));
|
output.positionCS = mul(pViewParams.projectionMatrix, mul(pViewParams.viewMatrix, float4(positionRWS, 1.0)));
|
||||||
@@ -53,26 +53,25 @@ float4 frag(PixelInput input) : SV_Target
|
|||||||
|
|
||||||
[shader("compute")]
|
[shader("compute")]
|
||||||
[numthreads(64, 1, 1)]
|
[numthreads(64, 1, 1)]
|
||||||
void deform(uint currentID: SV_DispatchThreadID)
|
void EvaluateDeformation(uint currentID : SV_DispatchThreadID)
|
||||||
{
|
{
|
||||||
if(currentID >= pParams.indirectDrawBuffer[9] * 4)
|
// This thread doesn't have any work to do, we're done
|
||||||
|
if (currentID >= pParams.indirectDrawBuffer[9] * 4)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Extract the bisector ID and the vertexID
|
||||||
uint bisectorID = currentID / 4;
|
uint bisectorID = currentID / 4;
|
||||||
uint localVertexID = currentID % 4;
|
uint localVertexID = currentID % 4;
|
||||||
|
|
||||||
|
// Operate the indirection
|
||||||
bisectorID = pParams.indexedBisectorBuffer[bisectorID];
|
bisectorID = pParams.indexedBisectorBuffer[bisectorID];
|
||||||
|
|
||||||
|
// Evaluate the source vertex
|
||||||
currentID = localVertexID < 3 ? bisectorID * 3 + localVertexID : 3 * pParams.geometry.totalNumElements + bisectorID;
|
currentID = localVertexID < 3 ? bisectorID * 3 + localVertexID : 3 * pParams.geometry.totalNumElements + bisectorID;
|
||||||
|
|
||||||
float3 positionWS = pParams.lebPositionBuffer[currentID];
|
// Grab the position that we will be displacing
|
||||||
float3 positionRWS = positionWS - pViewParams.cameraPosition_WS.xyz;
|
float3 positionWS = pParams.lebPositionBuffer[currentID].xyz;
|
||||||
|
float3 positionRWS = float3(positionWS - pViewParams.cameraPosition_WS.xyz);
|
||||||
|
|
||||||
float3 positionPS = positionWS;
|
pParams.currentVertexBuffer[currentID] = float4(positionRWS, 1);
|
||||||
|
}
|
||||||
float3 normalPS = float3(0, 1, 0);
|
|
||||||
|
|
||||||
float2 sampleUV = float2(0, 0);
|
|
||||||
|
|
||||||
pParams.currentVertexBuffer[currentID] = positionRWS;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ const static int MODIFIED_BISECTOR = 0x2;
|
|||||||
|
|
||||||
struct BisectorData
|
struct BisectorData
|
||||||
{
|
{
|
||||||
// Subvision that should be applied to this bisector
|
|
||||||
uint32_t subdivisionPattern;
|
|
||||||
|
|
||||||
// Allocated indices for this bisector
|
// Allocated indices for this bisector
|
||||||
uint32_t indices[3];
|
uint32_t indices[3];
|
||||||
|
|
||||||
|
// Subvision that should be applied to this bisector
|
||||||
|
uint32_t subdivisionPattern;
|
||||||
|
|
||||||
// Neighbor that should be processed
|
// Neighbor that should be processed
|
||||||
uint32_t problematicNeighbor;
|
uint32_t problematicNeighbor;
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ struct BisectorData
|
|||||||
uint32_t propagationID;
|
uint32_t propagationID;
|
||||||
};
|
};
|
||||||
|
|
||||||
uint heapIDDepth(uint64_t x)
|
uint HeapIDDepth(uint64_t x)
|
||||||
{
|
{
|
||||||
uint depth = 0;
|
uint depth = 0;
|
||||||
while (x > 0u) {
|
while (x > 0u) {
|
||||||
|
|||||||
@@ -563,11 +563,7 @@ void load_buffer_to_shared_memory(uint groupIndex)
|
|||||||
// Load the bitfield to the LDS
|
// Load the bitfield to the LDS
|
||||||
for (uint e = 0; e < BUFFER_ELEMENT_PER_LANE; ++e)
|
for (uint e = 0; e < BUFFER_ELEMENT_PER_LANE; ++e)
|
||||||
{
|
{
|
||||||
#ifdef AMD
|
|
||||||
uint target_element = BUFFER_ELEMENT_PER_LANE * groupIndex + e;
|
uint target_element = BUFFER_ELEMENT_PER_LANE * groupIndex + e;
|
||||||
#else
|
|
||||||
uint target_element = groupIndex + WORKGROUP_SIZE * e;
|
|
||||||
#endif
|
|
||||||
if (target_element < OCBT_TREE_NUM_SLOTS)
|
if (target_element < OCBT_TREE_NUM_SLOTS)
|
||||||
gs_cbtTree[target_element] = pParams.cbtBuffer[target_element];
|
gs_cbtTree[target_element] = pParams.cbtBuffer[target_element];
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
struct ComputeParams
|
||||||
|
{
|
||||||
|
RWStructuredBuffer<uint> indirectDrawBuffer;
|
||||||
|
RWStructuredBuffer<uint64_t> heapIDBuffer;
|
||||||
|
RWStructuredBuffer<uint> classificationBuffer;
|
||||||
|
RWStructuredBuffer<int> allocateBuffer;
|
||||||
|
RWStructuredBuffer<int> memoryBuffer;
|
||||||
|
RWStructuredBuffer<int> propagateBuffer;
|
||||||
|
RWStructuredBuffer<uint> simplifyBuffer;
|
||||||
|
};
|
||||||
|
ParameterBlock<ComputeParams> pParams;
|
||||||
|
|
||||||
|
// Split buffer slots
|
||||||
|
static const uint64_t SPLIT_COUNTER = 0;
|
||||||
|
static const uint64_t SIMPLIFY_COUNTER = 1;
|
||||||
|
static const uint64_t CLASSIFY_COUNTER_OFFSET = 2;
|
||||||
|
void ResetBuffers()
|
||||||
|
{
|
||||||
|
pParams.memoryBuffer[0] = 0;
|
||||||
|
pParams.memoryBuffer[1] = 0;
|
||||||
|
|
||||||
|
pParams.classificationBuffer[SPLIT_COUNTER] = 0;
|
||||||
|
pParams.classificationBuffer[SIMPLIFY_COUNTER] = 0;
|
||||||
|
|
||||||
|
pParams.allocateBuffer[0] = 0;
|
||||||
|
|
||||||
|
pParams.propagateBuffer[0] = 0;
|
||||||
|
pParams.propagateBuffer[1] = 0;
|
||||||
|
|
||||||
|
pParams.simplifyBuffer[0] = 0;
|
||||||
|
|
||||||
|
pParams.indirectDrawBuffer[0] = 0;
|
||||||
|
pParams.indirectDrawBuffer[1] = 1;
|
||||||
|
pParams.indirectDrawBuffer[2] = 0;
|
||||||
|
pParams.indirectDrawBuffer[3] = 0;
|
||||||
|
|
||||||
|
pParams.indirectDrawBuffer[4] = 0;
|
||||||
|
pParams.indirectDrawBuffer[5] = 1;
|
||||||
|
pParams.indirectDrawBuffer[6] = 0;
|
||||||
|
pParams.indirectDrawBuffer[7] = 0;
|
||||||
|
|
||||||
|
pParams.indirectDrawBuffer[8] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
[numthreads(1, 1, 1)]
|
||||||
|
void Reset()
|
||||||
|
{
|
||||||
|
ResetBuffers();
|
||||||
|
}
|
||||||
@@ -0,0 +1,332 @@
|
|||||||
|
import Parameters;
|
||||||
|
import CBT;
|
||||||
|
import Bisector;
|
||||||
|
|
||||||
|
static const uint32_t WORKGROUP_SIZE = 64;
|
||||||
|
|
||||||
|
// Resolution of the cache
|
||||||
|
#define LEB_TABLE_DEPTH 5ULL
|
||||||
|
|
||||||
|
// Cache in shared memory
|
||||||
|
groupshared float3x3 g_MatrixCache[2ULL << LEB_TABLE_DEPTH];
|
||||||
|
|
||||||
|
void load_leb_matrix_cache_to_shared_memory(uint groupIndex)
|
||||||
|
{
|
||||||
|
if (groupIndex < (2ULL << LEB_TABLE_DEPTH))
|
||||||
|
g_MatrixCache[groupIndex] = pParams.lebMatrixCache[groupIndex];
|
||||||
|
GroupMemoryBarrierWithGroupSync();
|
||||||
|
}
|
||||||
|
uint leb_depth(uint64_t heapID)
|
||||||
|
{
|
||||||
|
uint depth = 0;
|
||||||
|
while (heapID > 0u)
|
||||||
|
{
|
||||||
|
++depth;
|
||||||
|
heapID >>= 1u;
|
||||||
|
}
|
||||||
|
return depth - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* GetBitValue -- Returns the value of a bit stored in a 64-bit word
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint64_t leb__GetBitValue(uint64_t bitField, int64_t bitID)
|
||||||
|
{
|
||||||
|
return ((bitField >> bitID) & 1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* IdentityMatrix3x3 -- Sets a 3x3 matrix to identity
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void leb__IdentityMatrix3x3(out float3x3 m)
|
||||||
|
{
|
||||||
|
m[0][0] = 1.0f; m[0][1] = 0.0f; m[0][2] = 0.0f;
|
||||||
|
m[1][0] = 0.0f; m[1][1] = 1.0f; m[1][2] = 0.0f;
|
||||||
|
m[2][0] = 0.0f; m[2][1] = 0.0f; m[2][2] = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* SplittingMatrix -- Computes a LEB splitting matrix from a split bit
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void leb__SplittingMatrix(inout float3x3 mat, uint64_t bitValue)
|
||||||
|
{
|
||||||
|
float b = (float)bitValue;
|
||||||
|
float c = 1.0f - b;
|
||||||
|
const float3x3 splitMatrix = {
|
||||||
|
{0.0f, b, c},
|
||||||
|
{0.5f, 0.0f, 0.5f},
|
||||||
|
{b, c, 0.0f}
|
||||||
|
};
|
||||||
|
mat = mul(splitMatrix, mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* SplittingMatrix -- Computes a LEB splitting matrix from a split bit
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
float3x3 leb__SplittingMatrix_out(float3x3 mat, uint64_t bitValue)
|
||||||
|
{
|
||||||
|
float b = (float)bitValue;
|
||||||
|
float c = 1.0 - b;
|
||||||
|
float3x3 splitMatrix = {
|
||||||
|
{0.0, b, c},
|
||||||
|
{0.5, 0.0, 0.5},
|
||||||
|
{b, c, 0.0}
|
||||||
|
};
|
||||||
|
return mul(splitMatrix, mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* DecodeTransformationMatrix -- Computes the matrix associated to a LEB
|
||||||
|
* node
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void leb__DecodeTransformationMatrix(uint64_t heapID, out float3x3 mat)
|
||||||
|
{
|
||||||
|
int depth = leb_depth(heapID);
|
||||||
|
leb__IdentityMatrix3x3(mat);
|
||||||
|
for (int bitID = depth - 1; bitID >= 0; --bitID)
|
||||||
|
leb__SplittingMatrix(mat, leb__GetBitValue(heapID, bitID));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(LEB_MATRIX_CACHE_BINDING_SLOT)
|
||||||
|
void leb__DecodeTransformationMatrix_Tabulated(uint64_t heapID, out float3x3 mat)
|
||||||
|
{
|
||||||
|
leb__IdentityMatrix3x3(mat);
|
||||||
|
const uint64_t msb = (1ULL << LEB_TABLE_DEPTH);
|
||||||
|
const uint64_t mask = ~(~0ULL << LEB_TABLE_DEPTH);
|
||||||
|
while (heapID > mask)
|
||||||
|
{
|
||||||
|
uint32_t index = uint32_t((heapID & mask) | msb);
|
||||||
|
mat = mul(mat, g_MatrixCache[index]);
|
||||||
|
heapID >>= LEB_TABLE_DEPTH;
|
||||||
|
}
|
||||||
|
mat = mul(mat, g_MatrixCache[uint32_t(heapID)]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* DecodeTransformationMatrix -- Computes the matrix associated to a LEB
|
||||||
|
* node
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void leb__DecodeTransformationMatrix_parent_child(uint64_t heapID, out float3x3 parent, out float3x3 child)
|
||||||
|
{
|
||||||
|
int depth = leb_depth(heapID);
|
||||||
|
leb__IdentityMatrix3x3(parent);
|
||||||
|
|
||||||
|
// Evaluate the parent matrix
|
||||||
|
int bitID;
|
||||||
|
for (bitID = depth - 1; bitID > 0; --bitID)
|
||||||
|
leb__SplittingMatrix(parent, leb__GetBitValue(heapID, bitID));
|
||||||
|
|
||||||
|
// Evaluate the child
|
||||||
|
if (depth > 0)
|
||||||
|
child = leb__SplittingMatrix_out(parent, leb__GetBitValue(heapID, bitID));
|
||||||
|
else
|
||||||
|
child = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(LEB_MATRIX_CACHE_BINDING_SLOT)
|
||||||
|
void leb__DecodeTransformationMatrix_parent_child_Tabulated(uint64_t heapID, out float3x3 parent, out float3x3 child)
|
||||||
|
{
|
||||||
|
int depth = leb_depth(heapID);
|
||||||
|
leb__IdentityMatrix3x3(parent);
|
||||||
|
const uint64_t msb = (1ULL << LEB_TABLE_DEPTH);
|
||||||
|
const uint64_t mask = ~(~0ULL << LEB_TABLE_DEPTH);
|
||||||
|
uint64_t parentHeapID = heapID / 2;
|
||||||
|
while (parentHeapID > mask)
|
||||||
|
{
|
||||||
|
uint32_t index = uint32_t((parentHeapID & mask) | msb);
|
||||||
|
parent = mul(parent, g_MatrixCache[index]);
|
||||||
|
parentHeapID >>= LEB_TABLE_DEPTH;
|
||||||
|
}
|
||||||
|
if (parentHeapID != 0)
|
||||||
|
parent = mul(parent, g_MatrixCache[uint32_t(parentHeapID)]);
|
||||||
|
|
||||||
|
// Evaluate the child
|
||||||
|
if (depth > 0)
|
||||||
|
child = leb__SplittingMatrix_out(parent, leb__GetBitValue(heapID, 0));
|
||||||
|
else
|
||||||
|
child = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* DecodeNodeAttributeArray -- Compute the triangle attributes at the input node
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void leb_DecodeNodeAttributeArray(uint64_t heapID, inout float3 attributeArray[2])
|
||||||
|
{
|
||||||
|
float3x3 m;
|
||||||
|
leb__DecodeTransformationMatrix(heapID, m);
|
||||||
|
for (int i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
float3 attributeVector = attributeArray[i];
|
||||||
|
attributeArray[i][0] = dot(m[0], attributeVector);
|
||||||
|
attributeArray[i][1] = dot(m[1], attributeVector);
|
||||||
|
attributeArray[i][2] = dot(m[2], attributeVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void leb_DecodeNodeAttributeArray(uint64_t heapID, inout float3 attributeArray[3])
|
||||||
|
{
|
||||||
|
float3x3 m;
|
||||||
|
#if defined(LEB_MATRIX_CACHE_BINDING_SLOT)
|
||||||
|
leb__DecodeTransformationMatrix_Tabulated(heapID, m);
|
||||||
|
#else
|
||||||
|
leb__DecodeTransformationMatrix(heapID, m);
|
||||||
|
#endif
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
float3 attributeVector = attributeArray[i];
|
||||||
|
attributeArray[i][0] = dot(m[0], attributeVector);
|
||||||
|
attributeArray[i][1] = dot(m[1], attributeVector);
|
||||||
|
attributeArray[i][2] = dot(m[2], attributeVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* DecodeNodeAttributeArray -- Compute the triangle attributes at the input node
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void leb_DecodeNodeAttributeArray_parent_child(uint64_t heapID, inout float3 childAttribute[3], out float3 parentAttribute[3])
|
||||||
|
{
|
||||||
|
float3x3 child, parent;
|
||||||
|
#if defined(LEB_MATRIX_CACHE_BINDING_SLOT)
|
||||||
|
leb__DecodeTransformationMatrix_parent_child_Tabulated(heapID, parent, child);
|
||||||
|
#else
|
||||||
|
leb__DecodeTransformationMatrix_parent_child(heapID, parent, child);
|
||||||
|
#endif
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
float3 attributeVector = childAttribute[i];
|
||||||
|
parentAttribute[i][0] = dot(parent[0], attributeVector);
|
||||||
|
parentAttribute[i][1] = dot(parent[1], attributeVector);
|
||||||
|
parentAttribute[i][2] = dot(parent[2], attributeVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
float3 attributeVector = childAttribute[i];
|
||||||
|
childAttribute[i][0] = dot(child[0], attributeVector);
|
||||||
|
childAttribute[i][1] = dot(child[1], attributeVector);
|
||||||
|
childAttribute[i][2] = dot(child[2], attributeVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[numthreads(WORKGROUP_SIZE, 1, 1)]
|
||||||
|
void ClearBuffer(uint currentID : SV_DispatchThreadID)
|
||||||
|
{
|
||||||
|
// This thread doesn't have any work to do, we're done
|
||||||
|
if (currentID >= pParams.geometry.totalNumVertices)
|
||||||
|
return;
|
||||||
|
pParams.lebPositionBuffer[currentID] = float4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 TransformToPlanetCoordinate(float3 posPS)
|
||||||
|
{
|
||||||
|
// Evaluate the planet position
|
||||||
|
return normalize(posPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[vk::push_constant]]
|
||||||
|
ConstantBuffer<uint> preRendering;
|
||||||
|
struct Triangle
|
||||||
|
{
|
||||||
|
float3 p[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
void EvaluateElementPosition(uint64_t heapID, uint32_t vertexDataOffset, uint minDepth, RWStructuredBuffer<float4> vertexBuffer, out Triangle parentTri, out Triangle childTri)
|
||||||
|
{
|
||||||
|
// Get the depth of the element
|
||||||
|
uint depth = HeapIDDepth(heapID);
|
||||||
|
|
||||||
|
// Compute the required shift to find the original vertices
|
||||||
|
uint64_t subTreeDepth = depth - minDepth;
|
||||||
|
|
||||||
|
// Compute the base heapID
|
||||||
|
uint64_t baseHeapID = 1u << (minDepth - 1);
|
||||||
|
uint primitiveID = uint((heapID >> subTreeDepth) - baseHeapID);
|
||||||
|
|
||||||
|
// Grab the base positions of the element
|
||||||
|
float3 p0 = float3(vertexBuffer[3 * primitiveID + vertexDataOffset].xyz);
|
||||||
|
float3 p1 = float3(vertexBuffer[3 * primitiveID + 1 + vertexDataOffset].xyz);
|
||||||
|
float3 p2 = float3(vertexBuffer[3 * primitiveID + 2 + vertexDataOffset].xyz);
|
||||||
|
|
||||||
|
// Heap ID in the sub triangle
|
||||||
|
uint64_t mask = subTreeDepth != 0uL ? 0xFFFFFFFFFFFFFFFFull >> (64ull - subTreeDepth) : 0ull;
|
||||||
|
uint64_t baseHeap = (1ull << subTreeDepth);
|
||||||
|
uint64_t baseMask = (mask & heapID);
|
||||||
|
uint64_t subHeapID = baseMask + baseHeap;
|
||||||
|
|
||||||
|
// Generate the triangle positions
|
||||||
|
float3 childArray[3] = {{p0.x, p1.x, p2.x}, {p0.y, p1.y, p2.y}, {p0.z, p1.z, p2.z}};
|
||||||
|
float3 parentArray[3];
|
||||||
|
|
||||||
|
// Decode
|
||||||
|
leb_DecodeNodeAttributeArray_parent_child(subHeapID, childArray, parentArray);
|
||||||
|
|
||||||
|
// Fill the parent triangle
|
||||||
|
parentTri.p[0] = float3(parentArray[0][0], parentArray[1][0], parentArray[2][0]);
|
||||||
|
parentTri.p[1] = float3(parentArray[0][1], parentArray[1][1], parentArray[2][1]);
|
||||||
|
parentTri.p[2] = float3(parentArray[0][2], parentArray[1][2], parentArray[2][2]);
|
||||||
|
|
||||||
|
// Fill the child triangle
|
||||||
|
Triangle child;
|
||||||
|
childTri.p[0] = float3(childArray[0][0], childArray[1][0], childArray[2][0]);
|
||||||
|
childTri.p[1] = float3(childArray[0][1], childArray[1][1], childArray[2][1]);
|
||||||
|
childTri.p[2] = float3(childArray[0][2], childArray[1][2], childArray[2][2]);
|
||||||
|
}
|
||||||
|
[numthreads(WORKGROUP_SIZE, 1, 1)]
|
||||||
|
void EvaluateLEB(uint currentID : SV_DispatchThreadID, uint groupIndex: SV_GroupIndex)
|
||||||
|
{
|
||||||
|
#if defined(LEB_MATRIX_CACHE_BINDING_SLOT)
|
||||||
|
// Make sure these are loaded to the shared memory
|
||||||
|
load_leb_matrix_cache_to_shared_memory(groupIndex);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This thread doesn't have any work to do, we're done
|
||||||
|
uint32_t numBisectors = bool(preRendering) ? (pParams.indirectDrawBuffer[9]) : (pParams.indirectDrawBuffer[8] / 4);
|
||||||
|
if (currentID >= numBisectors)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Load the bisector for this element
|
||||||
|
currentID = pParams.indexedBisectorBuffer[currentID];
|
||||||
|
|
||||||
|
// Evaluate the depth of the element
|
||||||
|
uint64_t cHeapID = pParams.heapIDBuffer[currentID];
|
||||||
|
uint depth = HeapIDDepth(cHeapID);
|
||||||
|
|
||||||
|
// Evaluate the positions of the current element
|
||||||
|
Triangle parentTri, childTri;
|
||||||
|
EvaluateElementPosition(cHeapID, 0, pParams.geometry.baseDepth, pParams.currentVertexBuffer, parentTri, childTri);
|
||||||
|
|
||||||
|
// Export the child
|
||||||
|
pParams.lebPositionBuffer[3 * currentID] = float4(TransformToPlanetCoordinate(childTri.p[0]), 1.0f);
|
||||||
|
pParams.lebPositionBuffer[3 * currentID + 1] = float4(TransformToPlanetCoordinate(childTri.p[1]), 1.0f);
|
||||||
|
pParams.lebPositionBuffer[3 * currentID + 2] = float4(TransformToPlanetCoordinate(childTri.p[2]), 1.0f);
|
||||||
|
|
||||||
|
// Export the fourth element
|
||||||
|
if (pParams.geometry.baseDepth < depth)
|
||||||
|
{
|
||||||
|
// Offset for the parent buffer
|
||||||
|
const uint parentOffset = 3 * pParams.geometry.totalNumElements;
|
||||||
|
|
||||||
|
// Transform the coordinate to planet space
|
||||||
|
pParams.lebPositionBuffer[parentOffset + currentID] = float4(TransformToPlanetCoordinate(cHeapID % 2 == 0 ? parentTri.p[0] : parentTri.p[2]), 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ struct DeformationCB
|
|||||||
|
|
||||||
struct UpdateCB
|
struct UpdateCB
|
||||||
{
|
{
|
||||||
|
float4x4 viewProjectionMatrix;
|
||||||
float triangleSize;
|
float triangleSize;
|
||||||
uint32_t maxSubdivisionDepth;
|
uint32_t maxSubdivisionDepth;
|
||||||
float fov;
|
float fov;
|
||||||
@@ -28,12 +29,8 @@ struct UpdateCB
|
|||||||
|
|
||||||
struct DebugStruct
|
struct DebugStruct
|
||||||
{
|
{
|
||||||
float4 sourceP[3];
|
uint3 neighbours;
|
||||||
float2 areaP[3];
|
int status;
|
||||||
float area;
|
|
||||||
int validity;
|
|
||||||
float fDotV;
|
|
||||||
float vDotN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ComputeParams
|
struct ComputeParams
|
||||||
@@ -41,7 +38,7 @@ struct ComputeParams
|
|||||||
ConstantBuffer<GeometryCB> geometry;
|
ConstantBuffer<GeometryCB> geometry;
|
||||||
ConstantBuffer<UpdateCB> update;
|
ConstantBuffer<UpdateCB> update;
|
||||||
|
|
||||||
RWStructuredBuffer<float3> currentVertexBuffer;
|
RWStructuredBuffer<float4> currentVertexBuffer;
|
||||||
StructuredBuffer<uint> indexedBisectorBuffer;
|
StructuredBuffer<uint> indexedBisectorBuffer;
|
||||||
RWStructuredBuffer<uint> indirectDrawBuffer;
|
RWStructuredBuffer<uint> indirectDrawBuffer;
|
||||||
RWStructuredBuffer<uint64_t> heapIDBuffer;
|
RWStructuredBuffer<uint64_t> heapIDBuffer;
|
||||||
@@ -49,8 +46,8 @@ struct ComputeParams
|
|||||||
RWStructuredBuffer<uint> classificationBuffer;
|
RWStructuredBuffer<uint> classificationBuffer;
|
||||||
RWStructuredBuffer<int> allocateBuffer;
|
RWStructuredBuffer<int> allocateBuffer;
|
||||||
RWStructuredBuffer<uint> indirectDispatchBuffer;
|
RWStructuredBuffer<uint> indirectDispatchBuffer;
|
||||||
RWStructuredBuffer<uint3> neighboursBuffer;
|
RWStructuredBuffer<uint4> neighboursBuffer;
|
||||||
RWStructuredBuffer<uint3> neighboursOutputBuffer;
|
RWStructuredBuffer<uint4> neighboursOutputBuffer;
|
||||||
RWStructuredBuffer<int> memoryBuffer;
|
RWStructuredBuffer<int> memoryBuffer;
|
||||||
RWStructuredBuffer<uint> cbtBuffer;
|
RWStructuredBuffer<uint> cbtBuffer;
|
||||||
RWStructuredBuffer<uint64_t> bitFieldBuffer;
|
RWStructuredBuffer<uint64_t> bitFieldBuffer;
|
||||||
@@ -60,7 +57,7 @@ struct ComputeParams
|
|||||||
RWStructuredBuffer<uint> bisectorIndicesBuffer;
|
RWStructuredBuffer<uint> bisectorIndicesBuffer;
|
||||||
RWStructuredBuffer<uint> visibleBisectorIndices;
|
RWStructuredBuffer<uint> visibleBisectorIndices;
|
||||||
RWStructuredBuffer<uint> modifiedBisectorIndices;
|
RWStructuredBuffer<uint> modifiedBisectorIndices;
|
||||||
RWStructuredBuffer<float3> lebPositionBuffer;
|
RWStructuredBuffer<float4> lebPositionBuffer;
|
||||||
StructuredBuffer<float3x3> lebMatrixCache;
|
StructuredBuffer<float3x3> lebMatrixCache;
|
||||||
RWStructuredBuffer<DebugStruct> debugBuffer;
|
RWStructuredBuffer<DebugStruct> debugBuffer;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,966 @@
|
|||||||
|
import Common;
|
||||||
|
import Bisector;
|
||||||
|
import CBT;
|
||||||
|
import Parameters;
|
||||||
|
|
||||||
|
// Needs to be defined before including update_utilities
|
||||||
|
struct BisectorGeometry
|
||||||
|
{
|
||||||
|
float3 p[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Possible splits
|
||||||
|
static const uint64_t NO_SPLIT = 0x00;
|
||||||
|
static const uint64_t CENTER_SPLIT = 0x01;
|
||||||
|
static const uint64_t RIGHT_SPLIT = 0x02;
|
||||||
|
static const uint64_t LEFT_SPLIT = 0x04;
|
||||||
|
static const uint64_t RIGHT_DOUBLE_SPLIT = (CENTER_SPLIT | RIGHT_SPLIT);
|
||||||
|
static const uint64_t LEFT_DOUBLE_SPLIT = (CENTER_SPLIT | LEFT_SPLIT);
|
||||||
|
static const uint64_t TRIPLE_SPLIT = (CENTER_SPLIT | RIGHT_SPLIT | LEFT_SPLIT);
|
||||||
|
|
||||||
|
// Split buffer slots
|
||||||
|
static const uint64_t SPLIT_COUNTER = 0;
|
||||||
|
static const uint64_t SIMPLIFY_COUNTER = 1;
|
||||||
|
static const uint64_t CLASSIFY_COUNTER_OFFSET = 2;
|
||||||
|
|
||||||
|
int ClassifyBisector(in BisectorGeometry tri, uint depth)
|
||||||
|
{
|
||||||
|
// Check the triangle's visibility
|
||||||
|
float3 triNormal = normalize(cross(tri.p[2] - tri.p[1], tri.p[0] - tri.p[1]));
|
||||||
|
float3 triCenter = (tri.p[0] + tri.p[1] + tri.p[2]) / 3.0;
|
||||||
|
float3 viewDir = normalize(-triCenter);
|
||||||
|
float FdotV = dot(viewDir, pViewParams.cameraForward_WS.xyz);
|
||||||
|
float VdotN = dot(viewDir, triNormal);
|
||||||
|
|
||||||
|
// Here we don't use 0 as it introduces stability issues at grazing angles
|
||||||
|
if (FdotV < 0.0 && VdotN < -1e-3)
|
||||||
|
return BACK_FACE_CULLED;
|
||||||
|
|
||||||
|
// Compute the triangle's AABB
|
||||||
|
float3 aabbMin = float3(min(min(tri.p[0].x, tri.p[1].x), tri.p[2].x), min(min(tri.p[0].y, tri.p[1].y), tri.p[2].y), min(min(tri.p[0].z, tri.p[1].z), tri.p[2].z));
|
||||||
|
float3 aabbMax = float3(max(max(tri.p[0].x, tri.p[1].x), tri.p[2].x), max(max(tri.p[0].y, tri.p[1].y), tri.p[2].y), max(max(tri.p[0].z, tri.p[1].z), tri.p[2].z));
|
||||||
|
|
||||||
|
// First we do a frustum culling pass
|
||||||
|
//if (!FrustumAABBIntersect(_FrustumPlanes, aabbMin, aabbMax))
|
||||||
|
// return FRUSTUM_CULLED;
|
||||||
|
|
||||||
|
// Project the points on screen
|
||||||
|
float4x4 viewProjectionMatrix = mul(pViewParams.projectionMatrix, pViewParams.viewMatrix);
|
||||||
|
float4 p0P = mul(viewProjectionMatrix, float4(tri.p[0], 1.0));
|
||||||
|
p0P.xy = p0P.xy / p0P.w;
|
||||||
|
p0P.xy = (p0P.xy * 0.5 + 0.5);
|
||||||
|
|
||||||
|
float4 p1P = mul(viewProjectionMatrix, float4(tri.p[1], 1.0));
|
||||||
|
p1P.xy = p1P.xy / p1P.w;
|
||||||
|
p1P.xy = (p1P.xy * 0.5 + 0.5);
|
||||||
|
|
||||||
|
float4 p2P = mul(viewProjectionMatrix, float4(tri.p[2], 1.0));
|
||||||
|
p2P.xy = p2P.xy / p2P.w;
|
||||||
|
p2P.xy = (p2P.xy * 0.5 + 0.5);
|
||||||
|
|
||||||
|
// 2D area of the triangle
|
||||||
|
// here we didn't reverse the sign of the y coordinate at projection time, but we simply adapted the area evaluation
|
||||||
|
// The same way we don't multiply by the screen size before, but after which is equivalent
|
||||||
|
float area = 0.5 * abs(p0P.x * (p2P.y - p1P.y) + p1P.x * (p0P.y - p2P.y) + p2P.x * (p1P.y - p0P.y));
|
||||||
|
area *= pViewParams.screenDimensions.x * pViewParams.screenDimensions.y;
|
||||||
|
|
||||||
|
// We over estimate the area at grazing angles
|
||||||
|
float areaOverestimation = lerp(2.0, 1.0, pow(VdotN, 0.2));
|
||||||
|
area *= areaOverestimation;
|
||||||
|
|
||||||
|
// If the triangle's area is bigger than the target size and the depth is not the maximal depth, subdivide
|
||||||
|
if (pParams.update.triangleSize < area && depth < pParams.update.maxSubdivisionDepth)
|
||||||
|
{
|
||||||
|
// If the area is really big, put it in high priority.
|
||||||
|
return BISECT_ELEMENT;
|
||||||
|
}
|
||||||
|
else if ((pParams.update.triangleSize * 0.5 > area) || (depth > pParams.update.maxSubdivisionDepth))
|
||||||
|
{
|
||||||
|
// Transform the parent's point
|
||||||
|
float4 p3P = mul(viewProjectionMatrix, float4(tri.p[3], 1.0));
|
||||||
|
p3P.xy = p3P.xy / p3P.w;
|
||||||
|
p3P.xy = (p3P.xy * 0.5 + 0.5);
|
||||||
|
|
||||||
|
// Evaluate the parent area
|
||||||
|
float areaParent = 0.5 * abs(p0P.x * (p2P.y - p3P.y) + p3P.x * (p0P.y - p2P.y) + p2P.x * (p3P.y - p0P.y));
|
||||||
|
areaParent *= pViewParams.screenDimensions.x * pViewParams.screenDimensions.y;
|
||||||
|
areaParent *= areaOverestimation;
|
||||||
|
|
||||||
|
// If the depth is too high (max depth changed) or the area is too
|
||||||
|
return ((pParams.update.triangleSize >= areaParent ) || (depth > pParams.update.maxSubdivisionDepth)) ? TOO_SMALL : UNCHANGED_ELEMENT;
|
||||||
|
}
|
||||||
|
return UNCHANGED_ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetBuffers()
|
||||||
|
{
|
||||||
|
pParams.memoryBuffer[0] = 0;
|
||||||
|
pParams.memoryBuffer[1] = cbt_size() - bit_count_buffer();
|
||||||
|
|
||||||
|
pParams.classificationBuffer[SPLIT_COUNTER] = 0;
|
||||||
|
pParams.classificationBuffer[SIMPLIFY_COUNTER] = 0;
|
||||||
|
|
||||||
|
pParams.allocateBuffer[0] = 0;
|
||||||
|
|
||||||
|
pParams.propagateBuffer[0] = 0;
|
||||||
|
pParams.propagateBuffer[1] = 0;
|
||||||
|
|
||||||
|
pParams.simplifyBuffer[0] = 0;
|
||||||
|
|
||||||
|
pParams.indirectDrawBuffer[0] = 0;
|
||||||
|
pParams.indirectDrawBuffer[1] = 1;
|
||||||
|
pParams.indirectDrawBuffer[2] = 0;
|
||||||
|
pParams.indirectDrawBuffer[3] = 0;
|
||||||
|
|
||||||
|
pParams.indirectDrawBuffer[4] = 0;
|
||||||
|
pParams.indirectDrawBuffer[5] = 1;
|
||||||
|
pParams.indirectDrawBuffer[6] = 0;
|
||||||
|
pParams.indirectDrawBuffer[7] = 0;
|
||||||
|
|
||||||
|
pParams.indirectDrawBuffer[8] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassifyElement(uint currentID, BisectorGeometry bis, uint totalNumElements, uint baseDepth)
|
||||||
|
{
|
||||||
|
// Evaluate the depth of the element
|
||||||
|
uint64_t heapID = pParams.heapIDBuffer[currentID];
|
||||||
|
uint depth = HeapIDDepth(heapID);
|
||||||
|
BisectorData cbisectorData = pParams.bisectorDataBuffer[currentID];
|
||||||
|
|
||||||
|
// Reset some values
|
||||||
|
cbisectorData.subdivisionPattern = 0;
|
||||||
|
cbisectorData.bisectorState = UNCHANGED_ELEMENT;
|
||||||
|
cbisectorData.problematicNeighbor = INVALID_POINTER;
|
||||||
|
cbisectorData.flags = VISIBLE_BISECTOR;
|
||||||
|
|
||||||
|
// Does this triangle intersect the circle?
|
||||||
|
int currentValidity = ClassifyBisector(bis, depth);
|
||||||
|
if (currentValidity > UNCHANGED_ELEMENT)
|
||||||
|
{
|
||||||
|
// This element should be bisected
|
||||||
|
uint targetSlot = 0;
|
||||||
|
cbisectorData.bisectorState = BISECT_ELEMENT;
|
||||||
|
InterlockedAdd(pParams.classificationBuffer[SPLIT_COUNTER], 1, targetSlot);
|
||||||
|
pParams.classificationBuffer[CLASSIFY_COUNTER_OFFSET + targetSlot] = currentID;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cbisectorData.flags = currentValidity >= TOO_SMALL ? VISIBLE_BISECTOR : 0;
|
||||||
|
|
||||||
|
// What's the validity of the father?
|
||||||
|
if (baseDepth != depth && currentValidity < UNCHANGED_ELEMENT)
|
||||||
|
{
|
||||||
|
// Mark that it requires simplification
|
||||||
|
cbisectorData.bisectorState = SIMPLIFY_ELEMENT;
|
||||||
|
|
||||||
|
// Only register it if it has an even heapID, the odd ones will be processed by the even ones
|
||||||
|
if (heapID % 2 == 0)
|
||||||
|
{
|
||||||
|
uint targetSlot = 0;
|
||||||
|
InterlockedAdd(pParams.classificationBuffer[SIMPLIFY_COUNTER], 1, targetSlot);
|
||||||
|
pParams.classificationBuffer[CLASSIFY_COUNTER_OFFSET + totalNumElements + targetSlot] = currentID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the bisector data
|
||||||
|
pParams.bisectorDataBuffer[currentID] = cbisectorData;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SplitElement(uint currentID, uint baseDepth)
|
||||||
|
{
|
||||||
|
// Get the neighbors information
|
||||||
|
uint3 cNeighbors = pParams.neighboursBuffer[currentID].xyz;
|
||||||
|
|
||||||
|
// If there is a neighbor X
|
||||||
|
if (cNeighbors.x != INVALID_POINTER)
|
||||||
|
{
|
||||||
|
// This is on the path of it's neighbor X
|
||||||
|
uint3 xNeighbors = pParams.neighboursBuffer[cNeighbors.x].xyz;
|
||||||
|
if (xNeighbors.z == currentID && pParams.bisectorDataBuffer[cNeighbors.x].bisectorState != UNCHANGED_ELEMENT)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is a neighbor Y
|
||||||
|
if (cNeighbors.y != INVALID_POINTER)
|
||||||
|
{
|
||||||
|
// This is on the path of it's neighbor Y
|
||||||
|
uint3 yNeighbors = pParams.neighboursBuffer[cNeighbors.y].xyz;
|
||||||
|
if (yNeighbors.z == currentID && pParams.bisectorDataBuffer[cNeighbors.y].bisectorState != UNCHANGED_ELEMENT)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Depth of the current triangle
|
||||||
|
uint64_t heapID = pParams.heapIDBuffer[currentID];
|
||||||
|
uint currentDepth = HeapIDDepth(heapID);
|
||||||
|
|
||||||
|
// Compute the maximal required memory for this subdivision
|
||||||
|
int maxRequiredMemory = 2 * (currentDepth - baseDepth) - 1;
|
||||||
|
|
||||||
|
// Get the twin information
|
||||||
|
uint twinID = cNeighbors.z;
|
||||||
|
|
||||||
|
// This avoid the massive over-reservation and saves a bunch of artifacts
|
||||||
|
if (twinID == INVALID_POINTER)
|
||||||
|
maxRequiredMemory = 1;
|
||||||
|
else if (pParams.neighboursBuffer[twinID].z == currentID)
|
||||||
|
maxRequiredMemory = 2;
|
||||||
|
|
||||||
|
// Try to reserve
|
||||||
|
int remainingMemory;
|
||||||
|
InterlockedAdd(pParams.memoryBuffer[1], -maxRequiredMemory, remainingMemory);
|
||||||
|
|
||||||
|
// Did someone manage to sneak-in while we were trying to pick the memory, add it back and try again
|
||||||
|
if (remainingMemory < maxRequiredMemory)
|
||||||
|
{
|
||||||
|
// Then add back the required memory and stop
|
||||||
|
InterlockedAdd(pParams.memoryBuffer[1], maxRequiredMemory, remainingMemory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's actually count the memory that we will be using
|
||||||
|
uint usedMemory = 1;
|
||||||
|
uint prevPattern;
|
||||||
|
InterlockedOr(pParams.bisectorDataBuffer[currentID].subdivisionPattern, CENTER_SPLIT, prevPattern);
|
||||||
|
|
||||||
|
// If this is not zero, it means an other neighbor went faster than us, we restore the memory and leave.
|
||||||
|
if (prevPattern != 0)
|
||||||
|
{
|
||||||
|
InterlockedAdd(pParams.memoryBuffer[1], maxRequiredMemory, remainingMemory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark this for allocation
|
||||||
|
uint targetLocation = 0;
|
||||||
|
InterlockedAdd(pParams.allocateBuffer[0], 1, targetLocation);
|
||||||
|
pParams.allocateBuffer[1 + targetLocation] = currentID;
|
||||||
|
|
||||||
|
// While we're not done (up the tree or everything is subdivided properly)
|
||||||
|
bool done = false;
|
||||||
|
while (!done)
|
||||||
|
{
|
||||||
|
// If this neighbor is not allocated, we're done.
|
||||||
|
if (twinID == INVALID_POINTER)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Grab the bisector of the neighbor
|
||||||
|
uint64_t nHeapID = pParams.heapIDBuffer[twinID];
|
||||||
|
BisectorData nBisectorData = pParams.bisectorDataBuffer[twinID];
|
||||||
|
uint nDepth = HeapIDDepth(nHeapID);
|
||||||
|
uint3 nNeighbors = pParams.neighboursBuffer[twinID].xyz;
|
||||||
|
|
||||||
|
// If both triangles have the same depth
|
||||||
|
if (nDepth == currentDepth)
|
||||||
|
{
|
||||||
|
// Raised the center split
|
||||||
|
InterlockedOr(pParams.bisectorDataBuffer[twinID].subdivisionPattern, CENTER_SPLIT, prevPattern);
|
||||||
|
|
||||||
|
// Only account for it if it was not raised before.
|
||||||
|
if (prevPattern == 0)
|
||||||
|
{
|
||||||
|
// Mark this for allocation
|
||||||
|
uint targetLocation = 0;
|
||||||
|
InterlockedAdd(pParams.allocateBuffer[0], 1, targetLocation);
|
||||||
|
pParams.allocateBuffer[1 + targetLocation] = twinID;
|
||||||
|
usedMemory++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// And we're done
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
// If this node has already been subdivided, it means that we need to add the third subdivision and we're done
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (nNeighbors[0] == currentID)
|
||||||
|
InterlockedOr(pParams.bisectorDataBuffer[twinID].subdivisionPattern, RIGHT_DOUBLE_SPLIT, prevPattern);
|
||||||
|
else // if (nNeighbors[1] == currentID)
|
||||||
|
InterlockedOr(pParams.bisectorDataBuffer[twinID].subdivisionPattern, LEFT_DOUBLE_SPLIT, prevPattern);
|
||||||
|
|
||||||
|
if (prevPattern != 0)
|
||||||
|
{
|
||||||
|
usedMemory++;
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Mark this for allocation
|
||||||
|
uint targetLocation = 0;
|
||||||
|
InterlockedAdd(pParams.allocateBuffer[0], 1, targetLocation);
|
||||||
|
pParams.allocateBuffer[1 + targetLocation] = twinID;
|
||||||
|
|
||||||
|
// Account for two splits
|
||||||
|
usedMemory += 2;
|
||||||
|
|
||||||
|
// the new bisector that needs to be propagated
|
||||||
|
currentID = twinID;
|
||||||
|
currentDepth = nDepth;
|
||||||
|
twinID = pParams.neighboursBuffer[currentID].z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add back the unused memory (in case)
|
||||||
|
InterlockedAdd(pParams.memoryBuffer[1], max(maxRequiredMemory - usedMemory, 0), remainingMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AllocateElement(uint currentID)
|
||||||
|
{
|
||||||
|
// Load the bisector for this element
|
||||||
|
BisectorData bisectorData = pParams.bisectorDataBuffer[currentID];
|
||||||
|
|
||||||
|
// Does this guy need to be subdivided
|
||||||
|
if (bisectorData.subdivisionPattern != 0)
|
||||||
|
{
|
||||||
|
// How many bits do we need?
|
||||||
|
int numSlots = countbits(bisectorData.subdivisionPattern);
|
||||||
|
|
||||||
|
// Request the number of bits we need using an interlock add
|
||||||
|
uint firstBitIndex = 0;
|
||||||
|
InterlockedAdd(pParams.memoryBuffer[0], numSlots, firstBitIndex);
|
||||||
|
|
||||||
|
// llocate the bits we need
|
||||||
|
for (uint bitId = 0; bitId < numSlots; ++bitId)
|
||||||
|
{
|
||||||
|
uint index = decode_bit_complement(firstBitIndex + bitId);
|
||||||
|
bisectorData.indices[bitId] = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output
|
||||||
|
pParams.bisectorDataBuffer[currentID] = bisectorData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SUBLING0_ID 0
|
||||||
|
#define SUBLING1_ID 1
|
||||||
|
#define SUBLING2_ID 2
|
||||||
|
void evaluate_neighbors(uint currentID, uint bisectorID, out uint resX, out uint resY)
|
||||||
|
{
|
||||||
|
BisectorData nBisectorData = pParams.bisectorDataBuffer[bisectorID];
|
||||||
|
uint3 nNeighbors = pParams.neighboursBuffer[bisectorID].xyz;
|
||||||
|
if (nBisectorData.subdivisionPattern == 0x01)
|
||||||
|
{
|
||||||
|
resX = nBisectorData.indices[SUBLING0_ID];
|
||||||
|
resY = bisectorID;
|
||||||
|
}
|
||||||
|
else if (nBisectorData.subdivisionPattern == 0x03)
|
||||||
|
{
|
||||||
|
if (nNeighbors[0] == currentID)
|
||||||
|
{
|
||||||
|
resX = nBisectorData.indices[SUBLING1_ID];
|
||||||
|
resY = bisectorID;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resX = nBisectorData.indices[SUBLING0_ID];
|
||||||
|
resY = nBisectorData.indices[SUBLING1_ID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (nBisectorData.subdivisionPattern == 0x05)
|
||||||
|
{
|
||||||
|
if (nNeighbors[1] == currentID)
|
||||||
|
{
|
||||||
|
resX = nBisectorData.indices[SUBLING1_ID];
|
||||||
|
resY = nBisectorData.indices[SUBLING0_ID];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resX = nBisectorData.indices[SUBLING0_ID];
|
||||||
|
resY = bisectorID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (nNeighbors[0] == currentID)
|
||||||
|
{
|
||||||
|
resX = nBisectorData.indices[SUBLING1_ID];
|
||||||
|
resY = bisectorID;
|
||||||
|
}
|
||||||
|
else if (nNeighbors[1] == currentID)
|
||||||
|
{
|
||||||
|
resX = nBisectorData.indices[SUBLING2_ID];
|
||||||
|
resY = nBisectorData.indices[SUBLING0_ID];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resX = nBisectorData.indices[SUBLING0_ID];
|
||||||
|
resY = nBisectorData.indices[SUBLING1_ID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BisectElement(uint currentID)
|
||||||
|
{
|
||||||
|
// If this bisector is not allocated or not subdivided, stop right away
|
||||||
|
uint64_t baseHeapID = pParams.heapIDBuffer[currentID];
|
||||||
|
BisectorData cBisectorData = pParams.bisectorDataBuffer[currentID];
|
||||||
|
if (baseHeapID == 0 || cBisectorData.subdivisionPattern == NO_SPLIT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Load the bisector data of the target triangle
|
||||||
|
uint currentSubdiv = cBisectorData.subdivisionPattern;
|
||||||
|
|
||||||
|
// neighbors of the parent
|
||||||
|
uint3 cNeighbors = pParams.neighboursBuffer[currentID].xyz;
|
||||||
|
uint p_n0 = cNeighbors[0];
|
||||||
|
uint p_n1 = cNeighbors[1];
|
||||||
|
uint p_n2 = cNeighbors[2];
|
||||||
|
|
||||||
|
// Get the main axis subdiv
|
||||||
|
uint siblingID0 = cBisectorData.indices[0];
|
||||||
|
uint siblingID1 = cBisectorData.indices[1];
|
||||||
|
uint siblingID2 = cBisectorData.indices[2];
|
||||||
|
|
||||||
|
// Simple subdivision (along the main axis)
|
||||||
|
if (currentSubdiv == CENTER_SPLIT)
|
||||||
|
{
|
||||||
|
uint resX = INVALID_POINTER, resY = INVALID_POINTER;
|
||||||
|
if (p_n2 != INVALID_POINTER)
|
||||||
|
evaluate_neighbors(currentID, p_n2, resX, resY);
|
||||||
|
|
||||||
|
// Set the heap IDs
|
||||||
|
pParams.heapIDBuffer[currentID] = 2 * baseHeapID;
|
||||||
|
pParams.heapIDBuffer[siblingID0] = 2 * baseHeapID + 1;
|
||||||
|
|
||||||
|
// Update the neighbors
|
||||||
|
uint3 modifiedNeighbors;
|
||||||
|
modifiedNeighbors[0] = siblingID0;
|
||||||
|
modifiedNeighbors[1] = resX;
|
||||||
|
modifiedNeighbors[2] = p_n0;
|
||||||
|
pParams.neighboursOutputBuffer[currentID] = uint4(modifiedNeighbors, 0);
|
||||||
|
modifiedNeighbors[0] = resY;
|
||||||
|
modifiedNeighbors[1] = currentID;
|
||||||
|
modifiedNeighbors[2] = p_n1;
|
||||||
|
pParams.neighboursOutputBuffer[siblingID0] = uint4(modifiedNeighbors, 0);
|
||||||
|
|
||||||
|
// Keep track of the parent
|
||||||
|
BisectorData modifiedBisector = cBisectorData;
|
||||||
|
modifiedBisector.propagationID = currentID;
|
||||||
|
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[currentID] = modifiedBisector;
|
||||||
|
|
||||||
|
modifiedBisector.problematicNeighbor = p_n1;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[siblingID0] = modifiedBisector;
|
||||||
|
|
||||||
|
// Mark this for propagation
|
||||||
|
uint targetLocation = 0;
|
||||||
|
InterlockedAdd(pParams.propagateBuffer[0], 1, targetLocation);
|
||||||
|
pParams.propagateBuffer[2 + targetLocation] = siblingID0;
|
||||||
|
}
|
||||||
|
else if (currentSubdiv == RIGHT_DOUBLE_SPLIT)
|
||||||
|
{
|
||||||
|
// Grab the bisector of the twin
|
||||||
|
uint res0X = INVALID_POINTER, res0Y = INVALID_POINTER;
|
||||||
|
evaluate_neighbors(currentID, p_n0, res0X, res0Y);
|
||||||
|
|
||||||
|
uint res1X = INVALID_POINTER, res1Y = INVALID_POINTER;
|
||||||
|
if (p_n2 != INVALID_POINTER)
|
||||||
|
evaluate_neighbors(currentID, p_n2, res1X, res1Y);
|
||||||
|
|
||||||
|
// Set the heap IDs
|
||||||
|
pParams.heapIDBuffer[currentID] = 4 * baseHeapID;
|
||||||
|
pParams.heapIDBuffer[siblingID0] = 2 * baseHeapID + 1;
|
||||||
|
pParams.heapIDBuffer[siblingID1] = 4 * baseHeapID + 1;
|
||||||
|
|
||||||
|
uint3 modifiedNeighbors;
|
||||||
|
modifiedNeighbors[0] = siblingID1;
|
||||||
|
modifiedNeighbors[1] = res0X;
|
||||||
|
modifiedNeighbors[2] = siblingID0;
|
||||||
|
pParams.neighboursOutputBuffer[currentID] = uint4(modifiedNeighbors, 0);
|
||||||
|
modifiedNeighbors[0] = res1Y;
|
||||||
|
modifiedNeighbors[1] = currentID;
|
||||||
|
modifiedNeighbors[2] = p_n1;
|
||||||
|
pParams.neighboursOutputBuffer[siblingID0] = uint4(modifiedNeighbors, 0);
|
||||||
|
modifiedNeighbors[0] = res0Y;
|
||||||
|
modifiedNeighbors[1] = currentID;
|
||||||
|
modifiedNeighbors[2] = res1X;
|
||||||
|
pParams.neighboursOutputBuffer[siblingID1] = uint4(modifiedNeighbors, 0);
|
||||||
|
|
||||||
|
// Keep track of the parent
|
||||||
|
BisectorData modifiedBisector = cBisectorData;
|
||||||
|
modifiedBisector.propagationID = currentID;
|
||||||
|
|
||||||
|
// Lower the element down the tree and update it's sibling
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[currentID] = modifiedBisector;
|
||||||
|
|
||||||
|
// Create the sibling of the current element
|
||||||
|
modifiedBisector.problematicNeighbor = p_n1;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[siblingID0] = modifiedBisector;
|
||||||
|
|
||||||
|
// Create the sibling of the current element
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[siblingID1] = modifiedBisector;
|
||||||
|
|
||||||
|
// Mark this for propagation
|
||||||
|
uint targetLocation = 0;
|
||||||
|
InterlockedAdd(pParams.propagateBuffer[0], 1, targetLocation);
|
||||||
|
pParams.propagateBuffer[2 + targetLocation] = siblingID0;
|
||||||
|
}
|
||||||
|
else if (currentSubdiv == LEFT_DOUBLE_SPLIT)
|
||||||
|
{
|
||||||
|
// Grab the bisector of the twin
|
||||||
|
uint res0X = INVALID_POINTER, res0Y = INVALID_POINTER;
|
||||||
|
evaluate_neighbors(currentID, p_n1, res0X, res0Y);
|
||||||
|
|
||||||
|
uint res1X = INVALID_POINTER, res1Y = INVALID_POINTER;
|
||||||
|
if (p_n2 != INVALID_POINTER)
|
||||||
|
evaluate_neighbors(currentID, p_n2, res1X, res1Y);
|
||||||
|
|
||||||
|
// Set the heap IDs
|
||||||
|
pParams.heapIDBuffer[currentID] = 2 * baseHeapID;
|
||||||
|
pParams.heapIDBuffer[siblingID0] = 4 * baseHeapID + 2;
|
||||||
|
pParams.heapIDBuffer[siblingID1] = 4 * baseHeapID + 3;
|
||||||
|
|
||||||
|
uint3 modifiedNeighbors;
|
||||||
|
modifiedNeighbors[0] = siblingID1;
|
||||||
|
modifiedNeighbors[1] = res1X;
|
||||||
|
modifiedNeighbors[2] = p_n0;
|
||||||
|
pParams.neighboursOutputBuffer[currentID] = uint4(modifiedNeighbors, 0);
|
||||||
|
modifiedNeighbors[0] = siblingID1;
|
||||||
|
modifiedNeighbors[1] = res0X;
|
||||||
|
modifiedNeighbors[2] = res1Y;
|
||||||
|
pParams.neighboursOutputBuffer[siblingID0] = uint4(modifiedNeighbors, 0);
|
||||||
|
modifiedNeighbors[0] = res0Y;
|
||||||
|
modifiedNeighbors[1] = siblingID0;
|
||||||
|
modifiedNeighbors[2] = currentID;
|
||||||
|
pParams.neighboursOutputBuffer[siblingID1] = uint4(modifiedNeighbors, 0);
|
||||||
|
|
||||||
|
// Keep track of the parent
|
||||||
|
BisectorData modifiedBisector = cBisectorData;
|
||||||
|
modifiedBisector.propagationID = currentID;
|
||||||
|
|
||||||
|
// Lower the element down the tree and update it's sibling
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[currentID] = modifiedBisector;
|
||||||
|
|
||||||
|
// Create the sibling of the current element
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[siblingID0] = modifiedBisector;
|
||||||
|
|
||||||
|
// Create the sibling of the current element
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[siblingID1] = modifiedBisector;
|
||||||
|
}
|
||||||
|
else if (currentSubdiv == TRIPLE_SPLIT)
|
||||||
|
{
|
||||||
|
// Grab the bisector of the twin
|
||||||
|
uint res0X = INVALID_POINTER, res0Y = INVALID_POINTER;
|
||||||
|
evaluate_neighbors(currentID, p_n0, res0X, res0Y);
|
||||||
|
|
||||||
|
uint res1X = INVALID_POINTER, res1Y = INVALID_POINTER;
|
||||||
|
evaluate_neighbors(currentID, p_n1, res1X, res1Y);
|
||||||
|
|
||||||
|
uint res2X = INVALID_POINTER, res2Y = INVALID_POINTER;
|
||||||
|
if (p_n2 != INVALID_POINTER)
|
||||||
|
evaluate_neighbors(currentID, p_n2, res2X, res2Y);
|
||||||
|
|
||||||
|
// Set the heap IDs
|
||||||
|
pParams.heapIDBuffer[currentID] = 4 * baseHeapID;
|
||||||
|
pParams.heapIDBuffer[siblingID0] = 4 * baseHeapID + 2;
|
||||||
|
pParams.heapIDBuffer[siblingID1] = 4 * baseHeapID + 1;
|
||||||
|
pParams.heapIDBuffer[siblingID2] = 4 * baseHeapID + 3;
|
||||||
|
|
||||||
|
uint3 modifiedNeighbors;
|
||||||
|
modifiedNeighbors[0] = siblingID1;
|
||||||
|
modifiedNeighbors[1] = res0X;
|
||||||
|
modifiedNeighbors[2] = siblingID2;
|
||||||
|
pParams.neighboursOutputBuffer[currentID] = uint4(modifiedNeighbors, 0);
|
||||||
|
modifiedNeighbors[0] = siblingID2;
|
||||||
|
modifiedNeighbors[1] = res1X;
|
||||||
|
modifiedNeighbors[2] = res2Y;
|
||||||
|
pParams.neighboursOutputBuffer[siblingID0] = uint4(modifiedNeighbors, 0);
|
||||||
|
modifiedNeighbors[0] = res0Y;
|
||||||
|
modifiedNeighbors[1] = currentID;
|
||||||
|
modifiedNeighbors[2] = res2X;
|
||||||
|
pParams.neighboursOutputBuffer[siblingID1] = uint4(modifiedNeighbors, 0);
|
||||||
|
modifiedNeighbors[0] = res1Y;
|
||||||
|
modifiedNeighbors[1] = siblingID0;
|
||||||
|
modifiedNeighbors[2] = currentID;
|
||||||
|
pParams.neighboursOutputBuffer[siblingID2] = uint4(modifiedNeighbors, 0);
|
||||||
|
|
||||||
|
// Keep track of the parent
|
||||||
|
BisectorData modifiedBisector = cBisectorData;
|
||||||
|
modifiedBisector.propagationID = currentID;
|
||||||
|
|
||||||
|
// Lower the element down the tree and update it's sibling
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[currentID] = modifiedBisector;
|
||||||
|
|
||||||
|
// Create the sibling of the current element
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[siblingID0] = modifiedBisector;
|
||||||
|
|
||||||
|
// Create the sibling of the current element
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[siblingID1] = modifiedBisector;
|
||||||
|
|
||||||
|
// Create the sibling of the current element
|
||||||
|
modifiedBisector.problematicNeighbor = INVALID_POINTER;
|
||||||
|
modifiedBisector.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[siblingID2] = modifiedBisector;
|
||||||
|
}
|
||||||
|
|
||||||
|
// How many bits do we need to raise
|
||||||
|
uint numSiblings = countbits(currentSubdiv);
|
||||||
|
for (uint siblingIdx = 0; siblingIdx < numSiblings; ++siblingIdx)
|
||||||
|
{
|
||||||
|
set_bit_atomic_buffer(cBisectorData.indices[siblingIdx], true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropagateBisectElement(uint currentID)
|
||||||
|
{
|
||||||
|
// Load the bisector data of the target triangle
|
||||||
|
BisectorData cBisectorData = pParams.bisectorDataBuffer[currentID];
|
||||||
|
|
||||||
|
// neighbors of the parent
|
||||||
|
uint parentID = cBisectorData.propagationID;
|
||||||
|
uint problematicNeighbor = cBisectorData.problematicNeighbor;
|
||||||
|
|
||||||
|
// Read the neighbor that may have changed
|
||||||
|
BisectorData tBisectorData = pParams.bisectorDataBuffer[problematicNeighbor];
|
||||||
|
uint3 tNeighbors = pParams.neighboursBuffer[problematicNeighbor].xyz;
|
||||||
|
uint targetID = problematicNeighbor;
|
||||||
|
uint sibling1 = tBisectorData.indices[1];
|
||||||
|
|
||||||
|
if (tBisectorData.subdivisionPattern == NO_SPLIT)
|
||||||
|
{
|
||||||
|
if (tNeighbors[0] == parentID)
|
||||||
|
pParams.neighboursBuffer[targetID][0] = currentID;
|
||||||
|
if (tNeighbors[1] == parentID)
|
||||||
|
pParams.neighboursBuffer[targetID][1] = currentID;
|
||||||
|
if (tNeighbors[2] == parentID)
|
||||||
|
pParams.neighboursBuffer[targetID][2] = currentID;
|
||||||
|
}
|
||||||
|
else if (tBisectorData.subdivisionPattern == CENTER_SPLIT)
|
||||||
|
{
|
||||||
|
if (pParams.neighboursBuffer[targetID][2] == parentID)
|
||||||
|
pParams.neighboursBuffer[targetID][2] = currentID;
|
||||||
|
if (pParams.neighboursBuffer[tBisectorData.propagationID][2] == parentID)
|
||||||
|
pParams.neighboursBuffer[tBisectorData.propagationID][2] = currentID;
|
||||||
|
}
|
||||||
|
else if (tBisectorData.subdivisionPattern == RIGHT_DOUBLE_SPLIT)
|
||||||
|
{
|
||||||
|
pParams.neighboursBuffer[sibling1][2] = currentID;
|
||||||
|
}
|
||||||
|
else if (tBisectorData.subdivisionPattern == LEFT_DOUBLE_SPLIT)
|
||||||
|
{
|
||||||
|
pParams.neighboursBuffer[targetID][2] = currentID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the problematic neighbor and the bisection state
|
||||||
|
pParams.bisectorDataBuffer[currentID].problematicNeighbor = INVALID_POINTER;
|
||||||
|
pParams.bisectorDataBuffer[currentID].bisectorState = UNCHANGED_ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrepareSimplifyElement(uint currentID)
|
||||||
|
{
|
||||||
|
// Get the bisector
|
||||||
|
BisectorData cBisectorData = pParams.bisectorDataBuffer[currentID];
|
||||||
|
|
||||||
|
// Grab the current bisector
|
||||||
|
uint64_t cHeapID = pParams.heapIDBuffer[currentID];
|
||||||
|
|
||||||
|
// If this is not an even heap number it will be handeled by it's pair, the twin or the twin's pair
|
||||||
|
|
||||||
|
// Neighbors of this element
|
||||||
|
uint3 cNeighbors = pParams.neighboursBuffer[currentID].xyz;
|
||||||
|
|
||||||
|
// Evaluate the depth of this bisector
|
||||||
|
uint currentDepth = HeapIDDepth(cHeapID);
|
||||||
|
|
||||||
|
// Grab the pair neighbor (it has to exist)
|
||||||
|
uint pairID = cNeighbors[0];
|
||||||
|
uint64_t pHeapID = pParams.heapIDBuffer[pairID];
|
||||||
|
BisectorData pBisectorData = pParams.bisectorDataBuffer[pairID];
|
||||||
|
uint3 pNeighbors = pParams.neighboursBuffer[pairID].xyz;
|
||||||
|
|
||||||
|
// Evaluate the depth of the pair
|
||||||
|
uint pairDepth = HeapIDDepth(pHeapID);
|
||||||
|
|
||||||
|
// If they are not at the same depth or the pair is not to be simplified, we're done
|
||||||
|
if (pairDepth != currentDepth || pBisectorData.bisectorState != SIMPLIFY_ELEMENT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We need to identify our twin pair
|
||||||
|
uint twinLowID = pNeighbors[0];
|
||||||
|
uint twinHighID = cNeighbors[1];
|
||||||
|
if (twinLowID != INVALID_POINTER)
|
||||||
|
{
|
||||||
|
// Grab the two bisectors
|
||||||
|
uint64_t twinLowHeapID = pParams.heapIDBuffer[twinLowID];
|
||||||
|
uint64_t twinHighHeapID = pParams.heapIDBuffer[twinHighID];
|
||||||
|
|
||||||
|
// The current bisector is not the smallest element of the neighborhood, he will be handeled by twinLowBisect if needed
|
||||||
|
if (cHeapID > twinLowHeapID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Compute the depth of both neighbors
|
||||||
|
uint lowFacingDepth = HeapIDDepth(twinLowHeapID);
|
||||||
|
uint highFacingDepth = HeapIDDepth(twinHighHeapID);
|
||||||
|
|
||||||
|
// If all four elements are not on the same
|
||||||
|
if (lowFacingDepth != currentDepth || highFacingDepth != currentDepth)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Grab the two bisectors
|
||||||
|
BisectorData twinLowBisectData = pParams.bisectorDataBuffer[twinLowID];
|
||||||
|
BisectorData twinHighBisectData = pParams.bisectorDataBuffer[twinHighID];
|
||||||
|
|
||||||
|
// This element should not be doing the simplifications if:
|
||||||
|
// - One of the four elements doesn't have the same depth
|
||||||
|
// - One of the four elements isn't flagged for simplification
|
||||||
|
if (twinLowBisectData.bisectorState != SIMPLIFY_ELEMENT
|
||||||
|
|| twinHighBisectData.bisectorState != SIMPLIFY_ELEMENT)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This element will simplify itself, it's pair and possibilty it's twin and twin-pair.
|
||||||
|
uint bisectorSlot;
|
||||||
|
InterlockedAdd(pParams.simplifyBuffer[0], 1, bisectorSlot);
|
||||||
|
|
||||||
|
// Log the bisector ID
|
||||||
|
pParams.simplifyBuffer[1 + bisectorSlot] = currentID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SimplifyElement(uint currentID)
|
||||||
|
{
|
||||||
|
// Grab the current bisector
|
||||||
|
BisectorData cBisectorData = pParams.bisectorDataBuffer[currentID];
|
||||||
|
uint3 cNeighbors = pParams.neighboursBuffer[currentID].xyz;
|
||||||
|
|
||||||
|
// Grab the pair neighbor (it has to exist)
|
||||||
|
uint pairID = cNeighbors[0];
|
||||||
|
BisectorData pBisectorData = pParams.bisectorDataBuffer[pairID];
|
||||||
|
uint3 pNeighbors = pParams.neighboursBuffer[pairID].xyz;
|
||||||
|
|
||||||
|
// We need to indentify our twin pair
|
||||||
|
uint twinLowID = pNeighbors[0];
|
||||||
|
uint twinHighID = cNeighbors[1];
|
||||||
|
|
||||||
|
// Set the heap IDs
|
||||||
|
pParams.heapIDBuffer[currentID] = pParams.heapIDBuffer[currentID] / 2;
|
||||||
|
pParams.heapIDBuffer[pairID] = 0;
|
||||||
|
|
||||||
|
// All conditions are met for us to simplify these triangles
|
||||||
|
uint3 newNeighbors;
|
||||||
|
newNeighbors[0] = cNeighbors[2];
|
||||||
|
newNeighbors[1] = pNeighbors[2];
|
||||||
|
newNeighbors[2] = twinLowID;
|
||||||
|
pParams.neighboursBuffer[currentID] = uint4(newNeighbors, 0);
|
||||||
|
|
||||||
|
// Update the bisector data
|
||||||
|
cBisectorData.propagationID = pairID;
|
||||||
|
cBisectorData.problematicNeighbor = pNeighbors[2];
|
||||||
|
cBisectorData.bisectorState = MERGED_ELEMENT;
|
||||||
|
cBisectorData.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[currentID] = cBisectorData;
|
||||||
|
|
||||||
|
// Mark this for propagation
|
||||||
|
if (cBisectorData.problematicNeighbor != INVALID_POINTER)
|
||||||
|
{
|
||||||
|
// Mark this for propagation
|
||||||
|
uint targetLocation = 0;
|
||||||
|
InterlockedAdd(pParams.propagateBuffer[1], 1, targetLocation);
|
||||||
|
pParams.propagateBuffer[2 + targetLocation] = currentID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the pair's heap for identification
|
||||||
|
pBisectorData.bisectorState = MERGED_ELEMENT;
|
||||||
|
pBisectorData.flags = 0;
|
||||||
|
pParams.bisectorDataBuffer[pairID] = pBisectorData;
|
||||||
|
|
||||||
|
// Don't forget to free the bit
|
||||||
|
set_bit_atomic_buffer(pairID, false);
|
||||||
|
|
||||||
|
// If there was a facing pair, simplify it aswell
|
||||||
|
if (twinLowID != INVALID_POINTER)
|
||||||
|
{
|
||||||
|
// Set the heap IDs
|
||||||
|
pParams.heapIDBuffer[twinLowID] = pParams.heapIDBuffer[twinLowID] / 2;
|
||||||
|
pParams.heapIDBuffer[twinHighID] = 0;
|
||||||
|
|
||||||
|
// Read both bisectors
|
||||||
|
BisectorData lowFacingBst = pParams.bisectorDataBuffer[twinLowID];
|
||||||
|
uint3 lfNeighbors = pParams.neighboursBuffer[twinLowID].xyz;
|
||||||
|
BisectorData highFacingBst = pParams.bisectorDataBuffer[twinHighID];
|
||||||
|
uint3 hfNeighbors = pParams.neighboursBuffer[twinHighID].xyz;
|
||||||
|
|
||||||
|
// Update the lowest ID
|
||||||
|
newNeighbors[0] = lfNeighbors[2];
|
||||||
|
newNeighbors[1] = hfNeighbors[2];
|
||||||
|
newNeighbors[2] = currentID;
|
||||||
|
pParams.neighboursBuffer[twinLowID] = uint4(newNeighbors, 0);
|
||||||
|
|
||||||
|
// Update the twin bisector data
|
||||||
|
lowFacingBst.propagationID = twinHighID;
|
||||||
|
lowFacingBst.problematicNeighbor = hfNeighbors[2];
|
||||||
|
lowFacingBst.bisectorState = MERGED_ELEMENT;
|
||||||
|
lowFacingBst.flags = (VISIBLE_BISECTOR | MODIFIED_BISECTOR);
|
||||||
|
pParams.bisectorDataBuffer[twinLowID] = lowFacingBst;
|
||||||
|
|
||||||
|
if (lowFacingBst.problematicNeighbor != INVALID_POINTER)
|
||||||
|
{
|
||||||
|
// Mark this for propagation
|
||||||
|
uint targetLocation = 0;
|
||||||
|
InterlockedAdd(pParams.propagateBuffer[1], 1, targetLocation);
|
||||||
|
pParams.propagateBuffer[2 + targetLocation] = twinLowID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the pair's heap for identification
|
||||||
|
highFacingBst.bisectorState = MERGED_ELEMENT;
|
||||||
|
highFacingBst.flags = 0;
|
||||||
|
pParams.bisectorDataBuffer[twinHighID] = highFacingBst;
|
||||||
|
|
||||||
|
// Don't forget to free the bit
|
||||||
|
set_bit_atomic_buffer(twinHighID, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropagateElementSimplify(uint currentID)
|
||||||
|
{
|
||||||
|
// Load the bisector data of the target element
|
||||||
|
BisectorData cBisectorData = pParams.bisectorDataBuffer[currentID];
|
||||||
|
|
||||||
|
// Id of the element before the simplification
|
||||||
|
uint deletedPair = cBisectorData.propagationID;
|
||||||
|
|
||||||
|
// neighbors of the parent
|
||||||
|
uint neighborID = cBisectorData.problematicNeighbor;
|
||||||
|
|
||||||
|
// Read the neighbor that may have changed
|
||||||
|
BisectorData nBisectorData = pParams.bisectorDataBuffer[neighborID];
|
||||||
|
uint3 nNeighbors = pParams.neighboursBuffer[neighborID].xyz;
|
||||||
|
|
||||||
|
// The neighbor has not changed, so we just need to make it point on currentID instead of the pair that was deleted
|
||||||
|
if (nBisectorData.bisectorState != MERGED_ELEMENT)
|
||||||
|
{
|
||||||
|
for (uint i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
if (nNeighbors[i] == deletedPair)
|
||||||
|
pParams.neighboursBuffer[neighborID][i] = currentID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The neighbor has had a simplification, so we need to update a different neighbor based on if it went up one depth in the tree or was deleted.
|
||||||
|
else if (nBisectorData.bisectorState == MERGED_ELEMENT)
|
||||||
|
{
|
||||||
|
// He still exist, but was simplified
|
||||||
|
if (pParams.heapIDBuffer[neighborID] != 0)
|
||||||
|
{
|
||||||
|
for (uint i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
if (nNeighbors[i] == deletedPair)
|
||||||
|
pParams.neighboursBuffer[neighborID][i] = currentID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// He is gone, we need to update his pair instead of him.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint neighborPair = nNeighbors[1];
|
||||||
|
for (uint i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
if (pParams.neighboursBuffer[neighborPair][i] == deletedPair)
|
||||||
|
pParams.neighboursBuffer[neighborPair][i] = currentID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the problematic neighbor
|
||||||
|
pParams.bisectorDataBuffer[currentID].problematicNeighbor = INVALID_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BisectorElementIndexation(uint currentID)
|
||||||
|
{
|
||||||
|
// Grab the current heap ID
|
||||||
|
uint64_t cHeapID = pParams.heapIDBuffer[currentID];
|
||||||
|
|
||||||
|
// Deallocated element, we don't care
|
||||||
|
if (cHeapID == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Reserve a slot for this bisector
|
||||||
|
uint bisectorSlot;
|
||||||
|
InterlockedAdd(pParams.indirectDrawBuffer[0], 3, bisectorSlot);
|
||||||
|
|
||||||
|
// Keep track of it's global ID
|
||||||
|
pParams.bisectorIndicesBuffer[bisectorSlot / 3] = currentID;
|
||||||
|
|
||||||
|
// Load the bisector data of the target element
|
||||||
|
BisectorData cBisectorData = pParams.bisectorDataBuffer[currentID];
|
||||||
|
|
||||||
|
// Is it visible?
|
||||||
|
if ((cBisectorData.flags & VISIBLE_BISECTOR) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Reserve a slot for this visible bisector
|
||||||
|
InterlockedAdd(pParams.indirectDrawBuffer[4], 3, bisectorSlot);
|
||||||
|
|
||||||
|
// Keep track of it's global ID
|
||||||
|
pParams.visibleBisectorIndices[bisectorSlot / 3] = currentID;
|
||||||
|
|
||||||
|
// Is it visible?
|
||||||
|
if ((cBisectorData.flags & MODIFIED_BISECTOR) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Reserve a slot for this visible bisector
|
||||||
|
InterlockedAdd(pParams.indirectDrawBuffer[8], 4, bisectorSlot);
|
||||||
|
|
||||||
|
// Keep track of it's global ID
|
||||||
|
pParams.modifiedBisectorIndices[bisectorSlot / 4] = currentID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateBisector(uint currentID)
|
||||||
|
{
|
||||||
|
// Grab the current heap ID
|
||||||
|
uint64_t cHeapID = pParams.heapIDBuffer[currentID];
|
||||||
|
|
||||||
|
// Deallocated element, we don't care
|
||||||
|
if (cHeapID == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Load the bisector data of the target element
|
||||||
|
uint3 cNeighbors = pParams.neighboursBuffer[currentID].xyz;
|
||||||
|
|
||||||
|
bool failed = false;
|
||||||
|
uint targetNeighbor = INVALID_POINTER;
|
||||||
|
uint targetIdx = INVALID_POINTER;
|
||||||
|
for (uint i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
uint neighborID = cNeighbors[i];
|
||||||
|
if (neighborID != INVALID_POINTER)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
uint3 nNeighbors = pParams.neighboursBuffer[neighborID].xyz;
|
||||||
|
for (uint j = 0; j < 3; ++j)
|
||||||
|
{
|
||||||
|
if (nNeighbors[j] == currentID)
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
failed = true;
|
||||||
|
targetNeighbor = neighborID;
|
||||||
|
targetIdx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify the failure
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
uint prevValue;
|
||||||
|
InterlockedAdd(pParams.validationBuffer[0], 1, prevValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -281,27 +281,27 @@ void MeshUpdater::init(Gfx::PGraphics gfx, Gfx::PDescriptorLayout viewParamsLayo
|
|||||||
|
|
||||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||||
.name = "CBTCompute",
|
.name = "CBTCompute",
|
||||||
.modules = {"CBTCompute"},
|
.modules = {"CBTCompute", "LEB"},
|
||||||
.entryPoints =
|
.entryPoints =
|
||||||
{
|
{
|
||||||
{"reset", "CBTCompute"},
|
{"Reset", "CBTCompute"},
|
||||||
{"classify", "CBTCompute"},
|
{"Classify", "CBTCompute"},
|
||||||
{"split", "CBTCompute"},
|
{"Split", "CBTCompute"},
|
||||||
{"prepareIndirect", "CBTCompute"},
|
{"PrepareIndirect", "CBTCompute"},
|
||||||
{"allocate", "CBTCompute"},
|
{"Allocate", "CBTCompute"},
|
||||||
{"bisect", "CBTCompute"},
|
{"Bisect", "CBTCompute"},
|
||||||
{"propagateBisect", "CBTCompute"},
|
{"PropagateBisect", "CBTCompute"},
|
||||||
{"prepareSimplify", "CBTCompute"},
|
{"PrepareSimplify", "CBTCompute"},
|
||||||
{"simplify", "CBTCompute"},
|
{"Simplify", "CBTCompute"},
|
||||||
{"propagateSimplify", "CBTCompute"},
|
{"PropagateSimplify", "CBTCompute"},
|
||||||
{"reducePrePass", "CBTCompute"},
|
{"ReducePrePass", "CBTCompute"},
|
||||||
{"reduceFirstPass", "CBTCompute"},
|
{"ReduceFirstPass", "CBTCompute"},
|
||||||
{"reduceSecondPass", "CBTCompute"},
|
{"ReduceSecondPass", "CBTCompute"},
|
||||||
{"bisectorIndexation", "CBTCompute"},
|
{"BisectorIndexation", "CBTCompute"},
|
||||||
{"prepareBisectorIndirect", "CBTCompute"},
|
{"PrepareBisectorIndirect", "CBTCompute"},
|
||||||
{"validate", "CBTCompute"},
|
{"Validate", "CBTCompute"},
|
||||||
{"clearLeb", "CBTCompute"},
|
{"ClearBuffer", "LEB"},
|
||||||
{"evaluateLeb", "CBTCompute"},
|
{"EvaluateLEB", "LEB"},
|
||||||
},
|
},
|
||||||
.rootSignature = pipelineLayout,
|
.rootSignature = pipelineLayout,
|
||||||
});
|
});
|
||||||
@@ -412,9 +412,11 @@ void MeshUpdater::evaluateLeb(const BaseMesh& baseMesh, CBTMesh& mesh, Gfx::PDes
|
|||||||
clearCmd->bindPipeline(lebClear);
|
clearCmd->bindPipeline(lebClear);
|
||||||
clearCmd->bindDescriptor(set);
|
clearCmd->bindDescriptor(set);
|
||||||
clearCmd->dispatch((mesh.totalNumElements * 3 + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE, 1, 1);
|
clearCmd->dispatch((mesh.totalNumElements * 3 + WORKGROUP_SIZE - 1) / WORKGROUP_SIZE, 1, 1);
|
||||||
|
graphics->executeCommands(std::move(clearCmd));
|
||||||
mesh.currentVertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
mesh.currentVertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
|
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
|
||||||
set->updateBuffer(GEOMETRY_CB, 0, geometryBuffer);
|
set->updateBuffer(GEOMETRY_CB, 0, geometryBuffer);
|
||||||
set->updateBuffer(UPDATE_CB, 0, updateBuffer);
|
set->updateBuffer(UPDATE_CB, 0, updateBuffer);
|
||||||
@@ -432,7 +434,7 @@ void MeshUpdater::evaluateLeb(const BaseMesh& baseMesh, CBTMesh& mesh, Gfx::PDes
|
|||||||
evalCmd->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32), &val);
|
evalCmd->pushConstants(Gfx::SE_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(uint32), &val);
|
||||||
evalCmd->dispatchIndirect(mesh.indirectDispatchBuffer, complete ? 0 : sizeof(uint32) * 6);
|
evalCmd->dispatchIndirect(mesh.indirectDispatchBuffer, complete ? 0 : sizeof(uint32) * 6);
|
||||||
graphics->executeCommands(std::move(evalCmd));
|
graphics->executeCommands(std::move(evalCmd));
|
||||||
mesh.currentVertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
mesh.lebVertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,7 +458,6 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
|
set->updateBuffer(HEAP_ID_BUFFER, 0, mesh.heapIDBuffer);
|
||||||
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
|
set->updateBuffer(BISECTOR_DATA_BUFFER, 0, mesh.updateBuffer);
|
||||||
set->updateBuffer(CLASSIFICATION_BUFFER, 0, mesh.classificationBuffer);
|
set->updateBuffer(CLASSIFICATION_BUFFER, 0, mesh.classificationBuffer);
|
||||||
set->updateBuffer(DEBUG_BUFFER, 0, debugBuffer);
|
|
||||||
set->writeChanges();
|
set->writeChanges();
|
||||||
Gfx::OComputeCommand classifyCmd = graphics->createComputeCommand("Classify");
|
Gfx::OComputeCommand classifyCmd = graphics->createComputeCommand("Classify");
|
||||||
classifyCmd->bindPipeline(classify);
|
classifyCmd->bindPipeline(classify);
|
||||||
@@ -482,6 +483,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
// split pass
|
// split pass
|
||||||
{
|
{
|
||||||
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
|
Gfx::PDescriptorSet set = layout->allocateDescriptorSet();
|
||||||
@@ -494,6 +496,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
set->updateBuffer(NEIGHBOURS_BUFFER, 0, currentNeighborsBuffer);
|
set->updateBuffer(NEIGHBOURS_BUFFER, 0, currentNeighborsBuffer);
|
||||||
set->updateBuffer(MEMORY_BUFFER, 0, memoryBuffer);
|
set->updateBuffer(MEMORY_BUFFER, 0, memoryBuffer);
|
||||||
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.allocateBuffer);
|
set->updateBuffer(ALLOCATE_BUFFER, 0, mesh.allocateBuffer);
|
||||||
|
set->updateBuffer(DEBUG_BUFFER, 0, debugBuffer);
|
||||||
set->writeChanges();
|
set->writeChanges();
|
||||||
Gfx::OComputeCommand splitCmd = graphics->createComputeCommand("Split");
|
Gfx::OComputeCommand splitCmd = graphics->createComputeCommand("Split");
|
||||||
splitCmd->bindPipeline(split);
|
splitCmd->bindPipeline(split);
|
||||||
@@ -502,7 +505,10 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
graphics->executeCommands(std::move(splitCmd));
|
graphics->executeCommands(std::move(splitCmd));
|
||||||
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
|
mesh.allocateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// prepare indirect pass
|
// prepare indirect pass
|
||||||
{
|
{
|
||||||
@@ -518,6 +524,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// Allocate Pass
|
// Allocate Pass
|
||||||
{
|
{
|
||||||
@@ -539,6 +546,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// copy
|
// copy
|
||||||
currentNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
currentNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
@@ -546,6 +554,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
graphics->copyBuffer(currentNeighborsBuffer, nextNeighborsBuffer);
|
graphics->copyBuffer(currentNeighborsBuffer, nextNeighborsBuffer);
|
||||||
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// bisect
|
// bisect
|
||||||
{
|
{
|
||||||
@@ -570,6 +579,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// Prepare indirect pass
|
// Prepare indirect pass
|
||||||
{
|
{
|
||||||
@@ -585,6 +595,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// propagate split pass
|
// propagate split pass
|
||||||
{
|
{
|
||||||
@@ -604,6 +615,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
mesh.updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// prepare simplify
|
// prepare simplify
|
||||||
{
|
{
|
||||||
@@ -625,6 +637,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
mesh.simplificationBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
mesh.simplificationBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// Prepare Indirect Simplify
|
// Prepare Indirect Simplify
|
||||||
{
|
{
|
||||||
@@ -640,6 +653,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// Simplify Pass
|
// Simplify Pass
|
||||||
{
|
{
|
||||||
@@ -663,6 +677,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// Prepare Indirect Propagate Simplify
|
// Prepare Indirect Propagate Simplify
|
||||||
{
|
{
|
||||||
@@ -678,6 +693,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
indirectBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// Propagate Simplify Pass
|
// Propagate Simplify Pass
|
||||||
{
|
{
|
||||||
@@ -698,6 +714,7 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
nextNeighborsBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
// Update Tree
|
// Update Tree
|
||||||
{
|
{
|
||||||
@@ -730,10 +747,12 @@ void MeshUpdater::update(CBTMesh& mesh, Gfx::PDescriptorSet viewParamsSet, Gfx::
|
|||||||
mesh.gpuCBT.bufferArray[0]->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
mesh.gpuCBT.bufferArray[0]->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
}
|
}
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
mesh.currentNeighborsBufferIdx = nextNeighborsBufferIdx;
|
mesh.currentNeighborsBufferIdx = nextNeighborsBufferIdx;
|
||||||
|
|
||||||
prepareIndirection(mesh, geometryCB);
|
prepareIndirection(mesh, geometryCB);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshUpdater::validation(const CBTMesh& mesh, Gfx::PUniformBuffer geometryCB) {
|
void MeshUpdater::validation(const CBTMesh& mesh, Gfx::PUniformBuffer geometryCB) {
|
||||||
|
|||||||
@@ -327,6 +327,7 @@ struct GeometryCB {
|
|||||||
uint32 totalNumVertices;
|
uint32 totalNumVertices;
|
||||||
};
|
};
|
||||||
struct UpdateCB {
|
struct UpdateCB {
|
||||||
|
Matrix4 viewProjectionMatrix;
|
||||||
float triangleSize;
|
float triangleSize;
|
||||||
uint32_t maxSubdivisionDepth;
|
uint32_t maxSubdivisionDepth;
|
||||||
float fov;
|
float fov;
|
||||||
@@ -355,10 +356,10 @@ constexpr int64 BISECT_ELEMENT = 1;
|
|||||||
constexpr int64 SIMPLIFY_ELEMENT = 2;
|
constexpr int64 SIMPLIFY_ELEMENT = 2;
|
||||||
constexpr int64 MERGED_ELEMENT = 3;
|
constexpr int64 MERGED_ELEMENT = 3;
|
||||||
struct BisectorData {
|
struct BisectorData {
|
||||||
uint32 subdivisionPattern;
|
|
||||||
|
|
||||||
UVector indices;
|
UVector indices;
|
||||||
|
|
||||||
|
uint32 subdivisionPattern;
|
||||||
|
|
||||||
uint32 problematicNeighbor;
|
uint32 problematicNeighbor;
|
||||||
|
|
||||||
uint32 bisectorState;
|
uint32 bisectorState;
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ struct ShaderBufferCreateInfo {
|
|||||||
DataSource sourceData = DataSource();
|
DataSource sourceData = DataSource();
|
||||||
uint64 numElements = 1;
|
uint64 numElements = 1;
|
||||||
uint32 clearValue = 0;
|
uint32 clearValue = 0;
|
||||||
uint8 createCleared = 0;
|
|
||||||
Gfx::SeBufferUsageFlags usage = 0;
|
Gfx::SeBufferUsageFlags usage = 0;
|
||||||
std::string name = "Unnamed";
|
std::string name = "Unnamed";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ void BasePass::beginFrame(const Component::Camera& cam) {
|
|||||||
transparentCulling = lightCullingLayout->allocateDescriptorSet();
|
transparentCulling = lightCullingLayout->allocateDescriptorSet();
|
||||||
|
|
||||||
//waterRenderer->beginFrame();
|
//waterRenderer->beginFrame();
|
||||||
terrainRenderer->beginFrame(viewParamsSet);
|
terrainRenderer->beginFrame(viewParamsSet, cam);
|
||||||
|
|
||||||
// Debug vertices
|
// Debug vertices
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,11 +10,19 @@ using namespace Seele;
|
|||||||
TerrainRenderer::TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDescriptorLayout viewParamsLayout,
|
TerrainRenderer::TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDescriptorLayout viewParamsLayout,
|
||||||
Gfx::PDescriptorSet viewParamsSet)
|
Gfx::PDescriptorSet viewParamsSet)
|
||||||
: graphics(graphics), scene(scene) {
|
: graphics(graphics), scene(scene) {
|
||||||
|
//Gfx::OPipelineLayout test = graphics->createPipelineLayout();
|
||||||
|
//graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||||
|
// .modules = {"CompileTest"},
|
||||||
|
// .entryPoints = {{"Reset", "CompileTest"}},
|
||||||
|
// .rootSignature = test,
|
||||||
|
//});
|
||||||
|
//graphics->createComputeShader({0});
|
||||||
meshUpdater.init(graphics, viewParamsLayout);
|
meshUpdater.init(graphics, viewParamsLayout);
|
||||||
lebCache.init(graphics, 5);
|
lebCache.init(graphics, 5);
|
||||||
CBT<18> cbt;
|
CBT<18> cbt;
|
||||||
CPUMesh cpuMesh = generateCPUMesh(cbt.numElements());
|
CPUMesh cpuMesh = generateCPUMesh(cbt.numElements());
|
||||||
plainMesh.gpuCBT.lastLevelSize = cbt.lastLevelSize();
|
plainMesh.gpuCBT.lastLevelSize = cbt.lastLevelSize();
|
||||||
|
plainMesh.gpuCBT.bufferCount = 2;
|
||||||
for (uint32 i = 0; i < 2; ++i) {
|
for (uint32 i = 0; i < 2; ++i) {
|
||||||
uint32 bufferSize = cbt.bufferSize(i);
|
uint32 bufferSize = cbt.bufferSize(i);
|
||||||
uint32 elementSize = cbt.elementSize(i);
|
uint32 elementSize = cbt.elementSize(i);
|
||||||
@@ -74,7 +82,6 @@ TerrainRenderer::TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDe
|
|||||||
{
|
{
|
||||||
.size = sizeof(BisectorData) * cpuMesh.totalNumElements,
|
.size = sizeof(BisectorData) * cpuMesh.totalNumElements,
|
||||||
},
|
},
|
||||||
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
|
|
||||||
.name = "UpdateBuffer",
|
.name = "UpdateBuffer",
|
||||||
});
|
});
|
||||||
plainMesh.classificationBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
plainMesh.classificationBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
@@ -151,6 +158,8 @@ TerrainRenderer::TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDe
|
|||||||
},
|
},
|
||||||
.name = "LebVertexBuffer",
|
.name = "LebVertexBuffer",
|
||||||
});
|
});
|
||||||
|
plainMesh.lebVertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
plainMesh.currentVertexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
plainMesh.currentVertexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
.sourceData =
|
.sourceData =
|
||||||
{
|
{
|
||||||
@@ -213,6 +222,7 @@ TerrainRenderer::TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDe
|
|||||||
geometryBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_UNIFORM_READ_BIT,
|
geometryBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_UNIFORM_READ_BIT,
|
||||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
UpdateCB updateCB = {
|
UpdateCB updateCB = {
|
||||||
|
.viewProjectionMatrix = Matrix4(0),
|
||||||
.triangleSize = 10.0f,
|
.triangleSize = 10.0f,
|
||||||
.maxSubdivisionDepth = 63,
|
.maxSubdivisionDepth = 63,
|
||||||
.fov = 70.0f,
|
.fov = 70.0f,
|
||||||
@@ -234,7 +244,7 @@ TerrainRenderer::TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDe
|
|||||||
{
|
{
|
||||||
{"vert", "TerrainPass"},
|
{"vert", "TerrainPass"},
|
||||||
{"frag", "TerrainPass"},
|
{"frag", "TerrainPass"},
|
||||||
{"deform", "TerrainPass"},
|
{"EvaluateDeformation", "TerrainPass"},
|
||||||
},
|
},
|
||||||
.rootSignature = meshUpdater.pipelineLayout,
|
.rootSignature = meshUpdater.pipelineLayout,
|
||||||
});
|
});
|
||||||
@@ -245,20 +255,47 @@ TerrainRenderer::TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDe
|
|||||||
.computeShader = deformCS,
|
.computeShader = deformCS,
|
||||||
.pipelineLayout = meshUpdater.pipelineLayout,
|
.pipelineLayout = meshUpdater.pipelineLayout,
|
||||||
});
|
});
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
|
|
||||||
meshUpdater.resetBuffers(plainMesh);
|
meshUpdater.resetBuffers(plainMesh);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
meshUpdater.prepareIndirection(plainMesh, geometryBuffer);
|
meshUpdater.prepareIndirection(plainMesh, geometryBuffer);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
meshUpdater.evaluateLeb(baseMesh, plainMesh, viewParamsSet, geometryBuffer, updateBuffer, lebCache.getLebMatrixBuffer(), true, true);
|
meshUpdater.evaluateLeb(baseMesh, plainMesh, viewParamsSet, geometryBuffer, updateBuffer, lebCache.getLebMatrixBuffer(), true, true);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
applyDeformation(viewParamsSet);
|
applyDeformation(viewParamsSet);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
TerrainRenderer::~TerrainRenderer() {}
|
TerrainRenderer::~TerrainRenderer() {}
|
||||||
|
|
||||||
static bool first = true;
|
static bool first = true;
|
||||||
|
|
||||||
void TerrainRenderer::beginFrame(Gfx::PDescriptorSet viewParamsSet) {
|
void TerrainRenderer::beginFrame(Gfx::PDescriptorSet viewParamsSet, const Component::Camera& cam) {
|
||||||
|
UpdateCB updateCB = {
|
||||||
|
.viewProjectionMatrix = viewport->getProjectionMatrix() * cam.getViewMatrix(),
|
||||||
|
.triangleSize = 10.0f,
|
||||||
|
.maxSubdivisionDepth = 63,
|
||||||
|
.fov = 70.0f,
|
||||||
|
.farPlaneDistance = 1000.0f,
|
||||||
|
};
|
||||||
|
updateBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = sizeof(UpdateCB),
|
||||||
|
.data = (uint8*)&updateCB,
|
||||||
|
},
|
||||||
|
.name = "UpdateCB",
|
||||||
|
});
|
||||||
|
updateBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_UNIFORM_READ_BIT,
|
||||||
|
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
meshUpdater.update(plainMesh, viewParamsSet, geometryBuffer, updateBuffer);
|
meshUpdater.update(plainMesh, viewParamsSet, geometryBuffer, updateBuffer);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
meshUpdater.evaluateLeb(baseMesh, plainMesh, viewParamsSet, geometryBuffer, updateBuffer, lebCache.getLebMatrixBuffer(), false, false);
|
meshUpdater.evaluateLeb(baseMesh, plainMesh, viewParamsSet, geometryBuffer, updateBuffer, lebCache.getLebMatrixBuffer(), false, false);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
applyDeformation(viewParamsSet);
|
applyDeformation(viewParamsSet);
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
Gfx::ORenderCommand TerrainRenderer::render(Gfx::PDescriptorSet viewParamsSet) {
|
Gfx::ORenderCommand TerrainRenderer::render(Gfx::PDescriptorSet viewParamsSet) {
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class TerrainRenderer {
|
|||||||
public:
|
public:
|
||||||
TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDescriptorLayout viewParamsLayout, Gfx::PDescriptorSet viewParamsSet);
|
TerrainRenderer(Gfx::PGraphics graphics, PScene scene, Gfx::PDescriptorLayout viewParamsLayout, Gfx::PDescriptorSet viewParamsSet);
|
||||||
~TerrainRenderer();
|
~TerrainRenderer();
|
||||||
void beginFrame(Gfx::PDescriptorSet viewParamsSet);
|
void beginFrame(Gfx::PDescriptorSet viewParamsSet, const Component::Camera& cam);
|
||||||
Gfx::ORenderCommand render(Gfx::PDescriptorSet viewParamsSet);
|
Gfx::ORenderCommand render(Gfx::PDescriptorSet viewParamsSet);
|
||||||
void setViewport(Gfx::PViewport viewport, Gfx::PRenderPass renderPass);
|
void setViewport(Gfx::PViewport viewport, Gfx::PRenderPass renderPass);
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,6 @@ void VisibilityPass::publishOutputs() {
|
|||||||
|
|
||||||
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
.clearValue = 0xffffffff,
|
.clearValue = 0xffffffff,
|
||||||
.createCleared = true,
|
|
||||||
.name = "CullingBuffer",
|
.name = "CullingBuffer",
|
||||||
});
|
});
|
||||||
resources->registerBufferOutput("CULLINGBUFFER", cullingBuffer);
|
resources->registerBufferOutput("CULLINGBUFFER", cullingBuffer);
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ void Buffer::createBuffer(uint64 size, uint32 destIndex) {
|
|||||||
command->bindResource(PBufferAllocation(buffers[destIndex]));
|
command->bindResource(PBufferAllocation(buffers[destIndex]));
|
||||||
vkCmdFillBuffer(command->getHandle(), buffers[destIndex]->buffer, 0, VK_WHOLE_SIZE, clearValue);
|
vkCmdFillBuffer(command->getHandle(), buffers[destIndex]->buffer, 0, VK_WHOLE_SIZE, clearValue);
|
||||||
pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -417,7 +417,7 @@ void UniformBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSt
|
|||||||
ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& createInfo)
|
ShaderBuffer::ShaderBuffer(PGraphics graphics, const ShaderBufferCreateInfo& createInfo)
|
||||||
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), createInfo),
|
: Gfx::ShaderBuffer(graphics->getFamilyMapping(), createInfo),
|
||||||
Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | createInfo.usage,
|
Vulkan::Buffer(graphics, createInfo.sourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | createInfo.usage,
|
||||||
createInfo.sourceData.owner, true, createInfo.name, createInfo.createCleared, createInfo.clearValue) {
|
createInfo.sourceData.owner, true, createInfo.name, createInfo.sourceData.data == nullptr, createInfo.clearValue) {
|
||||||
if (createInfo.sourceData.size > 0 && createInfo.sourceData.data != nullptr) {
|
if (createInfo.sourceData.size > 0 && createInfo.sourceData.data != nullptr) {
|
||||||
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
|
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ using namespace Seele;
|
|||||||
{ \
|
{ \
|
||||||
if (diagnostics) { \
|
if (diagnostics) { \
|
||||||
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl; \
|
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl; \
|
||||||
assert(false); \
|
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,15 +34,15 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
|
|||||||
sessionDesc.flags = 0;
|
sessionDesc.flags = 0;
|
||||||
Array<slang::CompilerOptionEntry> option = {
|
Array<slang::CompilerOptionEntry> option = {
|
||||||
{
|
{
|
||||||
.name = slang::CompilerOptionName::IgnoreCapabilities,
|
.name = slang::CompilerOptionName::Capability,
|
||||||
.value =
|
.value =
|
||||||
{
|
{
|
||||||
.kind = slang::CompilerOptionValueKind::Int,
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
.intValue0 = 1,
|
.intValue0 = globalSession->findCapability("GLSL_450"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.name = slang::CompilerOptionName::EmitSpirvViaGLSL,
|
.name = slang::CompilerOptionName::EmitSpirvDirectly,
|
||||||
.value =
|
.value =
|
||||||
{
|
{
|
||||||
.kind = slang::CompilerOptionValueKind::Int,
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
@@ -89,7 +88,7 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
|
|||||||
sessionDesc.preprocessorMacroCount = macros.size();
|
sessionDesc.preprocessorMacroCount = macros.size();
|
||||||
sessionDesc.preprocessorMacros = macros.data();
|
sessionDesc.preprocessorMacros = macros.data();
|
||||||
slang::TargetDesc targetDesc;
|
slang::TargetDesc targetDesc;
|
||||||
targetDesc.profile = globalSession->findProfile("GLSL_450");
|
targetDesc.profile = globalSession->findProfile("glsl_450");
|
||||||
targetDesc.format = target;
|
targetDesc.format = target;
|
||||||
sessionDesc.targetCount = 1;
|
sessionDesc.targetCount = 1;
|
||||||
sessionDesc.targets = &targetDesc;
|
sessionDesc.targets = &targetDesc;
|
||||||
|
|||||||
Reference in New Issue
Block a user