Redo of render paths
This commit is contained in:
@@ -13,3 +13,9 @@
|
|||||||
[submodule "external/json"]
|
[submodule "external/json"]
|
||||||
path = external/json
|
path = external/json
|
||||||
url = https://github.com/nlohmann/json.git
|
url = https://github.com/nlohmann/json.git
|
||||||
|
[submodule "external/assimp"]
|
||||||
|
path = external/assimp
|
||||||
|
url = https://github.com/assimp/assimp.git
|
||||||
|
[submodule "external/stb"]
|
||||||
|
path = external/stb
|
||||||
|
url = https://github.com/nothings/stb.git
|
||||||
|
|||||||
Vendored
+2
-2
@@ -27,10 +27,10 @@
|
|||||||
"name": "Test",
|
"name": "Test",
|
||||||
"type": "cppvsdbg",
|
"type": "cppvsdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceRoot}/bin/Debug/test/Seele_unit_tests.exe",
|
"program": "${workspaceRoot}/bin/Debug/Seele_unit_tests.exe",
|
||||||
"args": [],
|
"args": [],
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"cwd": "${workspaceRoot}/bin/Debug/test",
|
"cwd": "${workspaceRoot}/bin/Debug",
|
||||||
"environment": [],
|
"environment": [],
|
||||||
"externalConsole": false
|
"externalConsole": false
|
||||||
},
|
},
|
||||||
|
|||||||
Vendored
+74
-2
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"C_Cpp.default.configurationProvider": "go2sh.cmake-integration",
|
|
||||||
"telemetry.enableTelemetry": false,
|
"telemetry.enableTelemetry": false,
|
||||||
"cmake.buildDirectory": "${workspaceFolder}/bin/${buildType}",
|
"cmake.buildDirectory": "${workspaceFolder}/bin/${buildType}",
|
||||||
"git.autofetch": false,
|
"git.autofetch": false,
|
||||||
@@ -17,9 +16,82 @@
|
|||||||
"memory": "cpp",
|
"memory": "cpp",
|
||||||
"*.ipp": "cpp",
|
"*.ipp": "cpp",
|
||||||
"iostream": "cpp",
|
"iostream": "cpp",
|
||||||
"initializer_list": "cpp"
|
"initializer_list": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"atomic": "cpp",
|
||||||
|
"cctype": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"clocale": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"concepts": "cpp",
|
||||||
|
"condition_variable": "cpp",
|
||||||
|
"cstddef": "cpp",
|
||||||
|
"cstdint": "cpp",
|
||||||
|
"cstdio": "cpp",
|
||||||
|
"cstdlib": "cpp",
|
||||||
|
"cstring": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"cwchar": "cpp",
|
||||||
|
"exception": "cpp",
|
||||||
|
"forward_list": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"ios": "cpp",
|
||||||
|
"iosfwd": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"iterator": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"map": "cpp",
|
||||||
|
"mutex": "cpp",
|
||||||
|
"new": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"set": "cpp",
|
||||||
|
"sstream": "cpp",
|
||||||
|
"stdexcept": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"valarray": "cpp",
|
||||||
|
"xfacet": "cpp",
|
||||||
|
"xlocale": "cpp",
|
||||||
|
"xlocinfo": "cpp",
|
||||||
|
"xlocmon": "cpp",
|
||||||
|
"xlocnum": "cpp",
|
||||||
|
"xloctime": "cpp",
|
||||||
|
"xstddef": "cpp",
|
||||||
|
"xtr1common": "cpp",
|
||||||
|
"xutility": "cpp",
|
||||||
|
"filesystem": "cpp",
|
||||||
|
"bitset": "cpp",
|
||||||
|
"complex": "cpp",
|
||||||
|
"csignal": "cpp",
|
||||||
|
"deque": "cpp",
|
||||||
|
"locale": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"typeindex": "cpp",
|
||||||
|
"variant": "cpp",
|
||||||
|
"xlocbuf": "cpp",
|
||||||
|
"xlocmes": "cpp",
|
||||||
|
"codecvt": "cpp",
|
||||||
|
"regex": "cpp",
|
||||||
|
"strstream": "cpp",
|
||||||
|
"resumable": "cpp",
|
||||||
|
"future": "cpp"
|
||||||
},
|
},
|
||||||
"C_Cpp.default.browse.limitSymbolsToIncludedHeaders": false,
|
"C_Cpp.default.browse.limitSymbolsToIncludedHeaders": false,
|
||||||
"C_Cpp.default.intelliSenseMode": "msvc-x64",
|
"C_Cpp.default.intelliSenseMode": "msvc-x64",
|
||||||
"C_Cpp.errorSquiggles": "Disabled",
|
"C_Cpp.errorSquiggles": "Disabled",
|
||||||
|
"cmake.generator": "Visual Studio 16 2019",
|
||||||
|
"cmake.skipConfigureIfCachePresent": false,
|
||||||
|
"cmake.configureArgs": ["-Wno-dev"],
|
||||||
|
"C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools"
|
||||||
}
|
}
|
||||||
+50
-21
@@ -1,30 +1,25 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED 20)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
# Handle superbuild first
|
# Handle superbuild first
|
||||||
option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON)
|
option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON)
|
||||||
|
|
||||||
set(ENGINE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/src/Engine)
|
set(ENGINE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/src/Engine)
|
||||||
set(EXTERNAL_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/external)
|
set(EXTERNAL_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/external)
|
||||||
set(SLANG_ROOT ${EXTERNAL_ROOT}/slang)
|
set(ASSIMP_ROOT ${EXTERNAL_ROOT}/assimp)
|
||||||
set(BOOST_ROOT ${EXTERNAL_ROOT}/boost)
|
set(BOOST_ROOT ${EXTERNAL_ROOT}/boost)
|
||||||
|
set(SLANG_ROOT ${EXTERNAL_ROOT}/slang)
|
||||||
set(GLM_ROOT ${EXTERNAL_ROOT}/glm)
|
set(GLM_ROOT ${EXTERNAL_ROOT}/glm)
|
||||||
set(GLFW_ROOT ${EXTERNAL_ROOT}/glfw)
|
set(GLFW_ROOT ${EXTERNAL_ROOT}/glfw)
|
||||||
set(JSON_ROOT ${EXTERNAL_ROOT}/json)
|
set(JSON_ROOT ${EXTERNAL_ROOT}/json)
|
||||||
set(CMAKE_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin/${CMAKE_BUILD_TYPE})
|
set(STB_ROOT ${EXTERNAL_ROOT}/stb)
|
||||||
set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
|
||||||
set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR})
|
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/)
|
||||||
|
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
set(Boost_LIB_PREFIX lib)
|
set(Boost_LIB_PREFIX lib)
|
||||||
|
|
||||||
set(ENKITS_BUILD_EXAMPLES OFF CACHE BOOL "Build basic example applications" )
|
|
||||||
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "GLFW lib only" )
|
|
||||||
set(GLFW_BUILD_TESTS OFF CACHE BOOL "GLFW lib only" )
|
|
||||||
set(GLFW_BUILD_DOCS OFF CACHE BOOL "GLFW lib only" )
|
|
||||||
set(GLFW_BUILD_INSTALL OFF CACHE BOOL "GLFW lib only" )
|
|
||||||
|
|
||||||
if (USE_SUPERBUILD)
|
if (USE_SUPERBUILD)
|
||||||
project (SUPERBUILD NONE)
|
project (SUPERBUILD NONE)
|
||||||
# execute the superbuild (this script will be invoked again without the
|
# execute the superbuild (this script will be invoked again without the
|
||||||
@@ -35,17 +30,27 @@ else()
|
|||||||
project (Seele)
|
project (Seele)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin/Debug)
|
||||||
|
#Workaround for vs, because it places artifacts into an additional subfolder
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_CURRENT_SOURCE_DIR}/bin/Debug)
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_CURRENT_SOURCE_DIR}/bin/Release)
|
||||||
|
|
||||||
find_package(Vulkan REQUIRED)
|
find_package(Vulkan REQUIRED)
|
||||||
find_package(Boost REQUIRED COMPONENTS serialization)
|
find_package(Boost REQUIRED COMPONENTS serialization)
|
||||||
find_package(Threads)
|
find_package(Threads REQUIRED)
|
||||||
include(${JSON_IMPORT})
|
find_package(assimp REQUIRED ${ASSIMP_ROOT})
|
||||||
include(${GLFW_IMPORT})
|
find_package(JSON REQUIRED)
|
||||||
|
find_package(GLFW REQUIRED)
|
||||||
|
|
||||||
include_directories(${GLFW_ROOT}/include)
|
|
||||||
include_directories(${GLM_INCLUDE_DIRS})
|
include_directories(${GLM_INCLUDE_DIRS})
|
||||||
|
include_directories(${STB_INCLUDE_DIRS})
|
||||||
include_directories(${Vulkan_INCLUDE_DIR})
|
include_directories(${Vulkan_INCLUDE_DIR})
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
include_directories(${GLFW_INCLUDE_DIRS})
|
||||||
include_directories(${SLANG_INCLUDE_DIRS})
|
include_directories(${SLANG_INCLUDE_DIRS})
|
||||||
|
include_directories(${ASSIMP_INCLUDE_DIRS})
|
||||||
|
include_directories(${JSON_INCLUDE_DIRS})
|
||||||
|
include_directories(${ENGINE_ROOT})
|
||||||
include_directories(src/Engine)
|
include_directories(src/Engine)
|
||||||
add_definitions(${GLM_DEFINITIONS})
|
add_definitions(${GLM_DEFINITIONS})
|
||||||
add_definitions(${Vulkan_DEFINITIONS})
|
add_definitions(${Vulkan_DEFINITIONS})
|
||||||
@@ -55,20 +60,44 @@ if(WIN32)
|
|||||||
add_compile_definitions(USE_EXTENSIONS)
|
add_compile_definitions(USE_EXTENSIONS)
|
||||||
endif()
|
endif()
|
||||||
add_executable(SeeleEngine "")
|
add_executable(SeeleEngine "")
|
||||||
target_link_libraries(SeeleEngine glfw)
|
|
||||||
target_link_libraries(SeeleEngine nlohmann_json::nlohmann_json)
|
|
||||||
target_link_libraries(SeeleEngine ${Boost_LIBRARIES})
|
|
||||||
target_link_libraries(SeeleEngine ${Vulkan_LIBRARY})
|
target_link_libraries(SeeleEngine ${Vulkan_LIBRARY})
|
||||||
|
target_link_libraries(SeeleEngine ${Boost_LIBRARIES})
|
||||||
|
target_link_libraries(SeeleEngine ${GLFW_LIBRARIES})
|
||||||
target_link_libraries(SeeleEngine ${SLANG_LIBRARY})
|
target_link_libraries(SeeleEngine ${SLANG_LIBRARY})
|
||||||
|
target_link_libraries(SeeleEngine ${ASSIMP_LIBRARIES})
|
||||||
|
target_link_libraries(SeeleEngine ${JSON_LIBRARY})
|
||||||
|
|
||||||
|
target_precompile_headers(SeeleEngine
|
||||||
|
PRIVATE
|
||||||
|
<assert.h>
|
||||||
|
<memory>
|
||||||
|
<atomic>
|
||||||
|
<cstring>
|
||||||
|
<iostream>
|
||||||
|
<string>
|
||||||
|
<thread>
|
||||||
|
<functional>
|
||||||
|
<filesystem>
|
||||||
|
<fstream>
|
||||||
|
<mutex>
|
||||||
|
<condition_variable>)
|
||||||
|
|
||||||
add_subdirectory(src/)
|
add_subdirectory(src/)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
target_compile_options(SeeleEngine PRIVATE /DEBUG:FASTLINK /Zi /W4)
|
set(_CRT_SECURE_NO_WARNINGS)
|
||||||
|
target_compile_options(SeeleEngine PRIVATE /DEBUG:FASTLINK /Zi)
|
||||||
else()
|
else()
|
||||||
target_compile_options(SeeleEngine PRIVATE -Wall -Wextra -pedantic)
|
target_compile_options(SeeleEngine PRIVATE -Wall -Wextra -pedantic)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_executable(Seele_unit_tests "")
|
||||||
add_subdirectory(test/)
|
add_subdirectory(test/)
|
||||||
|
|
||||||
add_custom_command(TARGET SeeleEngine POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DEPENDENT_BINARIES} $<TARGET_FILE_DIR:SeeleEngine>)
|
add_custom_target(copy-runtime-files ALL
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/res $<TARGET_FILE_DIR:SeeleEngine>
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_ROOT}/${SLANG_BINARY} $<TARGET_FILE_DIR:SeeleEngine>
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SLANG_ROOT}/${SLANG_GLSLANG} $<TARGET_FILE_DIR:SeeleEngine>
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${GLFW_BINARY} $<TARGET_FILE_DIR:SeeleEngine>
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${ASSIMP_BINARY} $<TARGET_FILE_DIR:SeeleEngine>
|
||||||
|
DEPENDS SeeleEngine)
|
||||||
+2
-7
@@ -2,13 +2,8 @@
|
|||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Debug",
|
"name": "Debug",
|
||||||
"generator": "Ninja",
|
"cmakeCommandArgs": "-DUSE_SUPERBUILD=OFF",
|
||||||
"configurationType": "Debug",
|
"buildCommandArgs": "",
|
||||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
|
||||||
"buildRoot": "${projectDir}\\bin\\${name}",
|
|
||||||
"installRoot": "${projectDir}\\install\\${name}",
|
|
||||||
"cmakeCommandArgs": "-DUSE_SUPERBUILD=TRUE",
|
|
||||||
"buildCommandArgs": "-v",
|
|
||||||
"ctestCommandArgs": "",
|
"ctestCommandArgs": "",
|
||||||
"variables": []
|
"variables": []
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ but keeping it simple to use, with lots of additional and optional parameters.
|
|||||||
The project is built using standard CMake 3.15, so that and a modern C++17 compiler should be the only prerequisites.
|
The project is built using standard CMake 3.15, so that and a modern C++17 compiler should be the only prerequisites.
|
||||||
|
|
||||||
Clone the repository and initialize the dependencies with `git submodule update --init --recursive`
|
Clone the repository and initialize the dependencies with `git submodule update --init --recursive`
|
||||||
|
~~*SLang library hasn't been included in the automatic build yet, so you have to manually compile that project, found in external/slang*~~ This has been fixed, but not extensively tested
|
||||||
*SLang library hasn't been included in the automatic build yet, so you have to manually compile that project, found in external/slang*
|
|
||||||
|
|
||||||
|
|
||||||
## Linux notes:
|
## Linux notes:
|
||||||
|
|||||||
@@ -34,5 +34,25 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"superbuild": {
|
||||||
|
"default": "off",
|
||||||
|
"description": "Use Superbuild",
|
||||||
|
"choices": {
|
||||||
|
"off": {
|
||||||
|
"short": "off",
|
||||||
|
"long": "Don't rebuild superbuild",
|
||||||
|
"settings": {
|
||||||
|
"USE_SUPERBUILD": "OFF"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"on": {
|
||||||
|
"short": "on",
|
||||||
|
"long": "Rebuild dependencies",
|
||||||
|
"settings": {
|
||||||
|
"USE_SUPERBUILD": "ON"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
#
|
||||||
|
# Find Assimp
|
||||||
|
#
|
||||||
|
# Try to find Assimp : Open Asset Import Library.
|
||||||
|
# This module defines the following variables:
|
||||||
|
# - ASSIMP_INCLUDE_DIRS
|
||||||
|
# - ASSIMP_LIBRARIES
|
||||||
|
# - ASSIMP_FOUND
|
||||||
|
#
|
||||||
|
# The following variables can be set as arguments for the module.
|
||||||
|
# - ASSIMP_ROOT : Root library directory of Assimp
|
||||||
|
#
|
||||||
|
|
||||||
|
# Additional modules
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
# Find include files
|
||||||
|
find_path(
|
||||||
|
ASSIMP_INCLUDE_DIR
|
||||||
|
NAMES assimp/scene.h
|
||||||
|
PATHS
|
||||||
|
$ENV{PROGRAMFILES}/include
|
||||||
|
${ASSIMP_ROOT}/include
|
||||||
|
DOC "The directory where assimp/scene.h resides")
|
||||||
|
|
||||||
|
# Find library files
|
||||||
|
find_library(
|
||||||
|
ASSIMP_LIBRARY
|
||||||
|
NAMES assimp${LIBRARY_SUFFIX}.lib
|
||||||
|
PATHS
|
||||||
|
$ENV{PROGRAMFILES}/lib
|
||||||
|
${ASSIMP_ROOT}/lib/
|
||||||
|
PATH_SUFFIXES Debug Release)
|
||||||
|
|
||||||
|
find_file(
|
||||||
|
ASSIMP_BINARY
|
||||||
|
NAMES assimp${LIBRARY_SUFFIX}.dll
|
||||||
|
PATHS
|
||||||
|
$ENV{PROGRAMFILES}/bin
|
||||||
|
${ASSIMP_ROOT}/bin/
|
||||||
|
PATH_SUFFIXES Debug Release)
|
||||||
|
else()
|
||||||
|
# Find include files
|
||||||
|
find_path(
|
||||||
|
ASSIMP_INCLUDE_DIR
|
||||||
|
NAMES assimp/scene.h
|
||||||
|
PATHS
|
||||||
|
/usr/include
|
||||||
|
/usr/local/include
|
||||||
|
/sw/include
|
||||||
|
/opt/local/include
|
||||||
|
DOC "The directory where assimp/scene.h resides")
|
||||||
|
|
||||||
|
# Find library files
|
||||||
|
find_library(
|
||||||
|
ASSIMP_LIBRARY
|
||||||
|
NAMES assimp
|
||||||
|
PATHS
|
||||||
|
/usr/lib64
|
||||||
|
/usr/lib
|
||||||
|
/usr/local/lib64
|
||||||
|
/usr/local/lib
|
||||||
|
/sw/lib
|
||||||
|
/opt/local/lib
|
||||||
|
${ASSIMP_ROOT}/lib
|
||||||
|
DOC "The Assimp library")
|
||||||
|
|
||||||
|
find_file(
|
||||||
|
ASSIMP_BINARY
|
||||||
|
NAMES assimp.so
|
||||||
|
PATHS
|
||||||
|
/usr/bin64
|
||||||
|
/usr/bin
|
||||||
|
/usr/local/bin64
|
||||||
|
/usr/local/bin
|
||||||
|
/sw/bin
|
||||||
|
/opt/local/bin
|
||||||
|
${ASSIMP_ROOT}/lib
|
||||||
|
DOC "The Assimp binary")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Handle REQUIRD argument, define *_FOUND variable
|
||||||
|
find_package_handle_standard_args(assimp DEFAULT_MSG ASSIMP_INCLUDE_DIR ASSIMP_LIBRARY ASSIMP_BINARY)
|
||||||
|
|
||||||
|
# Define GLFW_LIBRARIES and GLFW_INCLUDE_DIRS
|
||||||
|
if (ASSIMP_FOUND)
|
||||||
|
set(ASSIMP_LIBRARIES ${ASSIMP_LIBRARY})
|
||||||
|
set(ASSIMP_INCLUDE_DIRS ${ASSIMP_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS BINARY: ${ASSIMP_BINARY})
|
||||||
|
|
||||||
|
# Hide some variables
|
||||||
|
mark_as_advanced(ASSIMP_INCLUDE_DIR ASSIMP_LIBRARY)
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
#
|
||||||
|
# Find GLFW
|
||||||
|
#
|
||||||
|
# Try to find GLFW library.
|
||||||
|
# This module defines the following variables:
|
||||||
|
# - GLFW_INCLUDE_DIRS
|
||||||
|
# - GLFW_LIBRARIES
|
||||||
|
# - GLFW_FOUND
|
||||||
|
#
|
||||||
|
# The following variables can be set as arguments for the module.
|
||||||
|
# - GLFW_ROOT : Root library directory of GLFW
|
||||||
|
# - GLFW_USE_STATIC_LIBS : Specifies to use static version of GLFW library (Windows only)
|
||||||
|
#
|
||||||
|
# References:
|
||||||
|
# - https://github.com/progschj/OpenGL-Examples/blob/master/cmake_modules/FindGLFW.cmake
|
||||||
|
# - https://bitbucket.org/Ident8/cegui-mk2-opengl3-renderer/src/befd47200265/cmake/FindGLFW.cmake
|
||||||
|
#
|
||||||
|
|
||||||
|
# Additional modules
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
# Find include files
|
||||||
|
find_path(
|
||||||
|
GLFW_INCLUDE_DIR
|
||||||
|
NAMES GLFW/glfw3.h
|
||||||
|
PATHS
|
||||||
|
$ENV{PROGRAMFILES}/include
|
||||||
|
${GLFW_ROOT}/include
|
||||||
|
DOC "The directory where GLFW/glfw.h resides")
|
||||||
|
|
||||||
|
# Use glfw3.lib for static library
|
||||||
|
if (GLFW_USE_STATIC_LIBS)
|
||||||
|
set(GLFW_LIBRARY_NAME glfw3)
|
||||||
|
else()
|
||||||
|
set(GLFW_LIBRARY_NAME glfw3dll)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Find library files
|
||||||
|
find_library(
|
||||||
|
GLFW_LIBRARY
|
||||||
|
NAMES ${GLFW_LIBRARY_NAME}.lib
|
||||||
|
PATHS
|
||||||
|
$ENV{PROGRAMFILES}/lib
|
||||||
|
${GLFW_ROOT}/lib
|
||||||
|
${GLFW_ROOT}/src
|
||||||
|
PATH_SUFFIXES Debug Release)
|
||||||
|
|
||||||
|
message(STATUS cant find ${GLFW_LIBRARY_NAME} in ${GLFW_ROOT}/src)
|
||||||
|
|
||||||
|
unset(GLFW_LIBRARY_NAME)
|
||||||
|
|
||||||
|
find_file(
|
||||||
|
GLFW_BINARY
|
||||||
|
NAMES glfw3.dll
|
||||||
|
PATHS
|
||||||
|
$ENV{PROGRAMFILES}/bin
|
||||||
|
${GLFW_ROOT}/src
|
||||||
|
${GLFW_ROOT}/bin
|
||||||
|
PATH_SUFFIXES Debug Release)
|
||||||
|
else()
|
||||||
|
# Find include files
|
||||||
|
find_path(
|
||||||
|
GLFW_INCLUDE_DIR
|
||||||
|
NAMES GLFW/glfw.h
|
||||||
|
PATHS
|
||||||
|
/usr/include
|
||||||
|
/usr/local/include
|
||||||
|
/sw/include
|
||||||
|
/opt/local/include
|
||||||
|
DOC "The directory where GL/glfw.h resides")
|
||||||
|
|
||||||
|
# Find library files
|
||||||
|
# Try to use static libraries
|
||||||
|
find_library(
|
||||||
|
GLFW_LIBRARY
|
||||||
|
NAMES glfw3
|
||||||
|
PATHS
|
||||||
|
/usr/lib64
|
||||||
|
/usr/lib
|
||||||
|
/usr/local/lib64
|
||||||
|
/usr/local/lib
|
||||||
|
/sw/lib
|
||||||
|
/opt/local/lib
|
||||||
|
${GLFW_ROOT}/lib
|
||||||
|
DOC "The GLFW library")
|
||||||
|
|
||||||
|
find_file(
|
||||||
|
GLFW_BINARY
|
||||||
|
NAMES glfw3.so
|
||||||
|
PATHS
|
||||||
|
/usr/lib64
|
||||||
|
/usr/lib
|
||||||
|
/usr/local/lib64
|
||||||
|
/usr/local/lib
|
||||||
|
/sw/lib
|
||||||
|
/opt/local/lib
|
||||||
|
${GLFW_ROOT}/lib
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Handle REQUIRD argument, define *_FOUND variable
|
||||||
|
find_package_handle_standard_args(GLFW DEFAULT_MSG GLFW_INCLUDE_DIR GLFW_LIBRARY GLFW_BINARY)
|
||||||
|
|
||||||
|
# Define GLFW_LIBRARIES and GLFW_INCLUDE_DIRS
|
||||||
|
if (GLFW_FOUND)
|
||||||
|
set(GLFW_LIBRARIES ${OPENGL_LIBRARIES} ${GLFW_LIBRARY})
|
||||||
|
set(GLFW_INCLUDE_DIRS ${GLFW_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Hide some variables
|
||||||
|
mark_as_advanced(GLFW_INCLUDE_DIR GLFW_LIBRARY)
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#
|
||||||
|
# Find nlohmann_json
|
||||||
|
#
|
||||||
|
# Try to find nlohmann_json library
|
||||||
|
# This module defines the following variables:
|
||||||
|
# - JSON_INCLUDE_DIRS
|
||||||
|
# - JSON_FOUND
|
||||||
|
#
|
||||||
|
# The following variables can be set as arguments for the module.
|
||||||
|
# - JSON_ROOT : Root library directory of json
|
||||||
|
#
|
||||||
|
|
||||||
|
# Additional modules
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
if(JSON_MultipleHeaders)
|
||||||
|
find_path(
|
||||||
|
JSON_INCLUDE_DIR
|
||||||
|
NAMES nlohmann/json.hpp
|
||||||
|
PATHS
|
||||||
|
$ENV{PROGRAMFILES}/include
|
||||||
|
${JSON_ROOT}/single_include
|
||||||
|
DOC "The directory where nlohmann/json.hpp resides")
|
||||||
|
else()
|
||||||
|
find_path(
|
||||||
|
JSON_INCLUDE_DIR
|
||||||
|
NAMES nlohmann/json.hpp
|
||||||
|
PATHS
|
||||||
|
$ENV{PROGRAMFILES}/include
|
||||||
|
${JSON_ROOT}/include
|
||||||
|
DOC "The directory where nlohmann/json.hpp resides")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package_handle_standard_args(JSON DEFAULT_MSG JSON_INCLUDE_DIR)
|
||||||
|
|
||||||
|
if(JSON_FOUND)
|
||||||
|
set(JSON_INCLUDE_DIRS ${JSON_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Hide some variables
|
||||||
|
mark_as_advanced(JSON_INCLUDE_DIR)
|
||||||
+32
-34
@@ -1,12 +1,19 @@
|
|||||||
include (ExternalProject)
|
include (ExternalProject)
|
||||||
|
|
||||||
set_property(DIRECTORY PROPERTY EP_BASE external)
|
|
||||||
|
|
||||||
set(DEPENDENCIES)
|
set(DEPENDENCIES)
|
||||||
set(EXTRA_CMAKE_ARGS)
|
set(EXTRA_CMAKE_ARGS)
|
||||||
set(DEPENDENT_BINARIES "")
|
|
||||||
execute_process(COMMAND git submodule update --init --recursive -- ${CMAKE_SOURCE_DIR})
|
execute_process(COMMAND git submodule update --init --recursive -- ${CMAKE_SOURCE_DIR})
|
||||||
|
|
||||||
|
#------------ASSIMP---------------
|
||||||
|
list(APPEND DEPENDENCIES assimp)
|
||||||
|
set(ASSIMP_BUILD_TESTS OFF CACHE INTERNAL "")
|
||||||
|
set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE INTERNAL "")
|
||||||
|
set(ASSIMP_INSTALL OFF CACHE INTERNAL "")
|
||||||
|
set(ASSIMP_INJECT_DEBUG_POSTFIX OFF CACHE INTERNAL "")
|
||||||
|
|
||||||
|
add_subdirectory(${ASSIMP_ROOT} ${ASSIMP_ROOT})
|
||||||
|
target_compile_definitions(assimp PRIVATE _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING)
|
||||||
|
|
||||||
#-------------BOOST----------------
|
#-------------BOOST----------------
|
||||||
list(APPEND DEPENDENCIES boost)
|
list(APPEND DEPENDENCIES boost)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
@@ -38,48 +45,41 @@ list(APPEND EXTRA_CMAKE_ARGS
|
|||||||
)
|
)
|
||||||
|
|
||||||
#--------------------JSON------------------
|
#--------------------JSON------------------
|
||||||
#list(APPEND DEPENDENCIES nlohmann_json)
|
list(APPEND DEPENDENCIES nlohmann_json)
|
||||||
set(JSON_MultipleHeaders ON CACHE INTERNAL "")
|
set(JSON_MultipleHeaders ON CACHE INTERNAL "")
|
||||||
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
||||||
set(JSON_Install OFF CACHE INTERNAL "")
|
set(JSON_Install OFF CACHE INTERNAL "")
|
||||||
|
|
||||||
add_subdirectory(${JSON_ROOT})
|
add_subdirectory(${JSON_ROOT})
|
||||||
export(TARGETS nlohmann_json
|
|
||||||
NAMESPACE nlohmann_json::
|
|
||||||
FILE ${nlohmann_json_BINARY_DIR}/json_target.cmake)
|
|
||||||
|
|
||||||
list(APPEND EXTRA_CMAKE_ARGS
|
|
||||||
-DJSON_IMPORT=${nlohmann_json_BINARY_DIR}/json_target.cmake
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
#--------------GLFW------------------------------
|
#--------------GLFW------------------------------
|
||||||
list(APPEND DEPENDENCIES glfw)
|
list(APPEND DEPENDENCIES glfw)
|
||||||
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
set(ENKITS_BUILD_EXAMPLES OFF CACHE BOOL "Build basic example applications" )
|
||||||
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "GLFW lib only" )
|
||||||
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
set(GLFW_BUILD_TESTS OFF CACHE BOOL "GLFW lib only" )
|
||||||
|
set(GLFW_BUILD_DOCS OFF CACHE BOOL "GLFW lib only" )
|
||||||
|
set(GLFW_BUILD_INSTALL OFF CACHE BOOL "GLFW lib only" )
|
||||||
|
|
||||||
add_subdirectory(${GLFW_ROOT})
|
add_subdirectory(${GLFW_ROOT} ${GLFW_ROOT})
|
||||||
export(TARGETS glfw
|
|
||||||
FILE ${GLFW_BINARY_DIR}/glfw.cmake)
|
|
||||||
|
|
||||||
|
#---------------STB_IMAGE------------------------
|
||||||
list(APPEND EXTRA_CMAKE_ARGS
|
list(APPEND EXTRA_CMAKE_ARGS
|
||||||
-DGLFW_IMPORT=${GLFW_BINARY_DIR}/glfw.cmake
|
-DSTB_INCLUDE_DIRS=${STB_ROOT})
|
||||||
)
|
|
||||||
|
|
||||||
#--------------SLang------------------------------
|
#--------------SLang------------------------------
|
||||||
list(APPEND DEPENDENCIES slang)
|
list(APPEND DEPENDENCIES slang)
|
||||||
string(TOLOWER ${CMAKE_BUILD_TYPE}_${CMAKE_PLATFORM} SLANG_CONFIG)
|
string(TOLOWER release_${CMAKE_PLATFORM} SLANG_CONFIG)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
ExternalProject_Add(slang
|
ExternalProject_Add(slang
|
||||||
SOURCE_DIR ${SLANG_ROOT}
|
SOURCE_DIR ${SLANG_ROOT}
|
||||||
BINARY_DIR ${CMAKE_BINARY_DIR}/lib
|
BINARY_DIR ${CMAKE_BINARY_DIR}/lib
|
||||||
CONFIGURE_COMMAND devenv /upgrade ${SLANG_ROOT}/source/slang/slang.vcxproj
|
CONFIGURE_COMMAND devenv /upgrade ${SLANG_ROOT}/source/slang/slang.vcxproj
|
||||||
BUILD_COMMAND msbuild -p:Configuration=${CMAKE_BUILD_TYPE} -p:Platform=${CMAKE_PLATFORM} -p:WindowsTargetPlatformVersion=10.0 ${SLANG_ROOT}/source/slang/slang.vcxproj
|
BUILD_COMMAND msbuild -p:Configuration=Release -p:Platform=${CMAKE_PLATFORM} -p:WindowsTargetPlatformVersion=10.0 ${SLANG_ROOT}/source/slang/slang.vcxproj
|
||||||
INSTALL_COMMAND "")
|
INSTALL_COMMAND "")
|
||||||
|
|
||||||
string(TOLOWER bin/windows-${CMAKE_PLATFORM}/${CMAKE_BUILD_TYPE}/slang.dll SLANG_BINARY)
|
string(TOLOWER bin/windows-${CMAKE_PLATFORM}/Release/slang.dll SLANG_BINARY)
|
||||||
string(TOLOWER bin/windows-${CMAKE_PLATFORM}/${CMAKE_BUILD_TYPE}/slang.lib SLANG_LIB_PATH)
|
string(TOLOWER bin/windows-${CMAKE_PLATFORM}/Release/slang-glslang.dll SLANG_GLSLANG)
|
||||||
|
string(TOLOWER bin/windows-${CMAKE_PLATFORM}/Release/slang.lib SLANG_LIB_PATH)
|
||||||
set(SLANG_LIB_PATH ${SLANG_ROOT}/${SLANG_LIB_PATH})
|
set(SLANG_LIB_PATH ${SLANG_ROOT}/${SLANG_LIB_PATH})
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
ExternalProject_Add(slang
|
ExternalProject_Add(slang
|
||||||
@@ -89,24 +89,22 @@ ExternalProject_Add(slang
|
|||||||
BUILD_COMMAND make -C ${CMAKE_SOURCE_DIR}/external/slang/build.linux config=${SLANG_CONFIG}
|
BUILD_COMMAND make -C ${CMAKE_SOURCE_DIR}/external/slang/build.linux config=${SLANG_CONFIG}
|
||||||
INSTALL_COMMAND "")
|
INSTALL_COMMAND "")
|
||||||
|
|
||||||
string(TOLOWER bin/linux-${CMAKE_PLATFORM}/${CMAKE_BUILD_TYPE}/libslang.so SLANG_BINARY)
|
string(TOLOWER bin/linux-${CMAKE_PLATFORM}/Release/libslang.so SLANG_BINARY)
|
||||||
|
string(TOLOWER bin/linux-${CMAKE_PLATFORM}/Release/libslang-glslang.so SLANG_GLSLANG)
|
||||||
set(SLANG_LIB_PATH)
|
set(SLANG_LIB_PATH)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
list(APPEND EXTRA_CMAKE_ARGS
|
list(APPEND EXTRA_CMAKE_ARGS
|
||||||
-DSLANG_INCLUDE_DIRS=${EXTERNAL_ROOT}/slang
|
-DSLANG_INCLUDE_DIRS=${EXTERNAL_ROOT}/slang
|
||||||
-DSLANG_LIBRARY=${SLANG_LIB_PATH})
|
-DSLANG_LIBRARY=${SLANG_LIB_PATH}
|
||||||
|
-DSLANG_BINARY=${SLANG_BINARY}
|
||||||
|
-DSLANG_GLSLANG=${SLANG_GLSLANG})
|
||||||
|
|
||||||
list(APPEND DEPENDENT_BINARIES ${SLANG_ROOT}/${SLANG_BINARY})
|
|
||||||
|
|
||||||
list(APPEND EXTRA_CMAKE_ARGS
|
|
||||||
-DDEPENDENT_BINARIES=${DEPENDENT_BINARIES})
|
|
||||||
#-----------------SeeleEngine--------------------
|
#-----------------SeeleEngine--------------------
|
||||||
ExternalProject_Add(SeeleEngine
|
ExternalProject_Add(SeeleEngine
|
||||||
DEPENDS ${DEPENDENCIES}
|
DEPENDS ${DEPENDENCIES}
|
||||||
SOURCE_DIR ${PROJECT_SOURCE_DIR}
|
SOURCE_DIR ${PROJECT_SOURCE_DIR}
|
||||||
|
PREFIX ${CMAKE_BINARY_DIR}
|
||||||
|
BINARY_DIR ${CMAKE_BINARY_DIR}
|
||||||
CMAKE_ARGS -DUSE_SUPERBUILD=OFF ${EXTRA_CMAKE_ARGS}
|
CMAKE_ARGS -DUSE_SUPERBUILD=OFF ${EXTRA_CMAKE_ARGS}
|
||||||
INSTALL_COMMAND ""
|
INSTALL_COMMAND "")
|
||||||
BINARY_DIR ${CMAKE_BINARY_DIR})
|
|
||||||
|
|||||||
+1
Submodule external/assimp added at 110f8845a2
+1
Submodule external/stb added at f54acd4e13
@@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
import LightEnv;
|
||||||
|
import Common;
|
||||||
|
|
||||||
|
struct ComputeShaderInput
|
||||||
|
{
|
||||||
|
uint3 groupID : SV_GroupID;
|
||||||
|
uint3 groupThreadID : SV_GroupThreadID;
|
||||||
|
uint3 dispatchThreadID : SV_DispatchThreadID;
|
||||||
|
uint groupIndex : SV_GroupIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0)
|
||||||
|
cbuffer DispatchParams
|
||||||
|
{
|
||||||
|
uint3 numThreadGroups;
|
||||||
|
uint pad0;
|
||||||
|
uint3 numThreads;
|
||||||
|
uint pad1;
|
||||||
|
}
|
||||||
|
layout(set = 0, binding = 2)
|
||||||
|
RWStructuredBuffer<Frustum> out_Frustums;
|
||||||
|
|
||||||
|
|
||||||
|
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
|
||||||
|
[shader("compute")]
|
||||||
|
void computeFrustums(ComputeShaderInput in)
|
||||||
|
{
|
||||||
|
const float3 eyePos = float3(0,0,0);
|
||||||
|
|
||||||
|
float4 screenSpace[4];
|
||||||
|
|
||||||
|
screenSpace[0] = float4(in.dispatchThreadID.xy * BLOCK_SIZE, 1.0f, 1.0f);
|
||||||
|
screenSpace[1] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y) * BLOCK_SIZE, 1.0f, 1.0f);
|
||||||
|
screenSpace[2] = float4(float2(in.dispatchThreadID.x, in.dispatchThreadID.y + 1) * BLOCK_SIZE, 1.0f, 1.0f);
|
||||||
|
screenSpace[3] = float4(float2(in.dispatchThreadID.x + 1, in.dispatchThreadID.y + 1) * BLOCK_SIZE, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
//Convert to viewSpace
|
||||||
|
float3 viewSpace[4];
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
viewSpace[i] = screenToView(screenSpace[i]).xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Compute frustum
|
||||||
|
Frustum frustum;
|
||||||
|
|
||||||
|
frustum.planes[0] = computePlane(eyePos, viewSpace[0], viewSpace[2]);
|
||||||
|
frustum.planes[1] = computePlane(eyePos, viewSpace[3], viewSpace[1]);
|
||||||
|
frustum.planes[2] = computePlane(eyePos, viewSpace[1], viewSpace[0]);
|
||||||
|
frustum.planes[3] = computePlane(eyePos, viewSpace[2], viewSpace[3]);
|
||||||
|
|
||||||
|
if(in.dispatchThreadID.x < numThreads.x && in.dispatchThreadID.y < numThreads.y)
|
||||||
|
{
|
||||||
|
uint index = in.dispatchThreadID.x + (in.dispatchThreadID.y * numThreads.x);
|
||||||
|
out_Frustums[index] = frustum;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import InputGeometry;
|
||||||
|
|
||||||
|
struct ViewParams
|
||||||
|
{
|
||||||
|
float4x4 viewMatrix;
|
||||||
|
float4x4 projectionMatrix;
|
||||||
|
float4 cameraPos_WS;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0)
|
||||||
|
ParameterBlock<ViewParams> gViewParams;
|
||||||
|
|
||||||
|
struct ModelParameter
|
||||||
|
{
|
||||||
|
float4x4 modelMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[vk::push_constant]]
|
||||||
|
ConstantBuffer<ModelParameter> gModelParams;
|
||||||
|
|
||||||
|
struct VertexShaderOutput
|
||||||
|
{
|
||||||
|
float4 out_Position : SV_Position;
|
||||||
|
}
|
||||||
|
[shader("vertex")]
|
||||||
|
VertexShaderOutput depthPrepass(PositionOnlyVertexInput input)
|
||||||
|
{
|
||||||
|
VertexShaderOutput out;
|
||||||
|
float4 worldPos = mul(gModelParams.modelMatrix, float4(input.getVertexPosition(), 1));
|
||||||
|
float4 viewPos = mul(gViewParams.viewMatrix, worldPos);
|
||||||
|
out.out_Position = mul(gViewParams.projectionMatrix, viewPos);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
import LightEnv;
|
||||||
|
|
||||||
|
struct VertexInput
|
||||||
|
{
|
||||||
|
float3 basePosition;
|
||||||
|
float3 position;
|
||||||
|
float3 velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ViewParameter
|
||||||
|
{
|
||||||
|
float4 cameraPos_WS;
|
||||||
|
float4x4 viewMatrix;
|
||||||
|
float4x4 projectionMatrix;
|
||||||
|
PointLight light;
|
||||||
|
}
|
||||||
|
layout(set = 0, std430)
|
||||||
|
ParameterBlock<ViewParameter> gViewParams;
|
||||||
|
|
||||||
|
struct VertexToPixel
|
||||||
|
{
|
||||||
|
float4 position_CS : SV_Position;
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexToPixel vertexMain(VertexInput input)
|
||||||
|
{
|
||||||
|
VertexToPixel output = (VertexToPixel)0;
|
||||||
|
float3 cameraRight_WS = float3(gViewParams.viewMatrix[0][0], gViewParams.viewMatrix[0][1], gViewParams.viewMatrix[0][2]);
|
||||||
|
float3 cameraUp_WS = float3(gViewParams.viewMatrix[1][0], gViewParams.viewMatrix[1][1], gViewParams.viewMatrix[1][2]);
|
||||||
|
float3 worldPosition = input.position + cameraRight_WS * input.basePosition.x + cameraUp_WS * input.basePosition.y;
|
||||||
|
float4 viewPosition = mul(gViewParams.viewMatrix, float4(worldPosition, 1));
|
||||||
|
output.position_CS = mul(gViewParams.projectionMatrix, viewPosition);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 fragMain(VertexToPixel input) : SV_Target
|
||||||
|
{
|
||||||
|
return float4(0, 1, 0, 0.001f);
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import InputGeometry;
|
||||||
|
import LightEnv;
|
||||||
|
import BRDF;
|
||||||
|
import Material;
|
||||||
|
import TexturedMaterial;
|
||||||
|
import FlatColorMaterial;
|
||||||
|
|
||||||
|
struct ViewParameter
|
||||||
|
{
|
||||||
|
float4x4 viewMatrix;
|
||||||
|
float4x4 projectionMatrix;
|
||||||
|
float4 cameraPos_WS;
|
||||||
|
}
|
||||||
|
layout(set = 0, binding = 0, std430)
|
||||||
|
ConstantBuffer<ViewParameter> gViewParams;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 1, std430)
|
||||||
|
ConstantBuffer<Lights> gLightEnv;
|
||||||
|
|
||||||
|
layout(set = 1, std430)
|
||||||
|
type_param TMaterial : IMaterial;
|
||||||
|
ParameterBlock<TMaterial> gMaterial;
|
||||||
|
|
||||||
|
struct ModelParameter
|
||||||
|
{
|
||||||
|
float4x4 modelMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[vk::push_constant]]
|
||||||
|
ConstantBuffer<ModelParameter> gModelParams;
|
||||||
|
|
||||||
|
struct VertexStageOutput
|
||||||
|
{
|
||||||
|
MaterialPixelParameter materialParameter : MaterialParameter;
|
||||||
|
float4 sv_position : SV_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
|
VertexStageOutput vertexMain(
|
||||||
|
InputGeometry inputGeometry)
|
||||||
|
{
|
||||||
|
VertexStageOutput output;
|
||||||
|
MaterialPixelParameter pixelParams;
|
||||||
|
float4 worldPosition = mul(gModelParams.modelMatrix, float4(inputGeometry.getVertexPosition(), 1));
|
||||||
|
pixelParams.position = worldPosition.xyz;
|
||||||
|
pixelParams.texCoord = inputGeometry.texCoord;
|
||||||
|
|
||||||
|
float4 viewPosition = mul(gViewParams.viewMatrix, worldPosition);
|
||||||
|
pixelParams.viewDir = gViewParams.cameraPos_WS.xyz - worldPosition.xyz;
|
||||||
|
|
||||||
|
pixelParams.normal = mul(gModelParams.modelMatrix, float4(inputGeometry.getNormal(), 0)).xyz;
|
||||||
|
pixelParams.tangent = mul(gModelParams.modelMatrix, float4(inputGeometry.getTangent(), 0)).xyz;
|
||||||
|
pixelParams.biTangent = mul(gModelParams.modelMatrix, float4(inputGeometry.getBiTangent(), 0)).xyz;
|
||||||
|
pixelParams.clipPosition = mul(gViewParams.projectionMatrix, viewPosition);
|
||||||
|
|
||||||
|
output.materialParameter = pixelParams;
|
||||||
|
output.sv_position = pixelParams.clipPosition;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[shader("fragment")]
|
||||||
|
float4 fragmentMain(MaterialPixelParameter input : MaterialParameter) : SV_Target
|
||||||
|
{
|
||||||
|
TMaterial.BRDF brdf = gMaterial.prepare(input);
|
||||||
|
|
||||||
|
float3 viewDir = normalize(input.viewDir);
|
||||||
|
|
||||||
|
float3 result = float3(0, 0, 0);
|
||||||
|
for (int i = 0; i < gLightEnv.numDirectionalLights; ++i)
|
||||||
|
{
|
||||||
|
result += gLightEnv.directionalLights[i].illuminate(input, brdf, viewDir);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < gLightEnv.numPointLights; ++i)
|
||||||
|
{
|
||||||
|
result += gLightEnv.pointLights[i].illuminate(input, brdf, viewDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return float4(result, 0);
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import InputGeometry;
|
||||||
|
import LightEnv;
|
||||||
|
import BRDF;
|
||||||
|
import Material;
|
||||||
|
import TexturedMaterial;
|
||||||
|
import FlatColorMaterial;
|
||||||
|
import Common;
|
||||||
|
|
||||||
|
struct ViewParameter
|
||||||
|
{
|
||||||
|
float4x4 viewMatrix;
|
||||||
|
float4x4 projectionMatrix;
|
||||||
|
float4 cameraPos_WS;
|
||||||
|
}
|
||||||
|
layout(set = 0, binding = 0, std430)
|
||||||
|
ConstantBuffer<ViewParameter> gViewParams;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 1, std430)
|
||||||
|
ConstantBuffer<Lights> gLightEnv;
|
||||||
|
layout(set = 0, binding = 2)
|
||||||
|
StructuredBuffer<uint> lightIndexList;
|
||||||
|
layout(set = 0, binding = 3)
|
||||||
|
RWTexture2D<uint2> lightGrid;
|
||||||
|
|
||||||
|
layout(set = 1, std430)
|
||||||
|
type_param TMaterial : IMaterial;
|
||||||
|
ParameterBlock<TMaterial> gMaterial;
|
||||||
|
|
||||||
|
struct ModelParameter
|
||||||
|
{
|
||||||
|
float4x4 modelMatrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout(set = 2)
|
||||||
|
ConstantBuffer<ModelParameter> gModelParams;
|
||||||
|
|
||||||
|
struct VertexStageOutput
|
||||||
|
{
|
||||||
|
MaterialPixelParameter materialParameter : MaterialParameter;
|
||||||
|
float4 sv_position : SV_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
[shader("vertex")]
|
||||||
|
VertexStageOutput vertexMain(
|
||||||
|
InputGeometry inputGeometry)
|
||||||
|
{
|
||||||
|
VertexStageOutput output;
|
||||||
|
MaterialPixelParameter pixelParams;
|
||||||
|
float4 worldPosition = mul(gModelParams.modelMatrix, float4(inputGeometry.getVertexPosition(), 1));
|
||||||
|
pixelParams.position = worldPosition.xyz;
|
||||||
|
pixelParams.texCoord = inputGeometry.texCoord;
|
||||||
|
|
||||||
|
float4 viewPosition = mul(gViewParams.viewMatrix, worldPosition);
|
||||||
|
pixelParams.viewDir = gViewParams.cameraPos_WS.xyz - worldPosition.xyz;
|
||||||
|
|
||||||
|
pixelParams.normal = mul(gModelParams.modelMatrix, float4(inputGeometry.getNormal(), 0)).xyz;
|
||||||
|
pixelParams.tangent = mul(gModelParams.modelMatrix, float4(inputGeometry.getTangent(), 0)).xyz;
|
||||||
|
pixelParams.biTangent = mul(gModelParams.modelMatrix, float4(inputGeometry.getBiTangent(), 0)).xyz;
|
||||||
|
pixelParams.clipPosition = mul(gViewParams.projectionMatrix, viewPosition);
|
||||||
|
|
||||||
|
output.materialParameter = pixelParams;
|
||||||
|
output.sv_position = pixelParams.clipPosition;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[shader("fragment")]
|
||||||
|
float4 fragmentMain(MaterialPixelParameter input : MaterialParameter) : SV_Target
|
||||||
|
{
|
||||||
|
TMaterial.BRDF brdf = gMaterial.prepare(input);
|
||||||
|
|
||||||
|
float3 viewDir = normalize(input.viewDir);
|
||||||
|
|
||||||
|
float3 result = float3(0, 0, 0);
|
||||||
|
for (int i = 0; i < gLightEnv.numDirectionalLights; ++i)
|
||||||
|
{
|
||||||
|
result += gLightEnv.directionalLights[i].illuminate(input, brdf, viewDir);
|
||||||
|
}
|
||||||
|
uint2 tileIndex = uint2(floor(input.clipPosition.xy) / BLOCK_SIZE);
|
||||||
|
|
||||||
|
uint startOffset = lightGrid[tileIndex].x;
|
||||||
|
uint lightCount = lightGrid[tileIndex].y;
|
||||||
|
|
||||||
|
for (int j = 0; j < lightCount; ++j)
|
||||||
|
{
|
||||||
|
uint lightIndex = lightIndexList[startOffset + j];
|
||||||
|
PointLight pointLight = gLightEnv.pointLights[lightIndex];
|
||||||
|
result += pointLight.illuminate(input, brdf, viewDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
return float4(result, 1);
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
import LightEnv;
|
||||||
|
import Common;
|
||||||
|
|
||||||
|
struct ComputeShaderInput
|
||||||
|
{
|
||||||
|
uint3 groupID : SV_GroupID;
|
||||||
|
uint3 groupThreadID : SV_GroupThreadID;
|
||||||
|
uint3 dispatchThreadID : SV_DispatchThreadID;
|
||||||
|
uint groupIndex : SV_GroupIndex;
|
||||||
|
};
|
||||||
|
layout(binding = 0)
|
||||||
|
cbuffer DispatchParams
|
||||||
|
{
|
||||||
|
uint3 numThreadGroups;
|
||||||
|
uint pad0;
|
||||||
|
uint3 numThreads;
|
||||||
|
uint pad1;
|
||||||
|
}
|
||||||
|
|
||||||
|
layout(binding = 2)
|
||||||
|
RWTexture2D depthTextureVS;
|
||||||
|
layout(binding = 3)
|
||||||
|
ConstantBuffer<Lights> lights;
|
||||||
|
layout(binding = 4)
|
||||||
|
StructuredBuffer<Frustum> frustums;
|
||||||
|
|
||||||
|
layout(binding = 5)
|
||||||
|
RWStructuredBuffer<uint> oLightIndexCounter;
|
||||||
|
layout(binding = 6)
|
||||||
|
RWStructuredBuffer<uint> tLightIndexCounter;
|
||||||
|
|
||||||
|
layout(binding = 7)
|
||||||
|
RWStructuredBuffer<uint> oLightIndexList;
|
||||||
|
layout(binding = 8)
|
||||||
|
RWStructuredBuffer<uint> tLightIndexList;
|
||||||
|
layout(binding = 9)
|
||||||
|
RWTexture2D<uint2> oLightGrid;
|
||||||
|
layout(binding = 10)
|
||||||
|
RWTexture2D<uint2> tLightGrid;
|
||||||
|
|
||||||
|
groupshared uint uMinDepth;
|
||||||
|
groupshared uint uMaxDepth;
|
||||||
|
|
||||||
|
groupshared Frustum groupFrustum;
|
||||||
|
|
||||||
|
groupshared uint oLightCount;
|
||||||
|
groupshared uint oLightIndexStartOffset;
|
||||||
|
groupshared uint oLightList[1024];
|
||||||
|
|
||||||
|
groupshared uint tLightCount;
|
||||||
|
groupshared uint tLightIndexStartOffset;
|
||||||
|
groupshared uint tLightList[1024];
|
||||||
|
|
||||||
|
|
||||||
|
void oAppendLight(uint lightIndex)
|
||||||
|
{
|
||||||
|
uint index;
|
||||||
|
InterlockedAdd(oLightCount, 1, index);
|
||||||
|
if(index < 1024)
|
||||||
|
{
|
||||||
|
oLightList[index] = lightIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tAppendLight(uint lightIndex)
|
||||||
|
{
|
||||||
|
uint index;
|
||||||
|
InterlockedAdd(tLightCount, 1, index);
|
||||||
|
if(index < 1024)
|
||||||
|
{
|
||||||
|
tLightList[index] = lightIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[numthreads(BLOCK_SIZE, BLOCK_SIZE, 1)]
|
||||||
|
void cullLights(ComputeShaderInput in)
|
||||||
|
{
|
||||||
|
int2 texCoord = in.dispatchThreadID.xy;
|
||||||
|
float fDepth = depthTextureVS.Load(texCoord).r;
|
||||||
|
|
||||||
|
uint uDepth = asuint(fDepth);
|
||||||
|
if(in.groupIndex == 0)
|
||||||
|
{
|
||||||
|
uMinDepth = 0xffffffff;
|
||||||
|
uMaxDepth = 0x0;
|
||||||
|
oLightCount = 0;
|
||||||
|
tLightCount = 0;
|
||||||
|
groupFrustum = frustums[in.groupID.x + (in.groupID.y * numThreadGroups.x)];
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupMemoryBarrierWithGroupSync();
|
||||||
|
InterlockedMin(uMinDepth, uDepth);
|
||||||
|
InterlockedMax(uMaxDepth, uDepth);
|
||||||
|
|
||||||
|
GroupMemoryBarrierWithGroupSync();
|
||||||
|
|
||||||
|
float fMinDepth = asfloat(uMinDepth);
|
||||||
|
float fMaxDepth = asfloat(uMaxDepth);
|
||||||
|
|
||||||
|
float minDepthVS = clipToView(float4(0, 0, fMinDepth, 1)).z;
|
||||||
|
float maxDepthVS = clipToView(float4(0, 0, fMaxDepth, 1)).z;
|
||||||
|
float nearClipVS = clipToView(float4(0, 0, 0, 1.0f)).z;
|
||||||
|
|
||||||
|
Plane minPlane = {float3(0, 0, -1), -minDepthVS};
|
||||||
|
|
||||||
|
for ( uint i = in.groupIndex; i < lights.numPointLights; i += BLOCK_SIZE * BLOCK_SIZE )
|
||||||
|
{
|
||||||
|
PointLight light = lights.pointLights[i];
|
||||||
|
//if(light.insideFrustum(groupFrustum, nearClipVS, maxDepthVS))
|
||||||
|
{
|
||||||
|
//InterlockedAdd(tLightCount, 1, index);
|
||||||
|
//if(index < 1024)
|
||||||
|
//{
|
||||||
|
// tLightList[index] = i;
|
||||||
|
//}
|
||||||
|
//if(!light.insidePlane(minPlane))
|
||||||
|
//{
|
||||||
|
oAppendLight(i);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupMemoryBarrierWithGroupSync();
|
||||||
|
|
||||||
|
if(in.groupIndex == 0)
|
||||||
|
{
|
||||||
|
InterlockedAdd(oLightIndexCounter[0], (uint)oLightCount, oLightIndexStartOffset);
|
||||||
|
oLightGrid[in.groupID.xy] = uint2(oLightIndexStartOffset, oLightCount);
|
||||||
|
|
||||||
|
InterlockedAdd(tLightIndexCounter[0], (uint)tLightCount, tLightIndexStartOffset);
|
||||||
|
tLightGrid[in.groupID.xy] = uint2(tLightIndexStartOffset, tLightCount);
|
||||||
|
}
|
||||||
|
GroupMemoryBarrierWithGroupSync();
|
||||||
|
|
||||||
|
if(in.groupIndex == 0)
|
||||||
|
{
|
||||||
|
for (uint j = 0; j < (uint)oLightCount; j += 1/*BLOCK_SIZE * BLOCK_SIZE*/)
|
||||||
|
{
|
||||||
|
oLightIndexList[oLightIndexStartOffset + j] = oLightList[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For transparent geometry.
|
||||||
|
for ( uint k = in.groupIndex; k < (uint)tLightCount; k += BLOCK_SIZE * BLOCK_SIZE )
|
||||||
|
{
|
||||||
|
tLightIndexList[tLightIndexStartOffset + k] = tLightList[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"name": "Placeholder",
|
||||||
|
"profile": "BlinnPhong",
|
||||||
|
"params": {
|
||||||
|
"diffuseTexture": {
|
||||||
|
"type": "Texture2D"
|
||||||
|
},
|
||||||
|
"specularTexture": {
|
||||||
|
"type": "Texture2D"
|
||||||
|
},
|
||||||
|
"normalTexture": {
|
||||||
|
"type": "Texture2D"
|
||||||
|
},
|
||||||
|
"uvScale": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "0.0f"
|
||||||
|
},
|
||||||
|
"metallic": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "0.0f"
|
||||||
|
},
|
||||||
|
"subsurface": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "0.0f"
|
||||||
|
},
|
||||||
|
"roughness": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "0.5f"
|
||||||
|
},
|
||||||
|
"specularTint": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "0.0f"
|
||||||
|
},
|
||||||
|
"anisotropic": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "0.0f"
|
||||||
|
},
|
||||||
|
"sheen": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "0.0f"
|
||||||
|
},
|
||||||
|
"sheenTint": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "0.5f"
|
||||||
|
},
|
||||||
|
"clearCoat": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "0.0f"
|
||||||
|
},
|
||||||
|
"clearCoatGloss": {
|
||||||
|
"type": "float",
|
||||||
|
"default": "1.0f"
|
||||||
|
},
|
||||||
|
"textureSampler": {
|
||||||
|
"type": "SamplerState"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"code": [
|
||||||
|
"result.baseColor = diffuseTexture.Sample(textureSampler, geometry.texCoord * uvScale).xyz;",
|
||||||
|
"result.metallic = 0;",
|
||||||
|
"float3 bumpMapNormal = normalTexture.Sample(textureSampler, geometry.texCoord * uvScale).xyz;",
|
||||||
|
"bumpMapNormal = 2.0 * bumpMapNormal - float3(1.0, 1.0, 1.0);",
|
||||||
|
"result.normal = geometry.transformLocalToWorld(bumpMapNormal);",
|
||||||
|
"result.specular = specularTexture.Sample(textureSampler, geometry.texCoord * uvScale).x;",
|
||||||
|
"result.roughness = roughness;",
|
||||||
|
"result.specularTint = specularTint;",
|
||||||
|
"result.anisotropic = anisotropic;",
|
||||||
|
"result.sheen = sheen;",
|
||||||
|
"result.sheenTint = sheenTint;",
|
||||||
|
"result.clearCoat = clearCoat;",
|
||||||
|
"result.clearCoatGloss = clearCoatGloss;",
|
||||||
|
"return result;"
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
import Common;
|
||||||
|
|
||||||
|
interface IBRDF
|
||||||
|
{
|
||||||
|
float3 evaluate(float3 view, float3 light, float3 normal, float3 tangent, float3 biTangent, float3 lightColor);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BlinnPhong : IBRDF
|
||||||
|
{
|
||||||
|
float3 baseColor;
|
||||||
|
float metallic = 0;
|
||||||
|
float3 normal = float3(0, 1, 0);
|
||||||
|
float subsurface = 0;
|
||||||
|
float specular = 0.5;
|
||||||
|
float roughness = 0.5;
|
||||||
|
float specularTint = 0;
|
||||||
|
float anisotropic = 0;
|
||||||
|
float sheen = 0;
|
||||||
|
float sheenTint = 0.5f;
|
||||||
|
float clearCoat = 0;
|
||||||
|
float clearCoatGloss = 1;
|
||||||
|
|
||||||
|
float3 evaluate(float3 view, float3 light, float3 surfaceNormal, float3 tangent, float3 biTangent, float3 lightColor)
|
||||||
|
{
|
||||||
|
float nDotL = saturate(dot(normal, light));
|
||||||
|
float3 h = normalize(light + view);
|
||||||
|
float nDotH = saturate(dot(normal, h));
|
||||||
|
|
||||||
|
return baseColor * nDotL + lightColor * specular * pow(nDotH, sheen);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DisneyBRDF : IBRDF
|
||||||
|
{
|
||||||
|
float3 baseColor;
|
||||||
|
float metallic = 0;
|
||||||
|
float3 normal = float3(0, 1, 0);
|
||||||
|
float subsurface = 0;
|
||||||
|
float specular = 0.5;
|
||||||
|
float roughness = 0.5;
|
||||||
|
float specularTint = 0;
|
||||||
|
float anisotropic = 0;
|
||||||
|
float sheen = 0;
|
||||||
|
float sheenTint = 0.5f;
|
||||||
|
float clearCoat = 0;
|
||||||
|
float clearCoatGloss = 1;
|
||||||
|
|
||||||
|
float sqr(float x)
|
||||||
|
{
|
||||||
|
return x * x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SchlickFresnel(float u)
|
||||||
|
{
|
||||||
|
float m = clamp(1 - u, 0, 1);
|
||||||
|
float m2 = m * m;
|
||||||
|
return m2 * m2 * m; // pow(m,5)
|
||||||
|
}
|
||||||
|
|
||||||
|
float GTR1(float NdotH, float a)
|
||||||
|
{
|
||||||
|
if (a >= 1)
|
||||||
|
return 1 / PI;
|
||||||
|
float a2 = a * a;
|
||||||
|
float t = 1 + (a2 - 1) * NdotH * NdotH;
|
||||||
|
return (a2 - 1) / (PI * log(a2) * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
float GTR2(float NdotH, float a)
|
||||||
|
{
|
||||||
|
float a2 = a * a;
|
||||||
|
float t = 1 + (a2 - 1) * NdotH * NdotH;
|
||||||
|
return a2 / (PI * t * t);
|
||||||
|
}
|
||||||
|
|
||||||
|
float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay)
|
||||||
|
{
|
||||||
|
return 1 / (PI * ax * ay * sqr(sqr(HdotX / ax) + sqr(HdotY / ay) + NdotH * NdotH));
|
||||||
|
}
|
||||||
|
|
||||||
|
float smithG_GGX(float NdotV, float alphaG)
|
||||||
|
{
|
||||||
|
float a = alphaG * alphaG;
|
||||||
|
float b = NdotV * NdotV;
|
||||||
|
return 1 / (NdotV + sqrt(a + b - a * b));
|
||||||
|
}
|
||||||
|
|
||||||
|
float smithG_GGX_aniso(float NdotV, float VdotX, float VdotY, float ax, float ay)
|
||||||
|
{
|
||||||
|
return 1 / (NdotV + sqrt(sqr(VdotX * ax) + sqr(VdotY * ay) + sqr(NdotV)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float3 mon2lin(float3 x)
|
||||||
|
{
|
||||||
|
return float3(pow(x[0], 2.2), pow(x[1], 2.2), pow(x[2], 2.2));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float3 evaluate(float3 V, float3 L, float3 surfaceNormal, float3 X, float3 Y, float3 lightColor)
|
||||||
|
{
|
||||||
|
float3 N = normal;
|
||||||
|
float NdotL = dot(N, L);
|
||||||
|
float NdotV = dot(N, V);
|
||||||
|
if (NdotL < 0 || NdotV < 0)
|
||||||
|
return float3(0);
|
||||||
|
float3 H = normalize(L + V);
|
||||||
|
|
||||||
|
float NdotH = dot(N, H);
|
||||||
|
float LdotH = dot(L, H);
|
||||||
|
float3 Cdlin = mon2lin(baseColor);
|
||||||
|
float Cdlum = .3 * Cdlin[0] + .6 * Cdlin[1] + .1 * Cdlin[2]; // luminance approx.
|
||||||
|
float3 Ctint = Cdlum > 0 ? Cdlin / Cdlum : float3(1); // normalize lum. to isolate hue+sat
|
||||||
|
float3 Cspec0 = lerp(specular * .08 * lerp(float3(1), Ctint, specularTint), Cdlin, metallic);
|
||||||
|
float3 Csheen = lerp(float3(1), Ctint, sheenTint);
|
||||||
|
|
||||||
|
// Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
|
||||||
|
// and mix in diffuse retro-reflection based on roughness
|
||||||
|
float FL = SchlickFresnel(NdotL), FV = SchlickFresnel(NdotV);
|
||||||
|
float Fd90 = 0.5 + 2 * LdotH * LdotH * roughness;
|
||||||
|
float Fd = lerp(1.0, Fd90, FL) * lerp(1.0, Fd90, FV);
|
||||||
|
|
||||||
|
// Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
|
||||||
|
// 1.25 scale is used to (roughly) preserve albedo
|
||||||
|
// Fss90 used to "flatten" retroreflection based on roughness
|
||||||
|
float Fss90 = LdotH * LdotH * roughness;
|
||||||
|
float Fss = lerp(1.0, Fss90, FL) * lerp(1.0, Fss90, FV);
|
||||||
|
float ss = 1.25 * (Fss * (1 / (NdotL + NdotV) - .5) + .5);
|
||||||
|
|
||||||
|
// specular
|
||||||
|
float aspect = sqrt(1 - anisotropic * .9);
|
||||||
|
float ax = max(.001, sqr(roughness) / aspect);
|
||||||
|
float ay = max(.001, sqr(roughness) * aspect);
|
||||||
|
float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay);
|
||||||
|
float FH = SchlickFresnel(LdotH);
|
||||||
|
float3 Fs = lerp(Cspec0, float3(1), FH);
|
||||||
|
float Gs;
|
||||||
|
Gs = smithG_GGX_aniso(NdotL, dot(L, X), dot(L, Y), ax, ay);
|
||||||
|
Gs *= smithG_GGX_aniso(NdotV, dot(V, X), dot(V, Y), ax, ay);
|
||||||
|
|
||||||
|
// sheen
|
||||||
|
float3 Fsheen = FH * sheen * Csheen;
|
||||||
|
|
||||||
|
// clearcoat (ior = 1.5 -> F0 = 0.04)
|
||||||
|
float Dr = GTR1(NdotH, lerp(.1, .001, clearCoatGloss));
|
||||||
|
float Fr = lerp(.04, 1.0, FH);
|
||||||
|
float Gr = smithG_GGX(NdotL, .25) * smithG_GGX(NdotV, .25);
|
||||||
|
|
||||||
|
return ((1 / PI) * lerp(Fd, ss, subsurface) * Cdlin + Fsheen)
|
||||||
|
* (1 - metallic)
|
||||||
|
+ Gs * Fs * Ds + .25 * clearCoat * Gr * Fr * Dr;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
const static float PI = 3.1415926535897932f;
|
||||||
|
const static uint MAX_PARTICLES = 65536;
|
||||||
|
const static uint BLOCK_SIZE = 8;
|
||||||
|
|
||||||
|
cbuffer ScreenToViewParams
|
||||||
|
{
|
||||||
|
float4x4 inverseProjection;
|
||||||
|
float2 screenDimensions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert clip space coordinates to view space
|
||||||
|
float4 clipToView( float4 clip )
|
||||||
|
{
|
||||||
|
// View space position.
|
||||||
|
float4 view = mul( inverseProjection, clip );
|
||||||
|
// Perspective projection.
|
||||||
|
view = view / view.w;
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert screen space coordinates to view space.
|
||||||
|
float4 screenToView( float4 screen )
|
||||||
|
{
|
||||||
|
// Convert to normalized texture coordinates
|
||||||
|
float2 texCoord = screen.xy / screenDimensions;
|
||||||
|
|
||||||
|
// Convert to clip space
|
||||||
|
float4 clip = float4( float2( texCoord.x, -texCoord.y ) * 2.0f - 1.0f, screen.z, screen.w );
|
||||||
|
|
||||||
|
return clipToView( clip );
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Plane
|
||||||
|
{
|
||||||
|
float3 n;
|
||||||
|
float d;
|
||||||
|
float3 p0;
|
||||||
|
float3 p1;
|
||||||
|
float3 p2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Frustum
|
||||||
|
{
|
||||||
|
Plane planes[4];
|
||||||
|
};
|
||||||
|
Plane computePlane(float3 p0, float3 p1, float3 p2)
|
||||||
|
{
|
||||||
|
Plane plane;
|
||||||
|
|
||||||
|
float3 v0 = p2 - p0;
|
||||||
|
float3 v2 = p1 - p0;
|
||||||
|
|
||||||
|
plane.n = normalize(cross(v0, v2));
|
||||||
|
|
||||||
|
plane.d = dot(plane.n, p0);
|
||||||
|
plane.p0 = p0;
|
||||||
|
plane.p1 = p1;
|
||||||
|
plane.p2 = p2;
|
||||||
|
|
||||||
|
return plane;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import LightEnv;
|
||||||
|
import Material;
|
||||||
|
import BRDF;
|
||||||
|
import InputGeometry;
|
||||||
|
|
||||||
|
struct FlatColorMaterial : IMaterial
|
||||||
|
{
|
||||||
|
float3 diffuseColor;
|
||||||
|
float specularity;
|
||||||
|
|
||||||
|
typedef BlinnPhong BRDF;
|
||||||
|
BlinnPhong prepare(MaterialPixelParameter input)
|
||||||
|
{
|
||||||
|
BlinnPhong result;
|
||||||
|
result.baseColor = diffuseColor;
|
||||||
|
result.specular = specularity;
|
||||||
|
result.normal = normalize(input.normal);
|
||||||
|
result.roughness = 0.5;
|
||||||
|
result.specularTint = 0;
|
||||||
|
result.anisotropic = 1;
|
||||||
|
result.sheen = 1;
|
||||||
|
result.sheenTint = 0.5;
|
||||||
|
result.clearCoat = 0;
|
||||||
|
result.clearCoatGloss = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
interface IVertexShaderInput
|
||||||
|
{
|
||||||
|
//internally, the vertex layout is stored in vec4 for faster access,
|
||||||
|
//but here we unwrap them for convenience
|
||||||
|
float3 getVertexPosition();
|
||||||
|
float2 getTexCoords();
|
||||||
|
float3 getNormal();
|
||||||
|
float3 getTangent();
|
||||||
|
float3 getBiTangent();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PositionOnlyVertexInput : IVertexShaderInput
|
||||||
|
{
|
||||||
|
float4 position;
|
||||||
|
|
||||||
|
float3 getVertexPosition() { return position.xyz; }
|
||||||
|
float2 getTexCoords() { return float2(0, 0); }
|
||||||
|
float3 getNormal() { return float3(0, 1, 0); }
|
||||||
|
float3 getTangent() { return float3(1, 0, 0); }
|
||||||
|
float3 getBiTangent() { return float3(0, 0, 1); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PositionAndNormalVertexInput : IVertexShaderInput
|
||||||
|
{
|
||||||
|
float4 position;
|
||||||
|
float4 normal;
|
||||||
|
|
||||||
|
float3 getVertexPosition() { return position.xyz; }
|
||||||
|
float2 getTexCoords() { return float2(0, 0); }
|
||||||
|
float3 getNormal() { return normal.xyz; }
|
||||||
|
float3 getTangent() { return float3(1, 0, 0); }
|
||||||
|
float3 getBiTangent() { return float3(0, 0, 1); }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InputGeometry : IVertexShaderInput
|
||||||
|
{
|
||||||
|
float4 position;
|
||||||
|
float2 texCoord;
|
||||||
|
float4 normal;
|
||||||
|
float4 tangent;
|
||||||
|
float4 bitangent;
|
||||||
|
|
||||||
|
float3 getVertexPosition() { return position.xyz; }
|
||||||
|
float2 getTexCoords() { return texCoord; }
|
||||||
|
float3 getNormal() { return normal.xyz; }
|
||||||
|
float3 getTangent() { return tangent.xyz; }
|
||||||
|
float3 getBiTangent() { return bitangent.xyz; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MaterialPixelParameter
|
||||||
|
{
|
||||||
|
float3 position;
|
||||||
|
float2 texCoord;
|
||||||
|
float3 viewDir;
|
||||||
|
float3 normal;
|
||||||
|
float3 tangent;
|
||||||
|
float3 biTangent;
|
||||||
|
float4 clipPosition;
|
||||||
|
float3 transformLocalToWorld(float3 input)
|
||||||
|
{
|
||||||
|
float3 unitNormal = normalize(normal);
|
||||||
|
float3 unitTangent = normalize(tangent);
|
||||||
|
unitTangent = normalize(unitTangent - dot(unitTangent, unitNormal) * unitNormal);
|
||||||
|
float3 unitBitangent = cross(unitTangent, unitNormal);
|
||||||
|
float3x3 tbn = float3x3(unitTangent, unitBitangent, unitNormal);
|
||||||
|
float3 result = mul(tbn, input);
|
||||||
|
result = normalize(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
import InputGeometry;
|
||||||
|
import BRDF;
|
||||||
|
import Common;
|
||||||
|
|
||||||
|
interface ILightEnv
|
||||||
|
{
|
||||||
|
float3 illuminate<B:IBRDF>(InputGeometry input, B brdf, float3 wo);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DirectionalLight : ILightEnv
|
||||||
|
{
|
||||||
|
float4 color;
|
||||||
|
float4 direction;
|
||||||
|
float4 intensity;
|
||||||
|
|
||||||
|
float3 illuminate<B:IBRDF>(MaterialPixelParameter input, B brdf, float3 wo)
|
||||||
|
{
|
||||||
|
return intensity.xyz * brdf.evaluate(wo, direction.xyz, input.normal, input.tangent, input.biTangent, color.xyz);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PointLight : ILightEnv
|
||||||
|
{
|
||||||
|
float4 positionWS;
|
||||||
|
float4 positionVS;
|
||||||
|
float3 color;
|
||||||
|
float range;
|
||||||
|
|
||||||
|
float3 illuminate<B:IBRDF>(MaterialPixelParameter input, B brdf, float3 viewDir)
|
||||||
|
{
|
||||||
|
float3 lightVec = positionWS.xyz - input.position;
|
||||||
|
float d = length(lightVec);
|
||||||
|
float3 direction = normalize(lightVec);
|
||||||
|
float illuminance = max(1 - d / range, 0);
|
||||||
|
return illuminance * brdf.evaluate(viewDir, direction, input.normal, input.tangent, input.biTangent, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insidePlane(Plane plane)
|
||||||
|
{
|
||||||
|
return dot(plane.n, positionVS.xyz) - plane.d < -range;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insideFrustum(Frustum frustum, float zNear, float zFar)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
//if(positionVS.z - range > zNear || positionVS.z + range < zFar)
|
||||||
|
{
|
||||||
|
// result = false;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < 4 && result; ++i)
|
||||||
|
{
|
||||||
|
if(insidePlane(frustum.planes[i]))
|
||||||
|
{
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MAX_DIRECTIONAL_LIGHTS 4
|
||||||
|
#define MAX_POINT_LIGHTS 256
|
||||||
|
struct Lights
|
||||||
|
{
|
||||||
|
DirectionalLight directionalLights[MAX_DIRECTIONAL_LIGHTS];
|
||||||
|
PointLight pointLights[MAX_POINT_LIGHTS];
|
||||||
|
uint numDirectionalLights;
|
||||||
|
uint numPointLights;
|
||||||
|
};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import Common;
|
||||||
|
import BRDF;
|
||||||
|
import InputGeometry;
|
||||||
|
|
||||||
|
interface IMaterial
|
||||||
|
{
|
||||||
|
associatedtype BRDF : IBRDF;
|
||||||
|
BRDF prepare(MaterialPixelParameter geometry);
|
||||||
|
};
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import Material;
|
||||||
|
import InputGeometry;
|
||||||
|
|
||||||
|
struct ParallaxMaterial : IMaterial
|
||||||
|
{
|
||||||
|
Texture2D<float4> diffuseTexture;
|
||||||
|
Texture2D<float4> specularTexture;
|
||||||
|
Texture2D<float4> displacementTexture;
|
||||||
|
SamplerState textureSampler;
|
||||||
|
float specularity;
|
||||||
|
|
||||||
|
typedef BlinnPhong BRDF;
|
||||||
|
BlinnPhong prepare(InputGeometry geometry)
|
||||||
|
{
|
||||||
|
BlinnPhong blinn;
|
||||||
|
blinn.baseColor = diffuseTexture.Sample(textureSampler, geometry.getTexCoords()).xyz;
|
||||||
|
blinn.specularColor = specularTexture.Sample(textureSampler, geometry.getTexCoords()).xyz;
|
||||||
|
blinn.specular = specularity;
|
||||||
|
return blinn;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
struct Particle
|
||||||
|
{
|
||||||
|
float3 position;
|
||||||
|
float mass;
|
||||||
|
float3 velocity;
|
||||||
|
float age;
|
||||||
|
float3 forceAccumulator;
|
||||||
|
float life;
|
||||||
|
float color;
|
||||||
|
float3 pad;
|
||||||
|
};
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import LightEnv;
|
||||||
|
import Material;
|
||||||
|
import BRDF;
|
||||||
|
import InputGeometry;
|
||||||
|
|
||||||
|
struct TexturedMaterial : IMaterial
|
||||||
|
{
|
||||||
|
Texture2D diffuseTexture;
|
||||||
|
Texture2D specularTexture;
|
||||||
|
Texture2D normalTexture;
|
||||||
|
float uvScale;
|
||||||
|
float metallic = 0;
|
||||||
|
float subsurface = 0;
|
||||||
|
float roughness = 0.5;
|
||||||
|
float specularTint = 0;
|
||||||
|
float anisotropic = 0;
|
||||||
|
float sheen = 0;
|
||||||
|
float sheenTint = 0.5f;
|
||||||
|
float clearCoat = 0;
|
||||||
|
float clearCoatGloss = 1;
|
||||||
|
SamplerState textureSampler;
|
||||||
|
|
||||||
|
typedef BlinnPhong BRDF;
|
||||||
|
BlinnPhong prepare(MaterialPixelParameter geometry)
|
||||||
|
{
|
||||||
|
BlinnPhong result;
|
||||||
|
result.baseColor = diffuseTexture.Sample(textureSampler, geometry.texCoord * uvScale).xyz;
|
||||||
|
result.metallic = 0;
|
||||||
|
float3 bumpMapNormal = normalTexture.Sample(textureSampler, geometry.texCoord * uvScale).xyz;
|
||||||
|
bumpMapNormal = 2.0 * bumpMapNormal - float3(1.0, 1.0, 1.0);
|
||||||
|
result.normal = geometry.transformLocalToWorld(bumpMapNormal);
|
||||||
|
result.specular = specularTexture.Sample(textureSampler, geometry.texCoord * uvScale).x;
|
||||||
|
result.roughness = roughness;
|
||||||
|
result.specularTint = specularTint;
|
||||||
|
result.anisotropic = anisotropic;
|
||||||
|
result.sheen = sheen;
|
||||||
|
result.sheenTint = sheenTint;
|
||||||
|
result.clearCoat = clearCoat;
|
||||||
|
result.clearCoatGloss = clearCoatGloss;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,485 @@
|
|||||||
|
// shaders.slang
|
||||||
|
|
||||||
|
//
|
||||||
|
// This example builds on the simplistic shaders presented in the
|
||||||
|
// "Hello, World" example by adding support for (intentionally
|
||||||
|
// simplistic) surface materil and light shading.
|
||||||
|
//
|
||||||
|
// The code here is not meant to exemplify state-of-the-art material
|
||||||
|
// and lighting techniques, but rather to show how a shader
|
||||||
|
// library can be developed in a modular fashion without reliance
|
||||||
|
// on the C preprocessor manual parameter-binding decorations.
|
||||||
|
//
|
||||||
|
|
||||||
|
// We are going to define a simple model for surface material shading.
|
||||||
|
//
|
||||||
|
// The first building block in our model will be the representation of
|
||||||
|
// the geometry attributes of a surface as fed into the material.
|
||||||
|
//
|
||||||
|
struct SurfaceGeometry
|
||||||
|
{
|
||||||
|
float3 position;
|
||||||
|
float3 normal;
|
||||||
|
|
||||||
|
// TODO: tangent vectors would be the natural next thing to add here,
|
||||||
|
// and would be required for anisotropic materials. However, the
|
||||||
|
// simplistic model loading code we are currently using doesn't
|
||||||
|
// produce tangents...
|
||||||
|
//
|
||||||
|
// float3 tangentU;
|
||||||
|
// float3 tangentV;
|
||||||
|
|
||||||
|
// We store a single UV parameterization in these geometry attributes.
|
||||||
|
// A more complex renderer might need support for multiple UV sets,
|
||||||
|
// and indeed it might choose to use interfaces and generics to capture
|
||||||
|
// the different requirements that different materials impose on
|
||||||
|
// the available surface attributes. We won't go to that kind of
|
||||||
|
// trouble for such a simple example.
|
||||||
|
//
|
||||||
|
float2 uv;
|
||||||
|
};
|
||||||
|
//
|
||||||
|
// Next, we want to define the fundamental concept of a refletance
|
||||||
|
// function, so that we can use it as a building block for other
|
||||||
|
// parts of the system. This is a case where we are trying to
|
||||||
|
// show how a proper physically-based renderer (PBR) might
|
||||||
|
// decompose the problem using Slang, even though our simple
|
||||||
|
// example is *not* physically based.
|
||||||
|
//
|
||||||
|
interface IBRDF
|
||||||
|
{
|
||||||
|
// Technically, a BRDF is only a function of the incident
|
||||||
|
// (`wi`) and exitant (`wo`) directions, but for simplicity
|
||||||
|
// we are passing in the surface normal (`N`) as well.
|
||||||
|
//
|
||||||
|
float3 evaluate(float3 wo, float3 wi, float3 N);
|
||||||
|
};
|
||||||
|
//
|
||||||
|
// We can now define various implemntations of the `IBRDF` interface
|
||||||
|
// that represent different reflectance functions we want to support.
|
||||||
|
// For now we keep things simple by defining about the simplest
|
||||||
|
// reflectance function we can think of: the Blinn-Phong reflectance
|
||||||
|
// model:
|
||||||
|
//
|
||||||
|
struct BlinnPhong : IBRDF
|
||||||
|
{
|
||||||
|
// Blinn-Phong needs diffuse and specular reflectances, plus
|
||||||
|
// a specular exponent value (which relates to "roughness"
|
||||||
|
// in more modern physically-based models).
|
||||||
|
//
|
||||||
|
float3 kd;
|
||||||
|
float3 ks;
|
||||||
|
float specularity;
|
||||||
|
|
||||||
|
// Here we implement the one requirement of the `IBRDF` interface
|
||||||
|
// for our concrete implementation, using a textbook definition
|
||||||
|
// of Blinng-Phong shading.
|
||||||
|
//
|
||||||
|
// Note: our "BRDF" definition here folds the N-dot-L term into
|
||||||
|
// the evlauation of the reflectance function in case there are
|
||||||
|
// useful algebraic simplifications this enables.
|
||||||
|
//
|
||||||
|
float3 evaluate(float3 V, float3 L, float3 N)
|
||||||
|
{
|
||||||
|
float nDotL = saturate(dot(N, L));
|
||||||
|
float3 H = normalize(L + V);
|
||||||
|
float nDotH = saturate(dot(N, H));
|
||||||
|
|
||||||
|
return kd*nDotL + ks*pow(nDotH, specularity);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//
|
||||||
|
// It is important to note that a reflectance function is *not*
|
||||||
|
// a "material." In most cases, a material will have spatially-varying
|
||||||
|
// properties so that it cannot be summarized as a single `IBRDF`
|
||||||
|
// instance.
|
||||||
|
//
|
||||||
|
// Thus a "material" is a value that can produce a BRDF for any point
|
||||||
|
// on a surface (e.g., by sampling texture maps, etc.).
|
||||||
|
//
|
||||||
|
interface IMaterial
|
||||||
|
{
|
||||||
|
// Different concrete material implementations might yield BRDF
|
||||||
|
// values with different types. E.g., one material might yield
|
||||||
|
// reflectance functions using `BlinnPhong` while another uses
|
||||||
|
// a much more complicated/accurate representation.
|
||||||
|
//
|
||||||
|
// We encapsulate the choice of BRDF parameters/evaluation in
|
||||||
|
// our material interface with an "associated type." In the
|
||||||
|
// simplest terms, think of this as an interface requirement
|
||||||
|
// that is a type, instead of a method.
|
||||||
|
//
|
||||||
|
// (If you are C++-minded, you might think of this as akin to
|
||||||
|
// how every container provided an `iterator` type, but different
|
||||||
|
// containers may have different types of iterators)
|
||||||
|
//
|
||||||
|
associatedtype BRDF : IBRDF;
|
||||||
|
|
||||||
|
// For our simple example program, it is enough for a material to
|
||||||
|
// be able to return a BRDF given a point on the surface.
|
||||||
|
//
|
||||||
|
// A more complex implementation of material shading might also
|
||||||
|
// have the material return updated surface geometry to reflect
|
||||||
|
// the result of normal mapping, occlusion mapping, etc. or
|
||||||
|
// return an opacity/coverage value for partially transparent
|
||||||
|
// surfaces.
|
||||||
|
//
|
||||||
|
BRDF prepare(SurfaceGeometry geometry);
|
||||||
|
};
|
||||||
|
|
||||||
|
// We will now define a trivial first implementation of the material
|
||||||
|
// interface, which uses our Blinn-Phong BRDF with uniform values
|
||||||
|
// for its parameters.
|
||||||
|
//
|
||||||
|
// Note that this implemetnation is being provided *after* the
|
||||||
|
// shader parameter `gMaterial` is declared, so that there is no
|
||||||
|
// assumption in the shader code that `gMaterial` will be plugged
|
||||||
|
// in using an instance of `SimpleMaterial`
|
||||||
|
//
|
||||||
|
//
|
||||||
|
struct SimpleMaterial : IMaterial
|
||||||
|
{
|
||||||
|
// We declare the properties we need as fields of the material type.
|
||||||
|
// When `SimpleMaterial` is used for `TMaterial` above, then
|
||||||
|
// `gMaterial` will be a `ParameterBlock<SimpleMaterial>`, and these
|
||||||
|
// parameters will be allocated to a constant buffer that is part of
|
||||||
|
// that parameter block.
|
||||||
|
//
|
||||||
|
// TODO: A future version of this example will include texture parameters
|
||||||
|
// here to show that they are declared just like simple uniforms.
|
||||||
|
//
|
||||||
|
float3 diffuseColor;
|
||||||
|
float3 specularColor;
|
||||||
|
float specularity;
|
||||||
|
|
||||||
|
// To satisfy the requirements of the `IMaterial` interface, our
|
||||||
|
// material type needs to provide a suitable `BRDF` type. We
|
||||||
|
// do this by using a simple `typedef`, although a nested
|
||||||
|
// `struct` type can also satisfy an associated type requirement.
|
||||||
|
//
|
||||||
|
// A future version of the Slang compiler may allow the "right"
|
||||||
|
// associated type definition to be inferred from the signature
|
||||||
|
// of the `prepare()` method below.
|
||||||
|
//
|
||||||
|
typedef BlinnPhong BRDF;
|
||||||
|
|
||||||
|
BlinnPhong prepare(SurfaceGeometry geometry)
|
||||||
|
{
|
||||||
|
BlinnPhong brdf;
|
||||||
|
brdf.kd = diffuseColor;
|
||||||
|
brdf.ks = specularColor;
|
||||||
|
brdf.specularity = specularity;
|
||||||
|
return brdf;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//
|
||||||
|
// Note that no other code in this file statically
|
||||||
|
// references the `SimpleMaterial` type, and instead
|
||||||
|
// it is up to the application to "plug in" this type,
|
||||||
|
// or another `IMaterial` implementation for the
|
||||||
|
// `TMaterial` parameter.
|
||||||
|
//
|
||||||
|
|
||||||
|
// A light, or an entire lighting *environment* is an object
|
||||||
|
// that can illuminate a surface using some BRDF implemented
|
||||||
|
// with our abstractions above.
|
||||||
|
//
|
||||||
|
interface ILightEnv
|
||||||
|
{
|
||||||
|
// The `illuminate` method is intended to integrate incoming
|
||||||
|
// illumination from this light (environment) incident at the
|
||||||
|
// surface point given by `g` (which has the reflectance function
|
||||||
|
// `brdf`) and reflected into the outgoing direction `wo`.
|
||||||
|
//
|
||||||
|
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo);
|
||||||
|
//
|
||||||
|
// Note that the `illuminate()` method is allowed as an interface
|
||||||
|
// requirement in Slang even though it is a generic. Constract that
|
||||||
|
// with C++ where a `template` method cannot be `virtual`.
|
||||||
|
};
|
||||||
|
|
||||||
|
// Given the `ILightEnv` interface, we can write up almost textbook
|
||||||
|
// definition of directional and point lights.
|
||||||
|
|
||||||
|
struct DirectionalLight : ILightEnv
|
||||||
|
{
|
||||||
|
float3 direction;
|
||||||
|
float3 intensity;
|
||||||
|
|
||||||
|
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||||
|
{
|
||||||
|
return intensity * brdf.evaluate(wo, direction, g.normal);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
struct PointLight : ILightEnv
|
||||||
|
{
|
||||||
|
float3 position;
|
||||||
|
float3 intensity;
|
||||||
|
|
||||||
|
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||||
|
{
|
||||||
|
float3 delta = position - g.position;
|
||||||
|
float d = length(delta);
|
||||||
|
float3 direction = normalize(delta);
|
||||||
|
float3 illuminance = intensity / (d*d);
|
||||||
|
return illuminance * brdf.evaluate(wo, direction, g.normal);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// In most cases, a shader entry point will only be specialized for a single
|
||||||
|
// material, but interesting rendering almost always needs multiple lights.
|
||||||
|
// For that reason we will next define types to represent *composite* lighting
|
||||||
|
// environment with multiple lights.
|
||||||
|
//
|
||||||
|
// A naive approach might be to have a single undifferntiated list of lights
|
||||||
|
// where any type of light may appear at any index, but this would lose all
|
||||||
|
// of the benefits of static specialization: we would have to perform dynamic
|
||||||
|
// branching to determine what kind of light is stored at each index.
|
||||||
|
//
|
||||||
|
// Instead, we will start with a type for *homogeneous* arrays of lights:
|
||||||
|
//
|
||||||
|
struct LightArray<L : ILightEnv, let N : int> : ILightEnv
|
||||||
|
{
|
||||||
|
// The `LightArray` type has two generic parameters:
|
||||||
|
//
|
||||||
|
// - `L` is a type parameter, representing the type of lights that will be in our array
|
||||||
|
// - `N` is a generic *value* parameter, representing the maximum number of lights allowed
|
||||||
|
//
|
||||||
|
// Slang's support for generic value parameters is currently experimental,
|
||||||
|
// and the syntax might change.
|
||||||
|
|
||||||
|
int count;
|
||||||
|
L lights[N];
|
||||||
|
|
||||||
|
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||||
|
{
|
||||||
|
// Our light array integrates illumination by naively summing
|
||||||
|
// contributions from all the lights in the array (up to `count`).
|
||||||
|
//
|
||||||
|
// A more advanced renderer might try apply sampling techniques
|
||||||
|
// to pick a subset of lights to sample.
|
||||||
|
//
|
||||||
|
float3 sum = 0;
|
||||||
|
for( int ii = 0; ii < count; ++ii )
|
||||||
|
{
|
||||||
|
sum += lights[ii].illuminate(g, brdf, wo);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// `LightArray` can handle multiple lights as long as they have the
|
||||||
|
// same type, but we need a way to have a scene with multiple lights
|
||||||
|
// of different types *without* losing static specialization.
|
||||||
|
//
|
||||||
|
// The `LightPair<T,U>` type supports this in about the simplest way
|
||||||
|
// possible, by aggregating a light (environment) of type `T` and
|
||||||
|
// one of type `U`. Those light environments might themselves be
|
||||||
|
// `LightArray`s or `LightPair`s, so that arbitrarily complex
|
||||||
|
// environments can be created from just these two composite types.
|
||||||
|
//
|
||||||
|
// This is probably a good place to insert a reminder the Slang's
|
||||||
|
// generics are *not* C++ templates, so that the error messages
|
||||||
|
// produced when working with these types are in general reasonable,
|
||||||
|
// and this is *not* any form of "template metaprogramming."
|
||||||
|
//
|
||||||
|
// That said, we expect that future versions of Slang will make
|
||||||
|
// defining composite types light this a bit less cumbersome.
|
||||||
|
//
|
||||||
|
struct LightPair<T : ILightEnv, U : ILightEnv> : ILightEnv
|
||||||
|
{
|
||||||
|
T first;
|
||||||
|
U second;
|
||||||
|
|
||||||
|
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||||
|
{
|
||||||
|
return first.illuminate(g, brdf, wo)
|
||||||
|
+ second.illuminate(g, brdf, wo);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// As a final (degenerate) case, we will define a light
|
||||||
|
// environment with *no* lights, which contributes no illumination.
|
||||||
|
//
|
||||||
|
struct EmptyLightEnv : ILightEnv
|
||||||
|
{
|
||||||
|
float3 illuminate<B:IBRDF>(SurfaceGeometry g, B brdf, float3 wo)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The code above constitutes the "shader library" for our
|
||||||
|
// application, while the code below this point is the
|
||||||
|
// implementation of a simple forward rendering pass
|
||||||
|
// using that library.
|
||||||
|
//
|
||||||
|
// While the shader library has used many of Slang's advanced
|
||||||
|
// mechanisms, the vertex and fragment shaders will be
|
||||||
|
// much more modest, and hopefully easier to follow.
|
||||||
|
|
||||||
|
|
||||||
|
// We will start with a `struct` for per-view parameters that
|
||||||
|
// will be allocated into a `ParameterBlock`.
|
||||||
|
//
|
||||||
|
// As written, this isn't very different from using an HLSL
|
||||||
|
// `cbuffer` declaration, but importantly this code will
|
||||||
|
// continue to work if we add one or more resources (e.g.,
|
||||||
|
// an enironment map texture) to the `PerView` type.
|
||||||
|
//
|
||||||
|
struct PerView
|
||||||
|
{
|
||||||
|
float4x4 viewProjection;
|
||||||
|
float3 eyePosition;
|
||||||
|
};
|
||||||
|
ParameterBlock<PerView> gViewParams;
|
||||||
|
|
||||||
|
// Declaring a block for per-model parameter data is
|
||||||
|
// similarly simple.
|
||||||
|
//
|
||||||
|
struct PerModel
|
||||||
|
{
|
||||||
|
float4x4 modelTransform;
|
||||||
|
float4x4 inverseTransposeModelTransform;
|
||||||
|
};
|
||||||
|
ParameterBlock<PerModel> gModelParams;
|
||||||
|
|
||||||
|
// We want our shader to work with any kind of lighting environment
|
||||||
|
// - that is, and type that implements `ILightEnv`. Furthermore,
|
||||||
|
// we want the parameters of that lighting environment to be passed
|
||||||
|
// as parameter block - `ParameterBlock<L>` for some type `L`.
|
||||||
|
//
|
||||||
|
// We handle this by defining a global generic type parameter for
|
||||||
|
// our shader, and constrainting it to implement `ILightEnv`...
|
||||||
|
//
|
||||||
|
type_param TLightEnv : ILightEnv;
|
||||||
|
//
|
||||||
|
// ... and then defining a parameter block that uses that type
|
||||||
|
// parameter as the "element type" of the block:
|
||||||
|
//
|
||||||
|
ParameterBlock<TLightEnv> gLightEnv;
|
||||||
|
|
||||||
|
// Our handling of the material parameter for our shader
|
||||||
|
// is quite similar to the case for the lighting environment:
|
||||||
|
//
|
||||||
|
type_param TMaterial : IMaterial;
|
||||||
|
ParameterBlock<TMaterial> gMaterial;
|
||||||
|
|
||||||
|
// Our vertex shader entry point is only marginally more
|
||||||
|
// complicated than the Hello World example. We will
|
||||||
|
// start by declaring the various "connector" `struct`s.
|
||||||
|
//
|
||||||
|
struct AssembledVertex
|
||||||
|
{
|
||||||
|
float3 position : POSITION;
|
||||||
|
float3 normal : NORMAL;
|
||||||
|
float2 uv : UV;
|
||||||
|
};
|
||||||
|
struct CoarseVertex
|
||||||
|
{
|
||||||
|
float3 worldPosition;
|
||||||
|
float3 worldNormal;
|
||||||
|
float2 uv;
|
||||||
|
};
|
||||||
|
struct VertexStageOutput
|
||||||
|
{
|
||||||
|
CoarseVertex coarseVertex : CoarseVertex;
|
||||||
|
float4 sv_position : SV_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Perhaps most interesting new feature of the entry
|
||||||
|
// point decalrations is that we use a `[shader(...)]`
|
||||||
|
// attribute (as introduced in HLSL Shader Model 6.x)
|
||||||
|
// in order to tag our entry points.
|
||||||
|
//
|
||||||
|
// This attribute informs the Slang compiler which
|
||||||
|
// functions are intended to be compiled as shader
|
||||||
|
// entry points (and what stage they target), so that
|
||||||
|
// the programmer no longer needs to specify the
|
||||||
|
// entry point name/stage through the API (or on
|
||||||
|
// the command line when using `slangc`).
|
||||||
|
//
|
||||||
|
// While HLSL added this feature only in newer versions,
|
||||||
|
// the Slang compiler supports this attribute across
|
||||||
|
// *all* targets, so that it is okay to use whether you
|
||||||
|
// want DXBC, DXIL, or SPIR-V output.
|
||||||
|
//
|
||||||
|
[shader("vertex")]
|
||||||
|
VertexStageOutput vertexMain(
|
||||||
|
AssembledVertex assembledVertex)
|
||||||
|
{
|
||||||
|
VertexStageOutput output;
|
||||||
|
|
||||||
|
float3 position = assembledVertex.position;
|
||||||
|
float3 normal = assembledVertex.normal;
|
||||||
|
float2 uv = assembledVertex.uv;
|
||||||
|
|
||||||
|
float3 worldPosition = mul(gModelParams.modelTransform, float4(position, 1.0)).xyz;
|
||||||
|
float3 worldNormal = mul(gModelParams.inverseTransposeModelTransform, float4(normal, 0.0)).xyz;
|
||||||
|
|
||||||
|
output.coarseVertex.worldPosition = worldPosition;
|
||||||
|
output.coarseVertex.worldNormal = worldNormal;
|
||||||
|
output.coarseVertex.uv = uv;
|
||||||
|
|
||||||
|
output.sv_position = mul(gViewParams.viewProjection, float4(worldPosition, 1.0));
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Our fragment shader is almost trivial, with the most interesting
|
||||||
|
// thing being how it uses the `TMaterial` type parameter (through the
|
||||||
|
// value stored in the `gMaterial` parameter block) to dispatch to
|
||||||
|
// the correct implementation of the `getDiffuseColor()` method
|
||||||
|
// in the `IMaterial` interface.
|
||||||
|
//
|
||||||
|
// The `gMaterial` parameter block declaration thus serves not only
|
||||||
|
// to group certain shader parameters for efficient CPU-to-GPU
|
||||||
|
// communication, but also to select the code that will execute
|
||||||
|
// in specialized versions of the `fragmentMain` entry point.
|
||||||
|
//
|
||||||
|
[shader("fragment")]
|
||||||
|
float4 fragmentMain(
|
||||||
|
CoarseVertex coarseVertex : CoarseVertex) : SV_Target
|
||||||
|
{
|
||||||
|
// We start by using our interpolated vertex attributes
|
||||||
|
// to construct the local surface geometry that we will
|
||||||
|
// use for material evaluation.
|
||||||
|
//
|
||||||
|
SurfaceGeometry g;
|
||||||
|
g.position = coarseVertex.worldPosition;
|
||||||
|
g.normal = normalize(coarseVertex.worldNormal);
|
||||||
|
g.uv = coarseVertex.uv;
|
||||||
|
|
||||||
|
float3 V = normalize(gViewParams.eyePosition - g.position);
|
||||||
|
|
||||||
|
// Next we prepare the material, which involves running
|
||||||
|
// any "pattern generation" logic of the material (e.g.,
|
||||||
|
// sampling and blending texture layers), to produce
|
||||||
|
// a BRDF suitable for evaluating under illumination
|
||||||
|
// from different light sources.
|
||||||
|
//
|
||||||
|
// Note that the return type here is `TMaterial.BRDF`,
|
||||||
|
// which is the `BRDF` type *associated* with the (unknown)
|
||||||
|
// `TMaterial` type. When `TMaterial` gets substituted for
|
||||||
|
// a concrete type later (e.g., `SimpleMaterial`) this
|
||||||
|
// will resolve to a concrete type too (e.g., `SimpleMaterial.BRDF`
|
||||||
|
// which is an alias for `BlinnPhong`).
|
||||||
|
//
|
||||||
|
TMaterial.BRDF brdf = gMaterial.prepare(g);
|
||||||
|
|
||||||
|
// Now that we've done the first step of material evaluation
|
||||||
|
// and sampled texture maps, etc., it is time to start
|
||||||
|
// integrating incident light at our surface point.
|
||||||
|
//
|
||||||
|
// Because we've wrapped up the lighting environment as
|
||||||
|
// a single (composite) object, this is as simple as calling
|
||||||
|
// its `illuminate()` method. Our particular fragment shader
|
||||||
|
// is thus abstracted from how the renderer chooses to structure
|
||||||
|
// this integration step, somewhat similar to how an
|
||||||
|
// `illuminance` loop in RenderMan Shading Language works.
|
||||||
|
//
|
||||||
|
|
||||||
|
float3 color = gLightEnv.illuminate(g, brdf, V);
|
||||||
|
|
||||||
|
return float4(color, 1);
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
@@ -3,9 +3,65 @@
|
|||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
|
|
||||||
Asset::Asset()
|
Asset::Asset()
|
||||||
|
: fullPath("")
|
||||||
|
, name("")
|
||||||
|
, parentDir("")
|
||||||
|
, extension("")
|
||||||
|
, status(Status::Uninitialized)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
Asset::Asset(const std::filesystem::path& path)
|
||||||
|
: fullPath(std::filesystem::absolute(path))
|
||||||
|
, status(Status::Uninitialized)
|
||||||
|
{
|
||||||
|
fullPath.make_preferred();
|
||||||
|
parentDir = fullPath.parent_path();
|
||||||
|
name = fullPath.stem();
|
||||||
|
extension = fullPath.extension();
|
||||||
|
}
|
||||||
|
Asset::Asset(const std::string &fullPath)
|
||||||
|
: Asset(std::filesystem::path(fullPath))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Asset::Asset(const std::string &directory, const std::string &fileName)
|
||||||
|
: Asset(std::filesystem::path(directory + fileName))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Asset::~Asset()
|
Asset::~Asset()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::ifstream &Asset::getReadStream()
|
||||||
|
{
|
||||||
|
if(inStream.is_open())
|
||||||
|
{
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
inStream.open(fullPath);
|
||||||
|
return inStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream &Asset::getWriteStream()
|
||||||
|
{
|
||||||
|
if(outStream.is_open())
|
||||||
|
{
|
||||||
|
return outStream;
|
||||||
|
}
|
||||||
|
outStream.open(fullPath);
|
||||||
|
return outStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Asset::getFileName()
|
||||||
|
{
|
||||||
|
return name.generic_string();
|
||||||
|
}
|
||||||
|
std::string Asset::getFullPath()
|
||||||
|
{
|
||||||
|
return fullPath.generic_string();
|
||||||
|
}
|
||||||
|
std::string Asset::getExtension()
|
||||||
|
{
|
||||||
|
return extension.generic_string();
|
||||||
|
}
|
||||||
@@ -6,10 +6,47 @@ namespace Seele
|
|||||||
class Asset
|
class Asset
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum class Status
|
||||||
|
{
|
||||||
|
Uninitialized,
|
||||||
|
Loading,
|
||||||
|
Ready
|
||||||
|
};
|
||||||
Asset();
|
Asset();
|
||||||
|
Asset(const std::filesystem::path& path);
|
||||||
|
Asset(const std::string& directory, const std::string& name);
|
||||||
|
Asset(const std::string& fullPath);
|
||||||
virtual ~Asset();
|
virtual ~Asset();
|
||||||
|
std::ifstream& getReadStream();
|
||||||
|
std::ofstream& getWriteStream();
|
||||||
|
|
||||||
|
// returns the name of the file, without extension
|
||||||
|
std::string getFileName();
|
||||||
|
// returns the full absolute path, from root to extension
|
||||||
|
std::string getFullPath();
|
||||||
|
// returns the file extension, without preceding dot
|
||||||
|
std::string getExtension();
|
||||||
|
inline Status getStatus()
|
||||||
|
{
|
||||||
|
std::scoped_lock lck(lock);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
inline void setStatus(Status status)
|
||||||
|
{
|
||||||
|
std::scoped_lock lck(lock);
|
||||||
|
this->status = status;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
std::mutex lock;
|
||||||
private:
|
private:
|
||||||
|
Status status;
|
||||||
|
std::filesystem::path fullPath;
|
||||||
|
std::filesystem::path parentDir;
|
||||||
|
std::filesystem::path name;
|
||||||
|
std::filesystem::path extension;
|
||||||
|
uint32 byteSize;
|
||||||
|
std::ifstream inStream;
|
||||||
|
std::ofstream outStream;
|
||||||
};
|
};
|
||||||
DEFINE_REF(Asset);
|
DEFINE_REF(Asset);
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
#include "AssetRegistry.h"
|
||||||
|
#include "MeshAsset.h"
|
||||||
|
#include "TextureAsset.h"
|
||||||
|
#include "TextureLoader.h"
|
||||||
|
#include "MaterialLoader.h"
|
||||||
|
#include "MeshLoader.h"
|
||||||
|
#include "Material/Material.h"
|
||||||
|
#include "Graphics/Graphics.h"
|
||||||
|
#include "graphics/WindowManager.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
AssetRegistry::~AssetRegistry()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetRegistry::init(const std::string& rootFolder)
|
||||||
|
{
|
||||||
|
get().init(rootFolder, WindowManager::getGraphics());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetRegistry::importFile(const std::string &filePath)
|
||||||
|
{
|
||||||
|
std::string extension = filePath.substr(filePath.find_last_of(".") + 1);
|
||||||
|
std::cout << extension << std::endl;
|
||||||
|
if (extension.compare("fbx") == 0
|
||||||
|
|| extension.compare("obj") == 0)
|
||||||
|
{
|
||||||
|
get().registerMesh(filePath);
|
||||||
|
}
|
||||||
|
if (extension.compare("png") == 0
|
||||||
|
|| extension.compare("jpg") == 0)
|
||||||
|
{
|
||||||
|
get().registerTexture(filePath);
|
||||||
|
}
|
||||||
|
if (extension.compare("semat") == 0)
|
||||||
|
{
|
||||||
|
get().registerMaterial(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PMeshAsset AssetRegistry::findMesh(const std::string &filePath)
|
||||||
|
{
|
||||||
|
return get().meshes[filePath];
|
||||||
|
}
|
||||||
|
|
||||||
|
PMaterialAsset AssetRegistry::findMaterial(const std::string &filePath)
|
||||||
|
{
|
||||||
|
return get().materials[filePath];
|
||||||
|
}
|
||||||
|
|
||||||
|
PTextureAsset AssetRegistry::findTexture(const std::string &filePath)
|
||||||
|
{
|
||||||
|
return get().textures[filePath];
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetRegistry &AssetRegistry::get()
|
||||||
|
{
|
||||||
|
static AssetRegistry instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
AssetRegistry::AssetRegistry()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetRegistry::init(const std::string &rootFolder, Gfx::PGraphics graphics)
|
||||||
|
{
|
||||||
|
AssetRegistry ® = get();
|
||||||
|
reg.rootFolder = rootFolder;
|
||||||
|
reg.meshLoader = new MeshLoader(graphics);
|
||||||
|
reg.textureLoader = new TextureLoader(graphics);
|
||||||
|
reg.materialLoader = new MaterialLoader(graphics);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetRegistry::registerMesh(const std::string &filePath)
|
||||||
|
{
|
||||||
|
meshLoader->importAsset(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetRegistry::registerTexture(const std::string &filePath)
|
||||||
|
{
|
||||||
|
textureLoader->importAsset(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AssetRegistry::registerMaterial(const std::string &filePath)
|
||||||
|
{
|
||||||
|
materialLoader->queueAsset(filePath);
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "Asset.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
DECLARE_REF(TextureLoader);
|
||||||
|
DECLARE_REF(MeshLoader);
|
||||||
|
DECLARE_REF(MaterialLoader);
|
||||||
|
DECLARE_REF(TextureAsset);
|
||||||
|
DECLARE_REF(MeshAsset);
|
||||||
|
DECLARE_REF(MaterialAsset);
|
||||||
|
DECLARE_NAME_REF(Gfx, Graphics);
|
||||||
|
class AssetRegistry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~AssetRegistry();
|
||||||
|
static void init(const std::string& rootFolder);
|
||||||
|
|
||||||
|
static void importFile(const std::string& filePath);
|
||||||
|
|
||||||
|
static PMeshAsset findMesh(const std::string& filePath);
|
||||||
|
static PTextureAsset findTexture(const std::string& filePath);
|
||||||
|
static PMaterialAsset findMaterial(const std::string& filePath);
|
||||||
|
private:
|
||||||
|
static AssetRegistry& get();
|
||||||
|
|
||||||
|
AssetRegistry();
|
||||||
|
void init(const std::string& rootFolder, Gfx::PGraphics graphics);
|
||||||
|
|
||||||
|
void registerMesh(const std::string& filePath);
|
||||||
|
void registerTexture(const std::string& filePath);
|
||||||
|
void registerMaterial(const std::string& filePath);
|
||||||
|
|
||||||
|
std::string rootFolder;
|
||||||
|
Map<std::string, PTextureAsset> textures;
|
||||||
|
Map<std::string, PMeshAsset> meshes;
|
||||||
|
Map<std::string, PMaterialAsset> materials;
|
||||||
|
UPTextureLoader textureLoader;
|
||||||
|
UPMeshLoader meshLoader;
|
||||||
|
UPMaterialLoader materialLoader;
|
||||||
|
friend class TextureLoader;
|
||||||
|
friend class MaterialLoader;
|
||||||
|
friend class MeshLoader;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -2,5 +2,15 @@ target_sources(SeeleEngine
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
Asset.h
|
Asset.h
|
||||||
Asset.cpp
|
Asset.cpp
|
||||||
FileAsset.h
|
AssetRegistry.h
|
||||||
FileAsset.cpp)
|
AssetRegistry.cpp
|
||||||
|
MaterialLoader.h
|
||||||
|
MaterialLoader.cpp
|
||||||
|
MeshAsset.h
|
||||||
|
MeshAsset.cpp
|
||||||
|
MeshLoader.h
|
||||||
|
MeshLoader.cpp
|
||||||
|
TextureAsset.h
|
||||||
|
TextureAsset.cpp
|
||||||
|
TextureLoader.h
|
||||||
|
TextureLoader.cpp)
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
#include "FileAsset.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
|
|
||||||
FileAsset::FileAsset()
|
|
||||||
: path("")
|
|
||||||
, name("")
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FileAsset::FileAsset(const std::string &fullPath)
|
|
||||||
: path(fullPath)
|
|
||||||
{
|
|
||||||
name = fullPath.substr(fullPath.find_last_of('\\')+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FileAsset::FileAsset(const std::string &directory, const std::string &name)
|
|
||||||
: path(directory+name)
|
|
||||||
, name(name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FileAsset::~FileAsset()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ifstream &FileAsset::getReadStream()
|
|
||||||
{
|
|
||||||
if(inStream.is_open())
|
|
||||||
{
|
|
||||||
return inStream;
|
|
||||||
}
|
|
||||||
inStream.open(path);
|
|
||||||
return inStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ofstream &FileAsset::getWriteStream()
|
|
||||||
{
|
|
||||||
if(outStream.is_open())
|
|
||||||
{
|
|
||||||
return outStream;
|
|
||||||
}
|
|
||||||
outStream.open(path);
|
|
||||||
return outStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FileAsset::rename(const std::string& newName)
|
|
||||||
{
|
|
||||||
if(inStream.is_open())
|
|
||||||
{
|
|
||||||
inStream.close();
|
|
||||||
}
|
|
||||||
if(outStream.is_open())
|
|
||||||
{
|
|
||||||
outStream.flush();
|
|
||||||
outStream.close();
|
|
||||||
}
|
|
||||||
path.replace(path.find_last_of(name), name.size(), newName);
|
|
||||||
name = newName;
|
|
||||||
inStream.open(path);
|
|
||||||
outStream.open(path);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "Asset.h"
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
namespace Seele
|
|
||||||
{
|
|
||||||
class FileAsset
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FileAsset();
|
|
||||||
FileAsset(const std::string& directory, const std::string& name);
|
|
||||||
FileAsset(const std::string& fullPath);
|
|
||||||
virtual ~FileAsset();
|
|
||||||
std::ifstream& getReadStream();
|
|
||||||
std::ofstream& getWriteStream();
|
|
||||||
void rename(const std::string& newName);
|
|
||||||
private:
|
|
||||||
std::string name;
|
|
||||||
std::string path;
|
|
||||||
uint32 byteSize;
|
|
||||||
std::ifstream inStream;
|
|
||||||
std::ofstream outStream;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include "MaterialLoader.h"
|
||||||
|
#include "Material/Material.h"
|
||||||
|
#include "Graphics/Graphics.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
MaterialLoader::MaterialLoader(Gfx::PGraphics graphics)
|
||||||
|
{
|
||||||
|
placeholderMaterial = new Material("shaders/Placeholder.semat");
|
||||||
|
placeholderMaterial->compile();
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialLoader::~MaterialLoader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PMaterial MaterialLoader::queueAsset(const std::string& filePath)
|
||||||
|
{
|
||||||
|
PMaterial result = new Material(filePath);
|
||||||
|
//TODO
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "Containers/List.h"
|
||||||
|
#include <thread>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
DECLARE_REF(Material)
|
||||||
|
DECLARE_NAME_REF(Gfx, Graphics);
|
||||||
|
class MaterialLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MaterialLoader(Gfx::PGraphics graphic);
|
||||||
|
~MaterialLoader();
|
||||||
|
PMaterial queueAsset(const std::string& filePath);
|
||||||
|
private:
|
||||||
|
List<std::future<void>> futures;
|
||||||
|
PMaterial placeholderMaterial;
|
||||||
|
};
|
||||||
|
DEFINE_REF(MaterialLoader);
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#include "MeshAsset.h"
|
||||||
|
#include "Graphics/Mesh.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
|
||||||
|
MeshAsset::MeshAsset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
MeshAsset::MeshAsset(const std::string& directory, const std::string& name)
|
||||||
|
: Asset(directory, name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
MeshAsset::MeshAsset(const std::string& fullPath)
|
||||||
|
: Asset(fullPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Asset.h"
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
DECLARE_REF(Mesh);
|
||||||
|
class MeshAsset : public Asset
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MeshAsset();
|
||||||
|
MeshAsset(const std::string& directory, const std::string& name);
|
||||||
|
MeshAsset(const std::string& fullPath);
|
||||||
|
void setMesh(PMesh mesh)
|
||||||
|
{
|
||||||
|
std::scoped_lock lck(lock);
|
||||||
|
this->mesh = mesh;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
PMesh mesh;
|
||||||
|
};
|
||||||
|
DEFINE_REF(MeshAsset);
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#include "MeshLoader.h"
|
||||||
|
#include "Graphics/Graphics.h"
|
||||||
|
#include "MeshAsset.h"
|
||||||
|
#include "Graphics/Mesh.h"
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <assimp/postprocess.h>
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
MeshLoader::MeshLoader(Gfx::PGraphics graphics)
|
||||||
|
: graphics(graphics)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshLoader::~MeshLoader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshLoader::importAsset(const std::string& path)
|
||||||
|
{
|
||||||
|
futures.add(std::async(std::launch::async, &MeshLoader::import, this, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
void findMeshRoots(aiNode* node, List<aiNode*>& meshNodes)
|
||||||
|
{
|
||||||
|
if(node->mNumMeshes > 0)
|
||||||
|
{
|
||||||
|
meshNodes.add(node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(uint32 i = 0; i < node->mNumChildren; ++i)
|
||||||
|
{
|
||||||
|
findMeshRoots(node->mChildren[i], meshNodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshLoader::import(const std::string& path)
|
||||||
|
{
|
||||||
|
PMeshAsset asset = new MeshAsset(path);
|
||||||
|
asset->setStatus(Asset::Status::Loading);
|
||||||
|
Assimp::Importer importer;
|
||||||
|
const aiScene* scene = importer.ReadFile(path.c_str(),
|
||||||
|
aiProcess_CalcTangentSpace |
|
||||||
|
aiProcess_FlipUVs |
|
||||||
|
aiProcess_ImproveCacheLocality |
|
||||||
|
aiProcess_OptimizeMeshes |
|
||||||
|
aiProcess_GenBoundingBoxes |
|
||||||
|
aiProcessPreset_TargetRealtime_Fast);
|
||||||
|
|
||||||
|
List<aiNode*> meshNodes;
|
||||||
|
findMeshRoots(scene->mRootNode, meshNodes);
|
||||||
|
for(auto meshNode : meshNodes)
|
||||||
|
{
|
||||||
|
std::cout << "Test:" << meshNode->mNumMeshes << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
PMesh mesh = new Mesh(nullptr, nullptr);
|
||||||
|
asset->setMesh(mesh);
|
||||||
|
asset->setStatus(Asset::Status::Ready);
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "Containers/List.h"
|
||||||
|
#include <thread>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
DECLARE_REF(MeshAsset)
|
||||||
|
DECLARE_NAME_REF(Gfx, Graphics);
|
||||||
|
class MeshLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MeshLoader(Gfx::PGraphics graphic);
|
||||||
|
~MeshLoader();
|
||||||
|
void importAsset(const std::string& filePath);
|
||||||
|
private:
|
||||||
|
void import(const std::string& path);
|
||||||
|
List<std::future<void>> futures;
|
||||||
|
Gfx::PGraphics graphics;
|
||||||
|
};
|
||||||
|
DEFINE_REF(MeshLoader);
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#include "TextureAsset.h"
|
||||||
|
#include "Graphics/GraphicsResources.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
|
||||||
|
TextureAsset::TextureAsset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
TextureAsset::TextureAsset(const std::string& directory, const std::string& name)
|
||||||
|
: Asset(directory, name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
TextureAsset::TextureAsset(const std::string& fullPath)
|
||||||
|
: Asset(fullPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#include "Asset.h"
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
DECLARE_NAME_REF(Gfx, Texture);
|
||||||
|
class TextureAsset : public Asset
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextureAsset();
|
||||||
|
TextureAsset(const std::string& directory, const std::string& name);
|
||||||
|
TextureAsset(const std::string& fullPath);
|
||||||
|
void setTexture(Gfx::PTexture texture)
|
||||||
|
{
|
||||||
|
std::scoped_lock lck(lock);
|
||||||
|
this->texture = texture;
|
||||||
|
}
|
||||||
|
Gfx::PTexture getTexture()
|
||||||
|
{
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Gfx::PTexture texture;
|
||||||
|
};
|
||||||
|
DEFINE_REF(TextureAsset);
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#include "TextureLoader.h"
|
||||||
|
#include "TextureAsset.h"
|
||||||
|
#include "Graphics/Graphics.h"
|
||||||
|
#include "AssetRegistry.h"
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include <stb_image.h>
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
TextureLoader::TextureLoader(Gfx::PGraphics graphics)
|
||||||
|
: graphics(graphics)
|
||||||
|
{
|
||||||
|
import("./textures/placeholder.png");
|
||||||
|
placeholderTexture = AssetRegistry::findTexture("./textures/placeholder.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureLoader::~TextureLoader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureLoader::importAsset(const std::string& filePath)
|
||||||
|
{
|
||||||
|
futures.add(std::async(std::launch::async, &TextureLoader::import, this, filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureLoader::import(const std::string& path)
|
||||||
|
{
|
||||||
|
PTextureAsset asset = new TextureAsset(path);
|
||||||
|
AssetRegistry::get().textures[path] = asset;
|
||||||
|
asset->setStatus(Asset::Status::Loading);
|
||||||
|
int x, y, n;
|
||||||
|
const std::string fullPath = std::string(asset->getFullPath());
|
||||||
|
unsigned char* data = stbi_load(fullPath.c_str(), &x, &y, &n, 0);
|
||||||
|
TextureCreateInfo createInfo;
|
||||||
|
createInfo.resourceData.data = data;
|
||||||
|
createInfo.resourceData.size = x * y * n * sizeof(unsigned char);
|
||||||
|
createInfo.width = x;
|
||||||
|
createInfo.height = y;
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
createInfo.format = Gfx::SE_FORMAT_R8_UINT;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
createInfo.format = Gfx::SE_FORMAT_R8G8_UINT;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
createInfo.format = Gfx::SE_FORMAT_R8G8B8_UINT;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
createInfo.format = Gfx::SE_FORMAT_R8G8B8A8_UINT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
createInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||||
|
Gfx::PTexture2D texture = graphics->createTexture2D(createInfo);
|
||||||
|
texture->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||||
|
asset->setTexture(texture);
|
||||||
|
asset->setStatus(Asset::Status::Ready);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "Containers/List.h"
|
||||||
|
#include <thread>
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
DECLARE_REF(TextureAsset);
|
||||||
|
DECLARE_NAME_REF(Gfx, Graphics);
|
||||||
|
class TextureLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextureLoader(Gfx::PGraphics graphic);
|
||||||
|
~TextureLoader();
|
||||||
|
void importAsset(const std::string& filePath);
|
||||||
|
private:
|
||||||
|
void import(const std::string& path);
|
||||||
|
Gfx::PGraphics graphics;
|
||||||
|
List<std::future<void>> futures;
|
||||||
|
PTextureAsset placeholderTexture;
|
||||||
|
};
|
||||||
|
DEFINE_REF(TextureLoader);
|
||||||
|
} // namespace Seele
|
||||||
@@ -385,6 +385,11 @@ public:
|
|||||||
assert(index >= 0 && index < N);
|
assert(index >= 0 && index < N);
|
||||||
return _data[index];
|
return _data[index];
|
||||||
}
|
}
|
||||||
|
const T &operator[](int index) const
|
||||||
|
{
|
||||||
|
assert(index >= 0 && index < N);
|
||||||
|
return _data[index];
|
||||||
|
}
|
||||||
|
|
||||||
template <typename X>
|
template <typename X>
|
||||||
class IteratorBase
|
class IteratorBase
|
||||||
|
|||||||
@@ -132,6 +132,24 @@ public:
|
|||||||
size++;
|
size++;
|
||||||
return insertedElement;
|
return insertedElement;
|
||||||
}
|
}
|
||||||
|
Iterator add(T&& value)
|
||||||
|
{
|
||||||
|
if (root == nullptr)
|
||||||
|
{
|
||||||
|
root = new Node();
|
||||||
|
tail = root;
|
||||||
|
}
|
||||||
|
tail->data = std::move(value);
|
||||||
|
Node *newTail = new Node();
|
||||||
|
newTail->prev = tail;
|
||||||
|
newTail->next = nullptr;
|
||||||
|
tail->next = newTail;
|
||||||
|
Iterator insertedElement(tail);
|
||||||
|
tail = newTail;
|
||||||
|
refreshIterators();
|
||||||
|
size++;
|
||||||
|
return insertedElement;
|
||||||
|
}
|
||||||
Iterator remove(Iterator pos)
|
Iterator remove(Iterator pos)
|
||||||
{
|
{
|
||||||
size--;
|
size--;
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ public:
|
|||||||
Node *node;
|
Node *node;
|
||||||
Array<Node *> traversal;
|
Array<Node *> traversal;
|
||||||
};
|
};
|
||||||
|
|
||||||
V &operator[](const K &key)
|
V &operator[](const K &key)
|
||||||
{
|
{
|
||||||
root = splay(root, key);
|
root = splay(root, key);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
target_sources(SeeleEngine
|
target_sources(SeeleEngine
|
||||||
PRIVATE
|
PRIVATE
|
||||||
ForwardPlusRenderPath.h
|
|
||||||
ForwardPlusRenderPath.cpp
|
|
||||||
GraphicsResources.h
|
GraphicsResources.h
|
||||||
GraphicsResources.cpp
|
GraphicsResources.cpp
|
||||||
GraphicsInitializer.h
|
GraphicsInitializer.h
|
||||||
@@ -10,6 +8,7 @@ target_sources(SeeleEngine
|
|||||||
Graphics.cpp
|
Graphics.cpp
|
||||||
Mesh.h
|
Mesh.h
|
||||||
Mesh.cpp
|
Mesh.cpp
|
||||||
|
MeshBatch.h
|
||||||
RenderCore.h
|
RenderCore.h
|
||||||
RenderCore.cpp
|
RenderCore.cpp
|
||||||
RenderPath.h
|
RenderPath.h
|
||||||
@@ -25,4 +24,5 @@ target_sources(SeeleEngine
|
|||||||
WindowManager.h
|
WindowManager.h
|
||||||
WindowManager.cpp)
|
WindowManager.cpp)
|
||||||
|
|
||||||
|
add_subdirectory(RenderPass/)
|
||||||
add_subdirectory(Vulkan/)
|
add_subdirectory(Vulkan/)
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
#include "ForwardPlusRenderPath.h"
|
|
||||||
#include "Scene/Scene.h"
|
|
||||||
#include "Material/MaterialInstance.h"
|
|
||||||
#include "Material/Material.h"
|
|
||||||
#include "GraphicsResources.h"
|
|
||||||
|
|
||||||
using namespace Seele;
|
|
||||||
|
|
||||||
Seele::ForwardPlusRenderPath::ForwardPlusRenderPath(Gfx::PGraphics graphics, Gfx::PViewport viewport)
|
|
||||||
: SceneRenderPath(graphics, viewport)
|
|
||||||
{
|
|
||||||
PMaterial material = new Material("D:\\Private\\Programming\\C++\\Seele\\test.mat");
|
|
||||||
material->compile();
|
|
||||||
}
|
|
||||||
|
|
||||||
Seele::ForwardPlusRenderPath::~ForwardPlusRenderPath()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Seele::ForwardPlusRenderPath::beginFrame()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Seele::ForwardPlusRenderPath::render()
|
|
||||||
{
|
|
||||||
for (auto entry : scene->getMeshBatches())
|
|
||||||
{
|
|
||||||
PMaterial material = entry.key;
|
|
||||||
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
|
|
||||||
renderCommand->bindPipeline(material->getPipeline());
|
|
||||||
for (auto drawState : entry.value.instances)
|
|
||||||
{
|
|
||||||
renderCommand->bindVertexBuffer(drawState.vertexBuffer);
|
|
||||||
renderCommand->bindIndexBuffer(drawState.indexBuffer);
|
|
||||||
renderCommand->bindDescriptor(drawState.instance->getDescriptor());
|
|
||||||
renderCommand->draw(drawState);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Seele::ForwardPlusRenderPath::endFrame()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "SceneRenderPath.h"
|
|
||||||
|
|
||||||
namespace Seele
|
|
||||||
{
|
|
||||||
class ForwardPlusRenderPath : public SceneRenderPath
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ForwardPlusRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
|
|
||||||
virtual ~ForwardPlusRenderPath();
|
|
||||||
virtual void beginFrame() override;
|
|
||||||
virtual void render() override;
|
|
||||||
virtual void endFrame() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
||||||
} // namespace Seele
|
|
||||||
@@ -13,6 +13,12 @@ public:
|
|||||||
Graphics();
|
Graphics();
|
||||||
virtual ~Graphics();
|
virtual ~Graphics();
|
||||||
virtual void init(GraphicsInitializer initializer) = 0;
|
virtual void init(GraphicsInitializer initializer) = 0;
|
||||||
|
|
||||||
|
const QueueFamilyMapping getFamilyMapping() const
|
||||||
|
{
|
||||||
|
return queueMapping;
|
||||||
|
}
|
||||||
|
|
||||||
virtual PWindow createWindow(const WindowCreateInfo &createInfo) = 0;
|
virtual PWindow createWindow(const WindowCreateInfo &createInfo) = 0;
|
||||||
virtual PViewport createViewport(PWindow owner, const ViewportCreateInfo &createInfo) = 0;
|
virtual PViewport createViewport(PWindow owner, const ViewportCreateInfo &createInfo) = 0;
|
||||||
|
|
||||||
@@ -28,8 +34,18 @@ public:
|
|||||||
virtual PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) = 0;
|
virtual PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) = 0;
|
||||||
virtual PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) = 0;
|
virtual PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) = 0;
|
||||||
virtual PRenderCommand createRenderCommand() = 0;
|
virtual PRenderCommand createRenderCommand() = 0;
|
||||||
|
virtual PVertexShader createVertexShader(const ShaderCreateInfo& createInfo) = 0;
|
||||||
|
virtual PControlShader createControlShader(const ShaderCreateInfo& createInfo) = 0;
|
||||||
|
virtual PEvaluationShader createEvaluationShader(const ShaderCreateInfo& createInfo) = 0;
|
||||||
|
virtual PGeometryShader createGeometryShader(const ShaderCreateInfo& createInfo) = 0;
|
||||||
|
virtual PFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) = 0;
|
||||||
virtual PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) = 0;
|
virtual PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) = 0;
|
||||||
|
|
||||||
|
virtual Gfx::PDescriptorLayout createDescriptorLayout() = 0;
|
||||||
|
virtual Gfx::PPipelineLayout createPipelineLayout() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
QueueFamilyMapping queueMapping;
|
||||||
friend class Window;
|
friend class Window;
|
||||||
};
|
};
|
||||||
DEFINE_REF(Graphics);
|
DEFINE_REF(Graphics);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
#include "GraphicsEnums.h"
|
#include "GraphicsEnums.h"
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
@@ -42,8 +43,20 @@ struct ViewportCreateInfo
|
|||||||
uint32 offsetX;
|
uint32 offsetX;
|
||||||
uint32 offsetY;
|
uint32 offsetY;
|
||||||
};
|
};
|
||||||
|
// doesnt own the data, only proxy it
|
||||||
|
struct BulkResourceData
|
||||||
|
{
|
||||||
|
uint32 size;
|
||||||
|
uint8 *data;
|
||||||
|
Gfx::QueueType owner;
|
||||||
|
BulkResourceData()
|
||||||
|
: size(0), data(nullptr), owner(Gfx::QueueType::GRAPHICS)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
struct TextureCreateInfo
|
struct TextureCreateInfo
|
||||||
{
|
{
|
||||||
|
BulkResourceData resourceData;
|
||||||
uint32 width;
|
uint32 width;
|
||||||
uint32 height;
|
uint32 height;
|
||||||
uint32 depth;
|
uint32 depth;
|
||||||
@@ -53,20 +66,10 @@ struct TextureCreateInfo
|
|||||||
uint32 samples;
|
uint32 samples;
|
||||||
Gfx::SeFormat format;
|
Gfx::SeFormat format;
|
||||||
Gfx::SeImageUsageFlagBits usage;
|
Gfx::SeImageUsageFlagBits usage;
|
||||||
Gfx::QueueType queueType;
|
|
||||||
TextureCreateInfo()
|
TextureCreateInfo()
|
||||||
: width(1), height(1), depth(1), bArray(false), arrayLayers(1), mipLevels(1), samples(1), format(Gfx::SE_FORMAT_R32G32B32A32_SFLOAT), queueType(Gfx::QueueType::GRAPHICS), usage(Gfx::SE_IMAGE_USAGE_SAMPLED_BIT)
|
: resourceData(), width(1), height(1), depth(1), bArray(false), arrayLayers(1)
|
||||||
{
|
, mipLevels(1), samples(1), format(Gfx::SE_FORMAT_R32G32B32A32_SFLOAT)
|
||||||
}
|
, usage(Gfx::SE_IMAGE_USAGE_SAMPLED_BIT)
|
||||||
};
|
|
||||||
// doesnt own the data, only proxy it
|
|
||||||
struct BulkResourceData
|
|
||||||
{
|
|
||||||
uint32 size;
|
|
||||||
uint8 *data;
|
|
||||||
Gfx::QueueType owner;
|
|
||||||
BulkResourceData()
|
|
||||||
: size(0), data(nullptr), owner(Gfx::QueueType::GRAPHICS)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -90,6 +93,15 @@ struct IndexBufferCreateInfo
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
struct ShaderCreateInfo
|
||||||
|
{
|
||||||
|
std::string code;
|
||||||
|
std::string entryPoint;
|
||||||
|
Array<const char*> typeParameter;
|
||||||
|
ShaderCreateInfo(const std::string& code)
|
||||||
|
: code(code)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
@@ -101,6 +113,10 @@ struct SePushConstantRange
|
|||||||
};
|
};
|
||||||
struct VertexElement
|
struct VertexElement
|
||||||
{
|
{
|
||||||
|
VertexElement(){}
|
||||||
|
VertexElement(uint32 location, SeFormat vertexFormat, uint32 offset)
|
||||||
|
: location(location), vertexFormat(vertexFormat), offset(offset)
|
||||||
|
{}
|
||||||
uint32 location;
|
uint32 location;
|
||||||
SeFormat vertexFormat;
|
SeFormat vertexFormat;
|
||||||
uint32 offset;
|
uint32 offset;
|
||||||
@@ -173,7 +189,6 @@ struct GraphicsPipelineCreateInfo
|
|||||||
Gfx::PEvaluationShader evalShader;
|
Gfx::PEvaluationShader evalShader;
|
||||||
Gfx::PGeometryShader geometryShader;
|
Gfx::PGeometryShader geometryShader;
|
||||||
Gfx::PFragmentShader fragmentShader;
|
Gfx::PFragmentShader fragmentShader;
|
||||||
Gfx::PPipelineLayout pipelineLayout;
|
|
||||||
Gfx::PRenderPass renderPass;
|
Gfx::PRenderPass renderPass;
|
||||||
Gfx::SePrimitiveTopology topology;
|
Gfx::SePrimitiveTopology topology;
|
||||||
Gfx::RasterizationState rasterizationState;
|
Gfx::RasterizationState rasterizationState;
|
||||||
@@ -183,6 +198,23 @@ struct GraphicsPipelineCreateInfo
|
|||||||
GraphicsPipelineCreateInfo()
|
GraphicsPipelineCreateInfo()
|
||||||
{
|
{
|
||||||
std::memset(this, 0, sizeof(*this));
|
std::memset(this, 0, sizeof(*this));
|
||||||
|
topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||||
|
rasterizationState.cullMode = Gfx::SE_CULL_MODE_BACK_BIT;
|
||||||
|
rasterizationState.polygonMode = Gfx::SE_POLYGON_MODE_FILL;
|
||||||
|
rasterizationState.frontFace = Gfx::SE_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||||
|
depthStencilState.depthCompareOp = Gfx::SE_COMPARE_OP_LESS;
|
||||||
|
depthStencilState.minDepthBounds = 0.0f;
|
||||||
|
depthStencilState.maxDepthBounds = 1.0f;
|
||||||
|
depthStencilState.stencilTestEnable = false;
|
||||||
|
depthStencilState.depthWriteEnable = true;
|
||||||
|
depthStencilState.depthTestEnable = true;
|
||||||
|
multisampleState.samples = 1;
|
||||||
|
colorBlend.attachmentCount = 0;
|
||||||
|
colorBlend.logicOpEnable = false;
|
||||||
|
colorBlend.blendConstants[0] = 1.0f;
|
||||||
|
colorBlend.blendConstants[1] = 1.0f;
|
||||||
|
colorBlend.blendConstants[2] = 1.0f;
|
||||||
|
colorBlend.blendConstants[3] = 1.0f;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "GraphicsResources.h"
|
#include "GraphicsResources.h"
|
||||||
#include "Material/MaterialInstance.h"
|
#include "Material/MaterialInstance.h"
|
||||||
|
#include "Graphics.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Gfx;
|
using namespace Seele::Gfx;
|
||||||
@@ -56,22 +57,60 @@ void PipelineLayout::addPushConstants(const SePushConstantRange &pushConstant)
|
|||||||
pushConstants.add(pushConstant);
|
pushConstants.add(pushConstant);
|
||||||
}
|
}
|
||||||
|
|
||||||
UniformBuffer::UniformBuffer()
|
QueueOwnedResource::QueueOwnedResource(PGraphics graphics, QueueType startQueueType)
|
||||||
|
: graphics(graphics)
|
||||||
|
, currentOwner(startQueueType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueOwnedResource::~QueueOwnedResource()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueueOwnedResource::transferOwnership(QueueType newOwner)
|
||||||
|
{
|
||||||
|
if(graphics->getFamilyMapping().needsTransfer(currentOwner, newOwner))
|
||||||
|
{
|
||||||
|
executeOwnershipBarrier(newOwner);
|
||||||
|
currentOwner = newOwner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::Buffer(PGraphics graphics, QueueType startQueue)
|
||||||
|
: QueueOwnedResource(graphics, startQueue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer::~Buffer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
UniformBuffer::UniformBuffer(PGraphics graphics, QueueType startQueueType)
|
||||||
|
: Buffer(graphics, startQueueType)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
UniformBuffer::~UniformBuffer()
|
UniformBuffer::~UniformBuffer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
VertexBuffer::VertexBuffer(uint32 numVertices, uint32 vertexSize)
|
StructuredBuffer::StructuredBuffer(PGraphics graphics, QueueType startQueueType)
|
||||||
: numVertices(numVertices), vertexSize(vertexSize)
|
: Buffer(graphics, startQueueType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
StructuredBuffer::~StructuredBuffer()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
VertexBuffer::VertexBuffer(PGraphics graphics, uint32 numVertices, uint32 vertexSize, QueueType startQueueType)
|
||||||
|
: Buffer(graphics, startQueueType)
|
||||||
|
, numVertices(numVertices), vertexSize(vertexSize)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
VertexBuffer::~VertexBuffer()
|
VertexBuffer::~VertexBuffer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
IndexBuffer::IndexBuffer(uint32 size, Gfx::SeIndexType indexType)
|
IndexBuffer::IndexBuffer(PGraphics graphics, uint32 size, Gfx::SeIndexType indexType, QueueType startQueueType)
|
||||||
: indexType(indexType)
|
: Buffer(graphics, startQueueType)
|
||||||
|
, indexType(indexType)
|
||||||
{
|
{
|
||||||
switch (indexType)
|
switch (indexType)
|
||||||
{
|
{
|
||||||
@@ -87,9 +126,8 @@ IndexBuffer::IndexBuffer(uint32 size, Gfx::SeIndexType indexType)
|
|||||||
IndexBuffer::~IndexBuffer()
|
IndexBuffer::~IndexBuffer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
VertexStream::VertexStream(PVertexBuffer buffer, uint8 instanced)
|
VertexStream::VertexStream(uint32 stride, uint8 instanced)
|
||||||
: buffer(buffer)
|
: stride(stride), instanced(instanced)
|
||||||
, instanced(instanced)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
VertexStream::~VertexStream()
|
VertexStream::~VertexStream()
|
||||||
@@ -103,11 +141,6 @@ const Array<VertexElement> VertexStream::getVertexDescriptions() const
|
|||||||
{
|
{
|
||||||
return vertexDescription;
|
return vertexDescription;
|
||||||
}
|
}
|
||||||
Gfx::PVertexBuffer VertexStream::getVertexBuffer()
|
|
||||||
{
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
VertexDeclaration::VertexDeclaration()
|
VertexDeclaration::VertexDeclaration()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -125,6 +158,32 @@ const Array<VertexStream> &VertexDeclaration::getVertexStreams() const
|
|||||||
return vertexStreams;
|
return vertexStreams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Texture::Texture(PGraphics graphics, Gfx::QueueType startQueueType)
|
||||||
|
: QueueOwnedResource(graphics, startQueueType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture::~Texture()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D::Texture2D(PGraphics graphics, Gfx::QueueType startQueueType)
|
||||||
|
: Texture(graphics, startQueueType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Texture2D::~Texture2D()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderCommand::RenderCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderCommand::~RenderCommand()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
RenderTargetLayout::RenderTargetLayout()
|
RenderTargetLayout::RenderTargetLayout()
|
||||||
: inputAttachments(), colorAttachments(), depthAttachment()
|
: inputAttachments(), colorAttachments(), depthAttachment()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "Math/MemCRC.h"
|
#include "Math/MemCRC.h"
|
||||||
#include "Material/MaterialInstance.h"
|
#include "Material/MaterialInstance.h"
|
||||||
#include "GraphicsInitializer.h"
|
#include "GraphicsInitializer.h"
|
||||||
|
#include "MeshBatch.h"
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
#define ENABLE_VALIDATION
|
#define ENABLE_VALIDATION
|
||||||
@@ -13,34 +14,10 @@
|
|||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
|
|
||||||
DECLARE_NAME_REF(Gfx, VertexBuffer);
|
|
||||||
DECLARE_NAME_REF(Gfx, IndexBuffer);
|
|
||||||
struct DrawInstance
|
|
||||||
{
|
|
||||||
Matrix4 modelMatrix;
|
|
||||||
PMaterialInstance instance;
|
|
||||||
Gfx::PIndexBuffer indexBuffer;
|
|
||||||
Gfx::PVertexBuffer vertexBuffer;
|
|
||||||
|
|
||||||
uint32 numInstances;
|
|
||||||
uint32 baseVertexIndex;
|
|
||||||
uint32 minVertexIndex;
|
|
||||||
uint32 firstInstance;
|
|
||||||
DrawInstance()
|
|
||||||
: instance(nullptr), indexBuffer(nullptr), vertexBuffer(nullptr), modelMatrix(1), numInstances(1), baseVertexIndex(0), minVertexIndex(0), firstInstance(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
struct DrawState
|
|
||||||
{
|
|
||||||
Array<DrawInstance> instances;
|
|
||||||
|
|
||||||
DrawState()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
namespace Gfx
|
namespace Gfx
|
||||||
{
|
{
|
||||||
|
DECLARE_REF(Graphics);
|
||||||
|
|
||||||
class SamplerState
|
class SamplerState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -182,6 +159,7 @@ public:
|
|||||||
PipelineLayout() {}
|
PipelineLayout() {}
|
||||||
virtual ~PipelineLayout() {}
|
virtual ~PipelineLayout() {}
|
||||||
virtual void create() = 0;
|
virtual void create() = 0;
|
||||||
|
virtual void reset() = 0;
|
||||||
void addDescriptorLayout(uint32 setIndex, PDescriptorLayout layout);
|
void addDescriptorLayout(uint32 setIndex, PDescriptorLayout layout);
|
||||||
void addPushConstants(const SePushConstantRange &pushConstants);
|
void addPushConstants(const SePushConstantRange &pushConstants);
|
||||||
virtual uint32 getHash() const = 0;
|
virtual uint32 getHash() const = 0;
|
||||||
@@ -191,17 +169,79 @@ protected:
|
|||||||
Array<SePushConstantRange> pushConstants;
|
Array<SePushConstantRange> pushConstants;
|
||||||
};
|
};
|
||||||
DEFINE_REF(PipelineLayout);
|
DEFINE_REF(PipelineLayout);
|
||||||
class UniformBuffer
|
|
||||||
|
struct QueueFamilyMapping
|
||||||
|
{
|
||||||
|
uint32 graphicsFamily;
|
||||||
|
uint32 computeFamily;
|
||||||
|
uint32 transferFamily;
|
||||||
|
uint32 dedicatedTransferFamily;
|
||||||
|
uint32 getQueueTypeFamilyIndex(Gfx::QueueType type) const
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Gfx::QueueType::GRAPHICS:
|
||||||
|
return graphicsFamily;
|
||||||
|
case Gfx::QueueType::COMPUTE:
|
||||||
|
return computeFamily;
|
||||||
|
case Gfx::QueueType::TRANSFER:
|
||||||
|
return transferFamily;
|
||||||
|
case Gfx::QueueType::DEDICATED_TRANSFER:
|
||||||
|
return dedicatedTransferFamily;
|
||||||
|
default:
|
||||||
|
return 0x7fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool needsTransfer(Gfx::QueueType src, Gfx::QueueType dst) const
|
||||||
|
{
|
||||||
|
uint32 srcIndex = getQueueTypeFamilyIndex(src);
|
||||||
|
uint32 dstIndex = getQueueTypeFamilyIndex(dst);
|
||||||
|
return srcIndex != dstIndex;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class QueueOwnedResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
UniformBuffer();
|
QueueOwnedResource(PGraphics graphics, QueueType startQueueType);
|
||||||
|
virtual ~QueueOwnedResource();
|
||||||
|
|
||||||
|
//Preliminary checks to see if the barrier should be executed at all
|
||||||
|
void transferOwnership(QueueType newOwner);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||||
|
Gfx::QueueType currentOwner;
|
||||||
|
PGraphics graphics;
|
||||||
|
};
|
||||||
|
DEFINE_REF(QueueOwnedResource);
|
||||||
|
|
||||||
|
class Buffer : public QueueOwnedResource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Buffer(PGraphics graphics, QueueType startQueueType);
|
||||||
|
virtual ~Buffer();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UniformBuffer : public Buffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UniformBuffer(PGraphics graphics, QueueType startQueueType);
|
||||||
virtual ~UniformBuffer();
|
virtual ~UniformBuffer();
|
||||||
|
protected:
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||||
};
|
};
|
||||||
DEFINE_REF(UniformBuffer);
|
DEFINE_REF(UniformBuffer);
|
||||||
class VertexBuffer
|
|
||||||
|
class VertexBuffer : public Buffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VertexBuffer(uint32 numVertices, uint32 vertexSize);
|
VertexBuffer(PGraphics graphics, uint32 numVertices, uint32 vertexSize, QueueType startQueueType);
|
||||||
virtual ~VertexBuffer();
|
virtual ~VertexBuffer();
|
||||||
inline uint32 getNumVertices()
|
inline uint32 getNumVertices()
|
||||||
{
|
{
|
||||||
@@ -214,14 +254,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||||
uint32 numVertices;
|
uint32 numVertices;
|
||||||
uint32 vertexSize;
|
uint32 vertexSize;
|
||||||
};
|
};
|
||||||
DEFINE_REF(VertexBuffer);
|
DEFINE_REF(VertexBuffer);
|
||||||
class IndexBuffer
|
|
||||||
|
class IndexBuffer : public Buffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
IndexBuffer(uint32 size, Gfx::SeIndexType index);
|
IndexBuffer(PGraphics graphics, uint32 size, Gfx::SeIndexType index, QueueType startQueueType);
|
||||||
virtual ~IndexBuffer();
|
virtual ~IndexBuffer();
|
||||||
inline uint32 getNumIndices() const
|
inline uint32 getNumIndices() const
|
||||||
{
|
{
|
||||||
@@ -233,34 +276,41 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||||
Gfx::SeIndexType indexType;
|
Gfx::SeIndexType indexType;
|
||||||
uint32 numIndices;
|
uint32 numIndices;
|
||||||
};
|
};
|
||||||
DEFINE_REF(IndexBuffer);
|
DEFINE_REF(IndexBuffer);
|
||||||
class StructuredBuffer
|
|
||||||
|
class StructuredBuffer : public Buffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~StructuredBuffer()
|
StructuredBuffer(PGraphics graphics, QueueType startQueueType);
|
||||||
{
|
virtual ~StructuredBuffer();
|
||||||
}
|
protected:
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||||
};
|
};
|
||||||
DEFINE_REF(StructuredBuffer);
|
DEFINE_REF(StructuredBuffer);
|
||||||
|
|
||||||
class VertexStream
|
class VertexStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VertexStream() {}
|
VertexStream() {}
|
||||||
VertexStream(PVertexBuffer buffer, uint8 instanced);
|
VertexStream(uint32 stride, uint8 instanced);
|
||||||
~VertexStream();
|
~VertexStream();
|
||||||
void addVertexElement(VertexElement element);
|
void addVertexElement(VertexElement element);
|
||||||
const Array<VertexElement> getVertexDescriptions() const;
|
const Array<VertexElement> getVertexDescriptions() const;
|
||||||
PVertexBuffer getVertexBuffer();
|
|
||||||
inline uint8 isInstanced() const { return instanced; }
|
inline uint8 isInstanced() const { return instanced; }
|
||||||
|
|
||||||
private:
|
uint32 stride;
|
||||||
PVertexBuffer buffer;
|
uint32 offset;
|
||||||
Array<VertexElement> vertexDescription;
|
Array<VertexElement> vertexDescription;
|
||||||
uint8 instanced;
|
uint8 instanced;
|
||||||
|
PVertexBuffer vertexBuffer;
|
||||||
};
|
};
|
||||||
|
DEFINE_REF(VertexStream);
|
||||||
class VertexDeclaration
|
class VertexDeclaration
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -276,41 +326,46 @@ DEFINE_REF(VertexDeclaration);
|
|||||||
class GraphicsPipeline
|
class GraphicsPipeline
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) : createInfo(createInfo) {}
|
GraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo, PPipelineLayout layout) : createInfo(createInfo) , layout(layout) {}
|
||||||
virtual ~GraphicsPipeline(){}
|
virtual ~GraphicsPipeline(){}
|
||||||
const GraphicsPipelineCreateInfo& getCreateInfo() const {return createInfo;}
|
const GraphicsPipelineCreateInfo& getCreateInfo() const {return createInfo;}
|
||||||
|
PPipelineLayout getPipelineLayout() const { return layout; }
|
||||||
protected:
|
protected:
|
||||||
|
PPipelineLayout layout;
|
||||||
GraphicsPipelineCreateInfo createInfo;
|
GraphicsPipelineCreateInfo createInfo;
|
||||||
};
|
};
|
||||||
DEFINE_REF(GraphicsPipeline);
|
DEFINE_REF(GraphicsPipeline);
|
||||||
class Texture
|
class Texture : public QueueOwnedResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Texture()
|
Texture(PGraphics graphics, QueueType startQueueType);
|
||||||
{
|
virtual ~Texture();
|
||||||
}
|
protected:
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||||
};
|
};
|
||||||
DEFINE_REF(Texture);
|
DEFINE_REF(Texture);
|
||||||
class Texture2D : public Texture
|
class Texture2D : public Texture
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Texture2D()
|
Texture2D(PGraphics graphics, QueueType startQueueType);
|
||||||
{
|
virtual ~Texture2D();
|
||||||
}
|
protected:
|
||||||
|
//Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||||
};
|
};
|
||||||
DEFINE_REF(Texture2D);
|
DEFINE_REF(Texture2D);
|
||||||
|
|
||||||
class RenderCommand
|
class RenderCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~RenderCommand()
|
RenderCommand();
|
||||||
{
|
virtual ~RenderCommand();
|
||||||
}
|
|
||||||
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) = 0;
|
virtual void bindPipeline(Gfx::PGraphicsPipeline pipeline) = 0;
|
||||||
virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0;
|
virtual void bindDescriptor(Gfx::PDescriptorSet set) = 0;
|
||||||
virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) = 0;
|
virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) = 0;
|
||||||
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0;
|
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) = 0;
|
||||||
virtual void draw(DrawInstance data) = 0;
|
virtual void draw(const MeshBatchElement& data) = 0;
|
||||||
};
|
};
|
||||||
DEFINE_REF(RenderCommand);
|
DEFINE_REF(RenderCommand);
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,13 @@
|
|||||||
#include "Mesh.h"
|
#include "Mesh.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
Mesh::Mesh(Gfx::PVertexBuffer vertexBuffer, Gfx::PIndexBuffer indexBuffer)
|
||||||
|
: vertexBuffer(vertexBuffer)
|
||||||
|
, indexBuffer(indexBuffer)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Mesh::~Mesh()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -10,7 +10,8 @@ public:
|
|||||||
~Mesh();
|
~Mesh();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Gfx::VertexBuffer vertexBuffer;
|
Gfx::PVertexBuffer vertexBuffer;
|
||||||
Gfx::IndexBuffer indexBuffer;
|
Gfx::PIndexBuffer indexBuffer;
|
||||||
};
|
};
|
||||||
|
DEFINE_REF(Mesh);
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
DECLARE_NAME_REF(Gfx, VertexBuffer);
|
||||||
|
DECLARE_NAME_REF(Gfx, IndexBuffer);
|
||||||
|
DECLARE_NAME_REF(Gfx, UniformBuffer);
|
||||||
|
DECLARE_REF(Material);
|
||||||
|
DECLARE_REF(VertexFactory);
|
||||||
|
struct MeshBatchElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Gfx::PUniformBuffer uniformBuffer;
|
||||||
|
Gfx::PIndexBuffer indexBuffer;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
uint32* instanceRuns;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
uint32 firstIndex;
|
||||||
|
uint32 numPrimitives;
|
||||||
|
|
||||||
|
uint32 numInstances;
|
||||||
|
uint32 baseVertexIndex;
|
||||||
|
uint32 minVertexIndex;
|
||||||
|
uint32 maxVertexIndex;
|
||||||
|
|
||||||
|
uint8 isInstanced : 1;
|
||||||
|
Gfx::PVertexBuffer indirectArgsBuffer;
|
||||||
|
MeshBatchElement()
|
||||||
|
: uniformBuffer(nullptr)
|
||||||
|
, indexBuffer(nullptr)
|
||||||
|
, indirectArgsBuffer(nullptr)
|
||||||
|
, firstIndex(0)
|
||||||
|
, numPrimitives(0)
|
||||||
|
, numInstances(1)
|
||||||
|
, baseVertexIndex(0)
|
||||||
|
, minVertexIndex(0)
|
||||||
|
, maxVertexIndex(0)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
struct MeshBatch
|
||||||
|
{
|
||||||
|
Array<MeshBatchElement> elements;
|
||||||
|
|
||||||
|
uint8 useReverseCulling : 1;
|
||||||
|
uint8 isBackfaceCullingDisabled : 1;
|
||||||
|
uint8 isCastingShadow : 1;
|
||||||
|
uint8 useWireframe : 1;
|
||||||
|
|
||||||
|
const Gfx::SePrimitiveTopology topology;
|
||||||
|
|
||||||
|
const PVertexFactory vertexFactory;
|
||||||
|
|
||||||
|
const PMaterial material;
|
||||||
|
|
||||||
|
inline int32 getNumPrimitives() const
|
||||||
|
{
|
||||||
|
int32 count = 0;
|
||||||
|
for(uint32 index = 0; index < elements.size(); ++index)
|
||||||
|
{
|
||||||
|
if(elements[index].isInstanced && elements[index].instanceRuns)
|
||||||
|
{
|
||||||
|
for(uint32 run = 0; run < elements[index].numInstances; ++run)
|
||||||
|
{
|
||||||
|
count += elements[index].numPrimitives * (elements[index].instanceRuns[run * 2 + 1] - elements[index].instanceRuns[run * 2] - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count += elements[index].numPrimitives * elements[index].numInstances;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshBatch()
|
||||||
|
: useReverseCulling(false)
|
||||||
|
, isBackfaceCullingDisabled(false)
|
||||||
|
, isCastingShadow(true)
|
||||||
|
, useWireframe(false)
|
||||||
|
, vertexFactory(nullptr)
|
||||||
|
, material(nullptr)
|
||||||
|
, topology(Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
|
||||||
|
{
|
||||||
|
elements.add();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
DECLARE_REF(PrimitiveComponent);
|
||||||
|
struct StaticMeshBatch : public MeshBatch
|
||||||
|
{
|
||||||
|
uint32 index;
|
||||||
|
PPrimitiveComponent primitiveComponent;
|
||||||
|
};
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
class BasePass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BasePass();
|
||||||
|
~BasePass();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
target_sources(SeeleEngine
|
||||||
|
PRIVATE
|
||||||
|
BasePass.h
|
||||||
|
BasePass.cpp
|
||||||
|
DepthPrepass.h
|
||||||
|
DepthPrepass.cpp
|
||||||
|
MeshProcessor.h
|
||||||
|
MeshProcessor.cpp
|
||||||
|
VertexFactory.h
|
||||||
|
VertexFactory.cpp)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#include "MeshProcessor.h"
|
||||||
|
#include "Graphics/Graphics.h"
|
||||||
|
#include "VertexFactory.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
MeshProcessor::MeshProcessor(const PScene scene, Gfx::PGraphics graphics)
|
||||||
|
: scene(scene)
|
||||||
|
, graphics(graphics)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MeshProcessor::~MeshProcessor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshProcessor::buildMeshDrawCommands(
|
||||||
|
const MeshBatch& meshBatch,
|
||||||
|
const PPrimitiveComponent primitiveComponent,
|
||||||
|
PMaterial material,
|
||||||
|
Gfx::PVertexShader vertexShader,
|
||||||
|
Gfx::PControlShader controlShader,
|
||||||
|
Gfx::PEvaluationShader evaluationShader,
|
||||||
|
Gfx::PGeometryShader geometryShader,
|
||||||
|
Gfx::PFragmentShader fragmentShader,
|
||||||
|
bool positionOnly)
|
||||||
|
{
|
||||||
|
const PVertexFactory vertexFactory = meshBatch.vertexFactory;
|
||||||
|
|
||||||
|
GraphicsPipelineCreateInfo pipelineInitializer;
|
||||||
|
pipelineInitializer.topology = meshBatch.topology;
|
||||||
|
Gfx::PVertexDeclaration vertexDecl = positionOnly ? vertexFactory->getPositionDeclaration() : vertexFactory->getDeclaration();
|
||||||
|
pipelineInitializer.vertexDeclaration = vertexDecl;
|
||||||
|
pipelineInitializer.vertexShader = vertexShader;
|
||||||
|
pipelineInitializer.controlShader = controlShader;
|
||||||
|
pipelineInitializer.evalShader = evaluationShader;
|
||||||
|
pipelineInitializer.geometryShader = geometryShader;
|
||||||
|
pipelineInitializer.fragmentShader = fragmentShader;
|
||||||
|
|
||||||
|
VertexInputStreamArray vertexStreams;
|
||||||
|
if(positionOnly)
|
||||||
|
{
|
||||||
|
vertexFactory->getPositionOnlyStream(vertexStreams);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vertexFactory->getStreams(vertexStreams);
|
||||||
|
}
|
||||||
|
if(vertexShader != nullptr)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "Scene/Scene.h"
|
||||||
|
#include "Graphics/GraphicsResources.h"
|
||||||
|
#include "Graphics/MeshBatch.h"
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
class MeshProcessor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MeshProcessor(const PScene scene, Gfx::PGraphics graphics);
|
||||||
|
virtual ~MeshProcessor();
|
||||||
|
private:
|
||||||
|
PScene scene;
|
||||||
|
Gfx::PGraphics graphics;
|
||||||
|
virtual void addMeshBatch(
|
||||||
|
const MeshBatch& meshBatch,
|
||||||
|
const PPrimitiveComponent primitiveComponent,
|
||||||
|
int32 staticMeshId = -1) = 0;
|
||||||
|
void buildMeshDrawCommands(
|
||||||
|
const MeshBatch& meshBatch,
|
||||||
|
const PPrimitiveComponent primitiveComponent,
|
||||||
|
PMaterial material,
|
||||||
|
Gfx::PVertexShader vertexShader,
|
||||||
|
Gfx::PControlShader controlShader,
|
||||||
|
Gfx::PEvaluationShader evaluationShader,
|
||||||
|
Gfx::PGeometryShader geometryShader,
|
||||||
|
Gfx::PFragmentShader fragmentShader,
|
||||||
|
bool positionOnly);
|
||||||
|
};
|
||||||
|
} // namespace Seele
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#include "VertexFactory.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
void VertexFactory::getStreams(VertexInputStreamArray& outVertexStreams) const
|
||||||
|
{
|
||||||
|
for(uint32 i = 0; i < streams.size(); ++i)
|
||||||
|
{
|
||||||
|
const Gfx::VertexStream& stream = streams[i];
|
||||||
|
if(stream.vertexBuffer == nullptr)
|
||||||
|
{
|
||||||
|
outVertexStreams.add(VertexInputStream(i, 0, nullptr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outVertexStreams.add(VertexInputStream(i, stream.offset, stream.vertexBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexFactory::getPositionOnlyStream(VertexInputStreamArray& outVertexStreams) const
|
||||||
|
{
|
||||||
|
for (uint32 i = 0; i < positionStream.size(); ++i)
|
||||||
|
{
|
||||||
|
const Gfx::VertexStream& stream = positionStream[i];
|
||||||
|
outVertexStreams.add(VertexInputStream(i, stream.offset, stream.vertexBuffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "MinimalEngine.h"
|
||||||
|
#include "Graphics/GraphicsResources.h"
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
struct VertexInputStream
|
||||||
|
{
|
||||||
|
uint32 streamIndex : 4;
|
||||||
|
uint32 offset : 28;
|
||||||
|
Gfx::PVertexBuffer vertexBuffer;
|
||||||
|
|
||||||
|
VertexInputStream()
|
||||||
|
: streamIndex(0), offset(0), vertexBuffer(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexInputStream(uint32 streamIndex, uint32 offset, Gfx::PVertexBuffer vertexBuffer)
|
||||||
|
: streamIndex(streamIndex), offset(offset), vertexBuffer(vertexBuffer)
|
||||||
|
{
|
||||||
|
assert(this->streamIndex == streamIndex && this->offset == offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const VertexInputStream &rhs) const
|
||||||
|
{
|
||||||
|
if (streamIndex != rhs.streamIndex || offset != rhs.offset || vertexBuffer != rhs.vertexBuffer)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
inline bool operator!=(const VertexInputStream &rhs) const
|
||||||
|
{
|
||||||
|
return !(*this == rhs);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexStreamComponent
|
||||||
|
{
|
||||||
|
const Gfx::PVertexBuffer vertexBuffer = nullptr;
|
||||||
|
|
||||||
|
uint32 streamOffset = 0;
|
||||||
|
|
||||||
|
uint8 offset = 0;
|
||||||
|
|
||||||
|
uint8 stride;
|
||||||
|
|
||||||
|
Gfx::SeFormat type;
|
||||||
|
|
||||||
|
VertexStreamComponent()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexStreamComponent(const Gfx::PVertexBuffer vertexBuffer, uint32 offset, uint32 stride, Gfx::SeFormat type)
|
||||||
|
: vertexBuffer(vertexBuffer)
|
||||||
|
, streamOffset(0)
|
||||||
|
, offset(offset)
|
||||||
|
, stride(stride)
|
||||||
|
, type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VertexStreamComponent(const Gfx::PVertexBuffer vertexBuffer, uint32 streamOffset, uint32 offset, uint32 stride, Gfx::SeFormat type)
|
||||||
|
: vertexBuffer(vertexBuffer)
|
||||||
|
, streamOffset(streamOffset)
|
||||||
|
, offset(offset)
|
||||||
|
, stride(stride)
|
||||||
|
, type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Array<VertexInputStream> VertexInputStreamArray;
|
||||||
|
class VertexFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VertexFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void getStreams(VertexInputStreamArray& outVertexStreams) const;
|
||||||
|
void getPositionOnlyStream(VertexInputStreamArray& outVertexStreams) const;
|
||||||
|
virtual bool supportsTesselation() { return false; }
|
||||||
|
Gfx::PVertexDeclaration getDeclaration() const {return declaration;}
|
||||||
|
Gfx::PVertexDeclaration getPositionDeclaration() const {return positionDeclaration;}
|
||||||
|
private:
|
||||||
|
StaticArray<Gfx::VertexStream, 16> streams;
|
||||||
|
StaticArray<Gfx::VertexStream, 16> positionStream;
|
||||||
|
Gfx::PVertexDeclaration declaration;
|
||||||
|
Gfx::PVertexDeclaration positionDeclaration;
|
||||||
|
};
|
||||||
|
DEFINE_REF(VertexFactory);
|
||||||
|
} // namespace Seele
|
||||||
@@ -9,6 +9,7 @@ public:
|
|||||||
RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
|
RenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
|
||||||
virtual ~RenderPath();
|
virtual ~RenderPath();
|
||||||
virtual void applyArea(URect area);
|
virtual void applyArea(URect area);
|
||||||
|
virtual void init() = 0;
|
||||||
virtual void beginFrame() = 0;
|
virtual void beginFrame() = 0;
|
||||||
virtual void render() = 0;
|
virtual void render() = 0;
|
||||||
virtual void endFrame() = 0;
|
virtual void endFrame() = 0;
|
||||||
|
|||||||
@@ -1,12 +1,39 @@
|
|||||||
#include "SceneRenderPath.h"
|
#include "SceneRenderPath.h"
|
||||||
#include "Scene/Scene.h"
|
#include "Scene/Scene.h"
|
||||||
|
#include "Material/Material.h"
|
||||||
|
|
||||||
Seele::SceneRenderPath::SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target)
|
using namespace Seele;
|
||||||
|
|
||||||
|
SceneRenderPath::SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target)
|
||||||
: RenderPath(graphics, target)
|
: RenderPath(graphics, target)
|
||||||
{
|
{
|
||||||
scene = new Scene();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Seele::SceneRenderPath::~SceneRenderPath()
|
SceneRenderPath::~SceneRenderPath()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneRenderPath::setTargetScene(PScene newScene)
|
||||||
|
{
|
||||||
|
scene = newScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneRenderPath::init()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneRenderPath::beginFrame()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneRenderPath::render()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneRenderPath::endFrame()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,9 +9,11 @@ class SceneRenderPath : public RenderPath
|
|||||||
public:
|
public:
|
||||||
SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
|
SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
|
||||||
virtual ~SceneRenderPath();
|
virtual ~SceneRenderPath();
|
||||||
virtual void beginFrame() = 0;
|
void setTargetScene(PScene scene);
|
||||||
virtual void render() = 0;
|
virtual void init();
|
||||||
virtual void endFrame() = 0;
|
virtual void beginFrame();
|
||||||
|
virtual void render();
|
||||||
|
virtual void endFrame();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PScene scene;
|
PScene scene;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#include "SceneView.h"
|
#include "SceneView.h"
|
||||||
#include "ForwardPlusRenderPath.h"
|
#include "SceneRenderPath.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
|
||||||
Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo)
|
Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo)
|
||||||
: View(graphics, owner, createInfo)
|
: View(graphics, owner, createInfo)
|
||||||
{
|
{
|
||||||
renderer = new ForwardPlusRenderPath(graphics, viewport);
|
renderer = new SceneRenderPath(graphics, viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
Seele::SceneView::~SceneView()
|
Seele::SceneView::~SceneView()
|
||||||
|
|||||||
@@ -61,16 +61,15 @@ Allocation::Allocation(PGraphics graphics, Allocator *allocator, VkDeviceSize si
|
|||||||
|
|
||||||
Allocation::~Allocation()
|
Allocation::~Allocation()
|
||||||
{
|
{
|
||||||
allocator->free(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
|
PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDeviceSize alignment)
|
||||||
{
|
{
|
||||||
|
std::scoped_lock lck(lock);
|
||||||
if (isDedicated)
|
if (isDedicated)
|
||||||
{
|
{
|
||||||
if (activeAllocations.empty())
|
if (activeAllocations.empty() && requestedSize == bytesAllocated)
|
||||||
{
|
{
|
||||||
assert(requestedSize == bytesAllocated);
|
|
||||||
PSubAllocation suballoc = freeRanges[0];
|
PSubAllocation suballoc = freeRanges[0];
|
||||||
activeAllocations[0] = suballoc.getHandle();
|
activeAllocations[0] = suballoc.getHandle();
|
||||||
freeRanges.clear();
|
freeRanges.clear();
|
||||||
@@ -82,9 +81,9 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (uint32 i = 0; i < freeRanges.size(); ++i)
|
for (auto it : freeRanges)
|
||||||
{
|
{
|
||||||
PSubAllocation freeAllocation = freeRanges[i];
|
PSubAllocation freeAllocation = it.value;
|
||||||
VkDeviceSize allocatedOffset = freeAllocation->allocatedOffset;
|
VkDeviceSize allocatedOffset = freeAllocation->allocatedOffset;
|
||||||
VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
|
VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
|
||||||
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
|
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
|
||||||
@@ -115,32 +114,48 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
|||||||
|
|
||||||
void Allocation::markFree(SubAllocation *allocation)
|
void Allocation::markFree(SubAllocation *allocation)
|
||||||
{
|
{
|
||||||
|
// Dont free if it is already a free allocation, since they also mark themselves on deletion
|
||||||
|
if(freeRanges.find(allocation->allocatedOffset) != nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
VkDeviceSize lowerBound = allocation->allocatedOffset;
|
||||||
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
VkDeviceSize upperBound = allocation->allocatedOffset + allocation->allocatedSize;
|
||||||
PSubAllocation allocHandle;
|
PSubAllocation allocHandle;
|
||||||
|
std::scoped_lock lck(lock);
|
||||||
|
//Join lower bound
|
||||||
for (auto freeRange : freeRanges)
|
for (auto freeRange : freeRanges)
|
||||||
{
|
{
|
||||||
PSubAllocation freeAlloc = freeRange.value;
|
PSubAllocation freeAlloc = freeRange.value;
|
||||||
if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize + 1 == lowerBound)
|
if (freeAlloc->allocatedOffset + freeAlloc->allocatedSize == lowerBound)
|
||||||
{
|
{
|
||||||
|
//extend freeAlloc by the allocatedSize
|
||||||
freeAlloc->allocatedSize += allocation->allocatedSize;
|
freeAlloc->allocatedSize += allocation->allocatedSize;
|
||||||
allocHandle = freeAlloc;
|
allocHandle = freeAlloc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto foundAlloc = freeRanges.find(upperBound + 1);
|
//Join upper bound
|
||||||
|
auto foundAlloc = freeRanges.find(upperBound);
|
||||||
if (foundAlloc != freeRanges.end())
|
if (foundAlloc != freeRanges.end())
|
||||||
{
|
{
|
||||||
if (allocHandle == nullptr)
|
// There is a free allocation ending where the new free one ends
|
||||||
|
if (allocHandle != nullptr)
|
||||||
{
|
{
|
||||||
|
// extend allocHandle by another foundAlloc->allocatedSize bytes
|
||||||
allocHandle->allocatedSize += foundAlloc->value->allocatedSize;
|
allocHandle->allocatedSize += foundAlloc->value->allocatedSize;
|
||||||
freeRanges.erase(foundAlloc->key);
|
freeRanges.erase(foundAlloc->key);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// set foundAlloc back by size amount
|
||||||
allocHandle = foundAlloc->value;
|
allocHandle = foundAlloc->value;
|
||||||
|
// remove from offset map since key changes
|
||||||
|
freeRanges.erase(foundAlloc->key);
|
||||||
allocHandle->allocatedOffset -= allocation->allocatedSize;
|
allocHandle->allocatedOffset -= allocation->allocatedSize;
|
||||||
allocHandle->alignedOffset -= allocation->allocatedSize;
|
allocHandle->alignedOffset -= allocation->allocatedSize;
|
||||||
|
// place back at correct offset
|
||||||
|
freeRanges[allocHandle->allocatedOffset] = allocHandle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (allocHandle == nullptr)
|
if (allocHandle == nullptr)
|
||||||
@@ -150,6 +165,8 @@ void Allocation::markFree(SubAllocation *allocation)
|
|||||||
}
|
}
|
||||||
activeAllocations.erase(allocation->allocatedOffset);
|
activeAllocations.erase(allocation->allocatedOffset);
|
||||||
bytesUsed -= allocation->allocatedSize;
|
bytesUsed -= allocation->allocatedSize;
|
||||||
|
|
||||||
|
// TODO: delete allocation when bytesUsed == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocator::Allocator(PGraphics graphics)
|
Allocator::Allocator(PGraphics graphics)
|
||||||
@@ -167,6 +184,7 @@ Allocator::Allocator(PGraphics graphics)
|
|||||||
|
|
||||||
Allocator::~Allocator()
|
Allocator::~Allocator()
|
||||||
{
|
{
|
||||||
|
std::scoped_lock lck(lock);
|
||||||
for (auto heap : heaps)
|
for (auto heap : heaps)
|
||||||
{
|
{
|
||||||
for (auto alloc : heap.allocations)
|
for (auto alloc : heap.allocations)
|
||||||
@@ -181,6 +199,7 @@ Allocator::~Allocator()
|
|||||||
|
|
||||||
PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2, VkMemoryPropertyFlags properties, VkMemoryDedicatedAllocateInfo *dedicatedInfo)
|
||||||
{
|
{
|
||||||
|
std::scoped_lock lck(lock);
|
||||||
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
|
const VkMemoryRequirements &requirements = memRequirements2.memoryRequirements;
|
||||||
uint8 memoryTypeIndex;
|
uint8 memoryTypeIndex;
|
||||||
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
|
VK_CHECK(findMemoryType(requirements.memoryTypeBits, properties, &memoryTypeIndex));
|
||||||
@@ -213,6 +232,7 @@ PSubAllocation Allocator::allocate(const VkMemoryRequirements2 &memRequirements2
|
|||||||
|
|
||||||
void Allocator::free(Allocation *allocation)
|
void Allocator::free(Allocation *allocation)
|
||||||
{
|
{
|
||||||
|
std::scoped_lock lck(lock);
|
||||||
for (auto heap : heaps)
|
for (auto heap : heaps)
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < heap.allocations.size(); ++i)
|
for (uint32 i = 0; i < heap.allocations.size(); ++i)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include "VulkanGraphicsEnums.h"
|
#include "VulkanGraphicsEnums.h"
|
||||||
#include "Containers/Map.h"
|
#include "Containers/Map.h"
|
||||||
#include "Containers/Array.h"
|
#include "Containers/Array.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
@@ -101,6 +102,7 @@ private:
|
|||||||
VkMemoryPropertyFlags properties;
|
VkMemoryPropertyFlags properties;
|
||||||
Map<VkDeviceSize, SubAllocation *> activeAllocations;
|
Map<VkDeviceSize, SubAllocation *> activeAllocations;
|
||||||
Map<VkDeviceSize, PSubAllocation> freeRanges;
|
Map<VkDeviceSize, PSubAllocation> freeRanges;
|
||||||
|
std::mutex lock;
|
||||||
void *mappedPointer;
|
void *mappedPointer;
|
||||||
uint8 memoryTypeIndex;
|
uint8 memoryTypeIndex;
|
||||||
uint8 isDedicated : 1;
|
uint8 isDedicated : 1;
|
||||||
@@ -153,6 +155,7 @@ private:
|
|||||||
};
|
};
|
||||||
Array<HeapInfo> heaps;
|
Array<HeapInfo> heaps;
|
||||||
VkResult findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex);
|
VkResult findMemoryType(uint32 typeBits, VkMemoryPropertyFlags properties, uint8 *typeIndex);
|
||||||
|
std::mutex lock;
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
VkPhysicalDeviceMemoryProperties memProperties;
|
VkPhysicalDeviceMemoryProperties memProperties;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ struct PendingBuffer
|
|||||||
static Map<Buffer *, PendingBuffer> pendingBuffers;
|
static Map<Buffer *, PendingBuffer> pendingBuffers;
|
||||||
|
|
||||||
Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType)
|
Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType)
|
||||||
: QueueOwnedResource(graphics, queueType), currentBuffer(0), size(size)
|
: graphics(graphics), currentBuffer(0), size(size), currentOwner(queueType)
|
||||||
{
|
{
|
||||||
if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ||
|
if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ||
|
||||||
usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT ||
|
usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT ||
|
||||||
@@ -58,7 +58,7 @@ Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::Q
|
|||||||
|
|
||||||
Buffer::~Buffer()
|
Buffer::~Buffer()
|
||||||
{
|
{
|
||||||
auto fence = getCommands()->getCommands()->getFence();
|
auto fence = graphics->getQueueCommands(currentOwner)->getCommands()->getFence();
|
||||||
auto &deletionQueue = graphics->getDeletionQueue();
|
auto &deletionQueue = graphics->getDeletionQueue();
|
||||||
VkDevice device = graphics->getDevice();
|
VkDevice device = graphics->getDevice();
|
||||||
VkBuffer buf[Gfx::numFramesBuffered];
|
VkBuffer buf[Gfx::numFramesBuffered];
|
||||||
@@ -74,11 +74,11 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
{
|
{
|
||||||
VkBufferMemoryBarrier barrier =
|
VkBufferMemoryBarrier barrier =
|
||||||
init::BufferMemoryBarrier();
|
init::BufferMemoryBarrier();
|
||||||
PCommandBufferManager sourceManager = getCommands();
|
PCommandBufferManager sourceManager = graphics->getQueueCommands(currentOwner);
|
||||||
PCommandBufferManager dstManager = nullptr;
|
PCommandBufferManager dstManager = nullptr;
|
||||||
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||||
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||||
QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
||||||
barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner);
|
barrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner);
|
||||||
barrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner);
|
barrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner);
|
||||||
assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex);
|
assert(barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex);
|
||||||
@@ -134,7 +134,7 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
vkCmdPipelineBarrier(srcCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
|
vkCmdPipelineBarrier(srcCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
|
||||||
vkCmdPipelineBarrier(dstCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
|
vkCmdPipelineBarrier(dstCommand, srcStage, dstStage, 0, 0, nullptr, numBuffers, dynamicBarriers, 0, nullptr);
|
||||||
sourceManager->submitCommands();
|
sourceManager->submitCommands();
|
||||||
cachedCmdBufferManager = dstManager;
|
currentOwner = newOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *Buffer::lock(bool bWriteOnly)
|
void *Buffer::lock(bool bWriteOnly)
|
||||||
@@ -160,19 +160,19 @@ void *Buffer::lock(bool bWriteOnly)
|
|||||||
pending.prevQueue = currentOwner;
|
pending.prevQueue = currentOwner;
|
||||||
if (bWriteOnly)
|
if (bWriteOnly)
|
||||||
{
|
{
|
||||||
transferOwnership(Gfx::QueueType::DEDICATED_TRANSFER);
|
requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
|
||||||
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||||
data = stagingBuffer->getMappedPointer();
|
data = stagingBuffer->getMappedPointer();
|
||||||
pending.stagingBuffer = stagingBuffer;
|
pending.stagingBuffer = stagingBuffer;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PCmdBuffer current = getCommands()->getCommands();
|
PCmdBuffer current = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||||
getCommands()->submitCommands();
|
graphics->getQueueCommands(currentOwner)->submitCommands();
|
||||||
getCommands()->waitForCommands(current);
|
graphics->getQueueCommands(currentOwner)->waitForCommands(current);
|
||||||
|
|
||||||
transferOwnership(Gfx::QueueType::DEDICATED_TRANSFER);
|
requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
|
||||||
VkCommandBuffer handle = getCommands()->getCommands()->getHandle();
|
VkCommandBuffer handle = graphics->getQueueCommands(currentOwner)->getCommands()->getHandle();
|
||||||
|
|
||||||
VkBufferMemoryBarrier barrier =
|
VkBufferMemoryBarrier barrier =
|
||||||
init::BufferMemoryBarrier();
|
init::BufferMemoryBarrier();
|
||||||
@@ -194,8 +194,8 @@ void *Buffer::lock(bool bWriteOnly)
|
|||||||
|
|
||||||
vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, ®ions);
|
vkCmdCopyBuffer(handle, buffers[currentBuffer].buffer, stagingBuffer->getHandle(), 1, ®ions);
|
||||||
|
|
||||||
getCommands()->submitCommands();
|
graphics->getQueueCommands(currentOwner)->submitCommands();
|
||||||
vkQueueWaitIdle(getCommands()->getQueue()->getHandle());
|
vkQueueWaitIdle(graphics->getQueueCommands(currentOwner)->getQueue()->getHandle());
|
||||||
|
|
||||||
stagingBuffer->flushMappedMemory();
|
stagingBuffer->flushMappedMemory();
|
||||||
pending.stagingBuffer = stagingBuffer;
|
pending.stagingBuffer = stagingBuffer;
|
||||||
@@ -219,7 +219,7 @@ void Buffer::unlock()
|
|||||||
if (pending.bWriteOnly)
|
if (pending.bWriteOnly)
|
||||||
{
|
{
|
||||||
PStagingBuffer stagingBuffer = pending.stagingBuffer;
|
PStagingBuffer stagingBuffer = pending.stagingBuffer;
|
||||||
PCmdBuffer cmdBuffer = getCommands()->getCommands();
|
PCmdBuffer cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||||
VkCommandBuffer cmdHandle = cmdBuffer->getHandle();
|
VkCommandBuffer cmdHandle = cmdBuffer->getHandle();
|
||||||
|
|
||||||
VkBufferCopy region;
|
VkBufferCopy region;
|
||||||
@@ -227,13 +227,14 @@ void Buffer::unlock()
|
|||||||
region.size = size;
|
region.size = size;
|
||||||
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion);
|
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, ®ion);
|
||||||
}
|
}
|
||||||
transferOwnership(pending.prevQueue);
|
requestOwnershipTransfer(pending.prevQueue);
|
||||||
graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer);
|
graphics->getStagingManager()->releaseStagingBuffer(pending.stagingBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UniformBuffer::UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData)
|
UniformBuffer::UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData)
|
||||||
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, resourceData.owner)
|
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, resourceData.owner)
|
||||||
|
, Gfx::UniformBuffer(graphics, resourceData.owner)
|
||||||
{
|
{
|
||||||
if (resourceData.data != nullptr)
|
if (resourceData.data != nullptr)
|
||||||
{
|
{
|
||||||
@@ -247,6 +248,17 @@ UniformBuffer::~UniformBuffer()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||||
|
{
|
||||||
|
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||||
|
Buffer::currentOwner = newOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||||
|
{
|
||||||
|
Buffer::executeOwnershipBarrier(newOwner);
|
||||||
|
}
|
||||||
|
|
||||||
VkAccessFlags UniformBuffer::getSourceAccessMask()
|
VkAccessFlags UniformBuffer::getSourceAccessMask()
|
||||||
{
|
{
|
||||||
return VK_ACCESS_MEMORY_WRITE_BIT;
|
return VK_ACCESS_MEMORY_WRITE_BIT;
|
||||||
@@ -259,6 +271,7 @@ VkAccessFlags UniformBuffer::getDestAccessMask()
|
|||||||
|
|
||||||
StructuredBuffer::StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData)
|
StructuredBuffer::StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData)
|
||||||
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, resourceData.owner)
|
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, resourceData.owner)
|
||||||
|
, Gfx::StructuredBuffer(graphics, resourceData.owner)
|
||||||
{
|
{
|
||||||
if (resourceData.data != nullptr)
|
if (resourceData.data != nullptr)
|
||||||
{
|
{
|
||||||
@@ -272,6 +285,16 @@ StructuredBuffer::~StructuredBuffer()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||||
|
{
|
||||||
|
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StructuredBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||||
|
{
|
||||||
|
Buffer::executeOwnershipBarrier(newOwner);
|
||||||
|
}
|
||||||
|
|
||||||
VkAccessFlags StructuredBuffer::getSourceAccessMask()
|
VkAccessFlags StructuredBuffer::getSourceAccessMask()
|
||||||
{
|
{
|
||||||
return VK_ACCESS_MEMORY_WRITE_BIT;
|
return VK_ACCESS_MEMORY_WRITE_BIT;
|
||||||
@@ -284,7 +307,7 @@ VkAccessFlags StructuredBuffer::getDestAccessMask()
|
|||||||
|
|
||||||
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData)
|
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData)
|
||||||
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner)
|
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner)
|
||||||
, Gfx::VertexBuffer(resourceData.numVertices, resourceData.vertexSize)
|
, Gfx::VertexBuffer(graphics, resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner)
|
||||||
{
|
{
|
||||||
if (resourceData.resourceData.data != nullptr)
|
if (resourceData.resourceData.data != nullptr)
|
||||||
{
|
{
|
||||||
@@ -298,6 +321,16 @@ VertexBuffer::~VertexBuffer()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||||
|
{
|
||||||
|
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||||
|
{
|
||||||
|
Buffer::executeOwnershipBarrier(newOwner);
|
||||||
|
}
|
||||||
|
|
||||||
VkAccessFlags VertexBuffer::getSourceAccessMask()
|
VkAccessFlags VertexBuffer::getSourceAccessMask()
|
||||||
{
|
{
|
||||||
return VK_ACCESS_MEMORY_WRITE_BIT;
|
return VK_ACCESS_MEMORY_WRITE_BIT;
|
||||||
@@ -310,7 +343,7 @@ VkAccessFlags VertexBuffer::getDestAccessMask()
|
|||||||
|
|
||||||
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData)
|
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData)
|
||||||
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner)
|
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner)
|
||||||
, Gfx::IndexBuffer(resourceData.resourceData.size, resourceData.indexType)
|
, Gfx::IndexBuffer(graphics, resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner)
|
||||||
{
|
{
|
||||||
if (resourceData.resourceData.data != nullptr)
|
if (resourceData.resourceData.data != nullptr)
|
||||||
{
|
{
|
||||||
@@ -324,6 +357,16 @@ IndexBuffer::~IndexBuffer()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||||
|
{
|
||||||
|
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||||
|
{
|
||||||
|
Buffer::executeOwnershipBarrier(newOwner);
|
||||||
|
}
|
||||||
|
|
||||||
VkAccessFlags IndexBuffer::getSourceAccessMask()
|
VkAccessFlags IndexBuffer::getSourceAccessMask()
|
||||||
{
|
{
|
||||||
return VK_ACCESS_MEMORY_WRITE_BIT;
|
return VK_ACCESS_MEMORY_WRITE_BIT;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "VulkanRenderPass.h"
|
#include "VulkanRenderPass.h"
|
||||||
#include "VulkanPipeline.h"
|
#include "VulkanPipeline.h"
|
||||||
#include "VulkanDescriptorSets.h"
|
#include "VulkanDescriptorSets.h"
|
||||||
|
#include "Graphics/MeshBatch.h"
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
@@ -174,9 +175,9 @@ void SecondaryCmdBuffer::bindIndexBuffer(Gfx::PIndexBuffer indexBuffer)
|
|||||||
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
|
PIndexBuffer buf = indexBuffer.cast<IndexBuffer>();
|
||||||
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, VK_INDEX_TYPE_UINT16);
|
vkCmdBindIndexBuffer(handle, buf->getHandle(), 0, VK_INDEX_TYPE_UINT16);
|
||||||
}
|
}
|
||||||
void SecondaryCmdBuffer::draw(DrawInstance data)
|
void SecondaryCmdBuffer::draw(const MeshBatchElement& data)
|
||||||
{
|
{
|
||||||
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, data.firstInstance);
|
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue)
|
CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue)
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public:
|
|||||||
virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override;
|
virtual void bindDescriptor(Gfx::PDescriptorSet descriptorSet) override;
|
||||||
virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) override;
|
virtual void bindVertexBuffer(Gfx::PVertexBuffer vertexBuffer) override;
|
||||||
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
|
virtual void bindIndexBuffer(Gfx::PIndexBuffer indexBuffer) override;
|
||||||
virtual void draw(DrawInstance data) override;
|
virtual void draw(const MeshBatchElement& data) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PGraphicsPipeline pipeline;
|
PGraphicsPipeline pipeline;
|
||||||
|
|||||||
@@ -72,6 +72,13 @@ void PipelineLayout::create()
|
|||||||
layoutHash = memCrc32(&createInfo, sizeof(VkPipelineLayoutCreateInfo), 0);
|
layoutHash = memCrc32(&createInfo, sizeof(VkPipelineLayoutCreateInfo), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PipelineLayout::reset()
|
||||||
|
{
|
||||||
|
vkDestroyPipelineLayout(graphics->getDevice(), layoutHandle, nullptr);
|
||||||
|
descriptorSetLayouts.clear();
|
||||||
|
pushConstants.clear();
|
||||||
|
}
|
||||||
|
|
||||||
DescriptorSet::~DescriptorSet()
|
DescriptorSet::~DescriptorSet()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public:
|
|||||||
}
|
}
|
||||||
virtual ~PipelineLayout();
|
virtual ~PipelineLayout();
|
||||||
virtual void create();
|
virtual void create();
|
||||||
|
virtual void reset();
|
||||||
inline VkPipelineLayout getHandle() const
|
inline VkPipelineLayout getHandle() const
|
||||||
{
|
{
|
||||||
return layoutHandle;
|
return layoutHandle;
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#include "VulkanRenderPass.h"
|
#include "VulkanRenderPass.h"
|
||||||
#include "VulkanFramebuffer.h"
|
#include "VulkanFramebuffer.h"
|
||||||
#include "VulkanPipelineCache.h"
|
#include "VulkanPipelineCache.h"
|
||||||
|
#include "VulkanDescriptorSets.h"
|
||||||
|
#include "VulkanShader.h"
|
||||||
#include "Graphics/GraphicsResources.h"
|
#include "Graphics/GraphicsResources.h"
|
||||||
#include <glfw/glfw3.h>
|
#include <glfw/glfw3.h>
|
||||||
|
|
||||||
@@ -99,9 +101,7 @@ void Graphics::executeCommands(Array<Gfx::PRenderCommand> commands)
|
|||||||
|
|
||||||
Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo)
|
Gfx::PTexture2D Graphics::createTexture2D(const TextureCreateInfo &createInfo)
|
||||||
{
|
{
|
||||||
PTexture2D result = new Texture2D(this, createInfo.width, createInfo.height, createInfo.bArray,
|
PTexture2D result = new Texture2D(this, createInfo);
|
||||||
createInfo.bArray, createInfo.arrayLayers, createInfo.format,
|
|
||||||
createInfo.samples, createInfo.usage, createInfo.queueType);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,11 +133,51 @@ Gfx::PRenderCommand Graphics::createRenderCommand()
|
|||||||
cmdBuffer->begin(getGraphicsCommands()->getCommands());
|
cmdBuffer->begin(getGraphicsCommands()->getCommands());
|
||||||
return cmdBuffer;
|
return cmdBuffer;
|
||||||
}
|
}
|
||||||
|
Gfx::PVertexShader Graphics::createVertexShader(const ShaderCreateInfo& createInfo)
|
||||||
|
{
|
||||||
|
PVertexShader shader = new VertexShader(this);
|
||||||
|
shader->create(createInfo);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
Gfx::PControlShader Graphics::createControlShader(const ShaderCreateInfo& createInfo)
|
||||||
|
{
|
||||||
|
PControlShader shader = new ControlShader(this);
|
||||||
|
shader->create(createInfo);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
Gfx::PEvaluationShader Graphics::createEvaluationShader(const ShaderCreateInfo& createInfo)
|
||||||
|
{
|
||||||
|
PEvaluationShader shader = new EvaluationShader(this);
|
||||||
|
shader->create(createInfo);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
Gfx::PGeometryShader Graphics::createGeometryShader(const ShaderCreateInfo& createInfo)
|
||||||
|
{
|
||||||
|
PGeometryShader shader = new GeometryShader(this);
|
||||||
|
shader->create(createInfo);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
Gfx::PFragmentShader Graphics::createFragmentShader(const ShaderCreateInfo& createInfo)
|
||||||
|
{
|
||||||
|
PFragmentShader shader = new FragmentShader(this);
|
||||||
|
shader->create(createInfo);
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo)
|
Gfx::PGraphicsPipeline Graphics::createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo)
|
||||||
{
|
{
|
||||||
PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo);
|
PGraphicsPipeline pipeline = pipelineCache->createPipeline(createInfo);
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
Gfx::PDescriptorLayout Graphics::createDescriptorLayout()
|
||||||
|
{
|
||||||
|
PDescriptorLayout layout = new DescriptorLayout(this);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
Gfx::PPipelineLayout Graphics::createPipelineLayout()
|
||||||
|
{
|
||||||
|
PPipelineLayout layout = new PipelineLayout(this);
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
VkInstance Graphics::getInstance() const
|
VkInstance Graphics::getInstance() const
|
||||||
{
|
{
|
||||||
@@ -154,6 +194,23 @@ VkPhysicalDevice Graphics::getPhysicalDevice() const
|
|||||||
return physicalDevice;
|
return physicalDevice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PCommandBufferManager Graphics::getQueueCommands(Gfx::QueueType queueType)
|
||||||
|
{
|
||||||
|
switch (queueType)
|
||||||
|
{
|
||||||
|
case Gfx::QueueType::GRAPHICS:
|
||||||
|
return graphicsCommands;
|
||||||
|
case Gfx::QueueType::COMPUTE:
|
||||||
|
return computeCommands;
|
||||||
|
case Gfx::QueueType::TRANSFER:
|
||||||
|
return transferCommands;
|
||||||
|
case Gfx::QueueType::DEDICATED_TRANSFER:
|
||||||
|
return dedicatedTransferCommands;
|
||||||
|
default:
|
||||||
|
throw new std::logic_error("invalid queue type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PCommandBufferManager Graphics::getGraphicsCommands()
|
PCommandBufferManager Graphics::getGraphicsCommands()
|
||||||
{
|
{
|
||||||
return graphicsCommands;
|
return graphicsCommands;
|
||||||
|
|||||||
@@ -22,15 +22,12 @@ public:
|
|||||||
VkDevice getDevice() const;
|
VkDevice getDevice() const;
|
||||||
VkPhysicalDevice getPhysicalDevice() const;
|
VkPhysicalDevice getPhysicalDevice() const;
|
||||||
|
|
||||||
|
PCommandBufferManager getQueueCommands(Gfx::QueueType queueType);
|
||||||
PCommandBufferManager getGraphicsCommands();
|
PCommandBufferManager getGraphicsCommands();
|
||||||
PCommandBufferManager getComputeCommands();
|
PCommandBufferManager getComputeCommands();
|
||||||
PCommandBufferManager getTransferCommands();
|
PCommandBufferManager getTransferCommands();
|
||||||
PCommandBufferManager getDedicatedTransferCommands();
|
PCommandBufferManager getDedicatedTransferCommands();
|
||||||
|
|
||||||
const QueueFamilyMapping getFamilyMapping() const
|
|
||||||
{
|
|
||||||
return queueMapping;
|
|
||||||
}
|
|
||||||
QueueOwnedResourceDeletion &getDeletionQueue()
|
QueueOwnedResourceDeletion &getDeletionQueue()
|
||||||
{
|
{
|
||||||
return deletionQueue;
|
return deletionQueue;
|
||||||
@@ -56,8 +53,16 @@ public:
|
|||||||
virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override;
|
virtual Gfx::PVertexBuffer createVertexBuffer(const VertexBufferCreateInfo &bulkData) override;
|
||||||
virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override;
|
virtual Gfx::PIndexBuffer createIndexBuffer(const IndexBufferCreateInfo &bulkData) override;
|
||||||
virtual Gfx::PRenderCommand createRenderCommand() override;
|
virtual Gfx::PRenderCommand createRenderCommand() override;
|
||||||
|
virtual Gfx::PVertexShader createVertexShader(const ShaderCreateInfo& createInfo) override;
|
||||||
|
virtual Gfx::PControlShader createControlShader(const ShaderCreateInfo& createInfo) override;
|
||||||
|
virtual Gfx::PEvaluationShader createEvaluationShader(const ShaderCreateInfo& createInfo) override;
|
||||||
|
virtual Gfx::PGeometryShader createGeometryShader(const ShaderCreateInfo& createInfo) override;
|
||||||
|
virtual Gfx::PFragmentShader createFragmentShader(const ShaderCreateInfo& createInfo) override;
|
||||||
virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override;
|
virtual Gfx::PGraphicsPipeline createGraphicsPipeline(const GraphicsPipelineCreateInfo& createInfo) override;
|
||||||
|
|
||||||
|
virtual Gfx::PDescriptorLayout createDescriptorLayout() override;
|
||||||
|
virtual Gfx::PPipelineLayout createPipelineLayout() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Array<const char *> getRequiredExtensions();
|
Array<const char *> getRequiredExtensions();
|
||||||
void initInstance(GraphicsInitializer initInfo);
|
void initInstance(GraphicsInitializer initInfo);
|
||||||
@@ -73,7 +78,6 @@ protected:
|
|||||||
PQueue computeQueue;
|
PQueue computeQueue;
|
||||||
PQueue transferQueue;
|
PQueue transferQueue;
|
||||||
PQueue dedicatedTransferQueue;
|
PQueue dedicatedTransferQueue;
|
||||||
QueueFamilyMapping queueMapping;
|
|
||||||
QueueOwnedResourceDeletion deletionQueue;
|
QueueOwnedResourceDeletion deletionQueue;
|
||||||
PPipelineCache pipelineCache;
|
PPipelineCache pipelineCache;
|
||||||
PCommandBufferManager graphicsCommands;
|
PCommandBufferManager graphicsCommands;
|
||||||
|
|||||||
@@ -50,47 +50,6 @@ void QueueOwnedResourceDeletion::run()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueOwnedResource::QueueOwnedResource(PGraphics graphics, Gfx::QueueType startQueueType)
|
|
||||||
: graphics(graphics), currentOwner(startQueueType)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QueueOwnedResource::~QueueOwnedResource()
|
|
||||||
{
|
|
||||||
cachedCmdBufferManager = nullptr;
|
|
||||||
graphics = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QueueOwnedResource::transferOwnership(Gfx::QueueType newOwner)
|
|
||||||
{
|
|
||||||
if (graphics->getFamilyMapping().needsTransfer(currentOwner, newOwner))
|
|
||||||
{
|
|
||||||
executeOwnershipBarrier(newOwner);
|
|
||||||
currentOwner = newOwner;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PCommandBufferManager QueueOwnedResource::getCommands()
|
|
||||||
{
|
|
||||||
if (cachedCmdBufferManager != nullptr)
|
|
||||||
{
|
|
||||||
assert(cachedCmdBufferManager->getQueue()->getFamilyIndex() == graphics->getFamilyMapping().getQueueTypeFamilyIndex(currentOwner));
|
|
||||||
return cachedCmdBufferManager;
|
|
||||||
}
|
|
||||||
switch (currentOwner)
|
|
||||||
{
|
|
||||||
case Gfx::QueueType::GRAPHICS:
|
|
||||||
return graphics->getGraphicsCommands();
|
|
||||||
case Gfx::QueueType::COMPUTE:
|
|
||||||
return graphics->getComputeCommands();
|
|
||||||
case Gfx::QueueType::TRANSFER:
|
|
||||||
return graphics->getTransferCommands();
|
|
||||||
case Gfx::QueueType::DEDICATED_TRANSFER:
|
|
||||||
return graphics->getDedicatedTransferCommands();
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Semaphore::Semaphore(PGraphics graphics)
|
Semaphore::Semaphore(PGraphics graphics)
|
||||||
: graphics(graphics)
|
: graphics(graphics)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Graphics/GraphicsResources.h"
|
#include "Graphics/GraphicsResources.h"
|
||||||
#include <thread>
|
|
||||||
#include <functional>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
@@ -54,35 +51,6 @@ private:
|
|||||||
};
|
};
|
||||||
DEFINE_REF(Fence);
|
DEFINE_REF(Fence);
|
||||||
|
|
||||||
struct QueueFamilyMapping
|
|
||||||
{
|
|
||||||
uint32 graphicsFamily;
|
|
||||||
uint32 computeFamily;
|
|
||||||
uint32 transferFamily;
|
|
||||||
uint32 dedicatedTransferFamily;
|
|
||||||
uint32 getQueueTypeFamilyIndex(Gfx::QueueType type) const
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case Gfx::QueueType::GRAPHICS:
|
|
||||||
return graphicsFamily;
|
|
||||||
case Gfx::QueueType::COMPUTE:
|
|
||||||
return computeFamily;
|
|
||||||
case Gfx::QueueType::TRANSFER:
|
|
||||||
return transferFamily;
|
|
||||||
case Gfx::QueueType::DEDICATED_TRANSFER:
|
|
||||||
return dedicatedTransferFamily;
|
|
||||||
default:
|
|
||||||
return VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool needsTransfer(Gfx::QueueType src, Gfx::QueueType dst) const
|
|
||||||
{
|
|
||||||
uint32 srcIndex = getQueueTypeFamilyIndex(src);
|
|
||||||
uint32 dstIndex = getQueueTypeFamilyIndex(dst);
|
|
||||||
return srcIndex != dstIndex;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
class QueueOwnedResourceDeletion
|
class QueueOwnedResourceDeletion
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -103,24 +71,8 @@ private:
|
|||||||
static std::condition_variable cv;
|
static std::condition_variable cv;
|
||||||
static List<PendingItem> deletionQueue;
|
static List<PendingItem> deletionQueue;
|
||||||
};
|
};
|
||||||
class QueueOwnedResource
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QueueOwnedResource(PGraphics graphics, Gfx::QueueType startQueueType);
|
|
||||||
virtual ~QueueOwnedResource();
|
|
||||||
PCommandBufferManager getCommands();
|
|
||||||
//Preliminary checks to see if the barrier should be executed at all
|
|
||||||
void transferOwnership(Gfx::QueueType newOwner);
|
|
||||||
|
|
||||||
protected:
|
class Buffer
|
||||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner) = 0;
|
|
||||||
Gfx::QueueType currentOwner;
|
|
||||||
PGraphics graphics;
|
|
||||||
PCommandBufferManager cachedCmdBufferManager;
|
|
||||||
};
|
|
||||||
DEFINE_REF(QueueOwnedResource);
|
|
||||||
|
|
||||||
class Buffer : public QueueOwnedResource
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType);
|
Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType);
|
||||||
@@ -146,11 +98,14 @@ protected:
|
|||||||
uint32 numBuffers;
|
uint32 numBuffers;
|
||||||
uint32 currentBuffer;
|
uint32 currentBuffer;
|
||||||
uint32 size;
|
uint32 size;
|
||||||
|
PGraphics graphics;
|
||||||
|
Gfx::QueueType currentOwner;
|
||||||
|
|
||||||
|
void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||||
|
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner) = 0;
|
||||||
|
|
||||||
virtual VkAccessFlags getSourceAccessMask() = 0;
|
virtual VkAccessFlags getSourceAccessMask() = 0;
|
||||||
virtual VkAccessFlags getDestAccessMask() = 0;
|
virtual VkAccessFlags getDestAccessMask() = 0;
|
||||||
// Inherited via QueueOwnedResource
|
|
||||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
|
||||||
};
|
};
|
||||||
DEFINE_REF(Buffer);
|
DEFINE_REF(Buffer);
|
||||||
|
|
||||||
@@ -161,8 +116,12 @@ public:
|
|||||||
virtual ~UniformBuffer();
|
virtual ~UniformBuffer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Inherited via Vulkan::Buffer
|
||||||
|
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
|
||||||
virtual VkAccessFlags getSourceAccessMask();
|
virtual VkAccessFlags getSourceAccessMask();
|
||||||
virtual VkAccessFlags getDestAccessMask();
|
virtual VkAccessFlags getDestAccessMask();
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||||
};
|
};
|
||||||
DEFINE_REF(UniformBuffer);
|
DEFINE_REF(UniformBuffer);
|
||||||
|
|
||||||
@@ -173,8 +132,12 @@ public:
|
|||||||
virtual ~StructuredBuffer();
|
virtual ~StructuredBuffer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Inherited via Vulkan::Buffer
|
||||||
virtual VkAccessFlags getSourceAccessMask();
|
virtual VkAccessFlags getSourceAccessMask();
|
||||||
virtual VkAccessFlags getDestAccessMask();
|
virtual VkAccessFlags getDestAccessMask();
|
||||||
|
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||||
};
|
};
|
||||||
DEFINE_REF(StructuredBuffer);
|
DEFINE_REF(StructuredBuffer);
|
||||||
|
|
||||||
@@ -185,8 +148,12 @@ public:
|
|||||||
virtual ~VertexBuffer();
|
virtual ~VertexBuffer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Inherited via Vulkan::Buffer
|
||||||
virtual VkAccessFlags getSourceAccessMask();
|
virtual VkAccessFlags getSourceAccessMask();
|
||||||
virtual VkAccessFlags getDestAccessMask();
|
virtual VkAccessFlags getDestAccessMask();
|
||||||
|
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||||
};
|
};
|
||||||
DEFINE_REF(VertexBuffer);
|
DEFINE_REF(VertexBuffer);
|
||||||
|
|
||||||
@@ -197,17 +164,20 @@ public:
|
|||||||
virtual ~IndexBuffer();
|
virtual ~IndexBuffer();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Inherited via Vulkan::Buffer
|
||||||
|
virtual void requestOwnershipTransfer(Gfx::QueueType newOwner);
|
||||||
virtual VkAccessFlags getSourceAccessMask();
|
virtual VkAccessFlags getSourceAccessMask();
|
||||||
virtual VkAccessFlags getDestAccessMask();
|
virtual VkAccessFlags getDestAccessMask();
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||||
};
|
};
|
||||||
DEFINE_REF(IndexBuffer);
|
DEFINE_REF(IndexBuffer);
|
||||||
|
|
||||||
class TextureHandle : public QueueOwnedResource
|
class TextureHandle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TextureHandle(PGraphics graphics, VkImageViewType viewType, uint32 sizeX, uint32 sizeY, uint32 sizeZ,
|
TextureHandle(PGraphics graphics, VkImageViewType viewType,
|
||||||
bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format,
|
const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
|
||||||
uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE);
|
|
||||||
virtual ~TextureHandle();
|
virtual ~TextureHandle();
|
||||||
|
|
||||||
inline VkImageView getView() const
|
inline VkImageView getView() const
|
||||||
@@ -234,9 +204,10 @@ public:
|
|||||||
{
|
{
|
||||||
return aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
|
return aspect & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT);
|
||||||
}
|
}
|
||||||
// Inherited via QueueOwnedResource
|
void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||||
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
void changeLayout(VkImageLayout newLayout);
|
||||||
|
|
||||||
|
Gfx::QueueType currentOwner;
|
||||||
private:
|
private:
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
PSubAllocation allocation;
|
PSubAllocation allocation;
|
||||||
@@ -276,10 +247,7 @@ DEFINE_REF(TextureBase);
|
|||||||
class Texture2D : public TextureBase, public Gfx::Texture2D
|
class Texture2D : public TextureBase, public Gfx::Texture2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Texture2D(PGraphics graphics, uint32 sizeX, uint32 sizeY,
|
Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
|
||||||
bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format,
|
|
||||||
uint32 samples, Gfx::SeImageUsageFlags usage,
|
|
||||||
Gfx::QueueType owner = Gfx::QueueType::GRAPHICS, VkImage existingImage = VK_NULL_HANDLE);
|
|
||||||
virtual ~Texture2D();
|
virtual ~Texture2D();
|
||||||
inline uint32 getSizeX() const
|
inline uint32 getSizeX() const
|
||||||
{
|
{
|
||||||
@@ -305,8 +273,10 @@ public:
|
|||||||
{
|
{
|
||||||
return textureHandle->isDepthStencil();
|
return textureHandle->isDepthStencil();
|
||||||
}
|
}
|
||||||
|
protected:
|
||||||
|
// Inherited via QueueOwnedResource
|
||||||
|
virtual void executeOwnershipBarrier(Gfx::QueueType newOwner);
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
DEFINE_REF(Texture2D);
|
DEFINE_REF(Texture2D);
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ using namespace Seele;
|
|||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
GraphicsPipeline::GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo)
|
GraphicsPipeline::GraphicsPipeline(PGraphics graphics, VkPipeline handle, PPipelineLayout pipelineLayout, const GraphicsPipelineCreateInfo& createInfo)
|
||||||
: Gfx::GraphicsPipeline(createInfo)
|
: Gfx::GraphicsPipeline(createInfo, pipelineLayout)
|
||||||
, graphics(graphics)
|
, graphics(graphics)
|
||||||
, layout(pipelineLayout)
|
|
||||||
, pipeline(handle)
|
, pipeline(handle)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -24,5 +23,5 @@ void GraphicsPipeline::bind(VkCommandBuffer handle)
|
|||||||
|
|
||||||
VkPipelineLayout GraphicsPipeline::getLayout() const
|
VkPipelineLayout GraphicsPipeline::getLayout() const
|
||||||
{
|
{
|
||||||
return layout->getHandle();
|
return layout.cast<PipelineLayout>()->getHandle();
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,6 @@ public:
|
|||||||
VkPipelineLayout getLayout() const;
|
VkPipelineLayout getLayout() const;
|
||||||
private:
|
private:
|
||||||
VkPipeline pipeline;
|
VkPipeline pipeline;
|
||||||
PPipelineLayout layout;
|
|
||||||
PGraphics graphics;
|
PGraphics graphics;
|
||||||
};
|
};
|
||||||
DEFINE_REF(GraphicsPipeline);
|
DEFINE_REF(GraphicsPipeline);
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
createInfo.pNext = 0;
|
createInfo.pNext = 0;
|
||||||
createInfo.flags = 0;
|
createInfo.flags = 0;
|
||||||
createInfo.stageCount = 0;
|
createInfo.stageCount = 0;
|
||||||
|
|
||||||
|
PPipelineLayout layout = graphics->createPipelineLayout();
|
||||||
|
|
||||||
VkPipelineTessellationStateCreateInfo tessInfo;
|
VkPipelineTessellationStateCreateInfo tessInfo;
|
||||||
VkPipelineShaderStageCreateInfo stageInfos[5];
|
VkPipelineShaderStageCreateInfo stageInfos[5];
|
||||||
std::memset(stageInfos, 0, sizeof(stageInfos));
|
std::memset(stageInfos, 0, sizeof(stageInfos));
|
||||||
@@ -63,6 +66,10 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
vertInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
vertInfo.stage = VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
vertInfo.module = shader->getModuleHandle();
|
vertInfo.module = shader->getModuleHandle();
|
||||||
vertInfo.pName = shader->getEntryPointName();
|
vertInfo.pName = shader->getEntryPointName();
|
||||||
|
for(auto descriptor : shader->getDescriptorLayouts())
|
||||||
|
{
|
||||||
|
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(gfxInfo.controlShader != nullptr)
|
if(gfxInfo.controlShader != nullptr)
|
||||||
{
|
{
|
||||||
@@ -86,6 +93,15 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
tessInfo.pNext = 0;
|
tessInfo.pNext = 0;
|
||||||
tessInfo.flags = 0;
|
tessInfo.flags = 0;
|
||||||
tessInfo.patchControlPoints = control->getNumPatches();
|
tessInfo.patchControlPoints = control->getNumPatches();
|
||||||
|
|
||||||
|
for(auto descriptor : eval->getDescriptorLayouts())
|
||||||
|
{
|
||||||
|
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||||
|
}
|
||||||
|
for(auto descriptor : control->getDescriptorLayouts())
|
||||||
|
{
|
||||||
|
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(gfxInfo.geometryShader != nullptr)
|
if(gfxInfo.geometryShader != nullptr)
|
||||||
{
|
{
|
||||||
@@ -96,6 +112,11 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
geometryInfo.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
|
geometryInfo.stage = VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||||
geometryInfo.module = geometry->getModuleHandle();
|
geometryInfo.module = geometry->getModuleHandle();
|
||||||
geometryInfo.pName = geometry->getEntryPointName();
|
geometryInfo.pName = geometry->getEntryPointName();
|
||||||
|
|
||||||
|
for(auto descriptor : geometry->getDescriptorLayouts())
|
||||||
|
{
|
||||||
|
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(gfxInfo.fragmentShader != nullptr)
|
if(gfxInfo.fragmentShader != nullptr)
|
||||||
{
|
{
|
||||||
@@ -106,7 +127,13 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
fragmentInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
fragmentInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
fragmentInfo.module = fragment->getModuleHandle();
|
fragmentInfo.module = fragment->getModuleHandle();
|
||||||
fragmentInfo.pName = fragment->getEntryPointName();
|
fragmentInfo.pName = fragment->getEntryPointName();
|
||||||
|
|
||||||
|
for(auto descriptor : fragment->getDescriptorLayouts())
|
||||||
|
{
|
||||||
|
layout->addDescriptorLayout(descriptor.key, descriptor.value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
layout->create();
|
||||||
VkPipelineVertexInputStateCreateInfo vertexInput =
|
VkPipelineVertexInputStateCreateInfo vertexInput =
|
||||||
init::PipelineVertexInputStateCreateInfo();
|
init::PipelineVertexInputStateCreateInfo();
|
||||||
Gfx::PVertexDeclaration vertexDecl = gfxInfo.vertexDeclaration;
|
Gfx::PVertexDeclaration vertexDecl = gfxInfo.vertexDeclaration;
|
||||||
@@ -116,7 +143,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
uint32 bindingNum = 0;
|
uint32 bindingNum = 0;
|
||||||
for(auto vertexBinding : vertexStreams)
|
for(auto vertexBinding : vertexStreams)
|
||||||
{
|
{
|
||||||
uint32 stride = vertexBinding.getVertexBuffer()->getVertexSize();
|
uint32 stride = 0;
|
||||||
for(auto vertexAttrib : vertexBinding.getVertexDescriptions())
|
for(auto vertexAttrib : vertexBinding.getVertexDescriptions())
|
||||||
{
|
{
|
||||||
auto attrib = attribDesc.add();
|
auto attrib = attribDesc.add();
|
||||||
@@ -137,9 +164,9 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
|
|
||||||
VkPipelineInputAssemblyStateCreateInfo assemblyInfo =
|
VkPipelineInputAssemblyStateCreateInfo assemblyInfo =
|
||||||
init::PipelineInputAssemblyStateCreateInfo(
|
init::PipelineInputAssemblyStateCreateInfo(
|
||||||
cast(gfxInfo.topology),
|
cast(gfxInfo.topology),
|
||||||
0,
|
0,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
VkPipelineViewportStateCreateInfo viewportInfo =
|
VkPipelineViewportStateCreateInfo viewportInfo =
|
||||||
@@ -214,6 +241,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
createInfo.pStages = stageInfos;
|
createInfo.pStages = stageInfos;
|
||||||
createInfo.pVertexInputState = &vertexInput;
|
createInfo.pVertexInputState = &vertexInput;
|
||||||
createInfo.pInputAssemblyState = &assemblyInfo;
|
createInfo.pInputAssemblyState = &assemblyInfo;
|
||||||
@@ -225,7 +253,7 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
createInfo.pColorBlendState = &blendState;
|
createInfo.pColorBlendState = &blendState;
|
||||||
createInfo.pDynamicState = &dynamicState;
|
createInfo.pDynamicState = &dynamicState;
|
||||||
createInfo.renderPass = gfxInfo.renderPass.cast<RenderPass>()->getHandle();
|
createInfo.renderPass = gfxInfo.renderPass.cast<RenderPass>()->getHandle();
|
||||||
createInfo.layout = gfxInfo.pipelineLayout.cast<PipelineLayout>()->getHandle();
|
createInfo.layout = layout->getHandle();
|
||||||
createInfo.subpass = 0;
|
createInfo.subpass = 0;
|
||||||
|
|
||||||
VkPipeline pipelineHandle;
|
VkPipeline pipelineHandle;
|
||||||
@@ -235,6 +263,6 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
|||||||
int64 delta = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - beginTime).count();
|
int64 delta = std::chrono::duration_cast<std::chrono::milliseconds>(endTime - beginTime).count();
|
||||||
std::cout << "Gfx creation time: " << delta << std::endl;
|
std::cout << "Gfx creation time: " << delta << std::endl;
|
||||||
|
|
||||||
PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, gfxInfo.pipelineLayout.cast<PipelineLayout>(), gfxInfo);
|
PGraphicsPipeline result = new GraphicsPipeline(graphics, pipelineHandle, layout, gfxInfo);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,102 @@
|
|||||||
#include "VulkanShader.h"
|
#include "VulkanShader.h"
|
||||||
|
#include "VulkanGraphics.h"
|
||||||
|
#include "VulkanDescriptorSets.h"
|
||||||
|
#include "slang.h"
|
||||||
|
|
||||||
|
using namespace slang;
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using namespace Seele::Vulkan;
|
using namespace Seele::Vulkan;
|
||||||
|
|
||||||
|
Shader::Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage)
|
||||||
|
: graphics(graphics)
|
||||||
|
, type(shaderType)
|
||||||
|
, stage(stage)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader::~Shader()
|
||||||
|
{
|
||||||
|
if(module != VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
vkDestroyShaderModule(graphics->getDevice(), module, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<uint32, PDescriptorLayout> Shader::getDescriptorLayouts()
|
||||||
|
{
|
||||||
|
return descriptorSets;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SlangStage getStageFromShaderType(ShaderType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ShaderType::VERTEX:
|
||||||
|
return SLANG_STAGE_VERTEX;
|
||||||
|
case ShaderType::CONTROL:
|
||||||
|
return SLANG_STAGE_HULL;
|
||||||
|
case ShaderType::EVALUATION:
|
||||||
|
return SLANG_STAGE_DOMAIN;
|
||||||
|
case ShaderType::GEOMETRY:
|
||||||
|
return SLANG_STAGE_GEOMETRY;
|
||||||
|
case ShaderType::FRAGMENT:
|
||||||
|
return SLANG_STAGE_PIXEL;
|
||||||
|
default:
|
||||||
|
return SLANG_STAGE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::create(const ShaderCreateInfo& createInfo)
|
||||||
|
{
|
||||||
|
entryPointName = createInfo.entryPoint;
|
||||||
|
static SlangSession* session = spCreateSession(NULL);
|
||||||
|
|
||||||
|
SlangCompileRequest* request = spCreateCompileRequest(session);
|
||||||
|
int targetIndex = spAddCodeGenTarget(request, SLANG_SPIRV);
|
||||||
|
spSetTargetProfile(request, targetIndex, spFindProfile(session, "glsl_vk"));
|
||||||
|
spSetDumpIntermediates(request, true);
|
||||||
|
|
||||||
|
int translationUnitIndex = spAddTranslationUnit(request, SLANG_SOURCE_LANGUAGE_SLANG, "");
|
||||||
|
|
||||||
|
spAddTranslationUnitSourceString(
|
||||||
|
request,
|
||||||
|
translationUnitIndex,
|
||||||
|
entryPointName.c_str(),
|
||||||
|
createInfo.code.c_str()
|
||||||
|
);
|
||||||
|
spAddSearchPath(request, "shaders/lib/");
|
||||||
|
|
||||||
|
spSetGlobalGenericArgs(request, createInfo.typeParameter.size(), createInfo.typeParameter.data());
|
||||||
|
|
||||||
|
int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type));
|
||||||
|
if(spCompile(request))
|
||||||
|
{
|
||||||
|
char const* diagnostice = spGetDiagnosticOutput(request);
|
||||||
|
std::cout << diagnostice << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderReflection* reflection = slang::ShaderReflection::get(request);
|
||||||
|
|
||||||
|
uint32 parameterCount = reflection->getParameterCount();
|
||||||
|
for(uint32 i = 0; i < parameterCount; ++i)
|
||||||
|
{
|
||||||
|
VariableLayoutReflection* parameter =
|
||||||
|
reflection->getParameterByIndex(i);
|
||||||
|
uint32 descriptorIndex = parameter->getBindingSpace();
|
||||||
|
uint32 descriptorBinding = parameter->getBindingIndex();
|
||||||
|
PDescriptorLayout& layout = descriptorSets[descriptorIndex];
|
||||||
|
std::cout << parameter->getTypeLayout()->getName() << std::endl;
|
||||||
|
//layout->addDescriptorBinding(descriptorBinding, parame)
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t dataSize = 0;
|
||||||
|
const void* data = spGetEntryPointCode(request, entryPointIndex, &dataSize);
|
||||||
|
|
||||||
|
VkShaderModuleCreateInfo moduleInfo;
|
||||||
|
moduleInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
|
moduleInfo.pNext = nullptr;
|
||||||
|
moduleInfo.flags = 0;
|
||||||
|
moduleInfo.codeSize = dataSize;
|
||||||
|
moduleInfo.pCode = static_cast<const uint32*>(data);
|
||||||
|
VK_CHECK(vkCreateShaderModule(graphics->getDevice(), &moduleInfo, nullptr, &module));
|
||||||
|
}
|
||||||
@@ -6,13 +6,16 @@ namespace Seele
|
|||||||
{
|
{
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
{
|
{
|
||||||
|
DECLARE_REF(Graphics);
|
||||||
|
DECLARE_REF(DescriptorLayout);
|
||||||
class Shader
|
class Shader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage);
|
Shader(PGraphics graphics, ShaderType shaderType, VkShaderStageFlags stage);
|
||||||
virtual ~Shader();
|
virtual ~Shader();
|
||||||
|
|
||||||
|
void create(const ShaderCreateInfo& createInfo);
|
||||||
|
|
||||||
VkShaderModule getModuleHandle() const
|
VkShaderModule getModuleHandle() const
|
||||||
{
|
{
|
||||||
return module;
|
return module;
|
||||||
@@ -21,18 +24,23 @@ public:
|
|||||||
{
|
{
|
||||||
return entryPointName.c_str();
|
return entryPointName.c_str();
|
||||||
}
|
}
|
||||||
|
Map<uint32, PDescriptorLayout> getDescriptorLayouts();
|
||||||
private:
|
private:
|
||||||
|
PGraphics graphics;
|
||||||
|
Map<uint32, PDescriptorLayout> descriptorSets;
|
||||||
VkShaderModule module;
|
VkShaderModule module;
|
||||||
|
VkShaderStageFlags stage;
|
||||||
|
ShaderType type;
|
||||||
std::string entryPointName;
|
std::string entryPointName;
|
||||||
};
|
};
|
||||||
DEFINE_REF(Shader);
|
DEFINE_REF(Shader);
|
||||||
|
|
||||||
template <typename Base, ShaderType shaderType, VkShaderStageFlags stage>
|
template <typename Base, ShaderType shaderType, VkShaderStageFlags stageFlags>
|
||||||
class ShaderBase : public Base, public Shader
|
class ShaderBase : public Base, public Shader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ShaderBase(PGraphics graphics)
|
ShaderBase(PGraphics graphics)
|
||||||
: Shader(graphics, shaderType, stage)
|
: Shader(graphics, shaderType, stageFlags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual ~ShaderBase()
|
virtual ~ShaderBase()
|
||||||
|
|||||||
@@ -29,10 +29,21 @@ VkImageAspectFlags getAspectFromFormat(Gfx::SeFormat format)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint32 sizeX, uint32 sizeY, uint32 sizeZ,
|
TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType,
|
||||||
bool bArray, uint32 arraySize, uint32 mipLevel,
|
const TextureCreateInfo& createInfo, VkImage existingImage)
|
||||||
Gfx::SeFormat format, uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner, VkImage existingImage)
|
: currentOwner(createInfo.resourceData.owner)
|
||||||
: QueueOwnedResource(graphics, owner), graphics(graphics), sizeX(sizeX), sizeY(sizeY), sizeZ(sizeZ), mipLevels(mipLevel), format(format), samples(samples), usage(usage), arrayCount(bArray ? arraySize : 1), aspect(getAspectFromFormat(format)), image(existingImage), layout(VK_IMAGE_LAYOUT_UNDEFINED)
|
, graphics(graphics)
|
||||||
|
, sizeX(createInfo.width)
|
||||||
|
, sizeY(createInfo.height)
|
||||||
|
, sizeZ(createInfo.depth)
|
||||||
|
, mipLevels(createInfo.mipLevels)
|
||||||
|
, format(createInfo.format)
|
||||||
|
, samples(createInfo.samples)
|
||||||
|
, usage(createInfo.usage)
|
||||||
|
, arrayCount(createInfo.bArray ? createInfo.arrayLayers : 1)
|
||||||
|
, aspect(getAspectFromFormat(createInfo.format))
|
||||||
|
, image(existingImage)
|
||||||
|
, layout(VK_IMAGE_LAYOUT_UNDEFINED)
|
||||||
{
|
{
|
||||||
if (existingImage == VK_NULL_HANDLE)
|
if (existingImage == VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
@@ -42,7 +53,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
|
|||||||
info.extent.width = sizeX;
|
info.extent.width = sizeX;
|
||||||
info.extent.height = sizeY;
|
info.extent.height = sizeY;
|
||||||
info.extent.depth = sizeZ;
|
info.extent.depth = sizeZ;
|
||||||
info.arrayLayers = arraySize;
|
info.arrayLayers = arrayCount;
|
||||||
info.format = cast(format);
|
info.format = cast(format);
|
||||||
|
|
||||||
uint32 layerCount = 1;
|
uint32 layerCount = 1;
|
||||||
@@ -67,13 +78,18 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
info.initialLayout = layout;
|
||||||
info.mipLevels = mipLevel;
|
info.mipLevels = mipLevels;
|
||||||
info.arrayLayers = arrayCount * layerCount;
|
info.arrayLayers = arrayCount * layerCount;
|
||||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
info.samples = (VkSampleCountFlagBits)samples;
|
info.samples = (VkSampleCountFlagBits)samples;
|
||||||
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
info.usage = usage;
|
info.usage = usage;
|
||||||
|
//To upload to the image we need to specify transfer dst
|
||||||
|
if(createInfo.resourceData.size > 0)
|
||||||
|
{
|
||||||
|
info.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||||
|
}
|
||||||
VK_CHECK(vkCreateImage(graphics->getDevice(), &info, nullptr, &image));
|
VK_CHECK(vkCreateImage(graphics->getDevice(), &info, nullptr, &image));
|
||||||
|
|
||||||
VkMemoryDedicatedRequirements memDedicatedRequirements;
|
VkMemoryDedicatedRequirements memDedicatedRequirements;
|
||||||
@@ -91,6 +107,37 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
|
|||||||
allocation = allocator->allocate(requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, image);
|
allocation = allocator->allocate(requirements, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, image);
|
||||||
vkBindImageMemory(graphics->getDevice(), image, allocation->getHandle(), allocation->getOffset());
|
vkBindImageMemory(graphics->getDevice(), image, allocation->getHandle(), allocation->getOffset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BulkResourceData& resourceData = createInfo.resourceData;
|
||||||
|
if(resourceData.size > 0)
|
||||||
|
{
|
||||||
|
changeLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
PStagingBuffer staging = graphics->getStagingManager()->allocateStagingBuffer(resourceData.size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
|
||||||
|
void* data = staging->getMappedPointer();
|
||||||
|
std::memcpy(data, resourceData.data, resourceData.size);
|
||||||
|
staging->flushMappedMemory();
|
||||||
|
|
||||||
|
PCommandBufferManager cmdBufferManager = graphics->getQueueCommands(currentOwner);
|
||||||
|
VkBufferImageCopy region;
|
||||||
|
region.bufferOffset = 0;
|
||||||
|
region.bufferRowLength = 0;
|
||||||
|
region.bufferImageHeight = 0;
|
||||||
|
|
||||||
|
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
region.imageSubresource.mipLevel = 0;
|
||||||
|
region.imageSubresource.baseArrayLayer = 0;
|
||||||
|
region.imageSubresource.layerCount = 1;
|
||||||
|
|
||||||
|
region.imageOffset = {0, 0, 0};
|
||||||
|
region.imageExtent = {sizeX, sizeX, sizeZ};
|
||||||
|
|
||||||
|
vkCmdCopyBufferToImage(cmdBufferManager->getCommands()->getHandle(),
|
||||||
|
staging->getHandle(), image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||||
|
|
||||||
|
// When loading a texture from a file, we will almost always use it as a texture map for fragment shaders
|
||||||
|
changeLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
|
}
|
||||||
|
|
||||||
VkImageViewCreateInfo viewInfo =
|
VkImageViewCreateInfo viewInfo =
|
||||||
init::ImageViewCreateInfo();
|
init::ImageViewCreateInfo();
|
||||||
viewInfo.subresourceRange = init::ImageSubresourceRange(aspect);
|
viewInfo.subresourceRange = init::ImageSubresourceRange(aspect);
|
||||||
@@ -106,7 +153,7 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, uint3
|
|||||||
TextureHandle::~TextureHandle()
|
TextureHandle::~TextureHandle()
|
||||||
{
|
{
|
||||||
auto &deletionQueue = graphics->getDeletionQueue();
|
auto &deletionQueue = graphics->getDeletionQueue();
|
||||||
auto fence = getCommands()->getCommands()->getFence();
|
auto fence = graphics->getQueueCommands(currentOwner)->getCommands()->getFence();
|
||||||
VkDevice device = graphics->getDevice();
|
VkDevice device = graphics->getDevice();
|
||||||
VkImageView view = defaultView;
|
VkImageView view = defaultView;
|
||||||
VkImage img = image;
|
VkImage img = image;
|
||||||
@@ -114,6 +161,20 @@ TextureHandle::~TextureHandle()
|
|||||||
deletionQueue.addPendingDelete(fence, [device, img]() { vkDestroyImage(device, img, nullptr); });
|
deletionQueue.addPendingDelete(fence, [device, img]() { vkDestroyImage(device, img, nullptr); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TextureHandle::changeLayout(VkImageLayout newLayout)
|
||||||
|
{
|
||||||
|
VkImageMemoryBarrier barrier =
|
||||||
|
init::ImageMemoryBarrier(
|
||||||
|
image,
|
||||||
|
layout,
|
||||||
|
newLayout);
|
||||||
|
PCommandBufferManager cmdManager = graphics->getQueueCommands(currentOwner);
|
||||||
|
vkCmdPipelineBarrier(cmdManager->getCommands()->getHandle(),
|
||||||
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
||||||
|
0, 0, nullptr, 0, nullptr, 1, &barrier);
|
||||||
|
layout = newLayout;
|
||||||
|
}
|
||||||
|
|
||||||
void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||||
{
|
{
|
||||||
VkImageMemoryBarrier imageBarrier =
|
VkImageMemoryBarrier imageBarrier =
|
||||||
@@ -122,11 +183,11 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
imageBarrier.oldLayout = layout;
|
imageBarrier.oldLayout = layout;
|
||||||
imageBarrier.newLayout = layout;
|
imageBarrier.newLayout = layout;
|
||||||
imageBarrier.subresourceRange = init::ImageSubresourceRange(aspect);
|
imageBarrier.subresourceRange = init::ImageSubresourceRange(aspect);
|
||||||
PCommandBufferManager sourceManager = getCommands();
|
PCommandBufferManager sourceManager = graphics->getQueueCommands(currentOwner);
|
||||||
PCommandBufferManager dstManager = nullptr;
|
PCommandBufferManager dstManager = nullptr;
|
||||||
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
|
||||||
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
Gfx::QueueFamilyMapping mapping = graphics->getFamilyMapping();
|
||||||
imageBarrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner);
|
imageBarrier.srcQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(currentOwner);
|
||||||
imageBarrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner);
|
imageBarrier.dstQueueFamilyIndex = mapping.getQueueTypeFamilyIndex(newOwner);
|
||||||
if (currentOwner == Gfx::QueueType::TRANSFER || currentOwner == Gfx::QueueType::DEDICATED_TRANSFER)
|
if (currentOwner == Gfx::QueueType::TRANSFER || currentOwner == Gfx::QueueType::DEDICATED_TRANSFER)
|
||||||
@@ -150,7 +211,7 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
dstManager = graphics->getTransferCommands();
|
dstManager = graphics->getTransferCommands();
|
||||||
}
|
}
|
||||||
else if (currentOwner == Gfx::QueueType::DEDICATED_TRANSFER)
|
else if (newOwner == Gfx::QueueType::DEDICATED_TRANSFER)
|
||||||
{
|
{
|
||||||
imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
imageBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||||
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
dstStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
@@ -173,30 +234,25 @@ void TextureHandle::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
|||||||
vkCmdPipelineBarrier(sourceCmd, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
|
vkCmdPipelineBarrier(sourceCmd, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
|
||||||
vkCmdPipelineBarrier(destCmd, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
|
vkCmdPipelineBarrier(destCmd, srcStage, dstStage, 0, 0, nullptr, 0, nullptr, 1, &imageBarrier);
|
||||||
sourceManager->submitCommands();
|
sourceManager->submitCommands();
|
||||||
cachedCmdBufferManager = dstManager;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureBase::changeLayout(VkImageLayout newLayout)
|
void TextureBase::changeLayout(VkImageLayout newLayout)
|
||||||
{
|
{
|
||||||
VkImageMemoryBarrier barrier =
|
textureHandle->changeLayout(newLayout);
|
||||||
init::ImageMemoryBarrier(
|
|
||||||
textureHandle->image,
|
|
||||||
textureHandle->layout,
|
|
||||||
newLayout);
|
|
||||||
vkCmdPipelineBarrier(textureHandle->getCommands()->getCommands()->getHandle(),
|
|
||||||
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
|
||||||
0, 0, nullptr, 0, nullptr, 1, &barrier);
|
|
||||||
textureHandle->layout = newLayout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture2D::Texture2D(PGraphics graphics, uint32 sizeX, uint32 sizeY,
|
Texture2D::Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage)
|
||||||
bool bArray, uint32 arraySize, uint32 mipLevels, Gfx::SeFormat format,
|
: Gfx::Texture2D(graphics, createInfo.resourceData.owner)
|
||||||
uint32 samples, Gfx::SeImageUsageFlags usage, Gfx::QueueType owner, VkImage existingImage)
|
|
||||||
{
|
{
|
||||||
textureHandle = new TextureHandle(graphics, bArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
|
textureHandle = new TextureHandle(graphics, createInfo.bArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
|
||||||
sizeX, sizeY, 1, bArray, arraySize, mipLevels, format, samples, usage, owner, existingImage);
|
createInfo, existingImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture2D::~Texture2D()
|
Texture2D::~Texture2D()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Texture2D::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||||
|
{
|
||||||
|
textureHandle->executeOwnershipBarrier(newOwner);
|
||||||
|
}
|
||||||
@@ -181,13 +181,17 @@ void Window::createSwapchain()
|
|||||||
|
|
||||||
PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands();
|
PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands();
|
||||||
|
|
||||||
|
TextureCreateInfo backBufferCreateInfo;
|
||||||
|
backBufferCreateInfo.width = sizeX;
|
||||||
|
backBufferCreateInfo.height = sizeY;
|
||||||
|
backBufferCreateInfo.usage = Gfx::SE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
backBufferCreateInfo.resourceData.owner = Gfx::QueueType::GRAPHICS;
|
||||||
|
backBufferCreateInfo.format = cast(surfaceFormat.format);
|
||||||
for (uint32 i = 0; i < numSwapchainImages; ++i)
|
for (uint32 i = 0; i < numSwapchainImages; ++i)
|
||||||
{
|
{
|
||||||
imageAcquired[i] = new Semaphore(graphics);
|
imageAcquired[i] = new Semaphore(graphics);
|
||||||
renderFinished[i] = new Semaphore(graphics);
|
renderFinished[i] = new Semaphore(graphics);
|
||||||
backBufferImages[i] = new Texture2D(graphics, sizeX, sizeY, false, 1, 1,
|
backBufferImages[i] = new Texture2D(graphics, backBufferCreateInfo, swapchainImages[i]);
|
||||||
cast(surfaceFormat.format), 1, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
|
||||||
Gfx::QueueType::GRAPHICS, swapchainImages[i]);
|
|
||||||
|
|
||||||
VkClearColorValue clearColor;
|
VkClearColorValue clearColor;
|
||||||
std::memset(&clearColor, 0, sizeof(VkClearColorValue));
|
std::memset(&clearColor, 0, sizeof(VkClearColorValue));
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "WindowManager.h"
|
#include "WindowManager.h"
|
||||||
#include "Vulkan/VulkanGraphics.h"
|
#include "Vulkan/VulkanGraphics.h"
|
||||||
|
|
||||||
|
Gfx::PGraphics WindowManager::graphics;
|
||||||
|
|
||||||
Seele::WindowManager::WindowManager()
|
Seele::WindowManager::WindowManager()
|
||||||
{
|
{
|
||||||
graphics = new Vulkan::Graphics();
|
graphics = new Vulkan::Graphics();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public:
|
|||||||
PWindow addWindow(const WindowCreateInfo &createInfo);
|
PWindow addWindow(const WindowCreateInfo &createInfo);
|
||||||
void beginFrame();
|
void beginFrame();
|
||||||
void endFrame();
|
void endFrame();
|
||||||
Gfx::PGraphics getGraphics()
|
static Gfx::PGraphics getGraphics()
|
||||||
{
|
{
|
||||||
return graphics;
|
return graphics;
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Array<PWindow> windows;
|
Array<PWindow> windows;
|
||||||
Gfx::PGraphics graphics;
|
static Gfx::PGraphics graphics;
|
||||||
};
|
};
|
||||||
DEFINE_REF(WindowManager);
|
DEFINE_REF(WindowManager);
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -2,5 +2,8 @@ target_sources(SeeleEngine
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
Material.h
|
Material.h
|
||||||
Material.cpp
|
Material.cpp
|
||||||
|
MaterialAsset.h
|
||||||
|
MaterialAsset.cpp
|
||||||
MaterialInstance.h
|
MaterialInstance.h
|
||||||
MaterialInstance.cpp)
|
MaterialInstance.cpp
|
||||||
|
ShaderExpression.h)
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "Material.h"
|
#include "Material.h"
|
||||||
|
#include "Asset/AssetRegistry.h"
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
using namespace Seele;
|
using namespace Seele;
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
@@ -9,12 +11,12 @@ Material::Material()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Material::Material(const std::string& directory, const std::string& name)
|
Material::Material(const std::string& directory, const std::string& name)
|
||||||
: FileAsset(directory, name)
|
: MaterialAsset(directory, name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Material::Material(const std::string& fullPath)
|
Material::Material(const std::string& fullPath)
|
||||||
: FileAsset(fullPath)
|
: MaterialAsset(fullPath)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,16 +24,71 @@ Material::~Material()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Material::compile()
|
void Material::compile()
|
||||||
{
|
{
|
||||||
auto& stream = getReadStream();
|
auto& stream = getReadStream();
|
||||||
stream.seekg(0);
|
|
||||||
json j;
|
json j;
|
||||||
stream >> j;
|
stream >> j;
|
||||||
std::cout << j["test"] << std::endl;
|
std::stringstream codeStream;
|
||||||
}
|
materialName = j["name"].get<std::string>();
|
||||||
|
std::string profile = j["profile"].get<std::string>();
|
||||||
|
codeStream << "import LightEnv;" << std::endl;
|
||||||
|
codeStream << "import Material;" << std::endl;
|
||||||
|
codeStream << "import BRDF;" << std::endl;
|
||||||
|
codeStream << "import InputGeometry;" << std::endl;
|
||||||
|
|
||||||
Gfx::PGraphicsPipeline Material::getPipeline()
|
codeStream << "struct " << materialName << ": IMaterial {" << std::endl;
|
||||||
{
|
for(auto param : j["params"].items())
|
||||||
return pipeline;
|
{
|
||||||
|
std::string type = param.value()["type"].get<std::string>();
|
||||||
|
|
||||||
|
auto default = param.value().find("default");
|
||||||
|
if(type.compare("float") == 0)
|
||||||
|
{
|
||||||
|
PFloatParameter p = new FloatParameter();
|
||||||
|
if(default != param.value().end())
|
||||||
|
{
|
||||||
|
p->defaultValue = std::stof(default.value().get<std::string>());
|
||||||
|
}
|
||||||
|
parameters.add(p);
|
||||||
|
}
|
||||||
|
else if(type.compare("float3") == 0)
|
||||||
|
{
|
||||||
|
PVectorParameter p = new VectorParameter();
|
||||||
|
if(default != param.value().end())
|
||||||
|
{
|
||||||
|
p->defaultValue = parseVector(default.value().get<std::string>().c_str());
|
||||||
|
}
|
||||||
|
parameters.add(p);
|
||||||
|
}
|
||||||
|
else if(type.compare("Texture2D") == 0)
|
||||||
|
{
|
||||||
|
PTextureParameter p = new TextureParameter();
|
||||||
|
if(default != param.value().end())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
parameters.add(p);
|
||||||
|
}
|
||||||
|
else if(type.compare("SamplerState") == 0)
|
||||||
|
{
|
||||||
|
PSamplerParameter p = new SamplerParameter();
|
||||||
|
parameters.add(p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << "Error unsupported parameter type" << std::endl;
|
||||||
|
}
|
||||||
|
codeStream << type << " " << param.key();
|
||||||
|
}
|
||||||
|
codeStream << "typedef " << profile << " BRDF;" << std::endl;
|
||||||
|
codeStream << profile << " prepare(MaterialPixelParameter geometry){" << std::endl;
|
||||||
|
codeStream << profile << " result;" << std::endl;
|
||||||
|
for(auto c : j["code"].items())
|
||||||
|
{
|
||||||
|
codeStream << c.value().get<std::string>() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
codeStream << "}};" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -1,44 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "MinimalEngine.h"
|
#include "MinimalEngine.h"
|
||||||
#include "Asset/FileAsset.h"
|
#include "MaterialAsset.h"
|
||||||
#include "Graphics/GraphicsResources.h"
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
|
||||||
|
|
||||||
namespace Seele
|
namespace Seele
|
||||||
{
|
{
|
||||||
struct FloatExpression
|
|
||||||
{
|
class Material : public MaterialAsset
|
||||||
float data;
|
|
||||||
std::string name;
|
|
||||||
uint32 location;
|
|
||||||
};
|
|
||||||
struct VectorExpression
|
|
||||||
{
|
|
||||||
Vector data;
|
|
||||||
std::string name;
|
|
||||||
uint32 location;
|
|
||||||
};
|
|
||||||
struct TextureExpression
|
|
||||||
{
|
|
||||||
Gfx::PTexture texture;
|
|
||||||
std::string name;
|
|
||||||
uint32 location;
|
|
||||||
};
|
|
||||||
DECLARE_NAME_REF(Gfx, GraphicsPipeline);
|
|
||||||
DECLARE_NAME_REF(Gfx, PipelineLayout);
|
|
||||||
class Material : public FileAsset
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Material();
|
Material();
|
||||||
Material(const std::string &directory, const std::string &name);
|
Material(const std::string &directory, const std::string &name);
|
||||||
Material(const std::string &fullPath);
|
Material(const std::string &fullPath);
|
||||||
~Material();
|
~Material();
|
||||||
void compile();
|
inline std::string getMaterialName() const {return materialName;}
|
||||||
Gfx::PGraphicsPipeline getPipeline();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Gfx::PGraphicsPipeline pipeline;
|
void compile();
|
||||||
Gfx::PPipelineLayout pipelineLayout;
|
std::string materialName;
|
||||||
|
friend class MaterialLoader;
|
||||||
};
|
};
|
||||||
DEFINE_REF(Material);
|
DEFINE_REF(Material);
|
||||||
} // namespace Seele
|
} // namespace Seele
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#include "MaterialAsset.h"
|
||||||
|
|
||||||
|
using namespace Seele;
|
||||||
|
|
||||||
|
MaterialAsset::MaterialAsset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialAsset::MaterialAsset(const std::string& directory, const std::string& name)
|
||||||
|
: Asset(directory, name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialAsset::MaterialAsset(const std::string& fullPath)
|
||||||
|
: Asset(fullPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialAsset::~MaterialAsset()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "Asset/Asset.h"
|
||||||
|
#include "ShaderExpression.h"
|
||||||
|
|
||||||
|
namespace Seele
|
||||||
|
{
|
||||||
|
class MaterialAsset : public Asset
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MaterialAsset();
|
||||||
|
MaterialAsset(const std::string &directory, const std::string &name);
|
||||||
|
MaterialAsset(const std::string &fullPath);
|
||||||
|
~MaterialAsset();
|
||||||
|
protected:
|
||||||
|
//For now its simply the collection of parameters, since there is no point for expressions
|
||||||
|
Array<PShaderParameter> parameters;
|
||||||
|
};
|
||||||
|
DEFINE_REF(MaterialAsset);
|
||||||
|
} // namespace Seele
|
||||||
@@ -8,12 +8,12 @@ MaterialInstance::MaterialInstance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
MaterialInstance::MaterialInstance(const std::string& directory, const std::string& name)
|
MaterialInstance::MaterialInstance(const std::string& directory, const std::string& name)
|
||||||
: FileAsset(directory, name)
|
: Asset(directory, name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MaterialInstance::MaterialInstance(const std::string& fullPath)
|
MaterialInstance::MaterialInstance(const std::string& fullPath)
|
||||||
: FileAsset(fullPath)
|
: Asset(fullPath)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user