Preparing for Writeup

This commit is contained in:
2021-10-15 23:12:29 +02:00
parent 2cb70d7b16
commit b1d8ef4120
40 changed files with 284 additions and 192 deletions
+20
View File
@@ -4,6 +4,26 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{
"name": "Engine Debug (Linux)",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceRoot}/bin/Debug/SeeleEngine",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceRoot}/bin/Debug",
"console": "internalConsole",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable break on all exceptions",
"text": "catch throw",
"ignoreFailures": true
}
]
},
{ {
"name": "Engine Debug", "name": "Engine Debug",
"type": "cppvsdbg", "type": "cppvsdbg",
+7 -2
View File
@@ -112,14 +112,19 @@
"span": "cpp", "span": "cpp",
"charconv": "cpp", "charconv": "cpp",
"format": "cpp", "format": "cpp",
"semaphore": "cpp" "semaphore": "cpp",
"netfwd": "cpp",
"string_view": "cpp",
"rope": "cpp",
"slist": "cpp",
"numbers": "cpp"
}, },
"cmake.skipConfigureIfCachePresent": false, "cmake.skipConfigureIfCachePresent": false,
"cmake.configureArgs": [ "cmake.configureArgs": [
"-Wno-dev" "-Wno-dev"
], ],
"C_Cpp.default.cppStandard": "c++20", "C_Cpp.default.cppStandard": "c++20",
"C_Cpp.default.intelliSenseMode": "msvc-x64", "C_Cpp.default.intelliSenseMode": "gcc-x64",
"files.watcherExclude": { "files.watcherExclude": {
"**/target": true "**/target": true
}, },
+122 -1
View File
@@ -1,6 +1,6 @@
# Seele Engine # Seele Engine
Seele is a Proof-of-Concept 3D render engine using Vulkan as it's primary graphics API, but other APIs could also be implemented. Seele is a Proof-of-Concept 3D render engine using Vulkan as it's primary graphics API, but other APIs could also be implemented. Due to this, a lot of terminology will be Vulkan-related, but it can be translated to other APIs.
The focus of the project is to make the renderer use as many of the system resources as efficiently as possible to maximize the framerate The focus of the project is to make the renderer use as many of the system resources as efficiently as possible to maximize the framerate
while minimizing resource usage. while minimizing resource usage.
It does this by being designed to support multithreading for more recent APIs, like DX12 or Vulkan, while still providing an interface that could be implemented by an It does this by being designed to support multithreading for more recent APIs, like DX12 or Vulkan, while still providing an interface that could be implemented by an
@@ -23,3 +23,124 @@ performance optimizations, like serialization for example. Due to them occuring
- `PHelloWorld`, the same as `RefPtr<HelloWorld>` - `PHelloWorld`, the same as `RefPtr<HelloWorld>`
- `UPHelloWorld`, the same as `UniquePtr<HelloWorld>` - `UPHelloWorld`, the same as `UniquePtr<HelloWorld>`
## Basic Architecture
The first piece to the puzzle is the `WindowManager`, a container that manages a `Graphics` object, which is the interface for the graphics API, as well as all `Window`s that are active. Each `Window` represents, well, a window, and contains several `View`s. A `View` represents a viewport in the window. For an analogy to Unity, a `View` would be the Inspector, the Asset Browser or the Hierarchy.
Since all viewports in a window are backed by the same image and can only be presented together, the rendering for all viewports is synchronized, while the logic for each `View` runs in a separate thread.
The interactions between logic and rendering are modelled through two parts of the interface: `beginUpdate()`, `update()` and `commitUpdate()` for the logic side, and `prepareRender()` and `render()` for the rendering side. The views use a set of concrete `RenderPass` objects to render a new frame, depending on what kind of content should be displayed. In order to draw a frame, a `RenderPass` needs an "update packet" in form of a struct, but the contents of that packet is dependent on the render pass itself. A depth prepass for example might only need a mesh list, while a light culling pass needs the dynamic lights or a base pass might need both.
In order to avoid inheritance and casting for these update packets, each `RenderPass` needs to be updated individually by the view that uses it, so the thread interactions are not enforced in the `View` base class, instead `commitUpdate()` is called from a locked context from the logic thread, so that the view can copy the packet to a shared storage, while `prepareRender()` is locked and called from the render thread, so that it can be passed to the render passes.
## RenderPass
To better illustrate how render passes work, here is part of the `RenderPass` base class:
```cpp
template<typename RenderPassDataType>
class RenderPass
{
public:
RenderPass(Gfx::PGraphics graphics, Gfx::PViewport viewport)
: graphics(graphics)
, viewport(viewport)
{}
virtual ~RenderPass()
{}
void updateViewFrame(RenderPassDataType viewFrame) {
passData = std::move(viewFrame);
}
virtual void beginFrame() = 0;
virtual void render() = 0;
virtual void endFrame() = 0;
virtual void publishOutputs() = 0;
virtual void createRenderPass() = 0;
//....
private:
PRenderGraphResources resources;
RenderPassDataType passData;
Gfx::PGraphics graphics;
//....
};
```
All render passes in a `View` share a `RenderGraphResources` object, which is used to share outputs between the different passes. During initialization, every render pass "publishes" any outputs that it produces in `publishOutputs()`, so that they can be consumed by other render passes. For example the output of a depth prepass is the depth buffer, for a light culling pass it is the culled light indices. Next the render passes get any resources that they require and have been registered by other passes to create the render pass in `createRenderPass()`. This is split into two parts, so that the order of initialization of different renderpasses doesn't matter, as all outputs are available before any are requested.
## Materials
The material system fully embraced a Vulkan-style descriptor system, abstracted by the `Graphics` API. A material is a file stored on disk in form of a JSON document, here is an example:
```json
{
"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"
},
"roughness": {
"type": "float",
"default": "0.5f"
},
"sheen": {
"type": "float",
"default": "0.0f"
},
"worldOffset": {
"type": "float3",
"default": "float3(0, 0, 0)"
},
"textureSampler": {
"type": "SamplerState"
}
},
"code": {
"baseColor": [
"return diffuseTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;"
],
"metallic": [
"return metallic;"
],
"normal": [
"return normalTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;"
],
"specular": [
"return specularTexture.Sample(textureSampler, input.texCoords[0] * uvScale).x;"
],
"roughness": [
"return roughness;"
],
"sheen": [
"return sheen;"
],
"worldOffset": [
"return worldOffset;"
]
}
}
```
The document starts with the asset `name`, followed by the `profile`, which tells the engine which BRDF function it uses, and thus what outputs it can expect from the material. Next are the parameters, which are the inputs that need to get passed to the shader later. The `type` field must be a valid HLSL datatype and `default` a valid value for that datatype. In the `code` section, there must be an entry for every output required by the `profile`, each of which is a string array for each line of shader code to compute that value and ends by `return`ing that value.
### MaterialAsset
The `MaterialAsset` class represents such a JSON document on disk, and is the base class for `Material` and `MaterialInstance`. It stores the layout of the parameters as well as their values, but does not store, parse or generate any shader code.
### Material
The `Material` class inherits from `MaterialAsset` and represents a base material,
+2 -14
View File
@@ -55,7 +55,7 @@ else()
# Find library files # Find library files
find_library( find_library(
ASSIMP_LIBRARY ASSIMP_LIBRARY
NAMES libassimp${CMAKE_DEBUG_POSTFIX}.a NAMES libassimp${CMAKE_DEBUG_POSTFIX}.so
PATHS PATHS
/usr/lib64 /usr/lib64
/usr/lib /usr/lib
@@ -66,22 +66,10 @@ else()
${ASSIMP_ROOT}/code ${ASSIMP_ROOT}/code
DOC "Assimp library file") DOC "Assimp library file")
find_file(
ASSIMP_BINARY
NAMES libassimp${CMAKE_DEBUG_POSTFIX}.so
PATHS
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
/sw/lib
/opt/local/lib
${ASSIMP_ROOT}/code
DOC "The Assimp library")
endif() endif()
# Handle REQUIRD argument, define *_FOUND variable # Handle REQUIRD argument, define *_FOUND variable
find_package_handle_standard_args(assimp DEFAULT_MSG ASSIMP_INCLUDE_DIR ASSIMP_BINARY) find_package_handle_standard_args(assimp DEFAULT_MSG ASSIMP_INCLUDE_DIR ASSIMP_LIBRARY)
# Define GLFW_LIBRARIES and GLFW_INCLUDE_DIRS # Define GLFW_LIBRARIES and GLFW_INCLUDE_DIRS
if (ASSIMP_FOUND) if (ASSIMP_FOUND)
+2 -16
View File
@@ -69,22 +69,8 @@ else()
DOC "The directory where GL/glfw.h resides") DOC "The directory where GL/glfw.h resides")
# Find library files # Find library files
# Try to use static libraries
find_library(
GLFW_LIBRARY
NAMES libglfw3${CMAKE_DEBUG_POSTFIX}.a
PATHS
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
/sw/lib
/opt/local/lib
${GLFW_ROOT}/src
DOC "The GLFW library")
find_file( find_file(
GLFW_BINARY GLFW_LIBRARY
NAMES libglfw${CMAKE_DEBUG_POSTFIX}.so NAMES libglfw${CMAKE_DEBUG_POSTFIX}.so
PATHS PATHS
/usr/lib64 /usr/lib64
@@ -98,7 +84,7 @@ else()
endif() endif()
# Handle REQUIRD argument, define *_FOUND variable # Handle REQUIRD argument, define *_FOUND variable
find_package_handle_standard_args(GLFW DEFAULT_MSG GLFW_INCLUDE_DIR GLFW_LIBRARY GLFW_BINARY) find_package_handle_standard_args(GLFW DEFAULT_MSG GLFW_INCLUDE_DIR GLFW_LIBRARY)
# Define GLFW_LIBRARIES and GLFW_INCLUDE_DIRS # Define GLFW_LIBRARIES and GLFW_INCLUDE_DIRS
if (GLFW_FOUND) if (GLFW_FOUND)
+5 -36
View File
@@ -49,63 +49,32 @@ if (WIN32)
PATHS PATHS
${SLANG_BINARY_PATH}) ${SLANG_BINARY_PATH})
else() else()
set(SLANG_BINARY_PATH ${SLANG_ROOT}/bin/linux-${CMAKE_PLATFORM}/debug/) set(SLANG_BINARY_PATH ${SLANG_ROOT}/bin/linux-${CMAKE_PLATFORM}/release/)
# Find include files # Find include files
find_path( find_path(
SLANG_INCLUDE_DIR SLANG_INCLUDE_DIR
NAMES slang.h NAMES slang.h
PATHS PATHS
/usr/include
/usr/local/include
/sw/include
/opt/local/include
${SLANG_ROOT} ${SLANG_ROOT}
DOC "The directory where GL/glfw.h resides") DOC "The directory where GL/glfw.h resides")
find_library(
SLANG_LIBRARY
NAMES libcore.a
PATHS
/usr/include
/usr/local/include
/sw/include
/opt/local/include
${SLANG_BINARY_PATH}
DOC "The directory where GL/glfw.h resides")
find_library(
SLANG_COMPILER
NAMES libcompiler-core.a
PATHS
/usr/include
/usr/local/include
/sw/include
/opt/local/include
${SLANG_BINARY_PATH}
DOC "The directory where GL/glfw.h resides")
# Find library files # Find library files
find_library( find_library(
SLANG_BINARY SLANG_LIBRARY
NAMES libslang.so NAMES libslang.so
PATHS PATHS
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/lib
/sw/lib
/opt/local/lib
${SLANG_BINARY_PATH} ${SLANG_BINARY_PATH}
NO_DEFAULT_PATH
DOC "The SLANG library") DOC "The SLANG library")
endif() endif()
# Handle REQUIRD argument, define *_FOUND variable # Handle REQUIRD argument, define *_FOUND variable
find_package_handle_standard_args(SLANG DEFAULT_MSG SLANG_INCLUDE_DIR SLANG_LIBRARY SLANG_BINARY) find_package_handle_standard_args(SLANG DEFAULT_MSG SLANG_INCLUDE_DIR SLANG_LIBRARY)
# Define SLANG_LIBRARIES and SLANG_INCLUDE_DIRS # Define SLANG_LIBRARIES and SLANG_INCLUDE_DIRS
if (SLANG_FOUND) if (SLANG_FOUND)
set(SLANG_BINARIES ${SLANG_BINARY} ${SLANG_GLSLANG}) set(SLANG_BINARIES ${SLANG_BINARY} ${SLANG_GLSLANG})
set(SLANG_LIBRARIES ${SLANG_LIBRARY} ${SLANG_COMPILER}) set(SLANG_LIBRARIES ${SLANG_LIBRARY})
set(SLANG_INCLUDE_DIRS ${SLANG_INCLUDE_DIR}) set(SLANG_INCLUDE_DIRS ${SLANG_INCLUDE_DIR})
endif() endif()
+3 -3
View File
@@ -10,7 +10,7 @@ set(ASSIMP_BUILD_OVERALLS OFF CACHE INTERNAL "")
set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE INTERNAL "") set(ASSIMP_BUILD_ASSIMP_TOOLS OFF CACHE INTERNAL "")
set(ASSIMP_INSTALL OFF CACHE INTERNAL "") set(ASSIMP_INSTALL OFF CACHE INTERNAL "")
set(ASSIMP_BUILD_ZLIB OFF CACHE INTERNAL "") set(ASSIMP_BUILD_ZLIB OFF CACHE INTERNAL "")
set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "") set(BUILD_SHARED_LIBS ON CACHE INTERNAL "")
add_subdirectory(${ASSIMP_ROOT} ${ASSIMP_ROOT}) add_subdirectory(${ASSIMP_ROOT} ${ASSIMP_ROOT})
target_compile_definitions(assimp PRIVATE _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING) target_compile_definitions(assimp PRIVATE _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING)
@@ -59,13 +59,13 @@ set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "GLFW lib only" )
set(GLFW_BUILD_TESTS 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_DOCS OFF CACHE BOOL "GLFW lib only" )
set(GLFW_BUILD_INSTALL OFF CACHE BOOL "GLFW lib only" ) set(GLFW_BUILD_INSTALL OFF CACHE BOOL "GLFW lib only" )
set(GLFW_VULKAN_STATIC ON CACHE BOOL "GLFW vulkan static") set(GLFW_VULKAN_STATIC OFF CACHE BOOL "GLFW vulkan static")
add_subdirectory(${GLFW_ROOT} ${GLFW_ROOT}) add_subdirectory(${GLFW_ROOT} ${GLFW_ROOT})
#--------------SLang------------------------------ #--------------SLang------------------------------
list(APPEND DEPENDENCIES slang) list(APPEND DEPENDENCIES slang)
string(TOLOWER debug_${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}
+19 -58
View File
@@ -5,10 +5,10 @@
"diffuseTexture": { "diffuseTexture": {
"type": "Texture2D" "type": "Texture2D"
}, },
"specularTexture": { "specularTexture": {
"type": "Texture2D" "type": "Texture2D"
}, },
"normalTexture": { "normalTexture": {
"type": "Texture2D" "type": "Texture2D"
}, },
"uvScale": { "uvScale": {
@@ -19,82 +19,43 @@
"type": "float", "type": "float",
"default": "0.0f" "default": "0.0f"
}, },
"subsurface": {
"type": "float",
"default": "0.0f"
},
"roughness": { "roughness": {
"type": "float", "type": "float",
"default": "0.5f" "default": "0.5f"
}, },
"specularTint": {
"type": "float",
"default": "0.0f"
},
"anisotropic": {
"type": "float",
"default": "0.0f"
},
"sheen": { "sheen": {
"type": "float", "type": "float",
"default": "0.0f" "default": "0.0f"
}, },
"sheenTint": { "worldOffset": {
"type": "float", "type": "float3",
"default": "0.5f" "default": "float3(0, 0, 0)"
},
"clearCoat": {
"type": "float",
"default": "0.0f"
},
"clearCoatGloss": {
"type": "float",
"default": "1.0f"
},
"worldOffset": {
"type": "float3",
"default": "float3(0, 0, 0)"
}, },
"textureSampler": { "textureSampler": {
"type": "SamplerState" "type": "SamplerState"
} }
}, },
"code": { "code": {
"baseColor": [ "baseColor": [
"return diffuseTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;" "return diffuseTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;"
], ],
"metallic": [ "metallic": [
"return 0;" "return metallic;"
], ],
"normal": [ "normal": [
"return normalTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;" "return normalTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;"
], ],
"specular": [ "specular": [
"return specularTexture.Sample(textureSampler, input.texCoords[0] * uvScale).x;" "return specularTexture.Sample(textureSampler, input.texCoords[0] * uvScale).x;"
], ],
"roughness": [ "roughness": [
"return roughness;" "return roughness;"
], ],
"specularTint": [ "sheen": [
"return specularTint;" "return sheen;"
], ],
"anisotropic": [ "worldOffset": [
"return anisotropic;" "return worldOffset;"
],
"sheen": [
"return sheen;"
],
"sheenTint": [
"return sheenTint;"
],
"clearCoat": [
"return clearCoat;"
],
"clearCoatGloss": [
"return clearCoatGloss;"
],
"worldOffset": [
"return worldOffset;"
] ]
} }
} }
+5
View File
@@ -124,6 +124,11 @@ void AssetRegistry::registerMesh(PMeshAsset mesh)
} }
} }
void AssetRegistry::registerTexture(PTextureAsset texture)
{
textures[texture->getFileName()] = texture;
}
void AssetRegistry::registerMaterial(PMaterialAsset material) void AssetRegistry::registerMaterial(PMaterialAsset material)
{ {
materials[material->getFileName()] = material; materials[material->getFileName()] = material;
+5 -3
View File
@@ -86,8 +86,8 @@ void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& glob
outMatFile << std::setw(4) << matCode; outMatFile << std::setw(4) << matCode;
outMatFile.flush(); outMatFile.flush();
outMatFile.close(); outMatFile.close();
//TODO: let the material loader handle this instead
//std::cout << matCode << std::endl; std::cout << "writing json to " << outMatFilename << std::endl;
PMaterial result = new Material(outMatFilename); PMaterial result = new Material(outMatFilename);
result->compile(); result->compile();
graphics->getShaderCompiler()->registerMaterial(result); graphics->getShaderCompiler()->registerMaterial(result);
@@ -225,12 +225,13 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path&
stbi_write_png(texPngPath.string().c_str(), tex->mWidth, tex->mHeight, 4, tex->pcData, tex->mWidth * 32); stbi_write_png(texPngPath.string().c_str(), tex->mWidth, tex->mHeight, 4, tex->pcData, tex->mWidth * 32);
delete texData; delete texData;
} }
std::cout << "Loading model texture " << texPngPath.string() << std::endl;
AssetRegistry::importFile(texPngPath.string()); AssetRegistry::importFile(texPngPath.string());
} }
} }
void MeshLoader::import(PMeshAsset meshAsset, const std::filesystem::path &path) void MeshLoader::import(PMeshAsset meshAsset, const std::filesystem::path &path)
{ {
std::cout << "Starting to import "<<path << std::endl;
meshAsset->setStatus(Asset::Status::Loading); meshAsset->setStatus(Asset::Status::Loading);
Assimp::Importer importer; Assimp::Importer importer;
importer.ReadFile(path.string().c_str(), importer.ReadFile(path.string().c_str(),
@@ -262,4 +263,5 @@ void MeshLoader::import(PMeshAsset meshAsset, const std::filesystem::path &path)
} }
meshAsset->setStatus(Asset::Status::Ready); meshAsset->setStatus(Asset::Status::Ready);
meshAsset->save(); meshAsset->save();
std::cout << "Finished loading " << path << std::endl;
} }
+2 -1
View File
@@ -33,7 +33,8 @@ void TextureAsset::load()
{ {
setStatus(Status::Loading); setStatus(Status::Loading);
ktxTexture2* kTexture; ktxTexture2* kTexture;
KTX_error_code result = ktxTexture2_CreateFromNamedFile(getFullPath().c_str(), // TODO: consider return
ktxTexture2_CreateFromNamedFile(getFullPath().c_str(),
KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT, KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT,
&kTexture); &kTexture);
TextureCreateInfo createInfo; TextureCreateInfo createInfo;
+5 -5
View File
@@ -28,7 +28,8 @@ void TextureLoader::importAsset(const std::filesystem::path& filePath)
PTextureAsset asset = new TextureAsset(assetFileName.replace_extension("asset").filename().generic_string()); PTextureAsset asset = new TextureAsset(assetFileName.replace_extension("asset").filename().generic_string());
asset->setStatus(Asset::Status::Loading); asset->setStatus(Asset::Status::Loading);
asset->setTexture(placeholderAsset->getTexture()); asset->setTexture(placeholderAsset->getTexture());
AssetRegistry::get().textures[asset->getFileName()] = asset; std::cout << "Loading texture " << asset->getFileName() << std::endl;
AssetRegistry::get().registerTexture(asset);
futures.add(std::async(std::launch::async, [this, filePath, asset] () mutable { futures.add(std::async(std::launch::async, [this, filePath, asset] () mutable {
using namespace std::chrono_literals; using namespace std::chrono_literals;
//std::this_thread::sleep_for(5s); //std::this_thread::sleep_for(5s);
@@ -49,7 +50,6 @@ void TextureLoader::import(const std::filesystem::path& path, PTextureAsset text
unsigned char* data = stbi_load(path.string().c_str(), &x, &y, &n, 4); unsigned char* data = stbi_load(path.string().c_str(), &x, &y, &n, 4);
ktxTexture2* kTexture; ktxTexture2* kTexture;
ktxTextureCreateInfo createInfo; ktxTextureCreateInfo createInfo;
KTX_error_code result;
createInfo.vkFormat = VK_FORMAT_R8G8B8A8_SRGB; createInfo.vkFormat = VK_FORMAT_R8G8B8A8_SRGB;
createInfo.baseWidth = x; createInfo.baseWidth = x;
@@ -62,15 +62,15 @@ void TextureLoader::import(const std::filesystem::path& path, PTextureAsset text
createInfo.isArray = false; createInfo.isArray = false;
createInfo.generateMipmaps = true; createInfo.generateMipmaps = true;
result = ktxTexture2_Create(&createInfo, ktxTexture2_Create(&createInfo,
KTX_TEXTURE_CREATE_ALLOC_STORAGE, KTX_TEXTURE_CREATE_ALLOC_STORAGE,
&kTexture); &kTexture);
result = ktxTexture_SetImageFromMemory(ktxTexture(kTexture), ktxTexture_SetImageFromMemory(ktxTexture(kTexture),
0, 0, 0, data, x * y * 4 * sizeof(unsigned char)); 0, 0, 0, data, x * y * 4 * sizeof(unsigned char));
stbi_image_free(data); stbi_image_free(data);
result = ktxTexture_WriteToNamedFile(ktxTexture(kTexture), textureAsset->getFullPath().c_str()); ktxTexture_WriteToNamedFile(ktxTexture(kTexture), textureAsset->getFullPath().c_str());
ktxTexture_Destroy(ktxTexture(kTexture)); ktxTexture_Destroy(ktxTexture(kTexture));
} }
+2 -2
View File
@@ -32,9 +32,9 @@ namespace Seele
Array(Init_t) Array(Init_t)
: arraySize(0) : arraySize(0)
, allocated(0) , allocated(0)
, _data(nullptr)
, beginIt(Iterator(nullptr)) , beginIt(Iterator(nullptr))
, endIt(Iterator(nullptr)) , endIt(Iterator(nullptr))
, _data(nullptr)
{ {
} }
Array(size_t size, T value = T()) Array(size_t size, T value = T())
@@ -420,7 +420,7 @@ namespace Seele
} }
friend class boost::serialization::access; friend class boost::serialization::access;
template<class Archive> template<class Archive>
void serialize(Archive& ar, const unsigned int version) void serialize(Archive& ar, const unsigned int)
{ {
ar & arraySize; ar & arraySize;
resize(arraySize); resize(arraySize);
+2 -2
View File
@@ -111,10 +111,10 @@ private:
public: public:
Map() Map()
: root(nullptr) : root(nullptr)
, _size(0)
, iteratorsDirty(false)
, beginIt(nullptr) , beginIt(nullptr)
, endIt(nullptr) , endIt(nullptr)
, iteratorsDirty(false)
, _size(0)
{ {
} }
Map(const Map& other) Map(const Map& other)
+1 -1
View File
@@ -162,7 +162,7 @@ typedef uint32 KeyModifierFlags;
namespace Gfx namespace Gfx
{ {
static constexpr bool useAsyncCompute = true; static constexpr bool useAsyncCompute = true;
static constexpr bool waitIdleOnSubmit = true; static constexpr bool waitIdleOnSubmit = false;
static constexpr uint32 numFramesBuffered = 8; static constexpr uint32 numFramesBuffered = 8;
extern uint32 currentFrameIndex; extern uint32 currentFrameIndex;
extern double currentFrameDelta; extern double currentFrameDelta;
@@ -26,8 +26,10 @@ void modifyRenderPassMacros(Gfx::RenderPassType type, Map<const char*, const cha
{ {
case Gfx::RenderPassType::DepthPrepass: case Gfx::RenderPassType::DepthPrepass:
DepthPrepass::modifyRenderPassMacros(defines); DepthPrepass::modifyRenderPassMacros(defines);
break;
case Gfx::RenderPassType::BasePass: case Gfx::RenderPassType::BasePass:
BasePass::modifyRenderPassMacros(defines); BasePass::modifyRenderPassMacros(defines);
break;
} }
} }
@@ -138,10 +138,10 @@ void DepthPrepass::render()
Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT);
depthAttachment->getTexture()->transferOwnership(Gfx::QueueType::GRAPHICS); depthAttachment->getTexture()->transferOwnership(Gfx::QueueType::GRAPHICS);
graphics->beginRenderPass(renderPass); graphics->beginRenderPass(renderPass);
/*for (auto &&meshBatch : scene->getStaticMeshes()) for (auto &&meshBatch : passData.staticDrawList)
{ {
processor->addMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets); processor->addMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets);
}*/ }
graphics->executeCommands(processor->getRenderCommands()); graphics->executeCommands(processor->getRenderCommands());
graphics->endRenderPass(); graphics->endRenderPass();
} }
@@ -232,7 +232,7 @@ void LightCullingPass::createRenderPass()
depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH")->getTexture(); depthAttachment = resources->requestRenderTarget("DEPTHPREPASS_DEPTH")->getTexture();
} }
void LightCullingPass::modifyRenderPassMacros(Map<const char*, const char*>& defines) void LightCullingPass::modifyRenderPassMacros(Map<const char*, const char*>&)
{ {
} }
@@ -304,7 +304,7 @@ ComputeCommand::~ComputeCommand()
{ {
} }
void ComputeCommand::begin(PCmdBuffer parent) void ComputeCommand::begin(PCmdBuffer)
{ {
ready = false; ready = false;
VkCommandBufferBeginInfo beginInfo = VkCommandBufferBeginInfo beginInfo =
@@ -117,7 +117,7 @@ DescriptorSet::~DescriptorSet()
void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer) void DescriptorSet::updateBuffer(uint32_t binding, Gfx::PUniformBuffer uniformBuffer)
{ {
PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>(); PUniformBuffer vulkanBuffer = uniformBuffer.cast<UniformBuffer>();
UniformBuffer* cachedBuffer = reinterpret_cast<UniformBuffer*>(cachedData[binding]); //UniformBuffer* cachedBuffer = reinterpret_cast<UniformBuffer*>(cachedData[binding]);
/*if(vulkanBuffer->isDataEquals(cachedBuffer)) /*if(vulkanBuffer->isDataEquals(cachedBuffer))
{ {
std::cout << "uniform data equal, skip" << std::endl; std::cout << "uniform data equal, skip" << std::endl;
@@ -63,8 +63,8 @@ public:
: setHandle(VK_NULL_HANDLE) : setHandle(VK_NULL_HANDLE)
, graphics(graphics) , graphics(graphics)
, owner(owner) , owner(owner)
, currentlyInUse(false)
, currentlyBound(false) , currentlyBound(false)
, currentlyInUse(false)
{ {
} }
virtual ~DescriptorSet(); virtual ~DescriptorSet();
@@ -432,16 +432,19 @@ void Graphics::pickPhysicalDevice()
vkGetPhysicalDeviceFeatures(dev, &features); vkGetPhysicalDeviceFeatures(dev, &features);
if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
{ {
std::cout << "found dedicated gpu " << props.deviceName << std::endl;
currentRating += 100; currentRating += 100;
} }
else if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU) else if (props.deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU)
{ {
std::cout << "found integrated gpu " << props.deviceName << std::endl;
currentRating += 10; currentRating += 10;
} }
if (currentRating > deviceRating) if (currentRating > deviceRating)
{ {
deviceRating = currentRating; deviceRating = currentRating;
bestDevice = dev; bestDevice = dev;
std::cout << "bestDevice: " << props.deviceName << std::endl;
} }
} }
physicalDevice = bestDevice; physicalDevice = bestDevice;
@@ -765,8 +765,7 @@ VkPipelineShaderStageCreateInfo init::PipelineShaderStageCreateInfo(VkShaderStag
return info; return info;
} }
#pragma warning(disable : 4100) VkBool32 Seele::Vulkan::debugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t, const char *layerPrefix, const char *msg, void *)
VkBool32 Seele::Vulkan::debugCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t obj, size_t location, int32_t code, const char *layerPrefix, const char *msg, void *userDataManager)
{ {
if(flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) if(flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
{ {
@@ -778,7 +777,6 @@ VkBool32 Seele::Vulkan::debugCallback(VkDebugReportFlagsEXT flags, VkDebugReport
return VK_FALSE; return VK_FALSE;
} }
} }
#pragma warning(default : 4100)
VkResult Seele::Vulkan::CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) VkResult Seele::Vulkan::CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback)
{ {
+2 -2
View File
@@ -2,7 +2,7 @@
#include "VulkanGraphics.h" #include "VulkanGraphics.h"
#include "VulkanDescriptorSets.h" #include "VulkanDescriptorSets.h"
#include "slang.h" #include "slang.h"
//#include "spirv_cross/spirv_reflect.hpp" #include "stdlib.h"
using namespace slang; using namespace slang;
using namespace Seele; using namespace Seele;
@@ -55,7 +55,7 @@ static SlangStage getStageFromShaderType(ShaderType type)
void Shader::create(const ShaderCreateInfo& createInfo) void Shader::create(const ShaderCreateInfo& createInfo)
{ {
entryPointName = createInfo.entryPoint; entryPointName = createInfo.entryPoint;
static SlangSession* session = spCreateSession(NULL); static SlangSession* session = spCreateSession(nullptr);
SlangCompileRequest* request = spCreateCompileRequest(session); SlangCompileRequest* request = spCreateCompileRequest(session);
int targetIndex = spAddCodeGenTarget(request, SLANG_SPIRV); int targetIndex = spAddCodeGenTarget(request, SLANG_SPIRV);
@@ -162,9 +162,9 @@ void Window::advanceBackBuffer()
imageAcquiredSemaphore = imageAcquired[semaphoreIndex]; imageAcquiredSemaphore = imageAcquired[semaphoreIndex];
currentImageIndex = imageIndex; currentImageIndex = imageIndex;
PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands();
backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); backBufferImages[currentImageIndex]->changeLayout(Gfx::SE_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkClearColorValue clearColor = {0.0f, 0.0f, 0.0f, 0.0f}; VkClearColorValue clearColor = {0.0f, 0.0f, 0.0f, 0.0f};
PCmdBuffer cmdBuffer = graphics->getGraphicsCommands()->getCommands();
VkImageSubresourceRange range = init::ImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT); VkImageSubresourceRange range = init::ImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
vkCmdClearColorImage( vkCmdClearColorImage(
cmdBuffer->getHandle(), cmdBuffer->getHandle(),
+3 -2
View File
@@ -54,7 +54,6 @@ void Material::compile()
std::string profile = j["profile"].get<std::string>(); std::string profile = j["profile"].get<std::string>();
codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl; codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl;
codeStream << "import LightEnv;" << std::endl;
codeStream << "import Material;" << std::endl; codeStream << "import Material;" << std::endl;
codeStream << "import BRDF;" << std::endl; codeStream << "import BRDF;" << std::endl;
codeStream << "import MaterialParameter;" << std::endl; codeStream << "import MaterialParameter;" << std::endl;
@@ -105,7 +104,9 @@ void Material::compile()
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE); layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
if(defaultValue != param.value().end()) if(defaultValue != param.value().end())
{ {
p->data = AssetRegistry::findTexture(defaultValue.value().get<std::string>()); std::string defaultString = defaultValue.value().get<std::string>();
std::cout << "Texture parameter " << defaultString << std::endl;
p->data = AssetRegistry::findTexture(defaultString);
} }
else else
{ {
+1 -1
View File
@@ -82,7 +82,7 @@ CombinedTextureParameter::~CombinedTextureParameter()
} }
void CombinedTextureParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) void CombinedTextureParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8*)
{ {
descriptorSet->updateTexture(binding, data->getTexture(), sampler); descriptorSet->updateTexture(binding, data->getTexture(), sampler);
} }
+2 -2
View File
@@ -53,9 +53,9 @@ public:
std::scoped_lock lock(registeredObjectsLock); std::scoped_lock lock(registeredObjectsLock);
registeredObjects.erase(handle); registeredObjects.erase(handle);
} }
#pragma warning( disable: 4150) // #pragma warning( disable: 4150)
delete handle; delete handle;
#pragma warning( default: 4150) // #pragma warning( default: 4150)
} }
RefObject &operator=(const RefObject &rhs) RefObject &operator=(const RefObject &rhs)
{ {
@@ -6,8 +6,8 @@
using namespace Seele; using namespace Seele;
CameraComponent::CameraComponent() CameraComponent::CameraComponent()
: bNeedsProjectionBuild(true) : bNeedsViewBuild(true)
, bNeedsViewBuild(true) , bNeedsProjectionBuild(true)
, originPoint(0, 0, 0) , originPoint(0, 0, 0)
, cameraPosition(0, 0, 0) , cameraPosition(0, 0, 0)
{ {
+1 -1
View File
@@ -13,7 +13,7 @@ Component::Component()
Component::~Component() Component::~Component()
{ {
} }
void Component::tick(float deltaTime) void Component::tick(float)
{ {
} }
PComponent Component::getParent() PComponent Component::getParent()
+5
View File
@@ -11,6 +11,11 @@ Element::~Element()
{ {
} }
PElement Element::getParent() const
{
return parent;
}
void Element::addChild(PElement element) void Element::addChild(PElement element)
{ {
children.add(element); children.add(element);
+3 -3
View File
@@ -5,7 +5,7 @@ using namespace Seele;
InspectorView::InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo) InspectorView::InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo)
: View(graphics, window, createInfo) : View(graphics, window, createInfo)
, renderGraph(UIPass(graphics, viewport, new Gfx::SwapchainAttachment(window->getGfxHandle()))) , uiPass(UIPass(graphics, viewport, new Gfx::SwapchainAttachment(window->getGfxHandle())))
{ {
} }
@@ -13,7 +13,7 @@ InspectorView::~InspectorView()
{ {
} }
void InspectorView::beginFrame() void InspectorView::beginUpdate()
{ {
} }
@@ -22,7 +22,7 @@ void InspectorView::update()
} }
void InspectorView::endFrame() void InspectorView::commitUpdate()
{ {
} }
+3 -3
View File
@@ -13,15 +13,15 @@ public:
InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo); InspectorView(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &createInfo);
virtual ~InspectorView(); virtual ~InspectorView();
virtual void beginFrame() override; virtual void beginUpdate() override;
virtual void update() override; virtual void update() override;
virtual void endFrame() override; virtual void commitUpdate() override;
virtual void prepareRender() override; virtual void prepareRender() override;
virtual void render() override; virtual void render() override;
void selectActor(); void selectActor();
protected: protected:
UIPass renderGraph; UIPass uiPass;
UIPassData uiPassData; UIPassData uiPassData;
+36 -3
View File
@@ -1,6 +1,7 @@
#include "SceneView.h" #include "SceneView.h"
#include "Scene/Scene.h" #include "Scene/Scene.h"
#include "Window.h" #include "Window.h"
#include "Asset/AssetRegistry.h"
#include "Scene/Actor/CameraActor.h" #include "Scene/Actor/CameraActor.h"
#include "Scene/Components/CameraComponent.h" #include "Scene/Components/CameraComponent.h"
@@ -15,15 +16,39 @@ Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const Viewpo
{ {
scene = new Scene(graphics); scene = new Scene(graphics);
scene->addActor(activeCamera); scene->addActor(activeCamera);
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Body_Diffuse.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Body_Lightmap.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Face_Diffuse.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Hair_Diffuse.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Sword_Ayaka_Tex_Hair_Lightmap.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Avatar_Girl_Tex_FaceLightmap.png");
AssetRegistry::importFile("/home/dynamitos/Assets/Ayaka/Ayaka.fbx");
PPrimitiveComponent ayaka = new PrimitiveComponent(AssetRegistry::findMesh("Ayaka"));
ayaka->addWorldTranslation(Vector(0, 0, 100));
ayaka->setWorldScale(Vector(0.1f, 0.1f, 0.1f));
scene->addPrimitiveComponent(ayaka);
PRenderGraphResources resources = new RenderGraphResources();
depthPrepass.setResources(resources);
lightCullingPass.setResources(resources);
basePass.setResources(resources);
depthPrepass.publishOutputs();
lightCullingPass.publishOutputs();
basePass.publishOutputs();
depthPrepass.createRenderPass();
lightCullingPass.createRenderPass();
basePass.createRenderPass();
} }
Seele::SceneView::~SceneView() Seele::SceneView::~SceneView()
{ {
} }
void SceneView::beginFrame() void SceneView::beginUpdate()
{ {
View::beginFrame(); View::beginUpdate();
scene->tick(Gfx::currentFrameDelta); scene->tick(Gfx::currentFrameDelta);
} }
@@ -31,7 +56,7 @@ void SceneView::update()
{ {
} }
void SceneView::endFrame() void SceneView::commitUpdate()
{ {
depthPrepassData.staticDrawList = scene->getStaticMeshes(); depthPrepassData.staticDrawList = scene->getStaticMeshes();
lightCullingPassData.lightEnv = scene->getLightBuffer(); lightCullingPassData.lightEnv = scene->getLightBuffer();
@@ -47,9 +72,17 @@ void SceneView::prepareRender()
void SceneView::render() void SceneView::render()
{ {
depthPrepass.beginFrame();
lightCullingPass.beginFrame();
basePass.beginFrame();
depthPrepass.render(); depthPrepass.render();
lightCullingPass.render(); lightCullingPass.render();
basePass.render(); basePass.render();
depthPrepass.endFrame();
lightCullingPass.endFrame();
basePass.endFrame();
} }
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier) void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier)
+2 -2
View File
@@ -13,9 +13,9 @@ class SceneView : public View
public: public:
SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo); SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo);
~SceneView(); ~SceneView();
virtual void beginFrame() override; virtual void beginUpdate() override;
virtual void update() override; virtual void update() override;
virtual void endFrame() override; virtual void commitUpdate() override;
virtual void prepareRender() override; virtual void prepareRender() override;
virtual void render() override; virtual void render() override;
+1 -1
View File
@@ -14,7 +14,7 @@ View::~View()
{ {
} }
void View::applyArea(URect area) void View::applyArea(URect)
{ {
} }
+2 -2
View File
@@ -12,10 +12,10 @@ public:
virtual ~View(); virtual ~View();
// These are called from the view thread, and handle updating game data // These are called from the view thread, and handle updating game data
virtual void beginFrame() {} virtual void beginUpdate() {}
virtual void update() {} virtual void update() {}
// End frame is called with a lock, so it is safe to write to shared memory // End frame is called with a lock, so it is safe to write to shared memory
virtual void endFrame() {} virtual void commitUpdate() {}
// These are called from the render thread // These are called from the render thread
// prepare render is also locked, so reading from shared memory is also safe // prepare render is also locked, so reading from shared memory is also safe
+2 -2
View File
@@ -58,9 +58,9 @@ void Window::viewWorker(WindowView* windowView)
{ {
while(true) while(true)
{ {
windowView->view->beginFrame(); windowView->view->beginUpdate();
windowView->view->update(); windowView->view->update();
std::lock_guard lock(windowView->workerMutex); std::lock_guard lock(windowView->workerMutex);
windowView->view->endFrame(); windowView->view->commitUpdate();
} }
} }
+1 -9
View File
@@ -9,6 +9,7 @@ using namespace Seele;
int main() int main()
{ {
PWindowManager windowManager = new WindowManager(); PWindowManager windowManager = new WindowManager();
AssetRegistry::init("/home/dynamitos/TestSeeleProject");
WindowCreateInfo mainWindowInfo; WindowCreateInfo mainWindowInfo;
mainWindowInfo.title = "SeeleEngine"; mainWindowInfo.title = "SeeleEngine";
mainWindowInfo.width = 1280; mainWindowInfo.width = 1280;
@@ -33,15 +34,6 @@ int main()
PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo); PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo);
window->addView(inspectorView); window->addView(inspectorView);
sceneView->setFocused(); sceneView->setFocused();
AssetRegistry::init("D:\\Private\\Programming\\C++\\TestSeeleProject\\");
AssetRegistry::importFile("D:\\Private\\Programming\\Unreal Engine\\Assets\\Ely\\Ely.fbx");
AssetRegistry::importFile("D:\\Private\\Programming\\Unreal Engine\\Assets\\Cube\\cube.obj");
AssetRegistry::importFile("D:\\Private\\Programming\\Unreal Engine\\Assets\\Plane\\plane.fbx");
PPrimitiveComponent plane = new PrimitiveComponent(AssetRegistry::findMesh("plane"));
plane->setWorldScale(Vector(100, 100, 100));
PPrimitiveComponent arissa = new PrimitiveComponent(AssetRegistry::findMesh("Ely"));
arissa->addWorldTranslation(Vector(0, 0, 100));
arissa->setWorldScale(Vector(0.1f, 0.1f, 0.1f));
while (windowManager->isActive()) while (windowManager->isActive())
{ {
windowManager->render(); windowManager->render();