diff --git a/.vscode/launch.json b/.vscode/launch.json index 7312dc4..c57d040 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -34,7 +34,23 @@ "environment": [ { "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", @@ -45,6 +61,11 @@ "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true + }, + { + "description": "Import Seele pretty-printers", + "text": "python exec(open('${workspaceFolder}/Seele/gdb/Seele.py').read())", + "ignoreFailures": true } ], }, diff --git a/CMakeLists.txt b/CMakeLists.txt index 00ce42a..6e21c2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,11 @@ if(WIN32) endif() 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_link_libraries(Engine PUBLIC Vulkan::Vulkan) diff --git a/gdb/Seele.py b/gdb/Seele.py index 0673a4a..9be3019 100644 --- a/gdb/Seele.py +++ b/gdb/Seele.py @@ -2,6 +2,25 @@ import sys sys.path.insert(0, '/usr/share/gdb/python/') 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: def __init__(self, val): self.val = val @@ -13,8 +32,8 @@ class ArrayPrinter: data = self.val['_data'] size = int(self.val['arraySize']) allocated = int(self.val['allocated']) - #yield f"[size]", size - #yield f"[allocated]", allocated + yield f"[size]", size + yield f"[allocated]", allocated for i in range(size): elem_val = (data + i).dereference() yield f"[{i}]", elem_val @@ -22,6 +41,66 @@ class ArrayPrinter: def display_hint(self): 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: def __init__(self, val): self.val = val @@ -53,6 +132,8 @@ class VectorPrinter: def build_pretty_printer(): pp = gdb.printing.RegexpCollectionPrettyPrinter("Seele") 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) return pp diff --git a/gdb/Seele_lldb.py b/gdb/Seele_lldb.py index 870660c..3673c93 100644 --- a/gdb/Seele_lldb.py +++ b/gdb/Seele_lldb.py @@ -31,6 +31,39 @@ class ArraySyntheticProvider: def has_children(self): 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): # Get the template parameters to determine vector length 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 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 debugger.HandleCommand('type summary add -F Seele_lldb.Vector_SummaryProvider -x "^glm::(detail::)?t?vec[234]?<.*>$"') diff --git a/res/shaders/fluid/Advect.slang b/res/shaders/fluid/Advect.slang new file mode 100644 index 0000000..3b2467e --- /dev/null +++ b/res/shaders/fluid/Advect.slang @@ -0,0 +1,55 @@ +import FluidGridData; + +struct Params +{ + // read-write + FluidGridData density; + // read-only + FluidGridData density0; + // read-only + FluidGridData velocityX; + // read-only + FluidGridData velocityY; + // read-only + FluidGridData velocityZ; + float dt; +}; +ParameterBlock params; + +[shader("compute")] +[numthreads(32, 8, 1)] +void advect(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + FluidGridData density = params.density; + FluidGridData density0 = params.density0; + FluidGridData velocityX = params.velocityX; + FluidGridData velocityY = params.velocityY; + FluidGridData 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])); +} \ No newline at end of file diff --git a/res/shaders/fluid/Divergence.slang b/res/shaders/fluid/Divergence.slang new file mode 100644 index 0000000..d1c5c69 --- /dev/null +++ b/res/shaders/fluid/Divergence.slang @@ -0,0 +1,35 @@ +import FluidGridData; + +struct Params +{ + // read-only + FluidGridData velocityX; + // read-only + FluidGridData velocityY; + // read-only + FluidGridData velocityZ; + // read-write + FluidGridData divergence; + // read-write + FluidGridData pressure; +}; +ParameterBlock params; + +[shader("compute")] +[numthreads(32, 8, 1)] +void computeDivergence(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + FluidGridData velocityX = params.velocityX; + FluidGridData velocityY = params.velocityY; + FluidGridData velocityZ = params.velocityZ; + FluidGridData divergence = params.divergence; + FluidGridData 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; +} \ No newline at end of file diff --git a/res/shaders/fluid/Extract.slang b/res/shaders/fluid/Extract.slang new file mode 100644 index 0000000..4a6cc2a --- /dev/null +++ b/res/shaders/fluid/Extract.slang @@ -0,0 +1,47 @@ +import FluidGridData; + +struct Parameter +{ + float iso; + FluidGridData density; + RWStructuredBuffer vertices; + RWStructuredBuffer indices; + RWStructuredBuffer surfaceCount; + RWStructuredBuffer vertexCount; +}; +ParameterBlock 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 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; +} \ No newline at end of file diff --git a/res/shaders/fluid/FluidGridData.slang b/res/shaders/fluid/FluidGridData.slang new file mode 100644 index 0000000..6bd7ecd --- /dev/null +++ b/res/shaders/fluid/FluidGridData.slang @@ -0,0 +1,15 @@ +static const uint3 gridSize = uint3(256, 256, 256); +struct FluidGridData +{ + RWStructuredBuffer 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; } + } +}; diff --git a/res/shaders/fluid/LinearSolve.slang b/res/shaders/fluid/LinearSolve.slang new file mode 100644 index 0000000..c8dd9ef --- /dev/null +++ b/res/shaders/fluid/LinearSolve.slang @@ -0,0 +1,32 @@ +import FluidGridData; + +struct Params +{ + // read-write + FluidGridData next; + // read-only + FluidGridData current; + // read-only + FluidGridData grid0; + float a; + float c; +}; +ParameterBlock params; + +[shader("compute")] +[numthreads(32, 8, 1)] +void linearSolve(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + FluidGridData next = params.next; + FluidGridData current = params.current; + FluidGridData 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; +} \ No newline at end of file diff --git a/res/shaders/fluid/MarchingCubes.slang b/res/shaders/fluid/MarchingCubes.slang new file mode 100644 index 0000000..7ada291 --- /dev/null +++ b/res/shaders/fluid/MarchingCubes.slang @@ -0,0 +1,205 @@ +import FluidGridData; +import MarchingCubesData; + +struct Params +{ + RWStructuredBuffer vertexBuffer; + RWStructuredBuffer normalBuffer; + RWStructuredBuffer indexBuffer; + RWStructuredBuffer indicesCount; + FluidGridData levelSet; +}; +ParameterBlock 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 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; + } +} \ No newline at end of file diff --git a/res/shaders/fluid/MarchingCubesData.slang b/res/shaders/fluid/MarchingCubesData.slang new file mode 100644 index 0000000..bc94a36 --- /dev/null +++ b/res/shaders/fluid/MarchingCubesData.slang @@ -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 diff --git a/res/shaders/fluid/Project.slang b/res/shaders/fluid/Project.slang new file mode 100644 index 0000000..78cdfb2 --- /dev/null +++ b/res/shaders/fluid/Project.slang @@ -0,0 +1,33 @@ +import FluidGridData; + +struct Params +{ + // read-write + FluidGridData velocityX; + // read-write + FluidGridData velocityY; + // read-write + FluidGridData velocityZ; + // read-only + FluidGridData pressure; +}; +ParameterBlock params; + +[shader("compute")] +[numthreads(32, 8, 1)] +void project(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + FluidGridData velocityX = params.velocityX; + FluidGridData velocityY = params.velocityY; + FluidGridData velocityZ = params.velocityZ; + FluidGridData 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; +} \ No newline at end of file diff --git a/res/shaders/fluid/Render.slang b/res/shaders/fluid/Render.slang new file mode 100644 index 0000000..a136b4c --- /dev/null +++ b/res/shaders/fluid/Render.slang @@ -0,0 +1,59 @@ +import Common; +import FluidGridData; +import LightEnv; +import MaterialParameter; + +struct Params +{ + StructuredBuffer vertexBuffer; + StructuredBuffer normalBuffer; + StructuredBuffer indexBuffer; +}; +ParameterBlock 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); +} \ No newline at end of file diff --git a/res/shaders/fluid/SetBound.slang b/res/shaders/fluid/SetBound.slang new file mode 100644 index 0000000..48e1bb9 --- /dev/null +++ b/res/shaders/fluid/SetBound.slang @@ -0,0 +1,71 @@ +import FluidGridData; + +struct Params +{ + int b; + // read-write + FluidGridData grid; +}; +ParameterBlock params; + +[shader("compute")] +[numthreads(32, 8, 1)] +void setBound(uint3 dispatchThreadID : SV_DispatchThreadID) +{ + int b = params.b; + FluidGridData 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 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 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]); +} \ No newline at end of file diff --git a/res/shaders/fluid/SignedDistance.slang b/res/shaders/fluid/SignedDistance.slang new file mode 100644 index 0000000..56ab5b3 --- /dev/null +++ b/res/shaders/fluid/SignedDistance.slang @@ -0,0 +1,65 @@ +import FluidGridData; + +struct Params +{ + float dtau; + // read-write: phi being reinitialized + FluidGridData phi; + // read-only: snapshot of phi before reinitialization (for sign) + FluidGridData phi0; +}; +ParameterBlock 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 phi = params.phi; + FluidGridData 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); +} \ No newline at end of file diff --git a/res/shaders/lib/Common.slang b/res/shaders/lib/Common.slang index 3ed67ae..99391a0 100644 --- a/res/shaders/lib/Common.slang +++ b/res/shaders/lib/Common.slang @@ -21,7 +21,6 @@ struct ViewParameter uint frameIndex; float time; }; -layout(set=0) ParameterBlock pViewParams; float4 worldToModel(float4x4 inverseTransform, float4 world) diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index d72d614..a75f351 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -71,7 +71,6 @@ struct LightEnv Texture2D brdfLUT; SamplerState lutSampler; }; -layout(set=3) ParameterBlock pLightEnv; interface IBRDF diff --git a/res/shaders/lib/Material.slang b/res/shaders/lib/Material.slang index 0653a71..df034de 100644 --- a/res/shaders/lib/Material.slang +++ b/res/shaders/lib/Material.slang @@ -14,7 +14,6 @@ struct MaterialResources SamplerState samplerArray[512]; StructuredBuffer floatArray; }; -layout(set=4) ParameterBlock pResources; Texture2D getMaterialTextureParameter(uint index) diff --git a/res/shaders/lib/Scene.slang b/res/shaders/lib/Scene.slang index 03359db..0e6a5a3 100644 --- a/res/shaders/lib/Scene.slang +++ b/res/shaders/lib/Scene.slang @@ -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 pOffsets; - struct Scene { StructuredBuffer positions; @@ -73,6 +59,21 @@ struct Scene }; ParameterBlock 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 pOffsets; + uint32_t encodePrimitive(uint32_t meshletId) { return meshletId; diff --git a/res/shaders/lib/StaticMeshVertexData.slang b/res/shaders/lib/StaticMeshVertexData.slang index 0fee1cc..dbe6600 100644 --- a/res/shaders/lib/StaticMeshVertexData.slang +++ b/res/shaders/lib/StaticMeshVertexData.slang @@ -34,5 +34,4 @@ struct StaticMeshVertexData StructuredBuffer color; StructuredBuffer texCoords[MAX_TEXCOORDS]; }; -layout(set = 1) ParameterBlock pVertexData; \ No newline at end of file diff --git a/res/shaders/raytracing/ClosestHit.slang b/res/shaders/raytracing/ClosestHit.slang index d3f80c7..683f3a3 100644 --- a/res/shaders/raytracing/ClosestHit.slang +++ b/res/shaders/raytracing/ClosestHit.slang @@ -1,12 +1,12 @@ import Common; import MaterialParameter; import LightEnv; -import Scene; -import RayTracingData; import VertexData; import Material; import StaticMeshVertexData; import MATERIAL_FILE_NAME; +import RayTracingData; +import Scene; // simplification: all BLAS only have 1 geometry diff --git a/res/shaders/raytracing/RayTracingData.slang b/res/shaders/raytracing/RayTracingData.slang index 276b97a..6739ff0 100644 --- a/res/shaders/raytracing/RayTracingData.slang +++ b/res/shaders/raytracing/RayTracingData.slang @@ -9,7 +9,6 @@ struct RayTracingParams TextureCube skyBox; SamplerState skyBoxSampler; }; -layout(set=5) ParameterBlock pRayTracingParams; struct RayPayload diff --git a/src/Benchmark/PlayView.cpp b/src/Benchmark/PlayView.cpp index 5e7fdfc..69320ea 100644 --- a/src/Benchmark/PlayView.cpp +++ b/src/Benchmark/PlayView.cpp @@ -78,5 +78,3 @@ void PlayView::render() { GameView::render(); renderTimestamp->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "RenderEnd"); } - -void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) { GameView::keyCallback(code, action, modifier); } diff --git a/src/Benchmark/PlayView.h b/src/Benchmark/PlayView.h index 6b763cd..87b2f92 100644 --- a/src/Benchmark/PlayView.h +++ b/src/Benchmark/PlayView.h @@ -12,8 +12,6 @@ class PlayView : public GameView { virtual void prepareRender() override; virtual void render() override; - - virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override; private: std::thread queryThread; diff --git a/src/Editor/Asset/EnvironmentLoader.cpp b/src/Editor/Asset/EnvironmentLoader.cpp index f73af8d..da6aa2e 100644 --- a/src/Editor/Asset/EnvironmentLoader.cpp +++ b/src/Editor/Asset/EnvironmentLoader.cpp @@ -93,7 +93,6 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic {"precomputeBRDF", "EnvironmentMapping"}, }, .rootSignature = cubePipelineLayout, - .dumpIntermediate = true, }); cubePipelineLayout->create(); diff --git a/src/Editor/Asset/TextureLoader.cpp b/src/Editor/Asset/TextureLoader.cpp index 06075ad..1d48ff0 100644 --- a/src/Editor/Asset/TextureLoader.cpp +++ b/src/Editor/Asset/TextureLoader.cpp @@ -114,7 +114,7 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) { .uastcFlags = KTX_PACK_UASTC_LEVEL_DEFAULT, .uastcRDO = true, }; - KTX_ASSERT(ktxTexture2_CompressBasisEx(kTexture, &basisParams)); + // KTX_ASSERT(ktxTexture2_CompressBasis(kTexture, 0)); //KTX_ASSERT(ktxTexture2_DeflateZstd(kTexture, 10)); char writer[100]; diff --git a/src/Editor/Window/InspectorView.cpp b/src/Editor/Window/InspectorView.cpp index 1714b2e..241642a 100644 --- a/src/Editor/Window/InspectorView.cpp +++ b/src/Editor/Window/InspectorView.cpp @@ -38,11 +38,11 @@ void InspectorView::render() { renderGraph.render(Component::Camera(), Component void InspectorView::applyArea(URect ) {} -void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier) {} +void InspectorView::keyCallback(KeyCode, InputAction, KeyModifierFlags) {} void InspectorView::mouseMoveCallback(double, double) {} -void InspectorView::mouseButtonCallback(MouseButton, InputAction, KeyModifier) {} +void InspectorView::mouseButtonCallback(MouseButton, InputAction, KeyModifierFlags) {} void InspectorView::scrollCallback(double, double) {} diff --git a/src/Editor/Window/InspectorView.h b/src/Editor/Window/InspectorView.h index ffd8f8e..d4ef590 100644 --- a/src/Editor/Window/InspectorView.h +++ b/src/Editor/Window/InspectorView.h @@ -26,9 +26,9 @@ class InspectorView : public View { RenderGraph renderGraph; 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 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 fileCallback(int count, const char** paths) override; }; diff --git a/src/Editor/Window/PlayView.cpp b/src/Editor/Window/PlayView.cpp index d783c4b..540b8b8 100644 --- a/src/Editor/Window/PlayView.cpp +++ b/src/Editor/Window/PlayView.cpp @@ -2,6 +2,7 @@ #include "Graphics/Enums.h" #include "MinimalEngine.h" #include "Window/Window.h" +#include using namespace Seele; using namespace Seele::Editor; @@ -21,7 +22,7 @@ void PlayView::prepareRender() { GameView::prepareRender(); } 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); if (code == KeyCode::KEY_P && action == InputAction::RELEASE) { getGlobals().usePositionOnly = !getGlobals().usePositionOnly; diff --git a/src/Editor/Window/PlayView.h b/src/Editor/Window/PlayView.h index e62a612..41ffde6 100644 --- a/src/Editor/Window/PlayView.h +++ b/src/Editor/Window/PlayView.h @@ -14,7 +14,7 @@ class PlayView : public GameView { virtual void prepareRender() 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: }; diff --git a/src/Editor/Window/SceneView.cpp b/src/Editor/Window/SceneView.cpp index e9564ac..e1a3d3a 100644 --- a/src/Editor/Window/SceneView.cpp +++ b/src/Editor/Window/SceneView.cpp @@ -42,11 +42,11 @@ void SceneView::prepareRender() {} 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::mouseButtonCallback(MouseButton button, InputAction action, KeyModifier) { +void SceneView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags) { cameraSystem.mouseButtonCallback(button, action); } diff --git a/src/Editor/Window/SceneView.h b/src/Editor/Window/SceneView.h index 7cb4a31..14e5e80 100644 --- a/src/Editor/Window/SceneView.h +++ b/src/Editor/Window/SceneView.h @@ -29,9 +29,9 @@ class SceneView : public View { 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 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 fileCallback(int count, const char** paths) override; }; diff --git a/src/Editor/main.cpp b/src/Editor/main.cpp index 3f88846..8f06238 100644 --- a/src/Editor/main.cpp +++ b/src/Editor/main.cpp @@ -21,9 +21,9 @@ using namespace Seele::Editor; static Gfx::OGraphics graphics; int main() { - std::string gameName = "MeshShadingDemo"; - std::filesystem::path outputPath = fmt::format("/Users/dynamitos/{0}Game/", gameName); - std::filesystem::path sourcePath = fmt::format("/Users/dynamitos/{0}/", gameName); + std::string gameName = "FluidSimulation"; + std::filesystem::path outputPath = fmt::format("/home/dynamitos/{0}Game/", gameName); + std::filesystem::path sourcePath = fmt::format("/home/dynamitos/{0}/", gameName); #ifdef WIN32 std::string libraryEnding = "dll"; #elif __APPLE__ @@ -31,7 +31,7 @@ int main() { #else std::string libraryEnding = "so"; #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"; if (true) { graphics = new Vulkan::Graphics(); @@ -46,9 +46,9 @@ int main() { AssetImporter::importFont(FontImportArgs{ .filePath = "./fonts/arial.ttf", }); - // AssetImporter::importEnvironmentMap(EnvironmentImportArgs{ - // .filePath = sourcePath / "import" / "textures" / "newport_loft.hdr", - // }); + AssetImporter::importEnvironmentMap(EnvironmentImportArgs{ + .filePath = sourcePath / "import" / "newport_loft.hdr", + }); // AssetImporter::importTexture(TextureImportArgs{ // .filePath = sourcePath / "import" / "textures" / "grass_block_side.png", // .importPath = "", @@ -62,12 +62,12 @@ int main() { // .importPath = "rttest", // }); + // AssetImporter::importMesh(MeshImportArgs{ + // .filePath = sourcePath / "import" / "models" / "cube.fbx", + // .importPath = "", + // }); AssetImporter::importMesh(MeshImportArgs{ - .filePath = sourcePath / "import" / "models" / "cube.fbx", - .importPath = "", - }); - AssetImporter::importMesh(MeshImportArgs{ - .filePath = sourcePath / "import" / "models" / "rttest.gltf", + .filePath = sourcePath / "import" / "rttest.gltf", .importPath = "rttest", }); diff --git a/src/Engine/Component/CMakeLists.txt b/src/Engine/Component/CMakeLists.txt index a830681..612cc82 100644 --- a/src/Engine/Component/CMakeLists.txt +++ b/src/Engine/Component/CMakeLists.txt @@ -6,6 +6,7 @@ target_sources(Engine Collider.cpp Component.h DirectionalLight.h + FluidGrid.h KeyboardInput.h Mesh.h MeshCollider.h @@ -29,6 +30,7 @@ target_sources(Engine Collider.h Component.h DirectionalLight.h + FluidGrid.h KeyboardInput.h MeshCollider.h Mesh.h diff --git a/src/Engine/Component/FluidGrid.h b/src/Engine/Component/FluidGrid.h new file mode 100644 index 0000000..5c9aa9e --- /dev/null +++ b/src/Engine/Component/FluidGrid.h @@ -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 \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 59124a8..a645a92 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -1,5 +1,6 @@ #include "BasePass.h" #include "Asset/AssetRegistry.h" +#include "Asset/EnvironmentMapAsset.h" #include "Component/Camera.h" #include "Graphics/Command.h" #include "Graphics/Descriptor.h" @@ -12,10 +13,9 @@ #include "Math/Matrix.h" #include "Math/Vector.h" #include "MinimalEngine.h" -#include "ShadowPass.h" -#include "Scene/Scene.h" -#include "Asset/EnvironmentMapAsset.h" #include "Scene/LightEnvironment.h" +#include "Scene/Scene.h" +#include "ShadowPass.h" using namespace Seele; @@ -59,10 +59,8 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics) .name = SHADOWSAMPLER_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER, }); - shadowMappingLayout->addDescriptorBinding(Gfx::DescriptorBinding{ - .name = CASCADE_SPLIT_NAME, - .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER - }); + shadowMappingLayout->addDescriptorBinding( + Gfx::DescriptorBinding{.name = CASCADE_SPLIT_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER}); shadowMappingLayout->create(); basePassLayout->addDescriptorLayout(lightCullingLayout); @@ -116,6 +114,58 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics) .minLod = 0.0f, .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() {} @@ -176,7 +226,7 @@ void BasePass::render() { transparentCulling->updateTexture(LIGHTGRID_NAME, 0, tLightGrid->getDefaultView()); opaqueCulling->writeChanges(); transparentCulling->writeChanges(); - + shadowMappingLayout->reset(); shadowMapping = shadowMappingLayout->allocateDescriptorSet(); for (uint32 i = 0; i < NUM_CASCADES; ++i) { @@ -268,7 +318,8 @@ void BasePass::render() { command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo))); } 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) { command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, @@ -382,8 +433,8 @@ void BasePass::render() { transparentCommand->bindPipeline(pipeline); } transparentCommand->bindDescriptor({viewParamsSet, t.vertexData->getVertexDataSet(), t.vertexData->getInstanceDataSet(), - scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), shadowMapping, - transparentCulling}); + scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), + shadowMapping, transparentCulling}); transparentCommand->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(VertexData::DrawCallOffsets), &t.offsets); @@ -536,24 +587,6 @@ void BasePass::createRenderPass() { // 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 = { .bindings = { @@ -605,27 +638,6 @@ void BasePass::createRenderPass() { } // 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({ .magFilter = Gfx::SE_FILTER_LINEAR, .minFilter = Gfx::SE_FILTER_LINEAR, @@ -642,23 +654,6 @@ void BasePass::createRenderPass() { skyboxData.fogColor = skybox.fogColor; 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 = { .topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, .vertexShader = vertexShader, @@ -673,10 +668,11 @@ void BasePass::createRenderPass() { { .polygonMode = Gfx::SE_POLYGON_MODE_FILL, }, - .depthStencilState = { - .depthTestEnable = true, - .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, - }, + .depthStencilState = + { + .depthTestEnable = true, + .depthCompareOp = Gfx::SE_COMPARE_OP_GREATER, + }, .colorBlend = { .attachmentCount = 1, diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index 04972f2..2ed16da 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -2,6 +2,7 @@ #include "Graphics/Buffer.h" #include "Graphics/Descriptor.h" #include "Graphics/RenderPass/ShadowPass.h" +#include "Component/Skybox.h" #include "MinimalEngine.h" #include "RenderPass.h" diff --git a/src/Engine/Graphics/RenderPass/CMakeLists.txt b/src/Engine/Graphics/RenderPass/CMakeLists.txt index 00ec48c..9d7b723 100644 --- a/src/Engine/Graphics/RenderPass/CMakeLists.txt +++ b/src/Engine/Graphics/RenderPass/CMakeLists.txt @@ -6,6 +6,8 @@ target_sources(Engine CachedDepthPass.cpp DepthCullingPass.h DepthCullingPass.cpp + FluidRenderPass.h + FluidRenderPass.cpp LightCullingPass.h LightCullingPass.cpp RayTracingPass.h @@ -17,6 +19,10 @@ target_sources(Engine RenderPass.cpp ShadowPass.h ShadowPass.cpp + SimulationComputePass.h + SimulationComputePass.cpp + SurfaceExtractPass.h + SurfaceExtractPass.cpp #TerrainRenderer.h #TerrainRenderer.cpp ToneMappingPass.h @@ -34,6 +40,7 @@ target_sources(Engine BasePass.h CachedDepthPass.h DepthCullingPass.h + FluidRenderPass.h LightCullingPass.h ToneMappingPass.h RayTracingPass.h @@ -41,6 +48,8 @@ target_sources(Engine RenderGraphResources.h RenderPass.h ShadowPass.h + SimulationComputePass.h + SurfaceExtractPass.h #TerrainRenderer.h UIPass.h VisibilityPass.h) \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp index 7b9d2bb..f457c11 100644 --- a/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthCullingPass.cpp @@ -37,6 +37,24 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend .size = sizeof(MipParam), .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()) { graphics->getShaderCompiler()->registerRenderPass("DepthPass", Gfx::PassConfig{ @@ -255,24 +273,6 @@ void DepthCullingPass::publishOutputs() { .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"); resources->registerQueryOutput("DEPTH_QUERY", query); diff --git a/src/Engine/Graphics/RenderPass/FluidRenderPass.cpp b/src/Engine/Graphics/RenderPass/FluidRenderPass.cpp new file mode 100644 index 0000000..8e4fcc0 --- /dev/null +++ b/src/Engine/Graphics/RenderPass/FluidRenderPass.cpp @@ -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 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, + }, + }, + }, + }); +} \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/FluidRenderPass.h b/src/Engine/Graphics/RenderPass/FluidRenderPass.h new file mode 100644 index 0000000..9d61319 --- /dev/null +++ b/src/Engine/Graphics/RenderPass/FluidRenderPass.h @@ -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 \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 1674143..4a3af87 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -11,7 +11,137 @@ 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() {} @@ -91,86 +221,9 @@ void LightCullingPass::publishOutputs() { dispatchParamsSet = dispatchParamsLayout->allocateDescriptorSet(); dispatchParamsSet->updateConstants("numThreadGroups", 0, &numThreadGroups); dispatchParamsSet->updateConstants("numThreads", 0, &numThreads); + dispatchParamsSet->updateBuffer(FRUSTUMBUFFER_NAME, 0, frustumBuffer); 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; ShaderBufferCreateInfo structInfo = { .sourceData = @@ -188,8 +241,7 @@ void LightCullingPass::publishOutputs() { structInfo = { .sourceData = { - .size = (uint32)sizeof(uint32) * numThreadGroups.x * numThreadGroups.y * - numThreadGroups.z * 8192, + .size = (uint32)sizeof(uint32) * numThreadGroups.x * numThreadGroups.y * numThreadGroups.z * 8192, .data = nullptr, .owner = Gfx::QueueType::COMPUTE, }, @@ -237,41 +289,6 @@ void LightCullingPass::setupFrustums() { updateViewParameters(Component::Camera(), Component::Transform()); 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{ .sourceData = { @@ -299,6 +316,6 @@ void LightCullingPass::setupFrustums() { commands.add(std::move(command)); graphics->executeCommands(std::move(commands)); 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(); } diff --git a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp index 678079a..8c25ec8 100644 --- a/src/Engine/Graphics/RenderPass/RayTracingPass.cpp +++ b/src/Engine/Graphics/RenderPass/RayTracingPass.cpp @@ -4,9 +4,10 @@ #include "Graphics/RayTracing.h" #include "Graphics/Shader.h" #include "Graphics/StaticMeshVertexData.h" -#include "RenderPass.h" #include "Material/Material.h" #include "Material/MaterialInstance.h" +#include "RenderPass.h" +#include using namespace Seele; @@ -55,11 +56,24 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa .size = sizeof(SampleParams), .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{ .baseLayout = pipelineLayout, .mainFile = "ClosestHit", .useMaterial = true, .rayTracing = true, + .dumpIntermediates = true, }); skyBox = AssetRegistry::findEnvironmentMap("", "newport_loft")->getSkybox(); 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, Gfx::SE_ACCESS_SHADER_WRITE_BIT, 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, - Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); - ShaderCompilationInfo compileInfo = { - .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(); + resources->registerRenderPassOutput("BASEPASS_COLOR", + Gfx::RenderTargetAttachment(texture->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED, + Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)); } void RayTracingPass::createRenderPass() {} diff --git a/src/Engine/Graphics/RenderPass/SimulationComputePass.cpp b/src/Engine/Graphics/RenderPass/SimulationComputePass.cpp new file mode 100644 index 0000000..92cb0e4 --- /dev/null +++ b/src/Engine/Graphics/RenderPass/SimulationComputePass.cpp @@ -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 + +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(); +} diff --git a/src/Engine/Graphics/RenderPass/SimulationComputePass.h b/src/Engine/Graphics/RenderPass/SimulationComputePass.h new file mode 100644 index 0000000..656fcb6 --- /dev/null +++ b/src/Engine/Graphics/RenderPass/SimulationComputePass.h @@ -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 \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/SurfaceExtractPass.cpp b/src/Engine/Graphics/RenderPass/SurfaceExtractPass.cpp new file mode 100644 index 0000000..e7d8513 --- /dev/null +++ b/src/Engine/Graphics/RenderPass/SurfaceExtractPass.cpp @@ -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() { } \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/SurfaceExtractPass.h b/src/Engine/Graphics/RenderPass/SurfaceExtractPass.h new file mode 100644 index 0000000..59dee6e --- /dev/null +++ b/src/Engine/Graphics/RenderPass/SurfaceExtractPass.h @@ -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 \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp index 0c17c73..24abc48 100644 --- a/src/Engine/Graphics/RenderPass/VisibilityPass.cpp +++ b/src/Engine/Graphics/RenderPass/VisibilityPass.cpp @@ -4,7 +4,39 @@ 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() {} @@ -52,37 +84,6 @@ void VisibilityPass::publishOutputs() { uint32_t viewportWidth = viewport->getWidth(); uint32_t viewportHeight = viewport->getHeight(); 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{ .clearValue = 0xffffffff, diff --git a/src/Engine/Graphics/Shader.cpp b/src/Engine/Graphics/Shader.cpp index bfae762..8f5eb27 100644 --- a/src/Engine/Graphics/Shader.cpp +++ b/src/Engine/Graphics/Shader.cpp @@ -134,7 +134,6 @@ void ShaderCompiler::createShaders(ShaderPermutation permutation, Gfx::OPipeline } // createInfo.typeParameter.add({Pair("IVertexData", permutation.vertexDataName)}); createInfo.modules.add(permutation.vertexDataName); - createInfo.dumpIntermediate = true; if (permutation.useMeshShading) { if (permutation.hasTaskShader) { diff --git a/src/Engine/Graphics/Vulkan/Buffer.cpp b/src/Engine/Graphics/Vulkan/Buffer.cpp index 1a54701..c55d784 100644 --- a/src/Engine/Graphics/Vulkan/Buffer.cpp +++ b/src/Engine/Graphics/Vulkan/Buffer.cpp @@ -4,6 +4,7 @@ #include "Graphics/Enums.h" #include #include +#include using namespace Seele; 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, bool createCleared, uint32 clearValue) : 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) { if (size > 0) { buffers.add(nullptr); @@ -483,9 +485,8 @@ IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& create : Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo), 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_STORAGE_BUFFER_BIT | (graphics->supportRayTracing() - ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR - : 0), + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | + (graphics->supportRayTracing() ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0), createInfo.sourceData.owner, false, createInfo.name) { 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, diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 53141bc..d67b5c3 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -455,7 +455,7 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptor) { } } if (descriptorSet->setHandle->constantsBuffer != nullptr) { - descriptorSet->setHandle->bind(); + descriptorSet->setHandle->constantsBuffer->bind(); boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer)); } @@ -482,7 +482,7 @@ void ComputeCommand::bindDescriptor(const Array& descriptor } } if (descriptorSet->setHandle->constantsBuffer != nullptr) { - descriptorSet->setHandle->bind(); + descriptorSet->setHandle->constantsBuffer->bind(); boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer)); } sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle(); diff --git a/src/Engine/Graphics/Vulkan/Descriptor.cpp b/src/Engine/Graphics/Vulkan/Descriptor.cpp index 214607f..6edccee 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.cpp +++ b/src/Engine/Graphics/Vulkan/Descriptor.cpp @@ -175,7 +175,6 @@ Gfx::ODescriptorSet DescriptorPool::allocateDescriptorSet() { }; vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo); } - cachedHandles[setIndex]->isUsed = true; // Found set, stop searching 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() { - graphics->getDestructionManager()->queueResourceForDestruction(std::move(constantsBuffer)); -} +DescriptorSetHandle::~DescriptorSetHandle() { graphics->getDestructionManager()->queueResourceForDestruction(std::move(constantsBuffer)); } DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle) - : Gfx::DescriptorSet(owner->getLayout()), setHandle(setHandle), - graphics(graphics), owner(owner) { + : Gfx::DescriptorSet(owner->getLayout()), setHandle(setHandle), graphics(graphics), owner(owner) { + setHandle->isUsed = true; boundResources.resize(owner->getLayout()->bindings.size()); for (uint32 i = 0; i < boundResources.size(); ++i) { boundResources[i].resize(owner->getLayout()->bindings[i].descriptorCount); @@ -208,8 +205,10 @@ DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescrip constantData.resize(owner->getLayout()->constantsSize); } -DescriptorSet::~DescriptorSet() { - setHandle->isUsed = false; +DescriptorSet::~DescriptorSet() { + if (setHandle != nullptr) { + setHandle->isUsed = false; + } } void DescriptorSet::updateConstants(const std::string& mappingName, uint32 offset, const void* data) { @@ -406,20 +405,21 @@ void DescriptorSet::writeChanges() { if (setHandle->constantsBuffer != nullptr) { graphics->getDestructionManager()->queueResourceForDestruction(std::move(setHandle->constantsBuffer)); } - setHandle->constantsBuffer = new BufferAllocation(graphics, owner->getLayout()->getName(), - VkBufferCreateInfo{ - .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, - .pNext = nullptr, - .size = constantData.size(), - .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - }, - VmaAllocationCreateInfo{ - .usage = VMA_MEMORY_USAGE_AUTO, - }, - Gfx::QueueType::GRAPHICS); + setHandle->constantsBuffer = + new BufferAllocation(graphics, owner->getLayout()->getName(), + VkBufferCreateInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .pNext = nullptr, + .size = constantData.size(), + .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + }, + VmaAllocationCreateInfo{ + .usage = VMA_MEMORY_USAGE_AUTO, + }, + Gfx::QueueType::GRAPHICS); setHandle->constantsBuffer->updateContents(0, constantData.size(), constantData.data()); 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{ .buffer = setHandle->constantsBuffer->buffer, .offset = 0, diff --git a/src/Engine/Graphics/Vulkan/Descriptor.h b/src/Engine/Graphics/Vulkan/Descriptor.h index b5821d3..4a1236e 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.h +++ b/src/Engine/Graphics/Vulkan/Descriptor.h @@ -68,6 +68,10 @@ class DescriptorSet : public Gfx::DescriptorSet { public: DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle); virtual ~DescriptorSet(); + DescriptorSet(const DescriptorSet&) = delete; + DescriptorSet(DescriptorSet&&) noexcept; + DescriptorSet& operator=(const DescriptorSet&) = delete; + DescriptorSet& operator=(DescriptorSet&&) noexcept; virtual void writeChanges() 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; @@ -91,7 +95,7 @@ class DescriptorSet : public Gfx::DescriptorSet { // would not work anyways, so casts should be safe // Array cachedData; Array> boundResources; - PDescriptorSetHandle setHandle; + PDescriptorSetHandle setHandle = nullptr; PGraphics graphics; PDescriptorPool owner; friend class DescriptorPool; diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index ef2e251..35833ef 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -812,8 +812,7 @@ void Graphics::setupDebugCallback() { .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT, .pNext = nullptr, .flags = 0, - .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, + .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_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, .pfnUserCallback = &debugCallback, @@ -849,11 +848,11 @@ void Graphics::pickPhysicalDevice() { vkGetPhysicalDeviceProperties2(physicalDevice, &props.get()); features.get().features = { - .geometryShader = false, + .geometryShader = true, .sampleRateShading = true, .fillModeNonSolid = true, - .wideLines = false, - .pipelineStatisticsQuery = false, + .wideLines = true, + .pipelineStatisticsQuery = true, .fragmentStoresAndAtomics = true, .shaderInt64 = true, .shaderInt16 = true, @@ -862,12 +861,14 @@ void Graphics::pickPhysicalDevice() { features.get().multiview = true; features.get().storageBuffer16BitAccess = true; features.get().shaderDrawParameters = true; + features.get().uniformAndStorageBuffer16BitAccess = true; features.get().descriptorIndexing = true; features.get().descriptorBindingPartiallyBound = true; features.get().bufferDeviceAddress = true; features.get().storageBuffer8BitAccess = true; features.get().shaderInt8 = true; + features.get().uniformAndStorageBuffer8BitAccess = true; rayTracingFeatures.get().accelerationStructure = true; @@ -915,7 +916,7 @@ void Graphics::pickPhysicalDevice() { shaderFloatControls = true; } } - rayTracingEnabled = rayTracingPipelineSupport && accelerationStructureSupport && hostOperationsSupport && deviceAddressSupport && + rayTracingEnabled = false &&rayTracingPipelineSupport && accelerationStructureSupport && hostOperationsSupport && deviceAddressSupport && descriptorIndexingSupport && spirv14Support && shaderFloatControls; } diff --git a/src/Engine/Graphics/slang-compile.cpp b/src/Engine/Graphics/slang-compile.cpp index 07ca6e6..48a9d18 100644 --- a/src/Engine/Graphics/slang-compile.cpp +++ b/src/Engine/Graphics/slang-compile.cpp @@ -48,21 +48,79 @@ std::filesystem::path findExistingDirectory(std::initializer_list candidates) { + for (const auto& candidate : candidates) { + if (containsDownstreamCompilerArtifacts(candidate)) { + return candidate; + } + } + + return findExistingDirectory(candidates); +} + void configureDownstreamCompilers(slang::IGlobalSession* session) { const auto executableDirectory = getExecutableDirectory(); const auto currentDirectory = std::filesystem::current_path(); - const auto glslangDirectory = findExistingDirectory({ + const auto glslangDirectory = findDownstreamCompilerDirectory({ + executableDirectory, executableDirectory / "Seele", executableDirectory / "vcpkg_installed" / "x64-linux" / "lib", + currentDirectory / "build", + currentDirectory / "build" / "Seele", currentDirectory / "Seele", currentDirectory / "vcpkg_installed" / "x64-linux" / "lib", }); if (!glslangDirectory.empty()) { const std::string path = glslangDirectory.string(); - session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_GLSLANG, path.c_str()); - session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_OPT, path.c_str()); - session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_SPIRV_DIS, path.c_str()); + if (hasArtifactWithPrefix(glslangDirectory, "slang-glslang") || hasArtifactWithPrefix(glslangDirectory, "libslang-glslang")) { + session->setDownstreamCompilerPath(SLANG_PASS_THROUGH_GLSLANG, 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. @@ -130,10 +188,9 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg sessionDesc.preprocessorMacros = macros.data(); slang::TargetDesc targetDesc = {}; targetDesc.format = target; - targetDesc.flags = SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY; sessionDesc.targetCount = 1; sessionDesc.targets = &targetDesc; - StaticArray searchPaths = {"shaders/", "shaders/lib/", "shaders/raytracing/", "shaders/terrain", "shaders/game", "shaders/generated/", "Seele/shaders/lib/"}; + StaticArray searchPaths = {"shaders/", "shaders/lib/", "shaders/raytracing/", "shaders/terrain", "shaders/game", "shaders/generated/", "shaders/fluid"}; sessionDesc.searchPaths = searchPaths.data(); sessionDesc.searchPathCount = searchPaths.size(); @@ -184,16 +241,6 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg 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, std::string> Seele::generateShader(const ShaderCreateInfo& createInfo) { diff --git a/src/Engine/Scene/CMakeLists.txt b/src/Engine/Scene/CMakeLists.txt index 583abbb..11bd4b5 100644 --- a/src/Engine/Scene/CMakeLists.txt +++ b/src/Engine/Scene/CMakeLists.txt @@ -1,6 +1,8 @@ target_sources(Engine PRIVATE EventManager.h + FluidScene.h + FluidScene.cpp LightEnvironment.h LightEnvironment.cpp Util.h @@ -11,6 +13,7 @@ target_sources(Engine PUBLIC FILE_SET HEADERS FILES EventManager.h + FluidScene.h LightEnvironment.h Util.h Scene.h) \ No newline at end of file diff --git a/src/Engine/Scene/FluidScene.cpp b/src/Engine/Scene/FluidScene.cpp new file mode 100644 index 0000000..2d9e0dd --- /dev/null +++ b/src/Engine/Scene/FluidScene.cpp @@ -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 initialDensity(bufferSize / sizeof(float)); + Array initialVelocityX(bufferSize / sizeof(float)); + Array initialVelocityY(bufferSize / sizeof(float)); + Array initialVelocityZ(bufferSize / sizeof(float)); + Array initialPhi(bufferSize / sizeof(float)); + + // Initialize level set to positive (outside) everywhere + float halfGridX = static_cast(grid.gridSize.x) * 0.5f; + float halfGridY = static_cast(grid.gridSize.y) * 0.5f; + float radius = static_cast(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(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(x) - cx; + float dy = static_cast(y) - cy; + float dz = static_cast(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; +} \ No newline at end of file diff --git a/src/Engine/Scene/FluidScene.h b/src/Engine/Scene/FluidScene.h new file mode 100644 index 0000000..e8eb5e0 --- /dev/null +++ b/src/Engine/Scene/FluidScene.h @@ -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& getFluidDataMap() const { return fluidDataMap; } + + private: + Gfx::PGraphics graphics; + Map fluidDataMap; +}; +DEFINE_REF(FluidScene) +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Scene/LightEnvironment.cpp b/src/Engine/Scene/LightEnvironment.cpp index 76d3ca0..223a213 100644 --- a/src/Engine/Scene/LightEnvironment.cpp +++ b/src/Engine/Scene/LightEnvironment.cpp @@ -1,7 +1,7 @@ #include "LightEnvironment.h" #include "Asset/AssetRegistry.h" -#include "Asset/EnvironmentMapAsset.h" #include "Graphics/Descriptor.h" +#include "Asset/EnvironmentMapAsset.h" #include "Graphics/Enums.h" #include "Graphics/Graphics.h" diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index 7f646f3..2ba2d53 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -1,22 +1,14 @@ #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/Mesh.h" -#include "Graphics/StaticMeshVertexData.h" using namespace Seele; 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() {} void Scene::bakeLighting() {} void Scene::update(float deltaTime) { physics.update(deltaTime); } + diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index e68b025..ae7ec9b 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -1,12 +1,10 @@ #pragma once #include "MinimalEngine.h" -#include "Component/Skybox.h" #include "Graphics/Graphics.h" #include "LightEnvironment.h" #include "Physics/PhysicsSystem.h" +#include "FluidScene.h" #include -#include - namespace Seele { DECLARE_REF(Material) @@ -33,12 +31,14 @@ class Scene { template auto constructCallback() { return registry.on_construct(); } template auto destroyCallback() { return registry.on_destroy(); } PLightEnvironment getLightEnvironment() { return lightEnv; } + PFluidScene getFluidScene() { return fluidScene; } Gfx::PGraphics getGraphics() const { return graphics; } entt::registry registry; private: Gfx::PGraphics graphics; OLightEnvironment lightEnv; + OFluidScene fluidScene; PhysicsSystem physics; Array lightMaps; }; diff --git a/src/Engine/System/CMakeLists.txt b/src/Engine/System/CMakeLists.txt index fe6432a..99bd329 100644 --- a/src/Engine/System/CMakeLists.txt +++ b/src/Engine/System/CMakeLists.txt @@ -5,6 +5,8 @@ target_sources(Engine ComponentSystem.h Executor.h Executor.cpp + FluidUpdater.h + FluidUpdater.cpp KeyboardInput.h KeyboardInput.cpp LightGather.h @@ -21,6 +23,7 @@ target_sources(Engine CameraUpdater.h ComponentSystem.h Executor.h + FluidUpdater.h KeyboardInput.h LightGather.h MeshUpdater.h diff --git a/src/Engine/System/FluidUpdater.cpp b/src/Engine/System/FluidUpdater.cpp new file mode 100644 index 0000000..01b982d --- /dev/null +++ b/src/Engine/System/FluidUpdater.cpp @@ -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); +} \ No newline at end of file diff --git a/src/Engine/System/FluidUpdater.h b/src/Engine/System/FluidUpdater.h new file mode 100644 index 0000000..bb5f0f4 --- /dev/null +++ b/src/Engine/System/FluidUpdater.h @@ -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 { + public: + FluidUpdater(PScene scene); + virtual ~FluidUpdater(); + + virtual void update(entt::entity id, Component::FluidGrid& grid, Component::Transform& transform); + + private: +}; +} // namespace System +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Window/GameView.cpp b/src/Engine/Window/GameView.cpp index 53b96b1..a8bca20 100644 --- a/src/Engine/Window/GameView.cpp +++ b/src/Engine/Window/GameView.cpp @@ -4,12 +4,16 @@ #include "Graphics/RenderPass/BasePass.h" #include "Graphics/RenderPass/CachedDepthPass.h" #include "Graphics/RenderPass/DepthCullingPass.h" +#include "Graphics/RenderPass/FluidRenderPass.h" #include "Graphics/RenderPass/LightCullingPass.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/VisibilityPass.h" -#include "Graphics/RenderPass/ShadowPass.h" #include "System/CameraUpdater.h" +#include "System/FluidUpdater.h" #include "System/LightGather.h" #include "System/MeshUpdater.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 ShadowPass(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.setViewport(viewport); renderGraph.createRenderPass(); if (graphics->supportRayTracing()) { 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.setViewport(viewport); rayTracingGraph.createRenderPass(); @@ -90,12 +100,15 @@ void GameView::reloadGame() { System::OKeyboardInput keyInput = new System::KeyboardInput(scene); keyboardSystem = keyInput; systemGraph->addSystem(std::move(keyInput)); + systemGraph->addSystem(new System::FluidUpdater(scene)); systemGraph->addSystem(new System::LightGather(scene)); systemGraph->addSystem(new System::MeshUpdater(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); }