diff --git a/.vscode/settings.json b/.vscode/settings.json index d0c196e..d21560e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -4,6 +4,7 @@ "git.enabled": false, "files.associations": { "*.h": "cpp", + "*.ush": "hlsl", "xstring": "cpp", "list": "cpp", "xhash": "cpp", @@ -93,7 +94,18 @@ "shared_mutex": "cpp", "unordered_set": "cpp", "csetjmp": "cpp", - "memory_resource": "cpp" + "memory_resource": "cpp", + "*.inc": "cpp", + "any": "cpp", + "bit": "cpp", + "cfenv": "cpp", + "cinttypes": "cpp", + "compare": "cpp", + "execution": "cpp", + "hash_map": "cpp", + "hash_set": "cpp", + "scoped_allocator": "cpp", + "stack": "cpp" }, "cmake.generator": "Ninja", "cmake.skipConfigureIfCachePresent": false, diff --git a/external/slang b/external/slang index dd980b4..bc0d0f9 160000 --- a/external/slang +++ b/external/slang @@ -1 +1 @@ -Subproject commit dd980b492aba9ea1540193434184489d9d04608d +Subproject commit bc0d0f9e2a5a7297d8559a2ee1e3bd59454813cf diff --git a/res/shaders/ComputeFrustums.slang b/res/shaders/ComputeFrustums.slang index 9dd8b45..e35582b 100644 --- a/res/shaders/ComputeFrustums.slang +++ b/res/shaders/ComputeFrustums.slang @@ -10,7 +10,7 @@ struct ComputeShaderInput uint groupIndex : SV_GroupIndex; }; -layout(set = 0, binding = 0) +layout(set = 0, binding = 0, std430) cbuffer DispatchParams { uint3 numThreadGroups; @@ -18,7 +18,7 @@ cbuffer DispatchParams uint3 numThreads; uint pad1; } -layout(set = 0, binding = 2) +layout(set = 0, binding = 2, std430) RWStructuredBuffer out_Frustums; diff --git a/res/shaders/DepthPrepass.slang b/res/shaders/DepthPrepass.slang index cf7f6f1..ec3260e 100644 --- a/res/shaders/DepthPrepass.slang +++ b/res/shaders/DepthPrepass.slang @@ -1,4 +1,6 @@ -import InputGeometry; +import Material; +import VERTEX_INPUT_IMPORT; +import MATERIAL_IMPORT; struct ViewParams { @@ -10,6 +12,11 @@ struct ViewParams layout(set = 0, binding = 0) ParameterBlock gViewParams; + +layout(set = 1) +type_param TMaterial : IMaterial; +ParameterBlock gMaterial; + struct ModelParameter { float4x4 modelMatrix; @@ -18,16 +25,21 @@ struct ModelParameter [[vk::push_constant]] ConstantBuffer gModelParams; -struct VertexShaderOutput +struct VertexStageOutput { - float4 out_Position : SV_Position; + float4 position : SV_Position; } [shader("vertex")] -VertexShaderOutput depthPrepass(PositionOnlyVertexInput input) -{ - VertexShaderOutput out; - float4 worldPos = mul(gModelParams.modelMatrix, float4(input.getVertexPosition(), 1)); - float4 viewPos = mul(gViewParams.viewMatrix, worldPos); - out.out_Position = mul(gViewParams.projectionMatrix, viewPos); - return out; +VertexStageOutput vertexMain(PositionOnlyVertexShaderInput input) +{ + VertexStageOutput output; + + float3 worldPosition = input.getWorldPosition(); + worldPosition += gMaterial.getWorldOffset(); + float4 clipSpacePosition; + + float4 viewSpacePosition = mul(gViewParams.viewMatrix, float4(worldPosition, 1)); + clipSpacePosition = mul(gViewParams.projectionMatrix, viewSpacePosition); + output.position = clipSpacePosition; + return output; } \ No newline at end of file diff --git a/res/shaders/ForwardPlus.slang b/res/shaders/ForwardPlus.slang index bb43f58..732b9c5 100644 --- a/res/shaders/ForwardPlus.slang +++ b/res/shaders/ForwardPlus.slang @@ -1,11 +1,10 @@ import LightEnv; import BRDF; import Material; -import TexturedMaterial; -import FlatColorMaterial; import Common; -//TODO revert to pre processed shader attributes -import StaticMeshShaderAttributes; + +import VERTEX_INPUT_IMPORT; +import MATERIAL_IMPORT; import PrimitiveSceneData; import MaterialParameter; @@ -14,9 +13,9 @@ import MaterialParameter; //layout(set = 0, binding = 3) //RWTexture2D lightGrid; -layout(set = 1, std430) -//type_param TMaterial : IMaterial; -ParameterBlock gMaterial; +type_param TMaterial : IMaterial; +layout(set = 1) +ParameterBlock gMaterial; struct VertexStageOutput { @@ -31,7 +30,7 @@ VertexStageOutput vertexMain( { VertexStageOutput output; VertexValueCache cache = input.getVertexCache(); - float3 worldPosition = input.getWorldPosition(cache); + float3 worldPosition = input.getWorldPosition(); float4 clipSpacePosition; float3x3 tangentToLocal = cache.tangentToLocal; @@ -52,7 +51,7 @@ float4 fragmentMain( ) : SV_Target { MaterialFragmentParameter materialParams = input.getMaterialParameter(position); - BlinnPhong brdf = gMaterial.prepare(materialParams); + TMaterial.BRDF brdf = gMaterial.prepare(materialParams); float3 viewDir = normalize(materialParams.viewDir); diff --git a/res/shaders/Placeholder.semat b/res/shaders/Placeholder.asset similarity index 58% rename from res/shaders/Placeholder.semat rename to res/shaders/Placeholder.asset index 0c1d0e2..8fbe65b 100644 --- a/res/shaders/Placeholder.semat +++ b/res/shaders/Placeholder.asset @@ -50,26 +50,51 @@ "clearCoatGloss": { "type": "float", "default": "1.0f" + }, + "worldOffset": { + "type": "float3", + "default": "float3(0, 0, 0)" }, "textureSampler": { "type": "SamplerState" } }, - "code": [ - "result.baseColor = diffuseTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;", - "result.metallic = 0;", - "float3 bumpMapNormal = normalTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;", - "bumpMapNormal = 2.0 * bumpMapNormal - float3(1.0, 1.0, 1.0);", - "result.normal = input.transformLocalToWorld(bumpMapNormal);", - "result.specular = specularTexture.Sample(textureSampler, input.texCoords[0] * uvScale).x;", - "result.roughness = roughness;", - "result.specularTint = specularTint;", - "result.anisotropic = anisotropic;", - "result.sheen = sheen;", - "result.sheenTint = sheenTint;", - "result.clearCoat = clearCoat;", - "result.clearCoatGloss = clearCoatGloss;", - "return result;" - ] - + "code": { + "baseColor": [ + "return diffuseTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;" + ], + "metallic": [ + "return 0;" + ], + "normal": [ + "return normalTexture.Sample(textureSampler, input.texCoords[0] * uvScale).xyz;" + ], + "specular": [ + "return specularTexture.Sample(textureSampler, input.texCoords[0] * uvScale).x;" + ], + "roughness": [ + "return roughness;" + ], + "specularTint": [ + "return specularTint;" + ], + "anisotropic": [ + "return anisotropic;" + ], + "sheen": [ + "return sheen;" + ], + "sheenTint": [ + "return sheenTint;" + ], + "clearCoat": [ + "return clearCoat;" + ], + "clearCoatGloss": [ + "return clearCoatGloss;" + ], + "worldOffset": [ + "return worldOffset;" + ] + } } \ No newline at end of file diff --git a/res/shaders/lib/BRDF.slang b/res/shaders/lib/BRDF.slang index 815235a..2db0e3b 100644 --- a/res/shaders/lib/BRDF.slang +++ b/res/shaders/lib/BRDF.slang @@ -10,15 +10,9 @@ struct BlinnPhong : IBRDF float3 baseColor; float metallic = 0; float3 normal = float3(0, 1, 0); - float subsurface = 0; float specular = 0.5; float roughness = 0.5; - float specularTint = 0; - float anisotropic = 0; - float sheen = 0; - float sheenTint = 0.5f; - float clearCoat = 0; - float clearCoatGloss = 1; + float sheen = 1.f; float3 evaluate(float3 view, float3 light, float3 surfaceNormal, float3 tangent, float3 biTangent, float3 lightColor) { diff --git a/res/shaders/lib/LightEnv.slang b/res/shaders/lib/LightEnv.slang index 1be9555..66f4251 100644 --- a/res/shaders/lib/LightEnv.slang +++ b/res/shaders/lib/LightEnv.slang @@ -1,11 +1,10 @@ -import StaticMeshShaderAttributes; import MaterialParameter; import BRDF; import Common; interface ILightEnv { - float3 illuminate(VertexShaderInput input, B brdf, float3 wo); + float3 illuminate(MaterialFragmentParameter input, B brdf, float3 wo); }; struct DirectionalLight : ILightEnv @@ -70,5 +69,5 @@ struct Lights uint numPointLights; }; -layout(set = 0, binding = 1, std430) +layout(set = 0, binding = 1) ConstantBuffer gLightEnv; diff --git a/res/shaders/lib/Material.slang b/res/shaders/lib/Material.slang index 365b2ef..4ce6639 100644 --- a/res/shaders/lib/Material.slang +++ b/res/shaders/lib/Material.slang @@ -6,4 +6,13 @@ interface IMaterial { associatedtype BRDF : IBRDF; BRDF prepare(MaterialFragmentParameter input); + + float3 getWorldOffset(); + + float3 getBaseColor(MaterialFragmentParameter input); + float getMetallic(MaterialFragmentParameter input); + float3 getNormal(MaterialFragmentParameter input); + float getSpecular(MaterialFragmentParameter input); + float getRoughness(MaterialFragmentParameter input); + float getSheen(MaterialFragmentParameter input); }; diff --git a/res/shaders/lib/MaterialParameter.slang b/res/shaders/lib/MaterialParameter.slang index 4b26a59..1dba517 100644 --- a/res/shaders/lib/MaterialParameter.slang +++ b/res/shaders/lib/MaterialParameter.slang @@ -5,7 +5,7 @@ struct MaterialVertexParameter #if NUM_MATERIAL_TEXCOORDS float2 texCoords[NUM_MATERIAL_TEXCOORDS]; #endif -#if USE_INSTANCING +#ifdef USE_INSTANCING float4x4 instanceLocalToWorld; float3 instanceLocalPosition; float4 perInstanceParams; @@ -26,7 +26,7 @@ struct MaterialFragmentParameter float4 clipPosition; float4 vertexColor; float3x3 tangentToWorld; -#if USE_INSTANCING +#ifdef USE_INSTANCING float3 perInstanceParams; #endif #if NUM_MATERIAL_TEXCOORDS @@ -37,4 +37,11 @@ struct MaterialFragmentParameter float3 result = mul(tangentToWorld, tangentSpaceNormal); return result; } + float3 transformNormalTexture(float3 rawNormal) + { + rawNormal = 2.0 * rawNormal - float3(1.0, 1.0, 1.0); + return transformNormalToWorld(rawNormal); + } }; + + diff --git a/res/shaders/lib/StaticMeshShaderAttributes.slang b/res/shaders/lib/StaticMeshVertexInput.slang similarity index 94% rename from res/shaders/lib/StaticMeshShaderAttributes.slang rename to res/shaders/lib/StaticMeshVertexInput.slang index f3a373f..89ca563 100644 --- a/res/shaders/lib/StaticMeshShaderAttributes.slang +++ b/res/shaders/lib/StaticMeshVertexInput.slang @@ -114,7 +114,7 @@ struct VertexShaderInput return result; } - float3 getWorldPosition(VertexValueCache cache) + float3 getWorldPosition() { float4x4 localToWorld = gSceneData.localToWorld; float3 rotatedPosition = localToWorld[0].xyz * position.xxx + localToWorld[1].xyz * position.yyy + localToWorld[2].xyz * position.zzz; @@ -191,4 +191,10 @@ struct PositionOnlyVertexShaderInput float3 instanceTransform2; float3 instanceTransform3; #endif // USE_INSTANCING + float3 getWorldPosition() + { + float4x4 localToWorld = gSceneData.localToWorld; + float3 rotatedPosition = localToWorld[0].xyz * position.xxx + localToWorld[1].xyz * position.yyy + localToWorld[2].xyz * position.zzz; + return rotatedPosition + localToWorld[3].xyz; + } }; diff --git a/src/Engine/Asset/Asset.cpp b/src/Engine/Asset/Asset.cpp index 25d650a..234aaa4 100644 --- a/src/Engine/Asset/Asset.cpp +++ b/src/Engine/Asset/Asset.cpp @@ -1,4 +1,5 @@ #include "Asset.h" +#include "AssetRegistry.h" using namespace Seele; @@ -11,9 +12,18 @@ Asset::Asset() { } Asset::Asset(const std::filesystem::path& path) - : fullPath(std::filesystem::absolute(path)) - , status(Status::Uninitialized) + : status(Status::Uninitialized) { + if(path.is_absolute()) + { + fullPath = path; + } + else + { + fullPath = AssetRegistry::getRootFolder(); + fullPath.append(path.generic_string()); + } + fullPath.make_preferred(); parentDir = fullPath.parent_path(); name = fullPath.stem(); @@ -49,15 +59,15 @@ std::ofstream &Asset::getWriteStream() return outStream; } -std::string Asset::getFileName() +std::string Asset::getFileName() const { return name.generic_string(); } -std::string Asset::getFullPath() +std::string Asset::getFullPath() const { return fullPath.generic_string(); } -std::string Asset::getExtension() +std::string Asset::getExtension() const { return extension.generic_string(); } \ No newline at end of file diff --git a/src/Engine/Asset/Asset.h b/src/Engine/Asset/Asset.h index 7325263..ccfcc35 100644 --- a/src/Engine/Asset/Asset.h +++ b/src/Engine/Asset/Asset.h @@ -23,11 +23,11 @@ public: virtual void load() = 0; // returns the name of the file, without extension - std::string getFileName(); + std::string getFileName() const; // returns the full absolute path, from root to extension - std::string getFullPath(); + std::string getFullPath() const; // returns the file extension, without preceding dot - std::string getExtension(); + std::string getExtension() const; inline Status getStatus() { std::scoped_lock lck(lock); @@ -44,6 +44,7 @@ protected: std::ofstream& getWriteStream(); private: Status status; + // Path relative to the project root std::filesystem::path fullPath; std::filesystem::path parentDir; std::filesystem::path name; diff --git a/src/Engine/Asset/AssetRegistry.cpp b/src/Engine/Asset/AssetRegistry.cpp index 3aecfc2..b6ca24c 100644 --- a/src/Engine/Asset/AssetRegistry.cpp +++ b/src/Engine/Asset/AssetRegistry.cpp @@ -28,16 +28,16 @@ void AssetRegistry::importFile(const std::string &filePath) if (extension.compare(".fbx") == 0 || extension.compare(".obj") == 0) { - get().registerMesh(fsPath); + get().importMesh(fsPath); } if (extension.compare(".png") == 0 || extension.compare(".jpg") == 0) { - get().registerTexture(fsPath); + get().importTexture(fsPath); } if (extension.compare(".semat") == 0) { - get().registerMaterial(fsPath); + get().importMaterial(fsPath); } } @@ -51,6 +51,16 @@ PMaterialAsset AssetRegistry::findMaterial(const std::string &filePath) return get().materials[filePath]; } +std::ofstream AssetRegistry::createWriteStream(const std::string& relativePath, std::ios_base::openmode openmode) +{ + return get().internalCreateWriteStream(relativePath, openmode); +} + +std::ifstream AssetRegistry::createReadStream(const std::string& relativePath, std::ios_base::openmode openmode) +{ + return get().internalCreateReadStream(relativePath, openmode); +} + PTextureAsset AssetRegistry::findTexture(const std::string &filePath) { return get().textures[filePath]; @@ -75,17 +85,49 @@ void AssetRegistry::init(const std::filesystem::path &rootFolder, Gfx::PGraphics reg.materialLoader = new MaterialLoader(graphics); } -void AssetRegistry::registerMesh(const std::filesystem::path &filePath) +std::string AssetRegistry::getRootFolder() +{ + return get().rootFolder.generic_string(); +} + +void AssetRegistry::importMesh(const std::filesystem::path &filePath) { meshLoader->importAsset(filePath); } -void AssetRegistry::registerTexture(const std::filesystem::path &filePath) +void AssetRegistry::importTexture(const std::filesystem::path &filePath) { textureLoader->importAsset(filePath); } -void AssetRegistry::registerMaterial(const std::filesystem::path &filePath) +void AssetRegistry::importMaterial(const std::filesystem::path &filePath) { materialLoader->queueAsset(filePath); -} \ No newline at end of file +} + +void AssetRegistry::registerMesh(PMeshAsset mesh) +{ + PMeshAsset existingMesh = meshes[mesh->getFileName()]; + if(existingMesh != nullptr) + { + auto newMeshes = mesh->getMeshes(); + for(uint32 i = 0; i < newMeshes.size(); ++i) + { + existingMesh->addMesh(newMeshes[i]); + } + } + else + { + meshes[mesh->getFileName()] = mesh; + } +} + +std::ofstream AssetRegistry::internalCreateWriteStream(const std::string& relativePath, std::ios_base::openmode openmode) +{ + return std::ofstream(rootFolder.generic_string().append(relativePath), openmode); +} + +std::ifstream AssetRegistry::internalCreateReadStream(const std::string& relativePath, std::ios_base::openmode openmode) +{ + return std::ifstream(rootFolder.generic_string().append(relativePath), openmode); +} diff --git a/src/Engine/Asset/AssetRegistry.h b/src/Engine/Asset/AssetRegistry.h index 9c1bf32..6893a7f 100644 --- a/src/Engine/Asset/AssetRegistry.h +++ b/src/Engine/Asset/AssetRegistry.h @@ -18,21 +18,33 @@ public: ~AssetRegistry(); static void init(const std::string& rootFolder); + static std::string getRootFolder(); + static void importFile(const std::string& filePath); static PMeshAsset findMesh(const std::string& filePath); static PTextureAsset findTexture(const std::string& filePath); static PMaterialAsset findMaterial(const std::string& filePath); + + static std::ofstream createWriteStream(const std::string& relativePath, std::ios_base::openmode openmode = 0); + static std::ifstream createReadStream(const std::string& relativePath, std::ios_base::openmode openmode = 0); private: static AssetRegistry& get(); AssetRegistry(); void init(const std::filesystem::path& rootFolder, Gfx::PGraphics graphics); - void registerMesh(const std::filesystem::path& filePath); - void registerTexture(const std::filesystem::path& filePath); - void registerMaterial(const std::filesystem::path& filePath); - + void importMesh(const std::filesystem::path& filePath); + void importTexture(const std::filesystem::path& filePath); + void importMaterial(const std::filesystem::path& filePath); + + void registerMesh(PMeshAsset mesh); + void registerTexture(PTextureAsset texture); + void registerMaterial(PMaterialAsset material); + + std::ofstream internalCreateWriteStream(const std::string& relativePath, std::ios_base::openmode openmode = 0); + std::ifstream internalCreateReadStream(const std::string& relaitvePath, std::ios_base::openmode openmode = 0); + std::filesystem::path rootFolder; Map textures; Map meshes; diff --git a/src/Engine/Asset/MaterialLoader.cpp b/src/Engine/Asset/MaterialLoader.cpp index 551e7ae..29164dd 100644 --- a/src/Engine/Asset/MaterialLoader.cpp +++ b/src/Engine/Asset/MaterialLoader.cpp @@ -5,9 +5,11 @@ using namespace Seele; MaterialLoader::MaterialLoader(Gfx::PGraphics graphics) + : graphics(graphics) { - placeholderMaterial = new Material("shaders/Placeholder.semat"); + placeholderMaterial = new Material(std::filesystem::absolute("./shaders/Placeholder.asset")); placeholderMaterial->compile(); + graphics->getShaderCompiler()->registerMaterial(placeholderMaterial); } MaterialLoader::~MaterialLoader() @@ -17,6 +19,8 @@ MaterialLoader::~MaterialLoader() PMaterial MaterialLoader::queueAsset(const std::filesystem::path& filePath) { PMaterial result = new Material(filePath); + result->compile(); + graphics->getShaderCompiler()->registerMaterial(result); // TODO: There is actually no real reason to import a standalone material, // maybe in the future there could be a substance loader or something return result; diff --git a/src/Engine/Asset/MaterialLoader.h b/src/Engine/Asset/MaterialLoader.h index 1bc711c..c4b954c 100644 --- a/src/Engine/Asset/MaterialLoader.h +++ b/src/Engine/Asset/MaterialLoader.h @@ -16,6 +16,7 @@ public: ~MaterialLoader(); PMaterial queueAsset(const std::filesystem::path& filePath); private: + Gfx::PGraphics graphics; List> futures; PMaterial placeholderMaterial; }; diff --git a/src/Engine/Asset/MeshLoader.cpp b/src/Engine/Asset/MeshLoader.cpp index 23ce8b6..80d98ca 100644 --- a/src/Engine/Asset/MeshLoader.cpp +++ b/src/Engine/Asset/MeshLoader.cpp @@ -3,9 +3,11 @@ #include "Graphics/Graphics.h" #include "MeshAsset.h" #include "Graphics/Mesh.h" +#include "Graphics/StaticMeshVertexInput.h" #include "AssetRegistry.h" #include "Material/Material.h" #include +#include #include #include #include @@ -27,7 +29,8 @@ MeshLoader::~MeshLoader() void MeshLoader::importAsset(const std::filesystem::path &path) { - futures.add(std::async(std::launch::async, &MeshLoader::import, this, path)); + //futures.add(std::async(std::launch::async, &MeshLoader::import, this, path)); + import(path); } void loadMaterials(const aiScene* scene, Array& globalMaterials, Gfx::PGraphics graphics) @@ -52,7 +55,7 @@ void loadMaterials(const aiScene* scene, Array& globalMaterials, matCode["params"]["diffuseTexture"] = { {"type", "Texture2D"}, - {"default", texFilename} + {"default", texPath.C_Str()} }; code.push_back("result.baseColor = diffuseTexture.Sample(textureSampler, geometry.texCoord).xyz;\n"); } @@ -62,7 +65,7 @@ void loadMaterials(const aiScene* scene, Array& globalMaterials, matCode["params"]["specularTexture"] = { {"type", "Texture2D"}, - {"default", texFilename} + {"default", texPath.C_Str()} }; code.push_back("result.specular = specularTexture.Sample(textureSampler, geometry.texCoord).xyz;\n"); } @@ -72,7 +75,7 @@ void loadMaterials(const aiScene* scene, Array& globalMaterials, matCode["params"]["normalTexture"] = { {"type", "Texture2D"}, - {"default", texFilename} + {"default", texPath.C_Str()} }; code.push_back("float3 bumpMapNormal = normalTexture.Sample(textureSampler, geometry.texCoord).xyz;\n"); code.push_back("bumpMapNormal = 2.0 * bumpMapNormal - float3(1.0f, 1.0f, 1.0f);\n"); @@ -80,10 +83,15 @@ void loadMaterials(const aiScene* scene, Array& globalMaterials, } code.push_back("return result;\n"); matCode["code"] = code; - std::ofstream outMatFile("testMat.asset"); + std::string outMatFilename = matCode["name"].get().append(".asset"); + std::ofstream outMatFile = AssetRegistry::createWriteStream(outMatFilename); outMatFile << std::setw(4) << matCode; outMatFile.flush(); - PMaterial asset = new Material("testMat.asset"); + outMatFile.close(); + //TODO: let the material loader handle this instead + std::cout << matCode["name"] << std::endl; + AssetRegistry::importFile(outMatFilename); + PMaterialAsset asset = AssetRegistry::findMaterial(outMatFilename); globalMaterials[i] = asset; } } @@ -108,7 +116,7 @@ void loadToBuffer(Array& buffer, const aiVector3D* sourceData, uint32 si buffer[i] = Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z); } } -Gfx::VertexStream createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::PGraphics graphics) +VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::PGraphics graphics) { Array buffer(size); for(uint32 i = 0; i < size; ++i) @@ -121,12 +129,10 @@ Gfx::VertexStream createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::P vbInfo.resourceData.data = (uint8 *)buffer.data(); vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; vbInfo.resourceData.size = buffer.size(); - Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo); - auto stream = Gfx::VertexStream(vbInfo.vertexSize, 0, false, vertexBuffer); - stream.addVertexElement(Gfx::VertexElement(0, Gfx::SE_FORMAT_R32G32_SFLOAT, 0)); - return stream; + const Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo); + return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT); } -Gfx::VertexStream createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics) +VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics) { Array buffer(size); for(uint32 i = 0; i < size; ++i) @@ -140,9 +146,7 @@ Gfx::VertexStream createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::P vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER; vbInfo.resourceData.size = buffer.size(); Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo); - auto stream = Gfx::VertexStream(vbInfo.vertexSize, 0, false, vertexBuffer); - stream.addVertexElement(Gfx::VertexElement(0, Gfx::SE_FORMAT_R32G32B32_SFLOAT, 0)); - return stream; + return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT); } void loadGlobalMeshes(const aiScene* scene, Array& globalMeshes, Array materials, Gfx::PGraphics graphics) { @@ -150,32 +154,29 @@ void loadGlobalMeshes(const aiScene* scene, Array& globalMeshes, ArraymMeshes[meshIndex]; - MeshDescription description; - Gfx::PVertexDeclaration declaration = new Gfx::VertexDeclaration(); - declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics)); - description.layout.add(Gfx::VertexAttribute::POSITION); + PStaticMeshVertexInput vertexShaderInput = new StaticMeshVertexInput(std::string(mesh->mName.C_Str())); + VertexStreamComponent positionStream = createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics); + vertexShaderInput->setPositionStream(positionStream); - for(uint32 i = 0; i < MAX_TEX_CHANNELS; ++i) + for(uint32 i = 0; i < MAX_TEXCOORDS; ++i) { if(mesh->HasTextureCoords(i)) { - declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mTextureCoords[i], graphics)); - description.layout.add(Gfx::VertexAttribute::TEXCOORD); + VertexStreamComponent texCoordStream = createVertexStream(mesh->mNumVertices, mesh->mTextureCoords[i], graphics); + vertexShaderInput->setTexCoordStream(i, texCoordStream); } } if(mesh->HasNormals()) { - declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mNormals, graphics)); - description.layout.add(Gfx::VertexAttribute::NORMAL); + VertexStreamComponent normalStream = createVertexStream(mesh->mNumVertices, mesh->mNormals, graphics); + vertexShaderInput->setTangentXStream(normalStream); } if(mesh->HasTangentsAndBitangents()) { - declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics)); - declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics)); - description.layout.add(Gfx::VertexAttribute::TANGENT); - description.layout.add(Gfx::VertexAttribute::BITANGENT); + //TODO: use bitangent to calculate sign for 4th coordinate of tangentstream + VertexStreamComponent tangentStream = createVertexStream(mesh->mNumVertices, mesh->mTangents, graphics); + vertexShaderInput->setTangentZStream(tangentStream); } - description.declaration = declaration; Array indices(mesh->mNumFaces * 3); for (uint32 faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex) @@ -192,7 +193,7 @@ void loadGlobalMeshes(const aiScene* scene, Array& globalMeshes, ArraycreateIndexBuffer(idxInfo); indexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS); - globalMeshes[meshIndex] = new Mesh(description, indexBuffer); + globalMeshes[meshIndex] = new Mesh(vertexShaderInput, indexBuffer); globalMeshes[meshIndex]->referencedMaterial = materials[mesh->mMaterialIndex]; } } @@ -247,23 +248,27 @@ void MeshLoader::import(const std::filesystem::path &path) aiProcess_FindDegenerates | aiProcess_EmbedTextures); const aiScene *scene = importer.ApplyPostProcessing(aiProcess_CalcTangentSpace); - Array globalMeshes(scene->mNumMeshes); + Array globalMaterials(scene->mNumMaterials); - loadMaterials(scene, globalMaterials, graphics); - loadGlobalMeshes(scene, globalMeshes, globalMaterials, graphics); loadTextures(scene, graphics, path); + loadMaterials(scene, globalMaterials, graphics); + + Array globalMeshes(scene->mNumMeshes); + loadGlobalMeshes(scene, globalMeshes, globalMaterials, graphics); + List meshNodes; findMeshRoots(scene->mRootNode, meshNodes); + std::filesystem::path filePath = path.filename(); + filePath.replace_extension("asset"); + PMeshAsset meshAsset = new MeshAsset(filePath.generic_string()); for (auto meshNode : meshNodes) { - std::string fileName = std::string("arissa").append(".asset"); - PMeshAsset meshAsset = new MeshAsset(fileName); for(uint32 i = 0; i < meshNode->mNumMeshes; ++i) { meshAsset->addMesh(globalMeshes[meshNode->mMeshes[i]]); } - meshAsset->save(); - AssetRegistry::get().meshes[meshAsset->getFileName()] = meshAsset; } + meshAsset->save(); + AssetRegistry::get().registerMesh(meshAsset); } diff --git a/src/Engine/Asset/TextureLoader.cpp b/src/Engine/Asset/TextureLoader.cpp index 4a32cbc..b9d3393 100644 --- a/src/Engine/Asset/TextureLoader.cpp +++ b/src/Engine/Asset/TextureLoader.cpp @@ -12,8 +12,7 @@ using namespace Seele; TextureLoader::TextureLoader(Gfx::PGraphics graphics) : graphics(graphics) { - import("textures/placeholder.png"); - placeholderTexture = AssetRegistry::findTexture("textures/placeholder.png"); + placeholderTexture = import("./textures/placeholder.png"); } TextureLoader::~TextureLoader() @@ -22,15 +21,20 @@ TextureLoader::~TextureLoader() void TextureLoader::importAsset(const std::filesystem::path& filePath) { - futures.add(std::async(std::launch::async, &TextureLoader::import, this, filePath)); + auto assetFileName = filePath; + PTextureAsset asset = new TextureAsset(assetFileName.replace_extension("asset").filename().generic_string()); + asset->setStatus(Asset::Status::Loading); + asset->setTexture(placeholderTexture); + AssetRegistry::get().textures[filePath.string()] = asset; + futures.add(std::async(std::launch::async, [this, filePath, asset] () mutable { + Gfx::PTexture2D texture = import(filePath); + asset->setTexture(texture); + asset->setStatus(Asset::Status::Ready); + })); } -void TextureLoader::import(const std::filesystem::path& path) +Gfx::PTexture2D TextureLoader::import(const std::filesystem::path& path) { - auto assetFileName = path; - std::filesystem::path assetPath = AssetRegistry::get().rootFolder.append(assetFileName.replace_extension("asset").filename().string()); - PTextureAsset asset = new TextureAsset(assetPath); - asset->setStatus(Asset::Status::Loading); int x, y, n; unsigned char* data = stbi_load(path.string().c_str(), &x, &y, &n, 4); TextureCreateInfo createInfo; @@ -43,7 +47,5 @@ void TextureLoader::import(const std::filesystem::path& path) Gfx::PTexture2D texture = graphics->createTexture2D(createInfo); stbi_image_free(data); texture->transferOwnership(Gfx::QueueType::GRAPHICS); - asset->setTexture(texture); - asset->setStatus(Asset::Status::Ready); - AssetRegistry::get().textures[path.string()] = asset; + return texture; } \ No newline at end of file diff --git a/src/Engine/Asset/TextureLoader.h b/src/Engine/Asset/TextureLoader.h index fcdb15b..ea2baa5 100644 --- a/src/Engine/Asset/TextureLoader.h +++ b/src/Engine/Asset/TextureLoader.h @@ -9,6 +9,7 @@ namespace Seele { DECLARE_REF(TextureAsset); DECLARE_NAME_REF(Gfx, Graphics); +DECLARE_NAME_REF(Gfx, Texture2D); class TextureLoader { public: @@ -16,10 +17,10 @@ public: ~TextureLoader(); void importAsset(const std::filesystem::path& filePath); private: - void import(const std::filesystem::path& path); + Gfx::PTexture2D import(const std::filesystem::path& path); Gfx::PGraphics graphics; List> futures; - PTextureAsset placeholderTexture; + Gfx::PTexture2D placeholderTexture; }; DEFINE_REF(TextureLoader); } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Containers/List.h b/src/Engine/Containers/List.h index 7bbb97f..cd43d40 100644 --- a/src/Engine/Containers/List.h +++ b/src/Engine/Containers/List.h @@ -163,7 +163,14 @@ public: { prev->next = next; } - next->prev = prev; + if(next == nullptr) + { + root = prev; + } + else + { + next->prev = prev; + } delete pos.node; refreshIterators(); return Iterator(next); diff --git a/src/Engine/Graphics/CMakeLists.txt b/src/Engine/Graphics/CMakeLists.txt index 47ff4ea..20c9120 100644 --- a/src/Engine/Graphics/CMakeLists.txt +++ b/src/Engine/Graphics/CMakeLists.txt @@ -11,16 +11,22 @@ target_sources(SeeleEngine MeshBatch.h RenderCore.h RenderCore.cpp + RenderMaterial.h + RenderMaterial.cpp RenderPath.h RenderPath.cpp SceneView.h SceneView.cpp SceneRenderPath.h SceneRenderPath.cpp + ShaderCompiler.h + ShaderCompiler.cpp View.h View.cpp VertexShaderInput.h VertexShaderInput.cpp + StaticMeshVertexInput.h + StaticMeshVertexInput.cpp Window.cpp Window.h WindowManager.h diff --git a/src/Engine/Graphics/Graphics.cpp b/src/Engine/Graphics/Graphics.cpp index 141cc6d..d4a1d15 100644 --- a/src/Engine/Graphics/Graphics.cpp +++ b/src/Engine/Graphics/Graphics.cpp @@ -1,10 +1,11 @@ #include "Graphics.h" -#include +#include "ShaderCompiler.h" using namespace Seele::Gfx; Graphics::Graphics() { + shaderCompiler = new ShaderCompiler(this); } Graphics::~Graphics() diff --git a/src/Engine/Graphics/Graphics.h b/src/Engine/Graphics/Graphics.h index 15e1b4d..f469ad5 100644 --- a/src/Engine/Graphics/Graphics.h +++ b/src/Engine/Graphics/Graphics.h @@ -3,6 +3,7 @@ #include "GraphicsResources.h" #include "Containers/Array.h" #include "VertexShaderInput.h" +#include "ShaderCompiler.h" namespace Seele { @@ -19,6 +20,11 @@ public: { return queueMapping; } + + PShaderCompiler getShaderCompiler() const + { + return shaderCompiler; + } virtual PWindow createWindow(const WindowCreateInfo &createInfo) = 0; virtual PViewport createViewport(PWindow owner, const ViewportCreateInfo &createInfo) = 0; @@ -47,6 +53,7 @@ public: protected: QueueFamilyMapping queueMapping; + PShaderCompiler shaderCompiler; friend class Window; }; DEFINE_REF(Graphics); diff --git a/src/Engine/Graphics/GraphicsInitializer.h b/src/Engine/Graphics/GraphicsInitializer.h index acb8190..930c6b1 100644 --- a/src/Engine/Graphics/GraphicsInitializer.h +++ b/src/Engine/Graphics/GraphicsInitializer.h @@ -100,6 +100,7 @@ struct ShaderCreateInfo Array shaderCode; std::string entryPoint; Array typeParameter; + Map defines; }; namespace Gfx diff --git a/src/Engine/Graphics/GraphicsResources.cpp b/src/Engine/Graphics/GraphicsResources.cpp index 0362fac..266d6ec 100644 --- a/src/Engine/Graphics/GraphicsResources.cpp +++ b/src/Engine/Graphics/GraphicsResources.cpp @@ -42,18 +42,37 @@ ShaderCollection& ShaderMap::createShaders( PGraphics graphics, RenderPassType renderPass, PMaterial material, - PVertexShaderInput vertexInput, + VertexInputType* vertexInput, bool bPositionOnly) { ShaderCollection& collection = shaders.add(); - collection.vertexDeclaration = bPositionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration(); + //collection.vertexDeclaration = bPositionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration(); ShaderCreateInfo createInfo; createInfo.entryPoint = "vertexMain"; - createInfo.typeParameter = {material->getMaterialName().c_str(), vertexInput->getName().c_str()}; + 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"; + std::ifstream codeStream("./shaders/" + getShaderNameFromRenderPassType(renderPass), std::ios::ate); + auto fileSize = codeStream.tellg(); + codeStream.seekg(0); + Array buffer(static_cast(fileSize)); + codeStream.read(buffer.data(), fileSize); + + createInfo.shaderCode.add(std::string(buffer.data())); + collection.vertexShader = graphics->createVertexShader(createInfo); + if(renderPass != RenderPassType::DepthPrepass) + { + createInfo.entryPoint = "fragmentMain"; + + collection.fragmentShader = graphics->createFragmentShader(createInfo); + } + return collection; } void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount) @@ -108,8 +127,8 @@ void PipelineLayout::addPushConstants(const SePushConstantRange &pushConstant) pushConstants.add(pushConstant); } -QueueOwnedResource::QueueOwnedResource(PGraphics graphics, QueueType startQueueType) - : graphics(graphics) +QueueOwnedResource::QueueOwnedResource(QueueFamilyMapping mapping, QueueType startQueueType) + : mapping(mapping) , currentOwner(startQueueType) { } @@ -120,15 +139,15 @@ QueueOwnedResource::~QueueOwnedResource() void QueueOwnedResource::transferOwnership(QueueType newOwner) { - if(graphics->getFamilyMapping().needsTransfer(currentOwner, newOwner)) + if(mapping.needsTransfer(currentOwner, newOwner)) { executeOwnershipBarrier(newOwner); currentOwner = newOwner; } } -Buffer::Buffer(PGraphics graphics, QueueType startQueue) - : QueueOwnedResource(graphics, startQueue) +Buffer::Buffer(QueueFamilyMapping mapping, QueueType startQueue) + : QueueOwnedResource(mapping, startQueue) { } @@ -136,31 +155,32 @@ Buffer::~Buffer() { } -UniformBuffer::UniformBuffer(PGraphics graphics, QueueType startQueueType) - : Buffer(graphics, startQueueType) +UniformBuffer::UniformBuffer(QueueFamilyMapping mapping, QueueType startQueueType) + : Buffer(mapping, startQueueType) { } UniformBuffer::~UniformBuffer() { } -StructuredBuffer::StructuredBuffer(PGraphics graphics, QueueType startQueueType) - : Buffer(graphics, startQueueType) +StructuredBuffer::StructuredBuffer(QueueFamilyMapping mapping, QueueType startQueueType) + : Buffer(mapping, startQueueType) { } StructuredBuffer::~StructuredBuffer() { } -VertexBuffer::VertexBuffer(PGraphics graphics, uint32 numVertices, uint32 vertexSize, QueueType startQueueType) - : Buffer(graphics, startQueueType) - , numVertices(numVertices), vertexSize(vertexSize) +VertexBuffer::VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType) + : Buffer(mapping, startQueueType) + , numVertices(numVertices) + , vertexSize(vertexSize) { } VertexBuffer::~VertexBuffer() { } -IndexBuffer::IndexBuffer(PGraphics graphics, uint32 size, Gfx::SeIndexType indexType, QueueType startQueueType) - : Buffer(graphics, startQueueType) +IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint32 size, Gfx::SeIndexType indexType, QueueType startQueueType) + : Buffer(mapping, startQueueType) , indexType(indexType) { switch (indexType) @@ -179,8 +199,8 @@ IndexBuffer::~IndexBuffer() } VertexStream::VertexStream() {} -VertexStream::VertexStream(uint32 stride, uint32 offset, uint8 instanced, Gfx::PVertexBuffer vertexBuffer) - : stride(stride), instanced(instanced), offset(offset), vertexBuffer(vertexBuffer) +VertexStream::VertexStream(uint32 stride, uint32 offset, uint8 instanced) + : stride(stride), instanced(instanced), offset(offset) { } VertexStream::~VertexStream() @@ -200,19 +220,19 @@ VertexDeclaration::VertexDeclaration() VertexDeclaration::~VertexDeclaration() { } -uint32 VertexDeclaration::addVertexStream(const VertexStream &element) +uint32 VertexDeclaration::addVertexStream(const VertexStreamComponent &element) { - uint32 currIndex = vertexStreams.size(); - vertexStreams.add(element); - return currIndex; + VertexStream& stream = vertexStreams.add(); + stream.addVertexElement(VertexElement(element.streamOffset, element.type, element.offset)); + return stream.vertexDescription.size() - 1; } const Array &VertexDeclaration::getVertexStreams() const { return vertexStreams; } -Texture::Texture(PGraphics graphics, Gfx::QueueType startQueueType) - : QueueOwnedResource(graphics, startQueueType) +Texture::Texture(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) + : QueueOwnedResource(mapping, startQueueType) { } @@ -220,8 +240,8 @@ Texture::~Texture() { } -Texture2D::Texture2D(PGraphics graphics, Gfx::QueueType startQueueType) - : Texture(graphics, startQueueType) +Texture2D::Texture2D(QueueFamilyMapping mapping, Gfx::QueueType startQueueType) + : Texture(mapping, startQueueType) { } diff --git a/src/Engine/Graphics/GraphicsResources.h b/src/Engine/Graphics/GraphicsResources.h index 335b04c..ee25e52 100644 --- a/src/Engine/Graphics/GraphicsResources.h +++ b/src/Engine/Graphics/GraphicsResources.h @@ -6,13 +6,16 @@ #include "MeshBatch.h" #include -#ifdef _DEBUG #define ENABLE_VALIDATION + +#ifdef DEBUG #endif namespace Seele { struct VertexInputStream; +struct VertexStreamComponent; +class VertexInputType; namespace Gfx { DECLARE_REF(Graphics); @@ -111,7 +114,7 @@ struct PermutationId struct ShaderCollection { PermutationId id; - PVertexDeclaration vertexDeclaration; + //PVertexDeclaration vertexDeclaration; PVertexShader vertexShader; PControlShader controlShader; PEvaluationShader evalutionShader; @@ -128,7 +131,7 @@ public: PGraphics graphics, RenderPassType passName, PMaterial material, - PVertexShaderInput vertexInput, + VertexInputType* vertexInput, bool bPositionOnly); private: Array shaders; @@ -272,7 +275,7 @@ struct QueueFamilyMapping class QueueOwnedResource { public: - QueueOwnedResource(PGraphics graphics, QueueType startQueueType); + QueueOwnedResource(QueueFamilyMapping mapping, QueueType startQueueType); virtual ~QueueOwnedResource(); //Preliminary checks to see if the barrier should be executed at all @@ -281,14 +284,20 @@ public: protected: virtual void executeOwnershipBarrier(QueueType newOwner) = 0; Gfx::QueueType currentOwner; - PGraphics graphics; + QueueFamilyMapping mapping; }; DEFINE_REF(QueueOwnedResource); +// IMPORTANT!! +// WHEN DERIVING FROM ANY Gfx:: BASE CLASSES WITH MULTIPLE INHERITANCE +// ALWAYS PUT THE Gfx:: BASE CLASS FIRST +// This is because the refcounting object is unique per allocation, so +// the base address of both the Gfx:: and the implementation class +// need to match for it to work class Buffer : public QueueOwnedResource { public: - Buffer(PGraphics graphics, QueueType startQueueType); + Buffer(QueueFamilyMapping mapping, QueueType startQueueType); virtual ~Buffer(); protected: @@ -299,7 +308,7 @@ protected: class UniformBuffer : public Buffer { public: - UniformBuffer(PGraphics graphics, QueueType startQueueType); + UniformBuffer(QueueFamilyMapping mapping, QueueType startQueueType); virtual ~UniformBuffer(); protected: // Inherited via QueueOwnedResource @@ -310,7 +319,7 @@ DEFINE_REF(UniformBuffer); class VertexBuffer : public Buffer { public: - VertexBuffer(PGraphics graphics, uint32 numVertices, uint32 vertexSize, QueueType startQueueType); + VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType); virtual ~VertexBuffer(); inline uint32 getNumVertices() { @@ -333,7 +342,7 @@ DEFINE_REF(VertexBuffer); class IndexBuffer : public Buffer { public: - IndexBuffer(PGraphics graphics, uint32 size, Gfx::SeIndexType index, QueueType startQueueType); + IndexBuffer(QueueFamilyMapping mapping, uint32 size, Gfx::SeIndexType index, QueueType startQueueType); virtual ~IndexBuffer(); inline uint32 getNumIndices() const { @@ -355,7 +364,7 @@ DEFINE_REF(IndexBuffer); class StructuredBuffer : public Buffer { public: - StructuredBuffer(PGraphics graphics, QueueType startQueueType); + StructuredBuffer(QueueFamilyMapping mapping, QueueType startQueueType); virtual ~StructuredBuffer(); protected: // Inherited via QueueOwnedResource @@ -367,7 +376,7 @@ class VertexStream { public: VertexStream(); - VertexStream(uint32 stride, uint32 offset, uint8 instanced, Gfx::PVertexBuffer vertexBuffer); + VertexStream(uint32 stride, uint32 offset, uint8 instanced); ~VertexStream(); void addVertexElement(VertexElement element); const Array getVertexDescriptions() const; @@ -377,7 +386,6 @@ public: uint32 offset; Array vertexDescription; uint8 instanced; - PVertexBuffer vertexBuffer; }; DEFINE_REF(VertexStream); class VertexDeclaration @@ -385,7 +393,7 @@ class VertexDeclaration public: VertexDeclaration(); ~VertexDeclaration(); - uint32 addVertexStream(const VertexStream &vertexStream); + uint32 addVertexStream(const VertexStreamComponent &vertexStream); const Array &getVertexStreams() const; private: @@ -404,10 +412,17 @@ protected: GraphicsPipelineCreateInfo createInfo; }; DEFINE_REF(GraphicsPipeline); + +// IMPORTANT!! +// WHEN DERIVING FROM ANY Gfx:: BASE CLASSES WITH MULTIPLE INHERITANCE +// ALWAYS PUT THE Gfx:: BASE CLASS FIRST +// This is because the refcounting object is unique per allocation, so +// the base address of both the Gfx:: and the implementation class +// need to match for it to work class Texture : public QueueOwnedResource { public: - Texture(PGraphics graphics, QueueType startQueueType); + Texture(QueueFamilyMapping mapping, QueueType startQueueType); virtual ~Texture(); virtual SeFormat getFormat() const = 0; @@ -422,7 +437,7 @@ DEFINE_REF(Texture); class Texture2D : public Texture { public: - Texture2D(PGraphics graphics, QueueType startQueueType); + Texture2D(QueueFamilyMapping mapping, QueueType startQueueType); virtual ~Texture2D(); virtual SeFormat getFormat() const = 0; diff --git a/src/Engine/Graphics/Mesh.cpp b/src/Engine/Graphics/Mesh.cpp index 63b6414..3e75848 100644 --- a/src/Engine/Graphics/Mesh.cpp +++ b/src/Engine/Graphics/Mesh.cpp @@ -2,8 +2,8 @@ using namespace Seele; -Mesh::Mesh(MeshDescription description, Gfx::PIndexBuffer indexBuffer) - : description(description) +Mesh::Mesh(PVertexShaderInput vertexInput, Gfx::PIndexBuffer indexBuffer) + : vertexInput(vertexInput) , indexBuffer(indexBuffer) { } diff --git a/src/Engine/Graphics/Mesh.h b/src/Engine/Graphics/Mesh.h index 9c94603..291bc09 100644 --- a/src/Engine/Graphics/Mesh.h +++ b/src/Engine/Graphics/Mesh.h @@ -4,7 +4,7 @@ namespace Seele { -#define MAX_TEX_CHANNELS 8 +/*#define MAX_TEX_CHANNELS 8 struct MeshDescription { Array layout; @@ -41,23 +41,22 @@ struct MeshDescription ar & layout; //TODO declaration } -}; +};*/ DECLARE_REF(MaterialAsset); class Mesh { public: - Mesh(MeshDescription description, Gfx::PIndexBuffer indexBuffer); + Mesh(PVertexShaderInput vertexInput, Gfx::PIndexBuffer indexBuffer); ~Mesh(); Gfx::PIndexBuffer indexBuffer; - MeshDescription description; + PVertexShaderInput vertexInput; PMaterialAsset referencedMaterial; private: friend class boost::serialization::access; template void serialize(Archive& ar, const unsigned int version) { - ar & description; ar & referencedMaterial->getFullPath(); //TODO: } diff --git a/src/Engine/Graphics/RenderCore.cpp b/src/Engine/Graphics/RenderCore.cpp index 3c8d3e8..1c4e728 100644 --- a/src/Engine/Graphics/RenderCore.cpp +++ b/src/Engine/Graphics/RenderCore.cpp @@ -12,21 +12,6 @@ Seele::RenderCore::~RenderCore() void Seele::RenderCore::init() { - WindowCreateInfo mainWindowInfo; - mainWindowInfo.title = "SeeleEngine"; - mainWindowInfo.width = 1280; - mainWindowInfo.height = 720; - mainWindowInfo.bFullscreen = false; - mainWindowInfo.numSamples = 1; - mainWindowInfo.pixelFormat = Gfx::SE_FORMAT_R8G8B8_UNORM; - auto window = windowManager->addWindow(mainWindowInfo); - ViewportCreateInfo sceneViewInfo; - sceneViewInfo.sizeX = 1280; - sceneViewInfo.sizeY = 720; - sceneViewInfo.offsetX = 0; - sceneViewInfo.offsetY = 0; - PSceneView sceneView = new SceneView(windowManager->getGraphics(), window, sceneViewInfo); - window->addView(sceneView); } void Seele::RenderCore::renderLoop() @@ -34,6 +19,7 @@ void Seele::RenderCore::renderLoop() while (windowManager->isActive()) { windowManager->beginFrame(); + windowManager->render(); windowManager->endFrame(); } } diff --git a/src/Engine/Graphics/RenderCore.h b/src/Engine/Graphics/RenderCore.h index 45498d4..7ac4157 100644 --- a/src/Engine/Graphics/RenderCore.h +++ b/src/Engine/Graphics/RenderCore.h @@ -12,6 +12,7 @@ public: void renderLoop(); void shutdown(); + PWindowManager getWindowManager() const { return windowManager; }; private: PScene scene; PWindowManager windowManager; diff --git a/src/Engine/Graphics/RenderMaterial.cpp b/src/Engine/Graphics/RenderMaterial.cpp new file mode 100644 index 0000000..8b07183 --- /dev/null +++ b/src/Engine/Graphics/RenderMaterial.cpp @@ -0,0 +1,4 @@ +#include "RenderMaterial.h" + +using namespace Seele; +using namespace Seele::Gfx; \ No newline at end of file diff --git a/src/Engine/Graphics/RenderMaterial.h b/src/Engine/Graphics/RenderMaterial.h new file mode 100644 index 0000000..04d992a --- /dev/null +++ b/src/Engine/Graphics/RenderMaterial.h @@ -0,0 +1,44 @@ +#pragma once +#include "GraphicsResources.h" + +namespace Seele +{ +namespace Gfx +{ +class MaterialShaderMap;//TODO implement +class MaterialRenderContext; +struct UniformExpressionCache +{ + Gfx::PUniformBuffer uniformBuffer; + uint8 bUpToDate; + + const MaterialShaderMap* cachedUniformExpressionShaderMap; +}; +class Material; +class RenderMaterial +{ +public: + mutable UniformExpressionCache uniformExpressionCache; + RenderMaterial(); + virtual ~RenderMaterial(); + + void evaluateUniformExpressions(UniformExpressionCache& outUniforExpressionCache, const MaterialRenderContext& context); + + void cacheUniformExpressions(bool bRecreatueUniformBuffer); + + void invalidateUniformExpressionCache(bool bRecreateUniformBuffer); + + void updateUniformExpressionCacheIfNeeded() const; + + const Material* getMaterial() const + { + const RenderMaterial* unused = nullptr; + return &getMaterialWithFallback(unused); + } + + virtual const Material& getMaterialWithFallback(const RenderMaterial*& outFallbackRenderMaterial) const = 0; + + virtual Material* getMaterialNoFallback() const { return nullptr; } +}; +} // namespace Gfx +} // namespace Seele diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index b77ed71..5832edd 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -27,7 +27,8 @@ void BasePassMeshProcessor::addMeshBatch( //TODO query tesselation - const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput); + const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType()); + assert(collection != nullptr); Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); buildMeshDrawCommand(batch, primitiveComponent, @@ -79,12 +80,9 @@ void BasePass::render() { processor->clearCommands(); graphics->beginRenderPass(renderPass); - for (auto &&primitive : scene->getPrimitives()) + for (auto &&primitive : scene->getStaticMeshes()) { - for (auto &&meshBatch : primitive->staticMeshes) - { - processor->addMeshBatch(meshBatch, primitive, renderPass); - } + processor->addMeshBatch(primitive, nullptr, renderPass); } graphics->executeCommands(processor->getRenderCommands()); graphics->endRenderPass(); diff --git a/src/Engine/Graphics/SceneRenderPath.cpp b/src/Engine/Graphics/SceneRenderPath.cpp index 6b384cc..1703590 100644 --- a/src/Engine/Graphics/SceneRenderPath.cpp +++ b/src/Engine/Graphics/SceneRenderPath.cpp @@ -5,14 +5,11 @@ using namespace Seele; -SceneRenderPath::SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target) +SceneRenderPath::SceneRenderPath(PScene scene, Gfx::PGraphics graphics, Gfx::PViewport target) : RenderPath(graphics, target) - , basePass(new BasePass(scene, graphics, target)) + , scene(scene) { - scene = new Scene(); - PMeshAsset asset = AssetRegistry::findMesh("Unbenannt"); - PActor rootActor = new Actor(); - PPrimitiveComponent primitiveComponent = new PrimitiveComponent(); + basePass = new BasePass(scene, graphics, target); } SceneRenderPath::~SceneRenderPath() diff --git a/src/Engine/Graphics/SceneRenderPath.h b/src/Engine/Graphics/SceneRenderPath.h index 58658a4..f1a11ba 100644 --- a/src/Engine/Graphics/SceneRenderPath.h +++ b/src/Engine/Graphics/SceneRenderPath.h @@ -8,7 +8,7 @@ DECLARE_REF(Scene); class SceneRenderPath : public RenderPath { public: - SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target); + SceneRenderPath(PScene scene, Gfx::PGraphics graphics, Gfx::PViewport target); virtual ~SceneRenderPath(); void setTargetScene(PScene scene); virtual void init(); diff --git a/src/Engine/Graphics/SceneView.cpp b/src/Engine/Graphics/SceneView.cpp index 99b099d..bc4c6d2 100644 --- a/src/Engine/Graphics/SceneView.cpp +++ b/src/Engine/Graphics/SceneView.cpp @@ -8,7 +8,8 @@ using namespace Seele; Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo) : View(graphics, owner, createInfo) { - renderer = new SceneRenderPath(graphics, viewport); + scene = new Scene(graphics); + renderer = new SceneRenderPath(scene, graphics, viewport); } Seele::SceneView::~SceneView() diff --git a/src/Engine/Graphics/SceneView.h b/src/Engine/Graphics/SceneView.h index 57f1c77..0fdd8c5 100644 --- a/src/Engine/Graphics/SceneView.h +++ b/src/Engine/Graphics/SceneView.h @@ -2,11 +2,15 @@ #include "View.h" namespace Seele { +DECLARE_REF(Scene); class SceneView : public View { public: SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo); ~SceneView(); + PScene getScene() const { return scene; } +private: + PScene scene; }; DEFINE_REF(SceneView); } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/ShaderCompiler.cpp b/src/Engine/Graphics/ShaderCompiler.cpp new file mode 100644 index 0000000..7e2154c --- /dev/null +++ b/src/Engine/Graphics/ShaderCompiler.cpp @@ -0,0 +1,27 @@ +#include "ShaderCompiler.h" +#include "Material/Material.h" +#include "VertexShaderInput.h" + +using namespace Seele; +using namespace Seele::Gfx; + +ShaderCompiler::ShaderCompiler(PGraphics graphics) + : graphics(graphics) +{ + +} + +ShaderCompiler::~ShaderCompiler() +{ + +} + +void ShaderCompiler::registerMaterial(PMaterial material) +{ + for(auto type : VertexInputType::getTypeList()) + { + material->createShaders(graphics, Gfx::RenderPassType::DepthPrepass, type); + material->createShaders(graphics, Gfx::RenderPassType::BasePass, type); + } +} + diff --git a/src/Engine/Graphics/ShaderCompiler.h b/src/Engine/Graphics/ShaderCompiler.h new file mode 100644 index 0000000..65a5e3c --- /dev/null +++ b/src/Engine/Graphics/ShaderCompiler.h @@ -0,0 +1,22 @@ +#pragma once +#include "GraphicsResources.h" + +namespace Seele +{ +DECLARE_REF(Material); +DECLARE_NAME_REF(Gfx, Graphics); +namespace Gfx +{ +class ShaderCompiler +{ +public: + ShaderCompiler(PGraphics graphics); + ~ShaderCompiler(); + void registerMaterial(PMaterial material); +private: + Array pendingCompiles; + PGraphics graphics; +}; +DEFINE_REF(ShaderCompiler); +} // namespace Gfx +} // namespace Seele \ No newline at end of file diff --git a/src/Engine/Graphics/StaticMeshVertexInput.cpp b/src/Engine/Graphics/StaticMeshVertexInput.cpp new file mode 100644 index 0000000..c191606 --- /dev/null +++ b/src/Engine/Graphics/StaticMeshVertexInput.cpp @@ -0,0 +1,48 @@ +#include "StaticMeshVertexInput.h" + +using namespace Seele; + +StaticMeshVertexInput::StaticMeshVertexInput(std::string name) + : VertexShaderInput(name) +{ + +} + +StaticMeshVertexInput::~StaticMeshVertexInput() +{ + +} + +void StaticMeshVertexInput::setPositionStream(const VertexStreamComponent& positionStream) +{ + declaration->addVertexStream(positionStream); + positionDeclaration->addVertexStream(positionStream); + data.positionStream = positionStream; +} + +void StaticMeshVertexInput::setTangentXStream(const VertexStreamComponent& tangentXStream) +{ + declaration->addVertexStream(tangentXStream); + data.tangentBasisComponents[0] = tangentXStream; +} + +void StaticMeshVertexInput::setTangentZStream(const VertexStreamComponent& tangentZStream) +{ + declaration->addVertexStream(tangentZStream); + data.tangentBasisComponents[1] = tangentZStream; +} + +void StaticMeshVertexInput::setTexCoordStream(uint32 index, const VertexStreamComponent& textureStream) +{ + //TODO: replace add with proper indexing + declaration->addVertexStream(textureStream); + data.textureCoordinates.add(textureStream); +} + +void StaticMeshVertexInput::setColorStream(const VertexStreamComponent& colorStream) +{ + declaration->addVertexStream(colorStream); + data.colorComponent = colorStream; +} + +IMPLEMENT_VERTEX_INPUT_TYPE(StaticMeshVertexInput, "StaticMeshVertexInput"); \ No newline at end of file diff --git a/src/Engine/Graphics/StaticMeshVertexInput.h b/src/Engine/Graphics/StaticMeshVertexInput.h new file mode 100644 index 0000000..7ea8c9d --- /dev/null +++ b/src/Engine/Graphics/StaticMeshVertexInput.h @@ -0,0 +1,32 @@ +#pragma once +#include "VertexShaderInput.h" + +namespace Seele +{ +enum { MAX_TEXCOORDS = 4 }; +struct StaticMeshDataType +{ + VertexStreamComponent positionStream; + VertexStreamComponent tangentBasisComponents[2]; + + //Dont forget these are 4 component vectors + Array textureCoordinates; + + VertexStreamComponent colorComponent; +}; +class StaticMeshVertexInput : public VertexShaderInput +{ + DECLARE_VERTEX_INPUT_TYPE(StaticMeshVertexInput); +public: + StaticMeshVertexInput(std::string name); + virtual ~StaticMeshVertexInput(); + void setPositionStream(const VertexStreamComponent& positionStream); + void setTangentXStream(const VertexStreamComponent& tangentXStream); + void setTangentZStream(const VertexStreamComponent& tangentZStream); + void setTexCoordStream(uint32 index, const VertexStreamComponent& textureStream); + void setColorStream(const VertexStreamComponent& colorStream); +private: + StaticMeshDataType data; +}; +DEFINE_REF(StaticMeshVertexInput); +} \ No newline at end of file diff --git a/src/Engine/Graphics/VertexShaderInput.cpp b/src/Engine/Graphics/VertexShaderInput.cpp index f1991ed..299eb6c 100644 --- a/src/Engine/Graphics/VertexShaderInput.cpp +++ b/src/Engine/Graphics/VertexShaderInput.cpp @@ -5,49 +5,64 @@ using namespace Seele; -List VertexShaderInput::registeredInputs; -std::mutex VertexShaderInput::registeredInputsLock; +List VertexInputType::globalTypeList; + +List VertexInputType::getTypeList() +{ + return globalTypeList; +} + +VertexInputType* VertexInputType::getVertexInputByName(const std::string& name) +{ + for(auto type : globalTypeList) + { + if(name.compare(type->getName()) == 0) + { + return type; + } + } + return nullptr; +} + +VertexInputType::VertexInputType(const char* name, + const char* shaderFilename) + : name(name) + , shaderFilename(shaderFilename) +{ + globalTypeList.add(this); +} + +VertexInputType::~VertexInputType() +{ + globalTypeList.remove(globalTypeList.find(this)); +} + +const char* VertexInputType::getName() +{ + return name; +} + +const char* VertexInputType::getShaderFilename() +{ + return shaderFilename; +} VertexShaderInput::VertexShaderInput(std::string name) : name(name) { - std::scoped_lock lock(registeredInputsLock); - registeredInputs.add(this); -} - -VertexShaderInput::VertexShaderInput(MeshDescription description, std::string name) - : declaration(description.declaration) - , layout(description.layout) - , name(name) -{ - auto declStreams = declaration->getVertexStreams(); - std::copy(declStreams.begin(), declStreams.end(), streams.begin()); - - uint32 positionStreamIndex = 0; + declaration = new Gfx::VertexDeclaration(); positionDeclaration = new Gfx::VertexDeclaration(); - for (uint32 i = 0; i < declStreams.size(); i++) - { - if(description.layout[i] == Gfx::VertexAttribute::POSITION) - { - positionStreams[positionStreamIndex++] = declStreams[i]; - positionDeclaration->addVertexStream(declStreams[i]); - } - } - - std::scoped_lock lock(registeredInputsLock); - registeredInputs.add(this); } VertexShaderInput::~VertexShaderInput() { - registeredInputs.remove(registeredInputs.find(this)); } void VertexShaderInput::getStreams(VertexInputStreamArray& outVertexStreams) const { for(uint32 i = 0; i < streams.size(); ++i) { - const Gfx::VertexStream& stream = streams[i]; + const VertexInputStream& stream = streams[i]; if(stream.vertexBuffer == nullptr) { outVertexStreams.add(VertexInputStream(i, 0, nullptr)); @@ -63,7 +78,7 @@ void VertexShaderInput::getPositionOnlyStream(VertexInputStreamArray& outVertexS { for (uint32 i = 0; i < positionStreams.size(); ++i) { - const Gfx::VertexStream& stream = positionStreams[i]; + const VertexInputStream& stream = positionStreams[i]; outVertexStreams.add(VertexInputStream(i, stream.offset, stream.vertexBuffer)); } } \ No newline at end of file diff --git a/src/Engine/Graphics/VertexShaderInput.h b/src/Engine/Graphics/VertexShaderInput.h index d9b2895..3b6b45a 100644 --- a/src/Engine/Graphics/VertexShaderInput.h +++ b/src/Engine/Graphics/VertexShaderInput.h @@ -5,6 +5,7 @@ namespace Seele { +// Minimal vertex source used for building commands struct VertexInputStream { uint32 streamIndex : 4; @@ -35,33 +36,103 @@ struct VertexInputStream return !(*this == rhs); } }; +typedef Array VertexInputStreamArray; //TODO inline allocation + +// Typed data source for a vertex factory +struct VertexStreamComponent +{ + // Source vertex buffer + Gfx::PVertexBuffer vertexBuffer = nullptr; + + // Offset to the start of the vertex buffer fetch + uint32 streamOffset = 0; + + // Offset of the data, relative to the beginnning of each element in the vertex buffer + uint32 offset = 0; + + // Stride of the data + uint32 stride = 0; + + Gfx::SeFormat type = Gfx::SE_FORMAT_UNDEFINED; + + VertexStreamComponent() + {} + + VertexStreamComponent(const Gfx::PVertexBuffer vertexBuffer, uint32 offset, uint32 stride, Gfx::SeFormat type) + : vertexBuffer(vertexBuffer) + , streamOffset(0) + , offset(offset) + , stride(stride) + , type(type) + {} + + VertexStreamComponent(const Gfx::PVertexBuffer vertexBuffer, uint32 streamOffset, uint32 offset, uint32 stride, Gfx::SeFormat type) + : vertexBuffer(vertexBuffer) + , streamOffset(streamOffset) + , offset(offset) + , stride(stride) + , type(type) + {} +}; + +#define STRUCTMEMBER_VERTEXSTREAMCOMPONENT(vertexBuffer, vertexType, member, memberType) \ + VertexStreamComponent(vertexBuffer, offsetof(vertexType, member), sizeof(vertexType), memberType) + +class VertexInputType +{ +public: + static List getTypeList(); + static VertexInputType* getVertexInputByName(const std::string& name); + + VertexInputType( + const char* name, + const char* shaderFilename + ); + virtual ~VertexInputType(); + + const char* getName(); + const char* getShaderFilename(); +private: + const char* name; + const char* shaderFilename; + + static List globalTypeList; +}; + +#define DECLARE_VERTEX_INPUT_TYPE(inputClass) \ + public: \ + static VertexInputType staticType; \ + virtual VertexInputType* getType() const override; + +#define IMPLEMENT_VERTEX_INPUT_TYPE(inputClass, shaderFilename) \ + VertexInputType inputClass::staticType( \ + #inputClass, \ + shaderFilename); \ + VertexInputType* inputClass::getType() const { return &staticType; } -typedef Array VertexInputStreamArray; struct MeshDescription; DECLARE_REF(VertexShaderInput); class VertexShaderInput { public: VertexShaderInput(std::string name); - VertexShaderInput(MeshDescription description, std::string name); - ~VertexShaderInput(); + virtual ~VertexShaderInput(); void getStreams(VertexInputStreamArray& outVertexStreams) const; void getPositionOnlyStream(VertexInputStreamArray& outVertexStreams) const; virtual bool supportsTesselation() { return false; } + virtual VertexInputType* getType() const { return nullptr; } Gfx::PVertexDeclaration getDeclaration() const {return declaration;} Gfx::PVertexDeclaration getPositionDeclaration() const {return positionDeclaration;} std::string getName() const { return name; } - std::string getCode() const { return code; } -private: +protected: static List registeredInputs; static std::mutex registeredInputsLock; Array layout; - StaticArray streams; - StaticArray positionStreams; + StaticArray streams; + StaticArray positionStreams; Gfx::PVertexDeclaration declaration; Gfx::PVertexDeclaration positionDeclaration; std::string name; - std::string code; }; DEFINE_REF(VertexShaderInput); } // namespace Seele diff --git a/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp b/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp index 72d3b75..3f2b954 100644 --- a/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanAllocator.cpp @@ -114,7 +114,7 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice void Allocation::markFree(SubAllocation *allocation) { // Dont free if it is already a free allocation, since they also mark themselves on deletion - if(freeRanges.find(allocation->allocatedOffset) != nullptr) + if (freeRanges.find(allocation->allocatedOffset) != nullptr) { return; } @@ -286,6 +286,8 @@ void StagingManager::clearPending() PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead) { + + std::unique_lock l(lock); for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it) { auto freeBuffer = *it; @@ -296,6 +298,7 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF return freeBuffer; } } + PStagingBuffer stagingBuffer = new StagingBuffer(); VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size); VkDevice vulkanDevice = graphics->getDevice(); @@ -322,11 +325,13 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset()); activeBuffers.add(stagingBuffer.getHandle()); + return stagingBuffer; } void StagingManager::releaseStagingBuffer(PStagingBuffer buffer) { + std::unique_lock l(lock); freeBuffers.add(buffer); activeBuffers.remove(activeBuffers.find(buffer.getHandle())); } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanAllocator.h b/src/Engine/Graphics/Vulkan/VulkanAllocator.h index 609943e..9bbc435 100644 --- a/src/Engine/Graphics/Vulkan/VulkanAllocator.h +++ b/src/Engine/Graphics/Vulkan/VulkanAllocator.h @@ -213,6 +213,7 @@ private: PAllocator allocator; Array freeBuffers; Array activeBuffers; + std::mutex lock; }; DEFINE_REF(StagingManager); } // namespace Vulkan diff --git a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp index c972232..7d5d266 100644 --- a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp @@ -14,9 +14,9 @@ struct PendingBuffer bool bWriteOnly; }; -static Map pendingBuffers; +static Map pendingBuffers; -Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType) +ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType) : graphics(graphics), currentBuffer(0), size(size), currentOwner(queueType) { if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT || @@ -56,21 +56,22 @@ Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::Q info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; } -Buffer::~Buffer() +ShaderBuffer::~ShaderBuffer() { - auto fence = graphics->getQueueCommands(currentOwner)->getCommands()->getFence(); + auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); auto &deletionQueue = graphics->getDeletionQueue(); VkDevice device = graphics->getDevice(); VkBuffer buf[Gfx::numFramesBuffered]; for (uint32 i = 0; i < numBuffers; ++i) { buf[i] = buffers[i].buffer; - deletionQueue.addPendingDelete(fence, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); }); + deletionQueue.addPendingDelete(cmdBuffer, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); }); buffers[i].allocation = nullptr; } + graphics = nullptr; } -void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner) +void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { VkBufferMemoryBarrier barrier = init::BufferMemoryBarrier(); @@ -137,7 +138,7 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner) currentOwner = newOwner; } -void *Buffer::lock(bool bWriteOnly) +void *ShaderBuffer::lock(bool bWriteOnly) { void *data = nullptr; @@ -208,7 +209,7 @@ void *Buffer::lock(bool bWriteOnly) return data; } -void Buffer::unlock() +void ShaderBuffer::unlock() { auto found = pendingBuffers.find(this); if (found != pendingBuffers.end()) @@ -233,8 +234,8 @@ void Buffer::unlock() } UniformBuffer::UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData) - : Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, resourceData.owner) - , Gfx::UniformBuffer(graphics, resourceData.owner) + : Vulkan::ShaderBuffer(graphics, resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, resourceData.owner) + , Gfx::UniformBuffer(graphics->getFamilyMapping(), resourceData.owner) { if (resourceData.data != nullptr) { @@ -251,12 +252,12 @@ UniformBuffer::~UniformBuffer() void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) { Gfx::QueueOwnedResource::transferOwnership(newOwner); - Buffer::currentOwner = newOwner; + Vulkan::ShaderBuffer::currentOwner = newOwner; } void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Buffer::executeOwnershipBarrier(newOwner); + Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } VkAccessFlags UniformBuffer::getSourceAccessMask() @@ -270,8 +271,8 @@ VkAccessFlags UniformBuffer::getDestAccessMask() } StructuredBuffer::StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData) - : Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, resourceData.owner) - , Gfx::StructuredBuffer(graphics, resourceData.owner) + : Vulkan::ShaderBuffer(graphics, resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, resourceData.owner) + , Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.owner) { if (resourceData.data != nullptr) { @@ -292,7 +293,7 @@ void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) void StructuredBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Buffer::executeOwnershipBarrier(newOwner); + Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } VkAccessFlags StructuredBuffer::getSourceAccessMask() @@ -306,8 +307,8 @@ VkAccessFlags StructuredBuffer::getDestAccessMask() } VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData) - : Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner) - , Gfx::VertexBuffer(graphics, resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner) + : Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner) + , Gfx::VertexBuffer(graphics->getFamilyMapping(), resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner) { if (resourceData.resourceData.data != nullptr) { @@ -328,7 +329,7 @@ void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Buffer::executeOwnershipBarrier(newOwner); + Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } VkAccessFlags VertexBuffer::getSourceAccessMask() @@ -342,8 +343,8 @@ VkAccessFlags VertexBuffer::getDestAccessMask() } IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData) - : Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner) - , Gfx::IndexBuffer(graphics, resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner) + : Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner) + , Gfx::IndexBuffer(graphics->getFamilyMapping(), resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner) { if (resourceData.resourceData.data != nullptr) { @@ -364,7 +365,7 @@ void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner) void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner) { - Buffer::executeOwnershipBarrier(newOwner); + Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner); } VkAccessFlags IndexBuffer::getSourceAccessMask() diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp index fee8170..490dee2 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.cpp @@ -22,8 +22,8 @@ CmdBufferBase::~CmdBufferBase() graphics = nullptr; } -CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool) - : CmdBufferBase(graphics, cmdPool), renderPass(nullptr), framebuffer(nullptr), subpassIndex(0) +CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager) + : CmdBufferBase(graphics, cmdPool), renderPass(nullptr), framebuffer(nullptr), subpassIndex(0), manager(manager) { VkCommandBufferAllocateInfo allocInfo = init::CommandBufferAllocateInfo(cmdPool, @@ -120,6 +120,11 @@ PFence CmdBuffer::getFence() return fence; } +PCommandBufferManager CmdBuffer::getManager() +{ + return manager; +} + SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool) : CmdBufferBase(graphics, cmdPool) { @@ -195,8 +200,9 @@ CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue) VK_CHECK(vkCreateCommandPool(graphics->getDevice(), &info, nullptr, &commandPool)); - activeCmdBuffer = new CmdBuffer(graphics, commandPool); + activeCmdBuffer = new CmdBuffer(graphics, commandPool, this); activeCmdBuffer->begin(); + std::lock_guard lock(allocatedBufferLock); allocatedBuffers.add(activeCmdBuffer); } @@ -236,6 +242,7 @@ void CommandBufferManager::submitCommands(PSemaphore signalSemaphore) queue->submitCommandBuffer(activeCmdBuffer); } } + std::lock_guard lock(allocatedBufferLock); for (uint32 i = 0; i < allocatedBuffers.size(); ++i) { PCmdBuffer cmdBuffer = allocatedBuffers[i]; @@ -251,7 +258,7 @@ void CommandBufferManager::submitCommands(PSemaphore signalSemaphore) assert(cmdBuffer->state == CmdBuffer::State::Submitted); } } - activeCmdBuffer = new CmdBuffer(graphics, commandPool); + activeCmdBuffer = new CmdBuffer(graphics, commandPool, this); allocatedBuffers.add(activeCmdBuffer); activeCmdBuffer->begin(); } diff --git a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h index c3b7dc4..faee272 100644 --- a/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h +++ b/src/Engine/Graphics/Vulkan/VulkanCommandBuffer.h @@ -30,10 +30,11 @@ protected: DEFINE_REF(CmdBufferBase); DECLARE_REF(SecondaryCmdBuffer); +DECLARE_REF(CommandBufferManager); class CmdBuffer : public CmdBufferBase { public: - CmdBuffer(PGraphics graphics, VkCommandPool cmdPool); + CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager); virtual ~CmdBuffer(); void begin(); void end(); @@ -43,6 +44,7 @@ public: void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore); void refreshFence(); PFence getFence(); + PCommandBufferManager getManager(); enum State { ReadyBegin, @@ -53,6 +55,7 @@ public: }; private: + PCommandBufferManager manager; PRenderPass renderPass; PFramebuffer framebuffer; PFence fence; @@ -105,6 +108,7 @@ private: PQueue queue; uint32 queueFamilyIndex; PCmdBuffer activeCmdBuffer; + std::mutex allocatedBufferLock; Array allocatedBuffers; }; DEFINE_REF(CommandBufferManager); diff --git a/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp index f8602e6..4c3ef2b 100644 --- a/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanFramebuffer.cpp @@ -49,4 +49,5 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRende Framebuffer::~Framebuffer() { vkDestroyFramebuffer(graphics->getDevice(), handle, nullptr); + graphics = nullptr; } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp index f9f773a..9d70e37 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphics.cpp @@ -64,6 +64,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass) if (found == allocatedFramebuffers.end()) { framebuffer = new Framebuffer(this, rp, rp->getLayout()); + allocatedFramebuffers[framebufferHash] = framebuffer; } else { diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp index 83a4ef1..d250869 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.cpp @@ -23,10 +23,10 @@ QueueOwnedResourceDeletion::~QueueOwnedResourceDeletion() worker.join(); } -void QueueOwnedResourceDeletion::addPendingDelete(PFence fence, std::function func) +void QueueOwnedResourceDeletion::addPendingDelete(PCmdBuffer cmdbuffer, std::function func) { PendingItem item; - item.fence = fence; + item.cmdBuffer = cmdbuffer; item.func = func; deletionQueue.add(item); std::unique_lock lock(mutex); @@ -40,13 +40,12 @@ void QueueOwnedResourceDeletion::run() std::unique_lock lock(mutex); cv.wait(lock); auto entry = deletionQueue.begin(); - PFence fence = entry->fence; - fence->wait(1000ull); - if (fence->isSignaled()) - { - entry->func(); - deletionQueue.remove(entry); - } + PCmdBuffer cmdBuffer = entry->cmdBuffer; + //cmdBuffer->getManager()->waitForCommands(cmdBuffer); + //cmdBuffer->begin(); + + //entry->func(); + deletionQueue.remove(entry); } } diff --git a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h index 6b39768..7c3c7c9 100644 --- a/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h +++ b/src/Engine/Graphics/Vulkan/VulkanGraphicsResources.h @@ -10,6 +10,7 @@ namespace Vulkan DECLARE_REF(DescriptorAllocator); DECLARE_REF(CommandBufferManager); +DECLARE_REF(CmdBuffer); DECLARE_REF(Graphics); DECLARE_REF(SubAllocation); class Semaphore @@ -57,7 +58,7 @@ class QueueOwnedResourceDeletion public: QueueOwnedResourceDeletion(); virtual ~QueueOwnedResourceDeletion(); - static void addPendingDelete(PFence fence, std::function function); + static void addPendingDelete(PCmdBuffer fence, std::function function); private: std::thread worker; @@ -65,7 +66,7 @@ private: static void run(); struct PendingItem { - PFence fence; + PCmdBuffer cmdBuffer; std::function func; }; static std::mutex mutex; @@ -73,11 +74,11 @@ private: static List deletionQueue; }; -class Buffer +class ShaderBuffer { public: - Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType); - virtual ~Buffer(); + ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType); + virtual ~ShaderBuffer(); VkBuffer getHandle() const { return buffers[currentBuffer].buffer; @@ -108,9 +109,9 @@ protected: virtual VkAccessFlags getSourceAccessMask() = 0; virtual VkAccessFlags getDestAccessMask() = 0; }; -DEFINE_REF(Buffer); +DEFINE_REF(ShaderBuffer); -class UniformBuffer : public Buffer, public Gfx::UniformBuffer +class UniformBuffer : public Gfx::UniformBuffer, public ShaderBuffer { public: UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData); @@ -126,7 +127,7 @@ protected: }; DEFINE_REF(UniformBuffer); -class StructuredBuffer : public Buffer, public Gfx::StructuredBuffer +class StructuredBuffer : public Gfx::StructuredBuffer, public ShaderBuffer { public: StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData); @@ -142,7 +143,7 @@ protected: }; DEFINE_REF(StructuredBuffer); -class VertexBuffer : public Buffer, public Gfx::VertexBuffer +class VertexBuffer : public Gfx::VertexBuffer, public ShaderBuffer { public: VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData); @@ -158,7 +159,7 @@ protected: }; DEFINE_REF(VertexBuffer); -class IndexBuffer : public Buffer, public Gfx::IndexBuffer +class IndexBuffer : public Gfx::IndexBuffer, public ShaderBuffer { public: IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData); @@ -249,7 +250,7 @@ protected: }; DEFINE_REF(TextureBase); -class Texture2D : public TextureBase, public Gfx::Texture2D +class Texture2D : public Gfx::Texture2D, public TextureBase { public: Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE); diff --git a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp index 31675e9..34332b3 100644 --- a/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanPipelineCache.cpp @@ -242,7 +242,6 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo 0 ); - createInfo.pStages = stageInfos; createInfo.pVertexInputState = &vertexInput; createInfo.pInputAssemblyState = &assemblyInfo; diff --git a/src/Engine/Graphics/Vulkan/VulkanShader.cpp b/src/Engine/Graphics/Vulkan/VulkanShader.cpp index 53edce7..82cdb02 100644 --- a/src/Engine/Graphics/Vulkan/VulkanShader.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanShader.cpp @@ -55,7 +55,6 @@ void Shader::create(const ShaderCreateInfo& createInfo) 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) @@ -67,15 +66,20 @@ void Shader::create(const ShaderCreateInfo& createInfo) code.data() ); } + for(auto define : createInfo.defines) + { + spAddPreprocessorDefine(request, define.key, define.value); + } spAddSearchPath(request, "shaders/lib/"); + spAddSearchPath(request, "shaders/generated/"); spSetGlobalGenericArgs(request, createInfo.typeParameter.size(), createInfo.typeParameter.data()); int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type)); if(spCompile(request)) { - char const* diagnostice = spGetDiagnosticOutput(request); - std::cout << diagnostice << std::endl; + char const* diagnostics = spGetDiagnosticOutput(request); + std::cout << diagnostics << std::endl; } ShaderReflection* reflection = slang::ShaderReflection::get(request); diff --git a/src/Engine/Graphics/Vulkan/VulkanTexture.cpp b/src/Engine/Graphics/Vulkan/VulkanTexture.cpp index 593ed43..3b20a69 100644 --- a/src/Engine/Graphics/Vulkan/VulkanTexture.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanTexture.cpp @@ -154,12 +154,12 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType, TextureHandle::~TextureHandle() { auto &deletionQueue = graphics->getDeletionQueue(); - auto fence = graphics->getQueueCommands(currentOwner)->getCommands()->getFence(); + auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands(); VkDevice device = graphics->getDevice(); VkImageView view = defaultView; VkImage img = image; - deletionQueue.addPendingDelete(fence, [device, view]() { vkDestroyImageView(device, view, nullptr); }); - deletionQueue.addPendingDelete(fence, [device, img]() { vkDestroyImage(device, img, nullptr); }); + deletionQueue.addPendingDelete(cmdBuffer, [device, view]() { vkDestroyImageView(device, view, nullptr); }); + deletionQueue.addPendingDelete(cmdBuffer, [device, img]() { vkDestroyImage(device, img, nullptr); }); } void TextureHandle::changeLayout(VkImageLayout newLayout) @@ -243,7 +243,7 @@ void TextureBase::changeLayout(VkImageLayout newLayout) } Texture2D::Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage) - : Gfx::Texture2D(graphics, createInfo.resourceData.owner) + : Gfx::Texture2D(graphics->getFamilyMapping(), createInfo.resourceData.owner) { textureHandle = new TextureHandle(graphics, createInfo.bArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D, createInfo, existingImage); diff --git a/src/Engine/Graphics/WindowManager.cpp b/src/Engine/Graphics/WindowManager.cpp index 891d7ce..457de35 100644 --- a/src/Engine/Graphics/WindowManager.cpp +++ b/src/Engine/Graphics/WindowManager.cpp @@ -42,6 +42,14 @@ void Seele::WindowManager::beginFrame() } } +void WindowManager::render() +{ + for(auto window : windows) + { + window->render(); + } +} + void Seele::WindowManager::endFrame() { for (auto window : windows) diff --git a/src/Engine/Graphics/WindowManager.h b/src/Engine/Graphics/WindowManager.h index b2235b5..ceab37d 100644 --- a/src/Engine/Graphics/WindowManager.h +++ b/src/Engine/Graphics/WindowManager.h @@ -13,6 +13,7 @@ public: ~WindowManager(); PWindow addWindow(const WindowCreateInfo &createInfo); void beginFrame(); + void render(); void endFrame(); static Gfx::PGraphics getGraphics() { diff --git a/src/Engine/Material/BRDF.cpp b/src/Engine/Material/BRDF.cpp new file mode 100644 index 0000000..72bcf12 --- /dev/null +++ b/src/Engine/Material/BRDF.cpp @@ -0,0 +1,132 @@ +#include "BRDF.h" +#include +#include +#include + +using namespace Seele; +using json = nlohmann::json; + +List BRDF::globalBRDFList; + +BRDF::BRDF(const char* name) + : name(name) +{ + globalBRDFList.add(this); +} + +BRDF::~BRDF() +{ + globalBRDFList.remove(globalBRDFList.find(this)); +} + + +BRDF* BRDF::getBRDFByName(const std::string& name) +{ + for(auto brdf : globalBRDFList) + { + if(name.compare(brdf->name) == 0) + { + return brdf; + } + } + return nullptr; +} + +List BRDF::getBRDFList() +{ + return globalBRDFList; +} + +BlinnPhong::BlinnPhong(const char* name) + : BRDF(name) +{ +} + +BlinnPhong::~BlinnPhong() +{ +} + +void BlinnPhong::generateMaterialCode(std::ofstream& codeStream, json codeJson) +{ + std::stringstream accessorStream; + + auto generateAccessor = [codeJson](std::stringstream& accessorStream, const std::string& key, const std::string& defaultVal) + { + if(codeJson.contains(key)) + { + for(auto code : codeJson[key].items()) + { + accessorStream << code.value().get() << ";" << std::endl; + } + } + else + { + accessorStream << "return " << defaultVal << ";"; + } + + }; + accessorStream << "float3 getBaseColor(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "baseColor", "float3(0, 0, 0)"); + accessorStream << "}"; + + accessorStream << "float getMetallic(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "metallic", "0.f"); + accessorStream << "}"; + + accessorStream << "float3 getNormal(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "normal", "float3(0, 1, 0)"); + accessorStream << "}"; + + accessorStream << "float getSpecular(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "specular", "0.f"); + accessorStream << "}"; + + accessorStream << "float getRoughness(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "roughness", "0.f"); + accessorStream << "}"; + + accessorStream << "float getSheen(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "sheen", "0.f"); + accessorStream << "}"; + + /*accessorStream << "float getSpecularTint(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "specularTint", "0.f"); + accessorStream << "}"; + + accessorStream << "float getAnisotropic(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "anisotropic", "0.f"); + accessorStream << "}"; + + + accessorStream << "float getSheenTint(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "sheenTint", "0.f"); + accessorStream << "}"; + + accessorStream << "float getClearCoat(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "clearCoat", "0.f"); + accessorStream << "}"; + + accessorStream << "float getClearCoatGloss(MaterialFragmentParameter input) {\n"; + generateAccessor(accessorStream, "clearCoatGloss", "0.f"); + accessorStream << "}";*/ + + accessorStream << "float3 getWorldOffset() {\n"; + generateAccessor(accessorStream, "worldOffset", "0.f"); + accessorStream << "}"; + + codeStream << accessorStream.str(); + + codeStream << "typedef " << name << " BRDF;" << std::endl; + codeStream << name << " prepare(MaterialFragmentParameter geometry){" << std::endl; + codeStream << name << " result;" << std::endl; + codeStream << "result.baseColor = getBaseColor(geometry);" << std::endl; + codeStream << "result.metallic = getMetallic(geometry);" << std::endl; + codeStream << "result.normal = geometry.transformNormalTexture(getNormal(geometry));" << std::endl; + codeStream << "result.specular = getSpecular(geometry);" << std::endl; + codeStream << "result.roughness = getRoughness(geometry);" << std::endl; + codeStream << "result.sheen = getSheen(geometry);" << std::endl; + codeStream << "return result;" << std::endl; + codeStream << "}" << std::endl; +} + +IMPLEMENT_BRDF(BlinnPhong); \ No newline at end of file diff --git a/src/Engine/Material/BRDF.h b/src/Engine/Material/BRDF.h new file mode 100644 index 0000000..174b9cf --- /dev/null +++ b/src/Engine/Material/BRDF.h @@ -0,0 +1,39 @@ +#pragma once +#include "MinimalEngine.h" +#include "Containers/List.h" +#include + +namespace Seele +{ +class BRDF +{ +public: + static BRDF* getBRDFByName(const std::string& name); + static List getBRDFList(); + + virtual void generateMaterialCode(std::ofstream& codeStream, nlohmann::json codeJson) = 0; +protected: + BRDF(const char* name); + virtual ~BRDF(); + static List globalBRDFList; + const char* name; +}; + +#define DECLARE_BRDF(inputClass) \ + public: \ + static inputClass staticType; + +#define IMPLEMENT_BRDF(inputClass) \ + inputClass inputClass::staticType( \ + #inputClass); + +class BlinnPhong : public BRDF +{ + DECLARE_BRDF(BlinnPhong); +public: + virtual void generateMaterialCode(std::ofstream& codeStream, nlohmann::json codeJson); +protected: + BlinnPhong(const char* name); + virtual ~BlinnPhong(); +}; +} // namespace Seele diff --git a/src/Engine/Material/CMakeLists.txt b/src/Engine/Material/CMakeLists.txt index 54d19d0..4ebfe39 100644 --- a/src/Engine/Material/CMakeLists.txt +++ b/src/Engine/Material/CMakeLists.txt @@ -1,5 +1,7 @@ target_sources(SeeleEngine PRIVATE + BRDF.h + BRDF.cpp Material.h Material.cpp MaterialAsset.h diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index 1d19694..87812b4 100644 --- a/src/Engine/Material/Material.cpp +++ b/src/Engine/Material/Material.cpp @@ -1,6 +1,7 @@ #include "Material.h" #include "Asset/AssetRegistry.h" #include "Graphics/VertexShaderInput.h" +#include "BRDF.h" #include #include #include @@ -45,13 +46,15 @@ void Material::compile() auto& stream = getReadStream(); json j; stream >> j; - std::stringstream codeStream; materialName = j["name"].get(); + std::ofstream codeStream("./shaders/generated/"+materialName+".slang"); std::string profile = j["profile"].get(); + + codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl; codeStream << "import LightEnv;" << std::endl; codeStream << "import Material;" << std::endl; codeStream << "import BRDF;" << std::endl; - codeStream << "import InputGeometry;" << std::endl; + codeStream << "import MaterialParameter;" << std::endl; codeStream << "struct " << materialName << ": IMaterial {" << std::endl; for(auto param : j["params"].items()) @@ -62,6 +65,7 @@ void Material::compile() if(type.compare("float") == 0) { PFloatParameter p = new FloatParameter(); + p->name = param.key(); if(default != param.value().end()) { p->defaultValue = std::stof(default.value().get()); @@ -71,6 +75,7 @@ void Material::compile() else if(type.compare("float3") == 0) { PVectorParameter p = new VectorParameter(); + p->name = param.key(); if(default != param.value().end()) { p->defaultValue = parseVector(default.value().get().c_str()); @@ -80,6 +85,7 @@ void Material::compile() else if(type.compare("Texture2D") == 0) { PTextureParameter p = new TextureParameter(); + p->name = param.key(); if(default != param.value().end()) { @@ -89,37 +95,32 @@ void Material::compile() else if(type.compare("SamplerState") == 0) { PSamplerParameter p = new SamplerParameter(); + p->name = param.key(); parameters.add(p); } else { std::cout << "Error unsupported parameter type" << std::endl; } - codeStream << type << " " << param.key(); + codeStream << type << " " << param.key() << ";\n"; } - codeStream << "typedef " << profile << " BRDF;" << std::endl; - codeStream << profile << " prepare(MaterialPixelParameter geometry){" << std::endl; - codeStream << profile << " result;" << std::endl; - for(auto c : j["code"].items()) - { - codeStream << c.value().get() << std::endl; - } - - codeStream << "}};" << std::endl; - materialCode = codeStream.str(); + BRDF* brdf = BRDF::getBRDFByName(profile); + brdf->generateMaterialCode(codeStream, j["code"]); + codeStream << "};"; + codeStream.close(); } -const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput) const +const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const { Gfx::ShaderPermutation permutation; - std::string materialName = getMaterialName(); + std::string materialName = getFileName(); std::string vertexInputName = vertexInput->getName(); std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName)); std::memcpy(permutation.materialName, vertexInputName.c_str(), sizeof(permutation.materialName)); return shaderMap.findShaders(Gfx::PermutationId(permutation)); } -Gfx::ShaderCollection& Material::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput) +Gfx::ShaderCollection& Material::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput) { std::lock_guard lock(shaderMapLock); return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false); diff --git a/src/Engine/Material/Material.h b/src/Engine/Material/Material.h index 1d3a008..4f498f9 100644 --- a/src/Engine/Material/Material.h +++ b/src/Engine/Material/Material.h @@ -4,7 +4,7 @@ namespace Seele { - +class VertexInputType; class Material : public MaterialAsset { public: @@ -14,18 +14,17 @@ public: ~Material(); virtual void save() override; virtual void load() override; - virtual std::string getMaterialName() const { return materialName; } - inline std::string getCode() const { return materialCode; } + virtual PMaterial getRenderMaterial() { return this; } + const std::string& getName() {return materialName;} - const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput) const; - Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput); + const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const; + Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput); + void compile(); private: static Gfx::ShaderMap shaderMap; static std::mutex shaderMapLock; - void compile(); std::string materialName; - std::string materialCode; friend class MaterialLoader; }; DEFINE_REF(Material); diff --git a/src/Engine/Material/MaterialAsset.h b/src/Engine/Material/MaterialAsset.h index e7b74e2..e6c4efa 100644 --- a/src/Engine/Material/MaterialAsset.h +++ b/src/Engine/Material/MaterialAsset.h @@ -6,6 +6,7 @@ namespace Seele { DECLARE_REF(VertexShaderInput); +DECLARE_REF(Material); class MaterialAsset : public Asset { public: @@ -15,7 +16,7 @@ public: ~MaterialAsset(); virtual void save() = 0; virtual void load() = 0; - virtual std::string getMaterialName() const = 0; + virtual PMaterial getRenderMaterial() = 0; Gfx::SeBlendOp getBlendMode() const {return Gfx::SE_BLEND_OP_END_RANGE;} Gfx::MaterialShadingModel getShadingModel() const {return Gfx::MaterialShadingModel::DefaultLit;} diff --git a/src/Engine/Material/MaterialInstance.cpp b/src/Engine/Material/MaterialInstance.cpp index 260e151..ae5e47a 100644 --- a/src/Engine/Material/MaterialInstance.cpp +++ b/src/Engine/Material/MaterialInstance.cpp @@ -31,9 +31,9 @@ void MaterialInstance::load() } -inline std::string MaterialInstance::getMaterialName() const +PMaterial MaterialInstance::getRenderMaterial() { - return baseMaterial->getMaterialName(); + return baseMaterial; } PMaterial MaterialInstance::getBaseMaterial() const diff --git a/src/Engine/Material/MaterialInstance.h b/src/Engine/Material/MaterialInstance.h index 1df164b..d407ecb 100644 --- a/src/Engine/Material/MaterialInstance.h +++ b/src/Engine/Material/MaterialInstance.h @@ -14,7 +14,7 @@ public: ~MaterialInstance(); virtual void save() override; virtual void load() override; - inline std::string getMaterialName() const; + virtual PMaterial getRenderMaterial(); PMaterial getBaseMaterial() const; Gfx::PDescriptorSet getDescriptor(); private: diff --git a/src/Engine/MinimalEngine.h b/src/Engine/MinimalEngine.h index 70c82f0..40a5b7c 100644 --- a/src/Engine/MinimalEngine.h +++ b/src/Engine/MinimalEngine.h @@ -48,7 +48,10 @@ public: } ~RefObject() { - registeredObjects.erase(handle); + { + std::scoped_lock lock(registeredObjectsLock); + registeredObjects.erase(handle); + } // we cant always have the definition of every class #pragma warning(disable : 4150) delete handle; @@ -122,7 +125,9 @@ public: } RefPtr(T *ptr) { + std::unique_lock l(registeredObjectsLock); auto registeredObj = registeredObjects.find(ptr); + l.unlock(); if (registeredObj == registeredObjects.end()) { object = new RefObject(ptr); @@ -155,7 +160,7 @@ public: RefPtr(const RefPtr &other) { F *f = other.getObject()->getHandle(); - static_cast(f); + T* t = static_cast(f); object = (RefObject *)other.getObject(); object->addRef(); } diff --git a/src/Engine/Scene/Components/PrimitiveComponent.cpp b/src/Engine/Scene/Components/PrimitiveComponent.cpp index cba1fbb..7382e5d 100644 --- a/src/Engine/Scene/Components/PrimitiveComponent.cpp +++ b/src/Engine/Scene/Components/PrimitiveComponent.cpp @@ -12,6 +12,29 @@ 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 = assetMeshes[i]->referencedMaterial->getRenderMaterial(); + 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; + auto& batchElement = batch.elements.add(); + 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 + } } PrimitiveComponent::~PrimitiveComponent() diff --git a/src/Engine/Scene/Components/PrimitiveUniformBufferLayout.h b/src/Engine/Scene/Components/PrimitiveUniformBufferLayout.h index e8c5a52..76ff62e 100644 --- a/src/Engine/Scene/Components/PrimitiveUniformBufferLayout.h +++ b/src/Engine/Scene/Components/PrimitiveUniformBufferLayout.h @@ -6,7 +6,7 @@ namespace Seele struct PrimitiveUniformBuffer { Matrix4 localToWorld; - Vector4 worldToLocal; + Matrix4 worldToLocal; Vector4 actorWorldPosition; }; } // namespace Seele diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index aecf8af..f2f13cb 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -1,11 +1,14 @@ #include "Scene.h" #include "Components/PrimitiveComponent.h" +#include "Components/PrimitiveUniformBufferLayout.h" #include "Material/MaterialInstance.h" #include "Material/Material.h" +#include "Graphics/Graphics.h" using namespace Seele; -Scene::Scene() +Scene::Scene(Gfx::PGraphics graphics) + : graphics(graphics) { } @@ -30,4 +33,21 @@ void Scene::addActor(PActor actor) void Scene::addPrimitiveComponent(PPrimitiveComponent comp) { primitives.add(comp); + for(auto batch : comp->staticMeshes) + { + PrimitiveUniformBuffer data; + data.actorWorldPosition = Vector4(comp->getTransform().getPosition(), 1); + data.localToWorld = comp->getRenderMatrix(); + data.worldToLocal = glm::inverse(data.localToWorld); + BulkResourceData createInfo; + createInfo.data = reinterpret_cast(&data); + createInfo.owner = Gfx::QueueType::GRAPHICS; + createInfo.size = sizeof(data); + Gfx::PUniformBuffer uniformBuffer = graphics->createUniformBuffer(createInfo); + for(auto& element : batch.elements) + { + element.uniformBuffer = uniformBuffer; + } + staticMeshes.add(batch); + } } diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index 7ceb8d7..13ae5cc 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -13,17 +13,18 @@ DECLARE_REF(Material); class Scene { public: - Scene(); + Scene(Gfx::PGraphics graphics); ~Scene(); void tick(float deltaTime); void addActor(PActor actor); void addPrimitiveComponent(PPrimitiveComponent comp); const Array& getPrimitives() const { return primitives; } + const Array& getStaticMeshes() const { return staticMeshes; } private: - Array meshBatches; + Array staticMeshes; Array rootActors; Array primitives; -public: + Gfx::PGraphics graphics; }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/main.cpp b/src/Engine/main.cpp index f1e25d6..6671a32 100644 --- a/src/Engine/main.cpp +++ b/src/Engine/main.cpp @@ -1,12 +1,30 @@ #include "Graphics/RenderCore.h" +#include "Graphics/SceneView.h" #include "Asset/AssetRegistry.h" using namespace Seele; int main() { RenderCore core; core.init(); + WindowCreateInfo mainWindowInfo; + mainWindowInfo.title = "SeeleEngine"; + mainWindowInfo.width = 1280; + mainWindowInfo.height = 720; + mainWindowInfo.bFullscreen = false; + mainWindowInfo.numSamples = 1; + mainWindowInfo.pixelFormat = Gfx::SE_FORMAT_R8G8B8_UNORM; + auto window = core.getWindowManager()->addWindow(mainWindowInfo); + ViewportCreateInfo sceneViewInfo; + sceneViewInfo.sizeX = 1280; + sceneViewInfo.sizeY = 720; + sceneViewInfo.offsetX = 0; + sceneViewInfo.offsetY = 0; + PSceneView sceneView = new SceneView(core.getWindowManager()->getGraphics(), window, sceneViewInfo); + window->addView(sceneView); AssetRegistry::init("D:\\Private\\Programming\\C++\\TestSeeleProject"); AssetRegistry::importFile("D:\\Private\\Programming\\Unreal Engine\\Assets\\Arissa\\Arissa.fbx"); + PPrimitiveComponent arissa = new PrimitiveComponent(AssetRegistry::findMesh("Arissa")); + sceneView->getScene()->addPrimitiveComponent(arissa); core.renderLoop(); core.shutdown(); return 0;