Compare commits
14
Commits
9109baad18
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bedeb8f059 | ||
|
|
424dea0012 | ||
|
|
495e683522 | ||
|
|
ac317a3829 | ||
|
|
056589a6f9 | ||
|
|
b6a449d8e3 | ||
|
|
7af42b9bad | ||
|
|
ace1554020 | ||
|
|
87390db80d | ||
|
|
7271fe8a0b | ||
|
|
925537dcb3 | ||
|
|
4fd44b075f | ||
|
|
e2296cada2 | ||
|
|
54106e6fef |
Vendored
+24
-17
@@ -18,33 +18,35 @@
|
|||||||
"name": "Editor (Mac)",
|
"name": "Editor (Mac)",
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/build/Editor",
|
"program": "${workspaceRoot}/build/external/Seele/Editor",
|
||||||
"args": [],
|
"args": [],
|
||||||
"stopAtEntry": false,
|
"cwd": "${workspaceRoot}/build/external/Seele",
|
||||||
"cwd": "${workspaceRoot}/build",
|
"initCommands": [
|
||||||
"environment": [
|
"command script import ${workspaceFolder}/external/Seele/gdb/Seele_lldb.py"
|
||||||
{
|
]
|
||||||
"name": "VK_LAYER_PATH",
|
|
||||||
"value": "/opt/homebrew/opt/vulkan-validationlayers/share/vulkan/explicit_layer.d"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"logging": {
|
|
||||||
"moduleLoad": false
|
|
||||||
},
|
|
||||||
"externalConsole": false,
|
|
||||||
"MIMode": "lldb",
|
|
||||||
"targetArchitecture": "arm64"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Editor (Linux)",
|
"name": "Editor (Linux)",
|
||||||
"type": "cppdbg",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/build/Editor",
|
"program": "${workspaceRoot}/build/Editor",
|
||||||
"args": [],
|
"args": [],
|
||||||
"environment": [
|
"environment": [
|
||||||
{
|
{
|
||||||
"name": "ASAN_OPTIONS",
|
"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",
|
"cwd": "${workspaceRoot}/build",
|
||||||
@@ -55,6 +57,11 @@
|
|||||||
"description": "Enable pretty-printing for gdb",
|
"description": "Enable pretty-printing for gdb",
|
||||||
"text": "-enable-pretty-printing",
|
"text": "-enable-pretty-printing",
|
||||||
"ignoreFailures": true
|
"ignoreFailures": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Import Seele pretty-printers",
|
||||||
|
"text": "python exec(open('${workspaceFolder}/Seele/gdb/Seele.py').read())",
|
||||||
|
"ignoreFailures": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
+20
-38
@@ -22,14 +22,6 @@ set(CMAKE_TOOLCHAIN_FILE ${EXTERNAL_ROOT}/vcpkg/scripts/buildsystems/vcpkg.cmake
|
|||||||
|
|
||||||
set(CRCPP_ROOT ${EXTERNAL_ROOT}/CRCpp)
|
set(CRCPP_ROOT ${EXTERNAL_ROOT}/CRCpp)
|
||||||
set(METAL_ROOT ${EXTERNAL_ROOT}/metal-cpp)
|
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)
|
set(Boost_NO_WARN_NEW_VERSIONS 1)
|
||||||
|
|
||||||
project (Seele)
|
project (Seele)
|
||||||
@@ -48,6 +40,7 @@ find_package(Ktx CONFIG REQUIRED)
|
|||||||
find_package(nlohmann_json CONFIG REQUIRED)
|
find_package(nlohmann_json CONFIG REQUIRED)
|
||||||
find_package(fmt CONFIG REQUIRED)
|
find_package(fmt CONFIG REQUIRED)
|
||||||
find_package(lunasvg CONFIG REQUIRED)
|
find_package(lunasvg CONFIG REQUIRED)
|
||||||
|
find_package(slang CONFIG REQUIRED)
|
||||||
find_package(metis CONFIG REQUIRED)
|
find_package(metis CONFIG REQUIRED)
|
||||||
find_package(meshoptimizer CONFIG REQUIRED)
|
find_package(meshoptimizer CONFIG REQUIRED)
|
||||||
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
find_package(VulkanMemoryAllocator CONFIG REQUIRED)
|
||||||
@@ -61,10 +54,23 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(Engine SHARED "")
|
add_library(Engine SHARED "")
|
||||||
|
set_target_properties(Engine PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
target_include_directories(Engine PRIVATE src/Engine)
|
target_include_directories(Engine PRIVATE src/Engine)
|
||||||
target_include_directories(Engine PRIVATE ${VCPKG_BASE_FOLDER}/include/)
|
|
||||||
target_link_libraries(Engine PUBLIC Vulkan::Vulkan)
|
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 EnTT::EnTT)
|
||||||
target_link_libraries(Engine PUBLIC glfw)
|
target_link_libraries(Engine PUBLIC glfw)
|
||||||
target_link_libraries(Engine PUBLIC glm::glm)
|
target_link_libraries(Engine PUBLIC glm::glm)
|
||||||
@@ -77,17 +83,9 @@ target_link_libraries(Engine PUBLIC nlohmann_json::nlohmann_json)
|
|||||||
target_link_libraries(Engine PUBLIC crcpp)
|
target_link_libraries(Engine PUBLIC crcpp)
|
||||||
target_link_libraries(Engine PUBLIC fmt::fmt)
|
target_link_libraries(Engine PUBLIC fmt::fmt)
|
||||||
target_link_libraries(Engine PUBLIC lunasvg::lunasvg)
|
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 metis)
|
||||||
target_link_libraries(Engine PUBLIC meshoptimizer::meshoptimizer)
|
target_link_libraries(Engine PUBLIC meshoptimizer::meshoptimizer)
|
||||||
if(WIN32)
|
target_link_libraries(Engine PUBLIC slang::slang)
|
||||||
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()
|
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
target_link_libraries(Engine PUBLIC metal)
|
target_link_libraries(Engine PUBLIC metal)
|
||||||
@@ -133,33 +131,17 @@ if(APPLE)
|
|||||||
target_compile_options(Engine PUBLIC -Wno-gnu-anonymous-struct -Wno-nested-anon-types)
|
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)
|
target_compile_options(Editor PUBLIC -Wno-gnu-anonymous-struct -Wno-nested-anon-types)
|
||||||
endif()
|
endif()
|
||||||
target_compile_options(Engine PUBLIC "$<$<CONFIG:DEBUG>:-DENABLE_VALIDATION>")
|
|
||||||
target_compile_options(Engine PUBLIC "$<$<CONFIG:DEBUG>:-DSEELE_DEBUG>")
|
|
||||||
|
|
||||||
add_subdirectory(src/)
|
add_subdirectory(src/)
|
||||||
#add_subdirectory(tests/)
|
#add_subdirectory(tests/)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_custom_target(dll_copy ALL
|
add_custom_command(TARGET Engine POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_RUNTIME_DLLS:Engine> $<TARGET_FILE_DIR:Editor>
|
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)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target(SeeleEngine ALL
|
add_custom_command(TARGET Engine POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res $<TARGET_FILE_DIR:Engine>
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/res $<TARGET_FILE_DIR:Engine>)
|
||||||
COMMAND_EXPAND_LISTS
|
|
||||||
DEPENDS Editor dll_copy)
|
|
||||||
|
|
||||||
install(
|
install(
|
||||||
TARGETS
|
TARGETS
|
||||||
|
|||||||
+25
-4
@@ -40,6 +40,17 @@
|
|||||||
"CMAKE_INSTALL_PREFIX": "C:/Program Files/Seele"
|
"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",
|
"name": "debug-asan",
|
||||||
"displayName": "Debug (ASan)",
|
"displayName": "Debug (ASan)",
|
||||||
@@ -59,22 +70,32 @@
|
|||||||
{
|
{
|
||||||
"name": "release",
|
"name": "release",
|
||||||
"displayName": "Release (no ASan)",
|
"displayName": "Release (no ASan)",
|
||||||
"configurePreset": "release"
|
"configurePreset": "release",
|
||||||
|
"jobs": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "release-asan",
|
"name": "release-asan",
|
||||||
"displayName": "Release (ASan)",
|
"displayName": "Release (ASan)",
|
||||||
"configurePreset": "release-asan"
|
"configurePreset": "release-asan",
|
||||||
|
"jobs": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "debug",
|
"name": "debug",
|
||||||
"displayName": "Debug (no ASan)",
|
"displayName": "Debug (no ASan)",
|
||||||
"configurePreset": "debug"
|
"configurePreset": "debug",
|
||||||
|
"jobs": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "debug-mac",
|
||||||
|
"displayName": "Debug Mac (no ASan)",
|
||||||
|
"configurePreset": "debug-mac",
|
||||||
|
"jobs": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "debug-asan",
|
"name": "debug-asan",
|
||||||
"displayName": "Debug (ASan)",
|
"displayName": "Debug (ASan)",
|
||||||
"configurePreset": "debug-asan"
|
"configurePreset": "debug-asan",
|
||||||
|
"jobs": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
(?<enum>[A-Z_]*) = [0-9]*,
|
|
||||||
case SE_${enum}:\nreturn VK_${enum};
|
|
||||||
@@ -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)
|
|
||||||
Vendored
+1
-1
Submodule external/vcpkg updated: f9a99aa79c...cb2981c4e0
+83
-2
@@ -2,6 +2,25 @@ import sys
|
|||||||
sys.path.insert(0, '/usr/share/gdb/python/')
|
sys.path.insert(0, '/usr/share/gdb/python/')
|
||||||
import gdb.printing
|
import gdb.printing
|
||||||
|
|
||||||
|
|
||||||
|
def _base_cast(val):
|
||||||
|
for field in val.type.strip_typedefs().fields():
|
||||||
|
if getattr(field, 'is_base_class', False):
|
||||||
|
return val.cast(field.type)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _member(val, name):
|
||||||
|
"""Find a member by name on a value, searching base classes if needed."""
|
||||||
|
current = val
|
||||||
|
while current is not None:
|
||||||
|
t = current.type.strip_typedefs()
|
||||||
|
for field in t.fields():
|
||||||
|
if field.name == name:
|
||||||
|
return current[name]
|
||||||
|
current = _base_cast(current)
|
||||||
|
raise gdb.error(f"Member '{name}' not found on {val.type}")
|
||||||
|
|
||||||
class ArrayPrinter:
|
class ArrayPrinter:
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.val = val
|
self.val = val
|
||||||
@@ -13,8 +32,8 @@ class ArrayPrinter:
|
|||||||
data = self.val['_data']
|
data = self.val['_data']
|
||||||
size = int(self.val['arraySize'])
|
size = int(self.val['arraySize'])
|
||||||
allocated = int(self.val['allocated'])
|
allocated = int(self.val['allocated'])
|
||||||
#yield f"[size]", size
|
yield f"[size]", size
|
||||||
#yield f"[allocated]", allocated
|
yield f"[allocated]", allocated
|
||||||
for i in range(size):
|
for i in range(size):
|
||||||
elem_val = (data + i).dereference()
|
elem_val = (data + i).dereference()
|
||||||
yield f"[{i}]", elem_val
|
yield f"[{i}]", elem_val
|
||||||
@@ -22,6 +41,66 @@ class ArrayPrinter:
|
|||||||
def display_hint(self):
|
def display_hint(self):
|
||||||
return "array"
|
return "array"
|
||||||
|
|
||||||
|
|
||||||
|
class ListPrinter:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
size = int(_member(self.val, '_size'))
|
||||||
|
return f"List(size={size})"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
size = int(_member(self.val, '_size'))
|
||||||
|
root = _member(self.val, 'root')
|
||||||
|
tail = _member(self.val, 'tail')
|
||||||
|
yield "[size]", size
|
||||||
|
|
||||||
|
node = root
|
||||||
|
idx = 0
|
||||||
|
# Bound traversal by logical size to avoid walking corrupted links forever.
|
||||||
|
while idx < size and node != tail:
|
||||||
|
yield f"[{idx}]", node['data']
|
||||||
|
node = node['next']
|
||||||
|
idx += 1
|
||||||
|
|
||||||
|
def display_hint(self):
|
||||||
|
return "array"
|
||||||
|
|
||||||
|
|
||||||
|
class MapPrinter:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def to_string(self):
|
||||||
|
size = int(_member(self.val, '_size'))
|
||||||
|
return f"Map(size={size})"
|
||||||
|
|
||||||
|
def children(self):
|
||||||
|
size = int(_member(self.val, '_size'))
|
||||||
|
root = _member(self.val, 'root')
|
||||||
|
|
||||||
|
stack = []
|
||||||
|
node = root
|
||||||
|
idx = 0
|
||||||
|
|
||||||
|
# In-order traversal of Tree nodes yields map entries sorted by key.
|
||||||
|
while (node or stack) and idx < size:
|
||||||
|
while node:
|
||||||
|
stack.append(node)
|
||||||
|
node = node['leftChild']
|
||||||
|
|
||||||
|
node = stack.pop()
|
||||||
|
pair = node['data']
|
||||||
|
yield f"[{idx}].key", pair['key']
|
||||||
|
yield f"[{idx}].value", pair['value']
|
||||||
|
idx += 1
|
||||||
|
node = node['rightChild']
|
||||||
|
|
||||||
|
def display_hint(self):
|
||||||
|
return "map"
|
||||||
|
|
||||||
|
|
||||||
class VectorPrinter:
|
class VectorPrinter:
|
||||||
def __init__(self, val):
|
def __init__(self, val):
|
||||||
self.val = val
|
self.val = val
|
||||||
@@ -53,6 +132,8 @@ class VectorPrinter:
|
|||||||
def build_pretty_printer():
|
def build_pretty_printer():
|
||||||
pp = gdb.printing.RegexpCollectionPrettyPrinter("Seele")
|
pp = gdb.printing.RegexpCollectionPrettyPrinter("Seele")
|
||||||
pp.add_printer("Array", r'^Seele::Array<.*>$', ArrayPrinter)
|
pp.add_printer("Array", r'^Seele::Array<.*>$', ArrayPrinter)
|
||||||
|
pp.add_printer("List", r'^Seele::List<.*>$', ListPrinter)
|
||||||
|
pp.add_printer("Map", r'^Seele::Map<.*>$', MapPrinter)
|
||||||
pp.add_printer("Vector", r"^glm::(detail::)?t?vec(\d)?<[^<>]*>$", VectorPrinter)
|
pp.add_printer("Vector", r"^glm::(detail::)?t?vec(\d)?<[^<>]*>$", VectorPrinter)
|
||||||
return pp
|
return pp
|
||||||
|
|
||||||
|
|||||||
@@ -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")
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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]));
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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; }
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
@@ -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]);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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]);
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -21,7 +21,6 @@ struct ViewParameter
|
|||||||
uint frameIndex;
|
uint frameIndex;
|
||||||
float time;
|
float time;
|
||||||
};
|
};
|
||||||
layout(set=0)
|
|
||||||
ParameterBlock<ViewParameter> pViewParams;
|
ParameterBlock<ViewParameter> pViewParams;
|
||||||
|
|
||||||
float4 worldToModel(float4x4 inverseTransform, float4 world)
|
float4 worldToModel(float4x4 inverseTransform, float4 world)
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ struct LightEnv
|
|||||||
Texture2D brdfLUT;
|
Texture2D brdfLUT;
|
||||||
SamplerState lutSampler;
|
SamplerState lutSampler;
|
||||||
};
|
};
|
||||||
layout(set=3)
|
|
||||||
ParameterBlock<LightEnv> pLightEnv;
|
ParameterBlock<LightEnv> pLightEnv;
|
||||||
|
|
||||||
interface IBRDF
|
interface IBRDF
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ struct MaterialResources
|
|||||||
SamplerState samplerArray[512];
|
SamplerState samplerArray[512];
|
||||||
StructuredBuffer<float> floatArray;
|
StructuredBuffer<float> floatArray;
|
||||||
};
|
};
|
||||||
layout(set=4)
|
|
||||||
ParameterBlock<MaterialResources> pResources;
|
ParameterBlock<MaterialResources> pResources;
|
||||||
|
|
||||||
Texture2D getMaterialTextureParameter(uint index)
|
Texture2D getMaterialTextureParameter(uint index)
|
||||||
|
|||||||
+15
-14
@@ -45,20 +45,6 @@ struct MeshletCullingInfo
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DrawCallOffsets
|
|
||||||
{
|
|
||||||
uint instanceOffset;
|
|
||||||
uint textureOffset;
|
|
||||||
uint samplerOffset;
|
|
||||||
uint floatOffset;
|
|
||||||
};
|
|
||||||
#ifdef RAY_TRACING
|
|
||||||
layout(shaderRecordEXT)
|
|
||||||
#else
|
|
||||||
layout(push_constant)
|
|
||||||
#endif
|
|
||||||
ConstantBuffer<DrawCallOffsets> pOffsets;
|
|
||||||
|
|
||||||
struct Scene
|
struct Scene
|
||||||
{
|
{
|
||||||
StructuredBuffer<float> positions;
|
StructuredBuffer<float> positions;
|
||||||
@@ -73,6 +59,21 @@ struct Scene
|
|||||||
};
|
};
|
||||||
ParameterBlock<Scene> pScene;
|
ParameterBlock<Scene> pScene;
|
||||||
|
|
||||||
|
struct DrawCallOffsets
|
||||||
|
{
|
||||||
|
uint instanceOffset;
|
||||||
|
uint textureOffset;
|
||||||
|
uint samplerOffset;
|
||||||
|
uint floatOffset;
|
||||||
|
};
|
||||||
|
#ifdef RAY_TRACING
|
||||||
|
// Shader record buffers are accessed via a different mechanism and don't use descriptor set bindings
|
||||||
|
layout(set = 15, shaderRecordEXT)
|
||||||
|
#else
|
||||||
|
layout(push_constant)
|
||||||
|
#endif
|
||||||
|
ConstantBuffer<DrawCallOffsets> pOffsets;
|
||||||
|
|
||||||
uint32_t encodePrimitive(uint32_t meshletId)
|
uint32_t encodePrimitive(uint32_t meshletId)
|
||||||
{
|
{
|
||||||
return meshletId;
|
return meshletId;
|
||||||
|
|||||||
@@ -34,5 +34,4 @@ struct StaticMeshVertexData
|
|||||||
StructuredBuffer<uint16_t> color;
|
StructuredBuffer<uint16_t> color;
|
||||||
StructuredBuffer<uint16_t> texCoords[MAX_TEXCOORDS];
|
StructuredBuffer<uint16_t> texCoords[MAX_TEXCOORDS];
|
||||||
};
|
};
|
||||||
layout(set = 1)
|
|
||||||
ParameterBlock<StaticMeshVertexData> pVertexData;
|
ParameterBlock<StaticMeshVertexData> pVertexData;
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import Common;
|
import Common;
|
||||||
import MaterialParameter;
|
import MaterialParameter;
|
||||||
import LightEnv;
|
import LightEnv;
|
||||||
import Scene;
|
|
||||||
import RayTracingData;
|
|
||||||
import VertexData;
|
import VertexData;
|
||||||
import Material;
|
import Material;
|
||||||
import StaticMeshVertexData;
|
import StaticMeshVertexData;
|
||||||
import MATERIAL_FILE_NAME;
|
import MATERIAL_FILE_NAME;
|
||||||
|
import RayTracingData;
|
||||||
|
import Scene;
|
||||||
|
|
||||||
// simplification: all BLAS only have 1 geometry
|
// simplification: all BLAS only have 1 geometry
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ struct RayTracingParams
|
|||||||
TextureCube<float4> skyBox;
|
TextureCube<float4> skyBox;
|
||||||
SamplerState skyBoxSampler;
|
SamplerState skyBoxSampler;
|
||||||
};
|
};
|
||||||
layout(set=5)
|
|
||||||
ParameterBlock<RayTracingParams> pRayTracingParams;
|
ParameterBlock<RayTracingParams> pRayTracingParams;
|
||||||
|
|
||||||
struct RayPayload
|
struct RayPayload
|
||||||
|
|||||||
@@ -78,5 +78,3 @@ void PlayView::render() {
|
|||||||
GameView::render();
|
GameView::render();
|
||||||
renderTimestamp->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "RenderEnd");
|
renderTimestamp->write(Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT, "RenderEnd");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) { GameView::keyCallback(code, action, modifier); }
|
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ class PlayView : public GameView {
|
|||||||
virtual void prepareRender() override;
|
virtual void prepareRender() override;
|
||||||
virtual void render() override;
|
virtual void render() override;
|
||||||
|
|
||||||
virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::thread queryThread;
|
std::thread queryThread;
|
||||||
Gfx::OTimestampQuery renderTimestamp;
|
Gfx::OTimestampQuery renderTimestamp;
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ EnvironmentLoader::EnvironmentLoader(Gfx::PGraphics graphics) : graphics(graphic
|
|||||||
{"precomputeBRDF", "EnvironmentMapping"},
|
{"precomputeBRDF", "EnvironmentMapping"},
|
||||||
},
|
},
|
||||||
.rootSignature = cubePipelineLayout,
|
.rootSignature = cubePipelineLayout,
|
||||||
.dumpIntermediate = true,
|
|
||||||
});
|
});
|
||||||
cubePipelineLayout->create();
|
cubePipelineLayout->create();
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include "Asset/AssetRegistry.h"
|
#include "Asset/AssetRegistry.h"
|
||||||
#include "Asset/TextureAsset.h"
|
#include "Asset/TextureAsset.h"
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
#include "Graphics/Vulkan/Enums.h"
|
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
@@ -15,7 +14,7 @@
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#include "ktx.h"
|
#include "ktx.h"
|
||||||
#include <ThreadPool.h>
|
#include <ThreadPool.h>
|
||||||
#include <fstream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
@@ -60,9 +59,8 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) {
|
|||||||
int totalWidth = 0, totalHeight = 0, n = 0;
|
int totalWidth = 0, totalHeight = 0, n = 0;
|
||||||
unsigned char* data = stbi_load(args.filePath.string().c_str(), &totalWidth, &totalHeight, &n, 4);
|
unsigned char* data = stbi_load(args.filePath.string().c_str(), &totalWidth, &totalHeight, &n, 4);
|
||||||
ktxTexture2* kTexture = nullptr;
|
ktxTexture2* kTexture = nullptr;
|
||||||
VkFormat format = VK_FORMAT_R8G8B8A8_SRGB;
|
|
||||||
ktxTextureCreateInfo createInfo = {
|
ktxTextureCreateInfo createInfo = {
|
||||||
.vkFormat = (uint32)format,
|
.vkFormat = 43, // rgba8srgb
|
||||||
.baseDepth = 1,
|
.baseDepth = 1,
|
||||||
.numLevels = 1,
|
.numLevels = 1,
|
||||||
.numLayers = 1,
|
.numLayers = 1,
|
||||||
@@ -116,7 +114,7 @@ void TextureLoader::import(TextureImportArgs args, PTextureAsset textureAsset) {
|
|||||||
.uastcFlags = KTX_PACK_UASTC_LEVEL_DEFAULT,
|
.uastcFlags = KTX_PACK_UASTC_LEVEL_DEFAULT,
|
||||||
.uastcRDO = true,
|
.uastcRDO = true,
|
||||||
};
|
};
|
||||||
KTX_ASSERT(ktxTexture2_CompressBasisEx(kTexture, &basisParams));
|
// KTX_ASSERT(ktxTexture2_CompressBasis(kTexture, 0));
|
||||||
//KTX_ASSERT(ktxTexture2_DeflateZstd(kTexture, 10));
|
//KTX_ASSERT(ktxTexture2_DeflateZstd(kTexture, 10));
|
||||||
|
|
||||||
char writer[100];
|
char writer[100];
|
||||||
|
|||||||
@@ -38,11 +38,11 @@ void InspectorView::render() { renderGraph.render(Component::Camera(), Component
|
|||||||
|
|
||||||
void InspectorView::applyArea(URect ) {}
|
void InspectorView::applyArea(URect ) {}
|
||||||
|
|
||||||
void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier) {}
|
void InspectorView::keyCallback(KeyCode, InputAction, KeyModifierFlags) {}
|
||||||
|
|
||||||
void InspectorView::mouseMoveCallback(double, double) {}
|
void InspectorView::mouseMoveCallback(double, double) {}
|
||||||
|
|
||||||
void InspectorView::mouseButtonCallback(MouseButton, InputAction, KeyModifier) {}
|
void InspectorView::mouseButtonCallback(MouseButton, InputAction, KeyModifierFlags) {}
|
||||||
|
|
||||||
void InspectorView::scrollCallback(double, double) {}
|
void InspectorView::scrollCallback(double, double) {}
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ class InspectorView : public View {
|
|||||||
RenderGraph renderGraph;
|
RenderGraph renderGraph;
|
||||||
Component::Camera cam;
|
Component::Camera cam;
|
||||||
|
|
||||||
virtual void keyCallback(KeyCode code, InputAction action, KeyModifier modifier) override;
|
virtual void keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) override;
|
||||||
virtual void mouseMoveCallback(double xPos, double yPos) override;
|
virtual void mouseMoveCallback(double xPos, double yPos) override;
|
||||||
virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier) override;
|
virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags modifier) override;
|
||||||
virtual void scrollCallback(double xOffset, double yOffset) override;
|
virtual void scrollCallback(double xOffset, double yOffset) override;
|
||||||
virtual void fileCallback(int count, const char** paths) override;
|
virtual void fileCallback(int count, const char** paths) override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "Graphics/Enums.h"
|
#include "Graphics/Enums.h"
|
||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
#include "Window/Window.h"
|
#include "Window/Window.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Editor;
|
using namespace Seele::Editor;
|
||||||
@@ -21,7 +22,7 @@ void PlayView::prepareRender() { GameView::prepareRender(); }
|
|||||||
|
|
||||||
void PlayView::render() { GameView::render(); }
|
void PlayView::render() { GameView::render(); }
|
||||||
|
|
||||||
void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) {
|
void PlayView::keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) {
|
||||||
GameView::keyCallback(code, action, modifier);
|
GameView::keyCallback(code, action, modifier);
|
||||||
if (code == KeyCode::KEY_P && action == InputAction::RELEASE) {
|
if (code == KeyCode::KEY_P && action == InputAction::RELEASE) {
|
||||||
getGlobals().usePositionOnly = !getGlobals().usePositionOnly;
|
getGlobals().usePositionOnly = !getGlobals().usePositionOnly;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class PlayView : public GameView {
|
|||||||
virtual void prepareRender() override;
|
virtual void prepareRender() override;
|
||||||
virtual void render() override;
|
virtual void render() override;
|
||||||
|
|
||||||
virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override;
|
virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifierFlags modifier) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ void SceneView::prepareRender() {}
|
|||||||
|
|
||||||
void SceneView::render() { renderGraph.render(viewportCamera, Component::Transform()); }
|
void SceneView::render() { renderGraph.render(viewportCamera, Component::Transform()); }
|
||||||
|
|
||||||
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier) { cameraSystem.keyCallback(code, action); }
|
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifierFlags) { cameraSystem.keyCallback(code, action); }
|
||||||
|
|
||||||
void SceneView::mouseMoveCallback(double xPos, double yPos) { cameraSystem.mouseMoveCallback(xPos, yPos); }
|
void SceneView::mouseMoveCallback(double xPos, double yPos) { cameraSystem.mouseMoveCallback(xPos, yPos); }
|
||||||
|
|
||||||
void SceneView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifier) {
|
void SceneView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags) {
|
||||||
cameraSystem.mouseButtonCallback(button, action);
|
cameraSystem.mouseButtonCallback(button, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ class SceneView : public View {
|
|||||||
|
|
||||||
ViewportControl cameraSystem;
|
ViewportControl cameraSystem;
|
||||||
|
|
||||||
virtual void keyCallback(KeyCode code, InputAction action, KeyModifier modifier) override;
|
virtual void keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) override;
|
||||||
virtual void mouseMoveCallback(double xPos, double yPos) override;
|
virtual void mouseMoveCallback(double xPos, double yPos) override;
|
||||||
virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier) override;
|
virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags modifier) override;
|
||||||
virtual void scrollCallback(double xOffset, double yOffset) override;
|
virtual void scrollCallback(double xOffset, double yOffset) override;
|
||||||
virtual void fileCallback(int count, const char** paths) override;
|
virtual void fileCallback(int count, const char** paths) override;
|
||||||
};
|
};
|
||||||
|
|||||||
+15
-9
@@ -4,11 +4,12 @@
|
|||||||
#include "Asset/FontLoader.h"
|
#include "Asset/FontLoader.h"
|
||||||
#include "Asset/MaterialLoader.h"
|
#include "Asset/MaterialLoader.h"
|
||||||
#include "Asset/MeshLoader.h"
|
#include "Asset/MeshLoader.h"
|
||||||
|
#include "Graphics/Vulkan/Graphics.h"
|
||||||
#include "Asset/TextureLoader.h"
|
#include "Asset/TextureLoader.h"
|
||||||
#include "Graphics/Initializer.h"
|
#include "Graphics/Initializer.h"
|
||||||
#include "Material/Material.h"
|
#include "Material/Material.h"
|
||||||
#include "Graphics/StaticMeshVertexData.h"
|
|
||||||
#include "Graphics/Vulkan/Graphics.h"
|
#include "Graphics/Vulkan/Graphics.h"
|
||||||
|
#include "Graphics/StaticMeshVertexData.h"
|
||||||
#include "Window/PlayView.h"
|
#include "Window/PlayView.h"
|
||||||
#include "Window/WindowManager.h"
|
#include "Window/WindowManager.h"
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
@@ -20,7 +21,7 @@ using namespace Seele::Editor;
|
|||||||
static Gfx::OGraphics graphics;
|
static Gfx::OGraphics graphics;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
std::string gameName = "MeshShadingDemo";
|
std::string gameName = "FluidSimulation";
|
||||||
std::filesystem::path outputPath = fmt::format("/home/dynamitos/{0}Game/", gameName);
|
std::filesystem::path outputPath = fmt::format("/home/dynamitos/{0}Game/", gameName);
|
||||||
std::filesystem::path sourcePath = fmt::format("/home/dynamitos/{0}/", gameName);
|
std::filesystem::path sourcePath = fmt::format("/home/dynamitos/{0}/", gameName);
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -30,7 +31,7 @@ int main() {
|
|||||||
#else
|
#else
|
||||||
std::string libraryEnding = "so";
|
std::string libraryEnding = "so";
|
||||||
#endif
|
#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";
|
std::filesystem::path cmakePath = outputPath / "cmake";
|
||||||
if (true) {
|
if (true) {
|
||||||
graphics = new Vulkan::Graphics();
|
graphics = new Vulkan::Graphics();
|
||||||
@@ -46,7 +47,7 @@ int main() {
|
|||||||
.filePath = "./fonts/arial.ttf",
|
.filePath = "./fonts/arial.ttf",
|
||||||
});
|
});
|
||||||
AssetImporter::importEnvironmentMap(EnvironmentImportArgs{
|
AssetImporter::importEnvironmentMap(EnvironmentImportArgs{
|
||||||
.filePath = sourcePath / "import" / "textures" / "newport_loft.hdr",
|
.filePath = sourcePath / "import" / "newport_loft.hdr",
|
||||||
});
|
});
|
||||||
// AssetImporter::importTexture(TextureImportArgs{
|
// AssetImporter::importTexture(TextureImportArgs{
|
||||||
// .filePath = sourcePath / "import" / "textures" / "grass_block_side.png",
|
// .filePath = sourcePath / "import" / "textures" / "grass_block_side.png",
|
||||||
@@ -56,12 +57,17 @@ int main() {
|
|||||||
// .filePath = sourcePath / "import" / "models" / "main1_sponza" / "sponza.gltf",
|
// .filePath = sourcePath / "import" / "models" / "main1_sponza" / "sponza.gltf",
|
||||||
// .importPath = "sponza",
|
// .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{
|
AssetImporter::importMesh(MeshImportArgs{
|
||||||
.filePath = sourcePath / "import" / "models" / "cube.fbx",
|
.filePath = sourcePath / "import" / "rttest.gltf",
|
||||||
.importPath = "",
|
|
||||||
});
|
|
||||||
AssetImporter::importMesh(MeshImportArgs{
|
|
||||||
.filePath = sourcePath / "import" / "models" / "rttest.gltf",
|
|
||||||
.importPath = "rttest",
|
.importPath = "rttest",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#include "TextureAsset.h"
|
#include "TextureAsset.h"
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
#include "Graphics/Texture.h"
|
#include "Graphics/Texture.h"
|
||||||
#include "Graphics/Vulkan/Enums.h"
|
|
||||||
#include "Window/WindowManager.h"
|
#include "Window/WindowManager.h"
|
||||||
#include "ktx.h"
|
#include "ktx.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ target_sources(Engine
|
|||||||
Collider.cpp
|
Collider.cpp
|
||||||
Component.h
|
Component.h
|
||||||
DirectionalLight.h
|
DirectionalLight.h
|
||||||
|
FluidGrid.h
|
||||||
KeyboardInput.h
|
KeyboardInput.h
|
||||||
Mesh.h
|
Mesh.h
|
||||||
MeshCollider.h
|
MeshCollider.h
|
||||||
@@ -29,6 +30,7 @@ target_sources(Engine
|
|||||||
Collider.h
|
Collider.h
|
||||||
Component.h
|
Component.h
|
||||||
DirectionalLight.h
|
DirectionalLight.h
|
||||||
|
FluidGrid.h
|
||||||
KeyboardInput.h
|
KeyboardInput.h
|
||||||
MeshCollider.h
|
MeshCollider.h
|
||||||
Mesh.h
|
Mesh.h
|
||||||
|
|||||||
@@ -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,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <memory>
|
||||||
#include <memory_resource>
|
#include <memory_resource>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <string>
|
||||||
#include <memory_resource>
|
#include <memory_resource>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class RenderCommand {
|
|||||||
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) = 0;
|
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 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 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 drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) = 0;
|
||||||
virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) = 0;
|
virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) = 0;
|
||||||
virtual void traceRays(uint32 width, uint32 height, uint32 depth) = 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 bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) = 0;
|
||||||
virtual void pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) = 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(uint32 threadX, uint32 threadY, uint32 threadZ) = 0;
|
||||||
|
virtual void dispatch(UVector threadGroupSize) = 0;
|
||||||
virtual void dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) = 0;
|
virtual void dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) = 0;
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ class DescriptorSet {
|
|||||||
DescriptorSet(PDescriptorLayout layout);
|
DescriptorSet(PDescriptorLayout layout);
|
||||||
virtual ~DescriptorSet();
|
virtual ~DescriptorSet();
|
||||||
virtual void writeChanges() = 0;
|
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::PShaderBuffer shaderBuffer) = 0;
|
||||||
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer vertexBuffer) = 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::PIndexBuffer indexBuffer) = 0;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
#include "RenderTarget.h"
|
#include "RenderTarget.h"
|
||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
|
#define ENABLE_VALIDATION
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
namespace Gfx {
|
namespace Gfx {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ void DescriptorLayout::create() {
|
|||||||
MTL::ArgumentDescriptor** objects = new MTL::ArgumentDescriptor*[descriptorBindings.size()];
|
MTL::ArgumentDescriptor** objects = new MTL::ArgumentDescriptor*[descriptorBindings.size()];
|
||||||
uint32 mappingCounter = 0;
|
uint32 mappingCounter = 0;
|
||||||
for (uint32 i = 0; i < descriptorBindings.size(); ++i) {
|
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;
|
plainDescriptor = false;
|
||||||
}
|
}
|
||||||
objects[i] = MTL::ArgumentDescriptor::alloc()->init();
|
objects[i] = MTL::ArgumentDescriptor::alloc()->init();
|
||||||
@@ -116,13 +116,11 @@ void DescriptorSetHandle::updateBuffer(const std::string& name, uint32 index, Gf
|
|||||||
|
|
||||||
void DescriptorSetHandle::updateBuffer(const std::string& name, uint32 index, Gfx::PUniformBuffer uniformBuffer) {
|
void DescriptorSetHandle::updateBuffer(const std::string& name, uint32 index, Gfx::PUniformBuffer uniformBuffer) {
|
||||||
uint32 flattenedIndex = owner->getLayout()->variableMapping[name].index + index;
|
uint32 flattenedIndex = owner->getLayout()->variableMapping[name].index + index;
|
||||||
PIndexBuffer buffer = uniformBuffer.cast<IndexBuffer>();
|
PUniformBuffer buffer = uniformBuffer.cast<UniformBuffer>();
|
||||||
bufferWrites.add(BufferWriteInfo{
|
uniformWrites.add(UniformWriteInfo{
|
||||||
.index = flattenedIndex,
|
.index = flattenedIndex,
|
||||||
.buffer = buffer->getAlloc(),
|
.content = buffer->getContents(),
|
||||||
.access = owner->getLayout()->variableMapping[name].access,
|
|
||||||
});
|
});
|
||||||
boundResources.add(buffer->getAlloc());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorSetHandle::updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) {
|
void DescriptorSetHandle::updateSampler(const std::string& name, uint32 index, Gfx::PSampler samplerState) {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Graphics/Query.h"
|
#include "Graphics/Query.h"
|
||||||
#include <vulkan/vulkan_core.h>
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Metal;
|
using namespace Seele::Metal;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "BasePass.h"
|
#include "BasePass.h"
|
||||||
#include "Asset/AssetRegistry.h"
|
#include "Asset/AssetRegistry.h"
|
||||||
|
#include "Asset/EnvironmentMapAsset.h"
|
||||||
#include "Component/Camera.h"
|
#include "Component/Camera.h"
|
||||||
#include "Graphics/Command.h"
|
#include "Graphics/Command.h"
|
||||||
#include "Graphics/Descriptor.h"
|
#include "Graphics/Descriptor.h"
|
||||||
@@ -12,10 +13,9 @@
|
|||||||
#include "Math/Matrix.h"
|
#include "Math/Matrix.h"
|
||||||
#include "Math/Vector.h"
|
#include "Math/Vector.h"
|
||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
#include "ShadowPass.h"
|
|
||||||
#include "Scene/Scene.h"
|
|
||||||
#include "Asset/EnvironmentMapAsset.h"
|
|
||||||
#include "Scene/LightEnvironment.h"
|
#include "Scene/LightEnvironment.h"
|
||||||
|
#include "Scene/Scene.h"
|
||||||
|
#include "ShadowPass.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
@@ -59,10 +59,8 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics)
|
|||||||
.name = SHADOWSAMPLER_NAME,
|
.name = SHADOWSAMPLER_NAME,
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
||||||
});
|
});
|
||||||
shadowMappingLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
shadowMappingLayout->addDescriptorBinding(
|
||||||
.name = CASCADE_SPLIT_NAME,
|
Gfx::DescriptorBinding{.name = CASCADE_SPLIT_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER});
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER
|
|
||||||
});
|
|
||||||
shadowMappingLayout->create();
|
shadowMappingLayout->create();
|
||||||
|
|
||||||
basePassLayout->addDescriptorLayout(lightCullingLayout);
|
basePassLayout->addDescriptorLayout(lightCullingLayout);
|
||||||
@@ -116,6 +114,58 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics)
|
|||||||
.minLod = 0.0f,
|
.minLod = 0.0f,
|
||||||
.borderColor = Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
|
.borderColor = Gfx::SE_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
|
||||||
});
|
});
|
||||||
|
debugPipelineLayout = graphics->createPipelineLayout("DebugPassLayout");
|
||||||
|
debugPipelineLayout->addDescriptorLayout(viewParamsLayout);
|
||||||
|
|
||||||
|
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||||
|
.name = "DebugVertex",
|
||||||
|
.modules = {"Debug"},
|
||||||
|
.entryPoints =
|
||||||
|
{
|
||||||
|
{"vertexMain", "Debug"},
|
||||||
|
{"fragmentMain", "Debug"},
|
||||||
|
},
|
||||||
|
.rootSignature = debugPipelineLayout,
|
||||||
|
});
|
||||||
|
debugVertexShader = graphics->createVertexShader({0});
|
||||||
|
debugFragmentShader = graphics->createFragmentShader({1});
|
||||||
|
debugPipelineLayout->create();
|
||||||
|
|
||||||
|
skyboxDataLayout = graphics->createDescriptorLayout("pSkyboxData");
|
||||||
|
skyboxDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.name = "transformMatrix", .uniformLength = sizeof(Matrix4)});
|
||||||
|
skyboxDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.name = "fogBlend", .uniformLength = sizeof(Vector4)});
|
||||||
|
skyboxDataLayout->create();
|
||||||
|
textureLayout = graphics->createDescriptorLayout("pSkyboxTextures");
|
||||||
|
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = SKYBOXDAY_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
|
||||||
|
});
|
||||||
|
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = SKYBOXNIGHT_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
|
||||||
|
});
|
||||||
|
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = SKYBOXSAMPLER_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
||||||
|
});
|
||||||
|
textureLayout->create();
|
||||||
|
|
||||||
|
pipelineLayout = graphics->createPipelineLayout("SkyboxLayout");
|
||||||
|
pipelineLayout->addDescriptorLayout(viewParamsLayout);
|
||||||
|
pipelineLayout->addDescriptorLayout(skyboxDataLayout);
|
||||||
|
pipelineLayout->addDescriptorLayout(textureLayout);
|
||||||
|
|
||||||
|
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||||
|
.name = "SkyboxVertex",
|
||||||
|
.modules = {"Skybox"},
|
||||||
|
.entryPoints = {{"vertexMain", "Skybox"}, {"fragmentMain", "Skybox"}},
|
||||||
|
.rootSignature = pipelineLayout,
|
||||||
|
});
|
||||||
|
vertexShader = graphics->createVertexShader({0});
|
||||||
|
fragmentShader = graphics->createFragmentShader({1});
|
||||||
|
pipelineLayout->create();
|
||||||
}
|
}
|
||||||
|
|
||||||
BasePass::~BasePass() {}
|
BasePass::~BasePass() {}
|
||||||
@@ -268,7 +318,8 @@ void BasePass::render() {
|
|||||||
command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo)));
|
command->bindPipeline(graphics->createGraphicsPipeline(std::move(pipelineInfo)));
|
||||||
}
|
}
|
||||||
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(),
|
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(),
|
||||||
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), shadowMapping, opaqueCulling});
|
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), shadowMapping,
|
||||||
|
opaqueCulling});
|
||||||
for (const auto& drawCall : materialData.instances) {
|
for (const auto& drawCall : materialData.instances) {
|
||||||
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT |
|
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT |
|
||||||
Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
|
Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
@@ -382,8 +433,8 @@ void BasePass::render() {
|
|||||||
transparentCommand->bindPipeline(pipeline);
|
transparentCommand->bindPipeline(pipeline);
|
||||||
}
|
}
|
||||||
transparentCommand->bindDescriptor({viewParamsSet, t.vertexData->getVertexDataSet(), t.vertexData->getInstanceDataSet(),
|
transparentCommand->bindDescriptor({viewParamsSet, t.vertexData->getVertexDataSet(), t.vertexData->getInstanceDataSet(),
|
||||||
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), shadowMapping,
|
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(),
|
||||||
transparentCulling});
|
shadowMapping, transparentCulling});
|
||||||
transparentCommand->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT |
|
transparentCommand->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT |
|
||||||
Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
|
Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
|
||||||
0, sizeof(VertexData::DrawCallOffsets), &t.offsets);
|
0, sizeof(VertexData::DrawCallOffsets), &t.offsets);
|
||||||
@@ -536,24 +587,6 @@ void BasePass::createRenderPass() {
|
|||||||
|
|
||||||
// Debug rendering
|
// Debug rendering
|
||||||
{
|
{
|
||||||
debugPipelineLayout = graphics->createPipelineLayout("DebugPassLayout");
|
|
||||||
debugPipelineLayout->addDescriptorLayout(viewParamsLayout);
|
|
||||||
|
|
||||||
ShaderCompilationInfo createInfo = {
|
|
||||||
.name = "DebugVertex",
|
|
||||||
.modules = {"Debug"},
|
|
||||||
.entryPoints =
|
|
||||||
{
|
|
||||||
{"vertexMain", "Debug"},
|
|
||||||
{"fragmentMain", "Debug"},
|
|
||||||
},
|
|
||||||
.rootSignature = debugPipelineLayout,
|
|
||||||
};
|
|
||||||
graphics->beginShaderCompilation(createInfo);
|
|
||||||
debugVertexShader = graphics->createVertexShader({0});
|
|
||||||
debugFragmentShader = graphics->createFragmentShader({1});
|
|
||||||
debugPipelineLayout->create();
|
|
||||||
|
|
||||||
VertexInputStateCreateInfo inputCreate = {
|
VertexInputStateCreateInfo inputCreate = {
|
||||||
.bindings =
|
.bindings =
|
||||||
{
|
{
|
||||||
@@ -605,27 +638,6 @@ void BasePass::createRenderPass() {
|
|||||||
}
|
}
|
||||||
// Skybox
|
// Skybox
|
||||||
{
|
{
|
||||||
skyboxDataLayout = graphics->createDescriptorLayout("pSkyboxData");
|
|
||||||
skyboxDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.name = "transformMatrix", .uniformLength = sizeof(Matrix4)});
|
|
||||||
skyboxDataLayout->addDescriptorBinding(Gfx::DescriptorBinding{.name = "fogBlend", .uniformLength = sizeof(Vector4)});
|
|
||||||
skyboxDataLayout->create();
|
|
||||||
textureLayout = graphics->createDescriptorLayout("pSkyboxTextures");
|
|
||||||
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = SKYBOXDAY_NAME,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
|
||||||
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
|
|
||||||
});
|
|
||||||
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = SKYBOXNIGHT_NAME,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
|
||||||
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
|
|
||||||
});
|
|
||||||
textureLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = SKYBOXSAMPLER_NAME,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
|
||||||
});
|
|
||||||
textureLayout->create();
|
|
||||||
|
|
||||||
skyboxSampler = graphics->createSampler({
|
skyboxSampler = graphics->createSampler({
|
||||||
.magFilter = Gfx::SE_FILTER_LINEAR,
|
.magFilter = Gfx::SE_FILTER_LINEAR,
|
||||||
.minFilter = Gfx::SE_FILTER_LINEAR,
|
.minFilter = Gfx::SE_FILTER_LINEAR,
|
||||||
@@ -642,23 +654,6 @@ void BasePass::createRenderPass() {
|
|||||||
skyboxData.fogColor = skybox.fogColor;
|
skyboxData.fogColor = skybox.fogColor;
|
||||||
skyboxData.blendFactor = skybox.blendFactor;
|
skyboxData.blendFactor = skybox.blendFactor;
|
||||||
|
|
||||||
pipelineLayout = graphics->createPipelineLayout("SkyboxLayout");
|
|
||||||
pipelineLayout->addDescriptorLayout(viewParamsLayout);
|
|
||||||
pipelineLayout->addDescriptorLayout(skyboxDataLayout);
|
|
||||||
pipelineLayout->addDescriptorLayout(textureLayout);
|
|
||||||
|
|
||||||
ShaderCompilationInfo createInfo = {
|
|
||||||
.name = "SkyboxVertex",
|
|
||||||
.modules = {"Skybox"},
|
|
||||||
.entryPoints = {{"vertexMain", "Skybox"}, {"fragmentMain", "Skybox"}},
|
|
||||||
.rootSignature = pipelineLayout,
|
|
||||||
};
|
|
||||||
graphics->beginShaderCompilation(createInfo);
|
|
||||||
vertexShader = graphics->createVertexShader({0});
|
|
||||||
fragmentShader = graphics->createFragmentShader({1});
|
|
||||||
|
|
||||||
pipelineLayout->create();
|
|
||||||
|
|
||||||
Gfx::LegacyPipelineCreateInfo gfxInfo = {
|
Gfx::LegacyPipelineCreateInfo gfxInfo = {
|
||||||
.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||||
.vertexShader = vertexShader,
|
.vertexShader = vertexShader,
|
||||||
@@ -673,7 +668,8 @@ void BasePass::createRenderPass() {
|
|||||||
{
|
{
|
||||||
.polygonMode = Gfx::SE_POLYGON_MODE_FILL,
|
.polygonMode = Gfx::SE_POLYGON_MODE_FILL,
|
||||||
},
|
},
|
||||||
.depthStencilState = {
|
.depthStencilState =
|
||||||
|
{
|
||||||
.depthTestEnable = true,
|
.depthTestEnable = true,
|
||||||
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
|
.depthCompareOp = Gfx::SE_COMPARE_OP_GREATER,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "Graphics/Buffer.h"
|
#include "Graphics/Buffer.h"
|
||||||
#include "Graphics/Descriptor.h"
|
#include "Graphics/Descriptor.h"
|
||||||
#include "Graphics/RenderPass/ShadowPass.h"
|
#include "Graphics/RenderPass/ShadowPass.h"
|
||||||
|
#include "Component/Skybox.h"
|
||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
#include "RenderPass.h"
|
#include "RenderPass.h"
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ target_sources(Engine
|
|||||||
CachedDepthPass.cpp
|
CachedDepthPass.cpp
|
||||||
DepthCullingPass.h
|
DepthCullingPass.h
|
||||||
DepthCullingPass.cpp
|
DepthCullingPass.cpp
|
||||||
|
FluidRenderPass.h
|
||||||
|
FluidRenderPass.cpp
|
||||||
LightCullingPass.h
|
LightCullingPass.h
|
||||||
LightCullingPass.cpp
|
LightCullingPass.cpp
|
||||||
RayTracingPass.h
|
RayTracingPass.h
|
||||||
@@ -17,6 +19,10 @@ target_sources(Engine
|
|||||||
RenderPass.cpp
|
RenderPass.cpp
|
||||||
ShadowPass.h
|
ShadowPass.h
|
||||||
ShadowPass.cpp
|
ShadowPass.cpp
|
||||||
|
SimulationComputePass.h
|
||||||
|
SimulationComputePass.cpp
|
||||||
|
SurfaceExtractPass.h
|
||||||
|
SurfaceExtractPass.cpp
|
||||||
#TerrainRenderer.h
|
#TerrainRenderer.h
|
||||||
#TerrainRenderer.cpp
|
#TerrainRenderer.cpp
|
||||||
ToneMappingPass.h
|
ToneMappingPass.h
|
||||||
@@ -34,6 +40,7 @@ target_sources(Engine
|
|||||||
BasePass.h
|
BasePass.h
|
||||||
CachedDepthPass.h
|
CachedDepthPass.h
|
||||||
DepthCullingPass.h
|
DepthCullingPass.h
|
||||||
|
FluidRenderPass.h
|
||||||
LightCullingPass.h
|
LightCullingPass.h
|
||||||
ToneMappingPass.h
|
ToneMappingPass.h
|
||||||
RayTracingPass.h
|
RayTracingPass.h
|
||||||
@@ -41,6 +48,8 @@ target_sources(Engine
|
|||||||
RenderGraphResources.h
|
RenderGraphResources.h
|
||||||
RenderPass.h
|
RenderPass.h
|
||||||
ShadowPass.h
|
ShadowPass.h
|
||||||
|
SimulationComputePass.h
|
||||||
|
SurfaceExtractPass.h
|
||||||
#TerrainRenderer.h
|
#TerrainRenderer.h
|
||||||
UIPass.h
|
UIPass.h
|
||||||
VisibilityPass.h)
|
VisibilityPass.h)
|
||||||
@@ -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,
|
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = sizeof(VertexData::DrawCallOffsets),
|
.size = sizeof(VertexData::DrawCallOffsets),
|
||||||
|
.name = "pOffsets"
|
||||||
});
|
});
|
||||||
if (graphics->supportMeshShading()) {
|
if (graphics->supportMeshShading()) {
|
||||||
graphics->getShaderCompiler()->registerRenderPass("CachedDepthPass", Gfx::PassConfig{
|
graphics->getShaderCompiler()->registerRenderPass("CachedDepthPass", Gfx::PassConfig{
|
||||||
|
|||||||
@@ -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,
|
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = sizeof(VertexData::DrawCallOffsets),
|
.size = sizeof(VertexData::DrawCallOffsets),
|
||||||
|
.name = "pOffsets"
|
||||||
});
|
});
|
||||||
|
|
||||||
depthComputeLayout = graphics->createPipelineLayout("DepthComputeLayout");
|
depthComputeLayout = graphics->createPipelineLayout("DepthComputeLayout");
|
||||||
@@ -34,7 +35,26 @@ DepthCullingPass::DepthCullingPass(Gfx::PGraphics graphics, PScene scene) : Rend
|
|||||||
.stageFlags = Gfx::SE_SHADER_STAGE_COMPUTE_BIT,
|
.stageFlags = Gfx::SE_SHADER_STAGE_COMPUTE_BIT,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = sizeof(MipParam),
|
.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()) {
|
if (graphics->supportMeshShading()) {
|
||||||
graphics->getShaderCompiler()->registerRenderPass("DepthPass", Gfx::PassConfig{
|
graphics->getShaderCompiler()->registerRenderPass("DepthPass", Gfx::PassConfig{
|
||||||
@@ -253,24 +273,6 @@ void DepthCullingPass::publishOutputs() {
|
|||||||
.name = "DepthMipBuffer",
|
.name = "DepthMipBuffer",
|
||||||
});
|
});
|
||||||
|
|
||||||
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
|
||||||
.name = "DepthMipCompute",
|
|
||||||
.modules = {"DepthMipGen"},
|
|
||||||
.entryPoints = {{"sourceCopy", "DepthMipGen"}, {"reduceLevel", "DepthMipGen"}},
|
|
||||||
.rootSignature = depthComputeLayout,
|
|
||||||
});
|
|
||||||
depthSourceCopyShader = graphics->createComputeShader({0});
|
|
||||||
depthComputeLayout->create();
|
|
||||||
|
|
||||||
Gfx::ComputePipelineCreateInfo pipelineCreateInfo = {
|
|
||||||
.computeShader = depthSourceCopyShader,
|
|
||||||
.pipelineLayout = depthComputeLayout,
|
|
||||||
};
|
|
||||||
depthSourceCopy = graphics->createComputePipeline(pipelineCreateInfo);
|
|
||||||
|
|
||||||
depthReduceLevelShader = graphics->createComputeShader({1});
|
|
||||||
pipelineCreateInfo.computeShader = depthReduceLevelShader;
|
|
||||||
depthReduceLevel = graphics->createComputePipeline(pipelineCreateInfo);
|
|
||||||
|
|
||||||
query = graphics->createPipelineStatisticsQuery("DepthPipelineStatistics");
|
query = graphics->createPipelineStatisticsQuery("DepthPipelineStatistics");
|
||||||
resources->registerQueryOutput("DEPTH_QUERY", query);
|
resources->registerQueryOutput("DEPTH_QUERY", query);
|
||||||
|
|||||||
@@ -0,0 +1,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 "Math/Vector.h"
|
||||||
#include "RenderGraph.h"
|
#include "RenderGraph.h"
|
||||||
#include "Scene/Scene.h"
|
#include "Scene/Scene.h"
|
||||||
|
#include "Scene/LightEnvironment.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {}
|
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics), scene(scene) {
|
||||||
|
dispatchParamsLayout = graphics->createDescriptorLayout("pDispatchParams");
|
||||||
|
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = "numThreadGroups",
|
||||||
|
.uniformLength = sizeof(UVector4),
|
||||||
|
});
|
||||||
|
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = "numThreads",
|
||||||
|
.uniformLength = sizeof(UVector4),
|
||||||
|
});
|
||||||
|
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = FRUSTUMBUFFER_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
||||||
|
});
|
||||||
|
dispatchParamsLayout->create();
|
||||||
|
frustumLayout = graphics->createPipelineLayout("FrustumLayout");
|
||||||
|
frustumLayout->addDescriptorLayout(viewParamsLayout);
|
||||||
|
frustumLayout->addDescriptorLayout(dispatchParamsLayout);
|
||||||
|
ShaderCompilationInfo createInfo = {
|
||||||
|
.name = "Frustum",
|
||||||
|
.modules = {"ComputeFrustums"},
|
||||||
|
.entryPoints = {{"computeFrustums", "ComputeFrustums"}},
|
||||||
|
.rootSignature = frustumLayout,
|
||||||
|
};
|
||||||
|
graphics->beginShaderCompilation(createInfo);
|
||||||
|
frustumShader = graphics->createComputeShader({0});
|
||||||
|
// Have to compile shader before finalizing layout as parameters get mapped later
|
||||||
|
frustumLayout->create();
|
||||||
|
|
||||||
|
Gfx::ComputePipelineCreateInfo pipelineInfo;
|
||||||
|
pipelineInfo.computeShader = frustumShader;
|
||||||
|
pipelineInfo.pipelineLayout = frustumLayout;
|
||||||
|
frustumPipeline = graphics->createComputePipeline(pipelineInfo);
|
||||||
|
|
||||||
|
cullingDescriptorLayout = graphics->createDescriptorLayout("pCullingParams");
|
||||||
|
|
||||||
|
// DepthTexture
|
||||||
|
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = DEPTHATTACHMENT_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
|
||||||
|
});
|
||||||
|
// o_lightIndexCounter
|
||||||
|
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = OLIGHTINDEXCOUNTER_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
||||||
|
});
|
||||||
|
// t_lightIndexCounter
|
||||||
|
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = TLIGHTINDEXCOUNTER_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
||||||
|
});
|
||||||
|
// o_lightIndexList
|
||||||
|
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = OLIGHTINDEXLIST_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
||||||
|
});
|
||||||
|
// t_lightIndexList
|
||||||
|
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = TLIGHTINDEXLIST_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
||||||
|
});
|
||||||
|
// o_lightGrid
|
||||||
|
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = OLIGHTGRID_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
||||||
|
});
|
||||||
|
// t_lightGrid
|
||||||
|
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = TLIGHTGRID_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
||||||
|
});
|
||||||
|
|
||||||
|
cullingDescriptorLayout->create();
|
||||||
|
|
||||||
|
lightEnv = scene->getLightEnvironment();
|
||||||
|
|
||||||
|
{
|
||||||
|
cullingLayout = graphics->createPipelineLayout("CullingLayout");
|
||||||
|
cullingLayout->addDescriptorLayout(viewParamsLayout);
|
||||||
|
cullingLayout->addDescriptorLayout(dispatchParamsLayout);
|
||||||
|
cullingLayout->addDescriptorLayout(cullingDescriptorLayout);
|
||||||
|
cullingLayout->addDescriptorLayout(lightEnv->getDescriptorLayout());
|
||||||
|
|
||||||
|
ShaderCompilationInfo createInfo = {
|
||||||
|
.name = "Culling",
|
||||||
|
.modules = {"LightCulling"},
|
||||||
|
.entryPoints = {{"cullLights", "LightCulling"}},
|
||||||
|
.rootSignature = cullingLayout,
|
||||||
|
};
|
||||||
|
graphics->beginShaderCompilation(createInfo);
|
||||||
|
cullingShader = graphics->createComputeShader({0});
|
||||||
|
cullingLayout->create();
|
||||||
|
|
||||||
|
Gfx::ComputePipelineCreateInfo pipelineInfo;
|
||||||
|
pipelineInfo.computeShader = cullingShader;
|
||||||
|
pipelineInfo.pipelineLayout = cullingLayout;
|
||||||
|
cullingPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
cullingEnableLayout = graphics->createPipelineLayout("CullingEnabledLayout");
|
||||||
|
cullingEnableLayout->addDescriptorLayout(viewParamsLayout);
|
||||||
|
cullingEnableLayout->addDescriptorLayout(dispatchParamsLayout);
|
||||||
|
cullingEnableLayout->addDescriptorLayout(cullingDescriptorLayout);
|
||||||
|
cullingEnableLayout->addDescriptorLayout(lightEnv->getDescriptorLayout());
|
||||||
|
|
||||||
|
ShaderCompilationInfo createInfo = {
|
||||||
|
.name = "Culling",
|
||||||
|
.modules = {"LightCulling"},
|
||||||
|
.entryPoints = {{"cullLights", "LightCulling"}},
|
||||||
|
.rootSignature = cullingEnableLayout,
|
||||||
|
};
|
||||||
|
createInfo.defines["LIGHT_CULLING"] = "1";
|
||||||
|
graphics->beginShaderCompilation(createInfo);
|
||||||
|
cullingEnabledShader = graphics->createComputeShader({0});
|
||||||
|
cullingEnableLayout->create();
|
||||||
|
|
||||||
|
Gfx::ComputePipelineCreateInfo pipelineInfo;
|
||||||
|
pipelineInfo.computeShader = cullingShader;
|
||||||
|
pipelineInfo.pipelineLayout = cullingEnableLayout;
|
||||||
|
cullingEnabledPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LightCullingPass::~LightCullingPass() {}
|
LightCullingPass::~LightCullingPass() {}
|
||||||
|
|
||||||
@@ -91,86 +222,9 @@ void LightCullingPass::publishOutputs() {
|
|||||||
dispatchParamsSet = dispatchParamsLayout->allocateDescriptorSet();
|
dispatchParamsSet = dispatchParamsLayout->allocateDescriptorSet();
|
||||||
dispatchParamsSet->updateConstants("numThreadGroups", 0, &numThreadGroups);
|
dispatchParamsSet->updateConstants("numThreadGroups", 0, &numThreadGroups);
|
||||||
dispatchParamsSet->updateConstants("numThreads", 0, &numThreads);
|
dispatchParamsSet->updateConstants("numThreads", 0, &numThreads);
|
||||||
|
dispatchParamsSet->updateBuffer(FRUSTUMBUFFER_NAME, 0, frustumBuffer);
|
||||||
dispatchParamsSet->writeChanges();
|
dispatchParamsSet->writeChanges();
|
||||||
|
|
||||||
cullingDescriptorLayout = graphics->createDescriptorLayout("pCullingParams");
|
|
||||||
|
|
||||||
// DepthTexture
|
|
||||||
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = DEPTHATTACHMENT_NAME,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
|
||||||
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
|
|
||||||
});
|
|
||||||
// o_lightIndexCounter
|
|
||||||
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = OLIGHTINDEXCOUNTER_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
|
|
||||||
// t_lightIndexCounter
|
|
||||||
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = TLIGHTINDEXCOUNTER_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
|
|
||||||
// o_lightIndexList
|
|
||||||
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = OLIGHTINDEXLIST_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
|
|
||||||
// t_lightIndexList
|
|
||||||
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = TLIGHTINDEXLIST_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
|
|
||||||
// o_lightGrid
|
|
||||||
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = OLIGHTGRID_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
|
|
||||||
// t_lightGrid
|
|
||||||
cullingDescriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = TLIGHTGRID_NAME, .descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_IMAGE, .access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,});
|
|
||||||
|
|
||||||
cullingDescriptorLayout->create();
|
|
||||||
|
|
||||||
lightEnv = scene->getLightEnvironment();
|
|
||||||
|
|
||||||
{
|
|
||||||
cullingLayout = graphics->createPipelineLayout("CullingLayout");
|
|
||||||
cullingLayout->addDescriptorLayout(viewParamsLayout);
|
|
||||||
cullingLayout->addDescriptorLayout(dispatchParamsLayout);
|
|
||||||
cullingLayout->addDescriptorLayout(cullingDescriptorLayout);
|
|
||||||
cullingLayout->addDescriptorLayout(lightEnv->getDescriptorLayout());
|
|
||||||
|
|
||||||
ShaderCompilationInfo createInfo = {
|
|
||||||
.name = "Culling",
|
|
||||||
.modules = {"LightCulling"},
|
|
||||||
.entryPoints = {{"cullLights", "LightCulling"}},
|
|
||||||
.rootSignature = cullingLayout,
|
|
||||||
};
|
|
||||||
graphics->beginShaderCompilation(createInfo);
|
|
||||||
cullingShader = graphics->createComputeShader({0});
|
|
||||||
cullingLayout->create();
|
|
||||||
|
|
||||||
Gfx::ComputePipelineCreateInfo pipelineInfo;
|
|
||||||
pipelineInfo.computeShader = cullingShader;
|
|
||||||
pipelineInfo.pipelineLayout = cullingLayout;
|
|
||||||
cullingPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
cullingEnableLayout = graphics->createPipelineLayout("CullingEnabledLayout");
|
|
||||||
cullingEnableLayout->addDescriptorLayout(viewParamsLayout);
|
|
||||||
cullingEnableLayout->addDescriptorLayout(dispatchParamsLayout);
|
|
||||||
cullingEnableLayout->addDescriptorLayout(cullingDescriptorLayout);
|
|
||||||
cullingEnableLayout->addDescriptorLayout(lightEnv->getDescriptorLayout());
|
|
||||||
|
|
||||||
ShaderCompilationInfo createInfo = {
|
|
||||||
.name = "Culling",
|
|
||||||
.modules = {"LightCulling"},
|
|
||||||
.entryPoints = {{"cullLights", "LightCulling"}},
|
|
||||||
.rootSignature = cullingEnableLayout,
|
|
||||||
};
|
|
||||||
createInfo.defines["LIGHT_CULLING"] = "1";
|
|
||||||
graphics->beginShaderCompilation(createInfo);
|
|
||||||
cullingEnabledShader = graphics->createComputeShader({0});
|
|
||||||
cullingEnableLayout->create();
|
|
||||||
|
|
||||||
Gfx::ComputePipelineCreateInfo pipelineInfo;
|
|
||||||
pipelineInfo.computeShader = cullingShader;
|
|
||||||
pipelineInfo.pipelineLayout = cullingEnableLayout;
|
|
||||||
cullingEnabledPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 counterReset = 0;
|
uint32 counterReset = 0;
|
||||||
ShaderBufferCreateInfo structInfo = {
|
ShaderBufferCreateInfo structInfo = {
|
||||||
.sourceData =
|
.sourceData =
|
||||||
@@ -188,8 +242,7 @@ void LightCullingPass::publishOutputs() {
|
|||||||
structInfo = {
|
structInfo = {
|
||||||
.sourceData =
|
.sourceData =
|
||||||
{
|
{
|
||||||
.size = (uint32)sizeof(uint32) * numThreadGroups.x * numThreadGroups.y *
|
.size = (uint32)sizeof(uint32) * numThreadGroups.x * numThreadGroups.y * numThreadGroups.z * 8192,
|
||||||
numThreadGroups.z * 8192,
|
|
||||||
.data = nullptr,
|
.data = nullptr,
|
||||||
.owner = Gfx::QueueType::COMPUTE,
|
.owner = Gfx::QueueType::COMPUTE,
|
||||||
},
|
},
|
||||||
@@ -237,41 +290,6 @@ void LightCullingPass::setupFrustums() {
|
|||||||
updateViewParameters(Component::Camera(), Component::Transform());
|
updateViewParameters(Component::Camera(), Component::Transform());
|
||||||
viewParamsSet = createViewParamsSet();
|
viewParamsSet = createViewParamsSet();
|
||||||
|
|
||||||
dispatchParamsLayout = graphics->createDescriptorLayout("pDispatchParams");
|
|
||||||
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = "numThreadGroups",
|
|
||||||
.uniformLength = sizeof(UVector4),
|
|
||||||
});
|
|
||||||
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = "numThreads",
|
|
||||||
.uniformLength = sizeof(UVector4),
|
|
||||||
});
|
|
||||||
dispatchParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = FRUSTUMBUFFER_NAME,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
|
||||||
.access = Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
|
||||||
});
|
|
||||||
dispatchParamsLayout->create();
|
|
||||||
frustumLayout = graphics->createPipelineLayout("FrustumLayout");
|
|
||||||
frustumLayout->addDescriptorLayout(viewParamsLayout);
|
|
||||||
frustumLayout->addDescriptorLayout(dispatchParamsLayout);
|
|
||||||
ShaderCompilationInfo createInfo = {
|
|
||||||
.name = "Frustum",
|
|
||||||
.modules = {"ComputeFrustums"},
|
|
||||||
.entryPoints = {{"computeFrustums", "ComputeFrustums"}},
|
|
||||||
.rootSignature = frustumLayout,
|
|
||||||
.dumpIntermediate = true,
|
|
||||||
};
|
|
||||||
graphics->beginShaderCompilation(createInfo);
|
|
||||||
frustumShader = graphics->createComputeShader({0});
|
|
||||||
// Have to compile shader before finalizing layout as parameters get mapped later
|
|
||||||
frustumLayout->create();
|
|
||||||
|
|
||||||
Gfx::ComputePipelineCreateInfo pipelineInfo;
|
|
||||||
pipelineInfo.computeShader = frustumShader;
|
|
||||||
pipelineInfo.pipelineLayout = frustumLayout;
|
|
||||||
frustumPipeline = graphics->createComputePipeline(pipelineInfo);
|
|
||||||
|
|
||||||
frustumBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
frustumBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
.sourceData =
|
.sourceData =
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
#include "Graphics/RayTracing.h"
|
#include "Graphics/RayTracing.h"
|
||||||
#include "Graphics/Shader.h"
|
#include "Graphics/Shader.h"
|
||||||
#include "Graphics/StaticMeshVertexData.h"
|
#include "Graphics/StaticMeshVertexData.h"
|
||||||
#include "RenderPass.h"
|
|
||||||
#include "Material/Material.h"
|
#include "Material/Material.h"
|
||||||
#include "Material/MaterialInstance.h"
|
#include "Material/MaterialInstance.h"
|
||||||
|
#include "Scene/LightEnvironment.h"
|
||||||
|
#include "RenderPass.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
@@ -53,7 +55,20 @@ RayTracingPass::RayTracingPass(Gfx::PGraphics graphics, PScene scene) : RenderPa
|
|||||||
.stageFlags = Gfx::SE_SHADER_STAGE_RAYGEN_BIT_KHR,
|
.stageFlags = Gfx::SE_SHADER_STAGE_RAYGEN_BIT_KHR,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = sizeof(SampleParams),
|
.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{
|
graphics->getShaderCompiler()->registerRenderPass("RayTracing", Gfx::PassConfig{
|
||||||
.baseLayout = pipelineLayout,
|
.baseLayout = pipelineLayout,
|
||||||
.mainFile = "ClosestHit",
|
.mainFile = "ClosestHit",
|
||||||
@@ -211,20 +226,9 @@ void RayTracingPass::publishOutputs() {
|
|||||||
texture->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_NONE, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
texture->changeLayout(Gfx::SE_IMAGE_LAYOUT_GENERAL, Gfx::SE_ACCESS_NONE, Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
|
||||||
Gfx::SE_ACCESS_SHADER_WRITE_BIT,
|
Gfx::SE_ACCESS_SHADER_WRITE_BIT,
|
||||||
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT | Gfx::SE_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR);
|
||||||
resources->registerRenderPassOutput("BASEPASS_COLOR", Gfx::RenderTargetAttachment(texture->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
|
resources->registerRenderPassOutput("BASEPASS_COLOR",
|
||||||
|
Gfx::RenderTargetAttachment(texture->getDefaultView(), Gfx::SE_IMAGE_LAYOUT_UNDEFINED,
|
||||||
Gfx::SE_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
|
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RayTracingPass::createRenderPass() {}
|
void RayTracingPass::createRenderPass() {}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "Graphics/Initializer.h"
|
#include "Graphics/Initializer.h"
|
||||||
#include "Graphics/Shader.h"
|
#include "Graphics/Shader.h"
|
||||||
#include "Math/Matrix.h"
|
#include "Math/Matrix.h"
|
||||||
|
#include "Scene/LightEnvironment.h"
|
||||||
#include <glm/ext/matrix_transform.hpp>
|
#include <glm/ext/matrix_transform.hpp>
|
||||||
#include <glm/matrix.hpp>
|
#include <glm/matrix.hpp>
|
||||||
|
|
||||||
@@ -16,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,
|
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.size = sizeof(VertexData::DrawCallOffsets),
|
.size = sizeof(VertexData::DrawCallOffsets),
|
||||||
|
.name = "pOffsets",
|
||||||
});
|
});
|
||||||
if (graphics->supportMeshShading()) {
|
if (graphics->supportMeshShading()) {
|
||||||
graphics->getShaderCompiler()->registerRenderPass("ShadowPass", Gfx::PassConfig{
|
graphics->getShaderCompiler()->registerRenderPass("ShadowPass", Gfx::PassConfig{
|
||||||
@@ -253,7 +255,6 @@ void ShadowPass::render() {
|
|||||||
}
|
}
|
||||||
graphics->executeCommands(std::move(commands));
|
graphics->executeCommands(std::move(commands));
|
||||||
graphics->endRenderPass();
|
graphics->endRenderPass();
|
||||||
graphics->waitDeviceIdle();
|
|
||||||
}
|
}
|
||||||
graphics->endDebugRegion();
|
graphics->endDebugRegion();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -4,7 +4,39 @@
|
|||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
VisibilityPass::VisibilityPass(Gfx::PGraphics graphics) : RenderPass(graphics) {}
|
VisibilityPass::VisibilityPass(Gfx::PGraphics graphics) : RenderPass(graphics) {
|
||||||
|
visibilityDescriptor = graphics->createDescriptorLayout("pVisibilityParams");
|
||||||
|
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = VISIBILITY_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
|
||||||
|
});
|
||||||
|
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = CULLINGBUFFER_NAME,
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
||||||
|
});
|
||||||
|
visibilityDescriptor->create();
|
||||||
|
|
||||||
|
visibilityLayout = graphics->createPipelineLayout("VisibilityLayout");
|
||||||
|
visibilityLayout->addDescriptorLayout(visibilityDescriptor);
|
||||||
|
visibilityLayout->addDescriptorLayout(viewParamsLayout);
|
||||||
|
|
||||||
|
ShaderCompilationInfo createInfo = {
|
||||||
|
.name = "Visibility",
|
||||||
|
.modules = {"VisibilityCompute"},
|
||||||
|
.entryPoints = {{"computeMain", "VisibilityCompute"}},
|
||||||
|
.rootSignature = visibilityLayout,
|
||||||
|
};
|
||||||
|
graphics->beginShaderCompilation(createInfo);
|
||||||
|
visibilityShader = graphics->createComputeShader({0});
|
||||||
|
visibilityLayout->create();
|
||||||
|
|
||||||
|
Gfx::ComputePipelineCreateInfo pipelineInfo;
|
||||||
|
pipelineInfo.computeShader = visibilityShader;
|
||||||
|
pipelineInfo.pipelineLayout = visibilityLayout;
|
||||||
|
visibilityPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
|
||||||
|
}
|
||||||
|
|
||||||
VisibilityPass::~VisibilityPass() {}
|
VisibilityPass::~VisibilityPass() {}
|
||||||
|
|
||||||
@@ -52,37 +84,6 @@ void VisibilityPass::publishOutputs() {
|
|||||||
uint32_t viewportWidth = viewport->getWidth();
|
uint32_t viewportWidth = viewport->getWidth();
|
||||||
uint32_t viewportHeight = viewport->getHeight();
|
uint32_t viewportHeight = viewport->getHeight();
|
||||||
threadGroupSize = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1));
|
threadGroupSize = glm::ceil(glm::vec3(viewportWidth / (float)BLOCK_SIZE, viewportHeight / (float)BLOCK_SIZE, 1));
|
||||||
visibilityDescriptor = graphics->createDescriptorLayout("pVisibilityParams");
|
|
||||||
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = VISIBILITY_NAME,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
|
||||||
.access = Gfx::SE_DESCRIPTOR_ACCESS_SAMPLE_BIT,
|
|
||||||
});
|
|
||||||
visibilityDescriptor->addDescriptorBinding(Gfx::DescriptorBinding{
|
|
||||||
.name = CULLINGBUFFER_NAME,
|
|
||||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
|
||||||
.access = Gfx::SE_DESCRIPTOR_ACCESS_READ_BIT | Gfx::SE_DESCRIPTOR_ACCESS_WRITE_BIT,
|
|
||||||
});
|
|
||||||
visibilityDescriptor->create();
|
|
||||||
|
|
||||||
visibilityLayout = graphics->createPipelineLayout("VisibilityLayout");
|
|
||||||
visibilityLayout->addDescriptorLayout(visibilityDescriptor);
|
|
||||||
visibilityLayout->addDescriptorLayout(viewParamsLayout);
|
|
||||||
|
|
||||||
ShaderCompilationInfo createInfo = {
|
|
||||||
.name = "Visibility",
|
|
||||||
.modules = {"VisibilityCompute"},
|
|
||||||
.entryPoints = {{"computeMain", "VisibilityCompute"}},
|
|
||||||
.rootSignature = visibilityLayout,
|
|
||||||
};
|
|
||||||
graphics->beginShaderCompilation(createInfo);
|
|
||||||
visibilityShader = graphics->createComputeShader({0});
|
|
||||||
visibilityLayout->create();
|
|
||||||
|
|
||||||
Gfx::ComputePipelineCreateInfo pipelineInfo;
|
|
||||||
pipelineInfo.computeShader = visibilityShader;
|
|
||||||
pipelineInfo.pipelineLayout = visibilityLayout;
|
|
||||||
visibilityPipeline = graphics->createComputePipeline(std::move(pipelineInfo));
|
|
||||||
|
|
||||||
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
cullingBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
.clearValue = 0xffffffff,
|
.clearValue = 0xffffffff,
|
||||||
|
|||||||
@@ -134,7 +134,6 @@ void ShaderCompiler::createShaders(ShaderPermutation permutation, Gfx::OPipeline
|
|||||||
}
|
}
|
||||||
// createInfo.typeParameter.add({Pair<const char*, const char*>("IVertexData", permutation.vertexDataName)});
|
// createInfo.typeParameter.add({Pair<const char*, const char*>("IVertexData", permutation.vertexDataName)});
|
||||||
createInfo.modules.add(permutation.vertexDataName);
|
createInfo.modules.add(permutation.vertexDataName);
|
||||||
// createInfo.dumpIntermediate = true;
|
|
||||||
|
|
||||||
if (permutation.useMeshShading) {
|
if (permutation.useMeshShading) {
|
||||||
if (permutation.hasTaskShader) {
|
if (permutation.hasTaskShader) {
|
||||||
|
|||||||
@@ -619,7 +619,7 @@ void VertexData::loadMeshlets(MeshId id, const Array<Vector>& loadedPositions, c
|
|||||||
// todo: use meshopt for bb generation
|
// todo: use meshopt for bb generation
|
||||||
m.bounding = AABB();
|
m.bounding = AABB();
|
||||||
for (size_t j = 0; j < m.vertexIndices.size; ++j) {
|
for (size_t j = 0; j < m.vertexIndices.size; ++j) {
|
||||||
m.bounding.adjust(loadedPositions[vertexIndices[meshoptMeshlets[i].vertex_offset + j + m.indicesOffset]]);
|
m.bounding.adjust(loadedPositions[vertexIndices[meshoptMeshlets[i].vertex_offset + j + vertexOffset]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
registeredMeshes[id].meshData = MeshData{
|
registeredMeshes[id].meshData = MeshData{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "Graphics/Enums.h"
|
#include "Graphics/Enums.h"
|
||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <vk_mem_alloc.h>
|
#include <vk_mem_alloc.h>
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
@@ -192,7 +193,8 @@ void BufferAllocation::unmap() {
|
|||||||
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType queueType, bool dynamic, std::string name,
|
Buffer::Buffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType queueType, bool dynamic, std::string name,
|
||||||
bool createCleared, uint32 clearValue)
|
bool createCleared, uint32 clearValue)
|
||||||
: graphics(graphics), currentBuffer(0), initialOwner(queueType),
|
: graphics(graphics), currentBuffer(0), initialOwner(queueType),
|
||||||
usage(usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT),
|
usage(usage | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||||
|
(graphics->supportRayTracing() ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0)),
|
||||||
dynamic(dynamic), createCleared(createCleared), name(name), clearValue(clearValue) {
|
dynamic(dynamic), createCleared(createCleared), name(name), clearValue(clearValue) {
|
||||||
if (size > 0) {
|
if (size > 0) {
|
||||||
buffers.add(nullptr);
|
buffers.add(nullptr);
|
||||||
@@ -483,9 +485,8 @@ IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo& create
|
|||||||
: Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo),
|
: Gfx::IndexBuffer(graphics->getFamilyMapping(), createInfo),
|
||||||
Vulkan::Buffer(graphics, createInfo.sourceData.size,
|
Vulkan::Buffer(graphics, createInfo.sourceData.size,
|
||||||
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
|
||||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | (graphics->supportRayTracing()
|
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
|
||||||
? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR
|
(graphics->supportRayTracing() ? VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR : 0),
|
||||||
: 0),
|
|
||||||
createInfo.sourceData.owner, false, createInfo.name) {
|
createInfo.sourceData.owner, false, createInfo.name) {
|
||||||
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
|
getAlloc()->updateContents(createInfo.sourceData.offset, createInfo.sourceData.size, createInfo.sourceData.data);
|
||||||
// getAlloc()->pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_INDEX_READ_BIT,
|
// getAlloc()->pipelineBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_INDEX_READ_BIT,
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ void RenderCommand::bindDescriptor(Gfx::PDescriptorSet descriptor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (descriptorSet->setHandle->constantsBuffer != nullptr) {
|
if (descriptorSet->setHandle->constantsBuffer != nullptr) {
|
||||||
descriptorSet->setHandle->bind();
|
descriptorSet->setHandle->constantsBuffer->bind();
|
||||||
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
|
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +299,7 @@ void RenderCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptorS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (descriptorSet->setHandle->constantsBuffer != nullptr) {
|
if (descriptorSet->setHandle->constantsBuffer != nullptr) {
|
||||||
descriptorSet->setHandle->bind();
|
descriptorSet->setHandle->constantsBuffer->bind();
|
||||||
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
|
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
|
||||||
}
|
}
|
||||||
sets[layout->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
sets[layout->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
||||||
@@ -351,6 +351,12 @@ void RenderCommand::drawIndexed(uint32 indexCount, uint32 instanceCount, int32 f
|
|||||||
assert(threadId == std::this_thread::get_id());
|
assert(threadId == std::this_thread::get_id());
|
||||||
vkCmdDrawIndexed(handle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
vkCmdDrawIndexed(handle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderCommand::drawIndexedIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) {
|
||||||
|
assert(threadId == std::this_thread::get_id());
|
||||||
|
vkCmdDrawIndexedIndirect(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset, drawCount, stride);
|
||||||
|
}
|
||||||
|
|
||||||
void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) {
|
void RenderCommand::drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) {
|
||||||
assert(threadId == std::this_thread::get_id());
|
assert(threadId == std::this_thread::get_id());
|
||||||
if (groupX * groupY * groupZ == 0) // any dimension is 0
|
if (groupX * groupY * groupZ == 0) // any dimension is 0
|
||||||
@@ -449,7 +455,7 @@ void ComputeCommand::bindDescriptor(Gfx::PDescriptorSet descriptor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (descriptorSet->setHandle->constantsBuffer != nullptr) {
|
if (descriptorSet->setHandle->constantsBuffer != nullptr) {
|
||||||
descriptorSet->setHandle->bind();
|
descriptorSet->setHandle->constantsBuffer->bind();
|
||||||
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
|
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -476,7 +482,7 @@ void ComputeCommand::bindDescriptor(const Array<Gfx::PDescriptorSet>& descriptor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (descriptorSet->setHandle->constantsBuffer != nullptr) {
|
if (descriptorSet->setHandle->constantsBuffer != nullptr) {
|
||||||
descriptorSet->setHandle->bind();
|
descriptorSet->setHandle->constantsBuffer->bind();
|
||||||
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
|
boundResources.add(PBufferAllocation(descriptorSet->setHandle->constantsBuffer));
|
||||||
}
|
}
|
||||||
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
sets[pipeline->getPipelineLayout()->findParameter(descriptorSet->getName())] = descriptorSet->getHandle();
|
||||||
@@ -491,10 +497,16 @@ void ComputeCommand::pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset,
|
|||||||
vkCmdPushConstants(handle, pipeline->getLayout(), stage, offset, size, data);
|
vkCmdPushConstants(handle, pipeline->getLayout(), stage, offset, size, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ComputeCommand::dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) {
|
void ComputeCommand::dispatch(uint32 threadGroupCountX, uint32 threadGroupCountY, uint32 threadGroupCountZ) {
|
||||||
assert(threadId == std::this_thread::get_id());
|
assert(threadId == std::this_thread::get_id());
|
||||||
vkCmdDispatch(handle, threadX, threadY, threadZ);
|
vkCmdDispatch(handle, threadGroupCountX, threadGroupCountY, threadGroupCountZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ComputeCommand::dispatch(UVector threadGroupSize) {
|
||||||
|
assert(threadId == std::this_thread::get_id());
|
||||||
|
vkCmdDispatch(handle, threadGroupSize.x, threadGroupSize.y, threadGroupSize.z);
|
||||||
|
}
|
||||||
|
|
||||||
void ComputeCommand::dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) {
|
void ComputeCommand::dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) {
|
||||||
assert(threadId == std::this_thread::get_id());
|
assert(threadId == std::this_thread::get_id());
|
||||||
vkCmdDispatchIndirect(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset);
|
vkCmdDispatchIndirect(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset);
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ class RenderCommand : public Gfx::RenderCommand {
|
|||||||
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) override;
|
virtual void draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance) override;
|
||||||
virtual void drawIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override;
|
virtual void drawIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override;
|
||||||
virtual void drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) override;
|
virtual void drawIndexed(uint32 indexCount, uint32 instanceCount, int32 firstIndex, uint32 vertexOffset, uint32 firstInstance) override;
|
||||||
|
virtual void drawIndexedIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override;
|
||||||
virtual void drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) override;
|
virtual void drawMesh(uint32 groupX, uint32 groupY, uint32 groupZ) override;
|
||||||
virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override;
|
virtual void drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, uint32 drawCount, uint32 stride) override;
|
||||||
virtual void traceRays(uint32 width, uint32 height, uint32 depth) override;
|
virtual void traceRays(uint32 width, uint32 height, uint32 depth) override;
|
||||||
@@ -116,6 +117,7 @@ class ComputeCommand : public Gfx::ComputeCommand {
|
|||||||
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) override;
|
virtual void bindDescriptor(const Array<Gfx::PDescriptorSet>& sets) override;
|
||||||
virtual void pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) override;
|
virtual void pushConstants(Gfx::SeShaderStageFlags stage, uint32 offset, uint32 size, const void* data) override;
|
||||||
virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) override;
|
virtual void dispatch(uint32 threadX, uint32 threadY, uint32 threadZ) override;
|
||||||
|
virtual void dispatch(UVector threadGroupSize) override;
|
||||||
virtual void dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) override;
|
virtual void dispatchIndirect(Gfx::PShaderBuffer buffer, uint32 offset) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
#include "Debug.h"
|
#include "Debug.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const char* severityToString(VkDebugUtilsMessageSeverityFlagBitsEXT severity) {
|
||||||
|
if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
|
||||||
|
return "ERROR";
|
||||||
|
}
|
||||||
|
if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
|
||||||
|
return "WARNING";
|
||||||
|
}
|
||||||
|
if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
|
||||||
|
return "INFO";
|
||||||
|
}
|
||||||
|
return "VERBOSE";
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
VkBool32 Seele::Vulkan::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT, VkDebugUtilsMessageTypeFlagsEXT,
|
VkBool32 Seele::Vulkan::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT,
|
||||||
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void*) {
|
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void*) {
|
||||||
std::cerr << pCallbackData->pMessage << std::endl;
|
std::cerr << "[Vulkan " << severityToString(messageSeverity) << "] " << pCallbackData->pMessage << std::endl;
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,6 @@ Gfx::ODescriptorSet DescriptorPool::allocateDescriptorSet() {
|
|||||||
};
|
};
|
||||||
vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo);
|
vkSetDebugUtilsObjectNameEXT(graphics->getDevice(), &nameInfo);
|
||||||
}
|
}
|
||||||
cachedHandles[setIndex]->isUsed = true;
|
|
||||||
// Found set, stop searching
|
// Found set, stop searching
|
||||||
return new DescriptorSet(graphics, this, cachedHandles[setIndex]);
|
return new DescriptorSet(graphics, this, cachedHandles[setIndex]);
|
||||||
}
|
}
|
||||||
@@ -191,13 +190,11 @@ void DescriptorPool::reset() {}
|
|||||||
|
|
||||||
DescriptorSetHandle::DescriptorSetHandle(PGraphics graphics, const std::string& name) : CommandBoundResource(graphics, name) {}
|
DescriptorSetHandle::DescriptorSetHandle(PGraphics graphics, const std::string& name) : CommandBoundResource(graphics, name) {}
|
||||||
|
|
||||||
DescriptorSetHandle::~DescriptorSetHandle() {
|
DescriptorSetHandle::~DescriptorSetHandle() { graphics->getDestructionManager()->queueResourceForDestruction(std::move(constantsBuffer)); }
|
||||||
graphics->getDestructionManager()->queueResourceForDestruction(std::move(constantsBuffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle)
|
DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle)
|
||||||
: Gfx::DescriptorSet(owner->getLayout()), setHandle(setHandle),
|
: Gfx::DescriptorSet(owner->getLayout()), setHandle(setHandle), graphics(graphics), owner(owner) {
|
||||||
graphics(graphics), owner(owner) {
|
setHandle->isUsed = true;
|
||||||
boundResources.resize(owner->getLayout()->bindings.size());
|
boundResources.resize(owner->getLayout()->bindings.size());
|
||||||
for (uint32 i = 0; i < boundResources.size(); ++i) {
|
for (uint32 i = 0; i < boundResources.size(); ++i) {
|
||||||
boundResources[i].resize(owner->getLayout()->bindings[i].descriptorCount);
|
boundResources[i].resize(owner->getLayout()->bindings[i].descriptorCount);
|
||||||
@@ -209,11 +206,13 @@ DescriptorSet::DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescrip
|
|||||||
}
|
}
|
||||||
|
|
||||||
DescriptorSet::~DescriptorSet() {
|
DescriptorSet::~DescriptorSet() {
|
||||||
|
if (setHandle != nullptr) {
|
||||||
setHandle->isUsed = false;
|
setHandle->isUsed = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DescriptorSet::updateConstants(const std::string& mappingName, uint32 offset, void* data) {
|
void DescriptorSet::updateConstants(const std::string& mappingName, uint32 offset, const void* data) {
|
||||||
std::memcpy(constantData.data() + owner->getLayout()->mappings[mappingName].constantOffset, (char*)data + offset,
|
std::memcpy(constantData.data() + owner->getLayout()->mappings[mappingName].constantOffset, (const char*)data + offset,
|
||||||
owner->getLayout()->mappings[mappingName].constantSize);
|
owner->getLayout()->mappings[mappingName].constantSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -406,7 +405,8 @@ void DescriptorSet::writeChanges() {
|
|||||||
if (setHandle->constantsBuffer != nullptr) {
|
if (setHandle->constantsBuffer != nullptr) {
|
||||||
graphics->getDestructionManager()->queueResourceForDestruction(std::move(setHandle->constantsBuffer));
|
graphics->getDestructionManager()->queueResourceForDestruction(std::move(setHandle->constantsBuffer));
|
||||||
}
|
}
|
||||||
setHandle->constantsBuffer = new BufferAllocation(graphics, owner->getLayout()->getName(),
|
setHandle->constantsBuffer =
|
||||||
|
new BufferAllocation(graphics, owner->getLayout()->getName(),
|
||||||
VkBufferCreateInfo{
|
VkBufferCreateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
|||||||
@@ -68,8 +68,12 @@ class DescriptorSet : public Gfx::DescriptorSet {
|
|||||||
public:
|
public:
|
||||||
DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle);
|
DescriptorSet(PGraphics graphics, PDescriptorPool owner, PDescriptorSetHandle setHandle);
|
||||||
virtual ~DescriptorSet();
|
virtual ~DescriptorSet();
|
||||||
|
DescriptorSet(const DescriptorSet&) = delete;
|
||||||
|
DescriptorSet(DescriptorSet&&) noexcept;
|
||||||
|
DescriptorSet& operator=(const DescriptorSet&) = delete;
|
||||||
|
DescriptorSet& operator=(DescriptorSet&&) noexcept;
|
||||||
virtual void writeChanges() override;
|
virtual void writeChanges() override;
|
||||||
virtual void updateConstants(const std::string& name, uint32 offset, void* data) override;
|
virtual void updateConstants(const std::string& name, uint32 offset, const void* data) override;
|
||||||
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer shaderBuffer) override;
|
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PShaderBuffer shaderBuffer) override;
|
||||||
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer vertexBuffer) override;
|
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PVertexBuffer vertexBuffer) override;
|
||||||
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer indexBuffer) override;
|
virtual void updateBuffer(const std::string& name, uint32 index, Gfx::PIndexBuffer indexBuffer) override;
|
||||||
@@ -91,7 +95,7 @@ class DescriptorSet : public Gfx::DescriptorSet {
|
|||||||
// would not work anyways, so casts should be safe
|
// would not work anyways, so casts should be safe
|
||||||
// Array<void*> cachedData;
|
// Array<void*> cachedData;
|
||||||
Array<Array<PCommandBoundResource>> boundResources;
|
Array<Array<PCommandBoundResource>> boundResources;
|
||||||
PDescriptorSetHandle setHandle;
|
PDescriptorSetHandle setHandle = nullptr;
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
PDescriptorPool owner;
|
PDescriptorPool owner;
|
||||||
friend class DescriptorPool;
|
friend class DescriptorPool;
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
if (res == VK_ERROR_DEVICE_LOST) { \
|
if (res == VK_ERROR_DEVICE_LOST) { \
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(3)); \
|
std::this_thread::sleep_for(std::chrono::seconds(3)); \
|
||||||
} \
|
} \
|
||||||
std::cout << "Fatal : VkResult is " << res << " in " << __FILE__ << " at line " << __LINE__ << std::endl; \
|
std::cerr << "Fatal: VkResult is " << res << " in " << __FILE__ << " at line " << __LINE__ << std::endl; \
|
||||||
|
std::cerr.flush(); \
|
||||||
abort(); \
|
abort(); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,12 @@
|
|||||||
#include "RenderPass.h"
|
#include "RenderPass.h"
|
||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include <GLFW/glfw3.h>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <vector>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <GLFW/glfw3native.h>
|
||||||
|
#include <vulkan/vulkan_wayland.h>
|
||||||
#include <vulkan/vulkan_core.h>
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
#define VMA_IMPLEMENTATION
|
#define VMA_IMPLEMENTATION
|
||||||
@@ -26,6 +30,63 @@
|
|||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::vector<VkExtensionProperties> enumerateInstanceExtensions() {
|
||||||
|
uint32_t extensionCount = 0;
|
||||||
|
VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr));
|
||||||
|
std::vector<VkExtensionProperties> extensions(extensionCount);
|
||||||
|
if (extensionCount > 0) {
|
||||||
|
VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()));
|
||||||
|
}
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasInstanceExtension(const std::vector<VkExtensionProperties>& extensions, const char* extensionName) {
|
||||||
|
for (const auto& extension : extensions) {
|
||||||
|
if (std::strcmp(extension.extensionName, extensionName) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyCommonGlfwInitHints() {
|
||||||
|
#if defined(GLFW_WAYLAND_LIBDECOR) && defined(GLFW_WAYLAND_DISABLE_LIBDECOR)
|
||||||
|
glfwInitHint(GLFW_WAYLAND_LIBDECOR, GLFW_WAYLAND_DISABLE_LIBDECOR);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeGlfwForVulkan() {
|
||||||
|
applyCommonGlfwInitHints();
|
||||||
|
if (!glfwInit()) {
|
||||||
|
throw std::runtime_error("Failed to initialize GLFW");
|
||||||
|
}
|
||||||
|
if (!glfwVulkanSupported()) {
|
||||||
|
throw std::runtime_error("GLFW: Vulkan not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(GLFW_PLATFORM_WAYLAND) && defined(GLFW_PLATFORM_X11)
|
||||||
|
const auto availableExtensions = enumerateInstanceExtensions();
|
||||||
|
const bool hasWaylandSurface = hasInstanceExtension(availableExtensions, "VK_KHR_wayland_surface");
|
||||||
|
const bool hasXlibSurface = hasInstanceExtension(availableExtensions, "VK_KHR_xlib_surface");
|
||||||
|
const bool hasXcbSurface = hasInstanceExtension(availableExtensions, "VK_KHR_xcb_surface");
|
||||||
|
|
||||||
|
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND && !hasWaylandSurface && (hasXlibSurface || hasXcbSurface)) {
|
||||||
|
std::cerr << "Warning: Vulkan loader does not expose VK_KHR_wayland_surface on this run. Reinitializing GLFW on X11 backend." << std::endl;
|
||||||
|
glfwTerminate();
|
||||||
|
applyCommonGlfwInitHints();
|
||||||
|
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
||||||
|
if (!glfwInit()) {
|
||||||
|
throw std::runtime_error("Failed to reinitialize GLFW on X11 backend");
|
||||||
|
}
|
||||||
|
if (!glfwVulkanSupported()) {
|
||||||
|
throw std::runtime_error("GLFW: Vulkan not supported after switching to X11 backend");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
thread_local PCommandPool Seele::Vulkan::Graphics::graphicsCommands = nullptr;
|
thread_local PCommandPool Seele::Vulkan::Graphics::graphicsCommands = nullptr;
|
||||||
thread_local PCommandPool Seele::Vulkan::Graphics::computeCommands = nullptr;
|
thread_local PCommandPool Seele::Vulkan::Graphics::computeCommands = nullptr;
|
||||||
thread_local PCommandPool Seele::Vulkan::Graphics::transferCommands = nullptr;
|
thread_local PCommandPool Seele::Vulkan::Graphics::transferCommands = nullptr;
|
||||||
@@ -142,9 +203,7 @@ Graphics::~Graphics() {
|
|||||||
|
|
||||||
void Graphics::init(GraphicsInitializer initInfo) {
|
void Graphics::init(GraphicsInitializer initInfo) {
|
||||||
initInstance(initInfo);
|
initInstance(initInfo);
|
||||||
#ifdef ENABLE_VALIDATION
|
|
||||||
setupDebugCallback();
|
setupDebugCallback();
|
||||||
#endif
|
|
||||||
pickPhysicalDevice();
|
pickPhysicalDevice();
|
||||||
createDevice(initInfo);
|
createDevice(initInfo);
|
||||||
VmaAllocatorCreateInfo createInfo = {
|
VmaAllocatorCreateInfo createInfo = {
|
||||||
@@ -667,18 +726,54 @@ Array<const char*> Graphics::getRequiredExtensions() {
|
|||||||
unsigned int glfwExtensionCount = 0;
|
unsigned int glfwExtensionCount = 0;
|
||||||
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < glfwExtensionCount; i++) {
|
if (glfwExtensions == nullptr || glfwExtensionCount == 0) {
|
||||||
extensions.add(glfwExtensions[i]);
|
const char* glfwError = nullptr;
|
||||||
|
glfwGetError(&glfwError);
|
||||||
|
std::string message = "GLFW did not report required Vulkan instance extensions";
|
||||||
|
if (glfwError != nullptr) {
|
||||||
|
message += ": ";
|
||||||
|
message += glfwError;
|
||||||
}
|
}
|
||||||
|
std::cerr << "Warning: " << message << ". Falling back to platform-specific surface extensions." << std::endl;
|
||||||
|
|
||||||
|
extensions.addUnique(VK_KHR_SURFACE_EXTENSION_NAME);
|
||||||
|
|
||||||
|
#if defined(GLFW_PLATFORM_WAYLAND) && defined(GLFW_PLATFORM_X11)
|
||||||
|
const int platform = glfwGetPlatform();
|
||||||
|
if (platform == GLFW_PLATFORM_WAYLAND) {
|
||||||
|
extensions.addUnique("VK_KHR_wayland_surface");
|
||||||
|
} else if (platform == GLFW_PLATFORM_X11) {
|
||||||
|
extensions.addUnique("VK_KHR_xlib_surface");
|
||||||
|
extensions.addUnique("VK_KHR_xcb_surface");
|
||||||
|
} else {
|
||||||
|
extensions.addUnique("VK_KHR_wayland_surface");
|
||||||
|
extensions.addUnique("VK_KHR_xlib_surface");
|
||||||
|
extensions.addUnique("VK_KHR_xcb_surface");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool isWayland = std::getenv("WAYLAND_DISPLAY") != nullptr;
|
||||||
|
if (isWayland) {
|
||||||
|
extensions.addUnique("VK_KHR_wayland_surface");
|
||||||
|
} else {
|
||||||
|
extensions.addUnique("VK_KHR_xlib_surface");
|
||||||
|
extensions.addUnique("VK_KHR_xcb_surface");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
// GLFW successfully reported extensions
|
||||||
|
for (unsigned int i = 0; i < glfwExtensionCount; i++) {
|
||||||
|
extensions.addUnique(glfwExtensions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_VALIDATION
|
#ifdef ENABLE_VALIDATION
|
||||||
extensions.add(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
extensions.addUnique(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||||
#endif
|
#endif
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::initInstance(GraphicsInitializer initInfo) {
|
void Graphics::initInstance(GraphicsInitializer initInfo) {
|
||||||
glfwInit();
|
initializeGlfwForVulkan();
|
||||||
assert(glfwVulkanSupported());
|
|
||||||
VkApplicationInfo appInfo = {
|
VkApplicationInfo appInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -691,13 +786,12 @@ void Graphics::initInstance(GraphicsInitializer initInfo) {
|
|||||||
|
|
||||||
Array<const char*> extensions = getRequiredExtensions();
|
Array<const char*> extensions = getRequiredExtensions();
|
||||||
for (uint32 i = 0; i < initInfo.instanceExtensions.size(); ++i) {
|
for (uint32 i = 0; i < initInfo.instanceExtensions.size(); ++i) {
|
||||||
extensions.add(initInfo.instanceExtensions[i]);
|
extensions.addUnique(initInfo.instanceExtensions[i]);
|
||||||
}
|
}
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
extensions.add("VK_KHR_portability_enumeration");
|
extensions.addUnique("VK_KHR_portability_enumeration");
|
||||||
#endif
|
#endif
|
||||||
Array<const char*> layers = initInfo.layers;
|
Array<const char*> layers = initInfo.layers;
|
||||||
// layers.add("VK_LAYER_KHRONOS_validation");
|
|
||||||
VkInstanceCreateInfo info = {
|
VkInstanceCreateInfo info = {
|
||||||
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -754,11 +848,12 @@ void Graphics::pickPhysicalDevice() {
|
|||||||
|
|
||||||
vkGetPhysicalDeviceProperties2(physicalDevice, &props.get());
|
vkGetPhysicalDeviceProperties2(physicalDevice, &props.get());
|
||||||
features.get<VkPhysicalDeviceFeatures2>().features = {
|
features.get<VkPhysicalDeviceFeatures2>().features = {
|
||||||
.geometryShader = false,
|
// .robustBufferAccess = true,
|
||||||
|
.geometryShader = true,
|
||||||
.sampleRateShading = true,
|
.sampleRateShading = true,
|
||||||
.fillModeNonSolid = true,
|
.fillModeNonSolid = true,
|
||||||
.wideLines = false,
|
.wideLines = true,
|
||||||
.pipelineStatisticsQuery = false,
|
.pipelineStatisticsQuery = true,
|
||||||
.fragmentStoresAndAtomics = true,
|
.fragmentStoresAndAtomics = true,
|
||||||
.shaderInt64 = true,
|
.shaderInt64 = true,
|
||||||
.shaderInt16 = true,
|
.shaderInt16 = true,
|
||||||
@@ -766,12 +861,15 @@ void Graphics::pickPhysicalDevice() {
|
|||||||
};
|
};
|
||||||
features.get<VkPhysicalDeviceVulkan11Features>().multiview = true;
|
features.get<VkPhysicalDeviceVulkan11Features>().multiview = true;
|
||||||
features.get<VkPhysicalDeviceVulkan11Features>().storageBuffer16BitAccess = true;
|
features.get<VkPhysicalDeviceVulkan11Features>().storageBuffer16BitAccess = true;
|
||||||
|
features.get<VkPhysicalDeviceVulkan11Features>().shaderDrawParameters = true;
|
||||||
|
features.get<VkPhysicalDeviceVulkan11Features>().uniformAndStorageBuffer16BitAccess = true;
|
||||||
|
|
||||||
features.get<VkPhysicalDeviceVulkan12Features>().descriptorIndexing = true;
|
features.get<VkPhysicalDeviceVulkan12Features>().descriptorIndexing = true;
|
||||||
features.get<VkPhysicalDeviceVulkan12Features>().descriptorBindingPartiallyBound = true;
|
features.get<VkPhysicalDeviceVulkan12Features>().descriptorBindingPartiallyBound = true;
|
||||||
features.get<VkPhysicalDeviceVulkan12Features>().bufferDeviceAddress = true;
|
features.get<VkPhysicalDeviceVulkan12Features>().bufferDeviceAddress = true;
|
||||||
features.get<VkPhysicalDeviceVulkan12Features>().storageBuffer8BitAccess = true;
|
features.get<VkPhysicalDeviceVulkan12Features>().storageBuffer8BitAccess = true;
|
||||||
features.get<VkPhysicalDeviceVulkan12Features>().shaderInt8 = true;
|
features.get<VkPhysicalDeviceVulkan12Features>().shaderInt8 = true;
|
||||||
|
features.get<VkPhysicalDeviceVulkan12Features>().uniformAndStorageBuffer8BitAccess = true;
|
||||||
|
|
||||||
rayTracingFeatures.get<VkPhysicalDeviceAccelerationStructureFeaturesKHR>().accelerationStructure = true;
|
rayTracingFeatures.get<VkPhysicalDeviceAccelerationStructureFeaturesKHR>().accelerationStructure = true;
|
||||||
|
|
||||||
@@ -819,7 +917,7 @@ void Graphics::pickPhysicalDevice() {
|
|||||||
shaderFloatControls = true;
|
shaderFloatControls = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rayTracingEnabled = rayTracingPipelineSupport && accelerationStructureSupport && hostOperationsSupport && deviceAddressSupport &&
|
rayTracingEnabled = false &&rayTracingPipelineSupport && accelerationStructureSupport && hostOperationsSupport && deviceAddressSupport &&
|
||||||
descriptorIndexingSupport && spirv14Support && shaderFloatControls;
|
descriptorIndexingSupport && spirv14Support && shaderFloatControls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
#include "Command.h"
|
|
||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Window.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|||||||
@@ -3,11 +3,81 @@
|
|||||||
#include "Enums.h"
|
#include "Enums.h"
|
||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "Resources.h"
|
#include "Resources.h"
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
#define GLFW_EXPOSE_NATIVE_WAYLAND
|
||||||
|
#define GLFW_EXPOSE_NATIVE_X11
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <GLFW/glfw3native.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vulkan/vulkan_wayland.h>
|
||||||
|
#include <vulkan/vulkan_xlib.h>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
VkResult createSurfaceFromNativeHandles(VkInstance instance, GLFWwindow* handle, VkSurfaceKHR* surface, std::string& reason) {
|
||||||
|
#if defined(GLFW_PLATFORM_WAYLAND)
|
||||||
|
if (glfwGetPlatform() == GLFW_PLATFORM_WAYLAND) {
|
||||||
|
auto createWaylandSurface = reinterpret_cast<PFN_vkCreateWaylandSurfaceKHR>(
|
||||||
|
vkGetInstanceProcAddr(instance, "vkCreateWaylandSurfaceKHR"));
|
||||||
|
if (createWaylandSurface == nullptr) {
|
||||||
|
reason = "vkCreateWaylandSurfaceKHR is unavailable on the Vulkan instance";
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_display* display = glfwGetWaylandDisplay();
|
||||||
|
wl_surface* waylandSurface = glfwGetWaylandWindow(handle);
|
||||||
|
if (display == nullptr || waylandSurface == nullptr) {
|
||||||
|
reason = "GLFW did not provide valid Wayland native handles";
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkWaylandSurfaceCreateInfoKHR createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.display = display,
|
||||||
|
.surface = waylandSurface,
|
||||||
|
};
|
||||||
|
return createWaylandSurface(instance, &createInfo, nullptr, surface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(GLFW_PLATFORM_X11)
|
||||||
|
if (glfwGetPlatform() == GLFW_PLATFORM_X11) {
|
||||||
|
auto createXlibSurface = reinterpret_cast<PFN_vkCreateXlibSurfaceKHR>(
|
||||||
|
vkGetInstanceProcAddr(instance, "vkCreateXlibSurfaceKHR"));
|
||||||
|
if (createXlibSurface == nullptr) {
|
||||||
|
reason = "vkCreateXlibSurfaceKHR is unavailable on the Vulkan instance";
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Display* display = glfwGetX11Display();
|
||||||
|
::Window x11Window = glfwGetX11Window(handle);
|
||||||
|
if (display == nullptr || x11Window == 0) {
|
||||||
|
reason = "GLFW did not provide valid X11 native handles";
|
||||||
|
return VK_ERROR_INITIALIZATION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkXlibSurfaceCreateInfoKHR createInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
|
||||||
|
.pNext = nullptr,
|
||||||
|
.flags = 0,
|
||||||
|
.dpy = display,
|
||||||
|
.window = x11Window,
|
||||||
|
};
|
||||||
|
return createXlibSurface(instance, &createInfo, nullptr, surface);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
reason = "Unsupported GLFW platform for manual Vulkan surface creation";
|
||||||
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
double currentFrameDelta = 0;
|
double currentFrameDelta = 0;
|
||||||
double Gfx::getCurrentFrameDelta() { return currentFrameDelta; }
|
double Gfx::getCurrentFrameDelta() { return currentFrameDelta; }
|
||||||
|
|
||||||
@@ -21,46 +91,57 @@ void glfwKeyCallback(GLFWwindow* handle, int key, int, int action, int modifier)
|
|||||||
if (key == -1) {
|
if (key == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->keyPress((KeyCode)key, (InputAction)action, (KeyModifier)modifier);
|
window->keyPress(static_cast<Seele::KeyCode>(key), static_cast<InputAction>(action), modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos) {
|
void glfwMouseMoveCallback(GLFWwindow* handle, double xpos, double ypos) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->mouseMove(xpos, ypos);
|
window->mouseMove(xpos, ypos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier) {
|
void glfwMouseButtonCallback(GLFWwindow* handle, int button, int action, int modifier) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->mouseButton((MouseButton)button, (InputAction)action, (KeyModifier)modifier);
|
window->mouseButton(static_cast<MouseButton>(button), static_cast<InputAction>(action), static_cast<KeyModifierFlags>(modifier));
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset) {
|
void glfwScrollCallback(GLFWwindow* handle, double xoffset, double yoffset) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->scroll(xoffset, yoffset);
|
window->scroll(xoffset, yoffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwFileCallback(GLFWwindow* handle, int count, const char** paths) {
|
void glfwFileCallback(GLFWwindow* handle, int count, const char** paths) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->fileDrop(count, paths);
|
window->fileDrop(count, paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwCloseCallback(GLFWwindow* handle) {
|
void glfwCloseCallback(GLFWwindow* handle) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->close();
|
window->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void glfwFramebufferResizeCallback(GLFWwindow* handle, int width, int height) {
|
void glfwFramebufferResizeCallback(GLFWwindow* handle, int width, int height) {
|
||||||
Window* window = (Window*)glfwGetWindowUserPointer(handle);
|
auto* window = static_cast<Seele::Vulkan::Window*>(glfwGetWindowUserPointer(handle));
|
||||||
window->resize(width, height);
|
window->resize(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
Seele::Vulkan::Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
||||||
: graphics(graphics), preferences(createInfo), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE) {
|
: graphics(graphics), preferences(createInfo), instance(graphics->getInstance()), swapchain(VK_NULL_HANDLE) {
|
||||||
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &contentScaleX, &contentScaleY);
|
glfwGetMonitorContentScale(glfwGetPrimaryMonitor(), &contentScaleX, &contentScaleY);
|
||||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||||
|
glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
|
||||||
GLFWwindow* handle = glfwCreateWindow(createInfo.width / contentScaleX, createInfo.height / contentScaleY, createInfo.title, nullptr, nullptr);
|
GLFWwindow* handle = glfwCreateWindow(createInfo.width / contentScaleX, createInfo.height / contentScaleY, createInfo.title, nullptr, nullptr);
|
||||||
|
if (handle == nullptr) {
|
||||||
|
const char* glfwError = nullptr;
|
||||||
|
glfwGetError(&glfwError);
|
||||||
|
std::string message = "Failed to create GLFW window";
|
||||||
|
if (glfwError != nullptr) {
|
||||||
|
message += ": ";
|
||||||
|
message += glfwError;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(message);
|
||||||
|
}
|
||||||
windowHandle = handle;
|
windowHandle = handle;
|
||||||
glfwSetWindowUserPointer(handle, this);
|
glfwSetWindowUserPointer(handle, this);
|
||||||
|
|
||||||
@@ -73,7 +154,25 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
|||||||
glfwSetFramebufferSizeCallback(handle, &glfwFramebufferResizeCallback);
|
glfwSetFramebufferSizeCallback(handle, &glfwFramebufferResizeCallback);
|
||||||
// glfwSetWindowSizeCallback(handle, &glfwResizeCallback);
|
// glfwSetWindowSizeCallback(handle, &glfwResizeCallback);
|
||||||
|
|
||||||
glfwCreateWindowSurface(instance, handle, nullptr, &surface);
|
VkResult surfaceResult = glfwCreateWindowSurface(instance, handle, nullptr, &surface);
|
||||||
|
if (surfaceResult != VK_SUCCESS || surface == VK_NULL_HANDLE) {
|
||||||
|
const char* glfwError = nullptr;
|
||||||
|
glfwGetError(&glfwError);
|
||||||
|
|
||||||
|
std::string nativeReason;
|
||||||
|
surfaceResult = createSurfaceFromNativeHandles(instance, handle, &surface, nativeReason);
|
||||||
|
if (surfaceResult != VK_SUCCESS || surface == VK_NULL_HANDLE) {
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "Failed to create Vulkan surface via GLFW (VkResult=" << surfaceResult << ")";
|
||||||
|
if (glfwError != nullptr) {
|
||||||
|
oss << ": " << glfwError;
|
||||||
|
}
|
||||||
|
if (!nativeReason.empty()) {
|
||||||
|
oss << ". Native fallback failed: " << nativeReason;
|
||||||
|
}
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
querySurface();
|
querySurface();
|
||||||
chooseSwapSurfaceFormat();
|
chooseSwapSurfaceFormat();
|
||||||
@@ -85,17 +184,17 @@ Window::Window(PGraphics graphics, const WindowCreateInfo& createInfo)
|
|||||||
createSwapChain();
|
createSwapChain();
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window() {
|
Seele::Vulkan::Window::~Window() {
|
||||||
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
|
vkDestroySwapchainKHR(graphics->getDevice(), swapchain, nullptr);
|
||||||
vkDestroySurfaceKHR(instance, surface, nullptr);
|
vkDestroySurfaceKHR(instance, surface, nullptr);
|
||||||
glfwDestroyWindow(static_cast<GLFWwindow*>(windowHandle));
|
glfwDestroyWindow(static_cast<GLFWwindow*>(windowHandle));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::pollInput() { glfwPollEvents(); }
|
void Seele::Vulkan::Window::pollInput() { glfwPollEvents(); }
|
||||||
|
|
||||||
void Window::show() { glfwShowWindow(static_cast<GLFWwindow*>(windowHandle)); }
|
void Seele::Vulkan::Window::show() { glfwShowWindow(static_cast<GLFWwindow*>(windowHandle)); }
|
||||||
|
|
||||||
void Window::beginFrame() {
|
void Seele::Vulkan::Window::beginFrame() {
|
||||||
imageAvailableFences[currentSemaphoreIndex]->reset();
|
imageAvailableFences[currentSemaphoreIndex]->reset();
|
||||||
imageAvailableSemaphores[currentSemaphoreIndex]->resolveSignal();
|
imageAvailableSemaphores[currentSemaphoreIndex]->resolveSignal();
|
||||||
imageAvailableSemaphores[currentSemaphoreIndex]->rotateSemaphore();
|
imageAvailableSemaphores[currentSemaphoreIndex]->rotateSemaphore();
|
||||||
@@ -104,6 +203,9 @@ void Window::beginFrame() {
|
|||||||
imageAvailableFences[currentSemaphoreIndex]->getHandle(), ¤tImageIndex));
|
imageAvailableFences[currentSemaphoreIndex]->getHandle(), ¤tImageIndex));
|
||||||
imageAvailableSemaphores[currentSemaphoreIndex]->encodeSignal();
|
imageAvailableSemaphores[currentSemaphoreIndex]->encodeSignal();
|
||||||
imageAvailableFences[currentSemaphoreIndex]->submit();
|
imageAvailableFences[currentSemaphoreIndex]->submit();
|
||||||
|
// The image was reacquired, so the previous presentation using this image's
|
||||||
|
// renderDone semaphore has completed and it can be safely reused
|
||||||
|
renderingDoneSemaphores[currentImageIndex]->resolveSignal();
|
||||||
graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
graphics->getGraphicsCommands()->getCommands()->waitForSemaphore(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
||||||
imageAvailableSemaphores[currentSemaphoreIndex]);
|
imageAvailableSemaphores[currentSemaphoreIndex]);
|
||||||
static double start = glfwGetTime();
|
static double start = glfwGetTime();
|
||||||
@@ -113,13 +215,13 @@ void Window::beginFrame() {
|
|||||||
start = end;
|
start = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::endFrame() {
|
void Seele::Vulkan::Window::endFrame() {
|
||||||
swapChainTextures[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR, Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
swapChainTextures[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_PRESENT_SRC_KHR, Gfx::SE_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
||||||
Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_MEMORY_READ_BIT,
|
Gfx::SE_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, Gfx::SE_ACCESS_MEMORY_READ_BIT,
|
||||||
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
Gfx::SE_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||||
renderingDoneSemaphores[currentSemaphoreIndex]->rotateSemaphore();
|
renderingDoneSemaphores[currentImageIndex]->rotateSemaphore();
|
||||||
graphics->getGraphicsCommands()->submitCommands(renderingDoneSemaphores[currentSemaphoreIndex]);
|
graphics->getGraphicsCommands()->submitCommands(renderingDoneSemaphores[currentImageIndex]);
|
||||||
VkSemaphore renderDoneHandle = renderingDoneSemaphores[currentSemaphoreIndex]->getHandle();
|
VkSemaphore renderDoneHandle = renderingDoneSemaphores[currentImageIndex]->getHandle();
|
||||||
VkPresentInfoKHR presentInfo = {
|
VkPresentInfoKHR presentInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
@@ -137,46 +239,45 @@ void Window::endFrame() {
|
|||||||
} else {
|
} else {
|
||||||
VK_CHECK(r);
|
VK_CHECK(r);
|
||||||
}
|
}
|
||||||
renderingDoneSemaphores[currentSemaphoreIndex]->resolveSignal();
|
renderingDoneSemaphores[currentImageIndex]->encodeSignal();
|
||||||
currentSemaphoreIndex = (currentSemaphoreIndex + 1) % Gfx::numFramesBuffered;
|
currentSemaphoreIndex = (currentSemaphoreIndex + 1) % Gfx::numFramesBuffered;
|
||||||
currentFrameIndex = currentSemaphoreIndex;
|
currentFrameIndex = currentSemaphoreIndex;
|
||||||
// graphics->waitDeviceIdle();
|
// graphics->waitDeviceIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Window::shouldClose() const {
|
bool Seele::Vulkan::Window::shouldClose() const {
|
||||||
std::cout << "Checking if window should close: " << glfwWindowShouldClose((GLFWwindow*)windowHandle) << std::endl;
|
|
||||||
return glfwWindowShouldClose((GLFWwindow*)windowHandle);
|
return glfwWindowShouldClose((GLFWwindow*)windowHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gfx::PTexture2D Window::getBackBuffer() const { return PTexture2D(swapChainTextures[currentImageIndex]); }
|
Gfx::PTexture2D Seele::Vulkan::Window::getBackBuffer() const { return PTexture2D(swapChainTextures[currentImageIndex]); }
|
||||||
|
|
||||||
void Window::setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) { keyCallback = callback; }
|
void Seele::Vulkan::Window::setKeyCallback(std::function<void(Seele::KeyCode, InputAction, KeyModifierFlags)> callback) { keyCallback = callback; }
|
||||||
|
|
||||||
void Window::setMouseMoveCallback(std::function<void(double, double)> callback) { mouseMoveCallback = callback; }
|
void Seele::Vulkan::Window::setMouseMoveCallback(std::function<void(double, double)> callback) { mouseMoveCallback = callback; }
|
||||||
|
|
||||||
void Window::setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) { mouseButtonCallback = callback; }
|
void Seele::Vulkan::Window::setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifierFlags)> callback) { mouseButtonCallback = callback; }
|
||||||
|
|
||||||
void Window::setScrollCallback(std::function<void(double, double)> callback) { scrollCallback = callback; }
|
void Seele::Vulkan::Window::setScrollCallback(std::function<void(double, double)> callback) { scrollCallback = callback; }
|
||||||
|
|
||||||
void Window::setFileCallback(std::function<void(int, const char**)> callback) { fileCallback = callback; }
|
void Seele::Vulkan::Window::setFileCallback(std::function<void(int, const char**)> callback) { fileCallback = callback; }
|
||||||
|
|
||||||
void Window::setCloseCallback(std::function<void()> callback) { closeCallback = callback; }
|
void Seele::Vulkan::Window::setCloseCallback(std::function<void()> callback) { closeCallback = callback; }
|
||||||
|
|
||||||
void Window::setResizeCallback(std::function<void(uint32, uint32)> callback) { resizeCallback = callback; }
|
void Seele::Vulkan::Window::setResizeCallback(std::function<void(uint32, uint32)> callback) { resizeCallback = callback; }
|
||||||
|
|
||||||
void Window::keyPress(KeyCode code, InputAction action, KeyModifier modifier) { keyCallback(code, action, modifier); }
|
void Seele::Vulkan::Window::keyPress(Seele::KeyCode code, InputAction action, KeyModifierFlags modifier) { keyCallback(code, action, modifier); }
|
||||||
|
|
||||||
void Window::mouseMove(double x, double y) { mouseMoveCallback(x, y); }
|
void Seele::Vulkan::Window::mouseMove(double x, double y) { mouseMoveCallback(x, y); }
|
||||||
|
|
||||||
void Window::mouseButton(MouseButton button, InputAction action, KeyModifier modifier) { mouseButtonCallback(button, action, modifier); }
|
void Seele::Vulkan::Window::mouseButton(MouseButton button, InputAction action, KeyModifierFlags modifier) { mouseButtonCallback(button, action, modifier); }
|
||||||
|
|
||||||
void Window::scroll(double x, double y) { scrollCallback(x, y); }
|
void Seele::Vulkan::Window::scroll(double x, double y) { scrollCallback(x, y); }
|
||||||
|
|
||||||
void Window::fileDrop(int num, const char** files) { fileCallback(num, files); }
|
void Seele::Vulkan::Window::fileDrop(int num, const char** files) { fileCallback(num, files); }
|
||||||
|
|
||||||
void Window::close() { closeCallback(); }
|
void Seele::Vulkan::Window::close() { closeCallback(); }
|
||||||
|
|
||||||
void Window::resize(int width, int height) {
|
void Seele::Vulkan::Window::resize(int width, int height) {
|
||||||
if (width == 0 || height == 0) {
|
if (width == 0 || height == 0) {
|
||||||
paused = true;
|
paused = true;
|
||||||
return;
|
return;
|
||||||
@@ -193,7 +294,7 @@ void Window::resize(int width, int height) {
|
|||||||
resizeCallback(width, height);
|
resizeCallback(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::querySurface() {
|
void Seele::Vulkan::Window::querySurface() {
|
||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(graphics->getPhysicalDevice(), surface, &capabilities);
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(graphics->getPhysicalDevice(), surface, &capabilities);
|
||||||
|
|
||||||
uint32 numFormats;
|
uint32 numFormats;
|
||||||
@@ -207,7 +308,7 @@ void Window::querySurface() {
|
|||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, supportedPresentModes.data());
|
vkGetPhysicalDeviceSurfacePresentModesKHR(graphics->getPhysicalDevice(), surface, &numPresentModes, supportedPresentModes.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::chooseSwapSurfaceFormat() {
|
void Seele::Vulkan::Window::chooseSwapSurfaceFormat() {
|
||||||
for (const auto& supportedFormat : supportedFormats) {
|
for (const auto& supportedFormat : supportedFormats) {
|
||||||
if (supportedFormat.format == cast(preferences.preferredFormat)) {
|
if (supportedFormat.format == cast(preferences.preferredFormat)) {
|
||||||
format = supportedFormat;
|
format = supportedFormat;
|
||||||
@@ -223,7 +324,7 @@ void Window::chooseSwapSurfaceFormat() {
|
|||||||
format = supportedFormats[0];
|
format = supportedFormats[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::chooseSwapPresentMode() {
|
void Seele::Vulkan::Window::chooseSwapPresentMode() {
|
||||||
for (const auto& supportedPresentMode : supportedPresentModes) {
|
for (const auto& supportedPresentMode : supportedPresentModes) {
|
||||||
if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
if (supportedPresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
||||||
presentMode = supportedPresentMode;
|
presentMode = supportedPresentMode;
|
||||||
@@ -233,7 +334,7 @@ void Window::chooseSwapPresentMode() {
|
|||||||
presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::chooseSwapExtent() {
|
void Seele::Vulkan::Window::chooseSwapExtent() {
|
||||||
if (capabilities.currentExtent.width != std::numeric_limits<uint32>::max()) {
|
if (capabilities.currentExtent.width != std::numeric_limits<uint32>::max()) {
|
||||||
extent = capabilities.currentExtent;
|
extent = capabilities.currentExtent;
|
||||||
return;
|
return;
|
||||||
@@ -249,7 +350,8 @@ void Window::chooseSwapExtent() {
|
|||||||
extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
extent.height = std::clamp(extent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::createSwapChain() {
|
void Seele::Vulkan::Window::createSwapChain() {
|
||||||
|
graphics->waitDeviceIdle();
|
||||||
uint32 imageCount = Gfx::numFramesBuffered;
|
uint32 imageCount = Gfx::numFramesBuffered;
|
||||||
VkSwapchainCreateInfoKHR createInfo = {
|
VkSwapchainCreateInfoKHR createInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||||
|
|||||||
@@ -17,17 +17,17 @@ class Window : public Gfx::Window {
|
|||||||
virtual void endFrame() override;
|
virtual void endFrame() override;
|
||||||
virtual Gfx::PTexture2D getBackBuffer() const override;
|
virtual Gfx::PTexture2D getBackBuffer() const override;
|
||||||
virtual bool shouldClose() const override;
|
virtual bool shouldClose() const override;
|
||||||
virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) override;
|
virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifierFlags)> callback) override;
|
||||||
virtual void setMouseMoveCallback(std::function<void(double, double)> callback) override;
|
virtual void setMouseMoveCallback(std::function<void(double, double)> callback) override;
|
||||||
virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) override;
|
virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifierFlags)> callback) override;
|
||||||
virtual void setScrollCallback(std::function<void(double, double)> callback) override;
|
virtual void setScrollCallback(std::function<void(double, double)> callback) override;
|
||||||
virtual void setFileCallback(std::function<void(int, const char**)> callback) override;
|
virtual void setFileCallback(std::function<void(int, const char**)> callback) override;
|
||||||
virtual void setCloseCallback(std::function<void()> callback) override;
|
virtual void setCloseCallback(std::function<void()> callback) override;
|
||||||
virtual void setResizeCallback(std::function<void(uint32, uint32)> callback) override;
|
virtual void setResizeCallback(std::function<void(uint32, uint32)> callback) override;
|
||||||
|
|
||||||
void keyPress(KeyCode code, InputAction action, KeyModifier modifier);
|
void keyPress(KeyCode code, InputAction action, KeyModifierFlags modifier);
|
||||||
void mouseMove(double x, double y);
|
void mouseMove(double x, double y);
|
||||||
void mouseButton(MouseButton button, InputAction action, KeyModifier modifier);
|
void mouseButton(MouseButton button, InputAction action, KeyModifierFlags modifier);
|
||||||
void scroll(double x, double y);
|
void scroll(double x, double y);
|
||||||
void fileDrop(int num, const char** files);
|
void fileDrop(int num, const char** files);
|
||||||
void close();
|
void close();
|
||||||
@@ -61,9 +61,9 @@ class Window : public Gfx::Window {
|
|||||||
uint32 currentImageIndex = 0;
|
uint32 currentImageIndex = 0;
|
||||||
uint32 currentSemaphoreIndex = 0;
|
uint32 currentSemaphoreIndex = 0;
|
||||||
|
|
||||||
std::function<void(KeyCode, InputAction, KeyModifier)> keyCallback;
|
std::function<void(KeyCode, InputAction, KeyModifierFlags)> keyCallback;
|
||||||
std::function<void(double, double)> mouseMoveCallback;
|
std::function<void(double, double)> mouseMoveCallback;
|
||||||
std::function<void(MouseButton, InputAction, KeyModifier)> mouseButtonCallback;
|
std::function<void(MouseButton, InputAction, KeyModifierFlags)> mouseButtonCallback;
|
||||||
std::function<void(double, double)> scrollCallback;
|
std::function<void(double, double)> scrollCallback;
|
||||||
std::function<void(int, const char**)> fileCallback;
|
std::function<void(int, const char**)> fileCallback;
|
||||||
std::function<void()> closeCallback;
|
std::function<void()> closeCallback;
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ class Window {
|
|||||||
virtual void endFrame() = 0;
|
virtual void endFrame() = 0;
|
||||||
virtual bool shouldClose() const = 0;
|
virtual bool shouldClose() const = 0;
|
||||||
virtual PTexture2D getBackBuffer() const = 0;
|
virtual PTexture2D getBackBuffer() const = 0;
|
||||||
virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifier)> callback) = 0;
|
virtual void setKeyCallback(std::function<void(KeyCode, InputAction, KeyModifierFlags)> callback) = 0;
|
||||||
virtual void setMouseMoveCallback(std::function<void(double, double)> callback) = 0;
|
virtual void setMouseMoveCallback(std::function<void(double, double)> callback) = 0;
|
||||||
virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifier)> callback) = 0;
|
virtual void setMouseButtonCallback(std::function<void(MouseButton, InputAction, KeyModifierFlags)> callback) = 0;
|
||||||
virtual void setScrollCallback(std::function<void(double, double)> callback) = 0;
|
virtual void setScrollCallback(std::function<void(double, double)> callback) = 0;
|
||||||
virtual void setFileCallback(std::function<void(int, const char**)> callback) = 0;
|
virtual void setFileCallback(std::function<void(int, const char**)> callback) = 0;
|
||||||
virtual void setCloseCallback(std::function<void()> callback) = 0;
|
virtual void setCloseCallback(std::function<void()> callback) = 0;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include "slang-compile.h"
|
#include "slang-compile.h"
|
||||||
#include "Containers/Array.h"
|
#include "Containers/Array.h"
|
||||||
#include "Graphics/Descriptor.h"
|
#include "Graphics/Descriptor.h"
|
||||||
|
#include <array>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <filesystem>
|
||||||
#include <fmt/core.h>
|
#include <fmt/core.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <slang.h>
|
#include <slang.h>
|
||||||
@@ -27,37 +30,59 @@ thread_local Slang::ComPtr<slang::IComponentType> specializedComponent;
|
|||||||
thread_local Slang::ComPtr<slang::ISession> session;
|
thread_local Slang::ComPtr<slang::ISession> session;
|
||||||
thread_local Array<std::string> entryPoints;
|
thread_local Array<std::string> entryPoints;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
void appendEnvPath(const char* varName, const std::filesystem::path& path) {
|
||||||
|
if (!std::filesystem::exists(path) || !std::filesystem::is_directory(path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string newEntry = path.lexically_normal().string();
|
||||||
|
const char* currentRaw = std::getenv(varName);
|
||||||
|
std::string current = currentRaw ? currentRaw : "";
|
||||||
|
if (current.find(newEntry) != std::string::npos) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string updated = current.empty() ? newEntry : (newEntry + ":" + current);
|
||||||
|
setenv(varName, updated.c_str(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void configureSlangRuntimeEnv() {
|
||||||
|
std::filesystem::path exePath;
|
||||||
|
try {
|
||||||
|
exePath = std::filesystem::canonical("/proc/self/exe");
|
||||||
|
} catch (...) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::filesystem::path exeDir = exePath.parent_path();
|
||||||
|
const std::array<std::filesystem::path, 7> candidates = {
|
||||||
|
exeDir / "vcpkg_installed/x64-linux/lib",
|
||||||
|
exeDir / "vcpkg_installed/x64-linux/debug/lib",
|
||||||
|
exeDir / "vcpkg_installed/x64-linux/tools/shader-slang",
|
||||||
|
exeDir.parent_path() / "vcpkg_installed/x64-linux/lib",
|
||||||
|
exeDir.parent_path() / "vcpkg_installed/x64-linux/debug/lib",
|
||||||
|
exeDir.parent_path() / "vcpkg_installed/x64-linux/tools/shader-slang",
|
||||||
|
std::filesystem::current_path() / "build/vcpkg_installed/x64-linux/tools/shader-slang",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto& candidate : candidates) {
|
||||||
|
appendEnvPath("LD_LIBRARY_PATH", candidate);
|
||||||
|
appendEnvPath("PATH", candidate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarget target, Gfx::PPipelineLayout layout) {
|
void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarget target, Gfx::PPipelineLayout layout) {
|
||||||
if (!globalSession) {
|
if (!globalSession) {
|
||||||
slang::createGlobalSession(globalSession.writeRef());
|
configureSlangRuntimeEnv();
|
||||||
|
SlangGlobalSessionDesc sessionDesc = {};
|
||||||
|
sessionDesc.enableGLSL = true;
|
||||||
|
slang::createGlobalSession(&sessionDesc, globalSession.writeRef());
|
||||||
}
|
}
|
||||||
slang::SessionDesc sessionDesc;
|
slang::SessionDesc sessionDesc;
|
||||||
sessionDesc.flags = 0;
|
sessionDesc.flags = 0;
|
||||||
Array<slang::CompilerOptionEntry> option = {
|
Array<slang::CompilerOptionEntry> option = {
|
||||||
{
|
|
||||||
.name = slang::CompilerOptionName::LineDirectiveMode,
|
|
||||||
.value =
|
|
||||||
{
|
|
||||||
.kind = slang::CompilerOptionValueKind::Int,
|
|
||||||
.intValue0 = SLANG_LINE_DIRECTIVE_MODE_NONE,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = slang::CompilerOptionName::DebugInformation,
|
|
||||||
.value =
|
|
||||||
{
|
|
||||||
.kind = slang::CompilerOptionValueKind::Int,
|
|
||||||
.intValue0 = SLANG_DEBUG_INFO_LEVEL_STANDARD,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.name = slang::CompilerOptionName::DebugInformationFormat,
|
|
||||||
.value =
|
|
||||||
{
|
|
||||||
.kind = slang::CompilerOptionValueKind::Int,
|
|
||||||
.intValue0 = SLANG_DEBUG_INFO_FORMAT_PDB,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
.name = slang::CompilerOptionName::DumpIntermediates,
|
.name = slang::CompilerOptionName::DumpIntermediates,
|
||||||
.value =
|
.value =
|
||||||
@@ -66,10 +91,50 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
|
|||||||
.intValue0 = info.dumpIntermediate,
|
.intValue0 = info.dumpIntermediate,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = slang::CompilerOptionName::Optimization,
|
||||||
|
.value =
|
||||||
|
{
|
||||||
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
|
.intValue0 = SLANG_OPTIMIZATION_LEVEL_NONE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = slang::CompilerOptionName::EmitSpirvMethod,
|
||||||
|
.value =
|
||||||
|
{
|
||||||
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
|
.intValue0 = SLANG_EMIT_SPIRV_DIRECTLY,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = slang::CompilerOptionName::PassThrough,
|
||||||
|
.value =
|
||||||
|
{
|
||||||
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
|
.intValue0 = SLANG_PASS_THROUGH_NONE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = slang::CompilerOptionName::SkipSPIRVValidation,
|
||||||
|
.value =
|
||||||
|
{
|
||||||
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
|
.intValue0 = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = slang::CompilerOptionName::SkipDownstreamLinking,
|
||||||
|
.value =
|
||||||
|
{
|
||||||
|
.kind = slang::CompilerOptionValueKind::Int,
|
||||||
|
.intValue0 = 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
sessionDesc.compilerOptionEntries = 0;//option.data();
|
sessionDesc.compilerOptionEntries = option.data();
|
||||||
sessionDesc.compilerOptionEntryCount = 0;//(uint32)option.size();
|
sessionDesc.compilerOptionEntryCount = (uint32)option.size();
|
||||||
sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR;
|
sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR;
|
||||||
Array<slang::PreprocessorMacroDesc> macros;
|
Array<slang::PreprocessorMacroDesc> macros;
|
||||||
for (const auto& [key, val] : info.defines) {
|
for (const auto& [key, val] : info.defines) {
|
||||||
@@ -82,10 +147,9 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
|
|||||||
sessionDesc.preprocessorMacros = macros.data();
|
sessionDesc.preprocessorMacros = macros.data();
|
||||||
slang::TargetDesc targetDesc = {};
|
slang::TargetDesc targetDesc = {};
|
||||||
targetDesc.format = target;
|
targetDesc.format = target;
|
||||||
targetDesc.flags = SLANG_TARGET_FLAG_GENERATE_SPIRV_DIRECTLY;
|
|
||||||
sessionDesc.targetCount = 1;
|
sessionDesc.targetCount = 1;
|
||||||
sessionDesc.targets = &targetDesc;
|
sessionDesc.targets = &targetDesc;
|
||||||
StaticArray<const char*, 7> searchPaths = {"shaders/", "shaders/lib/", "shaders/raytracing/", "shaders/terrain", "shaders/game", "shaders/generated/", "Seele/shaders/lib/"};
|
StaticArray<const char*, 7> searchPaths = {"shaders/", "shaders/lib/", "shaders/raytracing/", "shaders/terrain", "shaders/game", "shaders/generated/", "shaders/fluid"};
|
||||||
sessionDesc.searchPaths = searchPaths.data();
|
sessionDesc.searchPaths = searchPaths.data();
|
||||||
sessionDesc.searchPathCount = searchPaths.size();
|
sessionDesc.searchPathCount = searchPaths.size();
|
||||||
|
|
||||||
@@ -136,16 +200,6 @@ void Seele::beginCompilation(const ShaderCompilationInfo& info, SlangCompileTarg
|
|||||||
layout->addMapping(param->getName(), param->getBindingIndex());
|
layout->addMapping(param->getName(), param->getBindingIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
// workaround
|
|
||||||
if (info.name == "RayGenMiss")
|
|
||||||
{
|
|
||||||
layout->addMapping("pScene", 2);
|
|
||||||
layout->addMapping("pLightEnv", 3);
|
|
||||||
layout->addMapping("pResources", 4);
|
|
||||||
layout->addMapping("pRayTracingParams", 5);
|
|
||||||
}
|
|
||||||
//layout->addMapping("pVertexData", 1);
|
|
||||||
// layout->addMapping("pWaterMaterial", 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<Slang::ComPtr<slang::IBlob>, std::string> Seele::generateShader(const ShaderCreateInfo& createInfo) {
|
Pair<Slang::ComPtr<slang::IBlob>, std::string> Seele::generateShader(const ShaderCreateInfo& createInfo) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
target_sources(Engine
|
target_sources(Engine
|
||||||
PRIVATE
|
PRIVATE
|
||||||
EventManager.h
|
EventManager.h
|
||||||
|
FluidScene.h
|
||||||
|
FluidScene.cpp
|
||||||
LightEnvironment.h
|
LightEnvironment.h
|
||||||
LightEnvironment.cpp
|
LightEnvironment.cpp
|
||||||
Util.h
|
Util.h
|
||||||
@@ -11,6 +13,7 @@ target_sources(Engine
|
|||||||
PUBLIC FILE_SET HEADERS
|
PUBLIC FILE_SET HEADERS
|
||||||
FILES
|
FILES
|
||||||
EventManager.h
|
EventManager.h
|
||||||
|
FluidScene.h
|
||||||
LightEnvironment.h
|
LightEnvironment.h
|
||||||
Util.h
|
Util.h
|
||||||
Scene.h)
|
Scene.h)
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
#include "FluidScene.h"
|
||||||
|
#include "Graphics/Command.h"
|
||||||
|
#include "Graphics/Descriptor.h"
|
||||||
|
#include "Graphics/Enums.h"
|
||||||
|
#include "Graphics/Initializer.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
FluidScene::FluidScene(Gfx::PGraphics graphics) : graphics(graphics) {
|
||||||
|
pipelineLayout = graphics->createPipelineLayout("FluidScenePipelineLayout");
|
||||||
|
gridParamsLayout = graphics->createDescriptorLayout("gridParams");
|
||||||
|
gridParamsLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = "gridSize",
|
||||||
|
.uniformLength = sizeof(UVector),
|
||||||
|
});
|
||||||
|
gridParamsLayout->create();
|
||||||
|
descriptorLayout = graphics->createDescriptorLayout("params");
|
||||||
|
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = "phi",
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
});
|
||||||
|
descriptorLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||||
|
.name = "density",
|
||||||
|
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||||
|
});
|
||||||
|
descriptorLayout->create();
|
||||||
|
pipelineLayout->addDescriptorLayout(descriptorLayout);
|
||||||
|
pipelineLayout->addDescriptorLayout(gridParamsLayout);
|
||||||
|
|
||||||
|
graphics->beginShaderCompilation(ShaderCompilationInfo{
|
||||||
|
.name = "AddSource",
|
||||||
|
.modules = {"AddSource"},
|
||||||
|
.entryPoints = {{"addSource", "AddSource"}},
|
||||||
|
.rootSignature = pipelineLayout,
|
||||||
|
});
|
||||||
|
pipelineLayout->create();
|
||||||
|
shader = graphics->createComputeShader({0});
|
||||||
|
pipeline = graphics->createComputePipeline(Gfx::ComputePipelineCreateInfo{
|
||||||
|
.computeShader = shader,
|
||||||
|
.pipelineLayout = pipelineLayout,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
FluidScene::~FluidScene() {}
|
||||||
|
|
||||||
|
void FluidScene::updateFluidData(uint32 entityID, const Component::Transform& transform, const Component::FluidGrid& grid) {
|
||||||
|
if (!fluidDataMap.contains(entityID)) {
|
||||||
|
auto& data = fluidDataMap[entityID];
|
||||||
|
uint64 totalCells = (uint64)grid.gridSize.x * grid.gridSize.y * grid.gridSize.z;
|
||||||
|
uint64 bufferSize = totalCells * sizeof(float);
|
||||||
|
// Array<float> initialDensity(bufferSize / sizeof(float));
|
||||||
|
// Array<float> initialVelocityX(bufferSize / sizeof(float));
|
||||||
|
// Array<float> initialVelocityY(bufferSize / sizeof(float));
|
||||||
|
// Array<float> initialVelocityZ(bufferSize / sizeof(float));
|
||||||
|
// Array<float> initialPhi(bufferSize / sizeof(float));
|
||||||
|
|
||||||
|
// // Initialize level set to positive (outside) everywhere
|
||||||
|
// float halfGridX = static_cast<float>(grid.gridSize.x) * 0.5f;
|
||||||
|
// float halfGridY = static_cast<float>(grid.gridSize.y) * 0.5f;
|
||||||
|
// float radius = static_cast<float>(grid.gridSize.x) * 0.2f;
|
||||||
|
// // Place sphere center in the lower portion of the grid
|
||||||
|
// float cx = halfGridX;
|
||||||
|
// float cy = halfGridY;
|
||||||
|
// float cz = static_cast<float>(grid.gridSize.z) * 0.3f;
|
||||||
|
// for (uint32 z = 1; z < grid.gridSize.z - 1; ++z) {
|
||||||
|
// for (uint32 y = 1; y < grid.gridSize.y - 1; ++y) {
|
||||||
|
// for (uint32 x = 1; x < grid.gridSize.x - 1; ++x) {
|
||||||
|
// uint32 idx = x + grid.gridSize.x * y + grid.gridSize.x * grid.gridSize.y * z;
|
||||||
|
// float dx = static_cast<float>(x) - cx;
|
||||||
|
// float dy = static_cast<float>(y) - cy;
|
||||||
|
// float dz = static_cast<float>(z) - cz;
|
||||||
|
// float dist = std::sqrt(dx * dx + dy * dy + dz * dz);
|
||||||
|
// initialPhi[idx] = dist - radius;
|
||||||
|
// if (dist < radius) {
|
||||||
|
// initialDensity[idx] = 1.0f;
|
||||||
|
// // Give an initial upward velocity to kick the simulation
|
||||||
|
// initialVelocityZ[idx] = 5.0f;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
data.phiBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
},
|
||||||
|
.name = "PhiBuffer",
|
||||||
|
});
|
||||||
|
data.phi0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
// .data = (uint8*)initialPhi.data(),
|
||||||
|
},
|
||||||
|
.name = "Phi0Buffer",
|
||||||
|
});
|
||||||
|
data.densityBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
},
|
||||||
|
.name = "DensityBuffer",
|
||||||
|
});
|
||||||
|
data.density0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
// .data = (uint8*)initialDensity.data(),
|
||||||
|
},
|
||||||
|
.name = "Density0Buffer",
|
||||||
|
});
|
||||||
|
data.scratchBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
},
|
||||||
|
.name = "ScratchBuffer",
|
||||||
|
});
|
||||||
|
data.velocityXNextBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
},
|
||||||
|
.name = "VelocityXNextBuffer",
|
||||||
|
});
|
||||||
|
data.velocityYNextBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
},
|
||||||
|
.name = "VelocityYNextBuffer",
|
||||||
|
});
|
||||||
|
data.velocityZNextBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
},
|
||||||
|
.name = "VelocityZNextBuffer",
|
||||||
|
});
|
||||||
|
data.velocityXBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
},
|
||||||
|
.name = "VelocityXBuffer",
|
||||||
|
});
|
||||||
|
data.velocityYBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
},
|
||||||
|
.name = "VelocityYBuffer",
|
||||||
|
});
|
||||||
|
data.velocityZBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
},
|
||||||
|
.name = "VelocityZBuffer",
|
||||||
|
});
|
||||||
|
data.velocityX0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
// .data = (uint8*)initialVelocityX.data(),
|
||||||
|
},
|
||||||
|
.name = "VelocityX0Buffer",
|
||||||
|
});
|
||||||
|
data.velocityY0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
// .data = (uint8*)initialVelocityY.data(),
|
||||||
|
},
|
||||||
|
.name = "VelocityY0Buffer",
|
||||||
|
});
|
||||||
|
data.velocityZ0Buffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = bufferSize,
|
||||||
|
// .data = (uint8*)initialVelocityZ.data(),
|
||||||
|
},
|
||||||
|
.name = "VelocityZ0Buffer",
|
||||||
|
});
|
||||||
|
data.vertexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.name = "VertexBuffer",
|
||||||
|
});
|
||||||
|
data.normalBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.name = "NormalBuffer",
|
||||||
|
});
|
||||||
|
data.indexBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.name = "IndexBuffer",
|
||||||
|
});
|
||||||
|
data.surfaceCountBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||||
|
.sourceData =
|
||||||
|
{
|
||||||
|
.size = 4 * sizeof(uint32),
|
||||||
|
},
|
||||||
|
.usage = Gfx::SE_BUFFER_USAGE_INDIRECT_BUFFER_BIT,
|
||||||
|
.name = "SurfaceCountBuffer",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
auto& data = fluidDataMap[entityID];
|
||||||
|
data.paused = grid.paused;
|
||||||
|
data.transform = transform.transform;
|
||||||
|
data.dt = grid.dt;
|
||||||
|
data.viscosity = grid.viscosity;
|
||||||
|
data.diffusion = grid.diffusion;
|
||||||
|
data.gridSize = grid.gridSize;
|
||||||
|
data.gravity = grid.gravity;
|
||||||
|
data.enableGravity = grid.enableGravity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FluidScene::addSource() {
|
||||||
|
for (auto& [entityID, data] : fluidDataMap) {
|
||||||
|
Gfx::ODescriptorSet gridParams = gridParamsLayout->allocateDescriptorSet();
|
||||||
|
gridParams->updateConstants("gridSize", 0, &data.gridSize);
|
||||||
|
gridParams->writeChanges();
|
||||||
|
Gfx::ODescriptorSet descriptorSet = descriptorLayout->allocateDescriptorSet();
|
||||||
|
descriptorSet->updateBuffer("phi", 0, data.phi0Buffer);
|
||||||
|
descriptorSet->updateBuffer("density", 0, data.density0Buffer);
|
||||||
|
descriptorSet->writeChanges();
|
||||||
|
Gfx::OComputeCommand command = graphics->createComputeCommand();
|
||||||
|
command->bindPipeline(pipeline);
|
||||||
|
command->bindDescriptor(descriptorSet);
|
||||||
|
command->bindDescriptor(gridParams);
|
||||||
|
command->dispatch((data.gridSize + threadGroupSize - UVector{1, 1, 1}) / threadGroupSize);
|
||||||
|
graphics->executeCommands(std::move(command));
|
||||||
|
data.phi0Buffer->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);
|
||||||
|
data.density0Buffer->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);
|
||||||
|
|
||||||
|
// Keep render/extraction level set in sync with injected source immediately.
|
||||||
|
graphics->copyBuffer(data.phi0Buffer, data.phiBuffer);
|
||||||
|
data.phiBuffer->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);
|
||||||
|
data.phi0Buffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_READ_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT,
|
||||||
|
Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||||
|
|
||||||
|
// Reinitialize soon after source injection to restore signed-distance quality.
|
||||||
|
data.frameCounter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Component/FluidGrid.h"
|
||||||
|
#include "Component/Transform.h"
|
||||||
|
#include "Containers/Array.h"
|
||||||
|
#include "Containers/Map.h"
|
||||||
|
#include "Graphics/Buffer.h"
|
||||||
|
#include "Graphics/Graphics.h"
|
||||||
|
#include "Graphics/Resources.h"
|
||||||
|
#include "Graphics/Shader.h"
|
||||||
|
#include "Math/Transform.h"
|
||||||
|
#include "Math/Vector.h"
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
|
||||||
|
namespace Seele {
|
||||||
|
class FluidScene {
|
||||||
|
public:
|
||||||
|
FluidScene(Gfx::PGraphics graphics);
|
||||||
|
virtual ~FluidScene();
|
||||||
|
struct FluidData {
|
||||||
|
Math::Transform transform;
|
||||||
|
bool paused;
|
||||||
|
float viscosity;
|
||||||
|
float diffusion;
|
||||||
|
float dt = 0.01f;
|
||||||
|
UVector gridSize;
|
||||||
|
Vector gravity;
|
||||||
|
bool enableGravity;
|
||||||
|
Gfx::OShaderBuffer phiBuffer;
|
||||||
|
Gfx::OShaderBuffer phi0Buffer;
|
||||||
|
Gfx::OShaderBuffer densityBuffer;
|
||||||
|
Gfx::OShaderBuffer density0Buffer;
|
||||||
|
Gfx::OShaderBuffer scratchBuffer;
|
||||||
|
Gfx::OShaderBuffer velocityXNextBuffer;
|
||||||
|
Gfx::OShaderBuffer velocityYNextBuffer;
|
||||||
|
Gfx::OShaderBuffer velocityZNextBuffer;
|
||||||
|
Gfx::OShaderBuffer velocityXBuffer;
|
||||||
|
Gfx::OShaderBuffer velocityYBuffer;
|
||||||
|
Gfx::OShaderBuffer velocityZBuffer;
|
||||||
|
Gfx::OShaderBuffer velocityX0Buffer;
|
||||||
|
Gfx::OShaderBuffer velocityY0Buffer;
|
||||||
|
Gfx::OShaderBuffer velocityZ0Buffer;
|
||||||
|
Gfx::OShaderBuffer vertexBuffer;
|
||||||
|
Gfx::OShaderBuffer normalBuffer;
|
||||||
|
Gfx::OShaderBuffer indexBuffer;
|
||||||
|
Gfx::OShaderBuffer surfaceCountBuffer;
|
||||||
|
uint32 frameCounter = 0;
|
||||||
|
constexpr uint getVertexBufferSize() {
|
||||||
|
// Max 5 triangles per cell, 3 vertices per triangle
|
||||||
|
return gridSize.x * gridSize.y * gridSize.z * 15;
|
||||||
|
}
|
||||||
|
constexpr uint getIndexBufferSize() { return gridSize.x * gridSize.y * gridSize.z * 15; }
|
||||||
|
};
|
||||||
|
void updateFluidData(uint32 entityID, const Component::Transform& transform, const Component::FluidGrid& grid);
|
||||||
|
const Map<uint32, FluidData>& getFluidDataMap() const { return fluidDataMap; }
|
||||||
|
|
||||||
|
void addSource();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Gfx::OPipelineLayout pipelineLayout;
|
||||||
|
Gfx::ODescriptorLayout descriptorLayout;
|
||||||
|
Gfx::ODescriptorLayout gridParamsLayout;
|
||||||
|
Gfx::OComputeShader shader;
|
||||||
|
Gfx::PComputePipeline pipeline;
|
||||||
|
constexpr static UVector threadGroupSize = {32, 8, 1};
|
||||||
|
Gfx::PGraphics graphics;
|
||||||
|
Map<uint32, FluidData> fluidDataMap;
|
||||||
|
};
|
||||||
|
DEFINE_REF(FluidScene)
|
||||||
|
} // namespace Seele
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "LightEnvironment.h"
|
#include "LightEnvironment.h"
|
||||||
#include "Asset/AssetRegistry.h"
|
#include "Asset/AssetRegistry.h"
|
||||||
#include "Asset/EnvironmentMapAsset.h"
|
|
||||||
#include "Graphics/Descriptor.h"
|
#include "Graphics/Descriptor.h"
|
||||||
|
#include "Asset/EnvironmentMapAsset.h"
|
||||||
#include "Graphics/Enums.h"
|
#include "Graphics/Enums.h"
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +1,16 @@
|
|||||||
#include "Scene.h"
|
#include "Scene.h"
|
||||||
#include "Actor/PointLightActor.h"
|
|
||||||
#include "Asset/MaterialAsset.h"
|
|
||||||
#include "Asset/TextureAsset.h"
|
|
||||||
#include "Component/DirectionalLight.h"
|
|
||||||
#include "Component/Mesh.h"
|
|
||||||
#include "Component/PointLight.h"
|
|
||||||
#include "Component/Transform.h"
|
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
#include "Graphics/Mesh.h"
|
#include "LightEnvironment.h"
|
||||||
#include "Graphics/StaticMeshVertexData.h"
|
#include "FluidScene.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
Scene::Scene(Gfx::PGraphics graphics)
|
Scene::Scene(Gfx::PGraphics graphics)
|
||||||
: graphics(graphics), lightEnv(new LightEnvironment(graphics)), physics(registry) {}
|
: graphics(graphics), lightEnv(new LightEnvironment(graphics)), fluidScene(new FluidScene(graphics)), physics(registry) {}
|
||||||
|
|
||||||
Scene::~Scene() {}
|
Scene::~Scene() {}
|
||||||
|
|
||||||
void Scene::bakeLighting() {}
|
void Scene::bakeLighting() {}
|
||||||
|
|
||||||
void Scene::update(float deltaTime) { physics.update(deltaTime); }
|
void Scene::update(float deltaTime) { physics.update(deltaTime); }
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
#include "Component/Skybox.h"
|
|
||||||
#include "Graphics/Graphics.h"
|
#include "Graphics/Graphics.h"
|
||||||
#include "LightEnvironment.h"
|
|
||||||
#include "Physics/PhysicsSystem.h"
|
#include "Physics/PhysicsSystem.h"
|
||||||
#include <entt/entt.hpp>
|
#include <entt/entt.hpp>
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
namespace Seele {
|
namespace Seele {
|
||||||
DECLARE_REF(Material)
|
DECLARE_REF(Material)
|
||||||
DECLARE_REF(Entity)
|
DECLARE_REF(Entity)
|
||||||
|
DECLARE_REF(FluidScene)
|
||||||
|
DECLARE_REF(LightEnvironment)
|
||||||
class Scene {
|
class Scene {
|
||||||
public:
|
public:
|
||||||
Scene(Gfx::PGraphics graphics);
|
Scene(Gfx::PGraphics graphics);
|
||||||
@@ -33,12 +31,14 @@ class Scene {
|
|||||||
template <typename Component> auto constructCallback() { return registry.on_construct<Component>(); }
|
template <typename Component> auto constructCallback() { return registry.on_construct<Component>(); }
|
||||||
template <typename Component> auto destroyCallback() { return registry.on_destroy<Component>(); }
|
template <typename Component> auto destroyCallback() { return registry.on_destroy<Component>(); }
|
||||||
PLightEnvironment getLightEnvironment() { return lightEnv; }
|
PLightEnvironment getLightEnvironment() { return lightEnv; }
|
||||||
|
PFluidScene getFluidScene() { return fluidScene; }
|
||||||
Gfx::PGraphics getGraphics() const { return graphics; }
|
Gfx::PGraphics getGraphics() const { return graphics; }
|
||||||
entt::registry registry;
|
entt::registry registry;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Gfx::PGraphics graphics;
|
Gfx::PGraphics graphics;
|
||||||
OLightEnvironment lightEnv;
|
OLightEnvironment lightEnv;
|
||||||
|
OFluidScene fluidScene;
|
||||||
PhysicsSystem physics;
|
PhysicsSystem physics;
|
||||||
Array<Gfx::OTexture2D> lightMaps;
|
Array<Gfx::OTexture2D> lightMaps;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ target_sources(Engine
|
|||||||
ComponentSystem.h
|
ComponentSystem.h
|
||||||
Executor.h
|
Executor.h
|
||||||
Executor.cpp
|
Executor.cpp
|
||||||
|
FluidUpdater.h
|
||||||
|
FluidUpdater.cpp
|
||||||
KeyboardInput.h
|
KeyboardInput.h
|
||||||
KeyboardInput.cpp
|
KeyboardInput.cpp
|
||||||
LightGather.h
|
LightGather.h
|
||||||
@@ -21,6 +23,7 @@ target_sources(Engine
|
|||||||
CameraUpdater.h
|
CameraUpdater.h
|
||||||
ComponentSystem.h
|
ComponentSystem.h
|
||||||
Executor.h
|
Executor.h
|
||||||
|
FluidUpdater.h
|
||||||
KeyboardInput.h
|
KeyboardInput.h
|
||||||
LightGather.h
|
LightGather.h
|
||||||
MeshUpdater.h
|
MeshUpdater.h
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#include "FluidUpdater.h"
|
||||||
|
#include "Graphics/DebugVertex.h"
|
||||||
|
#include "Scene/FluidScene.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
using namespace Seele::System;
|
||||||
|
|
||||||
|
FluidUpdater::FluidUpdater(PScene scene) : ComponentSystem(scene) {}
|
||||||
|
|
||||||
|
FluidUpdater::~FluidUpdater() {}
|
||||||
|
|
||||||
|
void FluidUpdater::update(entt::entity id, Component::FluidGrid &grid, Component::Transform &transform) {
|
||||||
|
auto fluidScene = scene->getFluidScene();
|
||||||
|
fluidScene->updateFluidData((uint32)id, transform, grid);
|
||||||
|
Vector corners[8];
|
||||||
|
corners[0] = transform.getPosition();
|
||||||
|
corners[1] = transform.getPosition() + Vector(transform.getScale().x, 0, 0);
|
||||||
|
corners[2] = transform.getPosition() + Vector(0, transform.getScale().y, 0);
|
||||||
|
corners[3] = transform.getPosition() + Vector(0, 0, transform.getScale().z);
|
||||||
|
corners[4] = transform.getPosition() + Vector(transform.getScale().x, transform.getScale().y, 0);
|
||||||
|
corners[5] = transform.getPosition() + Vector(transform.getScale().x, 0, transform.getScale().z);
|
||||||
|
corners[6] = transform.getPosition() + Vector(0, transform.getScale().y, transform.getScale().z);
|
||||||
|
corners[7] = transform.getPosition() + transform.getScale();
|
||||||
|
const Vector debugColor(1, 0, 0);
|
||||||
|
auto addEdge = [&](int a, int b) {
|
||||||
|
addDebugVertex(DebugVertex{.position = corners[a], .color = debugColor});
|
||||||
|
addDebugVertex(DebugVertex{.position = corners[b], .color = debugColor});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bottom face
|
||||||
|
addEdge(0, 1);
|
||||||
|
addEdge(1, 4);
|
||||||
|
addEdge(4, 2);
|
||||||
|
addEdge(2, 0);
|
||||||
|
|
||||||
|
// Top face
|
||||||
|
addEdge(3, 5);
|
||||||
|
addEdge(5, 7);
|
||||||
|
addEdge(7, 6);
|
||||||
|
addEdge(6, 3);
|
||||||
|
|
||||||
|
// Vertical edges
|
||||||
|
addEdge(0, 3);
|
||||||
|
addEdge(1, 5);
|
||||||
|
addEdge(2, 6);
|
||||||
|
addEdge(4, 7);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Component/FluidGrid.h"
|
||||||
|
#include "Component/Transform.h"
|
||||||
|
#include "ComponentSystem.h"
|
||||||
|
|
||||||
|
namespace Seele {
|
||||||
|
namespace System {
|
||||||
|
class FluidUpdater : public ComponentSystem<Component::FluidGrid, Component::Transform> {
|
||||||
|
public:
|
||||||
|
FluidUpdater(PScene scene);
|
||||||
|
virtual ~FluidUpdater();
|
||||||
|
|
||||||
|
virtual void update(entt::entity id, Component::FluidGrid& grid, Component::Transform& transform);
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
} // namespace System
|
||||||
|
} // namespace Seele
|
||||||
@@ -25,14 +25,14 @@ void KeyboardInput::update(Component::KeyboardInput& input) {
|
|||||||
scrollY = 0;
|
scrollY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardInput::keyCallback(KeyCode code, InputAction action, KeyModifier) { keys[code] = action != InputAction::RELEASE; }
|
void KeyboardInput::keyCallback(KeyCode code, InputAction action, KeyModifierFlags) { keys[code] = action != InputAction::RELEASE; }
|
||||||
|
|
||||||
void KeyboardInput::mouseCallback(double x, double y) {
|
void KeyboardInput::mouseCallback(double x, double y) {
|
||||||
mouseX = (float)x;
|
mouseX = (float)x;
|
||||||
mouseY = (float)y;
|
mouseY = (float)y;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardInput::mouseButtonCallback(MouseButton button, InputAction action, KeyModifier) {
|
void KeyboardInput::mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags) {
|
||||||
if (button == MouseButton::MOUSE_BUTTON_1) {
|
if (button == MouseButton::MOUSE_BUTTON_1) {
|
||||||
mouse1 = action != InputAction::RELEASE;
|
mouse1 = action != InputAction::RELEASE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ class KeyboardInput : public ComponentSystem<Component::KeyboardInput> {
|
|||||||
KeyboardInput(PScene scene);
|
KeyboardInput(PScene scene);
|
||||||
virtual ~KeyboardInput();
|
virtual ~KeyboardInput();
|
||||||
virtual void update(Component::KeyboardInput& input) override;
|
virtual void update(Component::KeyboardInput& input) override;
|
||||||
void keyCallback(KeyCode code, InputAction action, KeyModifier modifier);
|
void keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier);
|
||||||
void mouseCallback(double xPos, double yPos);
|
void mouseCallback(double xPos, double yPos);
|
||||||
void mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier);
|
void mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags modifier);
|
||||||
void scrollCallback(double xScroll, double yScroll);
|
void scrollCallback(double xScroll, double yScroll);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "LightGather.h"
|
#include "LightGather.h"
|
||||||
|
#include "Scene/LightEnvironment.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::System;
|
using namespace Seele::System;
|
||||||
|
|||||||
@@ -4,15 +4,20 @@
|
|||||||
#include "Graphics/RenderPass/BasePass.h"
|
#include "Graphics/RenderPass/BasePass.h"
|
||||||
#include "Graphics/RenderPass/CachedDepthPass.h"
|
#include "Graphics/RenderPass/CachedDepthPass.h"
|
||||||
#include "Graphics/RenderPass/DepthCullingPass.h"
|
#include "Graphics/RenderPass/DepthCullingPass.h"
|
||||||
|
#include "Graphics/RenderPass/FluidRenderPass.h"
|
||||||
#include "Graphics/RenderPass/LightCullingPass.h"
|
#include "Graphics/RenderPass/LightCullingPass.h"
|
||||||
#include "Graphics/RenderPass/RayTracingPass.h"
|
#include "Graphics/RenderPass/RayTracingPass.h"
|
||||||
|
#include "Graphics/RenderPass/ShadowPass.h"
|
||||||
|
#include "Graphics/RenderPass/SimulationComputePass.h"
|
||||||
|
#include "Graphics/RenderPass/SurfaceExtractPass.h"
|
||||||
#include "Graphics/RenderPass/ToneMappingPass.h"
|
#include "Graphics/RenderPass/ToneMappingPass.h"
|
||||||
#include "Graphics/RenderPass/VisibilityPass.h"
|
#include "Graphics/RenderPass/VisibilityPass.h"
|
||||||
#include "Graphics/RenderPass/ShadowPass.h"
|
|
||||||
#include "System/CameraUpdater.h"
|
#include "System/CameraUpdater.h"
|
||||||
|
#include "System/FluidUpdater.h"
|
||||||
#include "System/LightGather.h"
|
#include "System/LightGather.h"
|
||||||
#include "System/MeshUpdater.h"
|
#include "System/MeshUpdater.h"
|
||||||
#include "Window/Window.h"
|
#include "Window/Window.h"
|
||||||
|
#include "Scene/LightEnvironment.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
@@ -25,11 +30,17 @@ GameView::GameView(Gfx::PGraphics graphics, PWindow window, const ViewportCreate
|
|||||||
renderGraph.addPass(new LightCullingPass(graphics, scene));
|
renderGraph.addPass(new LightCullingPass(graphics, scene));
|
||||||
renderGraph.addPass(new ShadowPass(graphics, scene));
|
renderGraph.addPass(new ShadowPass(graphics, scene));
|
||||||
renderGraph.addPass(new BasePass(graphics, scene));
|
renderGraph.addPass(new BasePass(graphics, scene));
|
||||||
|
renderGraph.addPass(new SimulationComputePass(graphics, scene));
|
||||||
|
renderGraph.addPass(new SurfaceExtractPass(graphics, scene));
|
||||||
|
renderGraph.addPass(new FluidRenderPass(graphics, scene));
|
||||||
renderGraph.addPass(new ToneMappingPass(graphics));
|
renderGraph.addPass(new ToneMappingPass(graphics));
|
||||||
renderGraph.setViewport(viewport);
|
renderGraph.setViewport(viewport);
|
||||||
renderGraph.createRenderPass();
|
renderGraph.createRenderPass();
|
||||||
if (graphics->supportRayTracing()) {
|
if (graphics->supportRayTracing()) {
|
||||||
rayTracingGraph.addPass(new RayTracingPass(graphics, scene));
|
rayTracingGraph.addPass(new RayTracingPass(graphics, scene));
|
||||||
|
rayTracingGraph.addPass(new SimulationComputePass(graphics, scene));
|
||||||
|
rayTracingGraph.addPass(new SurfaceExtractPass(graphics, scene));
|
||||||
|
rayTracingGraph.addPass(new FluidRenderPass(graphics, scene));
|
||||||
rayTracingGraph.addPass(new ToneMappingPass(graphics));
|
rayTracingGraph.addPass(new ToneMappingPass(graphics));
|
||||||
rayTracingGraph.setViewport(viewport);
|
rayTracingGraph.setViewport(viewport);
|
||||||
rayTracingGraph.createRenderPass();
|
rayTracingGraph.createRenderPass();
|
||||||
@@ -90,16 +101,19 @@ void GameView::reloadGame() {
|
|||||||
System::OKeyboardInput keyInput = new System::KeyboardInput(scene);
|
System::OKeyboardInput keyInput = new System::KeyboardInput(scene);
|
||||||
keyboardSystem = keyInput;
|
keyboardSystem = keyInput;
|
||||||
systemGraph->addSystem(std::move(keyInput));
|
systemGraph->addSystem(std::move(keyInput));
|
||||||
|
systemGraph->addSystem(new System::FluidUpdater(scene));
|
||||||
systemGraph->addSystem(new System::LightGather(scene));
|
systemGraph->addSystem(new System::LightGather(scene));
|
||||||
systemGraph->addSystem(new System::MeshUpdater(scene));
|
systemGraph->addSystem(new System::MeshUpdater(scene));
|
||||||
systemGraph->addSystem(new System::CameraUpdater(scene));
|
systemGraph->addSystem(new System::CameraUpdater(scene));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) { keyboardSystem->keyCallback(code, action, modifier); }
|
void GameView::keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) {
|
||||||
|
keyboardSystem->keyCallback(code, action, modifier);
|
||||||
|
}
|
||||||
|
|
||||||
void GameView::mouseMoveCallback(double xPos, double yPos) { keyboardSystem->mouseCallback(xPos, yPos); }
|
void GameView::mouseMoveCallback(double xPos, double yPos) { keyboardSystem->mouseCallback(xPos, yPos); }
|
||||||
|
|
||||||
void GameView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier) {
|
void GameView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags modifier) {
|
||||||
keyboardSystem->mouseButtonCallback(button, action, modifier);
|
keyboardSystem->mouseButtonCallback(button, action, modifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ class GameView : public View {
|
|||||||
System::PKeyboardInput keyboardSystem;
|
System::PKeyboardInput keyboardSystem;
|
||||||
float updateTime = 0;
|
float updateTime = 0;
|
||||||
|
|
||||||
virtual void keyCallback(Seele::KeyCode code, Seele::InputAction action, Seele::KeyModifier modifier) override;
|
virtual void keyCallback(KeyCode code, InputAction action, KeyModifierFlags modifier) override;
|
||||||
virtual void mouseMoveCallback(double xPos, double yPos) override;
|
virtual void mouseMoveCallback(double xPos, double yPos) override;
|
||||||
virtual void mouseButtonCallback(Seele::MouseButton button, Seele::InputAction action, Seele::KeyModifier modifier) override;
|
virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifierFlags modifier) override;
|
||||||
virtual void scrollCallback(double xOffset, double yOffset) override;
|
virtual void scrollCallback(double xOffset, double yOffset) override;
|
||||||
virtual void fileCallback(int count, const char** paths) override;
|
virtual void fileCallback(int count, const char** paths) override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ class View {
|
|||||||
PWindow owner;
|
PWindow owner;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
virtual void keyCallback(KeyCode code, InputAction action, KeyModifier modifier) = 0;
|
virtual void keyCallback(KeyCode code, InputAction action, uint32_t modifier) = 0;
|
||||||
virtual void mouseMoveCallback(double xPos, double yPos) = 0;
|
virtual void mouseMoveCallback(double xPos, double yPos) = 0;
|
||||||
virtual void mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier) = 0;
|
virtual void mouseButtonCallback(MouseButton button, InputAction action, uint32_t modifier) = 0;
|
||||||
virtual void scrollCallback(double xOffset, double yOffset) = 0;
|
virtual void scrollCallback(double xOffset, double yOffset) = 0;
|
||||||
virtual void fileCallback(int count, const char** paths) = 0;
|
virtual void fileCallback(int count, const char** paths) = 0;
|
||||||
friend class Window;
|
friend class Window;
|
||||||
|
|||||||
+9
-3
@@ -1,18 +1,24 @@
|
|||||||
{
|
{
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"vulkan",
|
"vulkan",
|
||||||
|
{
|
||||||
|
"name": "vulkan-memory-allocator"
|
||||||
|
},
|
||||||
"assimp",
|
"assimp",
|
||||||
"entt",
|
|
||||||
"stb",
|
"stb",
|
||||||
"entt",
|
"entt",
|
||||||
"freetype",
|
"freetype",
|
||||||
"glfw3",
|
{
|
||||||
|
"name": "glfw3",
|
||||||
|
"features": [
|
||||||
|
"wayland"
|
||||||
|
]
|
||||||
|
},
|
||||||
"glm",
|
"glm",
|
||||||
"ktx",
|
"ktx",
|
||||||
"nlohmann-json",
|
"nlohmann-json",
|
||||||
"fmt",
|
"fmt",
|
||||||
"gtest",
|
"gtest",
|
||||||
"vulkan-memory-allocator",
|
|
||||||
"lunasvg",
|
"lunasvg",
|
||||||
"harfbuzz",
|
"harfbuzz",
|
||||||
"shader-slang",
|
"shader-slang",
|
||||||
|
|||||||
Reference in New Issue
Block a user