Compare commits

...
1 Commits
Author SHA1 Message Date
Dynamitos ac317a3829 Trying to add fluid simulation 2026-04-12 20:49:02 +02:00
65 changed files with 2708 additions and 371 deletions
+22 -1
View File
@@ -34,7 +34,23 @@
"environment": [ "environment": [
{ {
"name": "ASAN_OPTIONS", "name": "ASAN_OPTIONS",
"value": "alloc_dealloc_mismatch=0", "value": "detect_leaks=0",
},
{
"name": "VK_INSTANCE_LAYERS",
"value": "VK_LAYER_KHRONOS_validation",
},
{
"name": "DISABLE_VK_LAYER_VALVE_steam_overlay_1",
"value": "1",
},
{
"name": "DISABLE_VK_LAYER_VALVE_steam_fossilize_1",
"value": "1",
},
{
"name": "MANGOHUD",
"value": "0",
} }
], ],
"cwd": "${workspaceRoot}/build", "cwd": "${workspaceRoot}/build",
@@ -45,6 +61,11 @@
"description": "Enable pretty-printing for gdb", "description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing", "text": "-enable-pretty-printing",
"ignoreFailures": true "ignoreFailures": true
},
{
"description": "Import Seele pretty-printers",
"text": "python exec(open('${workspaceFolder}/Seele/gdb/Seele.py').read())",
"ignoreFailures": true
} }
], ],
}, },
+5
View File
@@ -54,6 +54,11 @@ if(WIN32)
endif() endif()
add_library(Engine SHARED "") add_library(Engine SHARED "")
set_target_properties(Engine PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
target_include_directories(Engine PRIVATE src/Engine) target_include_directories(Engine PRIVATE src/Engine)
target_link_libraries(Engine PUBLIC Vulkan::Vulkan) target_link_libraries(Engine PUBLIC Vulkan::Vulkan)
+83 -2
View File
@@ -2,6 +2,25 @@ import sys
sys.path.insert(0, '/usr/share/gdb/python/') sys.path.insert(0, '/usr/share/gdb/python/')
import gdb.printing import gdb.printing
def _base_cast(val):
for field in val.type.strip_typedefs().fields():
if getattr(field, 'is_base_class', False):
return val.cast(field.type)
return None
def _member(val, name):
"""Find a member by name on a value, searching base classes if needed."""
current = val
while current is not None:
t = current.type.strip_typedefs()
for field in t.fields():
if field.name == name:
return current[name]
current = _base_cast(current)
raise gdb.error(f"Member '{name}' not found on {val.type}")
class ArrayPrinter: class ArrayPrinter:
def __init__(self, val): def __init__(self, val):
self.val = val self.val = val
@@ -13,8 +32,8 @@ class ArrayPrinter:
data = self.val['_data'] data = self.val['_data']
size = int(self.val['arraySize']) size = int(self.val['arraySize'])
allocated = int(self.val['allocated']) allocated = int(self.val['allocated'])
#yield f"[size]", size yield f"[size]", size
#yield f"[allocated]", allocated yield f"[allocated]", allocated
for i in range(size): for i in range(size):
elem_val = (data + i).dereference() elem_val = (data + i).dereference()
yield f"[{i}]", elem_val yield f"[{i}]", elem_val
@@ -22,6 +41,66 @@ class ArrayPrinter:
def display_hint(self): def display_hint(self):
return "array" return "array"
class ListPrinter:
def __init__(self, val):
self.val = val
def to_string(self):
size = int(_member(self.val, '_size'))
return f"List(size={size})"
def children(self):
size = int(_member(self.val, '_size'))
root = _member(self.val, 'root')
tail = _member(self.val, 'tail')
yield "[size]", size
node = root
idx = 0
# Bound traversal by logical size to avoid walking corrupted links forever.
while idx < size and node != tail:
yield f"[{idx}]", node['data']
node = node['next']
idx += 1
def display_hint(self):
return "array"
class MapPrinter:
def __init__(self, val):
self.val = val
def to_string(self):
size = int(_member(self.val, '_size'))
return f"Map(size={size})"
def children(self):
size = int(_member(self.val, '_size'))
root = _member(self.val, 'root')
stack = []
node = root
idx = 0
# In-order traversal of Tree nodes yields map entries sorted by key.
while (node or stack) and idx < size:
while node:
stack.append(node)
node = node['leftChild']
node = stack.pop()
pair = node['data']
yield f"[{idx}].key", pair['key']
yield f"[{idx}].value", pair['value']
idx += 1
node = node['rightChild']
def display_hint(self):
return "map"
class VectorPrinter: class VectorPrinter:
def __init__(self, val): def __init__(self, val):
self.val = val self.val = val
@@ -53,6 +132,8 @@ class VectorPrinter:
def build_pretty_printer(): def build_pretty_printer():
pp = gdb.printing.RegexpCollectionPrettyPrinter("Seele") pp = gdb.printing.RegexpCollectionPrettyPrinter("Seele")
pp.add_printer("Array", r'^Seele::Array<.*>$', ArrayPrinter) pp.add_printer("Array", r'^Seele::Array<.*>$', ArrayPrinter)
pp.add_printer("List", r'^Seele::List<.*>$', ListPrinter)
pp.add_printer("Map", r'^Seele::Map<.*>$', MapPrinter)
pp.add_printer("Vector", r"^glm::(detail::)?t?vec(\d)?<[^<>]*>$", VectorPrinter) pp.add_printer("Vector", r"^glm::(detail::)?t?vec(\d)?<[^<>]*>$", VectorPrinter)
return pp return pp
+37
View File
@@ -31,6 +31,39 @@ class ArraySyntheticProvider:
def has_children(self): def has_children(self):
return True return True
def List_SummaryProvider(valobj, internal_dict):
size = valobj.GetChildMemberWithName('_size').GetValueAsUnsigned(0)
return f"List(size={size})"
class ListSyntheticProvider:
def __init__(self, valobj, internal_dict):
self.valobj = valobj
self.update()
def num_children(self):
return self.size
def get_child_index(self, name):
try:
return int(name.lstrip('[').rstrip(']'))
except:
return -1
def get_child_at_index(self, index):
if index < 0 or index >= self.size:
return None
current = self.root
for i in range(index):
current = current.GetChildMemberWithName('next')
return current.GetChildMemberWithName('data')
def update(self):
self.root = self.valobj.GetChildMemberWithName('root')
self.size = self.valobj.GetChildMemberWithName('_size').GetValueAsUnsigned(0)
def has_children(self):
return True
def Vector_SummaryProvider(valobj, internal_dict): def Vector_SummaryProvider(valobj, internal_dict):
# Get the template parameters to determine vector length # Get the template parameters to determine vector length
type_name = valobj.GetTypeName() type_name = valobj.GetTypeName()
@@ -56,6 +89,10 @@ def __lldb_init_module(debugger, internal_dict):
debugger.HandleCommand('type summary add -F Seele_lldb.Array_SummaryProvider -x "^Seele::Array<.*>$"') debugger.HandleCommand('type summary add -F Seele_lldb.Array_SummaryProvider -x "^Seele::Array<.*>$"')
debugger.HandleCommand('type synthetic add -l Seele_lldb.ArraySyntheticProvider -x "^Seele::Array<.*>$"') debugger.HandleCommand('type synthetic add -l Seele_lldb.ArraySyntheticProvider -x "^Seele::Array<.*>$"')
# Register List formatter
debugger.HandleCommand('type summary add -F Seele_lldb.List_SummaryProvider -x "^Seele::List<.*>$"')
debugger.HandleCommand('type synthetic add -l Seele_lldb.ListSyntheticProvider -x "^Seele::List<.*>$"')
# Register Vector formatter # Register Vector formatter
debugger.HandleCommand('type summary add -F Seele_lldb.Vector_SummaryProvider -x "^glm::(detail::)?t?vec[234]?<.*>$"') debugger.HandleCommand('type summary add -F Seele_lldb.Vector_SummaryProvider -x "^glm::(detail::)?t?vec[234]?<.*>$"')
+55
View File
@@ -0,0 +1,55 @@
import FluidGridData;
struct Params
{
// read-write
FluidGridData<float> density;
// read-only
FluidGridData<float> density0;
// read-only
FluidGridData<float> velocityX;
// read-only
FluidGridData<float> velocityY;
// read-only
FluidGridData<float> velocityZ;
float dt;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void advect(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> density = params.density;
FluidGridData<float> density0 = params.density0;
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
float dt = params.dt;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
float dt0x = dt * (gridSize.x - 2);
float dt0y = dt * (gridSize.y - 2);
float dt0z = dt * (gridSize.z - 2);
float3 pos = float3(x - dt0x * velocityX[x, y, z], y - dt0y * velocityY[x, y, z], z - dt0z * velocityZ[x, y, z]);
pos.x = clamp(pos.x, 0.5f, gridSize.x - 1.5f);
pos.y = clamp(pos.y, 0.5f, gridSize.y - 1.5f);
pos.z = clamp(pos.z, 0.5f, gridSize.z - 1.5f);
int3 i0 = int3(pos);
int3 i1 = i0 + int3(1, 1, 1);
float3 s1 = pos - i0;
float3 s0 = 1 - s1;
density[x, y, z] =
s0.x * (s0.y * (s0.z * density0[i0.x, i0.y, i0.z] + s1.z * density0[i0.x, i0.y, i1.z]) +
s1.y * (s0.z * density0[i0.x, i1.y, i0.z] + s1.z * density0[i0.x, i1.y, i1.z])) +
s1.x * (s0.y * (s0.z * density0[i1.x, i0.y, i0.z] + s1.z * density0[i1.x, i0.y, i1.z]) +
s1.y * (s0.z * density0[i1.x, i1.y, i0.z] + s1.z * density0[i1.x, i1.y, i1.z]));
}
+35
View File
@@ -0,0 +1,35 @@
import FluidGridData;
struct Params
{
// read-only
FluidGridData<float> velocityX;
// read-only
FluidGridData<float> velocityY;
// read-only
FluidGridData<float> velocityZ;
// read-write
FluidGridData<float> divergence;
// read-write
FluidGridData<float> pressure;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void computeDivergence(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
FluidGridData<float> divergence = params.divergence;
FluidGridData<float> pressure = params.pressure;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
divergence[x, y, z] = -0.5f * (velocityX[x + 1, y, z] - velocityX[x - 1, y, z] + velocityY[x, y + 1, z] - velocityY[x, y - 1, z] + velocityZ[x, y, z + 1] - velocityZ[x, y, z - 1]) / gridSize.x;
pressure[x, y, z] = 0;
}
+47
View File
@@ -0,0 +1,47 @@
import FluidGridData;
struct Parameter
{
float iso;
FluidGridData<float> density;
RWStructuredBuffer<float3> vertices;
RWStructuredBuffer<uint> indices;
RWStructuredBuffer<uint> surfaceCount;
RWStructuredBuffer<uint> vertexCount;
};
ParameterBlock<Parameter> params;
float getDensity(uint x, uint y, uint z)
{
return params.density[x + gridSize.x * y + gridSize.x * gridSize.y * z];
}
[shader("compute")]
[numthreads(32, 8, 1)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID)
{
uint x = dispatchThreadID.x+1;
uint y = dispatchThreadID.y+1;
uint z = dispatchThreadID.z+1;
FluidGridData<float> density = params.density;
if(x >= gridSize.x-3 || y >= gridSize.y-3 || z >= gridSize.z-3) return;
float phi[8] = {
getDensity(x, y, z),
getDensity(x + 1, y, z),
getDensity(x, y + 1, z),
getDensity(x + 1, y + 1, z),
getDensity(x, y, z + 1),
getDensity(x + 1, y, z + 1),
getDensity(x, y + 1, z + 1),
getDensity(x + 1, y + 1, z + 1)
};
uint cubeIndex = 0;
for (uint i = 0; i < 8; ++i) {
if (phi[i] < params.iso) {
cubeIndex |= (1 << i);
}
}
if(cubeIndex == 0 || cubeIndex == 255) return;
}
+15
View File
@@ -0,0 +1,15 @@
static const uint3 gridSize = uint3(256, 256, 256);
struct FluidGridData<T>
{
RWStructuredBuffer<T> dataGrid;
__subscript(uint3 index) -> T
{
get { return dataGrid[index.x + index.y * gridSize.x + index.z * gridSize.x * gridSize.y]; }
set { dataGrid[index.x + index.y * gridSize.x + index.z * gridSize.x * gridSize.y] = newValue; }
}
__subscript(uint x, uint y, uint z) -> T
{
get { return dataGrid[x + y * gridSize.x + z * gridSize.x * gridSize.y]; }
set { dataGrid[x + y * gridSize.x + z * gridSize.x * gridSize.y] = newValue; }
}
};
+32
View File
@@ -0,0 +1,32 @@
import FluidGridData;
struct Params
{
// read-write
FluidGridData<float> next;
// read-only
FluidGridData<float> current;
// read-only
FluidGridData<float> grid0;
float a;
float c;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void linearSolve(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> next = params.next;
FluidGridData<float> current = params.current;
FluidGridData<float> grid0 = params.grid0;
float a = params.a;
float cRecip = 1.0f / params.c;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
next[x, y, z] = (grid0[x, y, z] + a * (current[x + 1, y, z] + current[x - 1, y, z] + current[x, y + 1, z] + current[x, y - 1, z] + current[x, y, z + 1] + current[x, y, z - 1])) * cRecip;
}
+205
View File
@@ -0,0 +1,205 @@
import FluidGridData;
import MarchingCubesData;
struct Params
{
RWStructuredBuffer<float> vertexBuffer;
RWStructuredBuffer<float> normalBuffer;
RWStructuredBuffer<uint> indexBuffer;
RWStructuredBuffer<uint> indicesCount;
FluidGridData<float> levelSet;
};
ParameterBlock<Params> params;
const static float isoLevel = 0.0f;
const static float3 cellSize = 1.0f / gridSize;
float3 vertexInterp(float isoLevel, float3 p1, float3 p2, float valp1, float valp2)
{
if (abs(isoLevel - valp1) < 0.00001)
return p1;
if (abs(isoLevel - valp2) < 0.00001)
return p2;
if (abs(valp1 - valp2) < 0.00001)
return p1;
float mu = (isoLevel - valp1) / (valp2 - valp1);
return p1 + mu * (p2 - p1);
}
float3 gridPos(uint x, uint y, uint z)
{
return float3(x, y, z) * cellSize;
}
// TODO: parameterize
const static uint32_t LOCAL_THREADGROUP_SIZE = 16 * 8 * 1; // Must match numthreads
const static uint32_t MAX_TRIS_PER_THREAD = 5; // Max triangles per cube configuration
const static uint32_t MAX_VERTS_PER_GROUP = LOCAL_THREADGROUP_SIZE * MAX_TRIS_PER_THREAD * 3;
groupshared float3 localVertices[MAX_VERTS_PER_GROUP];
groupshared float3 localNormals[MAX_VERTS_PER_GROUP];
groupshared uint localTriCounts[LOCAL_THREADGROUP_SIZE]; // per-thread triangle counts
groupshared uint localOffsets[LOCAL_THREADGROUP_SIZE]; // per-thread exclusive offsets (in vertices)
groupshared uint localBaseOffset; // global base offset for this workgroup
// Hillis-Steele inclusive scan on localTriCounts, result in localOffsets
// Then convert to exclusive scan and allocate global space
void prefixSumAndAllocate(uint groupIndex)
{
localOffsets[groupIndex] = localTriCounts[groupIndex];
GroupMemoryBarrierWithGroupSync();
for (uint offset = 1; offset < LOCAL_THREADGROUP_SIZE; offset *= 2)
{
uint temp = 0;
if (groupIndex >= offset)
temp = localOffsets[groupIndex - offset];
GroupMemoryBarrierWithGroupSync();
localOffsets[groupIndex] += temp;
GroupMemoryBarrierWithGroupSync();
}
// localOffsets is now an inclusive prefix sum
// Last thread has the total — allocate global space
if (groupIndex == LOCAL_THREADGROUP_SIZE - 1)
{
uint totalVerts = localOffsets[groupIndex] * 3;
InterlockedAdd(params.indicesCount[0], totalVerts, localBaseOffset);
}
GroupMemoryBarrierWithGroupSync();
// Convert inclusive to exclusive: shift right, first element = 0
uint inclusive = localOffsets[groupIndex];
GroupMemoryBarrierWithGroupSync();
localOffsets[groupIndex] = (groupIndex == 0) ? 0 : localOffsets[groupIndex - 1];
GroupMemoryBarrierWithGroupSync();
}
[shader("compute")]
[numthreads(16, 8, 1)]
void marchingCubes(uint3 dispatchThreadID : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
{
uint x = dispatchThreadID.x + 1;
uint y = dispatchThreadID.y + 1;
uint z = dispatchThreadID.z + 1;
FluidGridData<float> levelSet = params.levelSet;
// Don't early-return — all threads must participate in barriers.
// Use a flag to skip work for out-of-bounds threads.
bool valid = (x < gridSize.x - 2 && y < gridSize.y - 2 && z < gridSize.z - 2);
float val[8];
uint cubeIndex = 0;
uint triCount = 0;
if (valid)
{
val[0] = levelSet[x, y, z];
val[1] = levelSet[x + 1, y, z];
val[2] = levelSet[x + 1, y + 1, z];
val[3] = levelSet[x, y + 1, z];
val[4] = levelSet[x, y, z + 1];
val[5] = levelSet[x + 1, y, z + 1];
val[6] = levelSet[x + 1, y + 1, z + 1];
val[7] = levelSet[x, y + 1, z + 1];
if (val[0] < isoLevel) cubeIndex |= 1;
if (val[1] < isoLevel) cubeIndex |= 2;
if (val[2] < isoLevel) cubeIndex |= 4;
if (val[3] < isoLevel) cubeIndex |= 8;
if (val[4] < isoLevel) cubeIndex |= 16;
if (val[5] < isoLevel) cubeIndex |= 32;
if (val[6] < isoLevel) cubeIndex |= 64;
if (val[7] < isoLevel) cubeIndex |= 128;
for (int i = 0; triTable[cubeIndex][i] != -1; i += 3)
triCount++;
}
// Prefix sum to compute per-thread offsets and allocate global space
localTriCounts[groupIndex] = triCount;
GroupMemoryBarrierWithGroupSync();
prefixSumAndAllocate(groupIndex);
// localOffsets[groupIndex] = exclusive sum of triCounts before this thread
// localBaseOffset = global vertex offset for this workgroup
if (valid && triCount > 0)
{
float3 pos[8];
pos[0] = gridPos(x, y, z);
pos[1] = gridPos(x + 1, y, z);
pos[2] = gridPos(x + 1, y + 1, z);
pos[3] = gridPos(x, y + 1, z);
pos[4] = gridPos(x, y, z + 1);
pos[5] = gridPos(x + 1, y, z + 1);
pos[6] = gridPos(x + 1, y + 1, z + 1);
pos[7] = gridPos(x, y + 1, z + 1);
float3 vertList[12];
if ((edgeTable[cubeIndex] & 1) != 0)
vertList[0] = vertexInterp(isoLevel, pos[0], pos[1], val[0], val[1]);
if ((edgeTable[cubeIndex] & 2) != 0)
vertList[1] = vertexInterp(isoLevel, pos[1], pos[2], val[1], val[2]);
if ((edgeTable[cubeIndex] & 4) != 0)
vertList[2] = vertexInterp(isoLevel, pos[2], pos[3], val[2], val[3]);
if ((edgeTable[cubeIndex] & 8) != 0)
vertList[3] = vertexInterp(isoLevel, pos[3], pos[0], val[3], val[0]);
if ((edgeTable[cubeIndex] & 16) != 0)
vertList[4] = vertexInterp(isoLevel, pos[4], pos[5], val[4], val[5]);
if ((edgeTable[cubeIndex] & 32) != 0)
vertList[5] = vertexInterp(isoLevel, pos[5], pos[6], val[5], val[6]);
if ((edgeTable[cubeIndex] & 64) != 0)
vertList[6] = vertexInterp(isoLevel, pos[6], pos[7], val[6], val[7]);
if ((edgeTable[cubeIndex] & 128) != 0)
vertList[7] = vertexInterp(isoLevel, pos[7], pos[4], val[7], val[4]);
if ((edgeTable[cubeIndex] & 256) != 0)
vertList[8] = vertexInterp(isoLevel, pos[0], pos[4], val[0], val[4]);
if ((edgeTable[cubeIndex] & 512) != 0)
vertList[9] = vertexInterp(isoLevel, pos[1], pos[5], val[1], val[5]);
if ((edgeTable[cubeIndex] & 1024) != 0)
vertList[10] = vertexInterp(isoLevel, pos[2], pos[6], val[2], val[6]);
if ((edgeTable[cubeIndex] & 2048) != 0)
vertList[11] = vertexInterp(isoLevel, pos[3], pos[7], val[3], val[7]);
// Write triangles into shared memory
uint localOff = localOffsets[groupIndex] * 3; // in vertices
for (int i = 0; triTable[cubeIndex][i] != -1; i += 3)
{
float3 v0 = vertList[triTable[cubeIndex][i]];
float3 v1 = vertList[triTable[cubeIndex][i + 1]];
float3 v2 = vertList[triTable[cubeIndex][i + 2]];
float3 n = normalize(cross(v1 - v0, v2 - v0));
localVertices[localOff] = v0;
localVertices[localOff + 1] = v1;
localVertices[localOff + 2] = v2;
localNormals[localOff] = n;
localNormals[localOff + 1] = n;
localNormals[localOff + 2] = n;
localOff += 3;
}
}
GroupMemoryBarrierWithGroupSync();
// Copy from shared memory to global buffers
// Each thread copies a chunk of the workgroup's output
uint totalGroupVerts = localTriCounts[LOCAL_THREADGROUP_SIZE - 1] > 0
? (localOffsets[LOCAL_THREADGROUP_SIZE - 1] + localTriCounts[LOCAL_THREADGROUP_SIZE - 1]) * 3
: localOffsets[LOCAL_THREADGROUP_SIZE - 1] * 3;
for (uint i = groupIndex; i < totalGroupVerts; i += LOCAL_THREADGROUP_SIZE)
{
uint globalIdx = localBaseOffset + i;
float3 v = localVertices[i];
float3 n = localNormals[i];
params.vertexBuffer[globalIdx * 3 + 0] = v.x;
params.vertexBuffer[globalIdx * 3 + 1] = v.y;
params.vertexBuffer[globalIdx * 3 + 2] = v.z;
params.normalBuffer[globalIdx * 3 + 0] = n.x;
params.normalBuffer[globalIdx * 3 + 1] = n.y;
params.normalBuffer[globalIdx * 3 + 2] = n.z;
params.indexBuffer[globalIdx] = globalIdx;
}
}
+299
View File
@@ -0,0 +1,299 @@
// Marching Cubes edge table: for each cube configuration (256), a 12-bit mask
// indicating which edges are intersected by the isosurface.
// clang-format off
static const uint16_t edgeTable[256] = {
0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c,
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc,
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c,
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc,
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460,
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0,
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230,
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190,
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000,
};
// Marching Cubes triangle table: for each cube configuration, up to 5
// triangles specified as sequences of edge indices, terminated by -1.
static const int8_t triTable[256][16] = {
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,8,3,9,8,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,3,1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,2,10,0,2,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,8,3,2,10,8,10,9,8,-1,-1,-1,-1,-1,-1,-1},
{3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,11,2,8,11,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,9,0,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,11,2,1,9,11,9,8,11,-1,-1,-1,-1,-1,-1,-1},
{3,10,1,11,10,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,10,1,0,8,10,8,11,10,-1,-1,-1,-1,-1,-1,-1},
{3,9,0,3,11,9,11,10,9,-1,-1,-1,-1,-1,-1,-1},
{9,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,3,0,7,3,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,1,9,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,1,9,4,7,1,7,3,1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,4,7,3,0,4,1,2,10,-1,-1,-1,-1,-1,-1,-1},
{9,2,10,9,0,2,8,4,7,-1,-1,-1,-1,-1,-1,-1},
{2,10,9,2,9,7,2,7,3,7,9,4,-1,-1,-1,-1},
{8,4,7,3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{11,4,7,11,2,4,2,0,4,-1,-1,-1,-1,-1,-1,-1},
{9,0,1,8,4,7,2,3,11,-1,-1,-1,-1,-1,-1,-1},
{4,7,11,9,4,11,9,11,2,9,2,1,-1,-1,-1,-1},
{3,10,1,3,11,10,7,8,4,-1,-1,-1,-1,-1,-1,-1},
{1,11,10,1,4,11,1,0,4,7,11,4,-1,-1,-1,-1},
{4,7,8,9,0,11,9,11,10,11,0,3,-1,-1,-1,-1},
{4,7,11,4,11,9,9,11,10,-1,-1,-1,-1,-1,-1,-1},
{9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,5,4,0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,5,4,1,5,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{8,5,4,8,3,5,3,1,5,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,0,8,1,2,10,4,9,5,-1,-1,-1,-1,-1,-1,-1},
{5,2,10,5,4,2,4,0,2,-1,-1,-1,-1,-1,-1,-1},
{2,10,5,3,2,5,3,5,4,3,4,8,-1,-1,-1,-1},
{9,5,4,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,11,2,0,8,11,4,9,5,-1,-1,-1,-1,-1,-1,-1},
{0,5,4,0,1,5,2,3,11,-1,-1,-1,-1,-1,-1,-1},
{2,1,5,2,5,8,2,8,11,4,8,5,-1,-1,-1,-1},
{10,3,11,10,1,3,9,5,4,-1,-1,-1,-1,-1,-1,-1},
{4,9,5,0,8,1,8,10,1,8,11,10,-1,-1,-1,-1},
{5,4,0,5,0,11,5,11,10,11,0,3,-1,-1,-1,-1},
{5,4,8,5,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1},
{9,7,8,5,7,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,3,0,9,5,3,5,7,3,-1,-1,-1,-1,-1,-1,-1},
{0,7,8,0,1,7,1,5,7,-1,-1,-1,-1,-1,-1,-1},
{1,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,7,8,9,5,7,10,1,2,-1,-1,-1,-1,-1,-1,-1},
{10,1,2,9,5,0,5,3,0,5,7,3,-1,-1,-1,-1},
{8,0,2,8,2,5,8,5,7,10,5,2,-1,-1,-1,-1},
{2,10,5,2,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1},
{7,9,5,7,8,9,3,11,2,-1,-1,-1,-1,-1,-1,-1},
{9,5,7,9,7,2,9,2,0,2,7,11,-1,-1,-1,-1},
{2,3,11,0,1,8,1,7,8,1,5,7,-1,-1,-1,-1},
{11,2,1,11,1,7,7,1,5,-1,-1,-1,-1,-1,-1,-1},
{9,5,8,8,5,7,10,1,3,10,3,11,-1,-1,-1,-1},
{5,7,0,5,0,9,7,11,0,1,0,10,11,10,0,-1},
{11,10,0,11,0,3,10,5,0,8,0,7,5,7,0,-1},
{11,10,5,7,11,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,3,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,0,1,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,8,3,1,9,8,5,10,6,-1,-1,-1,-1,-1,-1},
{1,6,5,2,6,1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,6,5,1,2,6,3,0,8,-1,-1,-1,-1,-1,-1},
{9,6,5,9,0,6,0,2,6,-1,-1,-1,-1,-1,-1},
{5,9,8,5,8,2,5,2,6,3,2,8,-1,-1,-1,-1},
{2,3,11,10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{11,0,8,11,2,0,10,6,5,-1,-1,-1,-1,-1,-1},
{0,1,9,2,3,11,5,10,6,-1,-1,-1,-1,-1,-1},
{5,10,6,1,9,2,9,11,2,9,8,11,-1,-1,-1,-1},
{6,3,11,6,5,3,5,1,3,-1,-1,-1,-1,-1,-1,-1},
{0,8,11,0,11,5,0,5,1,5,11,6,-1,-1,-1,-1},
{3,11,6,0,3,6,0,6,5,0,5,9,-1,-1,-1,-1},
{6,5,9,6,9,11,11,9,8,-1,-1,-1,-1,-1,-1,-1},
{5,10,6,4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,3,0,4,7,3,6,5,10,-1,-1,-1,-1,-1,-1,-1},
{1,9,0,5,10,6,8,4,7,-1,-1,-1,-1,-1,-1,-1},
{10,6,5,1,9,7,1,7,3,7,9,4,-1,-1,-1,-1},
{6,1,2,6,5,1,4,7,8,-1,-1,-1,-1,-1,-1,-1},
{1,2,5,5,2,6,3,0,4,3,4,7,-1,-1,-1,-1},
{8,4,7,9,0,5,0,6,5,0,2,6,-1,-1,-1,-1},
{7,3,9,7,9,4,3,2,9,5,9,6,2,6,9,-1},
{3,11,2,7,8,4,10,6,5,-1,-1,-1,-1,-1,-1,-1},
{5,10,6,4,7,2,4,2,0,2,7,11,-1,-1,-1,-1},
{0,1,9,4,7,8,2,3,11,5,10,6,-1,-1,-1,-1},
{9,2,1,9,11,2,9,4,11,7,11,4,5,10,6,-1},
{8,4,7,3,11,5,3,5,1,5,11,6,-1,-1,-1,-1},
{5,1,11,5,11,6,1,0,11,7,11,4,0,4,11,-1},
{0,5,9,0,6,5,0,3,6,11,6,3,8,4,7,-1},
{6,5,9,6,9,11,4,7,9,7,11,9,-1,-1,-1,-1},
{10,4,9,6,4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,10,6,4,9,10,0,8,3,-1,-1,-1,-1,-1,-1},
{10,0,1,10,6,0,6,4,0,-1,-1,-1,-1,-1,-1},
{8,3,1,8,1,6,8,6,4,6,1,10,-1,-1,-1,-1},
{1,4,9,1,2,4,2,6,4,-1,-1,-1,-1,-1,-1,-1},
{3,0,8,1,2,9,2,4,9,2,6,4,-1,-1,-1,-1},
{0,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{8,3,2,8,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1},
{10,4,9,10,6,4,11,2,3,-1,-1,-1,-1,-1,-1},
{0,8,2,2,8,11,4,9,10,4,10,6,-1,-1,-1,-1},
{3,11,2,0,1,6,0,6,4,6,1,10,-1,-1,-1,-1},
{6,4,1,6,1,10,4,8,1,2,1,11,8,11,1,-1},
{9,6,4,9,3,6,9,1,3,11,6,3,-1,-1,-1,-1},
{8,11,1,8,1,0,11,6,1,9,1,4,6,4,1,-1},
{3,11,6,3,6,0,0,6,4,-1,-1,-1,-1,-1,-1,-1},
{6,4,8,11,6,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{7,10,6,7,8,10,8,9,10,-1,-1,-1,-1,-1,-1,-1},
{0,7,3,0,10,7,0,9,10,6,7,10,-1,-1,-1,-1},
{10,6,7,1,10,7,1,7,8,1,8,0,-1,-1,-1,-1},
{10,6,7,10,7,1,1,7,3,-1,-1,-1,-1,-1,-1,-1},
{1,2,6,1,6,8,1,8,9,8,6,7,-1,-1,-1,-1},
{2,6,9,2,9,1,6,7,9,0,9,3,7,3,9,-1},
{7,8,0,7,0,6,6,0,2,-1,-1,-1,-1,-1,-1,-1},
{7,3,2,6,7,2,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,3,11,10,6,8,10,8,9,8,6,7,-1,-1,-1,-1},
{2,0,7,2,7,11,0,9,7,6,7,10,9,10,7,-1},
{1,8,0,1,7,8,1,10,7,6,7,10,2,3,11,-1},
{11,2,1,11,1,7,10,6,1,6,7,1,-1,-1,-1,-1},
{8,9,6,8,6,7,9,1,6,11,6,3,1,3,6,-1},
{0,9,1,11,6,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{7,8,0,7,0,6,3,11,0,11,6,0,-1,-1,-1,-1},
{7,11,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,0,8,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,1,9,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{8,1,9,8,3,1,11,7,6,-1,-1,-1,-1,-1,-1},
{10,1,2,6,11,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,3,0,8,6,11,7,-1,-1,-1,-1,-1,-1},
{2,9,0,2,10,9,6,11,7,-1,-1,-1,-1,-1,-1},
{6,11,7,2,10,3,10,8,3,10,9,8,-1,-1,-1,-1},
{7,2,3,6,2,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{7,0,8,7,6,0,6,2,0,-1,-1,-1,-1,-1,-1,-1},
{2,7,6,2,3,7,0,1,9,-1,-1,-1,-1,-1,-1,-1},
{1,6,2,1,8,6,1,9,8,8,7,6,-1,-1,-1,-1},
{10,7,6,10,1,7,1,3,7,-1,-1,-1,-1,-1,-1,-1},
{10,7,6,1,7,10,1,8,7,1,0,8,-1,-1,-1,-1},
{0,3,7,0,7,10,0,10,9,6,10,7,-1,-1,-1,-1},
{7,6,10,7,10,8,8,10,9,-1,-1,-1,-1,-1,-1,-1},
{6,8,4,11,8,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,6,11,3,0,6,0,4,6,-1,-1,-1,-1,-1,-1,-1},
{8,6,11,8,4,6,9,0,1,-1,-1,-1,-1,-1,-1,-1},
{9,4,6,9,6,3,9,3,1,11,3,6,-1,-1,-1,-1},
{6,8,4,6,11,8,2,10,1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,3,0,11,0,6,11,0,4,6,-1,-1,-1,-1},
{4,11,8,4,6,11,0,2,9,2,10,9,-1,-1,-1,-1},
{10,9,3,10,3,2,9,4,3,11,3,6,4,6,3,-1},
{8,2,3,8,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1},
{0,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,9,0,2,3,4,2,4,6,4,3,8,-1,-1,-1,-1},
{1,9,4,1,4,2,2,4,6,-1,-1,-1,-1,-1,-1,-1},
{8,1,3,8,6,1,8,4,6,6,10,1,-1,-1,-1,-1},
{10,1,0,10,0,6,6,0,4,-1,-1,-1,-1,-1,-1,-1},
{4,6,3,4,3,8,6,10,3,0,3,9,10,9,3,-1},
{10,9,4,6,10,4,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,9,5,7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,3,4,9,5,11,7,6,-1,-1,-1,-1,-1,-1,-1},
{5,0,1,5,4,0,7,6,11,-1,-1,-1,-1,-1,-1,-1},
{11,7,6,8,3,4,3,5,4,3,1,5,-1,-1,-1,-1},
{9,5,4,10,1,2,7,6,11,-1,-1,-1,-1,-1,-1,-1},
{6,11,7,1,2,10,0,8,3,4,9,5,-1,-1,-1,-1},
{7,6,11,5,4,10,4,2,10,4,0,2,-1,-1,-1,-1},
{3,4,8,3,5,4,3,2,5,10,5,2,11,7,6,-1},
{7,2,3,7,6,2,5,4,9,-1,-1,-1,-1,-1,-1,-1},
{9,5,4,0,8,6,0,6,2,6,8,7,-1,-1,-1,-1},
{3,6,2,3,7,6,1,5,0,5,4,0,-1,-1,-1,-1},
{6,2,8,6,8,7,2,1,8,4,8,5,1,5,8,-1},
{9,5,4,10,1,6,1,7,6,1,3,7,-1,-1,-1,-1},
{1,6,10,1,7,6,1,0,7,8,7,0,9,5,4,-1},
{4,0,10,4,10,5,0,3,10,6,10,7,3,7,10,-1},
{7,6,10,7,10,8,5,4,10,4,8,10,-1,-1,-1,-1},
{6,9,5,6,11,9,11,8,9,-1,-1,-1,-1,-1,-1,-1},
{3,6,11,0,6,3,0,5,6,0,9,5,-1,-1,-1,-1},
{0,11,8,0,5,11,0,1,5,5,6,11,-1,-1,-1,-1},
{6,11,3,6,3,5,5,3,1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,9,5,11,9,11,8,11,5,6,-1,-1,-1,-1},
{0,11,3,0,6,11,0,9,6,5,6,9,1,2,10,-1},
{11,8,5,11,5,6,8,0,5,10,5,2,0,2,5,-1},
{6,11,3,6,3,5,2,10,3,10,5,3,-1,-1,-1,-1},
{5,8,9,5,2,8,5,6,2,3,8,2,-1,-1,-1,-1},
{9,5,6,9,6,0,0,6,2,-1,-1,-1,-1,-1,-1,-1},
{1,5,8,1,8,0,5,6,8,3,8,2,6,2,8,-1},
{1,5,6,2,1,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,3,6,1,6,10,3,8,6,5,6,9,8,9,6,-1},
{10,1,0,10,0,6,9,5,0,5,6,0,-1,-1,-1,-1},
{0,3,8,5,6,10,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{10,5,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{11,5,10,7,5,11,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{11,5,10,11,7,5,8,3,0,-1,-1,-1,-1,-1,-1},
{5,11,7,5,10,11,1,9,0,-1,-1,-1,-1,-1,-1},
{10,7,5,10,11,7,9,8,1,8,3,1,-1,-1,-1,-1},
{11,1,2,11,7,1,7,5,1,-1,-1,-1,-1,-1,-1},
{0,8,3,1,2,7,1,7,5,7,2,11,-1,-1,-1,-1},
{9,7,5,9,2,7,9,0,2,2,11,7,-1,-1,-1,-1},
{7,5,2,7,2,11,5,9,2,3,2,8,9,8,2,-1},
{2,5,10,2,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1},
{8,2,0,8,5,2,8,7,5,10,2,5,-1,-1,-1,-1},
{9,0,1,5,10,3,5,3,7,3,10,2,-1,-1,-1,-1},
{9,8,2,9,2,1,8,7,2,10,2,5,7,5,2,-1},
{1,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,7,0,7,1,1,7,5,-1,-1,-1,-1,-1,-1,-1},
{9,0,3,9,3,5,5,3,7,-1,-1,-1,-1,-1,-1,-1},
{9,8,7,5,9,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{5,8,4,5,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1},
{5,0,4,5,11,0,5,10,11,11,3,0,-1,-1,-1,-1},
{0,1,9,8,4,10,8,10,11,10,4,5,-1,-1,-1,-1},
{10,11,4,10,4,5,11,3,4,9,4,1,3,1,4,-1},
{2,5,1,2,8,5,2,11,8,4,5,8,-1,-1,-1,-1},
{0,4,11,0,11,3,4,5,11,2,11,1,5,1,11,-1},
{0,2,5,0,5,9,2,11,5,4,5,8,11,8,5,-1},
{9,4,5,2,11,3,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,5,10,3,5,2,3,4,5,3,8,4,-1,-1,-1,-1},
{5,10,2,5,2,4,4,2,0,-1,-1,-1,-1,-1,-1,-1},
{3,10,2,3,5,10,3,8,5,4,5,8,0,1,9,-1},
{5,10,2,5,2,4,1,9,2,9,4,2,-1,-1,-1,-1},
{8,4,5,8,5,3,3,5,1,-1,-1,-1,-1,-1,-1,-1},
{0,4,5,1,0,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{8,4,5,8,5,3,9,0,5,0,3,5,-1,-1,-1,-1},
{9,4,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,11,7,4,9,11,9,10,11,-1,-1,-1,-1,-1,-1},
{0,8,3,4,9,7,9,11,7,9,10,11,-1,-1,-1,-1},
{1,10,11,1,11,4,1,4,0,7,4,11,-1,-1,-1,-1},
{3,1,4,3,4,8,1,10,4,7,4,11,10,11,4,-1},
{4,11,7,9,11,4,9,2,11,9,1,2,-1,-1,-1,-1},
{9,7,4,9,11,7,9,1,11,2,11,1,0,8,3,-1},
{11,7,4,11,4,2,2,4,0,-1,-1,-1,-1,-1,-1,-1},
{11,7,4,11,4,2,8,3,4,3,2,4,-1,-1,-1,-1},
{2,9,10,2,7,9,2,3,7,7,4,9,-1,-1,-1,-1},
{9,10,7,9,7,4,10,2,7,8,7,0,2,0,7,-1},
{3,7,10,3,10,2,7,4,10,1,10,0,4,0,10,-1},
{1,10,2,8,7,4,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,9,1,4,1,7,7,1,3,-1,-1,-1,-1,-1,-1,-1},
{4,9,1,4,1,7,0,8,1,8,7,1,-1,-1,-1,-1},
{4,0,3,7,4,3,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,8,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,0,9,3,9,11,11,9,10,-1,-1,-1,-1,-1,-1,-1},
{0,1,10,0,10,8,8,10,11,-1,-1,-1,-1,-1,-1,-1},
{3,1,10,11,3,10,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,2,11,1,11,9,9,11,8,-1,-1,-1,-1,-1,-1,-1},
{3,0,9,3,9,11,1,2,9,2,11,9,-1,-1,-1,-1},
{0,2,11,8,0,11,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,2,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,3,8,2,8,10,10,8,9,-1,-1,-1,-1,-1,-1,-1},
{9,10,2,0,9,2,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,3,8,2,8,10,0,1,8,1,10,8,-1,-1,-1,-1},
{1,10,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,3,8,9,1,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,9,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,3,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
};
// clang-format on
+33
View File
@@ -0,0 +1,33 @@
import FluidGridData;
struct Params
{
// read-write
FluidGridData<float> velocityX;
// read-write
FluidGridData<float> velocityY;
// read-write
FluidGridData<float> velocityZ;
// read-only
FluidGridData<float> pressure;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void project(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
FluidGridData<float> pressure = params.pressure;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
velocityX[x, y, z] -= 0.5f * (pressure[x + 1, y, z] - pressure[x - 1, y, z]) * gridSize.x;
velocityY[x, y, z] -= 0.5f * (pressure[x, y + 1, z] - pressure[x, y - 1, z]) * gridSize.y;
velocityZ[x, y, z] -= 0.5f * (pressure[x, y, z + 1] - pressure[x, y, z - 1]) * gridSize.z;
}
+59
View File
@@ -0,0 +1,59 @@
import Common;
import FluidGridData;
import LightEnv;
import MaterialParameter;
struct Params
{
StructuredBuffer<float> vertexBuffer;
StructuredBuffer<float> normalBuffer;
StructuredBuffer<uint> indexBuffer;
};
ParameterBlock<Params> params;
struct VertexOut
{
float3 position_WS : POSITION;
float4 position_CS : SV_Position;
float3 normal : NORMAL;
};
[shader("vertex")]
VertexOut vertexMain(uint vertexId : SV_VertexID)
{
VertexOut output;
uint index = params.indexBuffer[vertexId];
float3 vertex = float3(params.vertexBuffer[index * 3 + 0],
params.vertexBuffer[index * 3 + 1],
params.vertexBuffer[index * 3 + 2]) * 5;
float3 normal = float3(params.normalBuffer[index * 3 + 0],
params.normalBuffer[index * 3 + 1],
params.normalBuffer[index * 3 + 2]);
output.position_WS = vertex;
output.position_CS = mul(pViewParams.viewProjectionMatrix, float4(vertex, 1));
output.normal = normal;
return output;
}
[shader("pixel")]
float4 fragmentMain(VertexOut input) : SV_Target
{
BlinnPhong brdf;
brdf.baseColor = float3(0, 0, 1);
brdf.alpha = 1;
brdf.specularColor = float3(1, 1, 1);
brdf.normal = input.normal;
brdf.shininess = 32;
brdf.ambient = float3(0.1, 0.1, 0.1);
brdf.emissive = float3(0, 0, 0);
float3 result = float3(0, 0, 0);
float3 viewDir = normalize(pViewParams.cameraPosition_WS.xyz - input.position_WS);
for(int i = 0; i < pLightEnv.numDirectionalLights; i++)
{
LightingParameter lightParams;
lightParams.position_WS = input.position_WS;
lightParams.viewDir_WS = viewDir;
result += pLightEnv.directionalLights[i].illuminate(lightParams, brdf);
}
return float4(result, 1);
}
+71
View File
@@ -0,0 +1,71 @@
import FluidGridData;
struct Params
{
int b;
// read-write
FluidGridData<float> grid;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void setBound(uint3 dispatchThreadID : SV_DispatchThreadID)
{
int b = params.b;
FluidGridData<float> grid = params.grid;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1) return;
grid[0, x, y] = b == 1 ? -grid[1, x, y] : grid[1, x, y];
grid[gridSize.x - 1, x, y] = b == 1 ? -grid[gridSize.x - 2, x, y] : grid[gridSize.x - 2, x, y];
grid[x, 0, y] = b == 2 ? -grid[x, 1, y] : grid[x, 1, y];
grid[x, gridSize.y - 1, y] = b == 2 ? -grid[x, gridSize.y - 2, y] : grid[x, gridSize.y - 2, y];
grid[x, y, 0] = b == 3 ? -grid[x, y, 1] : grid[x, y, 1];
grid[x, y, gridSize.z - 1] = b == 3 ? -grid[x, y, gridSize.z - 2] : grid[x, y, gridSize.z - 2];
}
[shader("compute")]
[numthreads(128, 1, 1)]
void setBoundEdges(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> grid = params.grid;
int x = dispatchThreadID.x + 1;
if(x >= gridSize.x - 1) return;
grid[x, 0, 0] = 0.5f * (grid[x, 1, 0] + grid[x, 0, 1]);
grid[x, gridSize.y - 1, 0] = 0.5f * (grid[x, gridSize.y - 2, 0] + grid[x, gridSize.y - 1, 1]);
grid[x, 0, gridSize.z - 1] = 0.5f * (grid[x, 1, gridSize.z - 1] + grid[x, 0, gridSize.z - 2]);
grid[x, gridSize.y - 1, gridSize.z - 1] = 0.5f * (grid[x, gridSize.y - 2, gridSize.z - 1] + grid[x, gridSize.y - 1, gridSize.z - 2]);
grid[0, x, 0] = 0.5f * (grid[1, x, 0] + grid[0, x, 1]);
grid[0, x, gridSize.z - 1] = 0.5f * (grid[1, x, gridSize.z - 1] + grid[0, x, gridSize.z - 2]);
grid[gridSize.x - 1, x, 0] = 0.5f * (grid[gridSize.x - 2, x, 0] + grid[gridSize.x - 1, x, 1]);
grid[gridSize.x - 1, x, gridSize.z - 1] = 0.5f * (grid[gridSize.x - 2, x, gridSize.z - 1] + grid[gridSize.x - 1, x, gridSize.z - 2]);
grid[0, 0, x] = 0.5f * (grid[1, 0, x] + grid[0, 1, x]);
grid[0, gridSize.y - 1, x] = 0.5f * (grid[1, gridSize.y - 1, x] + grid[0, gridSize.y - 2, x]);
grid[gridSize.x - 1, 0, x] = 0.5f * (grid[gridSize.x - 2, 0, x] + grid[gridSize.x - 1, 1, x]);
grid[gridSize.x - 1, gridSize.y - 1, x] = 0.5f * (grid[gridSize.x - 2, gridSize.y - 1, x] + grid[gridSize.x - 1, gridSize.y - 2, x]);
}
[shader("compute")]
[numthreads(8, 1, 1)]
void setBoundCorners(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> grid = params.grid;
uint threadIdx = dispatchThreadID.x;
uint x = ((threadIdx & 1) == 0) ? 0 : (gridSize.x - 1);
uint y = ((threadIdx & 2) == 0) ? 0 : (gridSize.y - 1);
uint z = ((threadIdx & 4) == 0) ? 0 : (gridSize.z - 1);
uint nx = (x == 0) ? 1 : (gridSize.x - 2);
uint ny = (y == 0) ? 1 : (gridSize.y - 2);
uint nz = (z == 0) ? 1 : (gridSize.z - 2);
grid[x, y, z] = 0.33f * (grid[nx, y, z] + grid[x, ny, z] + grid[x, y, nz]);
}
+65
View File
@@ -0,0 +1,65 @@
import FluidGridData;
struct Params
{
float dtau;
// read-write: phi being reinitialized
FluidGridData<float> phi;
// read-only: snapshot of phi before reinitialization (for sign)
FluidGridData<float> phi0;
};
ParameterBlock<Params> params;
// Smooth sign function to avoid discontinuity at zero
float smoothSign(float x, float dx)
{
return x / sqrt(x * x + dx * dx);
}
[shader("compute")]
[numthreads(32, 8, 1)]
void reinitialize(uint3 dispatchThreadID : SV_DispatchThreadID)
{
uint x = dispatchThreadID.x + 1;
uint y = dispatchThreadID.y + 1;
uint z = dispatchThreadID.z + 1;
FluidGridData<float> phi = params.phi;
FluidGridData<float> phi0 = params.phi0;
if(x >= gridSize.x - 1 || y >= gridSize.y - 1 || z >= gridSize.z - 1) return;
float dtau = params.dtau;
float dx = 1.0f;
// Current value and original sign
float p = phi[x, y, z];
float s = smoothSign(phi0[x, y, z], dx);
// Upwind finite differences for |grad phi|
// Forward and backward differences
float dxp = phi[x + 1, y, z] - p;
float dxm = p - phi[x - 1, y, z];
float dyp = phi[x, y + 1, z] - p;
float dym = p - phi[x, y - 1, z];
float dzp = phi[x, y, z + 1] - p;
float dzm = p - phi[x, y, z - 1];
// Godunov upwind scheme
float gradPhi;
if (s > 0)
{
float ax = max(max(dxm, 0.0f), -min(dxp, 0.0f));
float ay = max(max(dym, 0.0f), -min(dyp, 0.0f));
float az = max(max(dzm, 0.0f), -min(dzp, 0.0f));
gradPhi = sqrt(ax * ax + ay * ay + az * az) / dx;
}
else
{
float ax = max(-min(dxm, 0.0f), max(dxp, 0.0f));
float ay = max(-min(dym, 0.0f), max(dyp, 0.0f));
float az = max(-min(dzm, 0.0f), max(dzp, 0.0f));
gradPhi = sqrt(ax * ax + ay * ay + az * az) / dx;
}
// Update: push |grad phi| toward 1
phi[x, y, z] = p - dtau * s * (gradPhi - 1.0f);
}
-1
View File
@@ -21,7 +21,6 @@ struct ViewParameter
uint frameIndex; uint frameIndex;
float time; float time;
}; };
layout(set=0)
ParameterBlock<ViewParameter> pViewParams; ParameterBlock<ViewParameter> pViewParams;
float4 worldToModel(float4x4 inverseTransform, float4 world) float4 worldToModel(float4x4 inverseTransform, float4 world)
-1
View File
@@ -71,7 +71,6 @@ struct LightEnv
Texture2D brdfLUT; Texture2D brdfLUT;
SamplerState lutSampler; SamplerState lutSampler;
}; };
layout(set=3)
ParameterBlock<LightEnv> pLightEnv; ParameterBlock<LightEnv> pLightEnv;
interface IBRDF interface IBRDF
-1
View File
@@ -14,7 +14,6 @@ struct MaterialResources
SamplerState samplerArray[512]; SamplerState samplerArray[512];
StructuredBuffer<float> floatArray; StructuredBuffer<float> floatArray;
}; };
layout(set=4)
ParameterBlock<MaterialResources> pResources; ParameterBlock<MaterialResources> pResources;
Texture2D getMaterialTextureParameter(uint index) Texture2D getMaterialTextureParameter(uint index)
+15 -14
View File
@@ -45,20 +45,6 @@ struct MeshletCullingInfo
} }
}; };
struct DrawCallOffsets
{
uint instanceOffset;
uint textureOffset;
uint samplerOffset;
uint floatOffset;
};
#ifdef RAY_TRACING
layout(shaderRecordEXT)
#else
layout(push_constant)
#endif
ConstantBuffer<DrawCallOffsets> pOffsets;
struct Scene struct Scene
{ {
StructuredBuffer<float> positions; StructuredBuffer<float> positions;
@@ -73,6 +59,21 @@ struct Scene
}; };
ParameterBlock<Scene> pScene; ParameterBlock<Scene> pScene;
struct DrawCallOffsets
{
uint instanceOffset;
uint textureOffset;
uint samplerOffset;
uint floatOffset;
};
#ifdef RAY_TRACING
// Shader record buffers are accessed via a different mechanism and don't use descriptor set bindings
layout(set = 15, shaderRecordEXT)
#else
layout(push_constant)
#endif
ConstantBuffer<DrawCallOffsets> pOffsets;
uint32_t encodePrimitive(uint32_t meshletId) uint32_t encodePrimitive(uint32_t meshletId)
{ {
return meshletId; return meshletId;
@@ -34,5 +34,4 @@ struct StaticMeshVertexData
StructuredBuffer<uint16_t> color; StructuredBuffer<uint16_t> color;
StructuredBuffer<uint16_t> texCoords[MAX_TEXCOORDS]; StructuredBuffer<uint16_t> texCoords[MAX_TEXCOORDS];
}; };
layout(set = 1)
ParameterBlock<StaticMeshVertexData> pVertexData; ParameterBlock<StaticMeshVertexData> pVertexData;
+2 -2
View File
@@ -1,12 +1,12 @@
import Common; import Common;
import MaterialParameter; import MaterialParameter;
import LightEnv; import LightEnv;
import Scene;
import RayTracingData;
import VertexData; import VertexData;
import Material; import Material;
import StaticMeshVertexData; import StaticMeshVertexData;
import MATERIAL_FILE_NAME; import MATERIAL_FILE_NAME;
import RayTracingData;
import Scene;
// simplification: all BLAS only have 1 geometry // simplification: all BLAS only have 1 geometry
@@ -9,7 +9,6 @@ struct RayTracingParams
TextureCube<float4> skyBox; TextureCube<float4> skyBox;
SamplerState skyBoxSampler; SamplerState skyBoxSampler;
}; };
layout(set=5)
ParameterBlock<RayTracingParams> pRayTracingParams; ParameterBlock<RayTracingParams> pRayTracingParams;
struct RayPayload struct RayPayload
-2
View File
@@ -78,5 +78,3 @@ void PlayView::render() {
GameView::render(); GameView::render();
renderTimestamp->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "RenderEnd"); renderTimestamp->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "RenderEnd");
} }
void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) { GameView::keyCallback(code, action, modifier); }
-2
View File
@@ -12,8 +12,6 @@ class PlayView : public GameView {
virtual void prepareRender() override; virtual void prepareRender() override;
virtual void render() override; virtual void render() override;
virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override;
private: private:
std::thread queryThread; std::thread queryThread;
-1
View File
@@ -93,7 +93,6 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic
{"precomputeBRDF", "EnvironmentMapping"}, {"precomputeBRDF", "EnvironmentMapping"},
}, },
.rootSignature = cubePipelineLayout, .rootSignature = cubePipelineLayout,
.dumpIntermediate = true,
}); });
cubePipelineLayout->create(); cubePipelineLayout->create();
+1 -1
View File
@@ -114,7 +114,7 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) {
.uastcFlags = KTX_PACK_UASTC_LEVEL_DEFAULT, .uastcFlags = KTX_PACK_UASTC_LEVEL_DEFAULT,
.uastcRDO = true, .uastcRDO = true,
}; };
KTX_ASSERT(ktxTexture2_CompressBasisEx(kTexture, &basisParams)); // KTX_ASSERT(ktxTexture2_CompressBasis(kTexture, 0));
//KTX_ASSERT(ktxTexture2_DeflateZstd(kTexture, 10)); //KTX_ASSERT(ktxTexture2_DeflateZstd(kTexture, 10));
char writer[100]; char writer[100];
+2 -2
View File
@@ -38,11 +38,11 @@ void InspectorView::render() { renderGraph.render(Component::Camera(), Component
void InspectorView::applyArea(URect ) {} void InspectorView::applyArea(URect ) {}
void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier) {} void InspectorView::keyCallback(KeyCode, InputAction, KeyModifierFlags) {}
void InspectorView::mouseMoveCallback(double, double) {} void InspectorView::mouseMoveCallback(double, double) {}
void InspectorView::mouseButtonCallback(MouseButton, InputAction, KeyModifier) {} void InspectorView::mouseButtonCallback(MouseButton, InputAction, KeyModifierFlags) {}
void InspectorView::scrollCallback(double, double) {} void InspectorView::scrollCallback(double, double) {}
+2 -2
View File
@@ -26,9 +26,9 @@ class InspectorView : public View {
RenderGraph renderGraph; RenderGraph renderGraph;
Component::Camera cam; Component::Camera cam;
virtual void keyCallback(KeyCode code, InputAction action, KeyModifier modifier) override; virtual void keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) override;
virtual void mouseMoveCallback(double xPos, double yPos) override; virtual void mouseMoveCallback(double xPos, double yPos) override;
virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier) override; virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags modifier) override;
virtual void scrollCallback(double xOffset, double yOffset) override; virtual void scrollCallback(double xOffset, double yOffset) override;
virtual void fileCallback(int count, const char** paths) override; virtual void fileCallback(int count, const char** paths) override;
}; };
+2 -1
View File
@@ -2,6 +2,7 @@
#include "Graphics/Enums.h" #include "Graphics/Enums.h"
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Window/Window.h" #include "Window/Window.h"
#include <iostream>
using namespace Seele; using namespace Seele;
using namespace Seele::Editor; using namespace Seele::Editor;
@@ -21,7 +22,7 @@ void PlayView::prepareRender() { GameView::prepareRender(); }
void PlayView::render() { GameView::render(); } void PlayView::render() { GameView::render(); }
void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) { void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) {
GameView::keyCallback(code, action, modifier); GameView::keyCallback(code, action, modifier);
if (code == KeyCode::KEY_P && action == InputAction::RELEASE) { if (code == KeyCode::KEY_P && action == InputAction::RELEASE) {
getGlobals().usePositionOnly = !getGlobals().usePositionOnly; getGlobals().usePositionOnly = !getGlobals().usePositionOnly;
+1 -1
View File
@@ -14,7 +14,7 @@ class PlayView : public GameView {
virtual void prepareRender() override; virtual void prepareRender() override;
virtual void render() override; virtual void render() override;
virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override; virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifierFlags modifier) override;
private: private:
}; };
+2 -2
View File
@@ -42,11 +42,11 @@ void SceneView::prepareRender() {}
void SceneView::render() { renderGraph.render(viewportCamera, Component::Transform()); } void SceneView::render() { renderGraph.render(viewportCamera, Component::Transform()); }
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier) { cameraSystem.keyCallback(code, action); } void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifierFlags) { cameraSystem.keyCallback(code, action); }
void SceneView::mouseMoveCallback(double xPos, double yPos) { cameraSystem.mouseMoveCallback(xPos, yPos); } void SceneView::mouseMoveCallback(double xPos, double yPos) { cameraSystem.mouseMoveCallback(xPos, yPos); }
void SceneView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifier) { void SceneView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags) {
cameraSystem.mouseButtonCallback(button, action); cameraSystem.mouseButtonCallback(button, action);
} }
+2 -2
View File
@@ -29,9 +29,9 @@ class SceneView : public View {
ViewportControl cameraSystem; ViewportControl cameraSystem;
virtual void keyCallback(KeyCode code, InputAction action, KeyModifier modifier) override; virtual void keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) override;
virtual void mouseMoveCallback(double xPos, double yPos) override; virtual void mouseMoveCallback(double xPos, double yPos) override;
virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier) override; virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags modifier) override;
virtual void scrollCallback(double xOffset, double yOffset) override; virtual void scrollCallback(double xOffset, double yOffset) override;
virtual void fileCallback(int count, const char** paths) override; virtual void fileCallback(int count, const char** paths) override;
}; };
+12 -12
View File
@@ -21,9 +21,9 @@ using namespace Seele::Editor;
static Gfx::OGraphics graphics; static Gfx::OGraphics graphics;
int main() { int main() {
std::string gameName = "MeshShadingDemo"; std::string gameName = "FluidSimulation";
std::filesystem::path outputPath = fmt::format("/Users/dynamitos/{0}Game/", gameName); std::filesystem::path outputPath = fmt::format("/home/dynamitos/{0}Game/", gameName);
std::filesystem::path sourcePath = fmt::format("/Users/dynamitos/{0}/", gameName); std::filesystem::path sourcePath = fmt::format("/home/dynamitos/{0}/", gameName);
#ifdef WIN32 #ifdef WIN32
std::string libraryEnding = "dll"; std::string libraryEnding = "dll";
#elif __APPLE__ #elif __APPLE__
@@ -31,7 +31,7 @@ int main() {
#else #else
std::string libraryEnding = "so"; std::string libraryEnding = "so";
#endif #endif
std::filesystem::path binaryPath = sourcePath / "build/Debug" / fmt::format("{}.{}", gameName, libraryEnding); std::filesystem::path binaryPath = sourcePath / "build" / fmt::format("{}.{}", gameName, libraryEnding);
std::filesystem::path cmakePath = outputPath / "cmake"; std::filesystem::path cmakePath = outputPath / "cmake";
if (true) { if (true) {
graphics = new Vulkan::Graphics(); graphics = new Vulkan::Graphics();
@@ -46,9 +46,9 @@ int main() {
AssetImporter::importFont(FontImportArgs{ AssetImporter::importFont(FontImportArgs{
.filePath = "./fonts/arial.ttf", .filePath = "./fonts/arial.ttf",
}); });
// AssetImporter::importEnvironmentMap(EnvironmentImportArgs{ AssetImporter::importEnvironmentMap(EnvironmentImportArgs{
// .filePath = sourcePath / "import" / "textures" / "newport_loft.hdr", .filePath = sourcePath / "import" / "newport_loft.hdr",
// }); });
// AssetImporter::importTexture(TextureImportArgs{ // AssetImporter::importTexture(TextureImportArgs{
// .filePath = sourcePath / "import" / "textures" / "grass_block_side.png", // .filePath = sourcePath / "import" / "textures" / "grass_block_side.png",
// .importPath = "", // .importPath = "",
@@ -62,12 +62,12 @@ int main() {
// .importPath = "rttest", // .importPath = "rttest",
// }); // });
// AssetImporter::importMesh(MeshImportArgs{
// .filePath = sourcePath / "import" / "models" / "cube.fbx",
// .importPath = "",
// });
AssetImporter::importMesh(MeshImportArgs{ AssetImporter::importMesh(MeshImportArgs{
.filePath = sourcePath / "import" / "models" / "cube.fbx", .filePath = sourcePath / "import" / "rttest.gltf",
.importPath = "",
});
AssetImporter::importMesh(MeshImportArgs{
.filePath = sourcePath / "import" / "models" / "rttest.gltf",
.importPath = "rttest", .importPath = "rttest",
}); });
+2
View File
@@ -6,6 +6,7 @@ target_sources(Engine
Collider.cpp Collider.cpp
Component.h Component.h
DirectionalLight.h DirectionalLight.h
FluidGrid.h
KeyboardInput.h KeyboardInput.h
Mesh.h Mesh.h
MeshCollider.h MeshCollider.h
@@ -29,6 +30,7 @@ target_sources(Engine
Collider.h Collider.h
Component.h Component.h
DirectionalLight.h DirectionalLight.h
FluidGrid.h
KeyboardInput.h KeyboardInput.h
MeshCollider.h MeshCollider.h
Mesh.h Mesh.h
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include "Math/Vector.h"
namespace Seele {
namespace Component {
struct FluidGrid {
float cellSize = 1.0f;
float viscosity = 0.1f;
float diffusion = 0.01f;
UVector gridSize = {128, 128, 128};
};
} // namespace Component
} // namespace Seele
+67 -71
View File
@@ -1,5 +1,6 @@
#include "BasePass.h" #include "BasePass.h"
#include "Asset/AssetRegistry.h" #include "Asset/AssetRegistry.h"
#include "Asset/EnvironmentMapAsset.h"
#include "Component/Camera.h" #include "Component/Camera.h"
#include "Graphics/Command.h" #include "Graphics/Command.h"
#include "Graphics/Descriptor.h" #include "Graphics/Descriptor.h"
@@ -12,10 +13,9 @@
#include "Math/Matrix.h" #include "Math/Matrix.h"
#include "Math/Vector.h" #include "Math/Vector.h"
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "ShadowPass.h"
#include "Scene/Scene.h"
#include "Asset/EnvironmentMapAsset.h"
#include "Scene/LightEnvironment.h" #include "Scene/LightEnvironment.h"
#include "Scene/Scene.h"
#include "ShadowPass.h"
using namespace Seele; using namespace Seele;
@@ -59,10 +59,8 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics)
.name = SHADOWSAMPLER_NAME, .name = SHADOWSAMPLER_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
}); });
shadowMappingLayout->addDescriptorBinding(Gfx::DescriptorBinding{ shadowMappingLayout->addDescriptorBinding(
.name = CASCADE_SPLIT_NAME, Gfx::DescriptorBinding{.name = CASCADE_SPLIT_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER});
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER
});
shadowMappingLayout->create(); shadowMappingLayout->create();
basePassLayout->addDescriptorLayout(lightCullingLayout); basePassLayout->addDescriptorLayout(lightCullingLayout);
@@ -116,6 +114,58 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics)
.minLod = 0.0f, .minLod = 0.0f,
.borderColor = Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE, .borderColor = Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
}); });
debugPipelineLayout = graphics->createPipelineLayout("DebugPassLayout");
debugPipelineLayout->addDescriptorLayout(viewParamsLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "DebugVertex",
.modules = {"Debug"},
.entryPoints =
{
{"vertexMain", "Debug"},
{"fragmentMain", "Debug"},
},
.rootSignature = debugPipelineLayout,
});
debugVertexShader = graphics->createVertexShader({0});
debugFragmentShader = graphics->createFragmentShader({1});
debugPipelineLayout->create();
skyboxDataLayout = graphics->createDescriptorLayout("pSkyboxData");
skyboxDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.name = "transformMatrix", .uniformLength = sizeof(Matrix4)});
skyboxDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.name = "fogBlend", .uniformLength = sizeof(Vector4)});
skyboxDataLayout->create();
textureLayout = graphics->createDescriptorLayout("pSkyboxTextures");
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = SKYBOXDAY_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
});
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = SKYBOXNIGHT_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
});
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = SKYBOXSAMPLER_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
});
textureLayout->create();
pipelineLayout = graphics->createPipelineLayout("SkyboxLayout");
pipelineLayout->addDescriptorLayout(viewParamsLayout);
pipelineLayout->addDescriptorLayout(skyboxDataLayout);
pipelineLayout->addDescriptorLayout(textureLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "SkyboxVertex",
.modules = {"Skybox"},
.entryPoints = {{"vertexMain", "Skybox"}, {"fragmentMain", "Skybox"}},
.rootSignature = pipelineLayout,
});
vertexShader = graphics->createVertexShader({0});
fragmentShader = graphics->createFragmentShader({1});
pipelineLayout->create();
} }
BasePass::~BasePass() {} BasePass::~BasePass() {}
@@ -176,7 +226,7 @@ void BasePass::render() {
transparentCulling->updateTexture(LIGHTGRID_NAME, 0, tLightGrid->getDefaultView()); transparentCulling->updateTexture(LIGHTGRID_NAME, 0, tLightGrid->getDefaultView());
opaqueCulling->writeChanges(); opaqueCulling->writeChanges();
transparentCulling->writeChanges(); transparentCulling->writeChanges();
shadowMappingLayout->reset(); shadowMappingLayout->reset();
shadowMapping = shadowMappingLayout->allocateDescriptorSet(); shadowMapping = shadowMappingLayout->allocateDescriptorSet();
for (uint32 i = 0; i < NUM_CASCADES; ++i) { for (uint32 i = 0; i < NUM_CASCADES; ++i) {
@@ -268,7 +318,8 @@ void BasePass::render() {
command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo))); command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo)));
} }
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(), command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(),
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), shadowMapping, opaqueCulling}); scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), shadowMapping,
opaqueCulling});
for (const auto& drawCall : materialData.instances) { for (const auto& drawCall : materialData.instances) {
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT | command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT |
Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
@@ -382,8 +433,8 @@ void BasePass::render() {
transparentCommand->bindPipeline(pipeline); transparentCommand->bindPipeline(pipeline);
} }
transparentCommand->bindDescriptor({viewParamsSet, t.vertexData->getVertexDataSet(), t.vertexData->getInstanceDataSet(), transparentCommand->bindDescriptor({viewParamsSet, t.vertexData->getVertexDataSet(), t.vertexData->getInstanceDataSet(),
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), shadowMapping, scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(),
transparentCulling}); shadowMapping, transparentCulling});
transparentCommand->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT | transparentCommand->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT |
Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
0, sizeof(VertexData::DrawCallOffsets), &t.offsets); 0, sizeof(VertexData::DrawCallOffsets), &t.offsets);
@@ -536,24 +587,6 @@ void BasePass::createRenderPass() {
// Debug rendering // Debug rendering
{ {
debugPipelineLayout = graphics->createPipelineLayout("DebugPassLayout");
debugPipelineLayout->addDescriptorLayout(viewParamsLayout);
ShaderCompilationInfo createInfo = {
.name = "DebugVertex",
.modules = {"Debug"},
.entryPoints =
{
{"vertexMain", "Debug"},
{"fragmentMain", "Debug"},
},
.rootSignature = debugPipelineLayout,
};
graphics->beginShaderCompilation(createInfo);
debugVertexShader = graphics->createVertexShader({0});
debugFragmentShader = graphics->createFragmentShader({1});
debugPipelineLayout->create();
VertexInputStateCreateInfo inputCreate = { VertexInputStateCreateInfo inputCreate = {
.bindings = .bindings =
{ {
@@ -605,27 +638,6 @@ void BasePass::createRenderPass() {
} }
// Skybox // Skybox
{ {
skyboxDataLayout = graphics->createDescriptorLayout("pSkyboxData");
skyboxDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.name = "transformMatrix", .uniformLength = sizeof(Matrix4)});
skyboxDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.name = "fogBlend", .uniformLength = sizeof(Vector4)});
skyboxDataLayout->create();
textureLayout = graphics->createDescriptorLayout("pSkyboxTextures");
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = SKYBOXDAY_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
});
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = SKYBOXNIGHT_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
});
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = SKYBOXSAMPLER_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
});
textureLayout->create();
skyboxSampler = graphics->createSampler({ skyboxSampler = graphics->createSampler({
.magFilter = Gfx::SE_FILTER_LINEAR, .magFilter = Gfx::SE_FILTER_LINEAR,
.minFilter = Gfx::SE_FILTER_LINEAR, .minFilter = Gfx::SE_FILTER_LINEAR,
@@ -642,23 +654,6 @@ void BasePass::createRenderPass() {
skyboxData.fogColor = skybox.fogColor; skyboxData.fogColor = skybox.fogColor;
skyboxData.blendFactor = skybox.blendFactor; skyboxData.blendFactor = skybox.blendFactor;
pipelineLayout = graphics->createPipelineLayout("SkyboxLayout");
pipelineLayout->addDescriptorLayout(viewParamsLayout);
pipelineLayout->addDescriptorLayout(skyboxDataLayout);
pipelineLayout->addDescriptorLayout(textureLayout);
ShaderCompilationInfo createInfo = {
.name = "SkyboxVertex",
.modules = {"Skybox"},
.entryPoints = {{"vertexMain", "Skybox"}, {"fragmentMain", "Skybox"}},
.rootSignature = pipelineLayout,
};
graphics->beginShaderCompilation(createInfo);
vertexShader = graphics->createVertexShader({0});
fragmentShader = graphics->createFragmentShader({1});
pipelineLayout->create();
Gfx::LegacyPipelineCreateInfo gfxInfo = { Gfx::LegacyPipelineCreateInfo gfxInfo = {
.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, .topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
.vertexShader = vertexShader, .vertexShader = vertexShader,
@@ -673,10 +668,11 @@ void BasePass::createRenderPass() {
{ {
.polygonMode = Gfx::SE_POLYGON_MODE_FILL, .polygonMode = Gfx::SE_POLYGON_MODE_FILL,
}, },
.depthStencilState = { .depthStencilState =
.depthTestEnable = true, {
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, .depthTestEnable = true,
}, .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend = .colorBlend =
{ {
.attachmentCount = 1, .attachmentCount = 1,
@@ -2,6 +2,7 @@
#include "Graphics/Buffer.h" #include "Graphics/Buffer.h"
#include "Graphics/Descriptor.h" #include "Graphics/Descriptor.h"
#include "Graphics/RenderPass/ShadowPass.h" #include "Graphics/RenderPass/ShadowPass.h"
#include "Component/Skybox.h"
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "RenderPass.h" #include "RenderPass.h"
@@ -6,6 +6,8 @@ target_sources(Engine
CachedDepthPass.cpp CachedDepthPass.cpp
DepthCullingPass.h DepthCullingPass.h
DepthCullingPass.cpp DepthCullingPass.cpp
FluidRenderPass.h
FluidRenderPass.cpp
LightCullingPass.h LightCullingPass.h
LightCullingPass.cpp LightCullingPass.cpp
RayTracingPass.h RayTracingPass.h
@@ -17,6 +19,10 @@ target_sources(Engine
RenderPass.cpp RenderPass.cpp
ShadowPass.h ShadowPass.h
ShadowPass.cpp ShadowPass.cpp
SimulationComputePass.h
SimulationComputePass.cpp
SurfaceExtractPass.h
SurfaceExtractPass.cpp
#TerrainRenderer.h #TerrainRenderer.h
#TerrainRenderer.cpp #TerrainRenderer.cpp
ToneMappingPass.h ToneMappingPass.h
@@ -34,6 +40,7 @@ target_sources(Engine
BasePass.h BasePass.h
CachedDepthPass.h CachedDepthPass.h
DepthCullingPass.h DepthCullingPass.h
FluidRenderPass.h
LightCullingPass.h LightCullingPass.h
ToneMappingPass.h ToneMappingPass.h
RayTracingPass.h RayTracingPass.h
@@ -41,6 +48,8 @@ target_sources(Engine
RenderGraphResources.h RenderGraphResources.h
RenderPass.h RenderPass.h
ShadowPass.h ShadowPass.h
SimulationComputePass.h
SurfaceExtractPass.h
#TerrainRenderer.h #TerrainRenderer.h
UIPass.h UIPass.h
VisibilityPass.h) VisibilityPass.h)
@@ -37,6 +37,24 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
.size = sizeof(MipParam), .size = sizeof(MipParam),
.name = "pMipParam" .name = "pMipParam"
}); });
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "DepthMipCompute",
.modules = {"DepthMipGen"},
.entryPoints = {{"sourceCopy", "DepthMipGen"}, {"reduceLevel", "DepthMipGen"}},
.rootSignature = depthComputeLayout,
});
depthSourceCopyShader = graphics->createComputeShader({0});
depthComputeLayout->create();
Gfx::ComputePipelineCreateInfo pipelineCreateInfo = {
.computeShader = depthSourceCopyShader,
.pipelineLayout = depthComputeLayout,
};
depthSourceCopy = graphics->createComputePipeline(pipelineCreateInfo);
depthReduceLevelShader = graphics->createComputeShader({1});
pipelineCreateInfo.computeShader = depthReduceLevelShader;
depthReduceLevel = graphics->createComputePipeline(pipelineCreateInfo);
if (graphics->supportMeshShading()) { if (graphics->supportMeshShading()) {
graphics->getShaderCompiler()->registerRenderPass("DepthPass", Gfx::PassConfig{ graphics->getShaderCompiler()->registerRenderPass("DepthPass", Gfx::PassConfig{
@@ -255,24 +273,6 @@ void DepthCullingPass::publishOutputs() {
.name = "DepthMipBuffer", .name = "DepthMipBuffer",
}); });
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "DepthMipCompute",
.modules = {"DepthMipGen"},
.entryPoints = {{"sourceCopy", "DepthMipGen"}, {"reduceLevel", "DepthMipGen"}},
.rootSignature = depthComputeLayout,
});
depthSourceCopyShader = graphics->createComputeShader({0});
depthComputeLayout->create();
Gfx::ComputePipelineCreateInfo pipelineCreateInfo = {
.computeShader = depthSourceCopyShader,
.pipelineLayout = depthComputeLayout,
};
depthSourceCopy = graphics->createComputePipeline(pipelineCreateInfo);
depthReduceLevelShader = graphics->createComputeShader({1});
pipelineCreateInfo.computeShader = depthReduceLevelShader;
depthReduceLevel = graphics->createComputePipeline(pipelineCreateInfo);
query = graphics->createPipelineStatisticsQuery("DepthPipelineStatistics"); query = graphics->createPipelineStatisticsQuery("DepthPipelineStatistics");
resources->registerQueryOutput("DEPTH_QUERY", query); resources->registerQueryOutput("DEPTH_QUERY", query);
@@ -0,0 +1,147 @@
#include "FluidRenderPass.h"
#include "Component/Transform.h"
#include "Graphics/Command.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h"
#include "Graphics/RenderTarget.h"
#include "Graphics/Shader.h"
#include "Scene/LightEnvironment.h"
#include "Scene/Scene.h"
using namespace Seele;
FluidRenderPass::FluidRenderPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
pipelineLayout = graphics->createPipelineLayout("FluidPipelineLayout");
descriptorLayout = graphics->createDescriptorLayout("params");
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "vertexBuffer",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "normalBuffer",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "indexBuffer",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->create();
pipelineLayout->addDescriptorLayout(viewParamsLayout);
pipelineLayout->addDescriptorLayout(descriptorLayout);
pipelineLayout->addDescriptorLayout(scene->getLightEnvironment()->getDescriptorLayout());
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "Fluid",
.modules = {"Render"},
.entryPoints = {{"vertexMain", "Render"}, {"fragmentMain", "Render"}},
.rootSignature = pipelineLayout,
});
pipelineLayout->create();
vertexShader = graphics->createVertexShader({0});
fragmentShader = graphics->createFragmentShader({1});
}
FluidRenderPass::~FluidRenderPass() {}
void FluidRenderPass::beginFrame(const Seele::Component::Camera& camera, const Seele::Component::Transform& transform) {
updateViewParameters(camera, transform);
}
void FluidRenderPass::render() {
viewParamsSet = createViewParamsSet();
graphics->beginRenderPass(renderPass);
descriptorLayout->reset();
for (const auto& [id, data] : scene->getFluidScene()->getFluidDataMap()) {
descriptorSet = descriptorLayout->allocateDescriptorSet();
descriptorSet->updateBuffer("vertexBuffer", 0, data.vertexBuffer);
descriptorSet->updateBuffer("normalBuffer", 0, data.normalBuffer);
descriptorSet->updateBuffer("indexBuffer", 0, data.indexBuffer);
descriptorSet->writeChanges();
Gfx::ORenderCommand renderCommand = graphics->createRenderCommand();
renderCommand->setViewport(viewport);
renderCommand->bindPipeline(pipeline);
renderCommand->bindDescriptor(viewParamsSet);
renderCommand->bindDescriptor(descriptorSet);
renderCommand->bindDescriptor(scene->getLightEnvironment()->getDescriptorSet());
renderCommand->drawIndirect(data.surfaceCountBuffer, 0, 1, 0);
graphics->executeCommands(std::move(renderCommand));
}
graphics->endRenderPass();
}
void FluidRenderPass::endFrame() {}
void FluidRenderPass::publishOutputs() {
depthTexture = graphics->createTexture2D(TextureCreateInfo{
.format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = viewport->getWidth(),
.height = viewport->getHeight(),
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
.name = "FluidDepth",
});
}
void FluidRenderPass::createRenderPass() {
colorAttachment = Gfx::RenderTargetAttachment(viewport, Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
depthAttachment = Gfx::RenderTargetAttachment(depthTexture->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR,
Gfx::SE_ATTACHMENT_STORE_OP_DONT_CARE);
depthAttachment.clear.depthStencil.depth = 0.0f;
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.colorAttachments = {colorAttachment},
.depthAttachment = depthAttachment,
};
Array<Gfx::SubPassDependency> dependency = {
{
.srcSubpass = ~0U,
.dstSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
};
renderPass = graphics->createRenderPass(layout, dependency, viewport->getRenderArea(), "FluidRenderPass");
pipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{
.vertexShader = vertexShader,
.fragmentShader = fragmentShader,
.renderPass = renderPass,
.pipelineLayout = pipelineLayout,
.multisampleState =
{
.samples = Gfx::SE_SAMPLE_COUNT_1_BIT,
},
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_FRONT_BIT,
},
.colorBlend =
{
.attachmentCount = 1,
.blendAttachments =
{
Gfx::ColorBlendState::BlendAttachment{
.blendEnable = true,
},
},
},
});
}
@@ -0,0 +1,39 @@
#pragma once
#include "Component/Transform.h"
#include "Graphics/Descriptor.h"
#include "Graphics/Initializer.h"
#include "Graphics/RenderPass/RenderPass.h"
#include "MinimalEngine.h"
#include "Scene/Scene.h"
namespace Seele {
class FluidRenderPass : public RenderPass {
public:
FluidRenderPass(Gfx::PGraphics graphics, PScene scene);
virtual ~FluidRenderPass() override;
virtual void beginFrame(const Component::Camera& camera, const Component::Transform& transform) override;
virtual void render() override;
virtual void endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
private:
Gfx::RenderTargetAttachment colorAttachment;
Gfx::RenderTargetAttachment depthAttachment;
Gfx::OTexture2D depthTexture;
Gfx::ODescriptorSet viewParamsSet;
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::ODescriptorSet descriptorSet;
Gfx::OVertexShader vertexShader;
Gfx::OFragmentShader fragmentShader;
Gfx::PGraphicsPipeline pipeline;
PScene scene;
};
DEFINE_REF(FluidRenderPass)
} // namespace Seele
@@ -11,7 +11,137 @@
using namespace Seele; using namespace Seele;
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {} LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
dispatchParamsLayout = graphics->createDescriptorLayout("pDispatchParams");
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "numThreadGroups",
.uniformLength = sizeof(UVector4),
});
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "numThreads",
.uniformLength = sizeof(UVector4),
});
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = FRUSTUMBUFFER_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.access = Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
dispatchParamsLayout->create();
frustumLayout = graphics->createPipelineLayout("FrustumLayout");
frustumLayout->addDescriptorLayout(viewParamsLayout);
frustumLayout->addDescriptorLayout(dispatchParamsLayout);
ShaderCompilationInfo createInfo = {
.name = "Frustum",
.modules = {"ComputeFrustums"},
.entryPoints = {{"computeFrustums", "ComputeFrustums"}},
.rootSignature = frustumLayout,
};
graphics->beginShaderCompilation(createInfo);
frustumShader = graphics->createComputeShader({0});
// Have to compile shader before finalizing layout as parameters get mapped later
frustumLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = frustumShader;
pipelineInfo.pipelineLayout = frustumLayout;
frustumPipeline = graphics->createComputePipeline(pipelineInfo);
cullingDescriptorLayout = graphics->createDescriptorLayout("pCullingParams");
// DepthTexture
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = DEPTHATTACHMENT_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
});
// o_lightIndexCounter
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = OLIGHTINDEXCOUNTER_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
// t_lightIndexCounter
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = TLIGHTINDEXCOUNTER_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
// o_lightIndexList
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = OLIGHTINDEXLIST_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
// t_lightIndexList
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = TLIGHTINDEXLIST_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
// o_lightGrid
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = OLIGHTGRID_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
// t_lightGrid
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = TLIGHTGRID_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
cullingDescriptorLayout->create();
lightEnv = scene->getLightEnvironment();
{
cullingLayout = graphics->createPipelineLayout("CullingLayout");
cullingLayout->addDescriptorLayout(viewParamsLayout);
cullingLayout->addDescriptorLayout(dispatchParamsLayout);
cullingLayout->addDescriptorLayout(cullingDescriptorLayout);
cullingLayout->addDescriptorLayout(lightEnv->getDescriptorLayout());
ShaderCompilationInfo createInfo = {
.name = "Culling",
.modules = {"LightCulling"},
.entryPoints = {{"cullLights", "LightCulling"}},
.rootSignature = cullingLayout,
};
graphics->beginShaderCompilation(createInfo);
cullingShader = graphics->createComputeShader({0});
cullingLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = cullingShader;
pipelineInfo.pipelineLayout = cullingLayout;
cullingPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
}
{
cullingEnableLayout = graphics->createPipelineLayout("CullingEnabledLayout");
cullingEnableLayout->addDescriptorLayout(viewParamsLayout);
cullingEnableLayout->addDescriptorLayout(dispatchParamsLayout);
cullingEnableLayout->addDescriptorLayout(cullingDescriptorLayout);
cullingEnableLayout->addDescriptorLayout(lightEnv->getDescriptorLayout());
ShaderCompilationInfo createInfo = {
.name = "Culling",
.modules = {"LightCulling"},
.entryPoints = {{"cullLights", "LightCulling"}},
.rootSignature = cullingEnableLayout,
};
createInfo.defines["LIGHT_CULLING"] = "1";
graphics->beginShaderCompilation(createInfo);
cullingEnabledShader = graphics->createComputeShader({0});
cullingEnableLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = cullingShader;
pipelineInfo.pipelineLayout = cullingEnableLayout;
cullingEnabledPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
}
}
LightCullingPass::~LightCullingPass() {} LightCullingPass::~LightCullingPass() {}
@@ -91,86 +221,9 @@ void LightCullingPass::publishOutputs() {
dispatchParamsSet = dispatchParamsLayout->allocateDescriptorSet(); dispatchParamsSet = dispatchParamsLayout->allocateDescriptorSet();
dispatchParamsSet->updateConstants("numThreadGroups", 0, &numThreadGroups); dispatchParamsSet->updateConstants("numThreadGroups", 0, &numThreadGroups);
dispatchParamsSet->updateConstants("numThreads", 0, &numThreads); dispatchParamsSet->updateConstants("numThreads", 0, &numThreads);
dispatchParamsSet->updateBuffer(FRUSTUMBUFFER_NAME, 0, frustumBuffer);
dispatchParamsSet->writeChanges(); dispatchParamsSet->writeChanges();
cullingDescriptorLayout = graphics->createDescriptorLayout("pCullingParams");
// DepthTexture
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = DEPTHATTACHMENT_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
});
// o_lightIndexCounter
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = OLIGHTINDEXCOUNTER_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
// t_lightIndexCounter
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = TLIGHTINDEXCOUNTER_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
// o_lightIndexList
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = OLIGHTINDEXLIST_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
// t_lightIndexList
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = TLIGHTINDEXLIST_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
// o_lightGrid
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = OLIGHTGRID_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
// t_lightGrid
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = TLIGHTGRID_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
cullingDescriptorLayout->create();
lightEnv = scene->getLightEnvironment();
{
cullingLayout = graphics->createPipelineLayout("CullingLayout");
cullingLayout->addDescriptorLayout(viewParamsLayout);
cullingLayout->addDescriptorLayout(dispatchParamsLayout);
cullingLayout->addDescriptorLayout(cullingDescriptorLayout);
cullingLayout->addDescriptorLayout(lightEnv->getDescriptorLayout());
ShaderCompilationInfo createInfo = {
.name = "Culling",
.modules = {"LightCulling"},
.entryPoints = {{"cullLights", "LightCulling"}},
.rootSignature = cullingLayout,
};
graphics->beginShaderCompilation(createInfo);
cullingShader = graphics->createComputeShader({0});
cullingLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = cullingShader;
pipelineInfo.pipelineLayout = cullingLayout;
cullingPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
}
{
cullingEnableLayout = graphics->createPipelineLayout("CullingEnabledLayout");
cullingEnableLayout->addDescriptorLayout(viewParamsLayout);
cullingEnableLayout->addDescriptorLayout(dispatchParamsLayout);
cullingEnableLayout->addDescriptorLayout(cullingDescriptorLayout);
cullingEnableLayout->addDescriptorLayout(lightEnv->getDescriptorLayout());
ShaderCompilationInfo createInfo = {
.name = "Culling",
.modules = {"LightCulling"},
.entryPoints = {{"cullLights", "LightCulling"}},
.rootSignature = cullingEnableLayout,
};
createInfo.defines["LIGHT_CULLING"] = "1";
graphics->beginShaderCompilation(createInfo);
cullingEnabledShader = graphics->createComputeShader({0});
cullingEnableLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = cullingShader;
pipelineInfo.pipelineLayout = cullingEnableLayout;
cullingEnabledPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
}
uint32 counterReset = 0; uint32 counterReset = 0;
ShaderBufferCreateInfo structInfo = { ShaderBufferCreateInfo structInfo = {
.sourceData = .sourceData =
@@ -188,8 +241,7 @@ void LightCullingPass::publishOutputs() {
structInfo = { structInfo = {
.sourceData = .sourceData =
{ {
.size = (uint32)sizeof(uint32) * numThreadGroups.x * numThreadGroups.y * .size = (uint32)sizeof(uint32) * numThreadGroups.x * numThreadGroups.y * numThreadGroups.z * 8192,
numThreadGroups.z * 8192,
.data = nullptr, .data = nullptr,
.owner = Gfx::QueueType::COMPUTE, .owner = Gfx::QueueType::COMPUTE,
}, },
@@ -237,41 +289,6 @@ void LightCullingPass::setupFrustums() {
updateViewParameters(Component::Camera(), Component::Transform()); updateViewParameters(Component::Camera(), Component::Transform());
viewParamsSet = createViewParamsSet(); viewParamsSet = createViewParamsSet();
dispatchParamsLayout = graphics->createDescriptorLayout("pDispatchParams");
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "numThreadGroups",
.uniformLength = sizeof(UVector4),
});
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "numThreads",
.uniformLength = sizeof(UVector4),
});
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = FRUSTUMBUFFER_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.access = Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
dispatchParamsLayout->create();
frustumLayout = graphics->createPipelineLayout("FrustumLayout");
frustumLayout->addDescriptorLayout(viewParamsLayout);
frustumLayout->addDescriptorLayout(dispatchParamsLayout);
ShaderCompilationInfo createInfo = {
.name = "Frustum",
.modules = {"ComputeFrustums"},
.entryPoints = {{"computeFrustums", "ComputeFrustums"}},
.rootSignature = frustumLayout,
.dumpIntermediate = true,
};
graphics->beginShaderCompilation(createInfo);
frustumShader = graphics->createComputeShader({0});
// Have to compile shader before finalizing layout as parameters get mapped later
frustumLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = frustumShader;
pipelineInfo.pipelineLayout = frustumLayout;
frustumPipeline = graphics->createComputePipeline(pipelineInfo);
frustumBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ frustumBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = .sourceData =
{ {
@@ -299,6 +316,6 @@ void LightCullingPass::setupFrustums() {
commands.add(std::move(command)); commands.add(std::move(command));
graphics->executeCommands(std::move(commands)); graphics->executeCommands(std::move(commands));
frustumBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, frustumBuffer->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->endDebugRegion(); graphics->endDebugRegion();
} }
@@ -4,9 +4,10 @@
#include "Graphics/RayTracing.h" #include "Graphics/RayTracing.h"
#include "Graphics/Shader.h" #include "Graphics/Shader.h"
#include "Graphics/StaticMeshVertexData.h" #include "Graphics/StaticMeshVertexData.h"
#include "RenderPass.h"
#include "Material/Material.h" #include "Material/Material.h"
#include "Material/MaterialInstance.h" #include "Material/MaterialInstance.h"
#include "RenderPass.h"
#include <iostream>
using namespace Seele; using namespace Seele;
@@ -55,11 +56,24 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa
.size = sizeof(SampleParams), .size = sizeof(SampleParams),
.name = "pSamps", .name = "pSamps",
}); });
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "RayGenMiss",
.modules = {"RayGen", "AnyHit", "Miss"},
.entryPoints = {{"raygen", "RayGen"}, {"anyhit", "AnyHit"}, {"miss", "Miss"}},
.defines = {{"RAY_TRACING", "1"}},
.rootSignature = pipelineLayout,
});
rayGen = graphics->createRayGenShader({0});
anyhit = graphics->createAnyHitShader({1});
miss = graphics->createMissShader({2});
pipelineLayout->create();
graphics->getShaderCompiler()->registerRenderPass("RayTracing", Gfx::PassConfig{ graphics->getShaderCompiler()->registerRenderPass("RayTracing", Gfx::PassConfig{
.baseLayout = pipelineLayout, .baseLayout = pipelineLayout,
.mainFile = "ClosestHit", .mainFile = "ClosestHit",
.useMaterial = true, .useMaterial = true,
.rayTracing = true, .rayTracing = true,
.dumpIntermediates = true,
}); });
skyBox = AssetRegistry::findEnvironmentMap("", "newport_loft")->getSkybox(); skyBox = AssetRegistry::findEnvironmentMap("", "newport_loft")->getSkybox();
skyBoxSampler = graphics->createSampler({}); skyBoxSampler = graphics->createSampler({});
@@ -212,20 +226,9 @@ void RayTracingPass::publishOutputs() {
texture->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_NONE, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, texture->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_NONE, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR); Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
resources->registerRenderPassOutput("BASEPASS_COLOR", Gfx::RenderTargetAttachment(texture->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED, resources->registerRenderPassOutput("BASEPASS_COLOR",
Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); Gfx::RenderTargetAttachment(texture->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
ShaderCompilationInfo compileInfo = { Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
.name = "RayGenMiss",
.modules = {"RayGen", "AnyHit", "Miss"},
.entryPoints = {{"raygen", "RayGen"}, {"anyhit", "AnyHit"}, {"miss", "Miss"}},
.defines = {{"RAY_TRACING", "1"}},
.rootSignature = pipelineLayout,
};
graphics->beginShaderCompilation(compileInfo);
rayGen = graphics->createRayGenShader({0});
anyhit = graphics->createAnyHitShader({1});
miss = graphics->createMissShader({2});
pipelineLayout->create();
} }
void RayTracingPass::createRenderPass() {} void RayTracingPass::createRenderPass() {}
@@ -0,0 +1,519 @@
#include "SimulationComputePass.h"
#include "Graphics/Buffer.h"
#include "Graphics/Command.h"
#include "Graphics/Descriptor.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h"
#include "Graphics/Shader.h"
#include "Math/Vector.h"
#include <iostream>
using namespace Seele;
constexpr static int reinitInterval = 5;
constexpr static int reinitIterations = 5;
constexpr static float reinitDtau = 0.5f;
#define SWAP(a, b) \
{ \
auto temp = std::move(a); \
a = std::move(b); \
b = std::move(temp); \
}
SimulationComputePass::SimulationComputePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
{
setBounds.pipelineLayout = graphics->createPipelineLayout("SetBoundsPipelineLayout");
setBounds.descriptorLayout = graphics->createDescriptorLayout("params");
setBounds.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "b",
.uniformLength = sizeof(int),
});
setBounds.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "grid",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
setBounds.descriptorLayout->create();
setBounds.pipelineLayout->addDescriptorLayout(setBounds.descriptorLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "SetBound",
.modules = {"SetBound"},
.entryPoints = {{"setBound", "SetBound"}, {"setBoundEdges", "SetBound"}, {"setBoundCorners", "SetBound"}},
.rootSignature = setBounds.pipelineLayout,
});
setBounds.pipelineLayout->create();
setBounds.shader = graphics->createComputeShader({0});
setBounds.shaderEdges = graphics->createComputeShader({1});
setBounds.shaderCorners = graphics->createComputeShader({2});
setBounds.pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = setBounds.shader,
.pipelineLayout = setBounds.pipelineLayout,
});
setBounds.pipelineEdges = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = setBounds.shaderEdges,
.pipelineLayout = setBounds.pipelineLayout,
});
setBounds.pipelineCorners = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = setBounds.shaderCorners,
.pipelineLayout = setBounds.pipelineLayout,
});
}
{
linearSolve.pipelineLayout = graphics->createPipelineLayout("LinearSolvePipelineLayout");
linearSolve.descriptorLayout = graphics->createDescriptorLayout("params");
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "a",
.uniformLength = sizeof(float),
});
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "c",
.uniformLength = sizeof(float),
});
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "next",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "current",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
linearSolve.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "grid0",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
linearSolve.descriptorLayout->create();
linearSolve.pipelineLayout->addDescriptorLayout(linearSolve.descriptorLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "LinearSolve",
.modules = {"LinearSolve"},
.entryPoints = {{"linearSolve", "LinearSolve"}},
.rootSignature = linearSolve.pipelineLayout,
});
linearSolve.pipelineLayout->create();
linearSolve.shader = graphics->createComputeShader({0});
linearSolve.pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = linearSolve.shader,
.pipelineLayout = linearSolve.pipelineLayout,
});
}
{
computeDivergence.pipelineLayout = graphics->createPipelineLayout("ComputeDivergencePipelineLayout");
computeDivergence.descriptorLayout = graphics->createDescriptorLayout("params");
computeDivergence.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityX",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
computeDivergence.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityY",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
computeDivergence.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityZ",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
computeDivergence.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "divergence",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
computeDivergence.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "pressure",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
computeDivergence.descriptorLayout->create();
computeDivergence.pipelineLayout->addDescriptorLayout(computeDivergence.descriptorLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "Divergence",
.modules = {"Divergence"},
.entryPoints = {{"computeDivergence", "Divergence"}},
.rootSignature = computeDivergence.pipelineLayout,
});
computeDivergence.pipelineLayout->create();
computeDivergence.shader = graphics->createComputeShader({0});
computeDivergence.pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = computeDivergence.shader,
.pipelineLayout = computeDivergence.pipelineLayout,
});
}
{
project.pipelineLayout = graphics->createPipelineLayout("ProjectPipelineLayout");
project.descriptorLayout = graphics->createDescriptorLayout("params");
project.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityX",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
project.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityY",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
project.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityZ",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
project.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "pressure",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
project.descriptorLayout->create();
project.pipelineLayout->addDescriptorLayout(project.descriptorLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "Project",
.modules = {"Project"},
.entryPoints = {{"project", "Project"}},
.rootSignature = project.pipelineLayout,
});
project.pipelineLayout->create();
project.shader = graphics->createComputeShader({0});
project.pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = project.shader,
.pipelineLayout = project.pipelineLayout,
});
}
{
advect.pipelineLayout = graphics->createPipelineLayout("AdvectPipelineLayout");
advect.descriptorLayout = graphics->createDescriptorLayout("params");
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "density",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "density0",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityX",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityY",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityZ",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
advect.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "dt",
.uniformLength = sizeof(float),
});
advect.descriptorLayout->create();
advect.pipelineLayout->addDescriptorLayout(advect.descriptorLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "Advect",
.modules = {"Advect"},
.entryPoints = {{"advect", "Advect"}},
.rootSignature = advect.pipelineLayout,
});
advect.pipelineLayout->create();
advect.shader = graphics->createComputeShader({0});
advect.pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = advect.shader,
.pipelineLayout = advect.pipelineLayout,
});
}
{
reinitialize.pipelineLayout = graphics->createPipelineLayout("ReinitializePipelineLayout");
reinitialize.descriptorLayout = graphics->createDescriptorLayout("params");
reinitialize.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "dtau",
.uniformLength = sizeof(float),
});
reinitialize.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "phi",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
reinitialize.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "phi0",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
reinitialize.descriptorLayout->create();
reinitialize.pipelineLayout->addDescriptorLayout(reinitialize.descriptorLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "SignedDistance",
.modules = {"SignedDistance"},
.entryPoints = {{"reinitialize", "SignedDistance"}},
.rootSignature = reinitialize.pipelineLayout,
});
reinitialize.pipelineLayout->create();
reinitialize.shader = graphics->createComputeShader({0});
reinitialize.pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = reinitialize.shader,
.pipelineLayout = reinitialize.pipelineLayout,
});
}
}
SimulationComputePass::~SimulationComputePass() {}
void SimulationComputePass::beginFrame(const Seele::Component::Camera&, const Seele::Component::Transform&) {
setBounds.descriptorLayout->reset();
linearSolve.descriptorLayout->reset();
computeDivergence.descriptorLayout->reset();
project.descriptorLayout->reset();
advect.descriptorLayout->reset();
reinitialize.descriptorLayout->reset();
}
void SimulationComputePass::render() {
for (auto& [entityID, data] : scene->getFluidScene()->getFluidDataMap()) {
graphics->beginDebugRegion("Diffuse");
for (uint iteration = 0; iteration < 4; ++iteration) {
float a = dt * data.viscosity * (data.gridSize.x - 2) * (data.gridSize.y - 2) * (data.gridSize.z - 2);
float c = 1 + 6 * a;
linearSolvePass(data.velocityXNextBuffer, data.velocityXBuffer, data.velocityX0Buffer, a, c, data.gridSize);
linearSolvePass(data.velocityYNextBuffer, data.velocityYBuffer, data.velocityY0Buffer, a, c, data.gridSize);
linearSolvePass(data.velocityZNextBuffer, data.velocityZBuffer, data.velocityZ0Buffer, a, c, data.gridSize);
setBoundsPass(data.velocityXNextBuffer, 1, data.gridSize);
setBoundsPass(data.velocityYNextBuffer, 2, data.gridSize);
setBoundsPass(data.velocityZNextBuffer, 3, data.gridSize);
SWAP(data.velocityXBuffer, data.velocityXNextBuffer);
SWAP(data.velocityYBuffer, data.velocityYNextBuffer);
SWAP(data.velocityZBuffer, data.velocityZNextBuffer);
}
SWAP(data.velocityX0Buffer, data.velocityXBuffer);
SWAP(data.velocityY0Buffer, data.velocityYBuffer);
SWAP(data.velocityZ0Buffer, data.velocityZBuffer);
graphics->endDebugRegion();
graphics->beginDebugRegion("Project");
Gfx::PShaderBuffer divergence = data.velocityXBuffer;
Gfx::PShaderBuffer pressureCurrent = data.velocityYBuffer;
Gfx::PShaderBuffer pressureNext = data.velocityZBuffer;
divergencePass(divergence, pressureCurrent, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, data.gridSize);
for (int iteration = 0; iteration < 4; ++iteration) {
linearSolvePass(pressureNext, pressureCurrent, divergence, 1, 6, data.gridSize);
setBoundsPass(pressureNext, 0, data.gridSize);
// swap pressure buffers
SWAP(pressureCurrent, pressureNext);
}
projectPass(data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, pressureCurrent, data.gridSize);
setBoundsPass(data.velocityX0Buffer, 1, data.gridSize);
setBoundsPass(data.velocityY0Buffer, 2, data.gridSize);
setBoundsPass(data.velocityZ0Buffer, 3, data.gridSize);
graphics->endDebugRegion();
graphics->beginDebugRegion("Advect");
advectPass(data.velocityXBuffer, data.velocityX0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
advectPass(data.velocityYBuffer, data.velocityY0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
advectPass(data.velocityZBuffer, data.velocityZ0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
setBoundsPass(data.velocityXBuffer, 1, data.gridSize);
setBoundsPass(data.velocityYBuffer, 2, data.gridSize);
setBoundsPass(data.velocityZBuffer, 3, data.gridSize);
graphics->endDebugRegion();
// swap velocity buffers
SWAP(data.velocityX0Buffer, data.velocityXBuffer);
SWAP(data.velocityY0Buffer, data.velocityYBuffer);
SWAP(data.velocityZ0Buffer, data.velocityZBuffer);
// diffuse density
graphics->beginDebugRegion("DiffuseDensity");
Gfx::PShaderBuffer densityCurrent = data.densityBuffer;
Gfx::PShaderBuffer densityNext = data.scratchBuffer;
Gfx::PShaderBuffer density0 = data.density0Buffer;
graphics->copyBuffer(density0, densityCurrent);
densityCurrent->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);
for (int iteration = 0; iteration < 4; ++iteration) {
float a = dt * data.diffusion * (data.gridSize.x - 2) * (data.gridSize.y - 2) * (data.gridSize.z - 2);
float c = 1 + 6 * a;
linearSolvePass(densityNext, densityCurrent, density0, a, c, data.gridSize);
setBoundsPass(densityNext, 0, data.gridSize);
SWAP(densityCurrent, densityNext);
}
graphics->endDebugRegion();
graphics->beginDebugRegion("AdvectDensity");
advectPass(data.density0Buffer, densityCurrent, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
setBoundsPass(data.density0Buffer, 0, data.gridSize);
graphics->endDebugRegion();
graphics->beginDebugRegion("AdvectLevelSet");
advectPass(data.phiBuffer, data.phi0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, dt, data.gridSize);
setBoundsPass(data.phiBuffer, 0, data.gridSize);
// Reinitialize level set every N frames to restore |grad phi| = 1
if (data.frameCounter % reinitInterval == 0) {
reinitializeLevelSetPass(data.phiBuffer, data.phi0Buffer, data.gridSize);
}
++data.frameCounter;
data.phiBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
graphics->copyBuffer(data.phiBuffer, data.phi0Buffer);
data.phi0Buffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
graphics->endDebugRegion();
}
}
void SimulationComputePass::endFrame() {}
void SimulationComputePass::publishOutputs() {}
void SimulationComputePass::createRenderPass() {}
UVector SimulationComputePass::getDispatchSize(const UVector& gridSize, const UVector& threadGroupSize) {
return {
(gridSize.x + threadGroupSize.x - 1) / threadGroupSize.x,
(gridSize.y + threadGroupSize.y - 1) / threadGroupSize.y,
(gridSize.z + threadGroupSize.z - 1) / threadGroupSize.z,
};
}
void SimulationComputePass::setBoundsPass(Gfx::PShaderBuffer grid, int b, UVector gridSize) {
Gfx::ODescriptorSet bounds = setBounds.descriptorLayout->allocateDescriptorSet();
bounds->updateConstants("b", 0, &b);
bounds->updateBuffer("grid", 0, grid);
bounds->writeChanges();
Gfx::OComputeCommand boundsCommand = graphics->createComputeCommand();
boundsCommand->bindPipeline(setBounds.pipeline);
boundsCommand->bindDescriptor(bounds);
boundsCommand->dispatch(getDispatchSize(gridSize, setBounds.threadGroupSize));
graphics->executeCommands(std::move(boundsCommand));
grid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
Gfx::OComputeCommand edgesCommand = graphics->createComputeCommand();
edgesCommand->bindPipeline(setBounds.pipelineEdges);
edgesCommand->bindDescriptor(bounds);
edgesCommand->dispatch(getDispatchSize(gridSize, setBounds.threadGroupSize).x, 1, 1);
graphics->executeCommands(std::move(edgesCommand));
grid->pipelineBarrier(Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_WRITE_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
Gfx::OComputeCommand cornersCommand = graphics->createComputeCommand();
cornersCommand->bindPipeline(setBounds.pipelineCorners);
cornersCommand->bindDescriptor(bounds);
cornersCommand->dispatch(1, 1, 1);
graphics->executeCommands(std::move(cornersCommand));
grid->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);
}
void SimulationComputePass::linearSolvePass(Gfx::PShaderBuffer next, Gfx::PShaderBuffer current, Gfx::PShaderBuffer grid0, float a, float c, UVector gridSize) {
Gfx::ODescriptorSet solve = linearSolve.descriptorLayout->allocateDescriptorSet();
solve->updateBuffer("next", 0, next);
solve->updateBuffer("current", 0, current);
solve->updateBuffer("grid0", 0, grid0);
solve->updateConstants("a", 0, &a);
solve->updateConstants("c", 0, &c);
solve->writeChanges();
Gfx::OComputeCommand solveCommand = graphics->createComputeCommand();
solveCommand->bindPipeline(linearSolve.pipeline);
solveCommand->bindDescriptor(solve);
solveCommand->dispatch(getDispatchSize(gridSize, linearSolve.threadGroupSize));
graphics->executeCommands(std::move(solveCommand));
next->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);
}
void SimulationComputePass::divergencePass(Seele::Gfx::PShaderBuffer divergence, Seele::Gfx::PShaderBuffer pressure,
Seele::Gfx::PShaderBuffer velocityX, Seele::Gfx::PShaderBuffer velocityY,
Seele::Gfx::PShaderBuffer velocityZ, UVector gridSize) {
Gfx::ODescriptorSet divergenceSet = computeDivergence.descriptorLayout->allocateDescriptorSet();
divergenceSet->updateBuffer("velocityX", 0, velocityX);
divergenceSet->updateBuffer("velocityY", 0, velocityY);
divergenceSet->updateBuffer("velocityZ", 0, velocityZ);
divergenceSet->updateBuffer("divergence", 0, divergence);
divergenceSet->updateBuffer("pressure", 0, pressure);
divergenceSet->writeChanges();
Gfx::OComputeCommand divergenceCommand = graphics->createComputeCommand();
divergenceCommand->bindPipeline(computeDivergence.pipeline);
divergenceCommand->bindDescriptor(divergenceSet);
divergenceCommand->dispatch(getDispatchSize(gridSize, computeDivergence.threadGroupSize));
graphics->executeCommands(std::move(divergenceCommand));
// divergence is now in velocityXBuffer, pressure is in velocityYBuffer
divergence->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);
pressure->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);
}
void SimulationComputePass::projectPass(Seele::Gfx::PShaderBuffer velocityX, Seele::Gfx::PShaderBuffer velocityY,
Seele::Gfx::PShaderBuffer velocityZ, Seele::Gfx::PShaderBuffer pressure, UVector gridSize) {
Gfx::ODescriptorSet projectSet = project.descriptorLayout->allocateDescriptorSet();
projectSet->updateBuffer("velocityX", 0, velocityX);
projectSet->updateBuffer("velocityY", 0, velocityY);
projectSet->updateBuffer("velocityZ", 0, velocityZ);
projectSet->updateBuffer("pressure", 0, pressure);
projectSet->writeChanges();
Gfx::OComputeCommand projectCommand = graphics->createComputeCommand();
projectCommand->bindPipeline(project.pipeline);
projectCommand->bindDescriptor(projectSet);
projectCommand->dispatch(getDispatchSize(gridSize, project.threadGroupSize));
graphics->executeCommands(std::move(projectCommand));
velocityX->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);
velocityY->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);
velocityZ->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);
}
void SimulationComputePass::advectPass(Gfx::PShaderBuffer quantity, Gfx::PShaderBuffer quantity0, Gfx::PShaderBuffer velocityX,
Gfx::PShaderBuffer velocityY, Gfx::PShaderBuffer velocityZ, float dt, UVector gridSize) {
Gfx::ODescriptorSet advectSet = this->advect.descriptorLayout->allocateDescriptorSet();
advectSet->updateBuffer("density", 0, quantity);
advectSet->updateBuffer("density0", 0, quantity0);
advectSet->updateBuffer("velocityX", 0, velocityX);
advectSet->updateBuffer("velocityY", 0, velocityY);
advectSet->updateBuffer("velocityZ", 0, velocityZ);
advectSet->updateConstants("dt", 0, &dt);
advectSet->writeChanges();
Gfx::OComputeCommand advectCommand = graphics->createComputeCommand();
advectCommand->bindPipeline(advect.pipeline);
advectCommand->bindDescriptor(advectSet);
advectCommand->dispatch(getDispatchSize(gridSize, advect.threadGroupSize));
graphics->executeCommands(std::move(advectCommand));
quantity->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);
}
void SimulationComputePass::reinitializeLevelSetPass(Seele::Gfx::PShaderBuffer phi, Seele::Gfx::PShaderBuffer phi0, UVector gridSize) {
graphics->beginDebugRegion("ReinitializeLevelSet");
// Snapshot current phi into phi0 for the sign function
phi->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_TRANSFER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT);
graphics->copyBuffer(phi, phi0);
phi0->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);
phi->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT | Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
float dtau = reinitDtau;
for (int i = 0; i < reinitIterations; ++i) {
Gfx::ODescriptorSet reinitSet = reinitialize.descriptorLayout->allocateDescriptorSet();
reinitSet->updateConstants("dtau", 0, &dtau);
reinitSet->updateBuffer("phi", 0, phi);
reinitSet->updateBuffer("phi0", 0, phi0);
reinitSet->writeChanges();
Gfx::OComputeCommand reinitCommand = graphics->createComputeCommand();
reinitCommand->bindPipeline(reinitialize.pipeline);
reinitCommand->bindDescriptor(reinitSet);
reinitCommand->dispatch(getDispatchSize(gridSize, reinitialize.threadGroupSize));
graphics->executeCommands(std::move(reinitCommand));
phi->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);
setBoundsPass(phi, 0, gridSize);
SWAP(phi, phi0);
}
graphics->endDebugRegion();
}
@@ -0,0 +1,82 @@
#pragma once
#include "Graphics/Buffer.h"
#include "Graphics/Descriptor.h"
#include "Graphics/Initializer.h"
#include "Graphics/RenderPass/RenderPass.h"
#include "Graphics/Resources.h"
#include "Math/Vector.h"
#include "Scene/Scene.h"
namespace Seele {
class SimulationComputePass : public RenderPass {
public:
SimulationComputePass(Gfx::PGraphics graphics, PScene scene);
virtual ~SimulationComputePass() override;
virtual void beginFrame(const Component::Camera& camera, const Seele::Component::Transform& transform) override;
virtual void render() override;
virtual void endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
private:
UVector getDispatchSize(const UVector& gridSize, const UVector& threadGroupSize);
void setBoundsPass(Gfx::PShaderBuffer buffer, int b, UVector gridSize);
void linearSolvePass(Gfx::PShaderBuffer next, Seele::Gfx::PShaderBuffer current, Seele::Gfx::PShaderBuffer grid0, float a, float c, UVector gridSize);
void divergencePass(Gfx::PShaderBuffer divergence, Seele::Gfx::PShaderBuffer pressure, Seele::Gfx::PShaderBuffer velocityX,
Seele::Gfx::PShaderBuffer velocityY, Seele::Gfx::PShaderBuffer velocityZ, UVector gridSize);
void projectPass(Gfx::PShaderBuffer velocityX, Seele::Gfx::PShaderBuffer velocityY, Seele::Gfx::PShaderBuffer velocityZ,
Seele::Gfx::PShaderBuffer pressure, UVector gridSize);
void advectPass(Gfx::PShaderBuffer quantity, Seele::Gfx::PShaderBuffer quantity0, Seele::Gfx::PShaderBuffer velocityX,
Seele::Gfx::PShaderBuffer velocityY, Seele::Gfx::PShaderBuffer velocityZ, float dt, UVector gridSize);
void reinitializeLevelSetPass(Gfx::PShaderBuffer phi, Seele::Gfx::PShaderBuffer phi0, UVector gridSize);
struct SetBounds {
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::OComputeShader shader;
Gfx::PComputePipeline pipeline;
Gfx::OComputeShader shaderEdges;
Gfx::PComputePipeline pipelineEdges;
Gfx::OComputeShader shaderCorners;
Gfx::PComputePipeline pipelineCorners;
constexpr static UVector threadGroupSize = {32, 8, 1};
} setBounds;
struct LinearSolve {
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::OComputeShader shader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {32, 8, 1};
} linearSolve;
struct ComputeDivergence {
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::OComputeShader shader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {32, 8, 1};
} computeDivergence;
struct Project {
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::OComputeShader shader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {32, 8, 1};
} project;
struct Advect {
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::OComputeShader shader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {32, 8, 1};
} advect;
struct Reinitialize {
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::OComputeShader shader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {32, 8, 1};
} reinitialize;
PScene scene;
constexpr static float dt = 0.1f;
};
DEFINE_REF(SimulationComputePass)
} // namespace Seele
@@ -0,0 +1,103 @@
#include "SurfaceExtractPass.h"
#include "Graphics/Command.h"
#include "Graphics/Descriptor.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h"
#include "Graphics/Shader.h"
#include "Math/Vector.h"
using namespace Seele;
// Linearly interpolate the position where the isosurface crosses the edge
// between two grid points.
static Vector vertexInterp(float isolevel, const Vector& p1, const Vector& p2, float v1, float v2) {
if (std::abs(v1 - v2) < 1e-10f)
return p1;
float t = (isolevel - v1) / (v2 - v1);
return Vector(p1.x + t * (p2.x - p1.x), p1.y + t * (p2.y - p1.y), p1.z + t * (p2.z - p1.z));
}
SurfaceExtractPass::SurfaceExtractPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
pipelineLayout = graphics->createPipelineLayout("SurfaceExtractPipelineLayout");
descriptorLayout = graphics->createDescriptorLayout("params");
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "vertexBuffer",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "normalBuffer",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "indexBuffer",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "surfaceCounts",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "levelSet",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
descriptorLayout->create();
pipelineLayout->addDescriptorLayout(descriptorLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "MarchingCubes",
.modules = {"MarchingCubes"},
.entryPoints = {{"marchingCubes", "MarchingCubes"}},
.rootSignature = pipelineLayout,
});
pipelineLayout->create();
computeShader = graphics->createComputeShader({0});
pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = computeShader,
.pipelineLayout = pipelineLayout,
});
}
SurfaceExtractPass::~SurfaceExtractPass() {}
void SurfaceExtractPass::beginFrame(const Seele::Component::Camera&, const Seele::Component::Transform&) {}
void SurfaceExtractPass::render() {
for (auto& [entityID, data] : scene->getFluidScene()->getFluidDataMap()) {
data.vertexBuffer->rotateBuffer(data.getVertexBufferSize() * sizeof(float));
data.normalBuffer->rotateBuffer(data.getVertexBufferSize() * sizeof(float));
data.indexBuffer->rotateBuffer(data.getIndexBufferSize() * sizeof(uint32));
uint32 surfaceCountData[4] = {0, 1, 0, 0};
data.surfaceCountBuffer->updateContents(0, sizeof(surfaceCountData), surfaceCountData);
data.surfaceCountBuffer->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);
descriptorSet = descriptorLayout->allocateDescriptorSet();
descriptorSet->updateBuffer("vertexBuffer", 0, data.vertexBuffer);
descriptorSet->updateBuffer("normalBuffer", 0, data.normalBuffer);
descriptorSet->updateBuffer("indexBuffer", 0, data.indexBuffer);
descriptorSet->updateBuffer("surfaceCounts", 0, data.surfaceCountBuffer);
descriptorSet->updateBuffer("levelSet", 0, data.phiBuffer);
descriptorSet->writeChanges();
Gfx::OComputeCommand cmd = graphics->createComputeCommand();
cmd->bindPipeline(pipeline);
cmd->bindDescriptor(descriptorSet);
cmd->dispatch((data.gridSize + threadGroupSize - 1u) / threadGroupSize);
graphics->executeCommands(std::move(cmd));
data.vertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
data.normalBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
data.indexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
data.surfaceCountBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_INDIRECT_COMMAND_READ_BIT, Gfx::SE_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
}
}
void SurfaceExtractPass::endFrame() {}
void SurfaceExtractPass::publishOutputs() {}
void SurfaceExtractPass::createRenderPass() { }
@@ -0,0 +1,29 @@
#pragma once
#include "Graphics/Graphics.h"
#include "Graphics/RenderPass/RenderPass.h"
#include "Graphics/Resources.h"
#include "Scene/Scene.h"
namespace Seele {
class SurfaceExtractPass : public RenderPass {
public:
SurfaceExtractPass(Gfx::PGraphics graphics, PScene scene);
virtual ~SurfaceExtractPass() override;
virtual void beginFrame(const Component::Camera &camera, const Component::Transform &transform) override;
virtual void render() override;
virtual void endFrame() override;
virtual void publishOutputs() override;
virtual void createRenderPass() override;
private:
PScene scene;
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::ODescriptorSet descriptorSet;
Gfx::OComputeShader computeShader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {16, 8, 1};
};
DEFINE_REF(SurfaceExtractPass)
} // namespace Seele
@@ -4,7 +4,39 @@
using namespace Seele; using namespace Seele;
VisibilityPass::VisibilityPass(Gfx::PGraphics graphics) : RenderPass(graphics) {} VisibilityPass::VisibilityPass(Gfx::PGraphics graphics) : RenderPass(graphics) {
visibilityDescriptor = graphics->createDescriptorLayout("pVisibilityParams");
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{
.name = VISIBILITY_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
});
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{
.name = CULLINGBUFFER_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
visibilityDescriptor->create();
visibilityLayout = graphics->createPipelineLayout("VisibilityLayout");
visibilityLayout->addDescriptorLayout(visibilityDescriptor);
visibilityLayout->addDescriptorLayout(viewParamsLayout);
ShaderCompilationInfo createInfo = {
.name = "Visibility",
.modules = {"VisibilityCompute"},
.entryPoints = {{"computeMain", "VisibilityCompute"}},
.rootSignature = visibilityLayout,
};
graphics->beginShaderCompilation(createInfo);
visibilityShader = graphics->createComputeShader({0});
visibilityLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = visibilityShader;
pipelineInfo.pipelineLayout = visibilityLayout;
visibilityPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
}
VisibilityPass::~VisibilityPass() {} VisibilityPass::~VisibilityPass() {}
@@ -52,37 +84,6 @@ void VisibilityPass::publishOutputs() {
uint32_t viewportWidth = viewport->getWidth(); uint32_t viewportWidth = viewport->getWidth();
uint32_t viewportHeight = viewport->getHeight(); uint32_t viewportHeight = viewport->getHeight();
threadGroupSize = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1)); threadGroupSize = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1));
visibilityDescriptor = graphics->createDescriptorLayout("pVisibilityParams");
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{
.name = VISIBILITY_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
});
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{
.name = CULLINGBUFFER_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
});
visibilityDescriptor->create();
visibilityLayout = graphics->createPipelineLayout("VisibilityLayout");
visibilityLayout->addDescriptorLayout(visibilityDescriptor);
visibilityLayout->addDescriptorLayout(viewParamsLayout);
ShaderCompilationInfo createInfo = {
.name = "Visibility",
.modules = {"VisibilityCompute"},
.entryPoints = {{"computeMain", "VisibilityCompute"}},
.rootSignature = visibilityLayout,
};
graphics->beginShaderCompilation(createInfo);
visibilityShader = graphics->createComputeShader({0});
visibilityLayout->create();
Gfx::ComputePipelineCreateInfo pipelineInfo;
pipelineInfo.computeShader = visibilityShader;
pipelineInfo.pipelineLayout = visibilityLayout;
visibilityPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{ cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.clearValue = 0xffffffff, .clearValue = 0xffffffff,
-1
View File
@@ -134,7 +134,6 @@ void ShaderCompiler::createShaders(ShaderPermutation permutation, Gfx::OPipeline
} }
// createInfo.typeParameter.add({Pair<const char*, const char*>("IVertexData", permutation.vertexDataName)}); // createInfo.typeParameter.add({Pair<const char*, const char*>("IVertexData", permutation.vertexDataName)});
createInfo.modules.add(permutation.vertexDataName); createInfo.modules.add(permutation.vertexDataName);
createInfo.dumpIntermediate = true;
if (permutation.useMeshShading) { if (permutation.useMeshShading) {
if (permutation.hasTaskShader) { if (permutation.hasTaskShader) {
+5 -4
View File
@@ -4,6 +4,7 @@
#include "Graphics/Enums.h" #include "Graphics/Enums.h"
#include <fmt/format.h> #include <fmt/format.h>
#include <vk_mem_alloc.h> #include <vk_mem_alloc.h>
#include <vulkan/vulkan_core.h>
using namespace Seele; using namespace Seele;
using namespace Seele::Vulkan; using namespace Seele::Vulkan;
@@ -192,7 +193,8 @@ void BufferAllocation::unmap() {
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType queueType, bool dynamic, std::string name, Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType queueType, bool dynamic, std::string name,
bool createCleared, uint32 clearValue) bool createCleared, uint32 clearValue)
: graphics(graphics), currentBuffer(0), initialOwner(queueType), : graphics(graphics), currentBuffer(0), initialOwner(queueType),
usage(usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT), usage(usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
(graphics->supportRayTracing() ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0)),
dynamic(dynamic), createCleared(createCleared), name(name), clearValue(clearValue) { dynamic(dynamic), createCleared(createCleared), name(name), clearValue(clearValue) {
if (size > 0) { if (size > 0) {
buffers.add(nullptr); buffers.add(nullptr);
@@ -483,9 +485,8 @@ IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& create
: Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo), : Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo),
Vulkan::Buffer(graphics, createInfo.sourceData.size, Vulkan::Buffer(graphics, createInfo.sourceData.size,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | (graphics->supportRayTracing() VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR (graphics->supportRayTracing() ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0),
: 0),
createInfo.sourceData.owner, false, createInfo.name) { createInfo.sourceData.owner, false, createInfo.name) {
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data); getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
// getAlloc()->pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_INDEX_READ_BIT, // getAlloc()->pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_INDEX_READ_BIT,
+2 -2
View File
@@ -455,7 +455,7 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptor) {
} }
} }
if (descriptorSet->setHandle->constantsBuffer != nullptr) { if (descriptorSet->setHandle->constantsBuffer != nullptr) {
descriptorSet->setHandle->bind(); descriptorSet->setHandle->constantsBuffer->bind();
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer)); boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
} }
@@ -482,7 +482,7 @@ void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptor
} }
} }
if (descriptorSet->setHandle->constantsBuffer != nullptr) { if (descriptorSet->setHandle->constantsBuffer != nullptr) {
descriptorSet->setHandle->bind(); descriptorSet->setHandle->constantsBuffer->bind();
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer)); boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
} }
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle(); sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
+20 -20
View File
@@ -175,7 +175,6 @@ Gfx::ODescriptorSet DescriptorPool::allocateDescriptorSet() {
}; };
vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo); vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo);
} }
cachedHandles[setIndex]->isUsed = true;
// Found set, stop searching // Found set, stop searching
return new DescriptorSet(graphics, this, cachedHandles[setIndex]); return new DescriptorSet(graphics, this, cachedHandles[setIndex]);
} }
@@ -191,13 +190,11 @@ void DescriptorPool::reset() {}
DescriptorSetHandle::DescriptorSetHandle(PGraphics graphics, const std::string& name) : CommandBoundResource(graphics, name) {} DescriptorSetHandle::DescriptorSetHandle(PGraphics graphics, const std::string& name) : CommandBoundResource(graphics, name) {}
DescriptorSetHandle::~DescriptorSetHandle() { DescriptorSetHandle::~DescriptorSetHandle() { graphics->getDestructionManager()->queueResourceForDestruction(std::move(constantsBuffer)); }
graphics->getDestructionManager()->queueResourceForDestruction(std::move(constantsBuffer));
}
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle) DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle)
: Gfx::DescriptorSet(owner->getLayout()), setHandle(setHandle), : Gfx::DescriptorSet(owner->getLayout()), setHandle(setHandle), graphics(graphics), owner(owner) {
graphics(graphics), owner(owner) { setHandle->isUsed = true;
boundResources.resize(owner->getLayout()->bindings.size()); boundResources.resize(owner->getLayout()->bindings.size());
for (uint32 i = 0; i < boundResources.size(); ++i) { for (uint32 i = 0; i < boundResources.size(); ++i) {
boundResources[i].resize(owner->getLayout()->bindings[i].descriptorCount); boundResources[i].resize(owner->getLayout()->bindings[i].descriptorCount);
@@ -208,8 +205,10 @@ DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescrip
constantData.resize(owner->getLayout()->constantsSize); constantData.resize(owner->getLayout()->constantsSize);
} }
DescriptorSet::~DescriptorSet() { DescriptorSet::~DescriptorSet() {
setHandle->isUsed = false; if (setHandle != nullptr) {
setHandle->isUsed = false;
}
} }
void DescriptorSet::updateConstants(const std::string& mappingName, uint32 offset, const void* data) { void DescriptorSet::updateConstants(const std::string& mappingName, uint32 offset, const void* data) {
@@ -406,20 +405,21 @@ void DescriptorSet::writeChanges() {
if (setHandle->constantsBuffer != nullptr) { if (setHandle->constantsBuffer != nullptr) {
graphics->getDestructionManager()->queueResourceForDestruction(std::move(setHandle->constantsBuffer)); graphics->getDestructionManager()->queueResourceForDestruction(std::move(setHandle->constantsBuffer));
} }
setHandle->constantsBuffer = new BufferAllocation(graphics, owner->getLayout()->getName(), setHandle->constantsBuffer =
VkBufferCreateInfo{ new BufferAllocation(graphics, owner->getLayout()->getName(),
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, VkBufferCreateInfo{
.pNext = nullptr, .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.size = constantData.size(), .pNext = nullptr,
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, .size = constantData.size(),
}, .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VmaAllocationCreateInfo{ },
.usage = VMA_MEMORY_USAGE_AUTO, VmaAllocationCreateInfo{
}, .usage = VMA_MEMORY_USAGE_AUTO,
Gfx::QueueType::GRAPHICS); },
Gfx::QueueType::GRAPHICS);
setHandle->constantsBuffer->updateContents(0, constantData.size(), constantData.data()); setHandle->constantsBuffer->updateContents(0, constantData.size(), constantData.data());
setHandle->constantsBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, setHandle->constantsBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
Gfx::SE_ACCESS_UNIFORM_READ_BIT, Gfx::SE_PIPELINE_STAGE_ALL_COMMANDS_BIT); Gfx::SE_ACCESS_UNIFORM_READ_BIT, Gfx::SE_PIPELINE_STAGE_ALL_COMMANDS_BIT);
bufferInfos.add(VkDescriptorBufferInfo{ bufferInfos.add(VkDescriptorBufferInfo{
.buffer = setHandle->constantsBuffer->buffer, .buffer = setHandle->constantsBuffer->buffer,
.offset = 0, .offset = 0,
+5 -1
View File
@@ -68,6 +68,10 @@ class DescriptorSet : public Gfx::DescriptorSet {
public: public:
DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle); DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle);
virtual ~DescriptorSet(); virtual ~DescriptorSet();
DescriptorSet(const DescriptorSet&) = delete;
DescriptorSet(DescriptorSet&&) noexcept;
DescriptorSet& operator=(const DescriptorSet&) = delete;
DescriptorSet& operator=(DescriptorSet&&) noexcept;
virtual void writeChanges() override; virtual void writeChanges() override;
virtual void updateConstants(const std::string& name, uint32 offset, const void* data) override; virtual void updateConstants(const std::string& name, uint32 offset, const void* data) override;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer shaderBuffer) override; virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer shaderBuffer) override;
@@ -91,7 +95,7 @@ class DescriptorSet : public Gfx::DescriptorSet {
// would not work anyways, so casts should be safe // would not work anyways, so casts should be safe
// Array<void*> cachedData; // Array<void*> cachedData;
Array<Array<PCommandBoundResource>> boundResources; Array<Array<PCommandBoundResource>> boundResources;
PDescriptorSetHandle setHandle; PDescriptorSetHandle setHandle = nullptr;
PGraphics graphics; PGraphics graphics;
PDescriptorPool owner; PDescriptorPool owner;
friend class DescriptorPool; friend class DescriptorPool;
+7 -6
View File
@@ -812,8 +812,7 @@ void Graphics::setupDebugCallback() {
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT,
VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT,
.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT, VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT,
.pfnUserCallback = &debugCallback, .pfnUserCallback = &debugCallback,
@@ -849,11 +848,11 @@ void Graphics::pickPhysicalDevice() {
vkGetPhysicalDeviceProperties2(physicalDevice, &props.get()); vkGetPhysicalDeviceProperties2(physicalDevice, &props.get());
features.get<VkPhysicalDeviceFeatures2>().features = { features.get<VkPhysicalDeviceFeatures2>().features = {
.geometryShader = false, .geometryShader = true,
.sampleRateShading = true, .sampleRateShading = true,
.fillModeNonSolid = true, .fillModeNonSolid = true,
.wideLines = false, .wideLines = true,
.pipelineStatisticsQuery = false, .pipelineStatisticsQuery = true,
.fragmentStoresAndAtomics = true, .fragmentStoresAndAtomics = true,
.shaderInt64 = true, .shaderInt64 = true,
.shaderInt16 = true, .shaderInt16 = true,
@@ -862,12 +861,14 @@ void Graphics::pickPhysicalDevice() {
features.get<VkPhysicalDeviceVulkan11Features>().multiview = true; features.get<VkPhysicalDeviceVulkan11Features>().multiview = true;
features.get<VkPhysicalDeviceVulkan11Features>().storageBuffer16BitAccess = true; features.get<VkPhysicalDeviceVulkan11Features>().storageBuffer16BitAccess = true;
features.get<VkPhysicalDeviceVulkan11Features>().shaderDrawParameters = true; features.get<VkPhysicalDeviceVulkan11Features>().shaderDrawParameters = true;
features.get<VkPhysicalDeviceVulkan11Features>().uniformAndStorageBuffer16BitAccess = true;
features.get<VkPhysicalDeviceVulkan12Features>().descriptorIndexing = true; features.get<VkPhysicalDeviceVulkan12Features>().descriptorIndexing = true;
features.get<VkPhysicalDeviceVulkan12Features>().descriptorBindingPartiallyBound = true; features.get<VkPhysicalDeviceVulkan12Features>().descriptorBindingPartiallyBound = true;
features.get<VkPhysicalDeviceVulkan12Features>().bufferDeviceAddress = true; features.get<VkPhysicalDeviceVulkan12Features>().bufferDeviceAddress = true;
features.get<VkPhysicalDeviceVulkan12Features>().storageBuffer8BitAccess = true; features.get<VkPhysicalDeviceVulkan12Features>().storageBuffer8BitAccess = true;
features.get<VkPhysicalDeviceVulkan12Features>().shaderInt8 = true; features.get<VkPhysicalDeviceVulkan12Features>().shaderInt8 = true;
features.get<VkPhysicalDeviceVulkan12Features>().uniformAndStorageBuffer8BitAccess = true;
rayTracingFeatures.get<VkPhysicalDeviceAccelerationStructureFeaturesKHR>().accelerationStructure = true; rayTracingFeatures.get<VkPhysicalDeviceAccelerationStructureFeaturesKHR>().accelerationStructure = true;
@@ -915,7 +916,7 @@ void Graphics::pickPhysicalDevice() {
shaderFloatControls = true; shaderFloatControls = true;
} }
} }
rayTracingEnabled = rayTracingPipelineSupport && accelerationStructureSupport && hostOperationsSupport && deviceAddressSupport && rayTracingEnabled = false &&rayTracingPipelineSupport && accelerationStructureSupport && hostOperationsSupport && deviceAddressSupport &&
descriptorIndexingSupport && spirv14Support && shaderFloatControls; descriptorIndexingSupport && spirv14Support && shaderFloatControls;
} }
+63 -16
View File
@@ -48,21 +48,79 @@ std::filesystem::path findExistingDirectory(std::initializer_list<std::filesyste
return {}; return {};
} }
bool containsDownstreamCompilerArtifacts(const std::filesystem::path& directory) {
std::error_code error;
if (!std::filesystem::exists(directory, error) || !std::filesystem::is_directory(directory, error)) {
return false;
}
for (const auto& entry : std::filesystem::directory_iterator(directory, error)) {
if (error || !entry.is_regular_file(error)) {
continue;
}
const auto fileName = entry.path().filename().string();
if (fileName.rfind("slang-glslang", 0) == 0 || fileName.rfind("spirv-opt", 0) == 0 || fileName.rfind("spirv-dis", 0) == 0) {
return true;
}
}
return false;
}
bool hasArtifactWithPrefix(const std::filesystem::path& directory, const char* prefix) {
std::error_code error;
if (!std::filesystem::exists(directory, error) || !std::filesystem::is_directory(directory, error)) {
return false;
}
for (const auto& entry : std::filesystem::directory_iterator(directory, error)) {
if (error || !entry.is_regular_file(error)) {
continue;
}
if (entry.path().filename().string().rfind(prefix, 0) == 0) {
return true;
}
}
return false;
}
std::filesystem::path findDownstreamCompilerDirectory(std::initializer_list<std::filesystem::path> candidates) {
for (const auto& candidate : candidates) {
if (containsDownstreamCompilerArtifacts(candidate)) {
return candidate;
}
}
return findExistingDirectory(candidates);
}
void configureDownstreamCompilers(slang::IGlobalSession* session) { void configureDownstreamCompilers(slang::IGlobalSession* session) {
const auto executableDirectory = getExecutableDirectory(); const auto executableDirectory = getExecutableDirectory();
const auto currentDirectory = std::filesystem::current_path(); const auto currentDirectory = std::filesystem::current_path();
const auto glslangDirectory = findExistingDirectory({ const auto glslangDirectory = findDownstreamCompilerDirectory({
executableDirectory,
executableDirectory / "Seele", executableDirectory / "Seele",
executableDirectory / "vcpkg_installed" / "x64-linux" / "lib", executableDirectory / "vcpkg_installed" / "x64-linux" / "lib",
currentDirectory / "build",
currentDirectory / "build" / "Seele",
currentDirectory / "Seele", currentDirectory / "Seele",
currentDirectory / "vcpkg_installed" / "x64-linux" / "lib", currentDirectory / "vcpkg_installed" / "x64-linux" / "lib",
}); });
if (!glslangDirectory.empty()) { if (!glslangDirectory.empty()) {
const std::string path = glslangDirectory.string(); const std::string path = glslangDirectory.string();
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_GLSLANG, path.c_str()); if (hasArtifactWithPrefix(glslangDirectory, "slang-glslang") || hasArtifactWithPrefix(glslangDirectory, "libslang-glslang")) {
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_OPT, path.c_str()); session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_GLSLANG, path.c_str());
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_DIS, path.c_str()); }
if (hasArtifactWithPrefix(glslangDirectory, "spirv-opt")) {
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_OPT, path.c_str());
}
if (hasArtifactWithPrefix(glslangDirectory, "spirv-dis")) {
session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_DIS, path.c_str());
}
} }
// Avoid optional SPIR-V downstream tools that are often unavailable in RenderDoc launch environments. // Avoid optional SPIR-V downstream tools that are often unavailable in RenderDoc launch environments.
@@ -130,10 +188,9 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
sessionDesc.preprocessorMacros = macros.data(); sessionDesc.preprocessorMacros = macros.data();
slang::TargetDesc targetDesc = {}; slang::TargetDesc targetDesc = {};
targetDesc.format = target; targetDesc.format = target;
targetDesc.flags = SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY;
sessionDesc.targetCount = 1; sessionDesc.targetCount = 1;
sessionDesc.targets = &targetDesc; sessionDesc.targets = &targetDesc;
StaticArray<const char*, 7> searchPaths = {"shaders/", "shaders/lib/", "shaders/raytracing/", "shaders/terrain", "shaders/game", "shaders/generated/", "Seele/shaders/lib/"}; StaticArray<const char*, 7> searchPaths = {"shaders/", "shaders/lib/", "shaders/raytracing/", "shaders/terrain", "shaders/game", "shaders/generated/", "shaders/fluid"};
sessionDesc.searchPaths = searchPaths.data(); sessionDesc.searchPaths = searchPaths.data();
sessionDesc.searchPathCount = searchPaths.size(); sessionDesc.searchPathCount = searchPaths.size();
@@ -184,16 +241,6 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
layout->addMapping(param->getName(), param->getBindingIndex()); layout->addMapping(param->getName(), param->getBindingIndex());
} }
// workaround
if (info.name == "RayGenMiss")
{
layout->addMapping("pScene", 2);
layout->addMapping("pLightEnv", 3);
layout->addMapping("pResources", 4);
layout->addMapping("pRayTracingParams", 5);
}
//layout->addMapping("pVertexData", 1);
// layout->addMapping("pWaterMaterial", 1);
} }
Pair<Slang::ComPtr<slang::IBlob>, std::string> Seele::generateShader(const ShaderCreateInfo& createInfo) { Pair<Slang::ComPtr<slang::IBlob>, std::string> Seele::generateShader(const ShaderCreateInfo& createInfo) {
+3
View File
@@ -1,6 +1,8 @@
target_sources(Engine target_sources(Engine
PRIVATE PRIVATE
EventManager.h EventManager.h
FluidScene.h
FluidScene.cpp
LightEnvironment.h LightEnvironment.h
LightEnvironment.cpp LightEnvironment.cpp
Util.h Util.h
@@ -11,6 +13,7 @@ target_sources(Engine
PUBLIC FILE_SET HEADERS PUBLIC FILE_SET HEADERS
FILES FILES
EventManager.h EventManager.h
FluidScene.h
LightEnvironment.h LightEnvironment.h
Util.h Util.h
Scene.h) Scene.h)
+173
View File
@@ -0,0 +1,173 @@
#include "FluidScene.h"
#include "Graphics/Enums.h"
using namespace Seele;
FluidScene::FluidScene(Gfx::PGraphics graphics) : graphics(graphics) {}
FluidScene::~FluidScene() {}
void FluidScene::updateFluidData(uint32 entityID, const Component::Transform& transform, const Component::FluidGrid& grid) {
if (!fluidDataMap.contains(entityID)) {
auto& data = fluidDataMap[entityID];
uint64 totalCells = (uint64)grid.gridSize.x * grid.gridSize.y * grid.gridSize.z;
uint64 bufferSize = totalCells * sizeof(float);
Array<float> initialDensity(bufferSize / sizeof(float));
Array<float> initialVelocityX(bufferSize / sizeof(float));
Array<float> initialVelocityY(bufferSize / sizeof(float));
Array<float> initialVelocityZ(bufferSize / sizeof(float));
Array<float> initialPhi(bufferSize / sizeof(float));
// Initialize level set to positive (outside) everywhere
float halfGridX = static_cast<float>(grid.gridSize.x) * 0.5f;
float halfGridY = static_cast<float>(grid.gridSize.y) * 0.5f;
float radius = static_cast<float>(grid.gridSize.x) * 0.2f;
// Place sphere center in the lower portion of the grid
float cx = halfGridX;
float cy = halfGridY;
float cz = static_cast<float>(grid.gridSize.z) * 0.3f;
for (uint32 z = 1; z < grid.gridSize.z - 1; ++z) {
for (uint32 y = 1; y < grid.gridSize.y - 1; ++y) {
for (uint32 x = 1; x < grid.gridSize.x - 1; ++x) {
uint32 idx = x + grid.gridSize.x * y + grid.gridSize.x * grid.gridSize.y * z;
float dx = static_cast<float>(x) - cx;
float dy = static_cast<float>(y) - cy;
float dz = static_cast<float>(z) - cz;
float dist = std::sqrt(dx * dx + dy * dy + dz * dz);
initialPhi[idx] = dist - radius;
if (dist < radius) {
initialDensity[idx] = 1.0f;
// Give an initial upward velocity to kick the simulation
initialVelocityZ[idx] = 5.0f;
}
}
}
}
data.phiBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
},
.name = "PhiBuffer",
});
data.phi0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialPhi.data(),
},
.name = "Phi0Buffer",
});
data.densityBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
},
.name = "DensityBuffer",
});
data.density0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialDensity.data(),
},
.name = "Density0Buffer",
});
data.scratchBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
},
.name = "ScratchBuffer",
});
data.velocityXNextBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
},
.name = "VelocityXNextBuffer",
});
data.velocityYNextBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
},
.name = "VelocityYNextBuffer",
});
data.velocityZNextBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
},
.name = "VelocityZNextBuffer",
});
data.velocityXBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
},
.name = "VelocityXBuffer",
});
data.velocityYBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
},
.name = "VelocityYBuffer",
});
data.velocityZBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
},
.name = "VelocityZBuffer",
});
data.velocityX0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialVelocityX.data(),
},
.name = "VelocityX0Buffer",
});
data.velocityY0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialVelocityY.data(),
},
.name = "VelocityY0Buffer",
});
data.velocityZ0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData =
{
.size = bufferSize,
.data = (uint8*)initialVelocityZ.data(),
},
.name = "VelocityZ0Buffer",
});
data.vertexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.name = "VertexBuffer",
});
data.normalBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.name = "NormalBuffer",
});
data.indexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.name = "IndexBuffer",
});
data.surfaceCountBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
.sourceData = {
.size = 4 * sizeof(uint32),
},
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
.name = "SurfaceCountBuffer",
});
}
auto& data = fluidDataMap[entityID];
data.transform = transform.transform;
data.cellSize = grid.cellSize;
data.viscosity = grid.viscosity;
data.diffusion = grid.diffusion;
data.gridSize = grid.gridSize;
}
+57
View File
@@ -0,0 +1,57 @@
#pragma once
#include "Component/FluidGrid.h"
#include "Component/Transform.h"
#include "Containers/Array.h"
#include "Containers/Map.h"
#include "Graphics/Buffer.h"
#include "Graphics/Graphics.h"
#include "Graphics/Shader.h"
#include "Math/Transform.h"
#include "Math/Vector.h"
#include "MinimalEngine.h"
namespace Seele {
class FluidScene {
public:
FluidScene(Gfx::PGraphics graphics);
virtual ~FluidScene();
struct FluidData {
Math::Transform transform;
float cellSize;
float viscosity;
float diffusion;
UVector gridSize;
Gfx::OShaderBuffer phiBuffer;
Gfx::OShaderBuffer phi0Buffer;
Gfx::OShaderBuffer densityBuffer;
Gfx::OShaderBuffer density0Buffer;
Gfx::OShaderBuffer scratchBuffer;
Gfx::OShaderBuffer velocityXNextBuffer;
Gfx::OShaderBuffer velocityYNextBuffer;
Gfx::OShaderBuffer velocityZNextBuffer;
Gfx::OShaderBuffer velocityXBuffer;
Gfx::OShaderBuffer velocityYBuffer;
Gfx::OShaderBuffer velocityZBuffer;
Gfx::OShaderBuffer velocityX0Buffer;
Gfx::OShaderBuffer velocityY0Buffer;
Gfx::OShaderBuffer velocityZ0Buffer;
Gfx::OShaderBuffer vertexBuffer;
Gfx::OShaderBuffer normalBuffer;
Gfx::OShaderBuffer indexBuffer;
Gfx::OShaderBuffer surfaceCountBuffer;
uint32 frameCounter = 0;
constexpr uint getVertexBufferSize() {
// Max 5 triangles per cell, 3 vertices per triangle
return gridSize.x * gridSize.y * gridSize.z * 15;
}
constexpr uint getIndexBufferSize() { return gridSize.x * gridSize.y * gridSize.z * 15; }
};
void updateFluidData(uint32 entityID, const Component::Transform& transform, const Component::FluidGrid& grid);
const Map<uint32, FluidData>& getFluidDataMap() const { return fluidDataMap; }
private:
Gfx::PGraphics graphics;
Map<uint32, FluidData> fluidDataMap;
};
DEFINE_REF(FluidScene)
} // namespace Seele
+1 -1
View File
@@ -1,7 +1,7 @@
#include "LightEnvironment.h" #include "LightEnvironment.h"
#include "Asset/AssetRegistry.h" #include "Asset/AssetRegistry.h"
#include "Asset/EnvironmentMapAsset.h"
#include "Graphics/Descriptor.h" #include "Graphics/Descriptor.h"
#include "Asset/EnvironmentMapAsset.h"
#include "Graphics/Enums.h" #include "Graphics/Enums.h"
#include "Graphics/Graphics.h" #include "Graphics/Graphics.h"
+2 -10
View File
@@ -1,22 +1,14 @@
#include "Scene.h" #include "Scene.h"
#include "Actor/PointLightActor.h"
#include "Asset/MaterialAsset.h"
#include "Asset/TextureAsset.h"
#include "Component/DirectionalLight.h"
#include "Component/Mesh.h"
#include "Component/PointLight.h"
#include "Component/Transform.h"
#include "Graphics/Graphics.h" #include "Graphics/Graphics.h"
#include "Graphics/Mesh.h"
#include "Graphics/StaticMeshVertexData.h"
using namespace Seele; using namespace Seele;
Scene::Scene(Gfx::PGraphics graphics) Scene::Scene(Gfx::PGraphics graphics)
: graphics(graphics), lightEnv(new LightEnvironment(graphics)), physics(registry) {} : graphics(graphics), lightEnv(new LightEnvironment(graphics)), fluidScene(new FluidScene(graphics)), physics(registry) {}
Scene::~Scene() {} Scene::~Scene() {}
void Scene::bakeLighting() {} void Scene::bakeLighting() {}
void Scene::update(float deltaTime) { physics.update(deltaTime); } void Scene::update(float deltaTime) { physics.update(deltaTime); }
+3 -3
View File
@@ -1,12 +1,10 @@
#pragma once #pragma once
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Component/Skybox.h"
#include "Graphics/Graphics.h" #include "Graphics/Graphics.h"
#include "LightEnvironment.h" #include "LightEnvironment.h"
#include "Physics/PhysicsSystem.h" #include "Physics/PhysicsSystem.h"
#include "FluidScene.h"
#include <entt/entt.hpp> #include <entt/entt.hpp>
#include <iostream>
namespace Seele { namespace Seele {
DECLARE_REF(Material) DECLARE_REF(Material)
@@ -33,12 +31,14 @@ class Scene {
template <typename Component> auto constructCallback() { return registry.on_construct<Component>(); } template <typename Component> auto constructCallback() { return registry.on_construct<Component>(); }
template <typename Component> auto destroyCallback() { return registry.on_destroy<Component>(); } template <typename Component> auto destroyCallback() { return registry.on_destroy<Component>(); }
PLightEnvironment getLightEnvironment() { return lightEnv; } PLightEnvironment getLightEnvironment() { return lightEnv; }
PFluidScene getFluidScene() { return fluidScene; }
Gfx::PGraphics getGraphics() const { return graphics; } Gfx::PGraphics getGraphics() const { return graphics; }
entt::registry registry; entt::registry registry;
private: private:
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
OLightEnvironment lightEnv; OLightEnvironment lightEnv;
OFluidScene fluidScene;
PhysicsSystem physics; PhysicsSystem physics;
Array<Gfx::OTexture2D> lightMaps; Array<Gfx::OTexture2D> lightMaps;
}; };
+3
View File
@@ -5,6 +5,8 @@ target_sources(Engine
ComponentSystem.h ComponentSystem.h
Executor.h Executor.h
Executor.cpp Executor.cpp
FluidUpdater.h
FluidUpdater.cpp
KeyboardInput.h KeyboardInput.h
KeyboardInput.cpp KeyboardInput.cpp
LightGather.h LightGather.h
@@ -21,6 +23,7 @@ target_sources(Engine
CameraUpdater.h CameraUpdater.h
ComponentSystem.h ComponentSystem.h
Executor.h Executor.h
FluidUpdater.h
KeyboardInput.h KeyboardInput.h
LightGather.h LightGather.h
MeshUpdater.h MeshUpdater.h
+13
View File
@@ -0,0 +1,13 @@
#include "FluidUpdater.h"
using namespace Seele;
using namespace Seele::System;
FluidUpdater::FluidUpdater(PScene scene) : ComponentSystem(scene) {}
FluidUpdater::~FluidUpdater() {}
void FluidUpdater::update(entt::entity id, Component::FluidGrid &grid, Component::Transform &transform) {
auto fluidScene = scene->getFluidScene();
fluidScene->updateFluidData((uint32)id, transform, grid);
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include "Component/FluidGrid.h"
#include "Component/Transform.h"
#include "ComponentSystem.h"
namespace Seele {
namespace System {
class FluidUpdater : public ComponentSystem<Component::FluidGrid, Component::Transform> {
public:
FluidUpdater(PScene scene);
virtual ~FluidUpdater();
virtual void update(entt::entity id, Component::FluidGrid& grid, Component::Transform& transform);
private:
};
} // namespace System
} // namespace Seele
+15 -2
View File
@@ -4,12 +4,16 @@
#include "Graphics/RenderPass/BasePass.h" #include "Graphics/RenderPass/BasePass.h"
#include "Graphics/RenderPass/CachedDepthPass.h" #include "Graphics/RenderPass/CachedDepthPass.h"
#include "Graphics/RenderPass/DepthCullingPass.h" #include "Graphics/RenderPass/DepthCullingPass.h"
#include "Graphics/RenderPass/FluidRenderPass.h"
#include "Graphics/RenderPass/LightCullingPass.h" #include "Graphics/RenderPass/LightCullingPass.h"
#include "Graphics/RenderPass/RayTracingPass.h" #include "Graphics/RenderPass/RayTracingPass.h"
#include "Graphics/RenderPass/ShadowPass.h"
#include "Graphics/RenderPass/SimulationComputePass.h"
#include "Graphics/RenderPass/SurfaceExtractPass.h"
#include "Graphics/RenderPass/ToneMappingPass.h" #include "Graphics/RenderPass/ToneMappingPass.h"
#include "Graphics/RenderPass/VisibilityPass.h" #include "Graphics/RenderPass/VisibilityPass.h"
#include "Graphics/RenderPass/ShadowPass.h"
#include "System/CameraUpdater.h" #include "System/CameraUpdater.h"
#include "System/FluidUpdater.h"
#include "System/LightGather.h" #include "System/LightGather.h"
#include "System/MeshUpdater.h" #include "System/MeshUpdater.h"
#include "Window/Window.h" #include "Window/Window.h"
@@ -25,11 +29,17 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
renderGraph.addPass(new LightCullingPass(graphics, scene)); renderGraph.addPass(new LightCullingPass(graphics, scene));
renderGraph.addPass(new ShadowPass(graphics, scene)); renderGraph.addPass(new ShadowPass(graphics, scene));
renderGraph.addPass(new BasePass(graphics, scene)); renderGraph.addPass(new BasePass(graphics, scene));
// renderGraph.addPass(new SimulationComputePass(graphics, scene));
// renderGraph.addPass(new SurfaceExtractPass(graphics, scene));
// renderGraph.addPass(new FluidRenderPass(graphics, scene));
renderGraph.addPass(new ToneMappingPass(graphics)); renderGraph.addPass(new ToneMappingPass(graphics));
renderGraph.setViewport(viewport); renderGraph.setViewport(viewport);
renderGraph.createRenderPass(); renderGraph.createRenderPass();
if (graphics->supportRayTracing()) { if (graphics->supportRayTracing()) {
rayTracingGraph.addPass(new RayTracingPass(graphics, scene)); rayTracingGraph.addPass(new RayTracingPass(graphics, scene));
rayTracingGraph.addPass(new SimulationComputePass(graphics, scene));
rayTracingGraph.addPass(new SurfaceExtractPass(graphics, scene));
rayTracingGraph.addPass(new FluidRenderPass(graphics, scene));
rayTracingGraph.addPass(new ToneMappingPass(graphics)); rayTracingGraph.addPass(new ToneMappingPass(graphics));
rayTracingGraph.setViewport(viewport); rayTracingGraph.setViewport(viewport);
rayTracingGraph.createRenderPass(); rayTracingGraph.createRenderPass();
@@ -90,12 +100,15 @@ void GameView::reloadGame() {
System::OKeyboardInput keyInput = new System::KeyboardInput(scene); System::OKeyboardInput keyInput = new System::KeyboardInput(scene);
keyboardSystem = keyInput; keyboardSystem = keyInput;
systemGraph->addSystem(std::move(keyInput)); systemGraph->addSystem(std::move(keyInput));
systemGraph->addSystem(new System::FluidUpdater(scene));
systemGraph->addSystem(new System::LightGather(scene)); systemGraph->addSystem(new System::LightGather(scene));
systemGraph->addSystem(new System::MeshUpdater(scene)); systemGraph->addSystem(new System::MeshUpdater(scene));
systemGraph->addSystem(new System::CameraUpdater(scene)); systemGraph->addSystem(new System::CameraUpdater(scene));
} }
void GameView::keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) { keyboardSystem->keyCallback(code, action, modifier); } void GameView::keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) {
keyboardSystem->keyCallback(code, action, modifier);
}
void GameView::mouseMoveCallback(double xPos, double yPos) { keyboardSystem->mouseCallback(xPos, yPos); } void GameView::mouseMoveCallback(double xPos, double yPos) { keyboardSystem->mouseCallback(xPos, yPos); }