Implementing ECS SystemBase and updating slang

This commit is contained in:
Dynamitos
2022-11-15 12:19:11 +01:00
parent 05bc31a2b4
commit f635ee2100
106 changed files with 1083 additions and 1675 deletions
+3
View File
@@ -34,3 +34,6 @@
[submodule "external/entt"]
path = external/entt
url = git@github.com:skypjack/entt.git
[submodule "external/thread-pool"]
path = external/thread-pool
url = https://github.com/DeveloperPaul123/thread-pool.git
+13 -10
View File
@@ -9,6 +9,7 @@ set(CMAKE_CXX_STANDARD 20)
option (USE_SUPERBUILD "Whether or not a superbuild should be invoked" ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_COMPILE_WARNING_AS_ERROR OFF)
set(ENGINE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/src/Engine)
set(EXTERNAL_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/external)
@@ -25,6 +26,7 @@ set(FREETYPE_ROOT ${EXTERNAL_ROOT}/freetype)
set(SPIRV_ROOT ${EXTERNAL_ROOT}/SPIRV-Cross)
set(ENTT_ROOT ${EXTERNAL_ROOT}/entt)
set(NSAM_ROOT ${EXTERNAL_ROOT}/aftermath)
set(THREADPOOL_ROOT ${EXTERNAL_ROOT}/thread-pool)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/)
set(Boost_NO_WARN_NEW_VERSIONS 1)
@@ -53,7 +55,8 @@ if(CMAKE_DEBUG_POSTFIX)
add_compile_definitions(ENABLE_VALIDATION)
add_compile_definitions(SEELE_DEBUG)
endif()
add_library(Engine "")
add_library(Engine SHARED "")
add_executable(Editor "")
target_compile_definitions(Engine PUBLIC GLFW_WINDOWS)
target_include_directories(Engine PUBLIC src/Engine)
@@ -70,9 +73,10 @@ target_link_libraries(Engine PUBLIC nsam)
target_link_libraries(Engine PUBLIC ktx)
target_link_libraries(Engine PUBLIC stb)
target_link_libraries(Engine PUBLIC nlohmann_json::nlohmann_json)
target_link_libraries(Engine PUBLIC dp::thread-pool)
if(UNIX)
target_link_libraries(Engine Threads::Threads)
target_link_libraries(Engine dl)
target_link_libraries(Engine Threads::Threads)
target_link_libraries(Engine dl)
endif()
target_precompile_headers(Engine
PUBLIC
@@ -89,20 +93,19 @@ target_precompile_headers(Engine
<mutex>
<string>
<thread>
<boost/serialization/serialization.hpp>
<boost/crc.hpp>)
target_link_libraries(Editor PRIVATE Engine)
add_subdirectory(src/)
<boost/serialization/serialization.hpp>)
if(MSVC)
set(_CRT_SECURE_NO_WARNINGS)
target_compile_options(Engine PUBLIC -Zi -MP -DEBUG)
target_compile_options(Engine PUBLIC /Zi /MP /W4 /DEBUG "/WX-")
else()
target_compile_options(Engine PUBLIC -g -Wall -Wextra -Wno-delete-incomplete -pedantic -fcoroutines)
endif()
target_link_libraries(Editor PUBLIC Engine)
add_subdirectory(src/)
add_executable(Seele_unit_tests "")
add_subdirectory(test/)
+5
View File
@@ -31,6 +31,7 @@ add_subdirectory(${JSON_ROOT})
#--------------GLM------------------------------
add_subdirectory(${GLM_ROOT})
target_compile_options(glm_shared INTERFACE /W0)
#--------------GLFW------------------------------
set(ENKITS_BUILD_EXAMPLES OFF CACHE BOOL "Build basic example applications" )
@@ -61,6 +62,10 @@ target_link_libraries(nsam INTERFACE ${NSAM_ROOT}/lib/${CMAKE_PLATFORM}/*.lib)
set_target_properties(nsam PROPERTIES NSAM_BINARY ${NSAM_ROOT}/lib/${CMAKE_PLATFORM}/GFSDK_Aftermath_Lib.${CMAKE_PLATFORM}.dll)
set_target_properties(nsam PROPERTIES LLVM_BINARY ${NSAM_ROOT}/lib/${CMAKE_PLATFORM}/llvm_7_0_1.dll)
#--------------thread-pool------------------------------
add_subdirectory(${THREADPOOL_ROOT})
target_compile_options(ThreadPool INTERFACE "/WX-")
#--------------SLang------------------------------
string(TOLOWER release_${CMAKE_PLATFORM} SLANG_CONFIG)
+1 -1
Vendored Submodule
+1
Submodule external/thread-pool added at dad69c1661
+1 -2
View File
@@ -1,8 +1,7 @@
import Common;
import Material;
import VERTEX_INPUT_IMPORT;
import MATERIAL_IMPORT;
import PrimitiveSceneData;
import StaticMeshVertexInput;
struct VertexStageOutput
+2 -4
View File
@@ -2,9 +2,8 @@ import Common;
import LightEnv;
import BRDF;
import Material;
import StaticMeshVertexInput;
import VERTEX_INPUT_IMPORT;
import MATERIAL_IMPORT;
import PrimitiveSceneData;
import MaterialParameter;
@@ -13,7 +12,6 @@ StructuredBuffer<uint> lightIndexList;
layout(set = INDEX_LIGHT_ENV, binding = 5)
RWTexture2D<uint2> lightGrid;
struct VertexStageOutput
{
ShaderAttributeInterpolation shaderAttributeInterpolation : Interpolation;
@@ -50,7 +48,7 @@ float4 fragmentMain(
) : SV_Target
{
MaterialFragmentParameter materialParams = input.getMaterialParameter(position);
TMaterial.BRDF brdf = gMaterial.prepare(materialParams);
let brdf = gMaterial.prepare(materialParams);
float3 viewDir = normalize(materialParams.viewDir);
+1 -1
View File
@@ -82,7 +82,7 @@ void tAppendLight(uint lightIndex)
[shader("compute")]
void cullLights(ComputeShaderInput in)
{
int2 texCoord = in.dispatchThreadID.xy;
int2 texCoord = int2(in.dispatchThreadID.xy);
float fDepth = depthTextureVS.Load(int3(texCoord, 0)).r;
uint uDepth = asuint(fDepth);
+7
View File
@@ -0,0 +1,7 @@
interface IMaterial
{
float4 sample(float2 texCoord);
}
type_param TMaterial : IMaterial;
ParameterBlock<TMaterial> gMaterial;
+10
View File
@@ -0,0 +1,10 @@
import Mat;
struct SimpleMaterial : IMaterial
{
float4 sample(float2 texCoord)
{
return float4(1, 0, 1, 1);
}
}
+1 -2
View File
@@ -17,6 +17,5 @@ interface IMaterial
float getSheen(MaterialFragmentParameter input);
};
type_param TMaterial : IMaterial;
layout(set = INDEX_MATERIAL, binding = 0, std430)
ParameterBlock<TMaterial> gMaterial;
ParameterBlock<IMaterial> gMaterial;
+2 -2
View File
@@ -63,7 +63,7 @@ struct ShaderAttributeInterpolation
#if NUM_MATERIAL_TEXCOORDS
for(int i = 0; i < NUM_MATERIAL_TEXCOORDS; ++i)
{
if(i % 2)
if(i % 2 == 1)
{
result.texCoords[i] = packedTexCoords[i / 2].zw;
}
@@ -191,7 +191,7 @@ struct VertexShaderInput
result.viewPosition = vertexParams.viewPosition;
for(int i = 0; i < NUM_MATERIAL_TEXCOORDS; ++i)
{
if(i % 2)
if(i % 2 == 1)
{
result.packedTexCoords[i / 2].zw = vertexParams.texCoords[i];
}
+4 -481
View File
@@ -1,485 +1,8 @@
// shaders.slang
import Mat;
import Simple;
//
// 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
float4 fragmentMain(float2 texCoord)
{
// 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);
return gMaterial.sample(texCoord);
}
-1
View File
@@ -1,5 +1,4 @@
#include "Window/WindowManager.h"
#include "Scene/Components/PrimitiveComponent.h"
#include "Window/SceneView.h"
#include "Window/InspectorView.h"
#include "Asset/AssetRegistry.h"
+2 -2
View File
@@ -31,10 +31,10 @@ public:
std::scoped_lock lck(lock);
return status;
}
inline void setStatus(Status status)
inline void setStatus(Status _status)
{
std::scoped_lock lck(lock);
this->status = status;
status = _status;
}
protected:
std::mutex lock;
+2 -2
View File
@@ -91,10 +91,10 @@ AssetRegistry::AssetRegistry()
{
}
void AssetRegistry::init(const std::filesystem::path &rootFolder, Gfx::PGraphics graphics)
void AssetRegistry::init(const std::filesystem::path &_rootFolder, Gfx::PGraphics graphics)
{
AssetRegistry &reg = get();
reg.rootFolder = rootFolder;
reg.rootFolder = _rootFolder;
reg.fontLoader = new FontLoader(graphics);
reg.meshLoader = new MeshLoader(graphics);
reg.textureLoader = new TextureLoader(graphics);
+1
View File
@@ -1,6 +1,7 @@
#pragma once
#include "MinimalEngine.h"
#include "Asset.h"
#include "Material/MaterialAsset.h"
#include <string>
#include <map>
+2 -2
View File
@@ -52,8 +52,8 @@ void FontAsset::load()
continue;
}
Glyph& glyph = glyphs[c];
glyph.size = IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
glyph.bearing = IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
glyph.size = Math::IVector2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
glyph.bearing = Math::IVector2(face->glyph->bitmap_left, face->glyph->bitmap_top);
glyph.advance = face->glyph->advance.x;
TextureCreateInfo imageData;
imageData.format = Gfx::SE_FORMAT_R8_UINT;
+2 -2
View File
@@ -17,8 +17,8 @@ public:
struct Glyph
{
Gfx::PTexture2D texture;
IVector2 size;
IVector2 bearing;
Math::IVector2 size;
Math::IVector2 bearing;
uint32 advance;
};
const std::map<uint32, Glyph> getGlyphData() const { return glyphs; }
+14 -14
View File
@@ -36,7 +36,7 @@ void MeshLoader::importAsset(const std::filesystem::path &path)
import(path, asset);
}
void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials, Gfx::PGraphics graphics)
void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials)
{
using json = nlohmann::json;
for(uint32 i = 0; i < scene->mNumMaterials; ++i)
@@ -111,44 +111,44 @@ void findMeshRoots(aiNode *node, List<aiNode *> &meshNodes)
}
VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::PGraphics graphics)
{
Array<Vector> buffer(size);
Array<Math::Vector> buffer(size);
for(uint32 i = 0; i < size; ++i)
{
buffer[i] = Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z);
buffer[i] = Math::Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z);
}
VertexBufferCreateInfo vbInfo;
vbInfo.numVertices = size;
vbInfo.vertexSize = sizeof(Vector);
vbInfo.vertexSize = sizeof(Math::Vector);
vbInfo.resourceData.data = (uint8 *)buffer.data();
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
vbInfo.resourceData.size = sizeof(Vector) * (uint32)buffer.size();
vbInfo.resourceData.size = sizeof(Math::Vector) * buffer.size();
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT);
}
VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics)
{
Array<Vector2> buffer(size);
Array<Math::Vector2> buffer(size);
for(uint32 i = 0; i < size; ++i)
{
buffer[i] = Vector2(sourceData[i].x, sourceData[i].y);
buffer[i] = Math::Vector2(sourceData[i].x, sourceData[i].y);
}
VertexBufferCreateInfo vbInfo;
vbInfo.numVertices = size;
vbInfo.vertexSize = sizeof(Vector2);
vbInfo.vertexSize = sizeof(Math::Vector2);
vbInfo.resourceData.data = (uint8 *)buffer.data();
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
vbInfo.resourceData.size = sizeof(Vector2) * (uint32)buffer.size();
vbInfo.resourceData.size = sizeof(Math::Vector2) * buffer.size();
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
vertexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT);
}
void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials, Gfx::PGraphics graphics)
void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials)
{
for (uint32 meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
{
aiMesh *mesh = scene->mMeshes[meshIndex];
PMaterialAsset material = materials[mesh->mMaterialIndex];
PStaticMeshVertexInput vertexShaderInput = new StaticMeshVertexInput(std::string(mesh->mName.C_Str()));
StaticMeshDataType data;
data.positionStream = createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics);
@@ -188,7 +188,7 @@ void MeshLoader::loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMesh
idxInfo.indexType = Gfx::SE_INDEX_TYPE_UINT32;
idxInfo.resourceData.data = (uint8 *)indices.data();
idxInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
idxInfo.resourceData.size = sizeof(uint32) * (uint32)indices.size();
idxInfo.resourceData.size = sizeof(uint32) * indices.size();
Gfx::PIndexBuffer indexBuffer = graphics->createIndexBuffer(idxInfo);
indexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
@@ -249,10 +249,10 @@ void MeshLoader::import(std::filesystem::path path, PMeshAsset meshAsset)
Array<PMaterialAsset> globalMaterials(scene->mNumMaterials);
loadTextures(scene, path.parent_path());
loadMaterials(scene, globalMaterials, graphics);
loadMaterials(scene, globalMaterials);
Array<PMesh> globalMeshes(scene->mNumMeshes);
loadGlobalMeshes(scene, globalMeshes, globalMaterials, graphics);
loadGlobalMeshes(scene, globalMeshes, globalMaterials);
List<aiNode *> meshNodes;
+2 -2
View File
@@ -18,9 +18,9 @@ public:
~MeshLoader();
void importAsset(const std::filesystem::path& filePath);
private:
void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials, Gfx::PGraphics graphics);
void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials);
void loadTextures(const aiScene* scene, const std::filesystem::path& meshPath);
void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials, Gfx::PGraphics graphics);
void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials);
void convertAssimpARGB(unsigned char* dst, aiTexel* src, uint32 numPixels);
void import(std::filesystem::path path, PMeshAsset meshAsset);
+4 -4
View File
@@ -50,10 +50,10 @@ void TextureAsset::load()
createInfo.mipLevels = kTexture->numLevels;
createInfo.usage = Gfx::SE_IMAGE_USAGE_SAMPLED_BIT;
createInfo.resourceData.data = ktxTexture_GetData(ktxTexture(kTexture));
createInfo.resourceData.size = (uint32)ktxTexture_GetDataSize(ktxTexture(kTexture));
createInfo.resourceData.size = ktxTexture_GetDataSize(ktxTexture(kTexture));
createInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
Gfx::PTexture2D texture = WindowManager::getGraphics()->createTexture2D(createInfo);
texture->transferOwnership(Gfx::QueueType::GRAPHICS);
setTexture(texture);
Gfx::PTexture2D tex = WindowManager::getGraphics()->createTexture2D(createInfo);
tex->transferOwnership(Gfx::QueueType::GRAPHICS);
setTexture(tex);
setStatus(Asset::Status::Ready);
}
+2 -2
View File
@@ -12,10 +12,10 @@ public:
virtual ~TextureAsset();
virtual void save() override;
virtual void load() override;
void setTexture(Gfx::PTexture texture)
void setTexture(Gfx::PTexture _texture)
{
std::scoped_lock lck(lock);
this->texture = texture;
texture = _texture;
}
Gfx::PTexture getTexture()
{
+10
View File
@@ -679,6 +679,16 @@ public:
beginIt = iterator(_data);
endIt = iterator(_data + N);
}
StaticArray(std::initializer_list<T> init)
{
assert(init.size() == N);
auto beg = init.begin();
for (int i = 0; i < N; ++i)
{
_data[i] = *beg;
beg++;
}
}
~StaticArray()
{
}
+18 -18
View File
@@ -40,8 +40,8 @@ private:
size_t rightChild;
Pair<K, V> pair;
Node()
: leftChild(-1)
, rightChild(-1)
: leftChild(SIZE_MAX)
, rightChild(SIZE_MAX)
, pair()
{
}
@@ -50,8 +50,8 @@ private:
Node& operator=(const Node& other) = default;
Node& operator=(Node&& other) = default;
Node(K key)
: leftChild(-1)
, rightChild(-1)
: leftChild(SIZE_MAX)
, rightChild(SIZE_MAX)
, pair(std::move(key))
{
}
@@ -71,7 +71,7 @@ public:
using reference = PairType&;
using pointer = PairType*;
IteratorBase(size_t x = -1)
IteratorBase(size_t x = SIZE_MAX)
: node(x)
{
}
@@ -199,9 +199,9 @@ public:
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
constexpr Map() noexcept
: root(-1)
, beginIt(-1)
, endIt(-1)
: root(SIZE_MAX)
, beginIt(SIZE_MAX)
, endIt(SIZE_MAX)
, iteratorsDirty(true)
, _size(0)
, comp(Compare())
@@ -209,9 +209,9 @@ public:
}
constexpr explicit Map(const Compare& comp, const Allocator& alloc = Allocator()) noexcept(noexcept(Allocator()))
: nodeContainer(alloc)
, root(-1)
, beginIt(-1)
, endIt(-1)
, root(SIZE_MAX)
, beginIt(SIZE_MAX)
, endIt(SIZE_MAX)
, iteratorsDirty(true)
, _size(0)
, comp(comp)
@@ -219,9 +219,9 @@ public:
}
constexpr explicit Map(const Allocator& alloc) noexcept(noexcept(Compare))
: nodeContainer(alloc)
, root(-1)
, beginIt(-1)
, endIt(-1)
, root(SIZE_MAX)
, beginIt(SIZE_MAX)
, endIt(SIZE_MAX)
, iteratorsDirty(true)
, _size(0)
, comp(Compare())
@@ -335,7 +335,7 @@ public:
constexpr void clear()
{
nodeContainer.clear();
root = -1;
root = SIZE_MAX;
_size = 0;
markIteratorsDirty();
}
@@ -510,13 +510,13 @@ private:
{
newNode->rightChild = r;
newNode->leftChild = node->leftChild;
node->leftChild = -1;
node->leftChild = SIZE_MAX;
}
else
{
newNode->leftChild = r;
newNode->rightChild = node->rightChild;
node->rightChild = -1;
node->rightChild = SIZE_MAX;
}
return nodeContainer.size() - 1;
}
@@ -525,7 +525,7 @@ private:
{
size_t temp;
if (!isValid(r))
return -1;
return SIZE_MAX;
r = splay(r, key);
Node* node = getNode(r);
+3 -3
View File
@@ -18,10 +18,10 @@ PVertexBuffer Graphics::getNullVertexBuffer()
{
VertexBufferCreateInfo createInfo;
createInfo.numVertices = 1;
createInfo.vertexSize = sizeof(Vector4);
Vector4 data = Vector4(1, 1, 1, 1);
createInfo.vertexSize = sizeof(Math::Vector4);
Math::Vector4 data = Math::Vector4(1, 1, 1, 1);
createInfo.resourceData.data = reinterpret_cast<uint8*>(&data);
createInfo.resourceData.size = sizeof(Vector4);
createInfo.resourceData.size = sizeof(Math::Vector4);
nullVertexBuffer = createVertexBuffer(createInfo);
}
return nullVertexBuffer;
+4 -2
View File
@@ -50,7 +50,8 @@ struct ViewportCreateInfo
// doesnt own the data, only proxy it
struct BulkResourceData
{
uint32 size = 0;
uint64 size = 0;
uint64 offset = 0;
uint8 *data = nullptr;
Gfx::QueueType owner = Gfx::QueueType::GRAPHICS;
};
@@ -111,8 +112,9 @@ struct StructuredBufferCreateInfo
};
struct ShaderCreateInfo
{
std::string mainModule;
//It's possible to input multiple source files for materials or vertexFactories
Array<std::string> shaderCode;
Array<std::string> additionalModules;
std::string name; // Debug info
std::string entryPoint;
Array<const char*> typeParameter;
+130 -6
View File
@@ -2,6 +2,7 @@
#include "Graphics.h"
#include "RenderPass/DepthPrepass.h"
#include "RenderPass/BasePass.h"
#include "Material/MaterialAsset.h"
using namespace Seele;
using namespace Seele::Gfx;
@@ -11,9 +12,9 @@ std::string getShaderNameFromRenderPassType(Gfx::RenderPassType type)
switch (type)
{
case Gfx::RenderPassType::DepthPrepass:
return "DepthPrepass.slang";
return "DepthPrepass";
case Gfx::RenderPassType::BasePass:
return "ForwardPlus.slang";
return "ForwardPlus";
default:
return "";
}
@@ -64,8 +65,6 @@ ShaderCollection& ShaderMap::createShaders(
ShaderCreateInfo createInfo;
createInfo.entryPoint = "vertexMain";
createInfo.typeParameter = {material->getName().c_str()};
createInfo.defines["VERTEX_INPUT_IMPORT"] = vertexInput->getShaderFilename();
createInfo.defines["MATERIAL_IMPORT"] = material->getName().c_str();
createInfo.defines["NUM_MATERIAL_TEXCOORDS"] = "1";
createInfo.defines["USE_INSTANCING"] = "0";
modifyRenderPassMacros(renderPass, createInfo.defines);
@@ -73,7 +72,9 @@ ShaderCollection& ShaderMap::createShaders(
std::ifstream codeStream("./shaders/" + getShaderNameFromRenderPassType(renderPass));
createInfo.shaderCode.add(std::string(std::istreambuf_iterator<char>{codeStream}, {}));
createInfo.mainModule = getShaderNameFromRenderPassType(renderPass);
createInfo.additionalModules.add(vertexInput->getShaderFilename());
createInfo.additionalModules.add(material->getName());
collection.vertexShader = graphics->createVertexShader(createInfo);
@@ -227,7 +228,7 @@ VertexBuffer::VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint3
VertexBuffer::~VertexBuffer()
{
}
IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint32 size, Gfx::SeIndexType indexType, QueueType startQueueType)
IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType indexType, QueueType startQueueType)
: Buffer(mapping, startQueueType)
, indexType(indexType)
{
@@ -264,6 +265,129 @@ const Array<VertexElement> VertexStream::getVertexDescriptions() const
{
return vertexDescription;
}
VertexDataManager::VertexDataManager(PGraphics graphics)
: currentSize(8 * 1024 * 1024)
, inUse(0)
, graphics(graphics)
{
VertexBufferCreateInfo defaultInfo = {
.resourceData = {
.size = currentSize,
.data = nullptr,
}
};
buffer = graphics->createVertexBuffer(defaultInfo);
}
VertexDataManager::~VertexDataManager()
{
}
VertexDataAllocation VertexDataManager::createVertexBuffer(const VertexBufferCreateInfo& vbInfo)
{
VertexDataAllocation data = allocateData(vbInfo.resourceData.size);
buffer->updateRegion(BulkResourceData{
.size = data.size,
.offset = data.offset,
.data = vbInfo.resourceData.data
});
activeAllocations[data.offset] = data;
return data;
}
void VertexDataManager::freeAllocation(VertexDataAllocation alloc)
{
uint64 lowerBound = alloc.offset;
uint64 upperBound = alloc.offset + alloc.size;
bool joinedLower = false;
uint64 lowerOffset = 0;
//Join lower bound
for (auto& [offset, freeAlloc] : freeRanges)
{
if (freeAlloc.offset <= lowerBound
&& freeAlloc.offset + freeAlloc.size >= upperBound)
{
// allocation is already in a free region
return;
}
if (freeAlloc.offset + freeAlloc.size == lowerBound)
{
//extend freeAlloc by the allocatedSize
freeAlloc.size += alloc.size;
joinedLower = true;
lowerOffset = freeAlloc.offset;
break;
}
}
//Join upper bound
auto foundAlloc = freeRanges.find(upperBound);
if (foundAlloc != freeRanges.end())
{
// There is a free allocation ending where the new free one ends
if (joinedLower)
{
// extend allocHandle by another foundAlloc->allocatedSize bytes
freeRanges[lowerOffset].size += foundAlloc->value.size;
freeRanges.erase(upperBound);
}
else
{
// set foundAlloc back by size amount
freeRanges[upperBound].offset -= alloc.size;
freeRanges[upperBound].size += alloc.size;
// place back at correct offset
freeRanges[freeRanges[upperBound].offset] = freeRanges[upperBound];
// remove from offset map since key changes
freeRanges.erase(upperBound);
}
}
else
{
// No matching upper bound found
if(!joinedLower)
{
// Lower bound also not joined, create new range
freeRanges[alloc.offset] = alloc;
}
}
activeAllocations.erase(alloc.offset);
inUse -= alloc.size;
}
VertexDataAllocation VertexDataManager::allocateData(uint64 size)
{
for (auto& [offset, freeAllocation] : freeRanges)
{
assert(offset == freeAllocation.offset);
if (freeAllocation.size == size)
{
activeAllocations[offset] = freeAllocation;
freeRanges.erase(offset);
inUse += size;
return freeAllocation;
}
else if (size < freeAllocation.size)
{
freeAllocation.size -= size;
freeAllocation.offset += size;
VertexDataAllocation subAlloc = VertexDataAllocation(size, offset);
activeAllocations[offset] = subAlloc;
freeRanges[freeAllocation.offset] = freeAllocation;
freeRanges.erase(offset);
inUse += size;
return subAlloc;
}
}
throw std::logic_error("TODO: expand buffer");
}
VertexDeclaration::VertexDeclaration()
{
}
+36 -4
View File
@@ -3,7 +3,10 @@
#include "Containers/Array.h"
#include "Containers/List.h"
#include "GraphicsInitializer.h"
#pragma warning(push)
#pragma warning(disable: 4701)
#include <boost/crc.hpp>
#pragma warning(pop)
#include <functional>
@@ -372,6 +375,8 @@ public:
return vertexSize;
}
virtual void updateRegion(BulkResourceData update) = 0;
protected:
// Inherited via QueueOwnedResource
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
@@ -385,9 +390,9 @@ DEFINE_REF(VertexBuffer)
class IndexBuffer : public Buffer
{
public:
IndexBuffer(QueueFamilyMapping mapping, uint32 size, Gfx::SeIndexType index, QueueType startQueueType);
IndexBuffer(QueueFamilyMapping mapping, uint64 size, Gfx::SeIndexType index, QueueType startQueueType);
virtual ~IndexBuffer();
constexpr uint32 getNumIndices() const
constexpr uint64 getNumIndices() const
{
return numIndices;
}
@@ -402,7 +407,7 @@ protected:
virtual void executePipelineBarrier(SeAccessFlags srcAccess, SePipelineStageFlags srcStage,
SeAccessFlags dstAccess, SePipelineStageFlags dstStage) = 0;
Gfx::SeIndexType indexType;
uint32 numIndices;
uint64 numIndices;
};
DEFINE_REF(IndexBuffer)
@@ -442,7 +447,6 @@ protected:
uint32 stride;
};
DEFINE_REF(StructuredBuffer)
class VertexStream
{
public:
@@ -459,6 +463,34 @@ public:
uint8 instanced;
};
DEFINE_REF(VertexStream)
struct VertexDataAllocation
{
uint64 size;
uint64 offset;
};
class VertexDataManager
{
public:
VertexDataManager(PGraphics graphics);
virtual ~VertexDataManager();
VertexDataAllocation createVertexBuffer(const VertexBufferCreateInfo& vbInfo);
void freeAllocation(VertexDataAllocation alloc);
PVertexBuffer getVertexBuffer() const { return buffer; }
private:
VertexDataAllocation allocateData(uint64 size);
Map<uint64, VertexDataAllocation> freeRanges;
Map<uint64, VertexDataAllocation> activeAllocations;
uint64 currentSize;
uint64 inUse;
PVertexBuffer buffer;
PGraphics graphics;
};
DEFINE_REF(VertexDataManager)
class VertexDeclaration
{
public:
+1 -3
View File
@@ -34,7 +34,7 @@ public:
};
struct MeshBatch
{
std::vector<MeshBatchElement> elements;
Array<MeshBatchElement> elements;
uint8 useReverseCulling : 1;
uint8 isBackfaceCullingDisabled : 1;
@@ -73,10 +73,8 @@ struct MeshBatch
MeshBatch& operator=(const MeshBatch& other) = default;
MeshBatch& operator=(MeshBatch&& other) = default;
};
DECLARE_REF(PrimitiveComponent)
struct StaticMeshBatch : public MeshBatch
{
uint32 index;
PPrimitiveComponent primitiveComponent;
};
} // namespace Seele
+7 -6
View File
@@ -1,10 +1,11 @@
#include "BasePass.h"
#include "Graphics/Graphics.h"
#include "Window/Window.h"
#include "Scene/Components/CameraComponent.h"
#include "Scene/Component/Camera.h"
#include "Scene/Actor/CameraActor.h"
#include "Math/Vector.h"
#include "RenderGraph.h"
#include "Material/MaterialAsset.h"
using namespace Seele;
@@ -73,7 +74,7 @@ BasePass::BasePass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActo
: RenderPass(graphics, viewport)
, processor(new BasePassMeshProcessor(viewport, graphics, false))
, descriptorSets(4)
, source(source->getCameraComponent())
, source(source)
{
UniformBufferCreateInfo uniformInitializer;
basePassLayout = graphics->createPipelineLayout();
@@ -120,11 +121,11 @@ void BasePass::beginFrame()
primitiveLayout->reset();
BulkResourceData uniformUpdate;
viewParams.viewMatrix = source->getViewMatrix();
viewParams.projectionMatrix = source->getProjectionMatrix();
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
viewParams.viewMatrix = source->getCameraComponent().getViewMatrix();
viewParams.projectionMatrix = source->getCameraComponent().getProjectionMatrix();
viewParams.cameraPosition = Math::Vector4(source->getCameraComponent().getCameraPosition(), 0);
viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
viewParams.screenDimensions = Math::Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
uniformUpdate.size = sizeof(ViewParameter);
uniformUpdate.data = (uint8*)&viewParams;
viewParamBuffer->updateContents(uniformUpdate);
+2 -3
View File
@@ -27,10 +27,9 @@ private:
};
DEFINE_REF(BasePassMeshProcessor)
DECLARE_REF(CameraActor)
DECLARE_REF(CameraComponent)
struct BasePassData
{
std::vector<StaticMeshBatch> staticDrawList;
Array<StaticMeshBatch> staticDrawList;
};
class BasePass : public RenderPass<BasePassData>
{
@@ -49,7 +48,7 @@ private:
UPBasePassMeshProcessor processor;
Array<Gfx::PDescriptorSet> descriptorSets;
PCameraComponent source;
PCameraActor source;
Gfx::PPipelineLayout basePassLayout;
// Set 0: Light environment
static constexpr uint32 INDEX_LIGHT_ENV = 0;
@@ -1,10 +1,11 @@
#include "DepthPrepass.h"
#include "Graphics/Graphics.h"
#include "Window/Window.h"
#include "Scene/Components/CameraComponent.h"
#include "Scene/Component/Camera.h"
#include "Scene/Actor/CameraActor.h"
#include "Math/Vector.h"
#include "RenderGraph.h"
#include "Material/MaterialAsset.h"
using namespace Seele;
@@ -72,7 +73,7 @@ DepthPrepass::DepthPrepass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCa
: RenderPass(graphics, viewport)
, processor(new DepthPrepassMeshProcessor(viewport, graphics))
, descriptorSets(3)
, source(source->getCameraComponent())
, source(source)
{
UniformBufferCreateInfo uniformInitializer;
@@ -103,11 +104,11 @@ void DepthPrepass::beginFrame()
primitiveLayout->reset();
BulkResourceData uniformUpdate;
viewParams.viewMatrix = source->getViewMatrix();
viewParams.projectionMatrix = source->getProjectionMatrix();
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
viewParams.viewMatrix = source->getCameraComponent().getViewMatrix();
viewParams.projectionMatrix = source->getCameraComponent().getProjectionMatrix();
viewParams.cameraPosition = Math::Vector4(source->getCameraComponent().getCameraPosition(), 0);
viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
viewParams.screenDimensions = Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
viewParams.screenDimensions = Math::Vector2(static_cast<float>(viewport->getSizeX()), static_cast<float>(viewport->getSizeY()));
uniformUpdate.size = sizeof(ViewParameter);
uniformUpdate.data = (uint8*)&viewParams;
viewParamBuffer->updateContents(uniformUpdate);
@@ -24,10 +24,9 @@ private:
};
DEFINE_REF(DepthPrepassMeshProcessor)
DECLARE_REF(CameraActor)
DECLARE_REF(CameraComponent)
struct DepthPrepassData
{
std::vector<StaticMeshBatch> staticDrawList;
Array<StaticMeshBatch> staticDrawList;
};
class DepthPrepass : public RenderPass<DepthPrepassData>
{
@@ -46,7 +45,7 @@ private:
UPDepthPrepassMeshProcessor processor;
Array<Gfx::PDescriptorSet> descriptorSets;
PCameraComponent source;
PCameraActor source;
Gfx::PPipelineLayout depthPrepassLayout;
// Set 0: viewParameter
static constexpr uint32 INDEX_VIEW_PARAMS = 0;
@@ -2,14 +2,14 @@
#include "Graphics/Graphics.h"
#include "Scene/Scene.h"
#include "Scene/Actor/CameraActor.h"
#include "Scene/Components/CameraComponent.h"
#include "Scene/Component/Camera.h"
#include "RenderGraph.h"
using namespace Seele;
LightCullingPass::LightCullingPass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor camera)
: RenderPass(graphics, viewport)
, source(camera->getCameraComponent())
, source(camera)
{
}
@@ -24,11 +24,11 @@ void LightCullingPass::beginFrame()
uint32_t viewportHeight = viewport->getSizeY();
BulkResourceData uniformUpdate;
viewParams.viewMatrix = source->getViewMatrix();
viewParams.projectionMatrix = source->getProjectionMatrix();
viewParams.cameraPosition = Vector4(source->getCameraPosition(), 0);
viewParams.viewMatrix = source->getCameraComponent().getViewMatrix();
viewParams.projectionMatrix = source->getCameraComponent().getProjectionMatrix();
viewParams.cameraPosition = Math::Vector4(source->getCameraComponent().getCameraPosition(), 0);
viewParams.inverseProjectionMatrix = glm::inverse(viewParams.projectionMatrix);
viewParams.screenDimensions = Vector2(static_cast<float>(viewportWidth), static_cast<float>(viewportHeight));
viewParams.screenDimensions = Math::Vector2(static_cast<float>(viewportWidth), static_cast<float>(viewportHeight));
uniformUpdate.size = sizeof(ViewParameter);
uniformUpdate.data = (uint8*)&viewParams;
viewParamsBuffer->updateContents(uniformUpdate);
@@ -162,13 +162,7 @@ void LightCullingPass::publishOutputs()
ShaderCreateInfo createInfo;
createInfo.name = "Culling";
std::ifstream codeStream("./shaders/LightCulling.slang", std::ios::ate);
auto fileSize = codeStream.tellg();
codeStream.seekg(0);
Array<char> buffer(static_cast<uint32>(fileSize));
codeStream.read(buffer.data(), fileSize);
createInfo.shaderCode.add(std::string(buffer.data()));
createInfo.mainModule = "LightCulling";
createInfo.entryPoint = "cullLights";
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
createInfo.defines["INDEX_LIGHT_ENV"] = "1";
@@ -269,10 +263,10 @@ void LightCullingPass::setupFrustums()
glm::uvec3 numThreadGroups = glm::ceil(glm::vec3(numThreads.x / (float)BLOCK_SIZE, numThreads.y / (float)BLOCK_SIZE, 1));
viewParams = {
.viewMatrix = source->getViewMatrix(),
.projectionMatrix = source->getProjectionMatrix(),
.inverseProjectionMatrix = glm::inverse(source->getProjectionMatrix()),
.cameraPosition = Vector4(source->getCameraPosition(), 0),
.viewMatrix = source->getCameraComponent().getViewMatrix(),
.projectionMatrix = source->getCameraComponent().getProjectionMatrix(),
.inverseProjectionMatrix = glm::inverse(source->getCameraComponent().getProjectionMatrix()),
.cameraPosition = Math::Vector4(source->getTransform().getPosition(), 0),
.screenDimensions = glm::vec2(viewportWidth, viewportHeight),
};
dispatchParams.numThreads = numThreads;
@@ -288,13 +282,7 @@ void LightCullingPass::setupFrustums()
ShaderCreateInfo createInfo;
createInfo.name = "Frustum";
std::ifstream codeStream("./shaders/ComputeFrustums.slang", std::ios::ate);
auto fileSize = codeStream.tellg();
codeStream.seekg(0);
Array<char> buffer(static_cast<uint32>(fileSize));
codeStream.read(buffer.data(), fileSize);
createInfo.shaderCode.add(std::string(buffer.data()));
createInfo.mainModule = "ComputeFrustums";
createInfo.entryPoint = "computeFrustums";
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
frustumShader = graphics->createComputeShader(createInfo);
@@ -6,7 +6,6 @@
namespace Seele
{
DECLARE_REF(CameraActor)
DECLARE_REF(CameraComponent)
DECLARE_REF(Scene)
DECLARE_REF(Viewport)
struct LightCullingPassData
@@ -37,7 +36,7 @@ private:
} dispatchParams;
struct Plane
{
Vector n;
Math::Vector n;
float d;
};
struct Frustum
@@ -72,7 +71,7 @@ private:
Gfx::PComputeShader cullingShader;
Gfx::PPipelineLayout cullingLayout;
Gfx::PComputePipeline cullingPipeline;
PCameraComponent source;
PCameraActor source;
};
DEFINE_REF(LightCullingPass)
} // namespace Seele
+7 -6
View File
@@ -26,15 +26,16 @@ public:
virtual void endFrame() = 0;
virtual void publishOutputs() = 0;
virtual void createRenderPass() = 0;
void setResources(PRenderGraphResources resources) { this->resources = resources; }
void setResources(PRenderGraphResources _resources) { resources = _resources; }
protected:
struct ViewParameter
{
Matrix4 viewMatrix;
Matrix4 projectionMatrix;
Matrix4 inverseProjectionMatrix;
Vector4 cameraPosition;
Vector2 screenDimensions;
Math::Matrix4 viewMatrix;
Math::Matrix4 projectionMatrix;
Math::Matrix4 inverseProjectionMatrix;
Math::Vector4 cameraPosition;
Math::Vector2 screenDimensions;
Math::Vector2 pad0;
} viewParams;
PRenderGraphResources resources;
RenderPassDataType passData;
+16 -22
View File
@@ -20,16 +20,16 @@ void TextPass::beginFrame()
{
for(TextRender& render : passData.texts)
{
FontData& fontData = getFontData(render.font);
TextResources& resources = textResources[render.font].add();
FontData& fd = getFontData(render.font);
TextResources& res = textResources[render.font].add();
Array<GlyphInstanceData> instanceData;
float x = render.position.x;
float y = render.position.y;
for(uint32 c : render.text)
{
const GlyphData& glyph = fontData.glyphDataSet[fontData.characterToGlyphIndex[c]];
Vector2 bearing = glyph.bearing;
Vector2 size = glyph.size;
const GlyphData& glyph = fd.glyphDataSet[fd.characterToGlyphIndex[c]];
Math::Vector2 bearing = glyph.bearing;
Math::Vector2 size = glyph.size;
float xpos = x + bearing.x * render.scale;
float ypos = y - (size.y - bearing.y) * render.scale;
@@ -37,9 +37,9 @@ void TextPass::beginFrame()
float h = size.y * render.scale;
instanceData.add(GlyphInstanceData{
.position = Vector2(xpos, ypos),
.widthHeight = Vector2(w, h),
.glyphIndex = fontData.characterToGlyphIndex[c],
.position = Math::Vector2(xpos, ypos),
.widthHeight = Math::Vector2(w, h),
.glyphIndex = fd.characterToGlyphIndex[c],
});
x += (glyph.advance >> 6) * render.scale;
}
@@ -51,11 +51,11 @@ void TextPass::beginFrame()
.vertexSize = sizeof(GlyphInstanceData),
.numVertices = static_cast<uint32>(instanceData.size()),
};
resources.vertexBuffer = graphics->createVertexBuffer(vbInfo);
res.vertexBuffer = graphics->createVertexBuffer(vbInfo);
resources.textureArraySet = fontData.textureArraySet;
res.textureArraySet = fd.textureArraySet;
resources.textData = {
res.textData = {
.textColor = render.textColor,
.scale = render.scale,
};
@@ -67,12 +67,12 @@ void TextPass::render()
{
graphics->beginRenderPass(renderPass);
Array<Gfx::PRenderCommand> commands;
for(const auto& [fontAsset, resources] : textResources)
for(const auto& [fontAsset, res] : textResources)
{
Gfx::PRenderCommand command = graphics->createRenderCommand("TextPassCommand");
command->setViewport(viewport);
command->bindPipeline(pipeline);
for(const auto& resource : resources)
for(const auto& resource : res)
{
command->bindDescriptor({generalSet, resource.textureArraySet});
command->bindVertexBuffer({VertexInputStream(0, 0, resource.vertexBuffer)});
@@ -100,14 +100,8 @@ void TextPass::publishOutputs()
void TextPass::createRenderPass()
{
depthAttachment = resources->requestRenderTarget("UIPASS_DEPTH");
std::ifstream codeStream("./shaders/TextPass.slang", std::ios::ate);
auto fileSize = codeStream.tellg();
codeStream.seekg(0);
Array<char> buffer(static_cast<uint32>(fileSize));
codeStream.read(buffer.data(), fileSize);
ShaderCreateInfo createInfo;
createInfo.shaderCode.add(std::string(buffer.data()));
createInfo.mainModule = "TextPass";
createInfo.defines["INDEX_VIEW_PARAMS"] = "0";
createInfo.name = "TextVertex";
createInfo.entryPoint = "vertexMain";
@@ -152,10 +146,10 @@ void TextPass::createRenderPass()
textureArrayLayout->addDescriptorBinding(0, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT);
textureArrayLayout->create();
Matrix4 projectionMatrix = glm::ortho(0.f, (float)viewport->getSizeX(), 0.f, (float)viewport->getSizeY());
Math::Matrix4 projectionMatrix = glm::ortho(0.f, (float)viewport->getSizeX(), 0.f, (float)viewport->getSizeY());
projectionBuffer = graphics->createUniformBuffer({
.resourceData = {
.size = sizeof(Matrix4),
.size = sizeof(Math::Matrix4),
.data = (uint8*)&projectionMatrix,
},
.bDynamic = false,
+7 -7
View File
@@ -13,8 +13,8 @@ struct TextRender
{
std::string text;
PFontAsset font;
Vector4 textColor;
Vector2 position;
Math::Vector4 textColor;
Math::Vector2 position;
float scale;
};
struct TextPassData
@@ -35,19 +35,19 @@ public:
private:
struct GlyphData
{
Vector2 bearing;
Vector2 size;
Math::Vector2 bearing;
Math::Vector2 size;
uint32 advance;
};
struct GlyphInstanceData
{
Vector2 position;
Vector2 widthHeight;
Math::Vector2 position;
Math::Vector2 widthHeight;
uint32 glyphIndex;
};
struct TextData
{
Vector4 textColor;
Math::Vector4 textColor;
float scale;
};
struct FontData
+5 -11
View File
@@ -26,7 +26,7 @@ void UIPass::beginFrame()
.numVertices = (uint32)passData.renderElements.size(),
};
elementBuffer = graphics->createVertexBuffer(info);
uint32 numTextures = passData.usedTextures.size();
uint32 numTextures = static_cast<uint32>(passData.usedTextures.size());
numTexturesBuffer->updateContents({
.size = sizeof(uint32),
.data = (uint8*)&numTextures,
@@ -45,7 +45,7 @@ void UIPass::render()
command->bindPipeline(pipeline);
command->bindVertexBuffer({VertexInputStream(0, 0, elementBuffer)});
command->bindDescriptor(descriptorSet);
command->draw(4, passData.renderElements.size(), 0, 0);
command->draw(4, static_cast<uint32>(passData.renderElements.size()), 0, 0);
graphics->executeCommands(Array<Gfx::PRenderCommand>({command}));
graphics->endRenderPass();
//co_return;
@@ -76,14 +76,8 @@ void UIPass::publishOutputs()
void UIPass::createRenderPass()
{
std::ifstream codeStream("./shaders/UIPass.slang", std::ios::ate);
auto fileSize = codeStream.tellg();
codeStream.seekg(0);
Array<char> buffer(static_cast<uint32>(fileSize));
codeStream.read(buffer.data(), fileSize);
ShaderCreateInfo createInfo;
createInfo.shaderCode.add(std::string(buffer.data()));
createInfo.mainModule = "UIPass";
createInfo.name = "UIVertex";
createInfo.entryPoint = "vertexMain";
vertexShader = graphics->createVertexShader(createInfo);
@@ -141,10 +135,10 @@ void UIPass::createRenderPass()
descriptorLayout->addDescriptorBinding(3, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 256, Gfx::SE_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT | Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT);
descriptorLayout->create();
Matrix4 projectionMatrix = glm::ortho(0, 1, 1, 0);
Math::Matrix4 projectionMatrix = glm::ortho(0, 1, 1, 0);
UniformBufferCreateInfo info = {
.resourceData = {
.size = sizeof(Matrix4),
.size = sizeof(Math::Matrix4),
.data = (uint8*)&projectionMatrix,
},
.bDynamic = false,
@@ -54,16 +54,16 @@ void StaticMeshVertexInput::init(Gfx::PGraphics graphics)
{
elements.add(accessStreamComponent(
data.textureCoordinates[coordinateIndex],
baseTexCoordAttribute + coordinateIndex
static_cast<uint8>(baseTexCoordAttribute + coordinateIndex)
));
}
}
initDeclaration(graphics, elements);
}
void StaticMeshVertexInput::setData(StaticMeshDataType&& data)
void StaticMeshVertexInput::setData(StaticMeshDataType&& _data)
{
this->data = std::move(data);
data = std::move(_data);
}
IMPLEMENT_VERTEX_INPUT_TYPE(StaticMeshVertexInput, "StaticMeshVertexInput")
+9 -7
View File
@@ -43,7 +43,7 @@ const char* VertexInputType::getName()
return name;
}
const char* VertexInputType::getShaderFilename()
std::string VertexInputType::getShaderFilename()
{
return shaderFilename;
}
@@ -90,20 +90,22 @@ Gfx::VertexElement VertexShaderInput::accessStreamComponent(const VertexStreamCo
{
VertexStream vertexStream;
vertexStream.vertexBuffer = component.vertexBuffer;
vertexStream.stride = component.stride;
vertexStream.offset = component.offset;
assert(component.stride < UINT8_MAX && component.offset < UINT8_MAX && component.offset < UINT8_MAX);
vertexStream.stride = static_cast<uint8>(component.stride);
vertexStream.offset = static_cast<uint8>(component.offset);
return Gfx::VertexElement((uint8)streams.indexOf(streams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride);
return Gfx::VertexElement((uint8)streams.indexOf(streams.addUnique(vertexStream)), static_cast<uint8>(component.offset), component.type, attributeIndex, vertexStream.stride);
}
Gfx::VertexElement VertexShaderInput::accessPositionStreamComponent(const VertexStreamComponent& component, uint8 attributeIndex)
{
VertexStream vertexStream;
vertexStream.vertexBuffer = component.vertexBuffer;
vertexStream.stride = component.stride;
vertexStream.offset = component.offset;
assert(component.stride < UINT8_MAX && component.offset < UINT8_MAX && component.offset < UINT8_MAX);
vertexStream.stride = static_cast<uint8>(component.stride);
vertexStream.offset = static_cast<uint8>(component.offset);
return Gfx::VertexElement((uint8)positionStreams.indexOf(positionStreams.addUnique(vertexStream)), component.offset, component.type, attributeIndex, vertexStream.stride);
return Gfx::VertexElement((uint8)positionStreams.indexOf(positionStreams.addUnique(vertexStream)), static_cast<uint8>(component.offset), component.type, attributeIndex, vertexStream.stride);
}
void VertexShaderInput::initDeclaration(Gfx::PGraphics graphics, Array<Gfx::VertexElement>& elements)
+1 -1
View File
@@ -91,7 +91,7 @@ public:
virtual ~VertexInputType();
const char* getName();
const char* getShaderFilename();
std::string getShaderFilename();
private:
const char* name;
const char* shaderFilename;
@@ -95,7 +95,7 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
VkDeviceSize allocatedOffset = it.first;
PSubAllocation freeAllocation = it.second;
assert(allocatedOffset == freeAllocation->allocatedOffset);
VkDeviceSize alignedOffset = align(allocatedOffset, alignment);
VkDeviceSize alignedOffset = Math::align(allocatedOffset, alignment);
VkDeviceSize alignmentAdjustment = alignedOffset - allocatedOffset;
VkDeviceSize size = alignmentAdjustment + requestedSize;
if (freeAllocation->size == size)
@@ -171,6 +171,8 @@ void Allocation::markFree(SubAllocation *allocation)
allocHandle = foundAlloc->second;
allocHandle->allocatedOffset -= allocation->allocatedSize;
allocHandle->alignedOffset -= allocation->allocatedSize;
allocHandle->size += allocation->allocatedSize;
allocHandle->allocatedSize += allocation->allocatedSize;
// place back at correct offset
freeRanges[allocHandle->allocatedOffset] = allocHandle;
// remove from offset map since key changes
@@ -310,7 +312,7 @@ void StagingManager::clearPending()
{
}
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
PStagingBuffer StagingManager::allocateStagingBuffer(uint64 size, VkBufferUsageFlags usage, bool bCPURead)
{
std::scoped_lock l(lock);
for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
+3 -3
View File
@@ -191,7 +191,7 @@ public:
{
return allocation->getOffset();
}
uint32 getSize() const
uint64 getSize() const
{
return size;
}
@@ -203,7 +203,7 @@ public:
private:
PSubAllocation allocation;
VkBuffer buffer;
uint32 size;
uint64 size;
VkBufferUsageFlags usage;
uint8 bReadable;
friend class StagingManager;
@@ -215,7 +215,7 @@ class StagingManager
public:
StagingManager(PGraphics graphics, PAllocator allocator);
~StagingManager();
PStagingBuffer allocateStagingBuffer(uint32 size, VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, bool bCPURead = false);
PStagingBuffer allocateStagingBuffer(uint64 size, VkBufferUsageFlags usageFlags = VK_BUFFER_USAGE_TRANSFER_SRC_BIT, bool bCPURead = false);
void releaseStagingBuffer(PStagingBuffer buffer);
void clearPending();
+22 -4
View File
@@ -9,6 +9,8 @@ using namespace Seele::Vulkan;
struct PendingBuffer
{
uint64 offset;
uint64 size;
PStagingBuffer stagingBuffer;
Gfx::QueueType prevQueue;
bool bWriteOnly;
@@ -16,7 +18,7 @@ struct PendingBuffer
static std::map<ShaderBuffer *, PendingBuffer> pendingBuffers;
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic)
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic)
: graphics(graphics)
, currentBuffer(0)
, size(size)
@@ -63,7 +65,7 @@ ShaderBuffer::~ShaderBuffer()
{
PCmdBuffer cmdBuffer = graphics->getQueueCommands(owner)->getCommands();
VkDevice device = graphics->getDevice();
auto deletionLambda = [cmdBuffer, device](VkBuffer buffer) -> void
auto deletionLambda = [cmdBuffer, device](VkBuffer) -> void
{
//co_await cmdBuffer->asyncWait();
//vkDestroyBuffer(device, buffer, nullptr);
@@ -169,6 +171,11 @@ void ShaderBuffer::executePipelineBarrier(VkAccessFlags srcAccess, VkPipelineSta
}
void *ShaderBuffer::lock(bool bWriteOnly)
{
return lockRegion(0, size, bWriteOnly);
}
void *ShaderBuffer::lockRegion(uint64 regionOffset, uint64 regionSize, bool bWriteOnly)
{
void *data = nullptr;
@@ -189,10 +196,12 @@ void *ShaderBuffer::lock(bool bWriteOnly)
PendingBuffer pending;
pending.bWriteOnly = bWriteOnly;
pending.prevQueue = owner;
pending.offset = regionOffset;
pending.size = regionSize;
if (bWriteOnly)
{
//requestOwnershipTransfer(Gfx::QueueType::DEDICATED_TRANSFER);
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
PStagingBuffer stagingBuffer = graphics->getStagingManager()->allocateStagingBuffer(regionSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
data = stagingBuffer->getMappedPointer();
pending.stagingBuffer = stagingBuffer;
}
@@ -255,7 +264,8 @@ void ShaderBuffer::unlock()
VkBufferCopy region;
std::memset(&region, 0, sizeof(VkBufferCopy));
region.size = size;
region.size = pending.size;
region.dstOffset = pending.offset;
vkCmdCopyBuffer(cmdHandle, stagingBuffer->getHandle(), buffers[currentBuffer].buffer, 1, &region);
graphics->getQueueCommands(owner)->submitCommands();
}
@@ -448,6 +458,14 @@ VertexBuffer::~VertexBuffer()
{
}
void VertexBuffer::updateRegion(BulkResourceData update)
{
void* data = lockRegion(update.offset, update.size);
std::memcpy(data, update.data, update.size);
unlock();
}
void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
{
Gfx::QueueOwnedResource::transferOwnership(newOwner);
@@ -302,7 +302,7 @@ void RenderCommand::pushConstants(Gfx::PPipelineLayout layout, Gfx::SeShaderStag
void RenderCommand::draw(const MeshBatchElement& data)
{
assert(threadId == std::this_thread::get_id());
vkCmdDrawIndexed(handle, data.indexBuffer->getNumIndices(), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
vkCmdDrawIndexed(handle, static_cast<uint32>(data.indexBuffer->getNumIndices()), data.numInstances, data.minVertexIndex, data.baseVertexIndex, 0);
}
void RenderCommand::draw(uint32 vertexCount, uint32 instanceCount, int32 firstVertex, uint32 firstInstance)
@@ -67,6 +67,7 @@ public:
virtual Gfx::PPipelineLayout createPipelineLayout(Gfx::PPipelineLayout baseLayout = nullptr) override;
virtual void copyTexture(Gfx::PTexture srcTexture, Gfx::PTexture dstTexture) override;
protected:
Array<const char *> getRequiredExtensions();
void initInstance(GraphicsInitializer initInfo);
@@ -1390,7 +1390,7 @@ Gfx::SeCompareOp Seele::Vulkan::cast(const VkCompareOp &op)
VkClearValue Seele::Vulkan::cast(const Gfx::SeClearValue& clear)
{
VkClearValue result;
if(sizeof(clear) == sizeof(Gfx::SeClearColorValue))
if constexpr (sizeof(clear) == sizeof(Gfx::SeClearColorValue))
{
result.color.float32[0] = clear.color.float32[0];
result.color.float32[1] = clear.color.float32[1];
@@ -1408,7 +1408,7 @@ VkClearValue Seele::Vulkan::cast(const Gfx::SeClearValue& clear)
Gfx::SeClearValue Seele::Vulkan::cast(const VkClearValue& clear)
{
Gfx::SeClearValue result;
if(sizeof(clear) == sizeof(VkClearColorValue))
if constexpr (sizeof(clear) == sizeof(VkClearColorValue))
{
result.color.float32[0] = clear.color.float32[0];
result.color.float32[1] = clear.color.float32[1];
@@ -72,13 +72,13 @@ DEFINE_REF(VertexDeclaration)
class ShaderBuffer
{
public:
ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false);
ShaderBuffer(PGraphics graphics, uint64 size, VkBufferUsageFlags usage, Gfx::QueueType& queueType, bool bDynamic = false);
virtual ~ShaderBuffer();
VkBuffer getHandle() const
{
return buffers[currentBuffer].buffer;
}
uint32 getSize() const
uint64 getSize() const
{
return size;
}
@@ -88,6 +88,7 @@ public:
currentBuffer = (currentBuffer + 1) % numBuffers;
}
virtual void *lock(bool bWriteOnly = true);
virtual void *lockRegion(uint64 regionOffset, uint64 regionSize, bool bWriteOnly = true);
virtual void unlock();
protected:
@@ -98,7 +99,7 @@ protected:
};
PGraphics graphics;
uint32 currentBuffer;
uint32 size;
uint64 size;
Gfx::QueueType& owner;
BufferAllocation buffers[Gfx::numFramesBuffered];
uint32 numBuffers;
@@ -168,6 +169,8 @@ public:
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData);
virtual ~VertexBuffer();
virtual void updateRegion(BulkResourceData update) override;
protected:
// Inherited via Vulkan::Buffer
virtual VkAccessFlags getSourceAccessMask();
+110 -65
View File
@@ -2,9 +2,9 @@
#include "VulkanGraphics.h"
#include "VulkanDescriptorSets.h"
#include "slang.h"
#include "slang-com-ptr.h"
#include "stdlib.h"
using namespace slang;
using namespace Seele;
using namespace Seele::Vulkan;
@@ -33,85 +33,130 @@ uint32 Seele::Vulkan::Shader::getShaderHash() const
return hash;
}
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(nullptr);
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, "");
for(auto code : createInfo.shaderCode)
thread_local Slang::ComPtr<slang::IGlobalSession> globalSession;
if(!globalSession)
{
spAddTranslationUnitSourceString(
request,
translationUnitIndex,
entryPointName.c_str(),
code.data()
slang::createGlobalSession(globalSession.writeRef());
}
slang::SessionDesc sessionDesc;
sessionDesc.flags = 0;
sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR;
Array<slang::PreprocessorMacroDesc> macros;
for(auto define : createInfo.defines)
{
macros.add(slang::PreprocessorMacroDesc{
.name = define.key,
.value = define.value
});
}
sessionDesc.preprocessorMacroCount = macros.size();
sessionDesc.preprocessorMacros = macros.data();
slang::TargetDesc vulkan;
vulkan.profile = globalSession->findProfile("glsl_vk");
vulkan.format = SLANG_SPIRV;
sessionDesc.targetCount = 1;
sessionDesc.targets = &vulkan;
StaticArray<const char*, 3> searchPaths = {"shaders/", "shaders/lib/", "shaders/generated/"};
sessionDesc.searchPaths = searchPaths.data();
sessionDesc.searchPathCount = searchPaths.size();
Slang::ComPtr<slang::ISession> session;
globalSession->createSession(sessionDesc, session.writeRef());
Slang::ComPtr<slang::IBlob> diagnostics;
Array<slang::IComponentType*> modules;
Slang::ComPtr<slang::IEntryPoint> entrypoint;
for (auto moduleName : createInfo.additionalModules)
{
modules.add(session->loadModule(moduleName.c_str(), diagnostics.writeRef()));
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
}
slang::IModule* mainModule = session->loadModule(createInfo.mainModule.c_str(), diagnostics.writeRef());
modules.add(mainModule);
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
mainModule->findEntryPointByName(createInfo.entryPoint.c_str(), entrypoint.writeRef());
modules.add(entrypoint);
slang::IComponentType* moduleComposition;
session->createCompositeComponentType(modules.data(), modules.size(), &moduleComposition, diagnostics.writeRef());
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
/*for(auto typeParam : createInfo.typeParameter)
{
Slang::ComPtr<slang::ITypeConformance> typeConformance;
session->createTypeConformanceComponentType(moduleComposition->getLayout()->findTypeByName(typeParam), moduleComposition->getLayout()->findTypeByName("IMaterial"), typeConformance.writeRef(), -1, diagnostics.writeRef());
modules.add(typeConformance);
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
}
Slang::ComPtr<slang::IComponentType> conformingModule;
session->createCompositeComponentType(modules.data(), modules.size(), conformingModule.writeRef(), diagnostics.writeRef());
*/
Slang::ComPtr<slang::IComponentType> linkedProgram;
moduleComposition->link(linkedProgram.writeRef(), diagnostics.writeRef());
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
slang::ProgramLayout* reflection = linkedProgram->getLayout(0, diagnostics.writeRef());
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
Array<slang::SpecializationArg> specialization;
for(auto typeArg : createInfo.typeParameter)
{
specialization.add(slang::SpecializationArg::fromType(reflection->findTypeByName(typeArg)));
}
Slang::ComPtr<slang::IComponentType> specializedComponent;
linkedProgram->specialize(specialization.data(), specialization.size(), specializedComponent.writeRef(), diagnostics.writeRef());
if(diagnostics)
{
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
Slang::ComPtr<slang::IBlob> kernelBlob;
specializedComponent->getEntryPointCode(
0,
0,
kernelBlob.writeRef(),
diagnostics.writeRef()
);
}
for(auto define : createInfo.defines)
if(diagnostics)
{
spAddPreprocessorDefine(request, define.key, define.value);
std::cout << (const char*)diagnostics->getBufferPointer() << std::endl;
}
spAddSearchPath(request, "shaders/lib/");
spAddSearchPath(request, "shaders/generated/");
spSetGlobalGenericArgs(request, (int)createInfo.typeParameter.size(), createInfo.typeParameter.data());
int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type));
if(spCompile(request))
{
char const* diagnostics = spGetDiagnosticOutput(request);
std::cout << "Compile error for shader " << createInfo.name << std::endl;
std::cout << diagnostics << std::endl;
std::cout << "Defines: " << std::endl;
for(auto define : createInfo.defines)
{
std::cout << define.key << ": " << define.value << std::endl;
}
std::cout << "For shader code: " << std::endl;
for(auto code : createInfo.shaderCode)
{
std::cout << code << std::endl;
}
return;
}
size_t dataSize = 0;
const uint32* data = reinterpret_cast<const uint32*>(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 = data;
moduleInfo.codeSize = kernelBlob->getBufferSize();
moduleInfo.pCode = (uint32_t*)kernelBlob->getBufferPointer();
VK_CHECK(vkCreateShaderModule(graphics->getDevice(), &moduleInfo, nullptr, &module));
boost::crc_32_type result;
result.process_bytes(entryPointName.data(), entryPointName.size());
result.process_bytes(data, dataSize);
result.process_bytes(kernelBlob->getBufferPointer(), kernelBlob->getBufferSize());
hash = result.checksum();
}
+2 -3
View File
@@ -53,7 +53,6 @@ void MaterialAsset::load()
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
std::string profile = j["profile"].get<std::string>();
codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl;
codeStream << "import Material;" << std::endl;
codeStream << "import BRDF;" << std::endl;
codeStream << "import MaterialParameter;" << std::endl << std::endl;
@@ -94,7 +93,7 @@ void MaterialAsset::load()
uniformBufferOffset += 12;
if(defaultValue != param.value().end())
{
p->data = parseVector(defaultValue.value().get<std::string>().c_str());
p->data = Math::parseVector(defaultValue.value().get<std::string>().c_str());
}
parameters.add(p);
}
@@ -184,6 +183,6 @@ const Gfx::ShaderCollection* MaterialAsset::getShaders(Gfx::RenderPassType rende
Gfx::ShaderCollection& MaterialAsset::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
{
std::scoped_lock lock(shaderMapLock);
std::scoped_lock l(shaderMapLock);
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
}
+2
View File
@@ -40,6 +40,8 @@ private:
uint8* uniformData;
int32 uniformBinding;
std::string materialName;
// With draw-indirect, we batch vertex data into big vertex buffers
// Gfx::PVertexDataManager vertexData;
};
DEFINE_REF(MaterialAsset)
} // namespace Seele
+1 -1
View File
@@ -40,7 +40,7 @@ VectorParameter::~VectorParameter()
void VectorParameter::updateDescriptorSet(Gfx::PDescriptorSet, uint8* dst)
{
std::memcpy(dst + byteOffset, &data, sizeof(Vector));
std::memcpy(dst + byteOffset, &data, sizeof(Math::Vector));
}
TextureParameter::TextureParameter(std::string name, uint32 byteOffset, uint32 binding)
+1 -1
View File
@@ -36,7 +36,7 @@ struct FloatParameter : public ShaderParameter
DEFINE_REF(FloatParameter)
struct VectorParameter : public ShaderParameter
{
Vector data;
Math::Vector data;
VectorParameter(std::string name, uint32 byteOffset, uint32 binding);
virtual ~VectorParameter();
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override;
+3 -3
View File
@@ -2,7 +2,7 @@ target_sources(Engine
PUBLIC
Math.h
Matrix.h
Vector.h
Vector.cpp
Transform.h
Transform.cpp)
Transform.cpp
Vector.h
Vector.cpp)
+3
View File
@@ -5,6 +5,8 @@
namespace Seele
{
namespace Math
{
struct Rect
{
Rect()
@@ -58,4 +60,5 @@ inline constexpr T align(const T ptr, int64_t alignment)
{
return (T)(((uint64_t)ptr + alignment - 1) & ~(alignment - 1));
}
} // namespace Math
} // namespace Seele
+3
View File
@@ -5,7 +5,10 @@
#include <glm/mat4x4.hpp>
namespace Seele
{
namespace Math
{
typedef glm::mat2 Matrix2;
typedef glm::mat3 Matrix3;
typedef glm::mat4 Matrix4;
} // namespace Math
} // namespace Seele
+8 -1
View File
@@ -2,6 +2,7 @@
#include <glm/gtx/quaternion.hpp>
using namespace Seele;
using namespace Seele::Math;
Transform::Transform()
: position(Vector4(0, 0, 0, 0)), rotation(Quaternion(1, 0, 0, 0)), scale(Vector4(1, 1, 1, 0))
@@ -44,7 +45,7 @@ Vector Transform::inverseTransformPosition(const Vector &v) const
{
return (unrotateVector(rotation, v - Vector(position))) * getSafeScaleReciprocal(scale);
}
Matrix4 Transform::toMatrix()
Matrix4 Transform::toMatrix() const
{
Matrix4 mat;
@@ -197,20 +198,26 @@ void Transform::add(Transform *outTransform, const Transform *a, const Transform
Transform &Transform::operator=(const Transform &other)
{
if(&other != this)
{
position = other.position;
rotation = other.rotation;
scale = other.scale;
}
return *this;
}
Transform &Transform::operator=(Transform &&other)
{
if(&other != this)
{
position = other.position;
rotation = other.rotation;
scale = other.scale;
other.position = Vector4(0, 0, 0, 0);
other.rotation = Quaternion(1, 0, 0, 0);
other.scale = Vector4(0, 0, 0, 0);
}
return *this;
}
+6 -3
View File
@@ -1,9 +1,11 @@
#pragma once
#include "Vector.h"
#include "Matrix.h"
#include "Math/Vector.h"
#include "Math/Matrix.h"
namespace Seele
{
namespace Math
{
class Transform
{
public:
@@ -16,7 +18,7 @@ public:
Transform(Quaternion rotation, Vector scale);
~Transform();
Vector inverseTransformPosition(const Vector &v) const;
Matrix4 toMatrix();
Matrix4 toMatrix() const;
static Vector getSafeScaleReciprocal(const Vector4 &inScale, float tolerance = 0.000000001f);
Vector transformPosition(const Vector &v) const;
@@ -41,4 +43,5 @@ private:
Quaternion rotation;
Vector4 scale;
};
} // namespace Math
} // namespace Seele
+5 -5
View File
@@ -1,25 +1,25 @@
#include "Vector.h"
#include <regex>
using namespace Seele;
using namespace Seele::Math;
std::ostream& Seele::operator<<(std::ostream& stream, const Vector2& vector)
std::ostream& operator<<(std::ostream& stream, const Vector2& vector)
{
stream << "(" << vector.x << ", " << vector.y << ")";
return stream;
}
std::ostream& Seele::operator<<(std::ostream& stream, const Vector& vector)
std::ostream& operator<<(std::ostream& stream, const Vector& vector)
{
stream << "(" << vector.x << ", " << vector.y << ", " << vector.z << ")";
return stream;
}
std::ostream& Seele::operator<<(std::ostream& stream, const Vector4& vector)
std::ostream& operator<<(std::ostream& stream, const Vector4& vector)
{
stream << "(" << vector.x << ", " << vector.y << ", " << vector.z << ", " << vector.w << ")";
return stream;
}
Vector Seele::parseVector(const char* str)
Vector Seele::Math::parseVector(const char* str)
{
//regex pattern consisting of 'float3(xComp, yComp, zComp)', more also matches for invalid floats, but that will throw later
std::regex pattern("float3\\(\\s*([0-9.]+f?)\\s*,\\s*([0-9.]+f?)\\s*,\\s*([0-9.]+f?)\\s*\\)");
+6
View File
@@ -1,11 +1,16 @@
#pragma once
#pragma warning(push)
#pragma warning(disable: 4201)
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <glm/gtc/quaternion.hpp>
#pragma warning(pop)
namespace Seele
{
namespace Math
{
typedef glm::vec2 Vector2;
typedef glm::vec3 Vector;
typedef glm::vec4 Vector4;
@@ -95,4 +100,5 @@ static inline Vector toRotator(const Quaternion &other)
}
return rotatorFromQuat;
}
} // namespace Math
} // namespace Seele
+11 -120
View File
@@ -1,61 +1,19 @@
#include "Actor.h"
#include "Scene/Components/Component.h"
#include "Scene/Scene.h"
using namespace Seele;
Actor::Actor()
Actor::Actor(PScene scene)
: Entity(scene)
{
scene->attachComponent<Component::Transform>(identifier);
}
Actor::~Actor()
{
}
void Actor::launchStart()
{
rootComponent->launchStart();
for(auto child : children)
{
child->launchStart();
}
start();
}
void Actor::launchTick(float deltaTime) const
{
rootComponent->launchTick(deltaTime);
for(auto child : children)
{
child->launchTick(deltaTime);
}
tick(deltaTime);
}
void Actor::launchUpdate()
{
rootComponent->launchUpdate();
for(auto child : children)
{
child->launchUpdate();
}
update();
}
void Actor::notifySceneAttach(PScene scene)
{
owningScene = scene;
rootComponent->notifySceneAttach(scene);
for(auto child : children)
{
child->notifySceneAttach(scene);
}
}
PScene Actor::getScene()
{
return owningScene;
}
void Actor::setParent(PActor newParent)
{
if(parent != nullptr)
@@ -68,86 +26,19 @@ void Actor::addChild(PActor child)
{
children.add(child);
child->setParent(this);
child->notifySceneAttach(owningScene);
}
void Actor::removeChild(PActor child)
{
children.remove(children.find(child), false);
child->setParent(nullptr);
child->notifySceneAttach(nullptr);
}
//void Actor::setAbsoluteLocation(Vector location)
//{
// rootComponent->setWorldLocation(location);
//}
//
//void Actor::setAbsoluteRotation(Quaternion rotation)
//{
// rootComponent->setAbsoluteRotation(rotation);
//}
//void Actor::setAbsoluteRotation(Vector rotation)
//{
// rootComponent->setAbsoluteRotation(rotation);
//}
//void Actor::setWorldScale(Vector scale)
//{
// rootComponent->setWorldScale(scale);
//}
void Actor::setRelativeLocation(Vector location)
const Component::Transform& Actor::getTransform() const
{
rootComponent->setRelativeLocation(location);
}
void Actor::setRelativeRotation(Quaternion rotation)
{
rootComponent->setRelativeRotation(rotation);
}
void Actor::setRelativeRotation(Vector rotation)
{
rootComponent->setRelativeRotation(rotation);
}
void Actor::setRelativeScale(Vector scale)
{
rootComponent->setRelativeScale(scale);
}
//void Actor::addAbsoluteTranslation(Vector translation)
//{
// rootComponent->addAbsoluteTranslation(translation);
//}
//void Actor::addAbsoluteRotation(Quaternion rotation)
//{
// rootComponent->addAbsoluteRotation(rotation);
//}
//void Actor::addAbsoluteRotation(Vector rotation)
//{
// rootComponent->addAbsoluteRotation(rotation);
//}
void Actor::addRelativeLocation(Vector translation)
{
rootComponent->addRelativeLocation(translation);
}
void Actor::addRelativeRotation(Quaternion rotation)
{
rootComponent->addRelativeRotation(rotation);
}
void Actor::addRelativeRotation(Vector rotation)
{
rootComponent->addRelativeRotation(rotation);
}
PComponent Actor::getRootComponent()
{
return rootComponent;
}
void Actor::setRootComponent(PComponent newRoot)
{
if(rootComponent != nullptr)
{
rootComponent->owner = nullptr;
}
rootComponent = newRoot;
rootComponent->owner = this;
return scene->accessComponent<Component::Transform>(identifier);
}
Transform Actor::getTransform() const
{
return rootComponent->getTransform();
}
//Component::Transform& Actor::getTransform()
//{
// return scene->accessComponent<Component::Transform>(identifier);
//}
+8 -37
View File
@@ -1,60 +1,31 @@
#pragma once
#include "MinimalEngine.h"
#include "Math/Transform.h"
#include "Entity.h"
#include "Scene/Component/Transform.h"
namespace Seele
{
DECLARE_REF(Actor)
DECLARE_REF(Component)
DECLARE_REF(Scene)
class Actor
// Actors are entities that are part of the scene hierarchy
// In order for that hierarchy to make sense it requires at least a transform component
class Actor : public Entity
{
public:
Actor();
Actor(PScene scene);
virtual ~Actor();
virtual void launchStart();
virtual void start() {}
void launchTick(float deltaTime) const;
virtual void tick(float) const { }//co_return; }
void launchUpdate();
virtual void update() { }//co_return; }
void notifySceneAttach(PScene scene);
PScene getScene();
PActor getParent();
void addChild(PActor child);
void removeChild(PActor child);
Array<PActor> getChildren();
//void setAbsoluteLocation(Vector location);
//void setAbsoluteRotation(Quaternion rotation);
//void setAbsoluteRotation(Vector rotation);
//void setWorldScale(Vector scale);
void setRelativeLocation(Vector location);
void setRelativeRotation(Quaternion rotation);
void setRelativeRotation(Vector rotation);
void setRelativeScale(Vector scale);
//void addAbsoluteTranslation(Vector translation);
//void addAbsoluteRotation(Quaternion rotation);
//void addAbsoluteRotation(Vector rotation);
void addRelativeLocation(Vector translation);
void addRelativeRotation(Quaternion rotation);
void addRelativeRotation(Vector rotation);
PComponent getRootComponent();
void setRootComponent(PComponent newRoot);
// Returns a read-only copy of the actors transform
Transform getTransform() const;
const Component::Transform& getTransform() const;
protected:
//Component::Transform& getTransform();
void setParent(PActor parent);
PScene owningScene;
PActor parent;
Array<PActor> children;
PComponent rootComponent;
};
DEFINE_REF(Actor)
} // namespace Seele
+3 -1
View File
@@ -3,4 +3,6 @@ target_sources(Engine
Actor.cpp
Actor.h
CameraActor.cpp
CameraActor.h)
CameraActor.h
Entity.cpp
Entity.h)
+15 -11
View File
@@ -1,21 +1,25 @@
#include "CameraActor.h"
#include "Scene/Components/Component.h"
#include "Scene/Components/CameraComponent.h"
#include "Scene/Scene.h"
using namespace Seele;
CameraActor::CameraActor()
CameraActor::CameraActor(PScene scene)
: Actor(scene)
{
sceneComponent = new Component();
setRootComponent(sceneComponent);
cameraComponent = new CameraComponent();
cameraComponent->fieldOfView = 70.0f;
cameraComponent->setParent(sceneComponent);
cameraComponent->setOwner(this);
sceneComponent->addChildComponent(cameraComponent);
scene->attachComponent<Component::Camera>(identifier);
scene->accessComponent<Component::Transform>(identifier).setRelativeLocation(Math::Vector(10, 5, 14));
}
CameraActor::~CameraActor()
{
}
Component::Camera& CameraActor::getCameraComponent()
{
return scene->accessComponent<Component::Camera>(identifier);
}
const Component::Camera& CameraActor::getCameraComponent() const
{
return scene->accessComponent<Component::Camera>(identifier);
}
+4 -8
View File
@@ -1,21 +1,17 @@
#pragma once
#include "Actor.h"
#include "Scene/Component/Camera.h"
namespace Seele
{
DECLARE_REF(CameraComponent)
class CameraActor : public Actor
{
public:
CameraActor();
CameraActor(PScene scene);
virtual ~CameraActor();
PCameraComponent getCameraComponent() const
{
return cameraComponent;
}
Component::Camera& getCameraComponent();
const Component::Camera& getCameraComponent() const;
private:
PCameraComponent cameraComponent;
PComponent sceneComponent; // This will be the root, camera will be the child
};
DEFINE_REF(CameraActor)
} // namespace Seele
+15
View File
@@ -0,0 +1,15 @@
#include "Entity.h"
using namespace Seele;
Entity::Entity(PScene scene)
: identifier(scene->createEntity())
, scene(scene)
{
}
Entity::~Entity()
{
}
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <entt/entt.hpp>
#include "MinimalEngine.h"
#include "Scene/Scene.h"
namespace Seele
{
// An entity describes a part of a scene
// It is just a wrapper the ID of a registry
class Entity
{
public:
Entity(PScene scene);
virtual ~Entity();
template<typename Component, typename... Args>
void attachComponent(Args... args)
{
scene->attachComponent<Component>(identifier, args...);
}
protected:
PScene scene;
entt::entity identifier;
};
DEFINE_REF(Entity)
} // namespace Seele
+2 -1
View File
@@ -5,4 +5,5 @@ target_sources(Engine
Scene.h)
add_subdirectory(Actor/)
add_subdirectory(Components/)
add_subdirectory(Component/)
add_subdirectory(System/)
@@ -0,0 +1,8 @@
target_sources(Engine
PUBLIC
Component.h
Camera.h
Camera.cpp
StaticMesh.h
Transform.h
Transform.cpp)
@@ -1,13 +1,15 @@
#include "CameraComponent.h"
#include "Camera.h"
#include "Scene/Actor/Actor.h"
#include <algorithm>
#include <iostream>
using namespace Seele;
using namespace Seele::Component;
using namespace Seele::Math;
CameraComponent::CameraComponent()
Camera::Camera()
: aspectRatio(0)
, fieldOfView(0)
, fieldOfView(glm::radians(70.f))
, bNeedsViewBuild(true)
, bNeedsProjectionBuild(true)
, viewMatrix(Matrix4())
@@ -15,14 +17,13 @@ CameraComponent::CameraComponent()
{
yaw = 0;
pitch = 0;
setRelativeLocation(Vector(0, 10, -50));
}
CameraComponent::~CameraComponent()
Camera::~Camera()
{
}
void CameraComponent::mouseMove(float deltaYaw, float deltaPitch)
void Camera::mouseMove(float deltaYaw, float deltaPitch)
{
yaw -= deltaYaw / 500.f;
pitch += deltaPitch / 500.f;
@@ -31,29 +32,29 @@ void CameraComponent::mouseMove(float deltaYaw, float deltaPitch)
Vector xyz = glm::cross(cameraDirection, Vector(0, 0, 1));
Quaternion result = Quaternion(glm::dot(cameraDirection, Vector(0, 0, 1)) + 1, xyz.x, xyz.y, xyz.z);
//std::cout << "Result " << Vector(0, 0, 1) * glm::normalize(result) << " cameraDirection: " << cameraDirection << std::endl;
setRelativeRotation(result);
getTransform().setRelativeRotation(result);
bNeedsViewBuild = true;
}
void CameraComponent::mouseScroll(float x)
void Camera::mouseScroll(float x)
{
addRelativeLocation(getTransform().getForward()*x);
getTransform().addRelativeLocation(getTransform().getForward()*x);
bNeedsViewBuild = true;
}
void CameraComponent::moveX(float amount)
void Camera::moveX(float amount)
{
addRelativeLocation(getTransform().getForward()*amount);
getTransform().addRelativeLocation(getTransform().getForward()*amount);
bNeedsViewBuild = true;
}
void CameraComponent::moveY(float amount)
void Camera::moveY(float amount)
{
addRelativeLocation(getTransform().getRight()*amount);
getTransform().addRelativeLocation(getTransform().getRight()*amount);
bNeedsViewBuild = true;
}
void CameraComponent::setViewport(Gfx::PViewport newViewport)
void Camera::setViewport(Gfx::PViewport newViewport)
{
viewport = newViewport;
aspectRatio = viewport->getSizeX() / (float)viewport->getSizeY();
@@ -61,17 +62,17 @@ void CameraComponent::setViewport(Gfx::PViewport newViewport)
bNeedsProjectionBuild = true;
}
void CameraComponent::buildViewMatrix()
void Camera::buildViewMatrix()
{
Vector eyePos = getAbsoluteTransform().getPosition();
Vector lookAt = eyePos + glm::normalize(Vector(cos(yaw) * cos(pitch), sin(pitch), sin(yaw) * cos(pitch)));
Vector eyePos = getTransform().getPosition();//getAbsoluteTransform().getPosition();
Vector lookAt = Vector(0, 0, 0);//eyePos + glm::normalize(Vector(cos(yaw) * cos(pitch), sin(pitch), sin(yaw) * cos(pitch)));
//std::cout << "Eye: " << eyePos << " lookAt: " << lookAt << std::endl;
viewMatrix = glm::lookAt(eyePos, lookAt, Vector(0, 1, 0));
bNeedsViewBuild = false;
}
void CameraComponent::buildProjectionMatrix()
void Camera::buildProjectionMatrix()
{
projectionMatrix = glm::perspective(fieldOfView, aspectRatio, 1.0f, 1000.f);
static Matrix4 correctionMatrix =
@@ -2,32 +2,30 @@
#include "Component.h"
#include "Math/Matrix.h"
#include "Graphics/GraphicsResources.h"
#include "Transform.h"
namespace Seele
{
class CameraComponent : public Component
namespace Component
{
public:
CameraComponent();
virtual ~CameraComponent();
struct Camera
{
REQUIRE_COMPONENT(Transform)
Matrix4 getViewMatrix()
Camera();
~Camera();
Math::Matrix4 getViewMatrix()
{
if (bNeedsViewBuild)
{
buildViewMatrix();
}
assert (!bNeedsViewBuild);
return viewMatrix;
}
Matrix4 getProjectionMatrix()
Math::Matrix4 getProjectionMatrix()
{
if (bNeedsProjectionBuild)
{
buildProjectionMatrix();
}
assert (!bNeedsProjectionBuild);
return projectionMatrix;
}
Vector getCameraPosition()
Math::Vector getCameraPosition()
{
return getTransform().getPosition();
}
@@ -38,19 +36,19 @@ public:
void moveY(float amount);
float aspectRatio;
float fieldOfView;
void buildViewMatrix();
void buildProjectionMatrix();
private:
bool bNeedsViewBuild;
bool bNeedsProjectionBuild;
void buildViewMatrix();
void buildProjectionMatrix();
Gfx::PViewport viewport;
//Transforms relative to actor
Matrix4 viewMatrix;
Matrix4 projectionMatrix;
Math::Matrix4 viewMatrix;
Math::Matrix4 projectionMatrix;
float yaw;
float pitch;
};
DEFINE_REF(CameraComponent)
} // namespace Component
} // namespace Seele
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include <concepts>
#include <tuple>
namespace Seele
{
template<typename... Types>
struct Dependencies;
template<>
struct Dependencies<>
{};
template<typename This, typename... Rest>
struct Dependencies<This, Rest...> : public Dependencies<Rest...>
{
template<typename... Right>
Dependencies<This, Rest..., Right...> operator|(const Dependencies<Right...>& other)
{
return Dependencies<This, Rest..., Right...>();
}
};
namespace Component
{
#pragma warning(disable: 4505)
template<typename Comp>
static int accessComponent(Comp& comp);
}
template<typename T, typename... Deps>
concept is_component = std::same_as<decltype(T::dependencies), Dependencies<Deps...>>;
#define REQUIRE_COMPONENT(x) \
private: \
x& get##x() { return *tl_##x; } \
const x& get##x() const { return *tl_##x; }; \
public: \
static Dependencies<x> dependencies;
#define DECLARE_COMPONENT(x) \
thread_local extern x* tl_##x; \
template<> \
int accessComponent<x>(x& val) { tl_##x = &val; return 0; }
#define DEFINE_COMPONENT(x) \
thread_local x* Seele::Component::tl_##x;
} // namespace Seele
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include "Graphics/GraphicsResources.h"
namespace Seele
{
namespace Component
{
struct StaticMesh
{
PVertexShaderInput vertexBuffer;
Gfx::PIndexBuffer indexBuffer;
PMaterialAsset material;
};
} // namespace Component
} // namespace Seele
+34
View File
@@ -0,0 +1,34 @@
#include "Transform.h"
using namespace Seele::Component;
DEFINE_COMPONENT(Transform)
void Transform::setRelativeLocation(Math::Vector location)
{
transform = Math::Transform(location, transform.getRotation(), transform.getScale());
}
void Transform::setRelativeRotation(Math::Vector rotation)
{
transform = Math::Transform(transform.getPosition(), Math::Quaternion(rotation), transform.getScale());
}
void Transform::setRelativeRotation(Math::Quaternion rotation)
{
transform = Math::Transform(transform.getPosition(), rotation, transform.getScale());
}
void Transform::setRelativeScale(Math::Vector scale)
{
transform = Math::Transform(transform.getPosition(), transform.getRotation(), scale);
}
void Transform::addRelativeLocation(Math::Vector translation)
{
transform = Math::Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
}
void Transform::addRelativeRotation(Math::Vector rotation)
{
transform = Math::Transform(transform.getPosition(), transform.getRotation() * Math::Quaternion(rotation), transform.getScale());
}
void Transform::addRelativeRotation(Math::Quaternion rotation)
{
transform = Math::Transform(transform.getPosition(), transform.getRotation() * rotation, transform.getScale());
}
+52
View File
@@ -0,0 +1,52 @@
#pragma once
#include "Math/Transform.h"
#include "Component.h"
namespace Seele
{
namespace Component
{
struct Transform
{
Transform() {}
Transform(const Transform& other) : transform(other.transform) {}
Transform(Transform&& other) : transform(other.transform) {}
Transform& operator=(const Transform& other) {
if (&other != this)
{
transform = other.transform;
}
return *this;
}
Transform& operator=(Transform&& other) {
if(&other != this)
{
transform = std::move(other.transform);
}
return *this;
}
Math::Vector getPosition() const { return transform.getPosition(); }
Math::Quaternion getRotation() const { return transform.getRotation(); }
Math::Vector getScale() const { return transform.getScale(); }
Math::Vector getForward() const { return transform.getForward(); }
Math::Vector getUp() const { return transform.getUp(); }
Math::Vector getRight() const { return transform.getRight(); }
Math::Matrix4 toMatrix() const { return transform.toMatrix(); }
void setRelativeLocation(Math::Vector location);
void setRelativeRotation(Math::Quaternion rotation);
void setRelativeRotation(Math::Vector rotation);
void setRelativeScale(Math::Vector scale);
void addRelativeLocation(Math::Vector translation);
void addRelativeRotation(Math::Quaternion rotation);
void addRelativeRotation(Math::Vector rotation);
private:
Math::Transform transform;
};
DECLARE_COMPONENT(Transform)
} // namespace Component
} // namespace Seele
@@ -1,12 +0,0 @@
target_sources(Engine
PUBLIC
CameraComponent.h
CameraComponent.cpp
Component.h
Component.cpp
MyComponent.h
MyComponent.cpp
MyOtherComponent.h
MyOtherComponent.cpp
PrimitiveComponent.cpp
PrimitiveComponent.h)
-201
View File
@@ -1,201 +0,0 @@
#include "Component.h"
#include "Scene/Actor/Actor.h"
#include "Scene/Scene.h"
using namespace Seele;
Component::Component()
{
}
Component::~Component()
{
}
void Component::launchStart()
{
for(auto child : children)
{
child->launchStart();
}
start();
}
void Component::launchTick(float deltaTime) const
{
for(auto child : children)
{
child->launchTick(deltaTime);
}
tick(deltaTime);
}
void Component::launchUpdate()
{
for(auto child : children)
{
child->launchUpdate();
}
update();
}
PComponent Component::getParent()
{
return parent;
}
PActor Component::getOwner()
{
if (owner != nullptr)
{
return owner;
}
if (parent != nullptr)
{
return parent->getOwner();
}
return nullptr;
}
const Array<PComponent>& Component::getChildComponents()
{
return children;
}
void Component::setParent(PComponent newParent)
{
parent = newParent;
}
void Component::setOwner(PActor newOwner)
{
owner = newOwner;
}
void Component::addChildComponent(PComponent component)
{
children.add(component);
}
void Component::notifySceneAttach(PScene scene)
{
owningScene = scene;
for (auto child : children)
{
child->notifySceneAttach(scene);
}
}
//void Component::setAbsoluteLocation(Vector location)
//{
// Vector newRelLocation = location;
// if (parent != nullptr)
// {
// Transform parentToWorld = getParent()->getTransform();
// newRelLocation = parentToWorld.inverseTransformPosition(location);
// }
// setRelativeLocation(newRelLocation);
//}
//void Component::setAbsoluteRotation(Vector rotation)
//{
// Vector newRelRotator = rotation;
// if (parent == nullptr)
// {
// setRelativeRotation(rotation);
// }
// else
// {
// setAbsoluteRotation(toQuaternion(newRelRotator));
// }
//}
//void Component::setAbsoluteRotation(Quaternion rotation)
//{
// Quaternion newRelRotation = getRelativeWorldRotation(rotation);
// setRelativeRotation(newRelRotation);
//}
//void Component::setWorldScale(Vector scale)
//{
// Vector newRelScale = scale;
// if (parent != nullptr)
// {
// Transform parentToWorld = parent->getTransform();
// newRelScale = scale * parentToWorld.getSafeScaleReciprocal(Vector4(parentToWorld.getScale(), 0));
// }
// setRelativeScale(newRelScale);
//}
void Component::setRelativeLocation(Vector location)
{
transform = Transform(location, transform.getRotation(), transform.getScale());
propagateTransformUpdate();
}
void Component::setRelativeRotation(Vector rotation)
{
transform = Transform(transform.getPosition(), Quaternion(rotation), transform.getScale());
propagateTransformUpdate();
}
void Component::setRelativeRotation(Quaternion rotation)
{
transform = Transform(transform.getPosition(), rotation, transform.getScale());
propagateTransformUpdate();
}
void Component::setRelativeScale(Vector scale)
{
transform = Transform(transform.getPosition(), transform.getRotation(), scale);
propagateTransformUpdate();
}
//void Component::addAbsoluteTranslation(Vector translation)
//{
// const Vector newWorldLocation = translation + getTransform().getPosition();
// setAbsoluteLocation(newWorldLocation);
//}
//void Component::addAbsoluteRotation(Vector rotation)
//{
// const Quaternion newWorldRotation = toQuaternion(rotation) * getTransform().getRotation();
// setAbsoluteRotation(newWorldRotation);
//}
//void Component::addAbsoluteRotation(Quaternion rotation)
//{
// const Quaternion newWorldRotation = rotation * getTransform().getRotation();
// setAbsoluteRotation(newWorldRotation);
//}
void Component::addRelativeLocation(Vector translation)
{
transform = Transform(transform.getPosition() + translation, transform.getRotation(), transform.getScale());
propagateTransformUpdate();
}
void Component::addRelativeRotation(Vector rotation)
{
transform = Transform(transform.getPosition(), transform.getRotation() * Quaternion(rotation), transform.getScale());
propagateTransformUpdate();
}
void Component::addRelativeRotation(Quaternion rotation)
{
transform = Transform(transform.getPosition(), transform.getRotation() * rotation, transform.getScale());
propagateTransformUpdate();
}
Transform Component::getTransform() const
{
return transform;
}
Transform Component::getAbsoluteTransform() const
{
return absoluteTransform;
}
void Component::propagateTransformUpdate()
{
if(parent != nullptr)
{
absoluteTransform = transform + parent->getAbsoluteTransform();
}
else
{
absoluteTransform = transform;
}
for(auto child : children)
{
child->propagateTransformUpdate();
}
}
-77
View File
@@ -1,77 +0,0 @@
#pragma once
#include "MinimalEngine.h"
#include "Math/Transform.h"
#include "Scene/Util.h"
namespace Seele
{
DECLARE_REF(Actor)
DECLARE_REF(Scene)
DECLARE_REF(Component)
class Component
{
public:
Component();
virtual ~Component();
void launchStart();
virtual void start() {};
void launchTick(float deltaTime) const;
virtual void tick(float) const { }//co_return; }
void launchUpdate();
virtual void update() { }//co_return; }
PComponent getParent();
PActor getOwner();
const Array<PComponent>& getChildComponents();
void setParent(PComponent parent);
void setOwner(PActor owner);
void addChildComponent(PComponent component);
virtual void notifySceneAttach(PScene scene);
void setRelativeLocation(Vector location);
void setRelativeRotation(Vector rotation);
void setRelativeRotation(Quaternion rotation);
void setRelativeScale(Vector scale);
void addRelativeLocation(Vector translation);
void addRelativeRotation(Vector rotation);
void addRelativeRotation(Quaternion rotation);
Transform getTransform() const;
Transform getAbsoluteTransform() const;
template<typename ComponentType>
RefPtr<ComponentType> getComponent()
{
return tryFindComponent<ComponentType>();
}
private:
template<typename ComponentType>
RefPtr<ComponentType> tryFindComponent()
{
for(auto child : children)
{
RefPtr<ComponentType> result = child.cast<ComponentType>();
if(result != nullptr)
{
return result;
}
result = parent->tryFindComponent<ComponentType>();
if(result != nullptr)
{
return result;
}
}
return nullptr;
}
void propagateTransformUpdate();
Transform transform;
Transform absoluteTransform;
PScene owningScene;
PActor owner;
PComponent parent;
Array<PComponent> children;
friend class Actor;
};
DEFINE_REF(Component)
} // namespace Seele
@@ -1,30 +0,0 @@
#include "MyComponent.h"
using namespace Seele;
MyComponent::MyComponent()
{
}
void MyComponent::start()
{
otherComp = getComponent<MyOtherComponent>();
otherComp.update();
}
void MyComponent::tick(float) const
{
//std::cout << "MyComponent::tick" << std::endl;
++writable;
//std::cout << "MyComponent::tick finished" << std::endl;
otherComp->data = *writable;
//co_return;
}
void MyComponent::update()
{
//std::cout << "MyComponent::update" << std::endl;
writable.update();
//std::cout << "MyComponent::update finished" << std::endl;
//co_return;
}
-20
View File
@@ -1,20 +0,0 @@
#pragma once
#include "Component.h"
#include "MyOtherComponent.h"
namespace Seele
{
class MyComponent : public Component
{
public:
MyComponent();
virtual void start();
virtual void tick(float deltatime) const;
virtual void update();
private:
Writable<PMyOtherComponent> otherComp;
Writable<uint32> writable = 0;
uint32 notWritable = 10;
};
DECLARE_REF(MyComponent);
} // namespace Seele
@@ -1,15 +0,0 @@
#include "MyOtherComponent.h"
using namespace Seele;
void MyOtherComponent::tick(float) const
{
//std::cout << *data << std::endl;
//co_return;
}
void MyOtherComponent::update()
{
data.update();
//co_return;
}
@@ -1,15 +0,0 @@
#pragma once
#include "Component.h"
namespace Seele
{
class MyOtherComponent : public Component
{
public:
virtual void tick(float deltaTime) const;
virtual void update();
Writable<uint32> data = Writable<uint32>(0);
private:
};
DEFINE_REF(MyOtherComponent);
} // namespace Seele
@@ -1,54 +0,0 @@
#include "PrimitiveComponent.h"
#include "Scene/Scene.h"
#include "Material/MaterialAsset.h"
#include "Asset/MeshAsset.h"
#include "Graphics/VertexShaderInput.h"
#include <iostream>
using namespace Seele;
PrimitiveComponent::PrimitiveComponent()
{
}
PrimitiveComponent::PrimitiveComponent(PMeshAsset asset)
{
auto assetMeshes = asset->getMeshes();
staticMeshes.resize(assetMeshes.size());
for (uint32 i = 0; i < assetMeshes.size(); i++)
{
auto& batch = staticMeshes[i];
batch.material = asset->referencedMaterials[i];
batch.isBackfaceCullingDisabled = false;
batch.isCastingShadow = true;
batch.primitiveComponent = this;
batch.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
batch.useReverseCulling = false;
batch.useWireframe = false;
batch.vertexInput = assetMeshes[i]->vertexInput;
MeshBatchElement batchElement;
batchElement.baseVertexIndex = 0;
batchElement.firstIndex = 0;
batchElement.indexBuffer = assetMeshes[i]->indexBuffer;
batchElement.indirectArgsBuffer = nullptr;
batchElement.instanceRuns = nullptr;
batchElement.isInstanced = false;
batchElement.numInstances = 1;
batchElement.numPrimitives = assetMeshes[i]->indexBuffer->getNumIndices() / 3; //TODO: hardcoded
batch.elements.push_back(batchElement);
}
}
PrimitiveComponent::~PrimitiveComponent()
{
}
void PrimitiveComponent::notifySceneAttach(PScene scene)
{
scene->addPrimitiveComponent(this);
}
Matrix4 PrimitiveComponent::getRenderMatrix()
{
return getAbsoluteTransform().toMatrix();
}
@@ -1,36 +0,0 @@
#pragma once
#include "Component.h"
#include "Graphics/GraphicsResources.h"
#include "Graphics/Mesh.h"
#include "Material/MaterialAsset.h"
#include "Graphics/MeshBatch.h"
namespace Seele
{
DECLARE_REF(MeshAsset)
class PrimitiveComponent : public Component
{
public:
PrimitiveComponent();
PrimitiveComponent(PMeshAsset asset);
~PrimitiveComponent();
virtual void notifySceneAttach(PScene scene) override;
Matrix4 getRenderMatrix();
std::vector<StaticMeshBatch>& getStaticMeshes()
{
return staticMeshes;
}
private:
std::vector<PMaterialAsset> materials;
Gfx::PUniformBuffer uniformBuffer;
std::vector<StaticMeshBatch> staticMeshes;
friend class Scene;
};
DEFINE_REF(PrimitiveComponent)
struct PrimitiveUniformBuffer
{
Matrix4 localToWorld;
Matrix4 worldToLocal;
Vector4 actorWorldPosition;
};
} // namespace Seele
+64 -50
View File
@@ -1,7 +1,8 @@
#include "Scene.h"
#include "Components/PrimitiveComponent.h"
#include "Material/MaterialAsset.h"
#include "Graphics/Graphics.h"
#include "Component/StaticMesh.h"
#include "Component/Transform.h"
using namespace Seele;
@@ -13,19 +14,6 @@ inline float frand()
Scene::Scene(Gfx::PGraphics graphics)
: graphics(graphics)
{
lightEnv.directionalLights[0].color = Vector4(1, 1, 1, 1);
lightEnv.directionalLights[0].direction = Vector4(1, 1, 0, 1);
lightEnv.directionalLights[0].intensity = Vector4(1, 1, 1, 1);
lightEnv.numDirectionalLights = 1;
srand((unsigned int)time(NULL));
for(uint32 i = 0; i < 16; ++i)
{
lightEnv.pointLights[i].colorRange = Vector4(frand(), frand(), frand(), frand() * 300);
lightEnv.pointLights[i].positionWS = Vector4(frand() * 100-50, frand(), frand() * 100-50, 1);
}
lightEnv.numPointLights = 16;
lightEnv.pointLights[0].colorRange = Vector4(1, 0, 1, 1000);
lightEnv.pointLights[0].positionWS = Vector4(0, 10, 0, 1);
}
Scene::~Scene()
@@ -34,23 +22,20 @@ Scene::~Scene()
void Scene::start()
{
for(auto actor : rootActors)
{
actor->launchStart();
}
//for(auto actor : rootActors)
//{
// actor->launchStart();
//}
}
static int64 lastUpdate;
static uint64 numUpdates;
void Scene::beginUpdate(double deltaTime)
void Scene::beginUpdate(double)
{
//std::cout << "Scene::beginUpdate" << std::endl;
auto startTime = std::chrono::high_resolution_clock::now();
for(auto actor : rootActors)
{
actor->launchTick(static_cast<float>(deltaTime));
}
// TODO
auto endTime = std::chrono::high_resolution_clock::now();
int64 delta = std::chrono::duration_cast<std::chrono::microseconds>(endTime - startTime).count();
lastUpdate += delta;
@@ -66,38 +51,67 @@ void Scene::beginUpdate(double deltaTime)
void Scene::commitUpdate()
{
//std::cout << "Scene::commitUpdate" << std::endl;
for(auto actor : rootActors)
{
actor->launchUpdate();
}
//for(auto actor : rootActors)
//{
// actor->launchUpdate();
//}
//std::cout << "Scene::commitUpdate finished waiting" << std::endl;
}
void Scene::addActor(PActor actor)
Array<StaticMeshBatch> Scene::getStaticMeshes()
{
rootActors.push_back(actor);
actor->notifySceneAttach(this);
Array<StaticMeshBatch> result;
auto view = registry.view<Component::StaticMesh, Component::Transform>();
struct PrimitiveSceneData
{
Math::Matrix4 localToWorld;
Math::Matrix4 worldToLocal;
Math::Vector4 actorLocation;
};
for(auto&& [entity, mesh, transform] : view.each())
{
PrimitiveSceneData sceneData = {
.localToWorld = transform.toMatrix(),
.worldToLocal = glm::inverse(transform.toMatrix()),
.actorLocation = Math::Vector4(transform.getPosition(), 1.0f)
};
UniformBufferCreateInfo info = {
.resourceData = {
.size = sizeof(PrimitiveSceneData),
.data = (uint8_t*)&sceneData,
}
};
Gfx::PUniformBuffer transformBuf = graphics->createUniformBuffer(info);
auto& batch = result.add();
batch.material = mesh.material;
batch.isBackfaceCullingDisabled = false;
batch.isCastingShadow = true;
batch.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
batch.useReverseCulling = false;
batch.useWireframe = false;
batch.vertexInput = mesh.vertexBuffer;
MeshBatchElement batchElement;
batchElement.baseVertexIndex = 0;
batchElement.firstIndex = 0;
batchElement.indexBuffer = mesh.indexBuffer;
batchElement.indirectArgsBuffer = nullptr;
batchElement.instanceRuns = nullptr;
batchElement.isInstanced = false;
batchElement.numInstances = 1;
batchElement.uniformBuffer = transformBuf;
batchElement.numPrimitives = static_cast<uint32>(mesh.indexBuffer->getNumIndices() / 3); //TODO: hardcoded
batch.elements.add(batchElement);
}
return result;
}
void Scene::addPrimitiveComponent(PPrimitiveComponent comp)
LightEnv Scene::getLightBuffer() const
{
primitives.push_back(comp);
for(auto& batch : comp->getStaticMeshes())
{
PrimitiveUniformBuffer data;
data.actorWorldPosition = Vector4(comp->getTransform().getPosition(), 1);
data.localToWorld = comp->getRenderMatrix();
data.worldToLocal = glm::inverse(data.localToWorld);
UniformBufferCreateInfo createInfo;
createInfo.resourceData.data = reinterpret_cast<uint8*>(&data);
createInfo.resourceData.owner = Gfx::QueueType::GRAPHICS;
createInfo.resourceData.size = sizeof(data);
createInfo.bDynamic = true;
Gfx::PUniformBuffer uniformBuffer = graphics->createUniformBuffer(createInfo);
for(auto& element : batch.elements)
{
element.uniformBuffer = uniformBuffer;
}
staticMeshes.push_back(batch);
}
LightEnv result;
result.directionalLights[0].color = Math::Vector4(0.4, 0.3, 0.5, 1.0);
result.directionalLights[0].direction = Math::Vector4(0.5, 0.5, 0, 0);
result.directionalLights[0].intensity = Math::Vector4(1.0, 0.9, 0.7, 0.5);\
result.numDirectionalLights = 1;
result.numPointLights = 0;
return result;
}
+30 -16
View File
@@ -1,26 +1,26 @@
#pragma once
#include <entt/entt.hpp>
#include "MinimalEngine.h"
#include "Actor/Actor.h"
#include "Graphics/GraphicsResources.h"
#include "Components/PrimitiveComponent.h"
#include "Graphics/MeshBatch.h"
namespace Seele
{
DECLARE_REF(Material)
DECLARE_REF(Entity)
struct DirectionalLight
{
Vector4 color;
Vector4 direction;
Vector4 intensity;
Math::Vector4 color;
Math::Vector4 direction;
Math::Vector4 intensity;
};
struct PointLight
{
Vector4 positionWS;
Math::Vector4 positionWS;
//Vector4 positionVS;
Vector4 colorRange;
Math::Vector4 colorRange;
};
#define MAX_DIRECTIONAL_LIGHTS 4
@@ -41,17 +41,31 @@ public:
void start();
void beginUpdate(double deltaTime);
void commitUpdate();
void addActor(PActor actor);
void addPrimitiveComponent(PPrimitiveComponent comp);
entt::entity createEntity()
{
return registry.create();
}
template<typename Component, typename... Args>
Component& attachComponent(entt::entity entity, Args... args)
{
return registry.emplace<Component>(entity, args...);
}
template<typename Component>
Component& accessComponent(entt::entity entity)
{
return registry.get<Component>(entity);
}
template<typename Component>
const Component& accessComponent(entt::entity entity) const
{
return registry.get<Component>(entity);
}
Array<StaticMeshBatch> getStaticMeshes();
LightEnv getLightBuffer() const;
const std::vector<PPrimitiveComponent>& getPrimitives() const { return primitives; }
const std::vector<StaticMeshBatch>& getStaticMeshes() const { return staticMeshes; }
LightEnv& getLightBuffer() { return lightEnv; }
entt::registry registry;
private:
std::vector<StaticMeshBatch> staticMeshes;
std::vector<PActor> rootActors;
std::vector<PPrimitiveComponent> primitives;
LightEnv lightEnv;
Gfx::PGraphics graphics;
};
DEFINE_REF(Scene)
} // namespace Seele
-75
View File
@@ -1,75 +0,0 @@
#include "SceneUpdater.h"
#include "Components/Component.h"
#include "Actor/Actor.h"
using namespace Seele;
SceneUpdater::SceneUpdater()
: pendingUpdatesSem(0)
{
running.store(true);
workers.resize(std::thread::hardware_concurrency());
for (size_t i = 0; i < workers.size(); i++)
{
workers[i] = std::thread(&SceneUpdater::work, this);
}
}
SceneUpdater::~SceneUpdater()
{
running.store(false);
for (size_t i = 0; i < workers.size(); i++)
{
workers[i].join();
}
}
void SceneUpdater::registerComponentUpdate(PComponent component)
{
std::scoped_lock lck(pendingUpdatesLock);
updatesRan.add([component](float delta) mutable { component->tick(delta); });
}
void SceneUpdater::registerActorUpdate(PActor actor)
{
std::scoped_lock lck(pendingUpdatesLock);
updatesRan.add([actor](float delta) mutable { actor->tick(delta); });
}
void SceneUpdater::runUpdates(float delta)
{
std::scoped_lock pendingLock(pendingUpdatesLock);
frameDelta = delta;
pendingUpdates = std::move(updatesRan);
updatesRan = List<std::function<void(float)>>();
std::scoped_lock lck(frameFinishedLock);
pendingLock.unlock();
pendingUpdatesSem.release(pendingUpdates.size());
frameFinishedCV.wait(lck);
}
void SceneUpdater::work()
{
while(running.load())
{
pendingUpdatesSem.acquire();
std::function<void(float)> function;
{
std::scoped_lock lck(pendingUpdatesLock);
function = std::move(pendingUpdates.front());
pendingUpdates.popFront();
if(pendingUpdates.empty())
{
std::scoped_lock lck(frameFinishedLock);
frameFinishedCV.notify_all();
}
}
function(frameDelta);
{
std::scoped_lock lck(pendingUpdatesLock);
updatesRan.add(std::move(function));
}
}
}
-31
View File
@@ -1,31 +0,0 @@
#pragma once
#include "MinimalEngine.h"
#include "Containers/List.h"
#include <semaphore>
//DEPRECATED
namespace Seele
{
DECLARE_REF(Component);
DECLARE_REF(Actor);
class SceneUpdater
{
public:
SceneUpdater();
~SceneUpdater();
void registerComponentUpdate(PComponent component);
void registerActorUpdate(PActor actor);
void runUpdates(float delta);
private:
Array<std::thread> workers;
std::mutex pendingUpdatesLock;
std::counting_semaphore<> pendingUpdatesSem;
List<std::function<void(float)>> pendingUpdates;
List<std::function<void(float)>> updatesRan;
void work();
float frameDelta;
std::atomic_bool running;
std::mutex frameFinishedLock;
std::condition_variable frameFinishedCV;
};
DEFINE_REF(SceneUpdater)
} // namespace Seele
+7
View File
@@ -0,0 +1,7 @@
target_sources(Engine
PUBLIC
Executor.h
Executor.cpp
CameraSystem.h
CameraSystem.cpp
SystemBase.h)
+11
View File
@@ -0,0 +1,11 @@
#include "CameraSystem.h"
#include "Scene/Component/Camera.h"
using namespace Seele;
using namespace Seele::System;
void CameraSystem::update(Component::Camera& camera)
{
camera.buildViewMatrix();
camera.buildProjectionMatrix();
}
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include "SystemBase.h"
#include "Scene/Component/Camera.h"
namespace Seele
{
namespace System
{
class CameraSystem : public SystemBase<Component::Camera>
{
public:
CameraSystem(entt::registry& registry) : SystemBase(registry) {}
virtual ~CameraSystem() {}
virtual void update(Component::Camera& component);
private:
};
} // namespace System
} // namespace Seele
+4
View File
@@ -0,0 +1,4 @@
#include "Executor.h"
using namespace Seele;
using namespace Seele::System;
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include "MinimalEngine.h"
#include "SystemBase.h"
#include <thread_pool/thread_pool.h>
namespace Seele
{
namespace System
{
class Executor
{
public:
Executor();
~Executor();
private:
dp::thread_pool<> pool;
};
} // namespace System
} // namespace Seele
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include <entt/entt.hpp>
#include <thread_pool/thread_pool.h>
#include "Scene/Component/Component.h"
namespace Seele
{
namespace System
{
template<typename... Components>
class SystemBase
{
public:
SystemBase(entt::registry& registry) : registry(registry) {}
virtual ~SystemBase() {}
template<typename Comp>
auto getDependencies()
{
return Comp::dependencies;
}
template<typename... Dep>
auto mergeDependencies(Dep... deps)
{
return (deps | ...);
}
template<typename... Deps>
void setupView(Dependencies<Deps...>, dp::thread_pool<>&)
{
registry.view<Components..., Deps...>().each([&](Components&... comp, Deps&... deps){
//pool.enqueue_detach([&](){
int ret = (accessComponent(deps) + ...);
assert(ret == 0);
update((comp,...));
//});
});
}
void run(dp::thread_pool<>& pool)
{
setupView(mergeDependencies((getDependencies<Components>(),...)), pool);
}
virtual void update(Components&... components) = 0;
private:
entt::registry& registry;
};
} // namespace System
} // namespace Seele
+2 -2
View File
@@ -59,12 +59,12 @@ bool Element::isEnabled() const
return enabled;
}
Rect& Element::getBoundingBox()
Math::Rect& Element::getBoundingBox()
{
return boundingBox;
}
const Rect Element::getBoundingBox() const
const Math::Rect Element::getBoundingBox() const
{
return boundingBox;
}
+3 -3
View File
@@ -23,13 +23,13 @@ public:
bool isEnabled() const;
// maybe not the healthiest inteface
// non-const version
Rect& getBoundingBox();
Math::Rect& getBoundingBox();
// The bounding box describes the relative size of any Element
// relative to the total view, meaning a bounding box of (0,0), (1,1)
// would take up the entire view
const Rect getBoundingBox() const;
const Math::Rect getBoundingBox() const;
protected:
Rect boundingBox;
Math::Rect boundingBox;
bool dirty;
bool enabled;
+2 -2
View File
@@ -18,14 +18,14 @@ HorizontalLayout::~HorizontalLayout()
void HorizontalLayout::apply()
{
Array<PElement> children = element->getChildren();
const Rect parent = element->getBoundingBox();
const Math::Rect parent = element->getBoundingBox();
float xOffset = parent.offset.x;
float yOffset = parent.offset.y;
float xSize = parent.size.x / children.size();
float ySize = parent.size.y;
for(uint32 index = 0; index < children.size(); ++index)
{
Rect& child = children[index]->getBoundingBox();
Math::Rect& child = children[index]->getBoundingBox();
child.offset.x = xOffset + (index * xSize);
child.offset.y = yOffset;
child.size.x = xSize;
+4 -4
View File
@@ -9,9 +9,9 @@ namespace UI
{
struct RenderElementStyle
{
Vector position = Vector(0, 0, 0);
uint32 backgroundImageIndex = -1;
Vector backgroundColor = Vector(1, 1, 1);
Math::Vector position = Math::Vector(0, 0, 0);
uint32 backgroundImageIndex = UINT32_MAX;
Math::Vector backgroundColor = Math::Vector(1, 1, 1);
float opacity = 1.0f;
//Vector4 borderBottomColor = Vector4(1, 1, 1, 1);
//Vector4 borderLeftColor = Vector4(1, 1, 1, 1);
@@ -21,7 +21,7 @@ struct RenderElementStyle
//float borderBottomRightRadius = 0;
//float borderTopLeftRadius = 0;
//float borderTopRightRadius = 0;
Vector2 dimensions = Vector2(1, 1);
Math::Vector2 dimensions = Math::Vector2(1, 1);
};
class RenderElement
{

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