Compare commits

...
37 Commits
Author SHA1 Message Date
Dynamitos bedeb8f059 idk 2026-04-21 22:00:00 +02:00
Dynamitos 424dea0012 So many changes again 2026-04-15 16:56:19 +02:00
Dynamitos 495e683522 Trying to fix fluid pass 2026-04-12 21:39:31 +02:00
Dynamitos ac317a3829 Trying to add fluid simulation 2026-04-12 20:49:02 +02:00
Dynamitos 056589a6f9 Changed key and mouse button callback signatures 2026-04-11 10:15:35 +02:00
Dynamitos b6a449d8e3 More windowing changes for renderdoc 2026-04-07 22:25:13 +02:00
Dynamitos 7af42b9bad I dont know anymore 2026-04-06 20:35:02 +02:00
Dynamitos ace1554020 Fixing glfw package breaking changes 2026-04-06 17:29:55 +02:00
Dynamitos 87390db80d Adding more Window validation 2026-04-06 14:28:58 +02:00
Dynamitos 7271fe8a0b new compute dispatch 2026-04-06 09:54:04 +02:00
Dynamitos 925537dcb3 Macos changes 2026-03-16 16:54:30 +01:00
Dynamitos 4fd44b075f reintroducing vulkan 2026-03-16 16:54:14 +01:00
Dynamitos e2296cada2 Metal changes 2026-03-16 16:53:30 +01:00
Dynamitos 54106e6fef removing vulkan references from mac builds 2026-03-16 16:52:43 +01:00
Dynamitos 9109baad18 shader adjustments 2026-03-15 22:37:08 +01:00
Dynamitos cd0f6d038f Reorganize includes 2026-03-14 13:53:04 +01:00
Dynamitos df5b2b6795 Minor changes 2026-03-13 22:30:46 +01:00
Dynamitos 661c91401f adding proper window close functionality 2026-03-09 22:28:21 +01:00
Dynamitos 61dcb0430a Fixed shadow pass and physics system a little bit 2026-02-25 07:13:54 +01:00
Dynamitos 2e63b3cb83 Shadow mapping works 99% 2026-02-24 22:52:21 +01:00
Dynamitos 2f146445a4 update vcpkg 2026-02-22 20:26:39 +01:00
Dynamitos 4a66b5d18d Compatibility changes with macos 2026-02-22 20:26:25 +01:00
Dynamitos 4eacda2ae0 Fixed array includes 2026-02-18 22:10:39 +01:00
Dynamitos c8ee843a09 Changes to shadowpass 2026-02-15 21:17:09 +01:00
Dynamitos 9f9663fb47 some things work, others dont 2025-09-27 22:29:04 +02:00
Dynamitos a2f1e0bd8c Reverse depth is now working in the shadow pass 2025-09-27 21:50:01 +02:00
Dynamitos ed69a21b80 Something about shadowpass 2025-09-21 22:09:24 +02:00
Dynamitos 209780cd54 Idk 2025-09-20 12:42:42 +02:00
Dynamitos 7d4cd26c31 Fixing perspective matrices 2025-09-07 20:13:26 +02:00
Dynamitos e97beda2bc Fixing command resource binding 2025-09-05 07:10:27 +02:00
Dynamitos 5be15b4929 Adding build cmake preset 2025-08-23 19:14:06 +02:00
Dynamitos ef9cb9c812 Broke everything for some reason 2025-08-23 18:09:01 +02:00
Dynamitos 757b75aaf3 Implementing graphics layer changes in metal 2025-08-14 18:28:33 +02:00
Dynamitos 7ab9e8a5e5 More shadowmappingchanges 2025-08-14 11:06:43 +02:00
Dynamitos 6537459b77 Changed descriptorset api 2025-08-10 19:16:55 +02:00
Dynamitos aa4b78586e Fixing pretty printers 2025-08-10 12:28:50 +02:00
Dynamitos 30d5b62447 Adding pretty printers 2025-08-08 22:29:54 +02:00
159 changed files with 5004 additions and 1296 deletions
+24 -17
View File
@@ -18,33 +18,35 @@
"name": "Editor (Mac)",
"type": "lldb",
"request": "launch",
"program": "${workspaceRoot}/build/Editor",
"program": "${workspaceRoot}/build/external/Seele/Editor",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceRoot}/build",
"environment": [
{
"name": "VK_LAYER_PATH",
"value": "/opt/homebrew/opt/vulkan-validationlayers/share/vulkan/explicit_layer.d"
}
],
"logging": {
"moduleLoad": false
},
"externalConsole": false,
"MIMode": "lldb",
"targetArchitecture": "arm64"
"cwd": "${workspaceRoot}/build/external/Seele",
"initCommands": [
"command script import ${workspaceFolder}/external/Seele/gdb/Seele_lldb.py"
]
},
{
"name": "Editor (Linux)",
"type": "cppdbg",
"type": "lldb",
"request": "launch",
"program": "${workspaceRoot}/build/Editor",
"args": [],
"environment": [
{
"name": "ASAN_OPTIONS",
"value": "alloc_dealloc_mismatch=0",
"value": "detect_leaks=0",
},
{
"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",
@@ -55,6 +57,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
}
],
},
+21 -39
View File
@@ -22,14 +22,6 @@ set(CMAKE_TOOLCHAIN_FILE ${EXTERNAL_ROOT}/vcpkg/scripts/buildsystems/vcpkg.cmake
set(CRCPP_ROOT ${EXTERNAL_ROOT}/CRCpp)
set(METAL_ROOT ${EXTERNAL_ROOT}/metal-cpp)
if(WIN32)
set(VCPKG_BASE_FOLDER ${CMAKE_BINARY_DIR}/vcpkg_installed/x64-windows/)
elseif(APPLE)
set(VCPKG_BASE_FOLDER ${CMAKE_BINARY_DIR}/vcpkg_installed/arm64-osx/)
else()
set(VCPKG_BASE_FOLDER ${CMAKE_BINARY_DIR}/vcpkg_installed/x64-linux/)
endif()
set(Boost_NO_WARN_NEW_VERSIONS 1)
project (Seele)
@@ -48,6 +40,7 @@ find_package(Ktx CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
find_package(lunasvg CONFIG REQUIRED)
find_package(slang CONFIG REQUIRED)
find_package(metis CONFIG REQUIRED)
find_package(meshoptimizer CONFIG REQUIRED)
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
@@ -61,10 +54,23 @@ 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_include_directories(Engine PRIVATE ${VCPKG_BASE_FOLDER}/include/)
target_link_libraries(Engine PUBLIC Vulkan::Vulkan)
target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator)
if(NOT APPLE)
# slang-glslang is a MODULE library (plugin) - copy it instead of linking
add_custom_command(TARGET Engine POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:slang::slang-glslang>
$<TARGET_FILE_DIR:Engine>
)
endif()
target_link_libraries(Engine PUBLIC EnTT::EnTT)
target_link_libraries(Engine PUBLIC glfw)
target_link_libraries(Engine PUBLIC glm::glm)
@@ -77,21 +83,13 @@ target_link_libraries(Engine PUBLIC nlohmann_json::nlohmann_json)
target_link_libraries(Engine PUBLIC crcpp)
target_link_libraries(Engine PUBLIC fmt::fmt)
target_link_libraries(Engine PUBLIC lunasvg::lunasvg)
target_link_libraries(Engine PUBLIC GPUOpen::VulkanMemoryAllocator)
target_link_libraries(Engine PUBLIC metis)
target_link_libraries(Engine PUBLIC meshoptimizer::meshoptimizer)
if(WIN32)
target_link_libraries(Engine PUBLIC ${VCPKG_BASE_FOLDER}/lib/slang.lib)
elseif(APPLE)
target_link_libraries(Engine PUBLIC ${VCPKG_BASE_FOLDER}/debug/lib/libslang.dylib)
else()
target_link_libraries(Engine PUBLIC ${VCPKG_BASE_FOLDER}/lib/libslang.so)
target_link_libraries(Engine PUBLIC ${VCPKG_BASE_FOLDER}/lib/libslang-glslang.so)
endif()
target_link_libraries(Engine PUBLIC slang::slang)
if(APPLE)
target_link_libraries(Engine PUBLIC metal)
SET(CMAKE_OSX_DEPLOYMENT_TARGET 15.0)
SET(CMAKE_OSX_DEPLOYMENT_TARGET 26.0)
endif()
if(UNIX)
target_link_libraries(Engine PUBLIC Threads::Threads)
@@ -133,33 +131,17 @@ if(APPLE)
target_compile_options(Engine PUBLIC -Wno-gnu-anonymous-struct -Wno-nested-anon-types)
target_compile_options(Editor PUBLIC -Wno-gnu-anonymous-struct -Wno-nested-anon-types)
endif()
target_compile_options(Engine PUBLIC "$<$<CONFIG:DEBUG>:-DENABLE_VALIDATION>")
target_compile_options(Engine PUBLIC "$<$<CONFIG:DEBUG>:-DSEELE_DEBUG>")
add_subdirectory(src/)
#add_subdirectory(tests/)
if(WIN32)
add_custom_target(dll_copy ALL
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:Engine> $<TARGET_FILE_DIR:Editor>
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${VCPKG_BASE_FOLDER}/bin/slang.dll $<TARGET_FILE_DIR:Editor>
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${VCPKG_BASE_FOLDER}/bin/slang-glslang.dll $<TARGET_FILE_DIR:Editor>
COMMAND_EXPAND_LISTS
DEPENDS Editor)
elseif(APPLE)
add_custom_target(dll_copy ALL
COMMAND ${CMAKE_COMMAND} -E true
COMMAND_EXPAND_LISTS
DEPENDS Editor)
else()
add_custom_target(dll_copy ALL
COMMAND ${CMAKE_COMMAND} -E true)
add_custom_command(TARGET Engine POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:Engine> $<TARGET_FILE_DIR:Editor>)
endif()
add_custom_target(SeeleEngine ALL
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res $<TARGET_FILE_DIR:Engine>
COMMAND_EXPAND_LISTS
DEPENDS Editor dll_copy)
add_custom_command(TARGET Engine POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res $<TARGET_FILE_DIR:Engine>)
install(
TARGETS
+98 -55
View File
@@ -1,58 +1,101 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 19,
"patch": 0
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 19,
"patch": 0
},
"configurePresets": [
{
"name": "release",
"displayName": "Release (no ASan)",
"description": "Release build without sanitizers",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
}
},
"configurePresets": [
{
"name": "release",
"displayName": "Release (no ASan)",
"description": "Release build without sanitizers",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
}
},
{
"name": "release-asan",
"displayName": "Release (ASan)",
"description": "Release build with Address Sanitizer",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_CXX_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
"CMAKE_C_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
"CMAKE_EXE_LINKER_FLAGS": "-fsanitize=address",
"CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address",
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
}
},
{
"name": "debug",
"displayName": "Debug (no ASan)",
"description": "Debug build without sanitizers",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
}
},
{
"name": "debug-asan",
"displayName": "Debug (ASan)",
"description": "Debug build with Address Sanitizer",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
"CMAKE_C_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
"CMAKE_EXE_LINKER_FLAGS": "-fsanitize=address",
"CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address",
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
}
}
]
{
"name": "release-asan",
"displayName": "Release (ASan)",
"description": "Release build with Address Sanitizer",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"CMAKE_CXX_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
"CMAKE_C_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
"CMAKE_EXE_LINKER_FLAGS": "-fsanitize=address",
"CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address",
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
}
},
{
"name": "debug",
"displayName": "Debug (no ASan)",
"description": "Debug build without sanitizers",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
}
},
{
"name": "debug-mac",
"displayName": "Debug Mac (no ASan)",
"description": "Debug Mac build without sanitizers",
"binaryDir": "${sourceDir}/build",
"generator": "Xcode",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
}
},
{
"name": "debug-asan",
"displayName": "Debug (ASan)",
"description": "Debug build with Address Sanitizer",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
"CMAKE_C_FLAGS": "-fsanitize=address -fno-omit-frame-pointer",
"CMAKE_EXE_LINKER_FLAGS": "-fsanitize=address",
"CMAKE_SHARED_LINKER_FLAGS": "-fsanitize=address",
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
}
}
],
"buildPresets": [
{
"name": "release",
"displayName": "Release (no ASan)",
"configurePreset": "release",
"jobs": 0
},
{
"name": "release-asan",
"displayName": "Release (ASan)",
"configurePreset": "release-asan",
"jobs": 0
},
{
"name": "debug",
"displayName": "Debug (no ASan)",
"configurePreset": "debug",
"jobs": 0
},
{
"name": "debug-mac",
"displayName": "Debug Mac (no ASan)",
"configurePreset": "debug-mac",
"jobs": 0
},
{
"name": "debug-asan",
"displayName": "Debug (ASan)",
"configurePreset": "debug-asan",
"jobs": 0
}
]
}
-2
View File
@@ -1,2 +0,0 @@
(?<enum>[A-Z_]*) = [0-9]*,
case SE_${enum}:\nreturn VK_${enum};
-4
View File
@@ -1,4 +0,0 @@
// Hint files help the Visual Studio IDE interpret Visual C++ identifiers
// such as names of functions and macros.
// For more information see https://go.microsoft.com/fwlink/?linkid=865984
#define DECLARE_REF(x)
+1 -1
+141
View File
@@ -0,0 +1,141 @@
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
def to_string(self):
return f"Array(size={int(self.val['arraySize'])})"
def children(self):
data = self.val['_data']
size = int(self.val['arraySize'])
allocated = int(self.val['allocated'])
yield f"[size]", size
yield f"[allocated]", allocated
for i in range(size):
elem_val = (data + i).dereference()
yield f"[{i}]", elem_val
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
t = val.type.strip_typedefs()
self.length = int(t.template_argument(0))
self.value_type = t.template_argument(1)
def to_string(self):
comps = [float(self.val['x']), float(self.val['y'])]
if self.length >= 3:
comps.append(float(self.val['z']))
if self.length == 4:
comps.append(float(self.val['w']))
return "(" + ", ".join(map(str, comps)) + ")"
def display_hint(self):
return "string"
def _children(self):
comps = {'x': self.val['x'], 'y': self.val['y']}
if self.length >= 3:
comps['z'] = self.val['z']
if self.length == 4:
comps['w'] = self.val['w']
for key, value in comps.items():
yield key, value
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
gdb.printing.register_pretty_printer(gdb.current_objfile(), build_pretty_printer())
+99
View File
@@ -0,0 +1,99 @@
import lldb
def Array_SummaryProvider(valobj, internal_dict):
size = valobj.GetChildMemberWithName('arraySize').GetValueAsUnsigned(0)
return f"Array(size={size})"
class ArraySyntheticProvider:
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
offset = index * self.data.GetType().GetPointeeType().GetByteSize()
return self.data.CreateChildAtOffset(f'[{index}]', offset, self.data.GetType().GetPointeeType())
def update(self):
self.data = self.valobj.GetChildMemberWithName('_data')
self.size = self.valobj.GetChildMemberWithName('arraySize').GetValueAsUnsigned(0)
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()
# Extract components
x = valobj.GetChildMemberWithName('x').GetValue()
y = valobj.GetChildMemberWithName('y').GetValue()
# Check if z and w exist
z_child = valobj.GetChildMemberWithName('z')
w_child = valobj.GetChildMemberWithName('w')
comps = [x, y]
if z_child.IsValid():
comps.append(z_child.GetValue())
if w_child.IsValid():
comps.append(w_child.GetValue())
return "(" + ", ".join(comps) + ")"
def __lldb_init_module(debugger, internal_dict):
# Register Array formatter
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]?<.*>$"')
print("Seele LLDB formatters loaded")
+23 -17
View File
@@ -5,16 +5,18 @@ import MATERIAL_FILE_NAME;
const static uint64_t NUM_CASCADES = 4;
/*struct ShadowMappingData
struct ShadowMappingData
{
Texture2DArray shadowMaps[NUM_CASCADES];
ConstantBuffer<float4x4> lightSpaceMatrices[NUM_CASCADES];
StructuredBuffer<float4x4> lightSpaceMatrices[NUM_CASCADES];
ConstantBuffer<float[NUM_CASCADES]> cascadeSplits;
SamplerState shadowSampler;
ConstantBuffer<float4> cascadeSplits;
};
ParameterBlock<ShadowMappingData> pShadowMapping;
*/
struct LightCullingData
{
RWStructuredBuffer<uint> lightIndexList;
@@ -42,16 +44,20 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target
float3 result = float3(0, 0, 0);
for(int i = 0; i < pLightEnv.numDirectionalLights; ++i)
{
/*uint cascadeIndex = 0;
uint cascadeIndex = 0;
for (uint c = 0; c < NUM_CASCADES - 1; ++c) {
if (params.position_VS.z < pShadowMapping.cascadeSplits[c]) {
if (-params.position_VS.z > pShadowMapping.cascadeSplits[c]) {
cascadeIndex = c + 1;
}
}
float4 lightSpacePos = mul(biasMat, mul(pShadowMapping.lightSpaceMatrices[i], float4(params.position_WS, 1)));
float4 shadowCoord = lightSpacePos / lightSpacePos.w;
int2 texDim;
pLightEnv.shadowMap.GetDimensions(texDim.x, texDim.y);
float4 lightSpacePos = mul(pShadowMapping.lightSpaceMatrices[cascadeIndex][i], float4(params.position_WS, 1));
// Negate Y to compensate for orthographic projection's Y negation + viewport Y-flip double-inversion
lightSpacePos = float4(lightSpacePos.x * 0.5 + 0.5, -lightSpacePos.y * 0.5 + 0.5, lightSpacePos.zw);
float4 shadowCoord = lightSpacePos;
// Convert NDC z to viewport depth space (inverse depth: near=1, far=0)
float currentDepth = 1.0 - shadowCoord.z;
int3 texDim;
pShadowMapping.shadowMaps[cascadeIndex].GetDimensions(texDim.x, texDim.y, texDim.z);
float scale = 1.5f;
float dx = scale * 1.0 / float(texDim.x);
float dy = scale * 1.0 / float(texDim.y);
@@ -62,10 +68,10 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target
for (int x = -range; x <= range; ++x) {
for (int y = -range; y <= range; ++y) {
float shadow = 1.0f;
if (shadowCoord.z > 0.0 && shadowCoord.z < 1.0)
if (currentDepth > 0.0 && currentDepth < 1.0)
{
float dist = pLightEnv.shadowMap.Sample(pLightEnv.shadowSampler, shadowCoord.xy + float2(dx * x, dy * y)).r;
if (shadowCoord.w > 0 && dist > shadowCoord.z)
float dist = pShadowMapping.shadowMaps[cascadeIndex].Sample(pShadowMapping.shadowSampler, float3(shadowCoord.xy + float2(dx * x, dy * y), i)).r;
if (shadowCoord.w > 0 && currentDepth < dist)
{
shadow = 0;
}
@@ -73,14 +79,14 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target
shadowFactor += shadow;
count++;
}
}*/
}
result += /*(shadowFactor / count) **/ pLightEnv.directionalLights[i].illuminate(lightingParams, brdf);
result = (shadowFactor / count) * pLightEnv.directionalLights[i].illuminate(lightingParams, brdf);
}
for (uint i = 0; i < pLightEnv.numPointLights; ++i)
{
//uint lightIndex = pLightCullingData.lightIndexList[startOffset + i];
result += pLightEnv.pointLights[i].illuminate(lightingParams, brdf);
uint lightIndex = pLightCullingData.lightIndexList[startOffset + i];
result += pLightEnv.pointLights[lightIndex].illuminate(lightingParams, brdf);
}
result += brdf.evaluateAmbient(lightingParams.viewDir_WS);
return float4(result, brdf.getAlpha());
+1
View File
@@ -1,4 +1,5 @@
import Common;
import Frustum;
import DispatchParams;
struct ComputeShaderInput
+1
View File
@@ -2,6 +2,7 @@ import Common;
import Scene;
import Bounding;
import DepthCommon;
import Frustum;
groupshared MeshPayload p;
groupshared uint head;
+1 -1
View File
@@ -253,7 +253,7 @@ float2 integrateBRDF(float nDotV, float roughness) {
}
[shader("pixel")]
float2 precomputeBRDF(float2 texCoords) : SV_Target
float2 precomputeBRDF(float2 texCoords : UV) : SV_Target
{
return integrateBRDF(texCoords.x, texCoords.y);
}
+3 -1
View File
@@ -9,6 +9,8 @@ QuadOutput quadMain(uint vertexIndex : SV_VertexID)
{
QuadOutput result;
result.uv = float2(vertexIndex & 2, (vertexIndex << 1) & 2);
result.position = float4(result.uv * 2.0f + -1.0f, 0.0f, 1.0f);
float2 ndc = result.uv * 2.0f + -1.0f;
ndc.y = -ndc.y; // Flip Y for flipped viewport
result.position = float4(ndc, 0.0f, 1.0f);
return result;
}
+1
View File
@@ -1,6 +1,7 @@
import Common;
import DispatchParams;
import LightEnv;
import Frustum;
struct ComputeShaderInput
{
+38
View File
@@ -0,0 +1,38 @@
import Common;
import MaterialParameter;
import VertexData;
import StaticMeshVertexData;
import Scene;
[numthreads(1, 1, 1)]
[shader("amplification")]
void taskMain(uint threadID: SV_GroupThreadID, uint groupID: SV_GroupID) { DispatchMesh(1, 1, 1, groupID); }
[numthreads(1, 1, 1)]
[shader("mesh")]
void meshMain(in payload uint taskGroupId, out vertices FragmentParameter vertices[MAX_VERTICES],
out indices uint3 indices[MAX_PRIMITIVES]) {
InstanceData inst = pScene.instances[pOffsets.instanceOffset + taskGroupId];
MeshData mesh = pScene.meshData[pOffsets.instanceOffset + taskGroupId];
MeshletDescription m = pScene.meshletInfos[mesh.meshletRange.offset];
SetMeshOutputCounts(m.vertexIndices.size, m.primitiveIndices.size);
for (uint p = 0; p < m.primitiveIndices.size; p++) {
uint baseIndex = m.primitiveIndices.offset + (p * 3);
uint local_idx0 = pScene.primitiveIndices[baseIndex + 0];
uint local_idx1 = pScene.primitiveIndices[baseIndex + 1];
uint local_idx2 = pScene.primitiveIndices[baseIndex + 2];
indices[p] = uint3(local_idx0, local_idx1, local_idx2);
}
for (uint v = 0; v < m.vertexIndices.size; v++) {
uint vertexIndex = pScene.vertexIndices[m.vertexIndices.offset + v];
VertexAttributes attr = pVertexData.getAttributes(m.indicesOffset + vertexIndex);
vertices[v] = attr.getParameter(inst.transformMatrix, inst.inverseTransformMatrix);
}
}
[shader("pixel")]
void pixelMain(in FragmentParameter input, out float4 outColor : SV_Target) {
outColor = float4(1.0, 0.0, 0.0, 1.0);
}
+1
View File
@@ -78,6 +78,7 @@ VertexShaderOutput vertexMain(
float4 worldPos = float4(mul(cameraRotation, vertices[vertexIndex]), 1.0f);
//clip(dot(worldPos, clipPlane));
output.clipPos = mul(pViewParams.projectionMatrix, worldPos);
output.clipPos.z = output.clipPos.w - 0.0001f; // Push to far plane
output.texCoords = normalize(vertices[vertexIndex]);
return output;
}
+35
View File
@@ -0,0 +1,35 @@
import FluidGridData;
struct Params
{
// read-write: phi to add source to
FluidGridData<float> phi;
FluidGridData<float> density;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void addSource(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> phi = params.phi;
FluidGridData<float> density = params.density;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridParams.gridSize.x - 1 || y >= gridParams.gridSize.y - 1 || z >= gridParams.gridSize.z - 1) return;
// Add a spherical source and union it into the existing level set.
float3 center = float3(gridParams.gridSize) * 0.5f;
float radius = min(gridParams.gridSize.x, min(gridParams.gridSize.y, gridParams.gridSize.z)) * 0.25f;
float3 pos = float3(x, y, z);
float dist = length(pos - center);
float sourcePhi = dist - radius;
phi[x, y, z] = min(phi[x, y, z], sourcePhi);
if (sourcePhi < 0.0f)
{
density[x, y, z] += 0.5f;
density[x, y, z] = min(density[x, y, z], 1.0f);
}
}
+55
View File
@@ -0,0 +1,55 @@
import FluidGridData;
struct Params
{
// read-write
FluidGridData<float> density;
// read-only
FluidGridData<float> density0;
// read-only
FluidGridData<float> velocityX;
// read-only
FluidGridData<float> velocityY;
// read-only
FluidGridData<float> velocityZ;
float dt;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void advect(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> density = params.density;
FluidGridData<float> density0 = params.density0;
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
float dt = params.dt;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridParams.gridSize.x - 1 || y >= gridParams.gridSize.y - 1 || z >= gridParams.gridSize.z - 1) return;
float dt0x = dt * (gridParams.gridSize.x - 2);
float dt0y = dt * (gridParams.gridSize.y - 2);
float dt0z = dt * (gridParams.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, gridParams.gridSize.x - 1.5f);
pos.y = clamp(pos.y, 0.5f, gridParams.gridSize.y - 1.5f);
pos.z = clamp(pos.z, 0.5f, gridParams.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]));
}
+31
View File
@@ -0,0 +1,31 @@
import FluidGridData;
struct Params
{
FluidGridData<float> velocityX;
FluidGridData<float> velocityY;
FluidGridData<float> velocityZ;
float3 force;
float dt;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void applyForces(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
float3 force = params.force;
float dt = params.dt;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridParams.gridSize.x - 1 || y >= gridParams.gridSize.y - 1 || z >= gridParams.gridSize.z - 1) return;
velocityX[x, y, z] += force.x * dt;
velocityY[x, y, z] += force.y * dt;
velocityZ[x, y, z] += force.z * dt;
}
+34
View File
@@ -0,0 +1,34 @@
import FluidGridData;
struct Params {
// read-only
FluidGridData<float> velocityX;
// read-only
FluidGridData<float> velocityY;
// read-only
FluidGridData<float> velocityZ;
// read-write
FluidGridData<float> divergence;
// read-write
FluidGridData<float> pressure;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void computeDivergence(uint3 dispatchThreadID: SV_DispatchThreadID) {
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
FluidGridData<float> divergence = params.divergence;
FluidGridData<float> pressure = params.pressure;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if (x >= gridParams.gridSize.x - 1 || y >= gridParams.gridSize.y - 1 || z >= gridParams.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]);
pressure[x, y, z] = 0;
}
+47
View File
@@ -0,0 +1,47 @@
import FluidGridData;
struct Parameter
{
float iso;
FluidGridData<float> density;
RWStructuredBuffer<float3> vertices;
RWStructuredBuffer<uint> indices;
RWStructuredBuffer<uint> surfaceCount;
RWStructuredBuffer<uint> vertexCount;
};
ParameterBlock<Parameter> params;
float getDensity(uint x, uint y, uint z)
{
return params.density[x + gridParams.gridSize.x * y + gridParams.gridSize.x * gridParams.gridSize.y * z];
}
[shader("compute")]
[numthreads(32, 8, 1)]
void main(uint3 dispatchThreadID : SV_DispatchThreadID)
{
uint x = dispatchThreadID.x+1;
uint y = dispatchThreadID.y+1;
uint z = dispatchThreadID.z+1;
FluidGridData<float> density = params.density;
if(x >= gridParams.gridSize.x-3 || y >= gridParams.gridSize.y-3 || z >= gridParams.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;
}
+19
View File
@@ -0,0 +1,19 @@
struct GridParams
{
uint3 gridSize;
};
ParameterBlock<GridParams> gridParams;
struct FluidGridData<T>
{
RWStructuredBuffer<T> dataGrid;
__subscript(uint3 index) -> T
{
get { return dataGrid[index.x + index.y * gridParams.gridSize.x + index.z * gridParams.gridSize.x * gridParams.gridSize.y]; }
set { dataGrid[index.x + index.y * gridParams.gridSize.x + index.z * gridParams.gridSize.x * gridParams.gridSize.y] = newValue; }
}
__subscript(uint x, uint y, uint z) -> T
{
get { return dataGrid[x + y * gridParams.gridSize.x + z * gridParams.gridSize.x * gridParams.gridSize.y]; }
set { dataGrid[x + y * gridParams.gridSize.x + z * gridParams.gridSize.x * gridParams.gridSize.y] = newValue; }
}
};
+32
View File
@@ -0,0 +1,32 @@
import FluidGridData;
struct Params
{
// read-write
FluidGridData<float> next;
// read-only
FluidGridData<float> current;
// read-only
FluidGridData<float> grid0;
float a;
float c;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void linearSolve(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> next = params.next;
FluidGridData<float> current = params.current;
FluidGridData<float> grid0 = params.grid0;
float a = params.a;
float cRecip = 1.0f / params.c;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridParams.gridSize.x - 1 || y >= gridParams.gridSize.y - 1 || z >= gridParams.gridSize.z - 1) return;
next[x, y, z] = (grid0[x, y, z] + a * (current[x + 1, y, z] + current[x - 1, y, z] + current[x, y + 1, z] + current[x, y - 1, z] + current[x, y, z + 1] + current[x, y, z - 1])) * cRecip;
}
+205
View File
@@ -0,0 +1,205 @@
import FluidGridData;
import MarchingCubesData;
struct Params
{
RWStructuredBuffer<float> vertexBuffer;
RWStructuredBuffer<float> normalBuffer;
RWStructuredBuffer<uint> indexBuffer;
RWStructuredBuffer<uint> indicesCount;
FluidGridData<float> levelSet;
};
ParameterBlock<Params> params;
const static float isoLevel = 0.0f;
const static float3 cellSize = 1.0f / gridParams.gridSize;
float3 vertexInterp(float isoLevel, float3 p1, float3 p2, float valp1, float valp2)
{
if (abs(isoLevel - valp1) < 0.00001)
return p1;
if (abs(isoLevel - valp2) < 0.00001)
return p2;
if (abs(valp1 - valp2) < 0.00001)
return p1;
float mu = (isoLevel - valp1) / (valp2 - valp1);
return p1 + mu * (p2 - p1);
}
float3 gridPos(uint x, uint y, uint z)
{
return float3(x, y, z) * cellSize;
}
// TODO: parameterize
const static uint32_t LOCAL_THREADGROUP_SIZE = 16 * 8 * 1; // Must match numthreads
const static uint32_t MAX_TRIS_PER_THREAD = 5; // Max triangles per cube configuration
const static uint32_t MAX_VERTS_PER_GROUP = LOCAL_THREADGROUP_SIZE * MAX_TRIS_PER_THREAD * 3;
groupshared float3 localVertices[MAX_VERTS_PER_GROUP];
groupshared float3 localNormals[MAX_VERTS_PER_GROUP];
groupshared uint localTriCounts[LOCAL_THREADGROUP_SIZE]; // per-thread triangle counts
groupshared uint localOffsets[LOCAL_THREADGROUP_SIZE]; // per-thread exclusive offsets (in vertices)
groupshared uint localBaseOffset; // global base offset for this workgroup
// Hillis-Steele inclusive scan on localTriCounts, result in localOffsets
// Then convert to exclusive scan and allocate global space
void prefixSumAndAllocate(uint groupIndex)
{
localOffsets[groupIndex] = localTriCounts[groupIndex];
GroupMemoryBarrierWithGroupSync();
for (uint offset = 1; offset < LOCAL_THREADGROUP_SIZE; offset *= 2)
{
uint temp = 0;
if (groupIndex >= offset)
temp = localOffsets[groupIndex - offset];
GroupMemoryBarrierWithGroupSync();
localOffsets[groupIndex] += temp;
GroupMemoryBarrierWithGroupSync();
}
// localOffsets is now an inclusive prefix sum
// Last thread has the total — allocate global space
if (groupIndex == LOCAL_THREADGROUP_SIZE - 1)
{
uint totalVerts = localOffsets[groupIndex] * 3;
InterlockedAdd(params.indicesCount[0], totalVerts, localBaseOffset);
}
GroupMemoryBarrierWithGroupSync();
// Convert inclusive to exclusive: shift right, first element = 0
uint inclusive = localOffsets[groupIndex];
GroupMemoryBarrierWithGroupSync();
localOffsets[groupIndex] = (groupIndex == 0) ? 0 : localOffsets[groupIndex - 1];
GroupMemoryBarrierWithGroupSync();
}
[shader("compute")]
[numthreads(16, 8, 1)]
void marchingCubes(uint3 dispatchThreadID : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex)
{
uint x = dispatchThreadID.x + 1;
uint y = dispatchThreadID.y + 1;
uint z = dispatchThreadID.z + 1;
FluidGridData<float> levelSet = params.levelSet;
// Don't early-return — all threads must participate in barriers.
// Use a flag to skip work for out-of-bounds threads.
bool valid = (x < gridParams.gridSize.x - 2 && y < gridParams.gridSize.y - 2 && z < gridParams.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(v2 - v0, v1 - v0));
localVertices[localOff] = v0;
localVertices[localOff + 1] = v1;
localVertices[localOff + 2] = v2;
localNormals[localOff] = n;
localNormals[localOff + 1] = n;
localNormals[localOff + 2] = n;
localOff += 3;
}
}
GroupMemoryBarrierWithGroupSync();
// Copy from shared memory to global buffers
// Each thread copies a chunk of the workgroup's output
uint totalGroupVerts = localTriCounts[LOCAL_THREADGROUP_SIZE - 1] > 0
? (localOffsets[LOCAL_THREADGROUP_SIZE - 1] + localTriCounts[LOCAL_THREADGROUP_SIZE - 1]) * 3
: localOffsets[LOCAL_THREADGROUP_SIZE - 1] * 3;
for (uint i = groupIndex; i < totalGroupVerts; i += LOCAL_THREADGROUP_SIZE)
{
uint globalIdx = localBaseOffset + i;
float3 v = localVertices[i];
float3 n = localNormals[i];
params.vertexBuffer[globalIdx * 3 + 0] = v.x;
params.vertexBuffer[globalIdx * 3 + 1] = v.y;
params.vertexBuffer[globalIdx * 3 + 2] = v.z;
params.normalBuffer[globalIdx * 3 + 0] = n.x;
params.normalBuffer[globalIdx * 3 + 1] = n.y;
params.normalBuffer[globalIdx * 3 + 2] = n.z;
params.indexBuffer[globalIdx] = globalIdx;
}
}
+299
View File
@@ -0,0 +1,299 @@
// Marching Cubes edge table: for each cube configuration (256), a 12-bit mask
// indicating which edges are intersected by the isosurface.
// clang-format off
static const uint16_t edgeTable[256] = {
0x000, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
0x190, 0x099, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
0x230, 0x339, 0x033, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
0x3a0, 0x2a9, 0x1a3, 0x0aa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
0x460, 0x569, 0x663, 0x76a, 0x066, 0x16f, 0x265, 0x36c,
0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0x0ff, 0x3f5, 0x2fc,
0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x055, 0x15c,
0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0x0cc,
0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
0x0cc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
0x15c, 0x055, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
0x2fc, 0x3f5, 0x0ff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
0x36c, 0x265, 0x16f, 0x066, 0x76a, 0x663, 0x569, 0x460,
0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
0x4ac, 0x5a5, 0x6af, 0x7a6, 0x0aa, 0x1a3, 0x2a9, 0x3a0,
0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x033, 0x339, 0x230,
0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x099, 0x190,
0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x000,
};
// Marching Cubes triangle table: for each cube configuration, up to 5
// triangles specified as sequences of edge indices, terminated by -1.
static const int8_t triTable[256][16] = {
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,8,3,9,8,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,3,1,2,10,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,2,10,0,2,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,8,3,2,10,8,10,9,8,-1,-1,-1,-1,-1,-1,-1},
{3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,11,2,8,11,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,9,0,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,11,2,1,9,11,9,8,11,-1,-1,-1,-1,-1,-1,-1},
{3,10,1,11,10,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,10,1,0,8,10,8,11,10,-1,-1,-1,-1,-1,-1,-1},
{3,9,0,3,11,9,11,10,9,-1,-1,-1,-1,-1,-1,-1},
{9,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,3,0,7,3,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,1,9,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,1,9,4,7,1,7,3,1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,8,4,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,4,7,3,0,4,1,2,10,-1,-1,-1,-1,-1,-1,-1},
{9,2,10,9,0,2,8,4,7,-1,-1,-1,-1,-1,-1,-1},
{2,10,9,2,9,7,2,7,3,7,9,4,-1,-1,-1,-1},
{8,4,7,3,11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{11,4,7,11,2,4,2,0,4,-1,-1,-1,-1,-1,-1,-1},
{9,0,1,8,4,7,2,3,11,-1,-1,-1,-1,-1,-1,-1},
{4,7,11,9,4,11,9,11,2,9,2,1,-1,-1,-1,-1},
{3,10,1,3,11,10,7,8,4,-1,-1,-1,-1,-1,-1,-1},
{1,11,10,1,4,11,1,0,4,7,11,4,-1,-1,-1,-1},
{4,7,8,9,0,11,9,11,10,11,0,3,-1,-1,-1,-1},
{4,7,11,4,11,9,9,11,10,-1,-1,-1,-1,-1,-1,-1},
{9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,5,4,0,8,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,5,4,1,5,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{8,5,4,8,3,5,3,1,5,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,9,5,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,0,8,1,2,10,4,9,5,-1,-1,-1,-1,-1,-1,-1},
{5,2,10,5,4,2,4,0,2,-1,-1,-1,-1,-1,-1,-1},
{2,10,5,3,2,5,3,5,4,3,4,8,-1,-1,-1,-1},
{9,5,4,2,3,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,11,2,0,8,11,4,9,5,-1,-1,-1,-1,-1,-1,-1},
{0,5,4,0,1,5,2,3,11,-1,-1,-1,-1,-1,-1,-1},
{2,1,5,2,5,8,2,8,11,4,8,5,-1,-1,-1,-1},
{10,3,11,10,1,3,9,5,4,-1,-1,-1,-1,-1,-1,-1},
{4,9,5,0,8,1,8,10,1,8,11,10,-1,-1,-1,-1},
{5,4,0,5,0,11,5,11,10,11,0,3,-1,-1,-1,-1},
{5,4,8,5,8,10,10,8,11,-1,-1,-1,-1,-1,-1,-1},
{9,7,8,5,7,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,3,0,9,5,3,5,7,3,-1,-1,-1,-1,-1,-1,-1},
{0,7,8,0,1,7,1,5,7,-1,-1,-1,-1,-1,-1,-1},
{1,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,7,8,9,5,7,10,1,2,-1,-1,-1,-1,-1,-1,-1},
{10,1,2,9,5,0,5,3,0,5,7,3,-1,-1,-1,-1},
{8,0,2,8,2,5,8,5,7,10,5,2,-1,-1,-1,-1},
{2,10,5,2,5,3,3,5,7,-1,-1,-1,-1,-1,-1,-1},
{7,9,5,7,8,9,3,11,2,-1,-1,-1,-1,-1,-1,-1},
{9,5,7,9,7,2,9,2,0,2,7,11,-1,-1,-1,-1},
{2,3,11,0,1,8,1,7,8,1,5,7,-1,-1,-1,-1},
{11,2,1,11,1,7,7,1,5,-1,-1,-1,-1,-1,-1,-1},
{9,5,8,8,5,7,10,1,3,10,3,11,-1,-1,-1,-1},
{5,7,0,5,0,9,7,11,0,1,0,10,11,10,0,-1},
{11,10,0,11,0,3,10,5,0,8,0,7,5,7,0,-1},
{11,10,5,7,11,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,3,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,0,1,5,10,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,8,3,1,9,8,5,10,6,-1,-1,-1,-1,-1,-1},
{1,6,5,2,6,1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,6,5,1,2,6,3,0,8,-1,-1,-1,-1,-1,-1},
{9,6,5,9,0,6,0,2,6,-1,-1,-1,-1,-1,-1},
{5,9,8,5,8,2,5,2,6,3,2,8,-1,-1,-1,-1},
{2,3,11,10,6,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{11,0,8,11,2,0,10,6,5,-1,-1,-1,-1,-1,-1},
{0,1,9,2,3,11,5,10,6,-1,-1,-1,-1,-1,-1},
{5,10,6,1,9,2,9,11,2,9,8,11,-1,-1,-1,-1},
{6,3,11,6,5,3,5,1,3,-1,-1,-1,-1,-1,-1,-1},
{0,8,11,0,11,5,0,5,1,5,11,6,-1,-1,-1,-1},
{3,11,6,0,3,6,0,6,5,0,5,9,-1,-1,-1,-1},
{6,5,9,6,9,11,11,9,8,-1,-1,-1,-1,-1,-1,-1},
{5,10,6,4,7,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,3,0,4,7,3,6,5,10,-1,-1,-1,-1,-1,-1,-1},
{1,9,0,5,10,6,8,4,7,-1,-1,-1,-1,-1,-1,-1},
{10,6,5,1,9,7,1,7,3,7,9,4,-1,-1,-1,-1},
{6,1,2,6,5,1,4,7,8,-1,-1,-1,-1,-1,-1,-1},
{1,2,5,5,2,6,3,0,4,3,4,7,-1,-1,-1,-1},
{8,4,7,9,0,5,0,6,5,0,2,6,-1,-1,-1,-1},
{7,3,9,7,9,4,3,2,9,5,9,6,2,6,9,-1},
{3,11,2,7,8,4,10,6,5,-1,-1,-1,-1,-1,-1,-1},
{5,10,6,4,7,2,4,2,0,2,7,11,-1,-1,-1,-1},
{0,1,9,4,7,8,2,3,11,5,10,6,-1,-1,-1,-1},
{9,2,1,9,11,2,9,4,11,7,11,4,5,10,6,-1},
{8,4,7,3,11,5,3,5,1,5,11,6,-1,-1,-1,-1},
{5,1,11,5,11,6,1,0,11,7,11,4,0,4,11,-1},
{0,5,9,0,6,5,0,3,6,11,6,3,8,4,7,-1},
{6,5,9,6,9,11,4,7,9,7,11,9,-1,-1,-1,-1},
{10,4,9,6,4,10,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,10,6,4,9,10,0,8,3,-1,-1,-1,-1,-1,-1},
{10,0,1,10,6,0,6,4,0,-1,-1,-1,-1,-1,-1},
{8,3,1,8,1,6,8,6,4,6,1,10,-1,-1,-1,-1},
{1,4,9,1,2,4,2,6,4,-1,-1,-1,-1,-1,-1,-1},
{3,0,8,1,2,9,2,4,9,2,6,4,-1,-1,-1,-1},
{0,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{8,3,2,8,2,4,4,2,6,-1,-1,-1,-1,-1,-1,-1},
{10,4,9,10,6,4,11,2,3,-1,-1,-1,-1,-1,-1},
{0,8,2,2,8,11,4,9,10,4,10,6,-1,-1,-1,-1},
{3,11,2,0,1,6,0,6,4,6,1,10,-1,-1,-1,-1},
{6,4,1,6,1,10,4,8,1,2,1,11,8,11,1,-1},
{9,6,4,9,3,6,9,1,3,11,6,3,-1,-1,-1,-1},
{8,11,1,8,1,0,11,6,1,9,1,4,6,4,1,-1},
{3,11,6,3,6,0,0,6,4,-1,-1,-1,-1,-1,-1,-1},
{6,4,8,11,6,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{7,10,6,7,8,10,8,9,10,-1,-1,-1,-1,-1,-1,-1},
{0,7,3,0,10,7,0,9,10,6,7,10,-1,-1,-1,-1},
{10,6,7,1,10,7,1,7,8,1,8,0,-1,-1,-1,-1},
{10,6,7,10,7,1,1,7,3,-1,-1,-1,-1,-1,-1,-1},
{1,2,6,1,6,8,1,8,9,8,6,7,-1,-1,-1,-1},
{2,6,9,2,9,1,6,7,9,0,9,3,7,3,9,-1},
{7,8,0,7,0,6,6,0,2,-1,-1,-1,-1,-1,-1,-1},
{7,3,2,6,7,2,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,3,11,10,6,8,10,8,9,8,6,7,-1,-1,-1,-1},
{2,0,7,2,7,11,0,9,7,6,7,10,9,10,7,-1},
{1,8,0,1,7,8,1,10,7,6,7,10,2,3,11,-1},
{11,2,1,11,1,7,10,6,1,6,7,1,-1,-1,-1,-1},
{8,9,6,8,6,7,9,1,6,11,6,3,1,3,6,-1},
{0,9,1,11,6,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{7,8,0,7,0,6,3,11,0,11,6,0,-1,-1,-1,-1},
{7,11,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,0,8,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,1,9,11,7,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{8,1,9,8,3,1,11,7,6,-1,-1,-1,-1,-1,-1},
{10,1,2,6,11,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,3,0,8,6,11,7,-1,-1,-1,-1,-1,-1},
{2,9,0,2,10,9,6,11,7,-1,-1,-1,-1,-1,-1},
{6,11,7,2,10,3,10,8,3,10,9,8,-1,-1,-1,-1},
{7,2,3,6,2,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{7,0,8,7,6,0,6,2,0,-1,-1,-1,-1,-1,-1,-1},
{2,7,6,2,3,7,0,1,9,-1,-1,-1,-1,-1,-1,-1},
{1,6,2,1,8,6,1,9,8,8,7,6,-1,-1,-1,-1},
{10,7,6,10,1,7,1,3,7,-1,-1,-1,-1,-1,-1,-1},
{10,7,6,1,7,10,1,8,7,1,0,8,-1,-1,-1,-1},
{0,3,7,0,7,10,0,10,9,6,10,7,-1,-1,-1,-1},
{7,6,10,7,10,8,8,10,9,-1,-1,-1,-1,-1,-1,-1},
{6,8,4,11,8,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,6,11,3,0,6,0,4,6,-1,-1,-1,-1,-1,-1,-1},
{8,6,11,8,4,6,9,0,1,-1,-1,-1,-1,-1,-1,-1},
{9,4,6,9,6,3,9,3,1,11,3,6,-1,-1,-1,-1},
{6,8,4,6,11,8,2,10,1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,3,0,11,0,6,11,0,4,6,-1,-1,-1,-1},
{4,11,8,4,6,11,0,2,9,2,10,9,-1,-1,-1,-1},
{10,9,3,10,3,2,9,4,3,11,3,6,4,6,3,-1},
{8,2,3,8,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1},
{0,4,2,4,6,2,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,9,0,2,3,4,2,4,6,4,3,8,-1,-1,-1,-1},
{1,9,4,1,4,2,2,4,6,-1,-1,-1,-1,-1,-1,-1},
{8,1,3,8,6,1,8,4,6,6,10,1,-1,-1,-1,-1},
{10,1,0,10,0,6,6,0,4,-1,-1,-1,-1,-1,-1,-1},
{4,6,3,4,3,8,6,10,3,0,3,9,10,9,3,-1},
{10,9,4,6,10,4,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,9,5,7,6,11,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,3,4,9,5,11,7,6,-1,-1,-1,-1,-1,-1,-1},
{5,0,1,5,4,0,7,6,11,-1,-1,-1,-1,-1,-1,-1},
{11,7,6,8,3,4,3,5,4,3,1,5,-1,-1,-1,-1},
{9,5,4,10,1,2,7,6,11,-1,-1,-1,-1,-1,-1,-1},
{6,11,7,1,2,10,0,8,3,4,9,5,-1,-1,-1,-1},
{7,6,11,5,4,10,4,2,10,4,0,2,-1,-1,-1,-1},
{3,4,8,3,5,4,3,2,5,10,5,2,11,7,6,-1},
{7,2,3,7,6,2,5,4,9,-1,-1,-1,-1,-1,-1,-1},
{9,5,4,0,8,6,0,6,2,6,8,7,-1,-1,-1,-1},
{3,6,2,3,7,6,1,5,0,5,4,0,-1,-1,-1,-1},
{6,2,8,6,8,7,2,1,8,4,8,5,1,5,8,-1},
{9,5,4,10,1,6,1,7,6,1,3,7,-1,-1,-1,-1},
{1,6,10,1,7,6,1,0,7,8,7,0,9,5,4,-1},
{4,0,10,4,10,5,0,3,10,6,10,7,3,7,10,-1},
{7,6,10,7,10,8,5,4,10,4,8,10,-1,-1,-1,-1},
{6,9,5,6,11,9,11,8,9,-1,-1,-1,-1,-1,-1,-1},
{3,6,11,0,6,3,0,5,6,0,9,5,-1,-1,-1,-1},
{0,11,8,0,5,11,0,1,5,5,6,11,-1,-1,-1,-1},
{6,11,3,6,3,5,5,3,1,-1,-1,-1,-1,-1,-1,-1},
{1,2,10,9,5,11,9,11,8,11,5,6,-1,-1,-1,-1},
{0,11,3,0,6,11,0,9,6,5,6,9,1,2,10,-1},
{11,8,5,11,5,6,8,0,5,10,5,2,0,2,5,-1},
{6,11,3,6,3,5,2,10,3,10,5,3,-1,-1,-1,-1},
{5,8,9,5,2,8,5,6,2,3,8,2,-1,-1,-1,-1},
{9,5,6,9,6,0,0,6,2,-1,-1,-1,-1,-1,-1,-1},
{1,5,8,1,8,0,5,6,8,3,8,2,6,2,8,-1},
{1,5,6,2,1,6,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,3,6,1,6,10,3,8,6,5,6,9,8,9,6,-1},
{10,1,0,10,0,6,9,5,0,5,6,0,-1,-1,-1,-1},
{0,3,8,5,6,10,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{10,5,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{11,5,10,7,5,11,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{11,5,10,11,7,5,8,3,0,-1,-1,-1,-1,-1,-1},
{5,11,7,5,10,11,1,9,0,-1,-1,-1,-1,-1,-1},
{10,7,5,10,11,7,9,8,1,8,3,1,-1,-1,-1,-1},
{11,1,2,11,7,1,7,5,1,-1,-1,-1,-1,-1,-1},
{0,8,3,1,2,7,1,7,5,7,2,11,-1,-1,-1,-1},
{9,7,5,9,2,7,9,0,2,2,11,7,-1,-1,-1,-1},
{7,5,2,7,2,11,5,9,2,3,2,8,9,8,2,-1},
{2,5,10,2,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1},
{8,2,0,8,5,2,8,7,5,10,2,5,-1,-1,-1,-1},
{9,0,1,5,10,3,5,3,7,3,10,2,-1,-1,-1,-1},
{9,8,2,9,2,1,8,7,2,10,2,5,7,5,2,-1},
{1,3,5,3,7,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,8,7,0,7,1,1,7,5,-1,-1,-1,-1,-1,-1,-1},
{9,0,3,9,3,5,5,3,7,-1,-1,-1,-1,-1,-1,-1},
{9,8,7,5,9,7,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{5,8,4,5,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1},
{5,0,4,5,11,0,5,10,11,11,3,0,-1,-1,-1,-1},
{0,1,9,8,4,10,8,10,11,10,4,5,-1,-1,-1,-1},
{10,11,4,10,4,5,11,3,4,9,4,1,3,1,4,-1},
{2,5,1,2,8,5,2,11,8,4,5,8,-1,-1,-1,-1},
{0,4,11,0,11,3,4,5,11,2,11,1,5,1,11,-1},
{0,2,5,0,5,9,2,11,5,4,5,8,11,8,5,-1},
{9,4,5,2,11,3,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,5,10,3,5,2,3,4,5,3,8,4,-1,-1,-1,-1},
{5,10,2,5,2,4,4,2,0,-1,-1,-1,-1,-1,-1,-1},
{3,10,2,3,5,10,3,8,5,4,5,8,0,1,9,-1},
{5,10,2,5,2,4,1,9,2,9,4,2,-1,-1,-1,-1},
{8,4,5,8,5,3,3,5,1,-1,-1,-1,-1,-1,-1,-1},
{0,4,5,1,0,5,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{8,4,5,8,5,3,9,0,5,0,3,5,-1,-1,-1,-1},
{9,4,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,11,7,4,9,11,9,10,11,-1,-1,-1,-1,-1,-1},
{0,8,3,4,9,7,9,11,7,9,10,11,-1,-1,-1,-1},
{1,10,11,1,11,4,1,4,0,7,4,11,-1,-1,-1,-1},
{3,1,4,3,4,8,1,10,4,7,4,11,10,11,4,-1},
{4,11,7,9,11,4,9,2,11,9,1,2,-1,-1,-1,-1},
{9,7,4,9,11,7,9,1,11,2,11,1,0,8,3,-1},
{11,7,4,11,4,2,2,4,0,-1,-1,-1,-1,-1,-1,-1},
{11,7,4,11,4,2,8,3,4,3,2,4,-1,-1,-1,-1},
{2,9,10,2,7,9,2,3,7,7,4,9,-1,-1,-1,-1},
{9,10,7,9,7,4,10,2,7,8,7,0,2,0,7,-1},
{3,7,10,3,10,2,7,4,10,1,10,0,4,0,10,-1},
{1,10,2,8,7,4,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,9,1,4,1,7,7,1,3,-1,-1,-1,-1,-1,-1,-1},
{4,9,1,4,1,7,0,8,1,8,7,1,-1,-1,-1,-1},
{4,0,3,7,4,3,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{4,8,7,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{9,10,8,10,11,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,0,9,3,9,11,11,9,10,-1,-1,-1,-1,-1,-1,-1},
{0,1,10,0,10,8,8,10,11,-1,-1,-1,-1,-1,-1,-1},
{3,1,10,11,3,10,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,2,11,1,11,9,9,11,8,-1,-1,-1,-1,-1,-1,-1},
{3,0,9,3,9,11,1,2,9,2,11,9,-1,-1,-1,-1},
{0,2,11,8,0,11,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{3,2,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,3,8,2,8,10,10,8,9,-1,-1,-1,-1,-1,-1,-1},
{9,10,2,0,9,2,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{2,3,8,2,8,10,0,1,8,1,10,8,-1,-1,-1,-1},
{1,10,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{1,3,8,9,1,8,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,9,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{0,3,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
{-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1},
};
// clang-format on
+33
View File
@@ -0,0 +1,33 @@
import FluidGridData;
struct Params
{
// read-write
FluidGridData<float> velocityX;
// read-write
FluidGridData<float> velocityY;
// read-write
FluidGridData<float> velocityZ;
// read-only
FluidGridData<float> pressure;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void project(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> velocityX = params.velocityX;
FluidGridData<float> velocityY = params.velocityY;
FluidGridData<float> velocityZ = params.velocityZ;
FluidGridData<float> pressure = params.pressure;
int x = dispatchThreadID.x + 1;
int y = dispatchThreadID.y + 1;
int z = dispatchThreadID.z + 1;
if(x >= gridParams.gridSize.x - 1 || y >= gridParams.gridSize.y - 1 || z >= gridParams.gridSize.z - 1) return;
velocityX[x, y, z] -= 0.5f * (pressure[x + 1, y, z] - pressure[x - 1, y, z]);
velocityY[x, y, z] -= 0.5f * (pressure[x, y + 1, z] - pressure[x, y - 1, z]);
velocityZ[x, y, z] -= 0.5f * (pressure[x, y, z + 1] - pressure[x, y, z - 1]);
}
+62
View File
@@ -0,0 +1,62 @@
import Common;
import FluidGridData;
import LightEnv;
import MaterialParameter;
struct Params
{
float4x4 transform;
StructuredBuffer<float> vertexBuffer;
StructuredBuffer<float> normalBuffer;
StructuredBuffer<uint> indexBuffer;
};
ParameterBlock<Params> params;
struct VertexOut
{
float3 position_WS : POSITION;
float4 position_CS : SV_Position;
float3 normal : NORMAL;
};
[shader("vertex")]
VertexOut vertexMain(uint vertexId : SV_VertexID)
{
VertexOut output;
uint index = params.indexBuffer[vertexId];
float3 vertex = float3(params.vertexBuffer[index * 3 + 0],
params.vertexBuffer[index * 3 + 1],
params.vertexBuffer[index * 3 + 2]);
float3 normal = float3(params.normalBuffer[index * 3 + 0],
params.normalBuffer[index * 3 + 1],
params.normalBuffer[index * 3 + 2]);
vertex = mul(params.transform, float4(vertex, 1)).xyz;
normal = mul((float3x3)params.transform, normal);
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);
}
+93
View File
@@ -0,0 +1,93 @@
import FluidGridData;
struct Params
{
int b;
// read-write
FluidGridData<float> grid;
};
ParameterBlock<Params> params;
[shader("compute")]
[numthreads(32, 8, 1)]
void setBound(uint3 dispatchThreadID : SV_DispatchThreadID)
{
int b = params.b;
FluidGridData<float> grid = params.grid;
int i = dispatchThreadID.x + 1;
int j = dispatchThreadID.y + 1;
// X-faces: indices range over (gridSize.y, gridSize.z)
if(i < gridParams.gridSize.y - 1 && j < gridParams.gridSize.z - 1)
{
grid[0, i, j] = b == 1 ? -grid[1, i, j] : grid[1, i, j];
grid[gridParams.gridSize.x - 1, i, j] = b == 1 ? -grid[gridParams.gridSize.x - 2, i, j] : grid[gridParams.gridSize.x - 2, i, j];
}
// Y-faces: indices range over (gridSize.x, gridSize.z)
if(i < gridParams.gridSize.x - 1 && j < gridParams.gridSize.z - 1)
{
grid[i, 0, j] = b == 2 ? -grid[i, 1, j] : grid[i, 1, j];
grid[i, gridParams.gridSize.y - 1, j] = b == 2 ? -grid[i, gridParams.gridSize.y - 2, j] : grid[i, gridParams.gridSize.y - 2, j];
}
// Z-faces: indices range over (gridSize.x, gridSize.y)
if(i < gridParams.gridSize.x - 1 && j < gridParams.gridSize.y - 1)
{
grid[i, j, 0] = b == 3 ? -grid[i, j, 1] : grid[i, j, 1];
grid[i, j, gridParams.gridSize.z - 1] = b == 3 ? -grid[i, j, gridParams.gridSize.z - 2] : grid[i, j, gridParams.gridSize.z - 2];
}
}
[shader("compute")]
[numthreads(128, 1, 1)]
void setBoundEdges(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> grid = params.grid;
int x = dispatchThreadID.x + 1;
// X-axis edges: x ranges [1, gridSize.x-2]
if(x < gridParams.gridSize.x - 1)
{
grid[x, 0, 0] = 0.5f * (grid[x, 1, 0] + grid[x, 0, 1]);
grid[x, gridParams.gridSize.y - 1, 0] = 0.5f * (grid[x, gridParams.gridSize.y - 2, 0] + grid[x, gridParams.gridSize.y - 1, 1]);
grid[x, 0, gridParams.gridSize.z - 1] = 0.5f * (grid[x, 1, gridParams.gridSize.z - 1] + grid[x, 0, gridParams.gridSize.z - 2]);
grid[x, gridParams.gridSize.y - 1, gridParams.gridSize.z - 1] = 0.5f * (grid[x, gridParams.gridSize.y - 2, gridParams.gridSize.z - 1] + grid[x, gridParams.gridSize.y - 1, gridParams.gridSize.z - 2]);
}
// Y-axis edges: x ranges [1, gridSize.y-2]
if(x < gridParams.gridSize.y - 1)
{
grid[0, x, 0] = 0.5f * (grid[1, x, 0] + grid[0, x, 1]);
grid[0, x, gridParams.gridSize.z - 1] = 0.5f * (grid[1, x, gridParams.gridSize.z - 1] + grid[0, x, gridParams.gridSize.z - 2]);
grid[gridParams.gridSize.x - 1, x, 0] = 0.5f * (grid[gridParams.gridSize.x - 2, x, 0] + grid[gridParams.gridSize.x - 1, x, 1]);
grid[gridParams.gridSize.x - 1, x, gridParams.gridSize.z - 1] = 0.5f * (grid[gridParams.gridSize.x - 2, x, gridParams.gridSize.z - 1] + grid[gridParams.gridSize.x - 1, x, gridParams.gridSize.z - 2]);
}
// Z-axis edges: x ranges [1, gridSize.z-2]
if(x < gridParams.gridSize.z - 1)
{
grid[0, 0, x] = 0.5f * (grid[1, 0, x] + grid[0, 1, x]);
grid[0, gridParams.gridSize.y - 1, x] = 0.5f * (grid[1, gridParams.gridSize.y - 1, x] + grid[0, gridParams.gridSize.y - 2, x]);
grid[gridParams.gridSize.x - 1, 0, x] = 0.5f * (grid[gridParams.gridSize.x - 2, 0, x] + grid[gridParams.gridSize.x - 1, 1, x]);
grid[gridParams.gridSize.x - 1, gridParams.gridSize.y - 1, x] = 0.5f * (grid[gridParams.gridSize.x - 2, gridParams.gridSize.y - 1, x] + grid[gridParams.gridSize.x - 1, gridParams.gridSize.y - 2, x]);
}
}
[shader("compute")]
[numthreads(8, 1, 1)]
void setBoundCorners(uint3 dispatchThreadID : SV_DispatchThreadID)
{
FluidGridData<float> grid = params.grid;
uint threadIdx = dispatchThreadID.x;
uint x = ((threadIdx & 1) == 0) ? 0 : (gridParams.gridSize.x - 1);
uint y = ((threadIdx & 2) == 0) ? 0 : (gridParams.gridSize.y - 1);
uint z = ((threadIdx & 4) == 0) ? 0 : (gridParams.gridSize.z - 1);
uint nx = (x == 0) ? 1 : (gridParams.gridSize.x - 2);
uint ny = (y == 0) ? 1 : (gridParams.gridSize.y - 2);
uint nz = (z == 0) ? 1 : (gridParams.gridSize.z - 2);
grid[x, y, z] = (1.0f / 3.0f) * (grid[nx, y, z] + grid[x, ny, z] + grid[x, y, nz]);
}
+65
View File
@@ -0,0 +1,65 @@
import FluidGridData;
struct Params
{
float dtau;
// read-write: phi being reinitialized
FluidGridData<float> phi;
// read-only: snapshot of phi before reinitialization (for sign)
FluidGridData<float> phi0;
};
ParameterBlock<Params> params;
// Smooth sign function to avoid discontinuity at zero
float smoothSign(float x, float dx)
{
return x / sqrt(x * x + dx * dx);
}
[shader("compute")]
[numthreads(32, 8, 1)]
void reinitialize(uint3 dispatchThreadID : SV_DispatchThreadID)
{
uint x = dispatchThreadID.x + 1;
uint y = dispatchThreadID.y + 1;
uint z = dispatchThreadID.z + 1;
FluidGridData<float> phi = params.phi;
FluidGridData<float> phi0 = params.phi0;
if(x >= gridParams.gridSize.x - 1 || y >= gridParams.gridSize.y - 1 || z >= gridParams.gridSize.z - 1) return;
float dtau = params.dtau;
float dx = 1.0f;
// Current value and original sign
float p = phi0[x, y, z];
float s = smoothSign(phi0[x, y, z], dx);
// Upwind finite differences for |grad phi| — read from snapshot to avoid race
// Forward and backward differences
float dxp = phi0[x + 1, y, z] - p;
float dxm = p - phi0[x - 1, y, z];
float dyp = phi0[x, y + 1, z] - p;
float dym = p - phi0[x, y - 1, z];
float dzp = phi0[x, y, z + 1] - p;
float dzm = p - phi0[x, y, z - 1];
// Godunov upwind scheme
float gradPhi;
if (s > 0)
{
float ax = max(max(dxm, 0.0f), -min(dxp, 0.0f));
float ay = max(max(dym, 0.0f), -min(dyp, 0.0f));
float az = max(max(dzm, 0.0f), -min(dzp, 0.0f));
gradPhi = sqrt(ax * ax + ay * ay + az * az) / dx;
}
else
{
float ax = max(-min(dxm, 0.0f), max(dxp, 0.0f));
float ay = max(-min(dym, 0.0f), max(dyp, 0.0f));
float az = max(-min(dzm, 0.0f), max(dzp, 0.0f));
gradPhi = sqrt(ax * ax + ay * ay + az * az) / dx;
}
// Update: push |grad phi| toward 1
phi[x, y, z] = p - dtau * s * (gradPhi - 1.0f);
}
+1
View File
@@ -1,4 +1,5 @@
import Common;
import Frustum;
struct BoundingSphere
{
+2 -49
View File
@@ -1,3 +1,5 @@
import Frustum;
const static float PI = 3.1415926535897932f;
const static uint BLOCK_SIZE = 32;
static const uint64_t MAX_TEXCOORDS = 8;
@@ -19,7 +21,6 @@ struct ViewParameter
uint frameIndex;
float time;
};
layout(set=0)
ParameterBlock<ViewParameter> pViewParams;
float4 worldToModel(float4x4 inverseTransform, float4 world)
@@ -96,51 +97,3 @@ float4 clipToScreen(float4 clip)
float zf = pz * ndc.z + oz;
return float4(texCoords * pViewParams.screenDimensions, zf, 1.0f);
}
struct Plane
{
float4 nd;
float3 getNormal()
{
return nd.xyz;
}
float getDistance()
{
return nd.w;
}
bool pointInside(float3 point)
{
return dot(getNormal(), point) - getDistance() > 0.0f;
}
};
struct Frustum
{
Plane sides[4];
bool pointInside(float3 point)
{
for(int p = 0; p < 4; ++p)
{
if(!sides[p].pointInside(point))
{
return false;
}
}
return true;
}
};
Plane computePlane(float3 p0, float3 p1, float3 p2)
{
Plane plane;
float3 v0 = p1 - p0;
float3 v2 = p2 - p0;
float3 n = normalize(cross(v0, v2));
float d = dot(n, p0);
plane.nd = float4(n, d);
return plane;
}
+1
View File
@@ -1,4 +1,5 @@
import Common;
import Frustum;
struct DispatchParams
{
+47
View File
@@ -0,0 +1,47 @@
struct Plane
{
float4 nd;
float3 getNormal()
{
return nd.xyz;
}
float getDistance()
{
return nd.w;
}
bool pointInside(float3 point)
{
return dot(getNormal(), point) - getDistance() > 0.0f;
}
};
struct Frustum
{
Plane sides[4];
bool pointInside(float3 point)
{
for(int p = 0; p < 4; ++p)
{
if(!sides[p].pointInside(point))
{
return false;
}
}
return true;
}
};
Plane computePlane(float3 p0, float3 p1, float3 p2)
{
Plane plane;
float3 v0 = p1 - p0;
float3 v2 = p2 - p0;
float3 n = normalize(cross(v0, v2));
float d = dot(n, p0);
plane.nd = float4(n, d);
return plane;
}
+11 -3
View File
@@ -1,5 +1,6 @@
import Common;
import MaterialParameter;
import Frustum;
interface ILightEnv
{
@@ -61,8 +62,6 @@ struct PointLight : ILightEnv
struct LightEnv
{
StructuredBuffer<DirectionalLight> directionalLights;
Texture2D shadowMap; // todo: not an array
SamplerState shadowSampler;
uint numDirectionalLights;
StructuredBuffer<PointLight> pointLights;
uint numPointLights;
@@ -72,7 +71,6 @@ struct LightEnv
Texture2D brdfLUT;
SamplerState lutSampler;
};
layout(set=3)
ParameterBlock<LightEnv> pLightEnv;
interface IBRDF
@@ -83,6 +81,8 @@ interface IBRDF
float3 evaluateAmbient(float3 viewDir_WS);
float getAlpha();
float3 getEmissive();
float getRoughness();
float getMetallic();
[mutating] void setNormal(float3 n);
};
@@ -136,6 +136,8 @@ struct Phong : IBRDF
{
return emissive;
}
float getRoughness() { return pow(2.0 / (shininess + 2.0), 0.25); }
float getMetallic() { return 0; }
[mutating] void setNormal(float3 n) { normal = n; }
};
@@ -189,6 +191,8 @@ struct BlinnPhong : IBRDF
{
return emissive;
}
float getRoughness() { return pow(2.0 / (shininess + 2.0), 0.25); }
float getMetallic() { return 0; }
[mutating] void setNormal(float3 n) { normal = n; }
};
@@ -242,6 +246,8 @@ struct CelShading : IBRDF
{
return emissive;
}
float getRoughness() { return 1.0; }
float getMetallic() { return 0; }
[mutating] void setNormal(float3 n) { normal = n; }
};
@@ -366,5 +372,7 @@ struct CookTorrance : IBRDF
{
return emissive;
}
float getRoughness() { return roughness; }
float getMetallic() { return metallic; }
[mutating] void setNormal(float3 n) { normal = n; }
};
-1
View File
@@ -14,7 +14,6 @@ struct MaterialResources
SamplerState samplerArray[512];
StructuredBuffer<float> floatArray;
};
layout(set=4)
ParameterBlock<MaterialResources> pResources;
Texture2D getMaterialTextureParameter(uint index)
+15 -14
View File
@@ -45,20 +45,6 @@ struct MeshletCullingInfo
}
};
struct DrawCallOffsets
{
uint instanceOffset;
uint textureOffset;
uint samplerOffset;
uint floatOffset;
};
#ifdef RAY_TRACING
layout(shaderRecordEXT)
#else
layout(push_constant)
#endif
ConstantBuffer<DrawCallOffsets> pOffsets;
struct Scene
{
StructuredBuffer<float> positions;
@@ -73,6 +59,21 @@ struct Scene
};
ParameterBlock<Scene> pScene;
struct DrawCallOffsets
{
uint instanceOffset;
uint textureOffset;
uint samplerOffset;
uint floatOffset;
};
#ifdef RAY_TRACING
// Shader record buffers are accessed via a different mechanism and don't use descriptor set bindings
layout(set = 15, shaderRecordEXT)
#else
layout(push_constant)
#endif
ConstantBuffer<DrawCallOffsets> pOffsets;
uint32_t encodePrimitive(uint32_t meshletId)
{
return meshletId;
@@ -34,5 +34,4 @@ struct StaticMeshVertexData
StructuredBuffer<uint16_t> color;
StructuredBuffer<uint16_t> texCoords[MAX_TEXCOORDS];
};
layout(set = 1)
ParameterBlock<StaticMeshVertexData> pVertexData;
+143 -92
View File
@@ -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
@@ -26,13 +26,10 @@ import MATERIAL_FILE_NAME;
float cos_a = 1 - rnd.x + rnd.x*cos_a_max, sin_a = sqrt(1 - cos_a*cos_a);
float phi = 2 * pi * rnd.y;
vec3 l = normalize(su*cos(phi)*sin_a + sv*sin(phi)*sin_a + sw*cos_a); // sampled direction towards light
if (intersect(Ray(x,l), matls, paramsls, sphereId, triId) && sphereId == i) { // test if shadow ray hits this light source
float omega = 2 * pi * (1-cos_a_max);
if(useAtt) {
float tau = exp(-kt * length(x - paramsls.x));
result += max(dot(l,nl),0) * ls.e * omega * tau;
} else {
result += accmat / pi * max(dot(l,nl),0) * ls.e * omega; // brdf term obj.c.xyz already in accmat, 1/pi for brdf
if (intersect(Ray(x,l), matls, paramsls, sphereId, triId) && sphereId == i) { // test if shadow ray hits this light
source float omega = 2 * pi * (1-cos_a_max); if(useAtt) { float tau = exp(-kt * length(x - paramsls.x)); result += max(dot(l,nl),0) *
ls.e * omega * tau; } else { result += accmat / pi * max(dot(l,nl),0) * ls.e * omega; // brdf term obj.c.xyz already in accmat, 1/pi
for brdf
}
}
}
@@ -78,11 +75,10 @@ const static float3 fogEmm = float3(0, 0.01, 0.01);
const static float eps = 1e-5;
[shader("closesthit")]
void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttributes attr)
{
void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttributes attr) {
hitValue.hit = true;
// todo: replace with anyhit shader
if(hitValue.anyHit)
if (hitValue.anyHit)
return;
const float3 barycentricCoords = float3(1.0f - attr.barycentrics.x - attr.barycentrics.y, attr.barycentrics.x, attr.barycentrics.y);
@@ -117,106 +113,161 @@ void closestHit(inout RayPayload hitValue, in BuiltInTriangleIntersectionAttribu
let brdf = Material.prepare(hitValue.materialParams);
float3 normal_WS = brdf.getNormal();
float3 normalLight_WS = dot(normal_WS,WorldRayDirection())<0 ? normal_WS : -normal_WS;
float3 normalLight_WS = dot(normal_WS, WorldRayDirection()) < 0 ? normal_WS : -normal_WS;
float3 intersection_WS = lightingParams.position_WS;
hitValue.depth++;
float3 rnd = rand01(hitValue.rndSeed);
//float kt = ka + ks;
//float s = -log(rnd.z) / kt;
//if (s < RayTCurrent()) {
// float kt = ka + ks;
// float s = -log(rnd.z) / kt;
// if (s < RayTCurrent()) {
// float3 xs = WorldRayOrigin() + s * WorldRayDirection();
// float p = kt * rnd.z;
// if (hitValue.depth > 5) {
// if (rnd.z >= p) return;
// else brdf.baseColor /= p;
// }
// float3 ldirect = nextEventEstimation(brdf.baseColor, WorldRayDirection(), xs, -WorldRayDirection(), kt, true, rnd);
// hitValue.light += (fogEmm + ks * ldirect) / kt;
// accmat *= ks / kt;
// rayDesc.Origin = xs;
// rayDesc.Direction = float3(
// cos(2*PI*rnd.x)*sqrt(1-rnd.y*rnd.y),
// sin(2*PI*rnd.x)*sqrt(1-rnd.y*rnd.y),
// rnd.y
// );
// TraceRay(scene, 0, 0xff, 0, 0, rayDesc);
//}
// float p = kt * rnd.z;
// if (hitValue.depth > 5) {
// if (rnd.z >= p) return;
// else brdf.baseColor /= p;
// }
// float3 ldirect = nextEventEstimation(brdf.baseColor, WorldRayDirection(), xs, -WorldRayDirection(), kt, true, rnd);
// hitValue.light += (fogEmm + ks * ldirect) / kt;
// accmat *= ks / kt;
// rayDesc.Origin = xs;
// rayDesc.Direction = float3(
// cos(2*PI*rnd.x)*sqrt(1-rnd.y*rnd.y),
// sin(2*PI*rnd.x)*sqrt(1-rnd.y*rnd.y),
// rnd.y
// );
// TraceRay(scene, 0, 0xff, 0, 0, rayDesc);
// }
float p = max(max(brdf.getBaseColor().x, brdf.getBaseColor().y), brdf.getBaseColor().z);
if(hitValue.depth > 5) {
if (rnd.z >= p) return;
if (hitValue.depth > 5) {
if (rnd.z >= p)
return;
}
hitValue.light += brdf.getEmissive() * hitValue.emissive + brdf.evaluateAmbient(lightingParams.viewDir_WS);
//-- Ideal DIFFUSE reflection
//if(bool(useNEE)) {
// if(bool(useNEE)) {
// accrad += nextEventEstimation(accmat, r.d, params.x, params.nl, kt, false, rnd);
//}
for(uint i = 0; i < pLightEnv.numDirectionalLights; ++i) {
float3 x = intersection_WS;
float3 l = -pLightEnv.directionalLights[i].direction.xyz;
RayDesc rayDesc;
rayDesc.TMax = 10000.0f;
rayDesc.TMin = eps;
rayDesc.Origin = x;
rayDesc.Direction = l;
RayPayload payload;
payload.depth = hitValue.depth;
payload.emissive = 1;
payload.anyHit = true;
payload.hit = false;
payload.rndSeed = hitValue.rndSeed;
TraceRay(pRayTracingParams.scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, 0xff, 0, 0, 0, rayDesc, payload);
// Only trace shadow rays for direct lighting at shallow depths
if (hitValue.depth <= 3) {
for (uint i = 0; i < pLightEnv.numDirectionalLights; ++i) {
float3 x = intersection_WS;
float3 l = -pLightEnv.directionalLights[i].direction.xyz;
RayDesc rayDesc;
rayDesc.TMax = 10000.0f;
rayDesc.TMin = eps;
rayDesc.Origin = x;
rayDesc.Direction = l;
RayPayload payload;
payload.depth = hitValue.depth;
payload.emissive = 1;
payload.anyHit = true;
payload.hit = false;
payload.rndSeed = hitValue.rndSeed;
TraceRay(pRayTracingParams.scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, 0xff, 0, 0, 0,
rayDesc, payload);
// we have missed all geometry, so directional light is affecting us
if(!payload.hit) {
hitValue.light += pLightEnv.directionalLights[i].illuminate(lightingParams, brdf);
// we have missed all geometry, so directional light is affecting us
if (!payload.hit) {
hitValue.light += pLightEnv.directionalLights[i].illuminate(lightingParams, brdf);
}
}
}
for(uint i = 0; i < pLightEnv.numPointLights; ++i) {
RayPayload payload;
payload.rndSeed = hitValue.rndSeed;
float3 x = intersection_WS;
float3 l = pLightEnv.pointLights[i].position_WS.xyz - intersection_WS;
if(length(l) > pLightEnv.pointLights[i].colorRange.w) {
continue;
}
RayDesc rayDesc;
rayDesc.TMax = 1.0f;
rayDesc.TMin = eps;
rayDesc.Origin = x;
rayDesc.Direction = l;
TraceRay(pRayTracingParams.scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, 0xff, 0, 0, 0, rayDesc, payload);
for (uint i = 0; i < pLightEnv.numPointLights; ++i) {
RayPayload payload;
payload.rndSeed = hitValue.rndSeed;
float3 x = intersection_WS;
float3 l = pLightEnv.pointLights[i].position_WS.xyz - intersection_WS;
if (length(l) > pLightEnv.pointLights[i].colorRange.w) {
continue;
}
RayDesc rayDesc;
rayDesc.TMax = 1.0f;
rayDesc.TMin = eps;
rayDesc.Origin = x;
rayDesc.Direction = l;
TraceRay(pRayTracingParams.scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES | RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, 0xff, 0, 0, 0,
rayDesc, payload);
// hitting only after the light
if(!payload.hit) {
hitValue.light += pLightEnv.pointLights[i].illuminate(lightingParams, brdf);
// hitting only after the light
if (!payload.hit) {
hitValue.light += pLightEnv.pointLights[i].illuminate(lightingParams, brdf);
}
}
}
// Indirect Illumination: cosine-weighted importance sampling
if(hitValue.depth < 1) {
float r1 = 2 * PI * rnd.x, r2 = rnd.y, r2s = sqrt(r2);
float3 w = normalLight_WS;
float3 u = normalize(cross(abs(w.x)>0.1 ? float3(0,1,0) : float3(1,0,0), w));
float3 v = cross(w,u);
} // end depth <= 2 direct lighting guard
// Indirect Illumination: probabilistic diffuse/specular importance sampling
if (hitValue.depth < 3) {
float3 V = -WorldRayDirection();
float3 N = normalLight_WS;
float rough = brdf.getRoughness();
float met = brdf.getMetallic();
float3 F0 = lerp(float3(0.04), brdf.getBaseColor(), met);
float NdotV = max(dot(N, V), 0.001);
float3 F = F0 + (1 - F0) * pow(1 - NdotV, 5.0);
float specProb = clamp((F.x + F.y + F.z) / 3.0, 0.1, 0.9);
RayDesc rayDesc;
rayDesc.TMax = 10000.0f;
rayDesc.TMin = eps;
rayDesc.Origin = intersection_WS;
rayDesc.Direction = normalize(u*cos(r1)*r2s + v * sin(r1)*r2s + w * sqrt(1 - r2));
RayPayload payload;
payload.light = float3(0);
payload.emissive = 1;
payload.hit = false;
//payload.emissive = 0; // in the next bounce, consider reflective part only!
payload.depth = hitValue.depth;
payload.anyHit = false;
payload.rndSeed = hitValue.rndSeed + 1;
TraceRay(pRayTracingParams.scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, 0xff, 0, 0, 0, rayDesc, payload);
float bias = dot(normalLight_WS, rayDesc.Direction);
hitValue.light += brdf.evaluate(-WorldRayDirection(), rayDesc.Direction, payload.light / bias);
}
//hitValue.light /= p;
float3 bounceWeight = float3(0);
bool validBounce = true;
if (rnd.z < specProb) {
// GGX importance sampling for specular reflection
float a = max(rough * rough, 0.001);
float a2 = a * a;
float phi = 2.0 * PI * rnd.x;
float cosTheta = sqrt((1.0 - rnd.y) / (1.0 + (a2 - 1.0) * rnd.y));
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
float3 u = normalize(cross(abs(N.x) > 0.1 ? float3(0, 1, 0) : float3(1, 0, 0), N));
float3 v = cross(N, u);
float3 H = normalize(u * cos(phi) * sinTheta + v * sin(phi) * sinTheta + N * cosTheta);
float3 L = reflect(-V, H);
rayDesc.Direction = L;
float NdotL = dot(N, L);
float NdotH = max(dot(N, H), 0.0);
float VdotH = max(dot(V, H), 0.0);
if (NdotL <= 0) {
validBounce = false;
} else {
// Smith G term
float k = (rough + 1);
k = (k * k) / 8;
float G = (NdotV / (NdotV * (1 - k) + k)) * (NdotL / (NdotL * (1 - k) + k));
// Fresnel at half-vector
float3 Fh = F0 + (max(float3(1.0 - rough), F0) - F0) * pow(clamp(1 - VdotH, 0, 1), 5.0);
// Monte Carlo weight: F * G * VdotH / (NdotH * NdotV * specProb)
bounceWeight = Fh * G * VdotH / (NdotH * NdotV * specProb + 0.0001);
}
} else {
// Cosine-weighted importance sampling for diffuse
float r1 = 2 * PI * rnd.x, r2 = rnd.y, r2s = sqrt(r2);
float3 w = N;
float3 u = normalize(cross(abs(w.x) > 0.1 ? float3(0, 1, 0) : float3(1, 0, 0), w));
float3 v = cross(w, u);
rayDesc.Direction = normalize(u * cos(r1) * r2s + v * sin(r1) * r2s + w * sqrt(1 - r2));
// Diffuse weight: kd * baseColor / (1 - specProb)
float3 kd = (1 - F) * (1 - met);
bounceWeight = kd * brdf.getBaseColor() / (1 - specProb);
}
if (validBounce) {
RayPayload payload;
payload.light = float3(0);
payload.hit = false;
payload.emissive = 0;
payload.depth = hitValue.depth;
payload.anyHit = false;
payload.rndSeed = hitValue.rndSeed + 1;
TraceRay(pRayTracingParams.scene, RAY_FLAG_CULL_BACK_FACING_TRIANGLES, 0xff, 0, 0, 0, rayDesc, payload);
hitValue.light += bounceWeight * payload.light;
}
}
// hitValue.light /= p;
}
@@ -9,7 +9,6 @@ struct RayTracingParams
TextureCube<float4> skyBox;
SamplerState skyBoxSampler;
};
layout(set=5)
ParameterBlock<RayTracingParams> pRayTracingParams;
struct RayPayload
-2
View File
@@ -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); }
-2
View File
@@ -13,8 +13,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;
Gfx::OTimestampQuery renderTimestamp;
+1 -9
View File
@@ -1,11 +1,7 @@
#include "Asset/AssetRegistry.h"
#include "Graphics/Initializer.h"
#include "Graphics/StaticMeshVertexData.h"
#ifdef __APPLE__
#include "Graphics/Metal/Graphics.h"
#else
#include "Graphics/Vulkan/Graphics.h"
#endif
#include "PlayView.h"
#include "Window/WindowManager.h"
#include <fmt/core.h>
@@ -29,11 +25,7 @@ int main(int argc, char** argv) {
std::filesystem::path binaryPath = "MeshShadingDemo.dll";
#ifdef __APPLE__
graphics = new Metal::Graphics();
#else
graphics = new Vulkan::Graphics();
#endif
graphics = new Vulkan::Graphics();
GraphicsInitializer initializer;
graphics->init(initializer);
StaticMeshVertexData* vd = StaticMeshVertexData::getInstance();
+6 -9
View File
@@ -6,6 +6,7 @@
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h"
#include "Graphics/RenderTarget.h"
#include "Math/Matrix.h"
#include "stb_image.h"
using namespace Seele;
@@ -20,7 +21,6 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic
.size = {SOURCE_RESOLUTION, SOURCE_RESOLUTION},
.offset = {0, 0},
},
.fieldOfView = glm::radians(90.0f),
});
convolutionViewport = graphics->createViewport(nullptr, ViewportCreateInfo{
.dimensions =
@@ -28,7 +28,6 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic
.size = {CONVOLUTED_RESOLUTION, CONVOLUTED_RESOLUTION},
.offset = {0, 0},
},
.fieldOfView = glm::radians(90.0f),
});
for (uint32 i = 0; i < prefilterViewports.size(); ++i) {
prefilterViewports[i] = graphics->createViewport(nullptr, ViewportCreateInfo{
@@ -37,7 +36,6 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic
.size = {128 * std::pow(0.5, i), 128 * std::pow(0.5, i)},
.offset = {0, 0},
},
.fieldOfView = glm::radians(90.0f),
});
}
cubeSampler = graphics->createSampler({
@@ -126,7 +124,6 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic
.size = {512, 512},
.offset = {0, 0},
},
.fieldOfView = glm::radians(90.0f),
});
Gfx::ORenderPass lutPass = graphics->createRenderPass(
Gfx::RenderTargetLayout{
@@ -194,7 +191,7 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
.height = (uint32)height,
.name = "HDRRaw",
});
Matrix4 captureProjection = cubeRenderViewport->getProjectionMatrix(0.1f, 10.0f);
Matrix4 captureProjection = perspectiveProjection(glm::radians(90.0f), 1.0f, 0.1f, 10.0f);
Matrix4 captureViews[] = {
glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(1.0f, 0.0f, 0.0f), Vector(0.0f, 1.0f, 0.0f)),
glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(-1.0f, 0.0f, 0.0f), Vector(0.0f, 1.0f, 0.0f)),
@@ -203,7 +200,7 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 0.0f, -1.0f), Vector(0.0f, 1.0f, 0.0f)),
glm::lookAt(Vector(0.0f, 0.0f, 0.0f), Vector(0.0f, 0.0f, 1.0f), Vector(0.0f, 1.0f, 0.0f)),
};
Gfx::PDescriptorSet set = cubeRenderLayout->allocateDescriptorSet();
Gfx::ODescriptorSet set = cubeRenderLayout->allocateDescriptorSet();
set->updateConstants("view", 0, captureViews);
set->updateConstants("projection", 0, &captureProjection);
set->updateTexture("equirectangularMap", 0, hdrTexture->getDefaultView());
@@ -262,7 +259,7 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
graphics->beginRenderPass(cubeRenderPass);
Gfx::ORenderCommand renderCommand = graphics->createRenderCommand("CubeMapRender");
renderCommand->bindPipeline(cubeRenderPipeline);
renderCommand->bindDescriptor({set});
renderCommand->bindDescriptor(set);
renderCommand->setViewport(cubeRenderViewport);
renderCommand->draw(6, 1, i * 6, 0);
graphics->executeCommands(std::move(renderCommand));
@@ -329,7 +326,7 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
graphics->beginRenderPass(convolutionPass);
Gfx::ORenderCommand cmd = graphics->createRenderCommand("ConvolutionPass");
cmd->bindPipeline(convolutionPipeline);
cmd->bindDescriptor({set});
cmd->bindDescriptor(set);
cmd->setViewport(convolutionViewport);
cmd->draw(6, 1, i * 6, 0);
graphics->executeCommands(std::move(cmd));
@@ -391,7 +388,7 @@ void EnvironmentLoader::import(EnvironmentImportArgs args, PEnvironmentMapAsset
graphics->beginRenderPass(prefilterPass);
Gfx::ORenderCommand cmd = graphics->createRenderCommand("PrefilterPass");
cmd->bindPipeline(prefilterPipeline);
cmd->bindDescriptor({set});
cmd->bindDescriptor(set);
float roughness = (float)mip / (float)(prefilteredCubeMap->getMipLevels() - 1);
cmd->pushConstants(Gfx::SE_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(float), &roughness);
cmd->setViewport(prefilterViewports[mip]);
+3 -5
View File
@@ -2,7 +2,6 @@
#include "Asset/AssetRegistry.h"
#include "Asset/TextureAsset.h"
#include "Graphics/Graphics.h"
#include "Graphics/Vulkan/Enums.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
@@ -15,7 +14,7 @@
#pragma GCC diagnostic pop
#include "ktx.h"
#include <ThreadPool.h>
#include <fstream>
#include <iostream>
using namespace Seele;
@@ -60,9 +59,8 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) {
int totalWidth = 0, totalHeight = 0, n = 0;
unsigned char* data = stbi_load(args.filePath.string().c_str(), &totalWidth, &totalHeight, &n, 4);
ktxTexture2* kTexture = nullptr;
VkFormat format = VK_FORMAT_R8G8B8A8_SRGB;
ktxTextureCreateInfo createInfo = {
.vkFormat = (uint32)format,
.vkFormat = 43, // rgba8srgb
.baseDepth = 1,
.numLevels = 1,
.numLayers = 1,
@@ -116,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];
+2 -2
View File
@@ -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) {}
+2 -2
View File
@@ -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;
};
+2 -1
View File
@@ -2,6 +2,7 @@
#include "Graphics/Enums.h"
#include "MinimalEngine.h"
#include "Window/Window.h"
#include <iostream>
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;
+1 -1
View File
@@ -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:
};
+2 -2
View File
@@ -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);
}
+2 -2
View File
@@ -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;
};
+18 -17
View File
@@ -4,19 +4,15 @@
#include "Asset/FontLoader.h"
#include "Asset/MaterialLoader.h"
#include "Asset/MeshLoader.h"
#include "Graphics/Vulkan/Graphics.h"
#include "Asset/TextureLoader.h"
#include "Graphics/Initializer.h"
#ifdef __APPLE__
#include "Graphics/Metal/Graphics.h"
#else
#endif
#include "Graphics/StaticMeshVertexData.h"
#include "Material/Material.h"
#include "Graphics/Vulkan/Graphics.h"
#include "Window/InspectorView.h"
#include "Graphics/StaticMeshVertexData.h"
#include "Window/PlayView.h"
#include "Window/WindowManager.h"
#include <fmt/core.h>
#include <random>
using namespace Seele;
using namespace Seele::Editor;
@@ -25,9 +21,9 @@ using namespace Seele::Editor;
static Gfx::OGraphics graphics;
int main() {
std::string gameName = "MeshShadingDemo";
std::filesystem::path outputPath = fmt::format("../../../../{0}Game/", gameName);
std::filesystem::path sourcePath = fmt::format("../../../../{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__
@@ -35,14 +31,10 @@ int main() {
#else
std::string libraryEnding = "so";
#endif
std::filesystem::path binaryPath = sourcePath / "bin" / fmt::format("{}.{}", gameName, libraryEnding);
std::filesystem::path binaryPath = sourcePath / "build" / fmt::format("{}.{}", gameName, libraryEnding);
std::filesystem::path cmakePath = outputPath / "cmake";
if (true) {
#ifdef __APPLE__
graphics = new Metal::Graphics();
#else
graphics = new Vulkan::Graphics();
#endif
GraphicsInitializer initializer;
graphics->init(initializer);
StaticMeshVertexData* vd = StaticMeshVertexData::getInstance();
@@ -55,7 +47,7 @@ int main() {
.filePath = "./fonts/arial.ttf",
});
AssetImporter::importEnvironmentMap(EnvironmentImportArgs{
.filePath = sourcePath / "import" / "textures" / "newport_loft.hdr",
.filePath = sourcePath / "import" / "newport_loft.hdr",
});
// AssetImporter::importTexture(TextureImportArgs{
// .filePath = sourcePath / "import" / "textures" / "grass_block_side.png",
@@ -65,8 +57,17 @@ int main() {
// .filePath = sourcePath / "import" / "models" / "main1_sponza" / "sponza.gltf",
// .importPath = "sponza",
//});
// AssetImporter::importMesh(MeshImportArgs{
// .filePath = sourcePath / "import" / "models" / "rttest.gltf",
// .importPath = "rttest",
// });
// 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",
});
+1 -1
View File
@@ -227,7 +227,7 @@ void AssetRegistry::initialize(const std::filesystem::path& _rootFolder, Gfx::PG
this->assetRoot = new AssetFolder("");
if (!std::filesystem::exists(rootFolder))
{
std::filesystem::create_directories(rootFolder);
//std::filesystem::create_directories(rootFolder);
}
else if (!std::filesystem::is_directory(rootFolder))
{
+1 -1
View File
@@ -1,9 +1,9 @@
#include "TextureAsset.h"
#include "Graphics/Graphics.h"
#include "Graphics/Texture.h"
#include "Graphics/Vulkan/Enums.h"
#include "Window/WindowManager.h"
#include "ktx.h"
#include <iostream>
using namespace Seele;
+2
View File
@@ -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
+18
View File
@@ -2,13 +2,31 @@
#include "Component.h"
#include "Math/Matrix.h"
#include "Transform.h"
#include <glm/trigonometric.hpp>
namespace Seele {
namespace Component {
struct Camera {
float fieldOfView = glm::radians(70.0f);
float aspectRatio = 16.0f / 9.0f;
float nearPlane = 0.1f;
float farPlane = 1000.0f;
bool mainCamera = false;
constexpr Matrix4 getProjectionMatrix() const {
if(fieldOfView > 0.0f) {
return perspectiveProjection(fieldOfView, aspectRatio, nearPlane, farPlane);
} else {
float orthoHeight = 10.0f;
float orthoWidth = orthoHeight * aspectRatio;
return orthographicProjection(-orthoWidth / 2.0f, orthoWidth / 2.0f, -orthoHeight / 2.0f, orthoHeight / 2.0f, nearPlane, farPlane);
}
}
constexpr Matrix4 getPerspectiveMatrix() const {
return perspectiveProjection(fieldOfView, aspectRatio, nearPlane, farPlane);
}
constexpr Matrix4 getOrthographicMatrix(float left, float right, float bottom, float top) const {
return orthographicProjection(left, right, bottom, top, nearPlane, farPlane);
}
};
} // namespace Component
} // namespace Seele
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include "Math/Vector.h"
namespace Seele {
namespace Component {
struct FluidGrid {
bool paused = true;
float dt = 0.1f;
float viscosity = 0.001f;
float diffusion = 0.0001f;
UVector gridSize = {128, 128, 128};
Vector gravity = {0.0f, -9.81f, 0.0f};
bool enableGravity = true;
};
} // namespace Component
} // namespace Seele
+1
View File
@@ -7,6 +7,7 @@
#include <cstring>
#include <initializer_list>
#include <iterator>
#include <ranges>
#include <memory_resource>
namespace Seele {
+2 -1
View File
@@ -1,7 +1,8 @@
#pragma once
#include <assert.h>
#include <memory>
#include <memory_resource>
#include <memory>
namespace Seele {
template <typename T, typename Allocator = std::pmr::polymorphic_allocator<T>> class List {
+2
View File
@@ -1,6 +1,8 @@
#pragma once
#include <string>
#include <memory_resource>
#include <map>
#include <string>
#include "MinimalEngine.h"
namespace Seele {
+5 -7
View File
@@ -1,4 +1,9 @@
#add_subdirectory(CBT/)
add_subdirectory(RenderPass/)
if(APPLE)
# add_subdirectory(Metal/)
endif()
add_subdirectory(Vulkan/)
target_sources(Engine
PRIVATE
@@ -65,10 +70,3 @@ target_sources(Engine
Texture.h
VertexData.h
Window.h)
add_subdirectory(RenderPass/)
if(APPLE)
add_subdirectory(Metal/)
else()
add_subdirectory(Vulkan/)
endif()
+2
View File
@@ -21,6 +21,7 @@ class RenderCommand {
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) = 0;
virtual void drawIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) = 0;
virtual void drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) = 0;
virtual void drawIndexedIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) = 0;
virtual void drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) = 0;
virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) = 0;
virtual void traceRays(uint32 width, uint32 height, uint32 depth) = 0;
@@ -36,6 +37,7 @@ class ComputeCommand {
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) = 0;
virtual void pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 0;
virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) = 0;
virtual void dispatch(UVector threadGroupSize) = 0;
virtual void dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) = 0;
std::string name;
};
+1 -1
View File
@@ -11,7 +11,7 @@ void DescriptorLayout::addDescriptorBinding(DescriptorBinding binding) {
descriptorBindings.add(binding);
}
PDescriptorSet DescriptorLayout::allocateDescriptorSet() { return pool->allocateDescriptorSet(); }
ODescriptorSet DescriptorLayout::allocateDescriptorSet() { return pool->allocateDescriptorSet(); }
void DescriptorLayout::reset() { pool->reset(); }
+13 -6
View File
@@ -9,7 +9,7 @@ struct DescriptorBinding {
std::string name;
// In Metal uniforms are plain bytes, and for that we need to know the struct size
uint32 uniformLength = 0;
SeDescriptorType descriptorType = SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
SeDescriptorType descriptorType = SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK;
SeImageViewType textureType = SE_IMAGE_VIEW_TYPE_2D;
uint32 descriptorCount = 1;
SeDescriptorBindingFlags bindingFlags = 0;
@@ -25,9 +25,8 @@ class DescriptorLayout {
virtual ~DescriptorLayout();
void addDescriptorBinding(DescriptorBinding binding);
void reset();
PDescriptorSet allocateDescriptorSet();
ODescriptorSet allocateDescriptorSet();
virtual void create() = 0;
constexpr const Array<DescriptorBinding>& getBindings() const { return descriptorBindings; }
constexpr uint32 getHash() const { return hash; }
constexpr const std::string& getName() const { return name; }
@@ -46,7 +45,7 @@ class DescriptorPool {
public:
DescriptorPool();
virtual ~DescriptorPool();
virtual PDescriptorSet allocateDescriptorSet() = 0;
virtual ODescriptorSet allocateDescriptorSet() = 0;
virtual void reset() = 0;
};
DEFINE_REF(DescriptorPool)
@@ -60,10 +59,11 @@ class DescriptorSet {
DescriptorSet(PDescriptorLayout layout);
virtual ~DescriptorSet();
virtual void writeChanges() = 0;
virtual void updateConstants(const std::string& name, uint32 offset, void* data) = 0;
virtual void updateConstants(const std::string& name, uint32 offset, const void* data) = 0;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer shaderBuffer) = 0;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer indexBuffer) = 0;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer vertexBuffer) = 0;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer indexBuffer) = 0;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PUniformBuffer uniformBuffer) = 0;
virtual void updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) = 0;
virtual void updateTexture(const std::string& name, uint32 index, Gfx::PTextureView texture) = 0;
virtual void updateAccelerationStructure(const std::string& name, uint32 index, Gfx::PTopLevelAS as) = 0;
@@ -93,6 +93,13 @@ class PipelineLayout {
constexpr std::string getName() const { return name; };
constexpr bool hasPushConstants() const { return !pushConstants.empty(); }
constexpr uint64 getPushConstantsSize() const { return pushConstants[0].size; }
constexpr const std::string& getPushConstantName(uint64 offset) {
for (uint32 i = 0; i < pushConstants.size(); ++i) {
if (offset == pushConstants[i].offset)
return pushConstants[i].name;
}
throw std::logic_error("unknown push constant offset");
}
protected:
uint32 layoutHash = 0;
+2 -1
View File
@@ -4,7 +4,7 @@
#include "MinimalEngine.h"
#include "RenderTarget.h"
#include "Resources.h"
#define ENABLE_VALIDATION
namespace Seele {
namespace Gfx {
@@ -67,6 +67,7 @@ class Graphics {
virtual void executeCommands(Array<OComputeCommand> commands) = 0;
virtual OTexture2D createTexture2D(const TextureCreateInfo& createInfo) = 0;
virtual OTexture2DArray createTexture2DArray(const TextureCreateInfo& createInfo) = 0;
virtual OTexture3D createTexture3D(const TextureCreateInfo& createInfo) = 0;
virtual OTextureCube createTextureCube(const TextureCreateInfo& createInfo) = 0;
virtual OUniformBuffer createUniformBuffer(const UniformBufferCreateInfo& bulkData) = 0;
-6
View File
@@ -31,12 +31,6 @@ struct WindowCreateInfo {
};
struct ViewportCreateInfo {
URect dimensions;
float fieldOfView = glm::radians(70.0f);
// ortho params
float left = 0;
float right = 0;
float top = 0;
float bottom = 0;
};
// doesnt own the data, only proxy it
struct DataSource {
+1 -1
View File
@@ -12,7 +12,7 @@ using namespace Seele;
using namespace Seele::Metal;
BufferAllocation::BufferAllocation(PGraphics graphics, const std::string& name, uint64 size, MTL::ResourceOptions options)
: CommandBoundResource(graphics) {
: CommandBoundResource(graphics, name) {
buffer = graphics->getDevice()->newBuffer(size, options);
buffer->setLabel(NS::String::string(name.c_str(), NS::ASCIIStringEncoding));
}
+69 -61
View File
@@ -128,16 +128,17 @@ void RenderCommand::bindPipeline(Gfx::PRayTracingPipeline pipeline) {}
void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) {
auto metalSet = descriptorSet.cast<DescriptorSet>();
metalSet->bind();
boundResources.add(metalSet);
auto setHandle = metalSet->setHandle;
setHandle->bind();
boundResources.add(setHandle);
uint32 descriptorIndex = boundPipeline->getPipelineLayout()->findParameter(metalSet->getLayout()->getName());
auto createEncoder = [&metalSet, descriptorIndex](MTL::Function* function, const Array<uint32>& usedSets) {
if(metalSet->encoder == nullptr) {
auto createEncoder = [metalSet, &setHandle, descriptorIndex](MTL::Function* function, const Array<uint32>& usedSets) {
if(setHandle->encoder == nullptr) {
if (metalSet->isPlainDescriptor()) {
metalSet->encoder = metalSet->createEncoder();
setHandle->encoder = metalSet->createEncoder();
} else if (function != nullptr && usedSets.contains(descriptorIndex)) {
metalSet->encoder = function->newArgumentEncoder(descriptorIndex);
setHandle->encoder = function->newArgumentEncoder(descriptorIndex);
}
}
};
@@ -145,39 +146,39 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) {
createEncoder(boundPipeline->meshFunction, boundPipeline->meshSets);
createEncoder(boundPipeline->vertexFunction, boundPipeline->vertexSets);
createEncoder(boundPipeline->fragmentFunction, boundPipeline->fragmentSets);
if(metalSet->argumentBuffer == nullptr) {
metalSet->argumentBuffer = new BufferAllocation(metalSet->graphics, "ArgumentBuffer", metalSet->encoder->encodedLength());
metalSet->encoder->setArgumentBuffer(metalSet->argumentBuffer->buffer, 0);
if(setHandle->argumentBuffer == nullptr) {
setHandle->argumentBuffer = new BufferAllocation(metalSet->graphics, "ArgumentBuffer", setHandle->encoder->encodedLength());
setHandle->encoder->setArgumentBuffer(setHandle->argumentBuffer->buffer, 0);
}
metalSet->argumentBuffer->bind();
boundResources.add(PBufferAllocation(metalSet->argumentBuffer));
for (const auto& write : metalSet->uniformWrites) {
write.apply(metalSet->encoder);
setHandle->argumentBuffer->bind();
boundResources.add(PBufferAllocation(setHandle->argumentBuffer));
for (const auto& write : setHandle->uniformWrites) {
write.apply(setHandle->encoder);
}
for (const auto& write : metalSet->bufferWrites) {
write.apply(metalSet->encoder);
for (const auto& write : setHandle->bufferWrites) {
write.apply(setHandle->encoder);
encoder->useResource(write.buffer->buffer, write.access);
}
for (const auto& write : metalSet->samplerWrites) {
write.apply(metalSet->encoder);
for (const auto& write : setHandle->samplerWrites) {
write.apply(setHandle->encoder);
}
for (const auto& write : metalSet->textureWrites) {
write.apply(metalSet->encoder);
encoder->useResource(write.texture->texture, write.access);
for (const auto& write : setHandle->textureWrites) {
write.apply(setHandle->encoder);
encoder->useResource(write.texture->getHandle(), write.access);
}
for (const auto& write : metalSet->accelerationWrites) {
write.apply(metalSet->encoder);
for (const auto& write : setHandle->accelerationWrites) {
write.apply(setHandle->encoder);
encoder->useResource(write.accelerationStructure, write.access);
}
for(auto& res : metalSet->boundResources) {
for(auto& res : setHandle->boundResources) {
res->bind();
boundResources.add(res);
}
encoder->useResource(metalSet->argumentBuffer->buffer, MTL::ResourceUsageRead);
encoder->setObjectBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex);
encoder->setMeshBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex);
encoder->setVertexBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex);
encoder->setFragmentBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex);
encoder->useResource(setHandle->argumentBuffer->buffer, MTL::ResourceUsageRead);
encoder->setObjectBuffer(setHandle->argumentBuffer->buffer, 0, descriptorIndex);
encoder->setMeshBuffer(setHandle->argumentBuffer->buffer, 0, descriptorIndex);
encoder->setVertexBuffer(setHandle->argumentBuffer->buffer, 0, descriptorIndex);
encoder->setFragmentBuffer(setHandle->argumentBuffer->buffer, 0, descriptorIndex);
}
void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorSets) {
@@ -197,18 +198,18 @@ void RenderCommand::bindIndexBuffer(Gfx::PIndexBuffer gfxIndexBuffer) {
}
void RenderCommand::pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) {
uint pushIndex = boundPipeline->getPipelineLayout()->findParameter("pOffsets");
uint pushIndex = boundPipeline->getPipelineLayout()->findParameter(boundPipeline->getPipelineLayout()->getPushConstantName(offset));
if (stage & Gfx::SE_SHADER_STAGE_VERTEX_BIT) {
encoder->setVertexBytes(data, size, pushIndex); // TODO: hardcoded
encoder->setVertexBytes(data, size, pushIndex);
}
if (stage & Gfx::SE_SHADER_STAGE_FRAGMENT_BIT) {
encoder->setFragmentBytes(data, size, pushIndex); // TODO: hardcoded
encoder->setFragmentBytes(data, size, pushIndex);
}
if (stage & Gfx::SE_SHADER_STAGE_TASK_BIT_EXT) {
encoder->setObjectBytes(data, size, pushIndex); // TODO: hardcoded
encoder->setObjectBytes(data, size, pushIndex);
}
if (stage & Gfx::SE_SHADER_STAGE_MESH_BIT_EXT) {
encoder->setMeshBytes(data, size, pushIndex); // TODO: hardcoded
encoder->setMeshBytes(data, size, pushIndex);
}
}
@@ -252,46 +253,53 @@ void ComputeCommand::bindPipeline(Gfx::PComputePipeline pipeline) {
encoder->setComputePipelineState(boundPipeline->getHandle());
}
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet set) {
auto metalSet = set.cast<DescriptorSet>();
metalSet->bind();
boundResources.add(metalSet);
void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptorSet) {
auto metalSet = descriptorSet.cast<DescriptorSet>();
auto setHandle = metalSet->setHandle;
setHandle->bind();
boundResources.add(setHandle);
uint32 descriptorIndex = boundPipeline->getPipelineLayout()->findParameter(metalSet->getLayout()->getName());
if(metalSet->encoder == nullptr) {
if (metalSet->isPlainDescriptor()) {
metalSet->encoder = metalSet->createEncoder();
} else {
metalSet->encoder = boundPipeline->computeFunction->newArgumentEncoder(descriptorIndex);
auto createEncoder = [metalSet, &setHandle, descriptorIndex](MTL::Function* function) {
if(setHandle->encoder == nullptr) {
if (metalSet->isPlainDescriptor()) {
setHandle->encoder = metalSet->createEncoder();
} else if (function != nullptr) {
setHandle->encoder = function->newArgumentEncoder(descriptorIndex);
}
}
metalSet->argumentBuffer = new BufferAllocation(metalSet->graphics, "ArgumentBuffer", metalSet->encoder->encodedLength());
metalSet->encoder->setArgumentBuffer(metalSet->argumentBuffer->buffer, 0);
};
createEncoder(boundPipeline->computeFunction);
if(setHandle->argumentBuffer == nullptr) {
setHandle->argumentBuffer = new BufferAllocation(metalSet->graphics, "ArgumentBuffer", setHandle->encoder->encodedLength());
setHandle->encoder->setArgumentBuffer(setHandle->argumentBuffer->buffer, 0);
}
metalSet->argumentBuffer->bind();
boundResources.add(PBufferAllocation(metalSet->argumentBuffer));
for (const auto& write : metalSet->uniformWrites) {
write.apply(metalSet->encoder);
setHandle->argumentBuffer->bind();
boundResources.add(PBufferAllocation(setHandle->argumentBuffer));
for (const auto& write : setHandle->uniformWrites) {
write.apply(setHandle->encoder);
}
for (const auto& write : metalSet->bufferWrites) {
write.apply(metalSet->encoder);
for (const auto& write : setHandle->bufferWrites) {
write.apply(setHandle->encoder);
encoder->useResource(write.buffer->buffer, write.access);
}
for (const auto& write : metalSet->samplerWrites) {
write.apply(metalSet->encoder);
for (const auto& write : setHandle->samplerWrites) {
write.apply(setHandle->encoder);
}
for (const auto& write : metalSet->textureWrites) {
write.apply(metalSet->encoder);
encoder->useResource(write.texture->texture, write.access);
for (const auto& write : setHandle->textureWrites) {
write.apply(setHandle->encoder);
encoder->useResource(write.texture->getHandle(), write.access);
}
for (const auto& write : metalSet->accelerationWrites) {
write.apply(metalSet->encoder);
for (const auto& write : setHandle->accelerationWrites) {
write.apply(setHandle->encoder);
encoder->useResource(write.accelerationStructure, write.access);
}
for(auto& res : metalSet->boundResources) {
for(auto& res : setHandle->boundResources) {
res->bind();
boundResources.add(res);
}
encoder->useResource(metalSet->argumentBuffer->buffer, MTL::ResourceUsageRead);
encoder->setBuffer(metalSet->argumentBuffer->buffer, 0, descriptorIndex);
encoder->useResource(setHandle->argumentBuffer->buffer, MTL::ResourceUsageRead);
encoder->setBuffer(setHandle->argumentBuffer->buffer, 0, descriptorIndex);
}
void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) {
@@ -358,6 +366,7 @@ void CommandQueue::submitCommands(PEvent signalSemaphore) {
for (auto it = pendingCommands.begin(); it != pendingCommands.end(); it++) {
if ((*it)->getHandle() == cmdBuffer) {
auto& cmd = *it;
std::cout << "Command completed" << std::endl;
cmd->reset();
readyCommands.add(std::move(*it));
pendingCommands.erase(it);
@@ -367,7 +376,6 @@ void CommandQueue::submitCommands(PEvent signalSemaphore) {
}));
PEvent prevCmdEvent = activeCommand->getCompletedEvent();
activeCommand->end(signalSemaphore);
activeCommand->waitDeviceIdle();
pendingCommands.add(std::move(activeCommand));
if (!readyCommands.empty()) {
activeCommand = std::move(readyCommands.front());
+56 -37
View File
@@ -40,49 +40,28 @@ class DescriptorLayout : public Gfx::DescriptorLayout {
// descriptor sets containing only uniform data are not actually argument buffers, so they need to be
// handled separately
bool plainDescriptor = true;
friend class DescriptorSet;
friend class DescriptorSetHandle;
};
DEFINE_REF(DescriptorLayout)
DECLARE_REF(DescriptorSet)
class DescriptorPool : public Gfx::DescriptorPool {
public:
DescriptorPool(PGraphics graphics, PDescriptorLayout layout);
virtual ~DescriptorPool();
virtual Gfx::PDescriptorSet allocateDescriptorSet() override;
virtual void reset() override;
constexpr PDescriptorLayout getLayout() const { return layout; }
DECLARE_REF(DescriptorPool)
class DescriptorSetHandle : public CommandBoundResource {
public:
DescriptorSetHandle(PGraphics grapics, PDescriptorPool owner, const std::string& name);
virtual ~DescriptorSetHandle();
void updateConstants(const std::string& name, uint32 offset, void* data);
void updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer uniformBuffer);
void updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer uniformBuffer);
void updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer uniformBuffer);
void updateBuffer(const std::string& name, uint32 index, Gfx::PUniformBuffer uniformBuffer);
void updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState);
void updateTexture(const std::string& name, uint32 index, Gfx::PTextureView texture);
void updateAccelerationStructure(const std::string& name, uint32 index, Gfx::PTopLevelAS as);
private:
PGraphics graphics;
PDescriptorLayout layout;
Array<ODescriptorSet> allocatedSets;
};
DEFINE_REF(DescriptorPool)
class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource {
public:
DescriptorSet(PGraphics graphics, PDescriptorPool owner);
virtual ~DescriptorSet();
virtual void reset();
virtual void writeChanges() override;
virtual void updateConstants(const std::string& name, uint32 offset, void* data) override;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer uniformBuffer) override;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer uniformBuffer) override;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer uniformBuffer) override;
virtual void updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) override;
virtual void updateTexture(const std::string& name, uint32 index, Gfx::PTexture texture) override;
virtual void updateAccelerationStructure(const std::string& name, uint32 index, Gfx::PTopLevelAS as) override;
constexpr bool isPlainDescriptor() const { return owner->getLayout()->isPlainDescriptor(); }
constexpr MTL::ArgumentEncoder* createEncoder() const { return owner->getLayout()->createEncoder(); }
private:
PGraphics graphics;
PDescriptorPool owner;
OBufferAllocation argumentBuffer = nullptr;
MTL::ArgumentEncoder* encoder = nullptr;
Array<PCommandBoundResource> boundResources;
struct UniformWriteInfo
{
uint32 index;
@@ -102,8 +81,8 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource {
{
uint32 index;
MTL::ResourceUsage access;
PTextureHandle texture;
void apply(MTL::ArgumentEncoder* encoder) const { encoder->setTexture(texture->texture, index); }
PTextureView texture;
void apply(MTL::ArgumentEncoder* encoder) const { encoder->setTexture(texture->getHandle(), index); }
};
Array<TextureWriteInfo> textureWrites;
struct SamplerWriteInfo
@@ -122,6 +101,46 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource {
};
Array<AccelerationStructureWriteInfo> accelerationWrites;
};
DEFINE_REF(DescriptorSetHandle)
DECLARE_REF(DescriptorSet)
class DescriptorPool : public Gfx::DescriptorPool {
public:
DescriptorPool(PGraphics graphics, PDescriptorLayout layout);
virtual ~DescriptorPool();
virtual Gfx::ODescriptorSet allocateDescriptorSet() override;
virtual void reset() override;
constexpr PDescriptorLayout getLayout() const { return layout; }
private:
PGraphics graphics;
PDescriptorLayout layout;
Array<ODescriptorSetHandle> allocatedSets;
};
DEFINE_REF(DescriptorPool)
class DescriptorSet : public Gfx::DescriptorSet {
public:
DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle handle);
virtual ~DescriptorSet();
virtual void writeChanges() override;
virtual void updateConstants(const std::string& name, uint32 offset, void* data) override;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer uniformBuffer) override;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer uniformBuffer) override;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer uniformBuffer) override;
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PUniformBuffer uniformBuffer) override;
virtual void updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) override;
virtual void updateTexture(const std::string& name, uint32 index, Gfx::PTextureView texture) override;
virtual void updateAccelerationStructure(const std::string& name, uint32 index, Gfx::PTopLevelAS as) override;
constexpr bool isPlainDescriptor() const { return owner->getLayout()->isPlainDescriptor(); }
constexpr MTL::ArgumentEncoder* createEncoder() const { return owner->getLayout()->createEncoder(); }
private:
PGraphics graphics;
PDescriptorPool owner;
PDescriptorSetHandle setHandle;
friend class RenderCommand;
friend class ComputeCommand;
};
+78 -44
View File
@@ -34,7 +34,7 @@ void DescriptorLayout::create() {
MTL::ArgumentDescriptor** objects = new MTL::ArgumentDescriptor*[descriptorBindings.size()];
uint32 mappingCounter = 0;
for (uint32 i = 0; i < descriptorBindings.size(); ++i) {
if (descriptorBindings[i].descriptorType != Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER) {
if (descriptorBindings[i].descriptorType != Gfx::SE_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) {
plainDescriptor = false;
}
objects[i] = MTL::ArgumentDescriptor::alloc()->init();
@@ -58,49 +58,20 @@ void DescriptorLayout::create() {
MTL::ArgumentEncoder* DescriptorLayout::createEncoder() { return graphics->getDevice()->newArgumentEncoder(arguments); }
DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) : graphics(graphics), layout(layout) {}
DescriptorSetHandle::DescriptorSetHandle(PGraphics graphics, PDescriptorPool owner, const std::string& name)
: CommandBoundResource(graphics, name), owner(owner)
{
DescriptorPool::~DescriptorPool() {}
Gfx::PDescriptorSet DescriptorPool::allocateDescriptorSet() {
for (uint32 setIndex = 0; setIndex < allocatedSets.size(); ++setIndex) {
if (allocatedSets[setIndex]->isCurrentlyBound()) {
// Currently in use, skip
continue;
}
// Found set, stop searching
allocatedSets[setIndex]->reset();
return PDescriptorSet(allocatedSets[setIndex]);
}
allocatedSets.add(new DescriptorSet(graphics, this));
return PDescriptorSet(allocatedSets.back());
}
void DescriptorPool::reset() {}
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner)
: Gfx::DescriptorSet(owner->getLayout()), CommandBoundResource(graphics), graphics(graphics), owner(owner) {
}
DescriptorSet::~DescriptorSet() {
DescriptorSetHandle::~DescriptorSetHandle() {
if(encoder != nullptr) {
encoder->release();
}
std::cout << "destroying descriptor set" << std::endl;
}
void DescriptorSet::reset() {
boundResources.clear();
uniformWrites.clear();
bufferWrites.clear();
textureWrites.clear();
samplerWrites.clear();
accelerationWrites.clear();
}
void DescriptorSet::writeChanges() {}
void DescriptorSet::updateConstants(const std::string& name, uint32 offset, void* data) {
void DescriptorSetHandle::updateConstants(const std::string& name, uint32 offset, void* data) {
uint32 flattenedIndex = owner->getLayout()->variableMapping[name].index;
Array<uint8> contents(owner->getLayout()->variableMapping[name].constantSize);
std::memcpy(contents.data(), (uint8*)data + offset, contents.size());
@@ -110,7 +81,7 @@ void DescriptorSet::updateConstants(const std::string& name, uint32 offset, void
});
}
void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer uniformBuffer) {
void DescriptorSetHandle::updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer uniformBuffer) {
uint32 flattenedIndex = owner->getLayout()->variableMapping[name].index + index;
PShaderBuffer buffer = uniformBuffer.cast<ShaderBuffer>();
bufferWrites.add(BufferWriteInfo{
@@ -121,7 +92,7 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PSh
boundResources.add(buffer->getAlloc());
}
void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer uniformBuffer) {
void DescriptorSetHandle::updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer uniformBuffer) {
uint32 flattenedIndex = owner->getLayout()->variableMapping[name].index + index;
PVertexBuffer buffer = uniformBuffer.cast<VertexBuffer>();
bufferWrites.add(BufferWriteInfo{
@@ -132,7 +103,7 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PVe
boundResources.add(buffer->getAlloc());
}
void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer uniformBuffer) {
void DescriptorSetHandle::updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer uniformBuffer) {
uint32 flattenedIndex = owner->getLayout()->variableMapping[name].index + index;
PIndexBuffer buffer = uniformBuffer.cast<IndexBuffer>();
bufferWrites.add(BufferWriteInfo{
@@ -143,7 +114,16 @@ void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PIn
boundResources.add(buffer->getAlloc());
}
void DescriptorSet::updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) {
void DescriptorSetHandle::updateBuffer(const std::string& name, uint32 index, Gfx::PUniformBuffer uniformBuffer) {
uint32 flattenedIndex = owner->getLayout()->variableMapping[name].index + index;
PUniformBuffer buffer = uniformBuffer.cast<UniformBuffer>();
uniformWrites.add(UniformWriteInfo{
.index = flattenedIndex,
.content = buffer->getContents(),
});
}
void DescriptorSetHandle::updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) {
uint32 flattenedIndex = owner->getLayout()->variableMapping[name].index + index;
PSampler sampler = samplerState.cast<Sampler>();
samplerWrites.add(SamplerWriteInfo{
@@ -152,18 +132,72 @@ void DescriptorSet::updateSampler(const std::string& name, uint32 index, Gfx::PS
});
}
void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PTexture texture) {
void DescriptorSetHandle::updateTexture(const std::string& name, uint32 index, Gfx::PTextureView texture) {
uint32 flattenedIndex = owner->getLayout()->variableMapping[name].index + index;
PTextureBase tex = texture.cast<TextureBase>();
PTextureView tex = texture.cast<TextureView>();
textureWrites.add(TextureWriteInfo{
.index = flattenedIndex,
.texture = tex->getHandle(),
.texture = tex,
.access = owner->getLayout()->variableMapping[name].access,
});
boundResources.add(tex->getHandle());
boundResources.add(tex);
boundResources.add(tex->getSource());
}
void DescriptorSet::updateAccelerationStructure(const std::string& name, uint32 index, Gfx::PTopLevelAS as) { assert(false && "TODO"); }
void DescriptorSetHandle::updateAccelerationStructure(const std::string& , uint32 , Gfx::PTopLevelAS ){}
DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout) : graphics(graphics), layout(layout) {}
DescriptorPool::~DescriptorPool() {}
Gfx::ODescriptorSet DescriptorPool::allocateDescriptorSet() {
for (uint32 setIndex = 0; setIndex < allocatedSets.size(); ++setIndex) {
if (allocatedSets[setIndex]->isCurrentlyBound()) {
// Currently in use, skip
continue;
}
// Found set, stop searching
return new DescriptorSet(graphics, this, allocatedSets[setIndex]);
}
allocatedSets.add(new DescriptorSetHandle(graphics, this, layout->getName()));
return new DescriptorSet(graphics, this, allocatedSets.back());
}
void DescriptorPool::reset() {}
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle handle)
: Gfx::DescriptorSet(owner->getLayout()), graphics(graphics), owner(owner), setHandle(handle) {
}
DescriptorSet::~DescriptorSet() {
}
void DescriptorSet::writeChanges() {}
void DescriptorSet::updateConstants(const std::string& name, uint32 offset, void* data) {
setHandle->updateConstants(name, offset, data);
}
void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer uniformBuffer){
setHandle->updateBuffer(name, index, uniformBuffer);
}
void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer uniformBuffer){
setHandle->updateBuffer(name, index, uniformBuffer);
}
void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer uniformBuffer){
setHandle->updateBuffer(name, index, uniformBuffer);
}
void DescriptorSet::updateBuffer(const std::string& name, uint32 index, Gfx::PUniformBuffer uniformBuffer){
setHandle->updateBuffer(name, index, uniformBuffer);
}
void DescriptorSet::updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState){
setHandle->updateSampler(name, index, samplerState);
}
void DescriptorSet::updateTexture(const std::string& name, uint32 index, Gfx::PTextureView texture){
setHandle->updateTexture(name, index, texture);
}
void DescriptorSet::updateAccelerationStructure(const std::string& name, uint32 index, Gfx::PTopLevelAS as){
setHandle->updateAccelerationStructure(name, index, as);
}
PipelineLayout::PipelineLayout(PGraphics graphics, const std::string& name, Gfx::PPipelineLayout baseLayout)
: Gfx::PipelineLayout(name, baseLayout), graphics(graphics) {}
+1
View File
@@ -28,6 +28,7 @@ class Graphics : public Gfx::Graphics {
virtual void executeCommands(Array<Gfx::OComputeCommand> commands) override;
virtual Gfx::OTexture2D createTexture2D(const TextureCreateInfo& createInfo) override;
virtual Gfx::OTexture2DArray createTexture2DArray(const TextureCreateInfo& createInfo) override;
virtual Gfx::OTexture3D createTexture3D(const TextureCreateInfo& createInfo) override;
virtual Gfx::OTextureCube createTextureCube(const TextureCreateInfo& createInfo) override;
virtual Gfx::OUniformBuffer createUniformBuffer(const UniformBufferCreateInfo& bulkData) override;
+10 -14
View File
@@ -38,7 +38,8 @@ Gfx::OViewport Graphics::createViewport(Gfx::PWindow owner, const ViewportCreate
return new Viewport(owner, createInfo);
}
Gfx::ORenderPass Graphics::createRenderPass(Gfx::RenderTargetLayout layout, Array<Gfx::SubPassDependency> dependencies, URect renderArea, std::string name, Array<uint32> viewMask, Array<uint32> correlationMask) {
Gfx::ORenderPass Graphics::createRenderPass(Gfx::RenderTargetLayout layout, Array<Gfx::SubPassDependency> dependencies, URect renderArea,
std::string name, Array<uint32>, Array<uint32>) {
return new RenderPass(this, layout, dependencies, renderArea, name);
}
@@ -46,9 +47,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) { queue->getCommands
void Graphics::endRenderPass() { queue->getCommands()->endRenderPass(); }
void Graphics::waitDeviceIdle() {
queue->submitCommands();
}
void Graphics::waitDeviceIdle() { queue->submitCommands(); }
void Graphics::executeCommands(Gfx::ORenderCommand commands) {
Array<Gfx::ORenderCommand> command;
@@ -68,6 +67,8 @@ void Graphics::executeCommands(Array<Gfx::OComputeCommand> commands) { queue->ex
Gfx::OTexture2D Graphics::createTexture2D(const TextureCreateInfo& createInfo) { return new Texture2D(this, createInfo); }
Gfx::OTexture2DArray Graphics::createTexture2DArray(const TextureCreateInfo& createInfo) { return new Texture2DArray(this, createInfo); }
Gfx::OTexture3D Graphics::createTexture3D(const TextureCreateInfo& createInfo) { return new Texture3D(this, createInfo); }
Gfx::OTextureCube Graphics::createTextureCube(const TextureCreateInfo& createInfo) { return new TextureCube(this, createInfo); }
@@ -155,23 +156,18 @@ void Graphics::beginDebugRegion(const std::string& name) {
queue->getCommands()->getHandle()->pushDebugGroup(NS::String::string(name.c_str(), NS::ASCIIStringEncoding));
}
void Graphics::endDebugRegion() {
queue->getCommands()->getHandle()->popDebugGroup();
}
void Graphics::endDebugRegion() { queue->getCommands()->getHandle()->popDebugGroup(); }
void Graphics::resolveTexture(Gfx::PTexture, Gfx::PTexture) {}
void Graphics::copyTexture(Gfx::PTexture, Gfx::PTexture) {}
void Graphics::copyTexture(Gfx::PTexture, Gfx::PTexture) { assert(false); }
void Graphics::copyBuffer(Gfx::PShaderBuffer src, Gfx::PShaderBuffer dst)
{
// TODO blit commands
}
void Graphics::copyBuffer(Gfx::PShaderBuffer, Gfx::PShaderBuffer) { assert(false); }
// Ray Tracing
Gfx::OBottomLevelAS Graphics::createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo& createInfo) { return nullptr; }
Gfx::OBottomLevelAS Graphics::createBottomLevelAccelerationStructure(const Gfx::BottomLevelASCreateInfo&) { return nullptr; }
Gfx::OTopLevelAS Graphics::createTopLevelAccelerationStructure(const Gfx::TopLevelASCreateInfo& createInfo) { return nullptr; }
Gfx::OTopLevelAS Graphics::createTopLevelAccelerationStructure(const Gfx::TopLevelASCreateInfo&) { return nullptr; }
void Graphics::buildBottomLevelAccelerationStructures(Array<Gfx::PBottomLevelAS>) {}
+6 -6
View File
@@ -88,11 +88,11 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::LegacyPipelineCreateInfo cr
}
MTL::DepthStencilDescriptor* depthDescriptor = MTL::DepthStencilDescriptor::alloc()->init();
if (createInfo.renderPass->getLayout().depthAttachment.getTexture() != nullptr) {
if (createInfo.renderPass->getLayout().depthAttachment.getTextureView() != nullptr) {
depthDescriptor->setDepthWriteEnabled(createInfo.depthStencilState.depthWriteEnable);
depthDescriptor->setDepthCompareFunction(cast(createInfo.depthStencilState.depthCompareOp));
pipelineDescriptor->setDepthAttachmentPixelFormat(
cast(createInfo.renderPass->getLayout().depthAttachment.getTexture().cast<Texture2D>()->getFormat()));
cast(createInfo.renderPass->getLayout().depthAttachment.getTextureView()->getFormat()));
}
pipelineDescriptor->setAlphaToCoverageEnabled(createInfo.multisampleState.alphaCoverageEnable);
pipelineDescriptor->setAlphaToOneEnabled(createInfo.multisampleState.alphaToOneEnable);
@@ -196,11 +196,11 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo crea
pipelineDescriptor->colorAttachments()->setObject(desc, c);
}
MTL::DepthStencilDescriptor* depthDescriptor = MTL::DepthStencilDescriptor::alloc()->init();
if (createInfo.renderPass->getLayout().depthAttachment.getTexture() != nullptr) {
if (createInfo.renderPass->getLayout().depthAttachment.getTextureView() != nullptr) {
depthDescriptor->setDepthWriteEnabled(createInfo.depthStencilState.depthWriteEnable);
depthDescriptor->setDepthCompareFunction(cast(createInfo.depthStencilState.depthCompareOp));
pipelineDescriptor->setDepthAttachmentPixelFormat(
cast(createInfo.renderPass->getLayout().depthAttachment.getTexture().cast<Texture2D>()->getFormat()));
cast(createInfo.renderPass->getLayout().depthAttachment.getTextureView()->getFormat()));
}
pipelineDescriptor->setAlphaToCoverageEnabled(createInfo.multisampleState.alphaCoverageEnable);
pipelineDescriptor->setAlphaToOneEnabled(createInfo.multisampleState.alphaToOneEnable);
@@ -209,9 +209,9 @@ PGraphicsPipeline PipelineCache::createPipeline(Gfx::MeshPipelineCreateInfo crea
MTL::DepthStencilState* depthState = graphics->getDevice()->newDepthStencilState(depthDescriptor);
depthDescriptor->release();
if (createInfo.renderPass->getLayout().depthAttachment.getTexture() != nullptr) {
if (createInfo.renderPass->getLayout().depthAttachment.getTextureView() != nullptr) {
pipelineDescriptor->setDepthAttachmentPixelFormat(
cast(createInfo.renderPass->getLayout().depthAttachment.getTexture().cast<Texture2D>()->getFormat()));
cast(createInfo.renderPass->getLayout().depthAttachment.getTextureView()->getFormat()));
}
pipelineDescriptor->setAlphaToCoverageEnabled(createInfo.multisampleState.alphaCoverageEnable);
pipelineDescriptor->setAlphaToOneEnabled(createInfo.multisampleState.alphaToOneEnable);
-1
View File
@@ -5,7 +5,6 @@
#include "Enums.h"
#include "Graphics.h"
#include "Graphics/Query.h"
#include <vulkan/vulkan_core.h>
using namespace Seele;
using namespace Seele::Metal;
+8 -8
View File
@@ -33,13 +33,13 @@ RenderPass::RenderPass(PGraphics graphics, Gfx::RenderTargetLayout _layout, Arra
}
}
}
if (layout.depthAttachment.getTexture() != nullptr) {
if (layout.depthAttachment.getTextureView() != nullptr) {
auto depth = renderPass->depthAttachment();
depth->setClearDepth(layout.depthAttachment.clear.depthStencil.depth);
depth->setLoadAction(cast(layout.depthAttachment.getLoadOp()));
depth->setStoreAction(cast(layout.depthAttachment.getStoreOp()));
if (layout.depthResolveAttachment.getTexture() != nullptr) {
if (layout.depthResolveAttachment.getTextureView() != nullptr) {
// store multisampled attachment as well
if(layout.depthAttachment.getStoreOp() == Gfx::SE_ATTACHMENT_STORE_OP_STORE) {
depth->setStoreAction(MTL::StoreActionStoreAndMultisampleResolve);
@@ -56,17 +56,17 @@ void RenderPass::updateRenderPass() {
for (size_t i = 0; i < layout.colorAttachments.size(); ++i) {
const auto& color = layout.colorAttachments[i];
auto desc = renderPass->colorAttachments()->object(i);
desc->setTexture(color.getTexture().cast<TextureBase>()->getImage());
desc->setTexture(color.getTextureView().cast<TextureView>()->getHandle());
if (!layout.resolveAttachments.empty()) {
const auto& resolve = layout.resolveAttachments[i];
desc->setResolveTexture(resolve.getTexture().cast<TextureBase>()->getImage());
desc->setResolveTexture(resolve.getTextureView().cast<TextureView>()->getHandle());
}
}
if (layout.depthAttachment.getTexture() != nullptr) {
if (layout.depthAttachment.getTextureView() != nullptr) {
auto depth = renderPass->depthAttachment();
depth->setTexture(layout.depthAttachment.getTexture().cast<TextureBase>()->getImage());
if (layout.depthResolveAttachment.getTexture() != nullptr) {
depth->setResolveTexture(layout.depthResolveAttachment.getTexture().cast<TextureBase>()->getImage());
depth->setTexture(layout.depthAttachment.getTextureView().cast<TextureView>()->getHandle());
if (layout.depthResolveAttachment.getTextureView() != nullptr) {
depth->setResolveTexture(layout.depthResolveAttachment.getTextureView().cast<TextureView>()->getHandle());
}
}
}
+13 -4
View File
@@ -5,6 +5,7 @@
#include <Foundation/Foundation.hpp>
#include <Metal/Metal.hpp>
#include <QuartzCore/QuartzCore.hpp>
#include <iostream>
namespace Seele {
namespace Metal {
@@ -25,18 +26,26 @@ class DestructionManager {
DEFINE_REF(DestructionManager)
class CommandBoundResource {
public:
CommandBoundResource(PGraphics graphics) : graphics(graphics) {}
public:
CommandBoundResource(PGraphics graphics, const std::string& name) : graphics(graphics), name(name) {}
virtual ~CommandBoundResource() {
if (isCurrentlyBound())
abort();
}
constexpr bool isCurrentlyBound() const { return bindCount > 0; }
constexpr void bind() { bindCount++; }
constexpr void unbind() { bindCount--; }
void bind() { bindCount++;
std::cout << "Bind " << bindCount << " " << name << std::endl;
}
void unbind() { bindCount--;
std::cout << "Unbind " << bindCount << " " << name << std::endl;
}
const std::string& getName() const {
return name;
}
protected:
PGraphics graphics;
std::string name;
uint64 bindCount = 0;
};
DEFINE_REF(CommandBoundResource)
+64 -1
View File
@@ -7,7 +7,38 @@
namespace Seele {
namespace Metal {
class TextureHandle : public CommandBoundResource{
DECLARE_REF(TextureHandle)
class TextureView : public Gfx::TextureView, public CommandBoundResource {
public:
TextureView(PGraphics graphics, PTextureHandle source, uint32 width, uint32 height, uint32 numLayers, uint32 numMipLevels, MTL::Texture* view);
virtual ~TextureView();
virtual Gfx::SeFormat getFormat() const override;
virtual uint32 getWidth() const override;
virtual uint32 getHeight() const override;
virtual uint32 getDepth() const override;
virtual uint32 getNumLayers() const override;
virtual Gfx::SeSampleCountFlags getNumSamples() const override;
virtual uint32 getMipLevels() const override;
virtual void pipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
Gfx::SePipelineStageFlags dstStage) override;
virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
MTL::Texture* getHandle() const { return view; }
PTextureHandle getSource() const { return source;}
private:
uint32 width;
uint32 height;
uint32 numLayers;
uint32 numMipLevels;
PTextureHandle source;
MTL::Texture* view;
friend class TextureBase;
};
DEFINE_REF(TextureView)
class TextureHandle : public CommandBoundResource {
public:
TextureHandle(PGraphics graphics, MTL::TextureType type, const TextureCreateInfo& createInfo, MTL::Texture* existingImage);
virtual ~TextureHandle();
@@ -18,8 +49,10 @@ class TextureHandle : public CommandBoundResource{
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage);
void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer);
void generateMipmaps();
Gfx::OTextureView createTextureView(uint32 baseMipLevel, uint32 levelCount, uint32 baseArrayLayer, uint32 layerCount);
MTL::Texture* texture;
OTextureView textureView;
MTL::TextureType type;
uint32 width;
uint32 height;
@@ -87,6 +120,8 @@ class Texture2D : public Gfx::Texture2D, public TextureBase {
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void generateMipmaps() override;
virtual Gfx::PTextureView getDefaultView() const override;
virtual Gfx::OTextureView createTextureView(uint32 baseMipLevel, uint32 levelCount, uint32 baseArrayLayer, uint32 layerCount) override;
protected:
// Inherited via QueueOwnedResource
@@ -95,7 +130,31 @@ class Texture2D : public Gfx::Texture2D, public TextureBase {
Gfx::SePipelineStageFlags dstStage) override;
};
DEFINE_REF(Texture2D)
class Texture2DArray : public Gfx::Texture2DArray, public TextureBase {
public:
Texture2DArray(PGraphics graphics, const TextureCreateInfo& createInfo, MTL::Texture* existingImage = nullptr);
virtual ~Texture2DArray();
virtual uint32 getWidth() const override { return handle->width; }
virtual uint32 getHeight() const override { return handle->height; }
virtual uint32 getDepth() const override { return handle->depth; }
virtual uint32 getNumLayers() const override { return handle->arrayCount; }
virtual Gfx::SeFormat getFormat() const override { return handle->format; }
virtual Gfx::SeSampleCountFlags getNumSamples() const override { return handle->samples; }
virtual uint32 getMipLevels() const override { return handle->mipLevels; }
virtual void changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void generateMipmaps() override;
virtual Gfx::PTextureView getDefaultView() const override;
virtual Gfx::OTextureView createTextureView(uint32 baseMipLevel, uint32 levelCount, uint32 baseArrayLayer, uint32 layerCount) override;
protected:
// Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) override;
virtual void executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
Gfx::SePipelineStageFlags dstStage) override;
};
DEFINE_REF(Texture2DArray)
class Texture3D : public Gfx::Texture3D, public TextureBase {
public:
Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo);
@@ -111,6 +170,8 @@ class Texture3D : public Gfx::Texture3D, public TextureBase {
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void generateMipmaps() override;
virtual Gfx::PTextureView getDefaultView() const override;
virtual Gfx::OTextureView createTextureView(uint32 baseMipLevel, uint32 levelCount, uint32 baseArrayLayer, uint32 layerCount) override;
protected:
// Inherited via QueueOwnedResource
@@ -135,6 +196,8 @@ class TextureCube : public Gfx::TextureCube, public TextureBase {
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) override;
virtual void download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) override;
virtual void generateMipmaps() override;
virtual Gfx::PTextureView getDefaultView() const override;
virtual Gfx::OTextureView createTextureView(uint32 baseMipLevel, uint32 levelCount, uint32 baseArrayLayer, uint32 layerCount) override;
protected:
// Inherited via QueueOwnedResource
+111 -15
View File
@@ -1,10 +1,10 @@
#include "Texture.h"
#include "Command.h"
#include "Enums.h"
#include "Graphics/Enums.h"
#include "Graphics/Initializer.h"
#include "Graphics/Metal/Buffer.h"
#include "Graphics/Metal/Graphics.h"
#include "Command.h"
#include "Graphics/Metal/Resources.h"
#include "Metal/MTLTexture.hpp"
#include "Metal/MTLTypes.hpp"
@@ -12,9 +12,54 @@
using namespace Seele;
using namespace Seele::Metal;
TextureView::TextureView(PGraphics graphics, PTextureHandle source, uint32 width, uint32 height, uint32 numLayers, uint32 numMipLevels, MTL::Texture* view)
: CommandBoundResource(graphics, source->getName()), width(width), height(height), numLayers(numLayers), numMipLevels(numMipLevels), source(source), view(view) {}
TextureView::~TextureView() {}
Gfx::SeFormat TextureView::getFormat() const { return source->format; }
uint32 TextureView::getWidth() const { return width; }
uint32 TextureView::getHeight() const { return height; }
uint32 TextureView::getDepth() const { return source->depth; }
uint32 TextureView::getNumLayers() const { return numLayers; }
Gfx::SeSampleCountFlags TextureView::getNumSamples() const { return source->samples; }
uint32 TextureView::getMipLevels() const { return numMipLevels; }
void TextureView::pipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
Gfx::SePipelineStageFlags dstStage) {
return source->pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
}
void TextureView::changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {
return source->changeLayout(newLayout, srcAccess, srcStage, dstAccess, dstStage);
}
Gfx::OTextureView TextureHandle::createTextureView(uint32 baseMipLevel, uint32 viewLevelCount, uint32 baseArrayLayer,
uint32 viewLayerCount) {
MTL::Texture* viewTexture;
if(viewLevelCount > 1)
{
viewTexture = texture->newTextureView(cast(format), type, NS::Range(baseMipLevel, viewLevelCount), NS::Range(baseArrayLayer, viewLayerCount));
}
else
{
viewTexture = texture->newTextureView(cast(format));
}
uint32 viewWidth = width * std::pow(0.5, baseMipLevel);
uint32 viewHeight = height * std::pow(0.5, baseMipLevel);
return new TextureView(graphics, this, viewWidth, viewHeight, viewLayerCount, viewLevelCount, viewTexture);
}
TextureHandle::TextureHandle(PGraphics graphics, MTL::TextureType type, const TextureCreateInfo& createInfo, MTL::Texture* existingImage)
: CommandBoundResource(graphics), texture(existingImage), type(type), width(createInfo.width), height(createInfo.height), depth(createInfo.depth),
arrayCount(createInfo.elements), mipLevels(1), samples(createInfo.samples), format(createInfo.format),
: CommandBoundResource(graphics, createInfo.name), texture(existingImage), type(type), width(createInfo.width), height(createInfo.height),
depth(createInfo.depth), arrayCount(createInfo.elements), mipLevels(1), samples(createInfo.samples), format(createInfo.format),
usage(createInfo.usage), layout(Gfx::SE_IMAGE_LAYOUT_UNDEFINED), ownsImage(existingImage == nullptr) {
if (createInfo.useMip) {
mipLevels = static_cast<uint32_t>(std::floor(std::log2(std::max(width, height)))) + 1;
@@ -41,7 +86,7 @@ TextureHandle::TextureHandle(PGraphics graphics, MTL::TextureType type, const Te
descriptor->setSampleCount(samples);
descriptor->setUsage(mtlUsage);
descriptor->setStorageMode(MTL::StorageModePrivate);
if(usage & Gfx::SE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
if (usage & Gfx::SE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
descriptor->setStorageMode(MTL::StorageModeMemoryless);
}
@@ -50,28 +95,30 @@ TextureHandle::TextureHandle(PGraphics graphics, MTL::TextureType type, const Te
descriptor->release();
}
if(createInfo.sourceData.data != nullptr)
{
OBufferAllocation stagingBuffer = new BufferAllocation(graphics, "TextureStaging", createInfo.sourceData.size, MTL::ResourceStorageModeShared);
if (createInfo.sourceData.data != nullptr) {
OBufferAllocation stagingBuffer =
new BufferAllocation(graphics, "TextureStaging", createInfo.sourceData.size, MTL::ResourceStorageModeShared);
std::memcpy(stagingBuffer->map(), createInfo.sourceData.data, createInfo.sourceData.size);
MTL::BlitCommandEncoder* blitEnc = graphics->getQueue()->getCommands()->getBlitEncoder();
uint32 sliceSize = createInfo.sourceData.size / arrayCount;
uint32 numSlices = arrayCount;
if(type == MTL::TextureTypeCube || type == MTL::TextureTypeCubeArray) {
if (type == MTL::TextureTypeCube || type == MTL::TextureTypeCubeArray) {
sliceSize /= 6;
numSlices *= 6;
}
uint32 offset = 0;
for(uint32 slice = 0; slice < numSlices; ++slice){
blitEnc->copyFromBuffer(stagingBuffer->buffer, offset, sliceSize / createInfo.height, arrayCount == 1 ? 0 : sliceSize, MTL::Size(createInfo.width, createInfo.height, createInfo.depth), texture, slice, 0, MTL::Origin());
for (uint32 slice = 0; slice < numSlices; ++slice) {
blitEnc->copyFromBuffer(stagingBuffer->buffer, offset, sliceSize / createInfo.height, arrayCount == 1 ? 0 : sliceSize,
MTL::Size(createInfo.width, createInfo.height, createInfo.depth), texture, slice, 0, MTL::Origin());
offset += sliceSize;
}
if(mipLevels > 1) {
if (mipLevels > 1) {
blitEnc->generateMipmaps(texture);
}
graphics->getQueue()->getCommands()->bindResource(PBufferAllocation(stagingBuffer));
graphics->getDestructionManager()->queueResourceForDestruction(std::move(stagingBuffer));
}
textureView = new TextureView(graphics, this, width, height, arrayCount, mipLevels, texture);
}
TextureHandle::~TextureHandle() {
@@ -85,7 +132,7 @@ void TextureHandle::pipelineBarrier(Gfx::SeAccessFlags, Gfx::SePipelineStageFlag
void TextureHandle::changeLayout(Gfx::SeImageLayout, Gfx::SeAccessFlags, Gfx::SePipelineStageFlags, Gfx::SeAccessFlags,
Gfx::SePipelineStageFlags) {}
void TextureHandle::transferOwnership(Gfx::QueueType newOwner) {}
void TextureHandle::transferOwnership(Gfx::QueueType) {}
void TextureHandle::download(uint32, uint32, uint32, Array<uint8>&) {}
@@ -94,9 +141,7 @@ void TextureHandle::generateMipmaps() {}
TextureBase::TextureBase(PGraphics graphics, MTL::TextureType viewType, const TextureCreateInfo& createInfo, MTL::Texture* existingImage)
: handle(new TextureHandle(graphics, viewType, createInfo, existingImage)), graphics(graphics) {}
TextureBase::~TextureBase() {
graphics->getDestructionManager()->queueResourceForDestruction(std::move(handle));
}
TextureBase::~TextureBase() { graphics->getDestructionManager()->queueResourceForDestruction(std::move(handle)); }
void TextureBase::pipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
Gfx::SePipelineStageFlags dstStage) {
@@ -132,6 +177,12 @@ void Texture2D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<
void Texture2D::generateMipmaps() { TextureBase::generateMipmaps(); }
Gfx::PTextureView Texture2D::getDefaultView() const { return PTextureView(handle->textureView); }
Gfx::OTextureView Texture2D::createTextureView(uint32 baseMipLevel, uint32 levelCount, uint32 baseArrayLayer, uint32 layerCount) {
return handle->createTextureView(baseMipLevel, levelCount, baseArrayLayer, layerCount);
}
void Texture2D::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::transferOwnership(newOwner); }
void Texture2D::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
@@ -139,6 +190,39 @@ void Texture2D::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipe
TextureBase::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
}
Texture2DArray::Texture2DArray(PGraphics graphics, const TextureCreateInfo& createInfo, MTL::Texture* existingImage)
: Gfx::Texture2DArray(graphics->getFamilyMapping()),
TextureBase(graphics,
createInfo.elements > 1 ? (createInfo.samples > 1 ? MTL::TextureType2DMultisampleArray : MTL::TextureType2DArray)
: (createInfo.samples > 1 ? MTL::TextureType2DMultisample : MTL::TextureType2D),
createInfo, existingImage) {}
Texture2DArray::~Texture2DArray() {}
void Texture2DArray::changeLayout(Gfx::SeImageLayout newLayout, Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage,
Gfx::SeAccessFlags dstAccess, Gfx::SePipelineStageFlags dstStage) {
TextureBase::changeLayout(newLayout, srcAccess, srcStage, dstAccess, dstStage);
}
void Texture2DArray::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<uint8>& buffer) {
TextureBase::download(mipLevel, arrayLayer, face, buffer);
}
void Texture2DArray::generateMipmaps() { TextureBase::generateMipmaps(); }
Gfx::PTextureView Texture2DArray::getDefaultView() const { return PTextureView(handle->textureView); }
Gfx::OTextureView Texture2DArray::createTextureView(uint32 baseMipLevel, uint32 levelCount, uint32 baseArrayLayer, uint32 layerCount) {
return handle->createTextureView(baseMipLevel, levelCount, baseArrayLayer, layerCount);
}
void Texture2DArray::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::transferOwnership(newOwner); }
void Texture2DArray::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
Gfx::SePipelineStageFlags dstStage) {
TextureBase::pipelineBarrier(srcAccess, srcStage, dstAccess, dstStage);
}
Texture3D::Texture3D(PGraphics graphics, const TextureCreateInfo& createInfo)
: Gfx::Texture3D(graphics->getFamilyMapping()), TextureBase(graphics, MTL::TextureType3D, createInfo) {}
@@ -155,6 +239,12 @@ void Texture3D::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Array<
void Texture3D::generateMipmaps() { TextureBase::generateMipmaps(); }
Gfx::PTextureView Texture3D::getDefaultView() const { return PTextureView(handle->textureView); }
Gfx::OTextureView Texture3D::createTextureView(uint32 baseMipLevel, uint32 levelCount, uint32 baseArrayLayer, uint32 layerCount) {
return handle->createTextureView(baseMipLevel, levelCount, baseArrayLayer, layerCount);
}
void Texture3D::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::transferOwnership(newOwner); }
void Texture3D::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
@@ -179,6 +269,12 @@ void TextureCube::download(uint32 mipLevel, uint32 arrayLayer, uint32 face, Arra
void TextureCube::generateMipmaps() { TextureBase::generateMipmaps(); }
Gfx::PTextureView TextureCube::getDefaultView() const { return PTextureView(handle->textureView); }
Gfx::OTextureView TextureCube::createTextureView(uint32 baseMipLevel, uint32 levelCount, uint32 baseArrayLayer, uint32 layerCount) {
return handle->createTextureView(baseMipLevel, levelCount, baseArrayLayer, layerCount);
}
void TextureCube::executeOwnershipBarrier(Gfx::QueueType newOwner) { TextureBase::transferOwnership(newOwner); }
void TextureCube::executePipelineBarrier(Gfx::SeAccessFlags srcAccess, Gfx::SePipelineStageFlags srcStage, Gfx::SeAccessFlags dstAccess,
+132 -82
View File
@@ -13,6 +13,9 @@
#include "Math/Matrix.h"
#include "Math/Vector.h"
#include "MinimalEngine.h"
#include "Scene/LightEnvironment.h"
#include "Scene/Scene.h"
#include "ShadowPass.h"
using namespace Seele;
@@ -41,7 +44,27 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics)
});
lightCullingLayout->create();
shadowMappingLayout = graphics->createDescriptorLayout("pShadowMapping");
shadowMappingLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = SHADOWMAPS_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
.descriptorCount = NUM_CASCADES,
});
shadowMappingLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = LIGHTSPACE_NAME,
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
.descriptorCount = NUM_CASCADES,
});
shadowMappingLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.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->create();
basePassLayout->addDescriptorLayout(lightCullingLayout);
basePassLayout->addDescriptorLayout(shadowMappingLayout);
basePassLayout->addPushConstants(Gfx::SePushConstantRange{
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
.offset = 0,
@@ -79,6 +102,70 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics)
.fogColor = Vector(0, 0, 0),
.blendFactor = 0,
};
shadowSampler = graphics->createSampler(SamplerCreateInfo{
.magFilter = Gfx::SE_FILTER_LINEAR,
.minFilter = Gfx::SE_FILTER_LINEAR,
.mipmapMode = Gfx::SE_SAMPLER_MIPMAP_MODE_LINEAR,
.addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeW = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.mipLodBias = 0.0f,
.maxAnisotropy = 1.0f,
.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() {}
@@ -140,12 +227,22 @@ void BasePass::render() {
opaqueCulling->writeChanges();
transparentCulling->writeChanges();
shadowMappingLayout->reset();
shadowMapping = shadowMappingLayout->allocateDescriptorSet();
for (uint32 i = 0; i < NUM_CASCADES; ++i) {
shadowMapping->updateTexture(SHADOWMAPS_NAME, i, shadowMaps[i]->getDefaultView());
shadowMapping->updateBuffer(LIGHTSPACE_NAME, i, lightSpaceMatrices[i]);
}
shadowMapping->updateSampler(SHADOWSAMPLER_NAME, 0, shadowSampler);
shadowMapping->updateBuffer(CASCADE_SPLIT_NAME, 0, cascadeSplits);
shadowMapping->writeChanges();
query->beginQuery();
timestamps->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "BaseBegin");
graphics->beginRenderPass(renderPass);
Array<VertexData::TransparentDraw> transparentData;
// Opaque
{
graphics->beginDebugRegion("Opaque");
Array<Gfx::ORenderCommand> commands;
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("BasePass");
permutation.setDepthCulling(true); // always use the culling info
@@ -176,7 +273,7 @@ void BasePass::render() {
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
//bool twoSided = materialData.material->isTwoSided();
// bool twoSided = materialData.material->isTwoSided();
if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = {
@@ -221,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(), 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,
@@ -241,7 +339,6 @@ void BasePass::render() {
}
}
graphics->executeCommands(std::move(commands));
graphics->endDebugRegion();
}
// commands.add(waterRenderer->render(viewParamsSet));
@@ -249,18 +346,15 @@ void BasePass::render() {
// Skybox
{
graphics->beginDebugRegion("Skybox");
Gfx::ORenderCommand skyboxCommand = graphics->createRenderCommand("SkyboxRender");
skyboxCommand->setViewport(viewport);
skyboxCommand->bindPipeline(skyboxPipeline);
skyboxCommand->bindDescriptor({viewParamsSet, skyboxDataSet, textureSet});
skyboxCommand->draw(36, 1, 0, 0);
graphics->executeCommands(std::move(skyboxCommand));
graphics->endDebugRegion();
}
// Transparent rendering
{
graphics->beginDebugRegion("Transparent");
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("BasePass");
permutation.setPositionOnly(false);
permutation.setDepthCulling(false); // ignore visibility infos for transparency
@@ -280,7 +374,7 @@ void BasePass::render() {
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
assert(collection != nullptr);
//bool twoSided = t.matInst->getBaseMaterial()->isTwoSided();
// bool twoSided = t.matInst->getBaseMaterial()->isTwoSided();
if (graphics->supportMeshShading()) {
Gfx::MeshPipelineCreateInfo pipelineInfo = {
@@ -324,10 +418,6 @@ void BasePass::render() {
{
.cullMode = Gfx::SE_CULL_MODE_BACK_BIT,
},
.depthStencilState =
{
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER_OR_EQUAL,
},
.colorBlend =
{
.attachmentCount = 1,
@@ -344,7 +434,7 @@ void BasePass::render() {
}
transparentCommand->bindDescriptor({viewParamsSet, t.vertexData->getVertexDataSet(), t.vertexData->getInstanceDataSet(),
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(),
transparentCulling});
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);
@@ -360,11 +450,9 @@ void BasePass::render() {
}
}
graphics->executeCommands(std::move(transparentCommand));
graphics->endDebugRegion();
}
// Debug vertices
if (gDebugVertices.size() > 0) {
graphics->beginDebugRegion("Debug");
Gfx::ShaderPermutation permutation = graphics->getShaderCompiler()->getTemplate("BasePass");
permutation.setDepthCulling(true); // always use the culling info
permutation.setPositionOnly(false);
@@ -375,7 +463,6 @@ void BasePass::render() {
debugCommand->bindVertexBuffer({debugVertices});
debugCommand->draw((uint32)gDebugVertices.size(), 1, 0, 0);
graphics->executeCommands(std::move(debugCommand));
graphics->endDebugRegion();
}
graphics->endRenderPass();
@@ -422,18 +509,18 @@ void BasePass::publishOutputs() {
Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
msDepthAttachment =
Gfx::RenderTargetAttachment(msBasePassDepth->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);
msDepthAttachment = Gfx::RenderTargetAttachment(msBasePassDepth->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);
msDepthAttachment.clear.depthStencil.depth = 0.0f;
colorAttachment =
Gfx::RenderTargetAttachment(basePassColor->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE, Gfx::SE_ATTACHMENT_STORE_OP_STORE);
colorAttachment = Gfx::RenderTargetAttachment(basePassColor->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_DONT_CARE,
Gfx::SE_ATTACHMENT_STORE_OP_STORE);
msColorAttachment =
Gfx::RenderTargetAttachment(msBasePassColor->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED, Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_DONT_CARE);
msColorAttachment = Gfx::RenderTargetAttachment(msBasePassColor->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR,
Gfx::SE_ATTACHMENT_STORE_OP_DONT_CARE);
msColorAttachment.clear.color.float32[0] = 0;
msColorAttachment.clear.color.float32[1] = 1;
msColorAttachment.clear.color.float32[2] = 0;
@@ -442,7 +529,6 @@ void BasePass::publishOutputs() {
resources->registerRenderPassOutput("BASEPASS_COLOR", colorAttachment);
resources->registerRenderPassOutput("BASEPASS_DEPTH", depthAttachment);
timestamps = graphics->createTimestampQuery(2, "BaseTS");
query = graphics->createPipelineStatisticsQuery("BasePassPipelineStatistics");
resources->registerQueryOutput("BASEPASS_QUERY", query);
}
@@ -452,6 +538,11 @@ void BasePass::createRenderPass() {
// terrainRenderer = new TerrainRenderer(graphics, scene, viewParamsLayout, viewParamsSet);
cullingBuffer = resources->requestBuffer("CULLINGBUFFER");
timestamps = resources->requestTimestampQuery("TIMESTAMPS");
for (uint32 i = 0; i < NUM_CASCADES; ++i) {
shadowMaps[i] = resources->requestTexture(fmt::format("SHADOWMAP_TEXTURE{0}", i));
lightSpaceMatrices[i] = resources->requestBuffer(fmt::format("SHADOWMAP_LIGHTSPACE{0}", i));
}
cascadeSplits = resources->requestUniform("SHADOWMAP_CASCADESPLITS");
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.colorAttachments = {msColorAttachment},
@@ -496,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 =
{
@@ -565,50 +638,22 @@ 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,
skyboxSampler = graphics->createSampler({
.magFilter = Gfx::SE_FILTER_LINEAR,
.minFilter = Gfx::SE_FILTER_LINEAR,
.mipmapMode = Gfx::SE_SAMPLER_MIPMAP_MODE_LINEAR,
.addressModeU = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeV = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.addressModeW = Gfx::SE_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
.maxAnisotropy = 1.0f,
.minLod = 0,
.maxLod = std::numeric_limits<float>::max(),
});
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({});
skyboxData.transformMatrix = Matrix4(1);
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,
@@ -623,6 +668,11 @@ void BasePass::createRenderPass() {
{
.polygonMode = Gfx::SE_POLYGON_MODE_FILL,
},
.depthStencilState =
{
.depthTestEnable = true,
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
},
.colorBlend =
{
.attachmentCount = 1,
+21 -6
View File
@@ -1,7 +1,10 @@
#pragma once
#include "Graphics/Buffer.h"
#include "Graphics/Descriptor.h"
#include "Graphics/RenderPass/ShadowPass.h"
#include "Component/Skybox.h"
#include "MinimalEngine.h"
#include "RenderPass.h"
#include "WaterRenderer.h"
namespace Seele {
DECLARE_REF(CameraActor)
@@ -30,9 +33,14 @@ class BasePass : public RenderPass {
Gfx::PTexture2D tLightGrid;
constexpr static const char* LIGHTINDEX_NAME = "lightIndexList";
constexpr static const char* LIGHTGRID_NAME = "lightGrid";
constexpr static const char* SHADOWMAPS_NAME = "shadowMaps";
constexpr static const char* LIGHTSPACE_NAME = "lightSpaceMatrices";
constexpr static const char* SHADOWSAMPLER_NAME = "shadowSampler";
constexpr static const char* CASCADE_SPLIT_NAME = "cascadeSplit";
Gfx::PDescriptorSet opaqueCulling;
Gfx::PDescriptorSet transparentCulling;
Gfx::ODescriptorSet opaqueCulling;
Gfx::ODescriptorSet transparentCulling;
Gfx::ODescriptorSet shadowMapping;
// use a different texture here so we can do multisampling
Gfx::OTexture2D msBasePassDepth;
@@ -44,11 +52,12 @@ class BasePass : public RenderPass {
// used for transparency sorting
Vector cameraPos;
Vector cameraForward;
Gfx::PDescriptorSet viewParamsSet;
Gfx::ODescriptorSet viewParamsSet;
PCameraActor source;
Gfx::OPipelineLayout basePassLayout;
Gfx::ODescriptorLayout lightCullingLayout;
Gfx::ODescriptorLayout shadowMappingLayout;
Gfx::OPipelineStatisticsQuery query;
Gfx::PTimestampQuery timestamps;
@@ -58,6 +67,12 @@ class BasePass : public RenderPass {
//OWaterRenderer waterRenderer;
//OTerrainRenderer terrainRenderer;
// Shadow mapping
Gfx::PTexture2D shadowMaps[NUM_CASCADES];
Gfx::PShaderBuffer lightSpaceMatrices[NUM_CASCADES];
Gfx::OSampler shadowSampler;
Gfx::PUniformBuffer cascadeSplits;
// Debug rendering
Gfx::OVertexInput debugVertexInput;
Gfx::OVertexBuffer debugVertices;
@@ -68,9 +83,9 @@ class BasePass : public RenderPass {
// Skybox
Gfx::ODescriptorLayout skyboxDataLayout;
Gfx::PDescriptorSet skyboxDataSet;
Gfx::ODescriptorSet skyboxDataSet;
Gfx::ODescriptorLayout textureLayout;
Gfx::PDescriptorSet textureSet;
Gfx::ODescriptorSet textureSet;
Gfx::OVertexShader vertexShader;
Gfx::OFragmentShader fragmentShader;
Gfx::OPipelineLayout pipelineLayout;
@@ -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)
@@ -11,6 +11,7 @@ CachedDepthPass::CachedDepthPass(Gfx::PGraphics graphics, PScene scene) : Render
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
.size = sizeof(VertexData::DrawCallOffsets),
.name = "pOffsets"
});
if (graphics->supportMeshShading()) {
graphics->getShaderCompiler()->registerRenderPass("CachedDepthPass", Gfx::PassConfig{
@@ -1,6 +1,7 @@
#pragma once
#include "RenderPass.h"
#include "Graphics/Query.h"
#include "Scene/Scene.h"
namespace Seele {
class CachedDepthPass : public RenderPass {
@@ -24,7 +25,7 @@ class CachedDepthPass : public RenderPass {
Gfx::OPipelineStatisticsQuery query;
Gfx::OTimestampQuery timestamps;
Gfx::PDescriptorSet viewParamsSet;
Gfx::ODescriptorSet viewParamsSet;
Gfx::PShaderBuffer cullingBuffer;
PScene scene;
};
@@ -25,6 +25,7 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
.size = sizeof(VertexData::DrawCallOffsets),
.name = "pOffsets"
});
depthComputeLayout = graphics->createPipelineLayout("DepthComputeLayout");
@@ -34,7 +35,26 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
.stageFlags = Gfx::SE_SHADER_STAGE_COMPUTE_BIT,
.offset = 0,
.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{
@@ -72,7 +92,7 @@ void DepthCullingPass::beginFrame(const Component::Camera& cam, const Component:
void DepthCullingPass::render() {
graphics->beginDebugRegion("DepthCullingPass");
Gfx::PDescriptorSet set = depthAttachmentLayout->allocateDescriptorSet();
Gfx::ODescriptorSet set = depthAttachmentLayout->allocateDescriptorSet();
{
graphics->beginDebugRegion("MipGeneration");
query->beginQuery();
@@ -253,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);
@@ -3,6 +3,7 @@
#include "Graphics/Query.h"
#include "MinimalEngine.h"
#include "RenderPass.h"
#include "Scene/Scene.h"
namespace Seele {
class DepthCullingPass : public RenderPass {
@@ -44,7 +45,7 @@ class DepthCullingPass : public RenderPass {
Gfx::PComputePipeline depthSourceCopy;
Gfx::OComputeShader depthReduceLevelShader;
Gfx::PComputePipeline depthReduceLevel;
Gfx::PDescriptorSet viewParamsSet;
Gfx::ODescriptorSet viewParamsSet;
Gfx::PShaderBuffer cullingBuffer;
PScene scene;
@@ -0,0 +1,151 @@
#include "FluidRenderPass.h"
#include "Component/Transform.h"
#include "Graphics/Command.h"
#include "Graphics/Descriptor.h"
#include "Graphics/Enums.h"
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h"
#include "Graphics/RenderTarget.h"
#include "Graphics/Shader.h"
#include "Math/Matrix.h"
#include "Scene/LightEnvironment.h"
#include "Scene/Scene.h"
#include "Scene/FluidScene.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 = "transform",
.uniformLength = sizeof(Matrix4),
});
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();
Matrix4 transformMatrix = data.transform.toMatrix();
descriptorSet->updateConstants("transform", 0, &transformMatrix);
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() {
}
void FluidRenderPass::createRenderPass() {
colorAttachment = resources->requestRenderTarget("BASEPASS_COLOR");
colorAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
colorAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
depthAttachment = resources->requestRenderTarget("BASEPASS_DEPTH");
depthAttachment.setLoadOp(Gfx::SE_ATTACHMENT_LOAD_OP_LOAD);
depthAttachment.setInitialLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
Gfx::RenderTargetLayout layout = Gfx::RenderTargetLayout{
.colorAttachments = {colorAttachment},
.depthAttachment = depthAttachment,
};
Array<Gfx::SubPassDependency> dependency = {
{
.srcSubpass = ~0U,
.dstSubpass = 0,
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
{
.srcSubpass = 0,
.dstSubpass = ~0U,
.srcStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.dstStage = Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
Gfx::SE_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
.srcAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dstAccess = Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
},
};
renderPass = graphics->createRenderPass(layout, dependency, viewport->getRenderArea(), "FluidRenderPass");
pipeline = graphics->createGraphicsPipeline(Gfx::LegacyPipelineCreateInfo{
.vertexShader = vertexShader,
.fragmentShader = fragmentShader,
.renderPass = renderPass,
.pipelineLayout = pipelineLayout,
.multisampleState =
{
.samples = Gfx::SE_SAMPLE_COUNT_1_BIT,
},
.rasterizationState =
{
.cullMode = Gfx::SE_CULL_MODE_NONE,
},
.colorBlend =
{
.attachmentCount = 1,
.blendAttachments =
{
Gfx::ColorBlendState::BlendAttachment{
.blendEnable = true,
},
},
},
});
}
@@ -0,0 +1,38 @@
#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::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
@@ -8,10 +8,141 @@
#include "Math/Vector.h"
#include "RenderGraph.h"
#include "Scene/Scene.h"
#include "Scene/LightEnvironment.h"
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 +222,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 = std::move(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 = std::move(cullingEnableLayout);
cullingEnabledPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
}
uint32 counterReset = 0;
ShaderBufferCreateInfo structInfo = {
.sourceData =
@@ -188,8 +242,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 +290,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 =
{
@@ -29,11 +29,11 @@ class LightCullingPass : public RenderPass {
Gfx::OShaderBuffer frustumBuffer;
const char* FRUSTUMBUFFER_NAME = "frustums";
Gfx::ODescriptorLayout dispatchParamsLayout;
Gfx::PDescriptorSet dispatchParamsSet;
Gfx::ODescriptorSet dispatchParamsSet;
Gfx::OComputeShader frustumShader;
Gfx::PComputePipeline frustumPipeline;
Gfx::OPipelineLayout frustumLayout;
Gfx::PDescriptorSet viewParamsSet;
Gfx::ODescriptorSet viewParamsSet;
PLightEnvironment lightEnv;
Gfx::PTextureView depthAttachment;
@@ -50,7 +50,7 @@ class LightCullingPass : public RenderPass {
constexpr static const char* OLIGHTGRID_NAME = "oLightGrid";
Gfx::OTexture2D tLightGrid;
constexpr static const char* TLIGHTGRID_NAME = "tLightGrid";
Gfx::PDescriptorSet cullingDescriptorSet;
Gfx::ODescriptorSet cullingDescriptorSet;
Gfx::ODescriptorLayout cullingDescriptorLayout;
Gfx::OPipelineLayout cullingLayout;
Gfx::OPipelineLayout cullingEnableLayout;
@@ -4,7 +4,11 @@
#include "Graphics/RayTracing.h"
#include "Graphics/Shader.h"
#include "Graphics/StaticMeshVertexData.h"
#include "Material/Material.h"
#include "Material/MaterialInstance.h"
#include "Scene/LightEnvironment.h"
#include "RenderPass.h"
#include <iostream>
using namespace Seele;
@@ -51,7 +55,20 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa
.stageFlags = Gfx::SE_SHADER_STAGE_RAYGEN_BIT_KHR,
.offset = 0,
.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",
@@ -66,7 +83,8 @@ static uint32 pass = 0;
static Component::Transform lastCam;
void RayTracingPass::beginFrame(const Component::Camera& cam, const Component::Transform& transform) {
updateViewParameters(cam, transform);
viewParamsSet = createViewParamsSet(); if (lastCam.getPosition() != transform.getPosition() || lastCam.getForward() != transform.getForward()) {
viewParamsSet = createViewParamsSet();
if (lastCam.getPosition() != transform.getPosition() || lastCam.getForward() != transform.getForward()) {
lastCam = transform;
pass = 0;
}
@@ -149,7 +167,7 @@ void RayTracingPass::render() {
.instances = instanceData,
.bottomLevelStructures = accelerationStructures,
});
Gfx::PDescriptorSet desc = paramsLayout->allocateDescriptorSet();
Gfx::ODescriptorSet desc = paramsLayout->allocateDescriptorSet();
desc->updateAccelerationStructure(TLAS_NAME, 0, tlas);
desc->updateTexture(ACCUMULATOR_NAME, 0, radianceAccumulator->getDefaultView());
desc->updateTexture(TEXTURE_NAME, 0, texture->getDefaultView());
@@ -208,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() {}
@@ -1,6 +1,7 @@
#pragma once
#include "Graphics/Graphics.h"
#include "RenderPass.h"
#include "Scene/Scene.h"
namespace Seele {
class RayTracingPass : public RenderPass {
@@ -32,7 +33,7 @@ class RayTracingPass : public RenderPass {
Gfx::OAnyHitShader anyhit;
Gfx::OMissShader miss;
Gfx::PRayTracingPipeline pipeline;
Gfx::PDescriptorSet viewParamsSet;
Gfx::ODescriptorSet viewParamsSet;
PScene scene;
};
} // namespace Seele
+1 -1
View File
@@ -38,7 +38,7 @@ class RenderGraph {
return res;
}
private:
PRenderGraphResources res;
ORenderGraphResources res;
List<ORenderPass> passes;
};
@@ -1,6 +1,5 @@
#include "RenderGraphResources.h"
#include "Graphics/Query.h"
#include <iostream>
#include <string>
using namespace Seele;
@@ -1,4 +1,5 @@
#include "RenderPass.h"
#include "Graphics/Graphics.h"
using namespace Seele;
@@ -32,7 +33,7 @@ void RenderPass::updateViewParameters(const Component::Camera& cam, const Compon
Vector eyePos = transform.getPosition();
Vector lookAt = eyePos + transform.getForward();
Matrix4 cameraMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
Matrix4 projectionMatrix = viewport->getProjectionMatrix(cam.nearPlane, cam.farPlane);
Matrix4 projectionMatrix = cam.getProjectionMatrix();
viewParams = {
.viewMatrix = cameraMatrix,
.inverseViewMatrix = glm::inverse(cameraMatrix),
@@ -49,7 +50,7 @@ void RenderPass::updateViewParameters(const Component::Camera& cam, const Compon
};
}
Gfx::PDescriptorSet RenderPass::createViewParamsSet()
Gfx::ODescriptorSet RenderPass::createViewParamsSet()
{
// screen space
//StaticArray<Vector4, 4> corners = {
@@ -71,8 +72,7 @@ Gfx::PDescriptorSet RenderPass::createViewParamsSet()
// extract_planes_from_view_projection_matrix(viewParams.viewProjectionMatrix, viewParams.viewFrustum);
viewParamsLayout->reset();
Gfx::PDescriptorSet viewParamsSet = viewParamsLayout->allocateDescriptorSet();
Gfx::ODescriptorSet viewParamsSet = viewParamsLayout->allocateDescriptorSet();
viewParamsSet->updateConstants("viewMatrix", 0, &viewParams.viewMatrix);
viewParamsSet->updateConstants("inverseViewMatrix", 0, &viewParams.inverseViewMatrix);
viewParamsSet->updateConstants("projectionMatrix", 0, &viewParams.projectionMatrix);
+2 -5
View File
@@ -1,12 +1,9 @@
#pragma once
#include "Component/Camera.h"
#include "Graphics/VertexData.h"
#include "Material/MaterialInstance.h"
#include "Math/Math.h"
#include "MinimalEngine.h"
#include "RenderGraphResources.h"
#include "Scene/Scene.h"
#include "Graphics/Descriptor.h"
namespace Seele {
DECLARE_NAME_REF(Gfx, Viewport)
@@ -28,7 +25,7 @@ class RenderPass {
protected:
void updateViewParameters(const Component::Camera& cam, const Component::Transform& transform);
Gfx::PDescriptorSet createViewParamsSet();
Gfx::ODescriptorSet createViewParamsSet();
struct Plane {
Vector n;
float d;
+121 -81
View File
@@ -3,6 +3,8 @@
#include "Graphics/Graphics.h"
#include "Graphics/Initializer.h"
#include "Graphics/Shader.h"
#include "Math/Matrix.h"
#include "Scene/LightEnvironment.h"
#include <glm/ext/matrix_transform.hpp>
#include <glm/matrix.hpp>
@@ -15,6 +17,7 @@ ShadowPass::ShadowPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graph
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
.size = sizeof(VertexData::DrawCallOffsets),
.name = "pOffsets",
});
if (graphics->supportMeshShading()) {
graphics->getShaderCompiler()->registerRenderPass("ShadowPass", Gfx::PassConfig{
@@ -44,94 +47,97 @@ ShadowPass::ShadowPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graph
ShadowPass::~ShadowPass() {}
void ShadowPass::beginFrame(const Component::Camera& camera, const Component::Transform& transform) {
uint32 cascadeDim = SHADOW_MAP_SIZE;
float cascadeSplits[NUM_CASCADES];
float splitDepths[NUM_CASCADES];
float nearClip = camera.nearPlane;
float farClip = camera.farPlane;
float clipRange = farClip - nearClip;
float minZ = nearClip;
float maxZ = nearClip + clipRange;
float maxZ = farClip;
float range = maxZ - minZ;
float ratio = maxZ / minZ;
constexpr float cascadeSplitLambda = 0.95f;
for (uint32 i = 0; i < NUM_CASCADES; ++i) {
cascades[i].shadowMaps = graphics->createTexture2D(TextureCreateInfo{
.format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = cascadeDim,
.height = cascadeDim,
.elements = (uint32)scene->getLightEnvironment()->getNumDirectionalLights(),
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT,
.name = "ShadowMapCascade",
});
cascades[i].views.clear();
for (uint32 j = 0; j < cascades[i].shadowMaps->getNumLayers(); ++j) {
cascades[i].views.add(cascades[i].shadowMaps->createTextureView(0, 1, j, 1));
}
cascadeDim /= 2;
float p = (i + 1) / static_cast<float>(NUM_CASCADES);
float log = minZ * std::pow(ratio, p);
float uniform = minZ + range * p;
float d = cascadeSplitLambda * (log - uniform) + uniform;
cascadeSplits[i] = (d - nearClip) / clipRange;
splitDepths[i] = d;
cascades[i].viewParams.clear();
}
cascadeSplitsBuffer->updateContents(0, sizeof(float) * NUM_CASCADES, splitDepths);
// call this to update view params member, ignore descriptor set
updateViewParameters(camera, transform);
Array<Vector> frustumCorners = {
Vector(-1.0f, 1.0f, 0.0f), Vector(1.0f, 1.0f, 0.0f), Vector(1.0f, -1.0f, 0.0f), Vector(-1.0f, -1.0f, 0.0f),
Vector(-1.0f, 1.0f, 1.0f), Vector(1.0f, 1.0f, 1.0f), Vector(1.0f, -1.0f, 1.0f), Vector(-1.0f, -1.0f, 1.0f),
};
Matrix4 invCam = viewParams.inverseViewProjectionMatrix;
float lastSplitDist = 0.0;
constexpr float cascadeOverlap = 0.1f; // overlap factor to prevent gaps at cascade boundaries
for (uint32 i = 0; i < NUM_CASCADES; ++i) {
float splitDist = cascadeSplits[i];
for (auto& c : frustumCorners) {
Vector4 invCorner = viewParams.inverseViewProjectionMatrix * Vector4(c, 1);
c = invCorner / invCorner.w;
}
for (uint32 s = 0; s < scene->getLightEnvironment()->getNumDirectionalLights(); ++s) {
float lastSplitDist = 0.0;
for (uint32 i = 0; i < NUM_CASCADES; ++i) {
float splitDist = cascadeSplits[i];
// Extend each cascade's frustum slice slightly into adjacent cascades
float overlapNear = (i > 0) ? lastSplitDist - cascadeOverlap * (lastSplitDist - (i > 1 ? cascadeSplits[i - 2] : 0.0f)) : 0.0f;
float overlapFar = (i < NUM_CASCADES - 1) ? splitDist + cascadeOverlap * (cascadeSplits[i + 1] - splitDist) : splitDist;
Array<Vector> cascadeCorners(8);
for (uint32 j = 0; j < 4; j++) {
Vector dist = frustumCorners[j + 4] - frustumCorners[j];
cascadeCorners[j + 4] = frustumCorners[j] + (dist * splitDist);
cascadeCorners[j] = frustumCorners[j] + (dist * lastSplitDist);
}
Array<Vector> frustumCorners = {
Vector(-1.0f, 1.0f, 0.0f), Vector(1.0f, 1.0f, 0.0f), Vector(1.0f, -1.0f, 0.0f), Vector(-1.0f, -1.0f, 0.0f),
Vector(-1.0f, 1.0f, 1.0f), Vector(1.0f, 1.0f, 1.0f), Vector(1.0f, -1.0f, 1.0f), Vector(-1.0f, -1.0f, 1.0f),
};
Vector frustumCenter = Vector(0);
for (uint32 j = 0; j < 8; j++) {
frustumCenter += cascadeCorners[j];
}
frustumCenter /= 8.0f;
float radius = 0.0f;
for (uint j = 0; j < 8; j++) {
float distance = glm::length(cascadeCorners[j] - frustumCenter);
radius = glm::max(radius, distance);
}
radius = std::ceil(radius * 16.0f) / 16.0f;
Vector maxExtents = Vector(radius);
Vector minExtents = -maxExtents;
Vector lightDir = glm::normalize(scene->getLightEnvironment()->getDirectionalLight(s).direction);
Matrix4 viewMatrix = glm::lookAt(frustumCenter - lightDir * -minExtents.z, frustumCenter, Vector(0, 1, 0));
Matrix4 projectionMatrix =
glm::ortho(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f, maxExtents.z - minExtents.z);
Matrix4 viewProjectionMatrix = projectionMatrix * viewMatrix;
viewParams.viewMatrix = viewMatrix;
viewParams.inverseViewMatrix = glm::inverse(viewMatrix);
viewParams.projectionMatrix = projectionMatrix;
viewParams.inverseProjection = glm::inverse(projectionMatrix);
viewParams.viewProjectionMatrix = viewProjectionMatrix;
viewParams.inverseViewProjectionMatrix = glm::inverse(viewProjectionMatrix);
viewParams.screenDimensions = Vector2(maxExtents.x - minExtents.x, maxExtents.y - minExtents.y);
viewParams.invScreenDimensions = 1.0f / viewParams.screenDimensions;
cascades[i].viewParams.add(createViewParamsSet());
for (auto& c : frustumCorners) {
Vector4 invCorner = invCam * Vector4(c, 1);
c = invCorner / invCorner.w;
}
for (uint32 j = 0; j < 4; j++) {
Vector dist = frustumCorners[j + 4] - frustumCorners[j];
frustumCorners[j + 4] = frustumCorners[j] + (dist * overlapFar);
frustumCorners[j] = frustumCorners[j] + (dist * overlapNear);
}
Vector frustumCenter = Vector(0);
for (uint32 j = 0; j < 8; j++) {
frustumCenter += frustumCorners[j];
}
frustumCenter /= 8.0f;
float radius = 0.0f;
for (uint j = 0; j < 8; j++) {
float distance = glm::length(frustumCorners[j] - frustumCenter);
radius = glm::max(radius, distance);
}
radius = std::ceil(radius * 16.0f) / 16.0f;
Vector maxExtents = Vector(radius);
Vector minExtents = -maxExtents;
for (uint32 s = 0; s < scene->getLightEnvironment()->getNumDirectionalLights(); ++s) {
Vector lightDir = glm::normalize(scene->getLightEnvironment()->getDirectionalLight(s).direction);
Vector cameraPos = frustumCenter - lightDir * (100.0f * -minExtents.z);
Matrix4 viewMatrix = glm::lookAt(cameraPos, frustumCenter, Vector(0, 1, 0));
Matrix4 projectionMatrix =
orthographicProjection(minExtents.x, maxExtents.x, minExtents.y, maxExtents.y, 0.0f, maxExtents.z - (100.0f * minExtents.z));
Matrix4 viewProjectionMatrix = projectionMatrix * viewMatrix;
viewParams = {
.viewMatrix = viewMatrix,
.inverseViewMatrix = glm::inverse(viewMatrix),
.projectionMatrix = projectionMatrix,
.inverseProjection = glm::inverse(projectionMatrix),
.viewProjectionMatrix = viewProjectionMatrix,
.inverseViewProjectionMatrix = glm::inverse(viewProjectionMatrix),
.cameraPosition_WS = Vector4(cameraPos, 1),
.cameraForward_WS = Vector4(frustumCenter - cameraPos, 0),
.screenDimensions = Vector2(maxExtents.x - minExtents.x, maxExtents.y - minExtents.y),
.invScreenDimensions = 1.0f / Vector2(maxExtents.x - minExtents.x, maxExtents.y - minExtents.y),
.frameIndex = Gfx::getCurrentFrameIndex(),
.time = (float)Gfx::getCurrentFrameTime(),
};
cascades[i].viewParams.add(createViewParamsSet());
cascades[i].lightSpaceBuffer->updateContents(0, sizeof(Matrix4), &viewProjectionMatrix);
}
lastSplitDist = cascadeSplits[i];
}
}
@@ -146,9 +152,9 @@ void ShadowPass::render() {
Array<Gfx::ORenderCommand> commands;
renderPass = graphics->createRenderPass(
Gfx::RenderTargetLayout{
.depthAttachment = Gfx::RenderTargetAttachment(
cascades[c].views[shadowIndex], Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE),
.depthAttachment = Gfx::RenderTargetAttachment(cascades[c].views[shadowIndex], Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
Gfx::SE_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
Gfx::SE_ATTACHMENT_LOAD_OP_CLEAR, Gfx::SE_ATTACHMENT_STORE_OP_STORE),
},
{
@@ -180,7 +186,7 @@ void ShadowPass::render() {
Gfx::PermutationId id(permutation);
Gfx::ORenderCommand command = graphics->createRenderCommand("ShadowRender");
command->setViewport(shadowViewport);
command->setViewport(cascades[c].shadowViewport);
const Gfx::ShaderCollection* collection = graphics->getShaderCompiler()->findShaders(id);
constexpr float depthBiasConstant = -1.25f;
@@ -219,7 +225,8 @@ void ShadowPass::render() {
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
command->bindPipeline(pipeline);
}
command->bindDescriptor({cascades[c].viewParams[shadowIndex], vertexData->getVertexDataSet(), vertexData->getInstanceDataSet()});
command->bindDescriptor(
{cascades[c].viewParams[shadowIndex], vertexData->getVertexDataSet(), vertexData->getInstanceDataSet()});
VertexData::DrawCallOffsets offsets = {
.instanceOffset = 0,
};
@@ -248,7 +255,6 @@ void ShadowPass::render() {
}
graphics->executeCommands(std::move(commands));
graphics->endRenderPass();
graphics->waitDeviceIdle();
}
graphics->endDebugRegion();
}
@@ -258,17 +264,51 @@ void ShadowPass::render() {
void ShadowPass::endFrame() {}
void ShadowPass::publishOutputs() {
shadowViewport = graphics->createViewport(nullptr, ViewportCreateInfo{.dimensions =
{
.size = {SHADOW_MAP_SIZE, SHADOW_MAP_SIZE},
.offset = {0, 0},
},
.fieldOfView = 0,
.left = -100,
.right = 100,
.top = 100,
.bottom = -100});
viewport = shadowViewport;
cascadeSplitsBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{.sourceData =
{
.size = sizeof(float) * NUM_CASCADES,
.data = nullptr,
},
.name = "CascadeSplits"});
uint32 cascadeDim = SHADOW_MAP_SIZE;
for (uint32 c = 0; c < NUM_CASCADES; ++c) {
cascades[c].shadowMaps = graphics->createTexture2DArray(TextureCreateInfo{
.format = Gfx::SE_FORMAT_D32_SFLOAT,
.width = cascadeDim,
.height = cascadeDim,
.elements = 1, // TODO:
.usage = Gfx::SE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | Gfx::SE_IMAGE_USAGE_SAMPLED_BIT,
.name = "ShadowMapCascade",
});
cascades[c].lightSpaceBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{.sourceData =
{
.size = sizeof(Matrix4),
.data = nullptr,
},
.name = "LightSpaceBuffer"});
cascades[c].views.clear();
for (uint32 j = 0; j < cascades[c].shadowMaps->getNumLayers(); ++j) {
cascades[c].views.add(cascades[c].shadowMaps->createTextureView(0, 1, j, 1));
}
cascades[c].shadowViewport = graphics->createViewport(nullptr, ViewportCreateInfo{
.dimensions =
{
.size = {cascadeDim, cascadeDim},
.offset = {0, 0},
},
});
cascadeDim /= 2;
resources->registerTextureOutput(fmt::format("SHADOWMAP_TEXTURE{0}", c), Gfx::PTexture2DArray(cascades[c].shadowMaps));
resources->registerBufferOutput(fmt::format("SHADOWMAP_LIGHTSPACE{0}", c), cascades[c].lightSpaceBuffer);
}
cascadeSplitsBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{.sourceData =
{
.size = sizeof(float) * NUM_CASCADES,
.data = nullptr,
},
.name = "CASCADE_SPLITS"});
resources->registerUniformOutput("SHADOWMAP_CASCADESPLITS", cascadeSplitsBuffer);
viewport = cascades[0].shadowViewport;
}
void ShadowPass::createRenderPass() { cullingBuffer = resources->requestBuffer("CULLINGBUFFER"); }
+8 -4
View File
@@ -1,11 +1,13 @@
#pragma once
#include "Graphics/Buffer.h"
#include "Graphics/Descriptor.h"
#include "Scene/Scene.h"
#include "RenderPass.h"
namespace Seele {
static constexpr uint64 SHADOW_MAP_SIZE = 8192;
static constexpr uint64 NUM_CASCADES = 4;
class ShadowPass : public RenderPass {
public:
@@ -20,16 +22,18 @@ class ShadowPass : public RenderPass {
virtual void createRenderPass() override;
private:
AABB cameraFrustumBox;
static constexpr uint64 NUM_CASCADES = 4;
struct Cascade {
Gfx::OTexture2D shadowMaps;
Gfx::OTexture2DArray shadowMaps;
Array<Gfx::OTextureView> views;
Array<Gfx::PDescriptorSet> viewParams;
Array<Matrix4> lightSpaceMatrices;
Gfx::OShaderBuffer lightSpaceBuffer;
Array<Gfx::ODescriptorSet> viewParams;
Gfx::OViewport shadowViewport;
};
StaticArray<Cascade, NUM_CASCADES> cascades;
Gfx::OUniformBuffer cascadeSplitsBuffer;
Gfx::OPipelineLayout shadowLayout;
Gfx::PShaderBuffer cullingBuffer;
Gfx::OViewport shadowViewport;
PScene scene;
};
DEFINE_REF(ShadowPass)
@@ -0,0 +1,651 @@
#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 "Scene/FluidScene.h"
#include <algorithm>
using namespace Seele;
// Reinitialization is in pseudo-time; keep it gentle to avoid eroding the interface each frame.
constexpr static int reinitInterval = 20;
constexpr static int reinitIterations = 1;
constexpr static float reinitDtau = 0.05f;
constexpr static int velocityDiffuseIterations = 8;
constexpr static int pressureSolveIterations = 24;
constexpr static int densityDiffuseIterations = 8;
#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) {
gridSizeLayout = graphics->createDescriptorLayout("gridParams");
gridSizeLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "gridSize",
.uniformLength = sizeof(UVector),
});
gridSizeLayout->create();
{
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);
setBounds.pipelineLayout->addDescriptorLayout(gridSizeLayout);
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);
linearSolve.pipelineLayout->addDescriptorLayout(gridSizeLayout);
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);
computeDivergence.pipelineLayout->addDescriptorLayout(gridSizeLayout);
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);
project.pipelineLayout->addDescriptorLayout(gridSizeLayout);
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);
advect.pipelineLayout->addDescriptorLayout(gridSizeLayout);
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);
reinitialize.pipelineLayout->addDescriptorLayout(gridSizeLayout);
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,
});
}
{
applyForces.pipelineLayout = graphics->createPipelineLayout("ApplyForcesPipelineLayout");
applyForces.descriptorLayout = graphics->createDescriptorLayout("params");
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityX",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityY",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "velocityZ",
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
});
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "force",
.uniformLength = sizeof(Vector),
});
applyForces.descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "dt",
.uniformLength = sizeof(float),
});
applyForces.descriptorLayout->create();
applyForces.pipelineLayout->addDescriptorLayout(applyForces.descriptorLayout);
applyForces.pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "ApplyForces",
.modules = {"ApplyForces"},
.entryPoints = {{"applyForces", "ApplyForces"}},
.rootSignature = applyForces.pipelineLayout,
});
applyForces.pipelineLayout->create();
applyForces.shader = graphics->createComputeShader({0});
applyForces.pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
.computeShader = applyForces.shader,
.pipelineLayout = applyForces.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();
applyForces.descriptorLayout->reset();
gridSizeLayout->reset();
}
void SimulationComputePass::render() {
for (auto& [entityID, data] : scene->getFluidScene()->getFluidDataMap()) {
if (data.paused) {
continue;
}
gridSizeSet = gridSizeLayout->allocateDescriptorSet();
gridSizeSet->updateConstants("gridSize", 0, &data.gridSize);
gridSizeSet->writeChanges();
graphics->beginDebugRegion("Diffuse");
for (int iteration = 0; iteration < velocityDiffuseIterations; ++iteration) {
float a = data.dt * data.viscosity * (data.gridSize.x - 2) * (data.gridSize.x - 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);
// Divergence/pressure buffers are aliased to velocity buffers whose boundary
// cells still contain stale velocity data. Zero the boundaries before solving.
setBoundsPass(divergence, 0, data.gridSize);
setBoundsPass(pressureCurrent, 0, data.gridSize);
for (int iteration = 0; iteration < pressureSolveIterations; ++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, data.dt,
data.gridSize);
advectPass(data.velocityYBuffer, data.velocityY0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, data.dt,
data.gridSize);
advectPass(data.velocityZBuffer, data.velocityZ0Buffer, data.velocityX0Buffer, data.velocityY0Buffer, data.velocityZ0Buffer, data.dt,
data.gridSize);
if (data.enableGravity) {
applyForcesPass(data.velocityXBuffer, data.velocityYBuffer, data.velocityZBuffer, data.gravity, data.dt, data.gridSize);
}
// Set boundary conditions after advection/forces so the divergence sees correct wall values
setBoundsPass(data.velocityXBuffer, 1, data.gridSize);
setBoundsPass(data.velocityYBuffer, 2, data.gridSize);
setBoundsPass(data.velocityZBuffer, 3, data.gridSize);
// Re-project after advection/forces to keep the final velocity field divergence-free.
Gfx::PShaderBuffer advectedDivergence = data.velocityXNextBuffer;
Gfx::PShaderBuffer advectedPressureCurrent = data.velocityYNextBuffer;
Gfx::PShaderBuffer advectedPressureNext = data.velocityZNextBuffer;
divergencePass(advectedDivergence, advectedPressureCurrent, data.velocityXBuffer, data.velocityYBuffer, data.velocityZBuffer, data.gridSize);
setBoundsPass(advectedDivergence, 0, data.gridSize);
setBoundsPass(advectedPressureCurrent, 0, data.gridSize);
for (int iteration = 0; iteration < pressureSolveIterations; ++iteration) {
linearSolvePass(advectedPressureNext, advectedPressureCurrent, advectedDivergence, 1, 6, data.gridSize);
setBoundsPass(advectedPressureNext, 0, data.gridSize);
SWAP(advectedPressureCurrent, advectedPressureNext);
}
projectPass(data.velocityXBuffer, data.velocityYBuffer, data.velocityZBuffer, advectedPressureCurrent, 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 < densityDiffuseIterations; ++iteration) {
float a = data.dt * data.diffusion * (data.gridSize.x - 2) * (data.gridSize.x - 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, data.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, data.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->bindDescriptor(gridSizeSet);
// Dispatch covers max(gridSize.x, gridSize.y) x max(gridSize.y, gridSize.z) to handle all faces on non-cubic grids
UVector faceDispatchGrid = {std::max(gridSize.x, gridSize.y), std::max(gridSize.y, gridSize.z), 1};
auto dispatchSize = getDispatchSize(faceDispatchGrid, setBounds.threadGroupSize);
boundsCommand->dispatch(dispatchSize.x, dispatchSize.y, 1);
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->bindDescriptor(gridSizeSet);
// Dispatch covers max dimension to handle all 12 edges on non-cubic grids; edge shader uses numthreads(128,1,1)
uint32_t maxDim = std::max({gridSize.x, gridSize.y, gridSize.z});
edgesCommand->dispatch((maxDim + 127) / 128, 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->bindDescriptor(gridSizeSet);
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->bindDescriptor(gridSizeSet);
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->bindDescriptor(gridSizeSet);
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->bindDescriptor(gridSizeSet);
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->bindDescriptor(gridSizeSet);
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::applyForcesPass(Gfx::PShaderBuffer velocityX, Gfx::PShaderBuffer velocityY, Gfx::PShaderBuffer velocityZ, Vector gravity, float dt, UVector gridSize) {
Gfx::ODescriptorSet forcesSet = applyForces.descriptorLayout->allocateDescriptorSet();
forcesSet->updateBuffer("velocityX", 0, velocityX);
forcesSet->updateBuffer("velocityY", 0, velocityY);
forcesSet->updateBuffer("velocityZ", 0, velocityZ);
forcesSet->updateConstants("force", 0, &gravity);
forcesSet->updateConstants("dt", 0, &dt);
forcesSet->writeChanges();
Gfx::OComputeCommand forcesCommand = graphics->createComputeCommand();
forcesCommand->bindPipeline(applyForces.pipeline);
forcesCommand->bindDescriptor(forcesSet);
forcesCommand->bindDescriptor(gridSizeSet);
forcesCommand->dispatch(getDispatchSize(gridSize, applyForces.threadGroupSize));
graphics->executeCommands(std::move(forcesCommand));
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::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->bindDescriptor(gridSizeSet);
reinitCommand->dispatch(getDispatchSize(gridSize, reinitialize.threadGroupSize));
graphics->executeCommands(std::move(reinitCommand));
phi->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
setBoundsPass(phi, 0, gridSize);
SWAP(phi, phi0);
}
graphics->endDebugRegion();
}
@@ -0,0 +1,91 @@
#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;
struct ApplyForces {
Gfx::OPipelineLayout pipelineLayout;
Gfx::ODescriptorLayout descriptorLayout;
Gfx::OComputeShader shader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {32, 8, 1};
} applyForces;
void applyForcesPass(Gfx::PShaderBuffer velocityX, Gfx::PShaderBuffer velocityY, Gfx::PShaderBuffer velocityZ, Vector gravity, float dt, UVector gridSize);
Gfx::ODescriptorLayout gridSizeLayout;
Gfx::ODescriptorSet gridSizeSet;
PScene scene;
};
DEFINE_REF(SimulationComputePass)
} // namespace Seele
@@ -0,0 +1,107 @@
#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 "Scene/FluidScene.h"
using namespace Seele;
SurfaceExtractPass::SurfaceExtractPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
pipelineLayout = graphics->createPipelineLayout("SurfaceExtractPipelineLayout");
gridSizeLayout = graphics->createDescriptorLayout("gridParams");
gridSizeLayout->addDescriptorBinding(Gfx::DescriptorBinding{
.name = "gridSize",
.uniformLength = sizeof(UVector),
});
gridSizeLayout->create();
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);
pipelineLayout->addDescriptorLayout(gridSizeLayout);
graphics->beginShaderCompilation(ShaderCompilationInfo{
.name = "MarchingCubes",
.modules = {"MarchingCubes"},
.entryPoints = {{"marchingCubes", "MarchingCubes"}},
.rootSignature = pipelineLayout,
.dumpIntermediate = true,
});
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()) {
Gfx::ODescriptorSet gridSizeSet = gridSizeLayout->allocateDescriptorSet();
gridSizeSet->updateConstants("gridSize", 0, &data.gridSize);
gridSizeSet->writeChanges();
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->bindDescriptor(gridSizeSet);
cmd->dispatch((data.gridSize + threadGroupSize - 1u) / threadGroupSize);
graphics->executeCommands(std::move(cmd));
data.vertexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
data.normalBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
data.indexBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_VERTEX_SHADER_BIT);
data.surfaceCountBuffer->pipelineBarrier(Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
Gfx::SE_ACCESS_INDIRECT_COMMAND_READ_BIT, Gfx::SE_PIPELINE_STAGE_DRAW_INDIRECT_BIT);
}
}
void SurfaceExtractPass::endFrame() {}
void SurfaceExtractPass::publishOutputs() {}
void SurfaceExtractPass::createRenderPass() {}
@@ -0,0 +1,30 @@
#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::ODescriptorLayout gridSizeLayout;
Gfx::ODescriptorSet descriptorSet;
Gfx::OComputeShader computeShader;
Gfx::PComputePipeline pipeline;
constexpr static UVector threadGroupSize = {16, 8, 1};
};
DEFINE_REF(SurfaceExtractPass)
} // namespace Seele

Some files were not shown because too many files have changed in this diff Show More