diff --git a/Assets/Materials/ShinyHightlight.shmat b/Assets/Materials/ShinyHightlight.shmat new file mode 100644 index 00000000..bb521519 --- /dev/null +++ b/Assets/Materials/ShinyHightlight.shmat @@ -0,0 +1,8 @@ +- VertexShader: 37048829 + FragmentShader: 45685219 + SubPass: G-Buffer Write + Properties: + data.color: {x: 1, y: 1, z: 1, w: 1} + data.textureIndex: 57342922 + data.alpha: 0 + data.beta: {x: 1, y: 1, z: 1} \ No newline at end of file diff --git a/Assets/Materials/ShinyHightlight.shmat.shmeta b/Assets/Materials/ShinyHightlight.shmat.shmeta new file mode 100644 index 00000000..6ab0ac19 --- /dev/null +++ b/Assets/Materials/ShinyHightlight.shmat.shmeta @@ -0,0 +1,3 @@ +Name: ShinyHightlight +ID: 122370915 +Type: 7 diff --git a/Assets/Materials/Silhouette.shmat b/Assets/Materials/Silhouette.shmat new file mode 100644 index 00000000..912775f0 --- /dev/null +++ b/Assets/Materials/Silhouette.shmat @@ -0,0 +1,8 @@ +- VertexShader: 38847805 + FragmentShader: 42962441 + SubPass: Object VFX Subpass No Depth + Properties: + data.color: {x: 1, y: 1, z: 1, w: 1} + data.textureIndex: 0 + data.alpha: 0 + data.beta: {x: 1, y: 1, z: 1} \ No newline at end of file diff --git a/Assets/Materials/Silhouette.shmat.shmeta b/Assets/Materials/Silhouette.shmat.shmeta new file mode 100644 index 00000000..be1f7bde --- /dev/null +++ b/Assets/Materials/Silhouette.shmat.shmeta @@ -0,0 +1,3 @@ +Name: Silhouette +ID: 126391182 +Type: 7 diff --git a/Assets/Scenes/MainGame.shade b/Assets/Scenes/MainGame.shade index 591c386f..837e0e78 100644 --- a/Assets/Scenes/MainGame.shade +++ b/Assets/Scenes/MainGame.shade @@ -8599,7 +8599,7 @@ IsActive: true Renderable Component: Mesh: 136892700 - Material: 131956078 + Material: 122370915 IsActive: true RigidBody Component: Type: Dynamic @@ -9594,6 +9594,9 @@ Text: My name is Brandon. Font: 176667660 IsActive: true + UI Component: + Canvas ID: 199 + IsActive: true Scripts: ~ - EID: 206 Name: Timer @@ -9609,6 +9612,9 @@ Text: My name is Brandon. Font: 176667660 IsActive: true + UI Component: + Canvas ID: 199 + IsActive: true Scripts: ~ - EID: 139 Name: Multiplier @@ -9624,6 +9630,9 @@ Text: TEST Font: 176667660 IsActive: true + UI Component: + Canvas ID: 199 + IsActive: true Scripts: ~ - EID: 11 Name: GamePause diff --git a/Assets/Shaders/DeferredComposite_CS.glsl b/Assets/Shaders/DeferredComposite_CS.glsl index 745b93e0..f17c9d84 100644 --- a/Assets/Shaders/DeferredComposite_CS.glsl +++ b/Assets/Shaders/DeferredComposite_CS.glsl @@ -26,6 +26,7 @@ layout(set = 3, binding = 3, r32ui) uniform uimage2D lightLayerData; layout(set = 3, binding = 4, r8) uniform image2D ssaoBlurredImage; layout(set = 3, binding = 5, rgba8) uniform image2D positionWorldSpace; layout(set = 3, binding = 6, rgba8) uniform image2D targetImage; +layout(set = 3, binding = 7, rgba8) uniform image2D objectVFXImage; layout (set = 4, binding = 0) uniform sampler2D shadowMaps[]; // for textures (global) @@ -141,6 +142,9 @@ void main() float ssaoVal = imageLoad (ssaoBlurredImage, globalThread).r; fragColor *= ssaoVal; + vec4 objectVFXColor = imageLoad (objectVFXImage, globalThread); + fragColor += objectVFXColor.rgb * objectVFXColor.a; + // store result into result image imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f)); diff --git a/Assets/Shaders/DeferredComposite_CS.shshaderb b/Assets/Shaders/DeferredComposite_CS.shshaderb index ff474e27..e5a0a730 100644 Binary files a/Assets/Shaders/DeferredComposite_CS.shshaderb and b/Assets/Shaders/DeferredComposite_CS.shshaderb differ diff --git a/Assets/Shaders/ShinyHighlight_FS.glsl b/Assets/Shaders/ShinyHighlight_FS.glsl new file mode 100644 index 00000000..92020d9a --- /dev/null +++ b/Assets/Shaders/ShinyHighlight_FS.glsl @@ -0,0 +1,97 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable +#extension GL_EXT_nonuniform_qualifier : require + +struct MatPropData +{ + int textureIndex; + float highlightPosition; +}; + +struct GenericData +{ + //! Delta time + float dt; + + //! Elapsed time of the application + float elapsedTime; + + //! Viewport width of the scene (excluding imgui, that means smaller than window) + uint viewportWidth; + + //! Ditto but for height + uint viewportHeight; +}; + + +layout(location = 0) in struct +{ + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 normal; // location = 2 + vec4 worldPos; // location = 3 +} In; + +// material stuff +layout(location = 4) flat in struct +{ + int materialIndex; + uint eid; + uint lightLayerIndex; + vec3 screenSpacePos; + +} In2; + +layout (set = 0, binding = 0) uniform GenericDataBuffer +{ + GenericData data; +} genericDataBuffer; + +layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global) +layout (std430, set = 2, binding = 0) buffer MaterialProperties // For materials +{ + MatPropData data[]; +} MatProp; + +layout(location = 0) out vec4 position; +layout(location = 1) out uint outEntityID; +layout(location = 2) out uint lightLayerIndices; +layout(location = 3) out vec4 normals; +layout(location = 4) out vec4 albedo; +layout(location = 5) out vec4 worldSpacePosition; +layout(location = 6) out vec4 objectVFX; + +float map (float value, float srcLow, float srcHigh, float dstLow, float dstHigh) +{ + return dstLow + (value - srcLow) * (dstHigh - dstLow) / (srcHigh - srcLow); +} + +void main() +{ + position = In.vertPos; + normals = In.normal; + albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv); + worldSpacePosition = In.worldPos; + + outEntityID = In2.eid; + lightLayerIndices = In2.lightLayerIndex; + + float vpHeight = (float (In2.screenSpacePos.y) - (genericDataBuffer.data.elapsedTime * 4000.0f * (1.0f - In2.screenSpacePos.z))); + vpHeight = float (int (vpHeight) % genericDataBuffer.data.viewportHeight); + float scanlineScale = 2500.0f * (1.0f - In2.screenSpacePos.z); + + float lowerLimit = vpHeight - scanlineScale; + float upperLimit = vpHeight + scanlineScale; + if (gl_FragCoord.y > lowerLimit && gl_FragCoord.y < upperLimit) + { + float opacity = 0.0f; + opacity = map (abs (gl_FragCoord.y - vpHeight), 0.0f, upperLimit - vpHeight, 0.0f, 1.0f); + opacity = 1.0f - clamp (opacity, 0.0f, 1.0f); + + + objectVFX = vec4(opacity); + } + else + objectVFX = vec4(0.0f, 0.0f, 0.0f, 1.0f); +} \ No newline at end of file diff --git a/Assets/Shaders/ShinyHighlight_FS.shshaderb b/Assets/Shaders/ShinyHighlight_FS.shshaderb new file mode 100644 index 00000000..af550ffe Binary files /dev/null and b/Assets/Shaders/ShinyHighlight_FS.shshaderb differ diff --git a/Assets/Shaders/ShinyHighlight_FS.shshaderb.shmeta b/Assets/Shaders/ShinyHighlight_FS.shshaderb.shmeta new file mode 100644 index 00000000..3c17101d --- /dev/null +++ b/Assets/Shaders/ShinyHighlight_FS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: ShinyHighlight_FS +ID: 45685219 +Type: 2 diff --git a/Assets/Shaders/ShinyHighlight_VS.glsl b/Assets/Shaders/ShinyHighlight_VS.glsl new file mode 100644 index 00000000..c0268737 --- /dev/null +++ b/Assets/Shaders/ShinyHighlight_VS.glsl @@ -0,0 +1,99 @@ +#version 450 +#extension GL_KHR_vulkan_glsl : enable + +layout(location = 0) in vec3 aVertexPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec3 aNormal; +layout(location = 3) in vec3 aTangent; +layout(location = 4) in mat4 worldTransform; +layout(location = 8) in uvec2 integerData; +layout(location = 9) in uvec4 aBoneIndices; +layout(location = 10) in vec4 aBoneWeights; +layout(location = 11) in uint firstBoneIndex; + +layout(location = 0) out struct +{ + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 normal; // location = 2 + vec4 worldPos; // location = 3 + +} Out; + +struct GenericData +{ + //! Delta time + float dt; + + //! Elapsed time of the application + float elapsedTime; + + //! Viewport width of the scene (excluding imgui, that means smaller than window) + uint viewportWidth; + + //! Ditto but for height + uint viewportHeight; +}; + +// material stuff +layout(location = 4) out struct +{ + int materialIndex; + uint eid; + uint lightLayerIndex; + vec3 screenSpacePos; + + +} Out2; + +layout(set = 1, binding = 0) uniform CameraData +{ + vec4 position; + mat4 vpMat; + mat4 viewMat; + mat4 projMat; +} cameraData; + +layout (set = 0, binding = 0) uniform GenericDataBuffer +{ + GenericData data; +} genericDataBuffer; + +void main() +{ + Out2.materialIndex = gl_InstanceIndex; + Out2.eid = integerData[0]; + Out2.lightLayerIndex = integerData[1]; + + // for transforming gBuffer position and normal data + mat4 modelViewMat = cameraData.viewMat * worldTransform; + + // gBuffer position will be in view space + Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f); + + Out.worldPos = worldTransform * vec4 (aVertexPos, 1.0f); + + // uvs for texturing in fragment shader + Out.uv = aUV; + + mat3 transposeInv = mat3 (transpose(inverse(modelViewMat))); + + // normals are also in view space + Out.normal.rgb = transposeInv * aNormal.rgb; + Out.normal.rgb = normalize (Out.normal.rgb); + + // Get center of object in world position + vec4 worldPos = vec4(worldTransform[3][0], worldTransform[3][1], worldTransform[3][2], 1.0f); + + // transform to clip space + worldPos = cameraData.vpMat * worldPos; + worldPos.xyz /= worldPos.w; + + // transform to screen space + worldPos.xy = ((worldPos.xy + vec2(1.0f)) * vec2 (0.5f)) * vec2 (genericDataBuffer.data.viewportWidth, genericDataBuffer.data.viewportHeight); + + Out2.screenSpacePos = worldPos.xyz; + + // clip space for rendering + gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); +} \ No newline at end of file diff --git a/Assets/Shaders/ShinyHighlight_VS.shshaderb b/Assets/Shaders/ShinyHighlight_VS.shshaderb new file mode 100644 index 00000000..98187085 Binary files /dev/null and b/Assets/Shaders/ShinyHighlight_VS.shshaderb differ diff --git a/Assets/Shaders/ShinyHighlight_VS.shshaderb.shmeta b/Assets/Shaders/ShinyHighlight_VS.shshaderb.shmeta new file mode 100644 index 00000000..f036de5a --- /dev/null +++ b/Assets/Shaders/ShinyHighlight_VS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: ShinyHighlight_VS +ID: 37048829 +Type: 2 diff --git a/Assets/Shaders/Silhouette_FS.glsl b/Assets/Shaders/Silhouette_FS.glsl new file mode 100644 index 00000000..292bdfe7 --- /dev/null +++ b/Assets/Shaders/Silhouette_FS.glsl @@ -0,0 +1,67 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable +#extension GL_EXT_nonuniform_qualifier : require + +struct MatPropData +{ + vec4 color; +}; + +struct GenericData +{ + //! Delta time + float dt; + + //! Elapsed time of the application + float elapsedTime; + + //! Viewport width of the scene (excluding imgui, that means smaller than window) + uint viewportWidth; + + //! Ditto but for height + uint viewportHeight; +}; + +layout(location = 0) in struct +{ + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 normal; // location = 2 + vec4 worldPos; // location = 3 +} In; + +// material stuff +layout(location = 4) flat in struct +{ + int materialIndex; + uint eid; + uint lightLayerIndex; +} In2; + +layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global) +layout (std430, set = 2, binding = 0) buffer MaterialProperties // For materials +{ + MatPropData data[]; +} MatProp; + +layout (set = 0, binding = 0) uniform GenericDataBuffer +{ + GenericData data; +} genericDataBuffer; + +layout(location = 0) out vec4 objectVFX; +layout(input_attachment_index = 0, set = 3, binding = 0) uniform subpassInput depthBuffer; + +void main() +{ + // Sample depth buffer using UV and save it + float currentDepth = subpassLoad (depthBuffer).r; + + // Use depth buffer to check against current fragment's depth. If fragment is behind depth buffer, render fragment. + if (currentDepth > gl_FragCoord.z) + discard; + + objectVFX = MatProp.data[In2.materialIndex].color; + +} \ No newline at end of file diff --git a/Assets/Shaders/Silhouette_FS.shshaderb b/Assets/Shaders/Silhouette_FS.shshaderb new file mode 100644 index 00000000..4710b8a6 Binary files /dev/null and b/Assets/Shaders/Silhouette_FS.shshaderb differ diff --git a/Assets/Shaders/Silhouette_FS.shshaderb.shmeta b/Assets/Shaders/Silhouette_FS.shshaderb.shmeta new file mode 100644 index 00000000..e094c1d6 --- /dev/null +++ b/Assets/Shaders/Silhouette_FS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: Silhouette_FS +ID: 42962441 +Type: 2 diff --git a/Assets/Shaders/Silhouette_VS.glsl b/Assets/Shaders/Silhouette_VS.glsl new file mode 100644 index 00000000..1b45c333 --- /dev/null +++ b/Assets/Shaders/Silhouette_VS.glsl @@ -0,0 +1,68 @@ +#version 450 +#extension GL_KHR_vulkan_glsl : enable + +//#include "ShaderDescriptorDefinitions.glsl" + + +layout(location = 0) in vec3 aVertexPos; +layout(location = 1) in vec2 aUV; +layout(location = 2) in vec3 aNormal; +layout(location = 3) in vec3 aTangent; +layout(location = 4) in mat4 worldTransform; +layout(location = 8) in uvec2 integerData; +layout(location = 9) in uvec4 aBoneIndices; +layout(location = 10) in vec4 aBoneWeights; +layout(location = 11) in uint firstBoneIndex; + +layout(location = 0) out struct +{ + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 normal; // location = 2 + vec4 worldPos; // location = 3 + +} Out; + +// material stuff +layout(location = 4) out struct +{ + int materialIndex; + uint eid; + uint lightLayerIndex; + +} Out2; + +layout(set = 1, binding = 0) uniform CameraData +{ + vec4 position; + mat4 vpMat; + mat4 viewMat; + mat4 projMat; +} cameraData; + +void main() +{ + Out2.materialIndex = gl_InstanceIndex; + Out2.eid = integerData[0]; + Out2.lightLayerIndex = integerData[1]; + + // for transforming gBuffer position and normal data + mat4 modelViewMat = cameraData.viewMat * worldTransform; + + // gBuffer position will be in view space + Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f); + + Out.worldPos = worldTransform * vec4 (aVertexPos, 1.0f); + + // uvs for texturing in fragment shader + Out.uv = aUV; + + mat3 transposeInv = mat3 (transpose(inverse(modelViewMat))); + + // normals are also in view space + Out.normal.rgb = transposeInv * aNormal.rgb; + Out.normal.rgb = normalize (Out.normal.rgb); + + // clip space for rendering + gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); +} \ No newline at end of file diff --git a/Assets/Shaders/Silhouette_VS.shshaderb b/Assets/Shaders/Silhouette_VS.shshaderb new file mode 100644 index 00000000..1bb76ec4 Binary files /dev/null and b/Assets/Shaders/Silhouette_VS.shshaderb differ diff --git a/Assets/Shaders/Silhouette_VS.shshaderb.shmeta b/Assets/Shaders/Silhouette_VS.shshaderb.shmeta new file mode 100644 index 00000000..508a8788 --- /dev/null +++ b/Assets/Shaders/Silhouette_VS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: Silhouette_VS +ID: 38847805 +Type: 2 diff --git a/Assets/Shaders/ToSwapchain_FS.glsl b/Assets/Shaders/ToSwapchain_FS.glsl index 3cf1752f..d353c15f 100644 --- a/Assets/Shaders/ToSwapchain_FS.glsl +++ b/Assets/Shaders/ToSwapchain_FS.glsl @@ -3,7 +3,7 @@ #extension GL_ARB_shading_language_420pack : enable #extension GL_EXT_nonuniform_qualifier : require -layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput sceneTexture; +layout (input_attachment_index = 0, set = 3, binding = 0) uniform subpassInput sceneTexture; layout(location = 0) out vec4 fragColor; diff --git a/Assets/Shaders/ToSwapchain_FS.shshaderb b/Assets/Shaders/ToSwapchain_FS.shshaderb index 0bee0ac6..24cb54fe 100644 Binary files a/Assets/Shaders/ToSwapchain_FS.shshaderb and b/Assets/Shaders/ToSwapchain_FS.shshaderb differ diff --git a/SHADE_Engine/src/Assets/Events/SHAssetManagerEvents.h b/SHADE_Engine/src/Assets/Events/SHAssetManagerEvents.h new file mode 100644 index 00000000..d61395e9 --- /dev/null +++ b/SHADE_Engine/src/Assets/Events/SHAssetManagerEvents.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +namespace SHADE +{ + struct SHCompileAssetEvent + { + //! Name of the asset (where applicable) + std::string assetName; + + //! asset ID of the asset + AssetID assetID; + + //! type of the asset + AssetType assetType; + }; +} + diff --git a/SHADE_Engine/src/Assets/Libraries/Compilers/SHShaderSourceCompiler.cpp b/SHADE_Engine/src/Assets/Libraries/Compilers/SHShaderSourceCompiler.cpp index fd1f6d8a..0bde59c7 100644 --- a/SHADE_Engine/src/Assets/Libraries/Compilers/SHShaderSourceCompiler.cpp +++ b/SHADE_Engine/src/Assets/Libraries/Compilers/SHShaderSourceCompiler.cpp @@ -11,6 +11,7 @@ #include "SHpch.h" #include "SHShaderSourceCompiler.h" #include "shaderc/shaderc.hpp" +#include "Events/SHEventManager.hpp" #include #include diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index 363b7829..b7f7fbb4 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -28,6 +28,8 @@ #include "Filesystem/SHFileSystem.h" #include +#include "Assets/Events/SHAssetManagerEvents.h" +#include "Events/SHEventManager.hpp" namespace SHADE { @@ -39,7 +41,7 @@ namespace SHADE std::vector SHAssetManager::loaders(TYPE_COUNT); std::unordered_map SHAssetManager::assetCollection; - std::unordered_map SHAssetManager::assetData; + std::unordered_map SHAssetManager::assetData; /**************************************************************************** @@ -167,6 +169,17 @@ namespace SHADE return {}; } + AssetID SHAssetManager::GetAssetIDFromPath(AssetPath const& path) noexcept + { + for (auto const& pair : assetCollection) + { + if (pair.second.path.stem() == path.stem()) + return pair.first; + } + + return 0; + } + /**************************************************************************** * \brief Create record for new asset. CAN ONLY CREATE FOR CUSTOM * ASSETS CREATED BY THE ENGINE. @@ -438,10 +451,39 @@ namespace SHADE return; } + AssetID target{ 0 }; if (genMeta) { - GenerateNewMeta(newPath); + auto result = GenerateNewMeta(newPath); + target = result.has_value() ? result.value() : 0; } + else + { + target = GetAssetIDFromPath(path); + + //Reload data + auto result = GetAsset(target); + if (result.has_value()) + { + auto const& asset{ result.value() }; + auto newData = loaders[static_cast(asset.type)]->Load(asset.path); + delete assetData[target]; + assetData[target] = newData; + } + else + { + SHLOG_ERROR("[Asset Manager] Critical: reload of existing compiled data failed"); + } + } + + // send compile asset event + SHCompileAssetEvent compileShaderEvent + { + .assetName = newPath.filename().stem().string(), + .assetID = target, + .assetType = AssetType::SHADER, + }; + SHEventManager::BroadcastEvent(compileShaderEvent, SH_ASSET_COMPILE_EVENT); } FolderPointer SHAssetManager::GetRootFolder() noexcept diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index 6cac6c71..e5cd0359 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -50,7 +50,7 @@ namespace SHADE * \return const& to unordered_map ****************************************************************************/ static std::vector GetAllAssets() noexcept; - static std::optional GetAsset(AssetID id) noexcept; + static std::optional GetAsset(AssetID id) noexcept; static AssetType GetType(AssetID id) noexcept; @@ -97,6 +97,7 @@ namespace SHADE private: + static AssetID GetAssetIDFromPath(AssetPath const& path) noexcept; static void InitLoaders() noexcept; static void LoadAllData() noexcept; static SHAssetData* LoadData(SHAsset const& asset) noexcept; @@ -122,7 +123,7 @@ namespace SHADE // For all resources static std::unordered_map assetCollection; - static std::unordered_map assetData; + static std::unordered_map assetData; }; } diff --git a/SHADE_Engine/src/Events/SHEventDefines.h b/SHADE_Engine/src/Events/SHEventDefines.h index fffe8b5f..a7447be0 100644 --- a/SHADE_Engine/src/Events/SHEventDefines.h +++ b/SHADE_Engine/src/Events/SHEventDefines.h @@ -29,4 +29,5 @@ constexpr SHEventIdentifier SH_WINDOW_RESIZE_EVENT { 20 }; constexpr SHEventIdentifier SH_BUTTON_RELEASE_EVENT { 21 }; constexpr SHEventIdentifier SH_BUTTON_HOVER_ENTER_EVENT { 22 }; constexpr SHEventIdentifier SH_BUTTON_HOVER_EXIT_EVENT { 23 }; +constexpr SHEventIdentifier SH_ASSET_COMPILE_EVENT { 24 }; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GenericData/SHGraphicsGenericData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GenericData/SHGraphicsGenericData.cpp new file mode 100644 index 00000000..b77c20f9 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GenericData/SHGraphicsGenericData.cpp @@ -0,0 +1,53 @@ +#include "SHpch.h" +#include "SHGraphicsGenericData.h" +#include "Graphics/Devices/SHVkLogicalDevice.h" +#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h" +#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h" +#include "Graphics/Buffers/SHVkBuffer.h" + + +namespace SHADE +{ + void SHGraphicsGenericData::Init(Handle logicalDevice, Handle descSet) noexcept + { + alignedGpuStructSize = logicalDevice->PadUBOSize(sizeof (GpuStruct)); + + gpuBuffer = logicalDevice->CreateBuffer(alignedGpuStructSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, nullptr, alignedGpuStructSize * SHGraphicsConstants::NUM_FRAME_BUFFERS, vk::BufferUsageFlagBits::eUniformBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, "Generic Data"); + + std::array gpuBufferArray{ gpuBuffer }; + + // We use index 0 because the descriptor set is standalone created from a single desc set layout. What the driver sees is that this set is at index 0 during updating. + static constexpr uint8_t SET_0 = 0; + + descSet->ModifyWriteDescBuffer(SET_0, SHGraphicsConstants::DescriptorSetBindings::GENERIC_DATA, std::span>{ gpuBufferArray.data(), gpuBufferArray.size()}, 0, sizeof(GpuStruct)); + + descSet->UpdateDescriptorSetBuffer(SET_0, SHGraphicsConstants::DescriptorSetBindings::GENERIC_DATA); + + } + + void SHGraphicsGenericData::UpdateBuffer(uint32_t frameIndex) noexcept + { + gpuBuffer->WriteToMemory(&data, sizeof(GpuStruct), 0, alignedGpuStructSize * frameIndex); + } + + void SHGraphicsGenericData::SetDt(float dt) noexcept + { + data.dt = dt; + } + + void SHGraphicsGenericData::UpdateElapsedTime(float dt) noexcept + { + data.elapsedTime += dt; + } + + void SHGraphicsGenericData::SetViewportWidth(uint32_t width) noexcept + { + data.viewportWidth = width; + } + + void SHGraphicsGenericData::SetViewportHeight(uint32_t height) noexcept + { + data.viewportHeight = height; + } + +} \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GenericData/SHGraphicsGenericData.h b/SHADE_Engine/src/Graphics/MiddleEnd/GenericData/SHGraphicsGenericData.h new file mode 100644 index 00000000..a9a590f6 --- /dev/null +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GenericData/SHGraphicsGenericData.h @@ -0,0 +1,51 @@ +#pragma once + +#include +#include "Resource/SHHandle.h" + +namespace SHADE +{ + class SHVkDescriptorSetGroup; + class SHVkBuffer; + class SHVkLogicalDevice; + + class SHGraphicsGenericData + { + public: + struct GpuStruct + { + //! Delta time + float dt{ 0.0f }; + + //! Elapsed time of the application + float elapsedTime{ 0.0f }; + + //! Viewport width of the scene (excluding imgui, that means smaller than window) + uint32_t viewportWidth{ 0 }; + + //! Ditto but for height + uint32_t viewportHeight{ 0 }; + }; + private: + + //! This will be access + GpuStruct data; + + //! Buffer to hold the generic data + Handle gpuBuffer; + + //! gpu struct size for GPU to use + uint32_t alignedGpuStructSize; + + public: + void Init (Handle logicalDevice, Handle descSet) noexcept; + void UpdateBuffer(uint32_t frameIndex) noexcept; + + void SetDt (float dt) noexcept; + void UpdateElapsedTime (float dt) noexcept; + void SetViewportWidth(uint32_t width) noexcept; + void SetViewportHeight(uint32_t height) noexcept; + + }; +} + diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.cpp index fd94968e..e079b933 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.cpp @@ -2,11 +2,13 @@ #include "SHGlobalDescriptorSets.h" #include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h" #include "Graphics/Commands/SHVkCommandBuffer.h" +#include "Graphics/MiddleEnd/GenericData/SHGraphicsGenericData.h" +#include "Graphics/Devices/SHVkLogicalDevice.h" namespace SHADE { - Handle SHGlobalDescriptorSets::staticGlobalDataDescriptorSet; + Handle SHGlobalDescriptorSets::genericAndTextureDataDescSet; Handle SHGlobalDescriptorSets::lightingSubSystem; //void SHGlobalDescriptorSets::BindLightingData(Handle cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t firstSet) noexcept @@ -20,11 +22,13 @@ namespace SHADE lightingSubSystem->BindDescSet(cmdBuffer, setIndex, frameIndex); } - void SHGlobalDescriptorSets::BindStaticGlobalData(Handle cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t setIndex) noexcept + void SHGlobalDescriptorSets::BindGenericAndTextureData(Handle device, Handle cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t setIndex, uint32_t frameIndex) noexcept { + uint32_t alignedGenericStructSize = device->PadUBOSize(sizeof(SHGraphicsGenericData::GpuStruct)); + // Bind descriptor set for static global data - static std::array TEX_DYNAMIC_OFFSET{ 0 }; - cmdBuffer->BindDescriptorSet(staticGlobalDataDescriptorSet, pipelineType, setIndex, std::span{ TEX_DYNAMIC_OFFSET.data(), 1 }); + static std::array TEX_DYNAMIC_OFFSET = { alignedGenericStructSize, }; + cmdBuffer->BindDescriptorSet(genericAndTextureDataDescSet, pipelineType, setIndex, std::span{ TEX_DYNAMIC_OFFSET.data(), 1 }); } /***************************************************************************/ @@ -43,9 +47,9 @@ namespace SHADE lightingSubSystem = system; } - void SHGlobalDescriptorSets::SetStaticGlobalDataDescriptorSet(Handle staticGlobalDescSet) noexcept + void SHGlobalDescriptorSets::SetStaticGlobalDataDescriptorSet(Handle descSet) noexcept { - staticGlobalDataDescriptorSet = staticGlobalDescSet; + genericAndTextureDataDescSet = descSet; } } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h index 2e2dca7d..4ee09a6a 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h @@ -15,7 +15,7 @@ namespace SHADE private: //! Static global descriptor sets for miscellaneous data and textures - static Handle staticGlobalDataDescriptorSet; + static Handle genericAndTextureDataDescSet; //! Lighting sub system required to get information to bind descriptor sets for light data static Handle lightingSubSystem; @@ -25,7 +25,7 @@ namespace SHADE /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ static void BindLightingData (Handle cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t setIndex, uint32_t frameIndex) noexcept; - static void BindStaticGlobalData (Handle cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t setIndex) noexcept; + static void BindGenericAndTextureData (Handle device, Handle cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t setIndex, uint32_t frameIndex) noexcept; /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp index 63b39c9f..85559bc7 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.cpp @@ -25,9 +25,10 @@ namespace SHADE { perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descMappings.AddMappings ({ - {SHPredefinedDescriptorTypes::STATIC_DATA, 0}, - {SHPredefinedDescriptorTypes::CAMERA, 1}, - {SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH, 2}, + {SHPredefinedDescriptorTypes::STATIC_DATA, 0}, + {SHPredefinedDescriptorTypes::CAMERA, 1}, + {SHPredefinedDescriptorTypes::PER_INSTANCE_BATCH, 2}, + {SHPredefinedDescriptorTypes::RENDER_GRAPH_RESOURCE, 3}, }); perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING_ANIM)].descMappings.AddMappings diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h index 38fe9aa3..54b02608 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsConstants.h @@ -129,11 +129,13 @@ namespace SHADE static constexpr std::string_view GBUFFER_WRITE_SUBPASS = "G-Buffer Write"; static constexpr std::string_view UI_SUBPASS = "UI"; static constexpr std::string_view VFX_SUBPASS = "VFX"; + static constexpr std::string_view OBJ_VFX_SUBPASS = "Object VFX Subpass No Depth"; static constexpr std::array USABLE_SUBPASSES = { GBUFFER_WRITE_SUBPASS, - UI_SUBPASS + UI_SUBPASS, + OBJ_VFX_SUBPASS }; }; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 8f4f30af..7f40e558 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -47,6 +47,7 @@ of DigiPen Institute of Technology is prohibited. #include "Events/SHEvent.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Input/SHInputManager.h" +#include "Assets/Events/SHAssetManagerEvents.h" namespace SHADE { @@ -210,10 +211,11 @@ namespace SHADE renderGraph->Init("World Render Graph", device, swapchain, &resourceManager, renderContextCmdPools); renderGraph->AddResource("Position", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); renderGraph->AddResource("Position World Space", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); + renderGraph->AddResource("Object VFX", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); renderGraph->AddResource("Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); //worldRenderGraph->AddResource("Tangents", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat); renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second); - renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); + renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint); renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); renderGraph->AddResource("Light Layer Indices", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc); renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second); @@ -235,7 +237,8 @@ namespace SHADE "Depth Buffer", "SSAO", "SSAO Blur", - "Position World Space" + "Position World Space", + "Object VFX" }, {}); // no predecessors @@ -249,9 +252,16 @@ namespace SHADE gBufferSubpass->AddColorOutput("Normals"); gBufferSubpass->AddColorOutput("Albedo"); gBufferSubpass->AddColorOutput("Position World Space"); + gBufferSubpass->AddColorOutput("Object VFX"); gBufferSubpass->AddDepthOutput("Depth Buffer", SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL); - usableSubpassesMapping.emplace (std::string (SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data()), gBufferSubpass); + // We add the object VFX render target and depth buffer as input just in case we want to make comparisons + auto objectVfxSubpassNoDepth = gBufferNode->AddSubpass(SHGraphicsConstants::RenderGraphEntityNames::OBJ_VFX_SUBPASS.data(), worldViewport, worldRenderer); + objectVfxSubpassNoDepth->AddColorOutput("Object VFX"); + objectVfxSubpassNoDepth->AddInput ("Depth Buffer"); + + usableSubpassesMapping.emplace(std::string(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_WRITE_SUBPASS.data()), gBufferSubpass); + usableSubpassesMapping.emplace(std::string(SHGraphicsConstants::RenderGraphEntityNames::OBJ_VFX_SUBPASS.data()), objectVfxSubpassNoDepth); /*-----------------------------------------------------------------------*/ /* SSAO PASS AND DATA INIT */ @@ -297,15 +307,15 @@ namespace SHADE "Albedo", "Scene", "SSAO Blur", - "Position World Space" + "Position World Space", + "Object VFX" }, { SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS .data()}); - /*-----------------------------------------------------------------------*/ /* DEFERRED COMPOSITE SUBPASS INIT */ /*-----------------------------------------------------------------------*/ - auto deferredCompositeCompute = deferredCompositeNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data(), deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Position World Space", "Scene"}, {}, SHLightingSubSystem::MAX_SHADOWS); + auto deferredCompositeCompute = deferredCompositeNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data(), deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Position World Space", "Scene", "Object VFX"}, {}, SHLightingSubSystem::MAX_SHADOWS); deferredCompositeCompute->AddPreComputeFunction([=](Handle cmdBuffer, uint32_t frameIndex) { lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer); @@ -409,7 +419,6 @@ namespace SHADE InitRenderGraph(); - // Create Semaphore for (auto& semaHandle : graphSemaphores) { @@ -491,12 +500,34 @@ namespace SHADE void SHGraphicsSystem::InitEvents(void) noexcept { - std::shared_ptr> thisReceiver + std::shared_ptr> lightEnableShadowReceiver { std::make_shared>(this, &SHGraphicsSystem::ReceiveLightEnableShadowEvent) }; - ReceiverPtr receiver = std::dynamic_pointer_cast(thisReceiver); - SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, receiver); + ReceiverPtr lightEnableShadowReceivePtr = std::dynamic_pointer_cast(lightEnableShadowReceiver); + SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, lightEnableShadowReceivePtr); + + std::shared_ptr> compileAssetReceiever + { + std::make_shared>(this, &SHGraphicsSystem::ReceiveCompileAssetEvent) + }; + ReceiverPtr compileAssetReceivePtr = std::dynamic_pointer_cast(compileAssetReceiever); + SHEventManager::SubscribeTo(SH_ASSET_COMPILE_EVENT, compileAssetReceivePtr); + } + + void SHGraphicsSystem::InitGenericDataAndTexturesDescSet(void) noexcept + { + // descriptor set for generic data and textures + genericAndTextureDescSet = descPool->Allocate(SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA), { SHTextureLibrary::DEFAULT_MAX_TEXTURES }); + + for (auto set : genericAndTextureDescSet->GetVkHandle()) + SET_VK_OBJ_NAME(device, vk::ObjectType::eDescriptorSet, set, "[Descriptor Set] Static Globals"); + + SHGlobalDescriptorSets::SetStaticGlobalDataDescriptorSet(genericAndTextureDescSet); + + // Create buffer for generic data and attach to descriptor set + graphicsGenericData.Init(device, genericAndTextureDescSet); + } /*---------------------------------------------------------------------------------*/ @@ -507,6 +538,7 @@ namespace SHADE InitBoilerplate(); InitMiddleEnd(); InitSubsystems(); + InitGenericDataAndTexturesDescSet(); InitBuiltInResources(); InitEvents(); } @@ -536,7 +568,7 @@ namespace SHADE */ /***************************************************************************/ - void SHGraphicsSystem::Run(double) noexcept + void SHGraphicsSystem::Run(double dt) noexcept { if (window->IsMinimized() || renderContext.GetWindowIsDead()) { @@ -572,6 +604,9 @@ namespace SHADE auto cameraSystem = SHSystemManager::GetSystem(); + graphicsGenericData.SetDt(dt); + graphicsGenericData.UpdateElapsedTime(dt); + graphicsGenericData.UpdateBuffer(frameIndex); { #ifdef SHEDITOR @@ -860,6 +895,29 @@ namespace SHADE return eventPtr->handle; } + SHEventHandle SHGraphicsSystem::ReceiveCompileAssetEvent(SHEventPtr eventPtr) noexcept + { + auto const& EVENT_DATA = reinterpret_cast*>(eventPtr.get())->data; + + // check for asset type + if (EVENT_DATA->assetType == AssetType::SHADER) + { + // loop through all shaders + auto denseIterators = SHVkInstance::GetResourceManager().GetDenseAccess(); + for (auto it = denseIterators.first; it != denseIterators.second; ++it) + { + if (it->GetName() == EVENT_DATA->assetName) + { + auto* shaderAsset = SHAssetManager::GetData(EVENT_DATA->assetID); + it->OnChange(shaderAsset->spirvBinary); + break; + } + } + } + + return eventPtr->handle; + } + Handle SHGraphicsSystem::AddMaterial(Handle vertShader, Handle fragShader, Handle subpass) { // Retrieve pipeline from pipeline storage or create if unavailable @@ -980,12 +1038,11 @@ namespace SHADE device->WaitIdle(); texLibrary.BuildTextures ( - device, graphicsTexCmdBuffer, graphicsQueue, descPool + device, graphicsTexCmdBuffer, graphicsQueue, genericAndTextureDescSet ); device->WaitIdle(); graphicsTexCmdBuffer.Free(); graphicsTexCmdBuffer = {}; - SHGlobalDescriptorSets::SetStaticGlobalDataDescriptorSet(texLibrary.GetTextureDescriptorSetGroup()); - + //SHGlobalDescriptorSets::SetStaticGlobalDataDescriptorSet(texLibrary.GetTextureDescriptorSetGroup()); } Handle SHGraphicsSystem::GetTextureHandle(SHTexture::Index textureId) const @@ -1134,6 +1191,10 @@ namespace SHADE resizeWidth = newWidth; resizeHeight = newHeight; + graphicsGenericData.SetViewportWidth(resizeWidth); + graphicsGenericData.SetViewportHeight(resizeHeight); + + renderContext.SetIsResized(true); } @@ -1186,6 +1247,7 @@ namespace SHADE SHEventManager::BroadcastEvent(newEvent, SH_WINDOW_RESIZE_EVENT); + #else // Create new event and broadcast it SHWindowResizeEvent newEvent; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 21d18be1..0b98f843 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -37,6 +37,7 @@ of DigiPen Institute of Technology is prohibited. #include "Graphics/MiddleEnd/Interface/SHRenderer.h" #include "Graphics/Events/SHGraphicsEvents.h" #include "Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.h" +#include "Graphics/MiddleEnd/GenericData/SHGraphicsGenericData.h" namespace SHADE { @@ -106,6 +107,7 @@ namespace SHADE void InitSubsystems (void) noexcept; void InitBuiltInResources (void); void InitEvents (void) noexcept; + void InitGenericDataAndTexturesDescSet (void) noexcept; public: class SH_API BeginRoutine final : public SHSystemRoutine @@ -181,6 +183,11 @@ namespace SHADE /*-----------------------------------------------------------------------*/ SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr eventPtr) noexcept; + /*-----------------------------------------------------------------------*/ + /* Asset Events */ + /*-----------------------------------------------------------------------*/ + SHEventHandle ReceiveCompileAssetEvent (SHEventPtr eventPtr) noexcept; + /*-----------------------------------------------------------------------------*/ /* Material Functions */ /*-----------------------------------------------------------------------------*/ @@ -433,6 +440,7 @@ namespace SHADE SHResourceHub resourceManager; SHMeshLibrary meshLibrary; SHTextureLibrary texLibrary; + SHGraphicsGenericData graphicsGenericData; SHFontLibrary fontLibrary; SHSamplerCache samplerCache; SHMaterialInstanceCache materialInstanceCache; @@ -490,6 +498,8 @@ namespace SHADE Handle debugDrawFilledDepthPipeline; Handle shadowMapPipeline; // initialized only when a shadow map is needed + Handle genericAndTextureDescSet; + // Built-In Textures Handle defaultTexture; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.cpp index e1935634..0452e4e9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.cpp @@ -14,6 +14,7 @@ #include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h" #include "Graphics/MiddleEnd/Interface/SHRenderer.h" #include "Scene/SHSceneManager.h" +#include "UI/SHUIComponent.h" namespace SHADE { @@ -197,7 +198,7 @@ namespace SHADE cmdBuffer->BindPipeline(pipeline); // Bind global data - SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, staticGlobalSetIndex); + SHGlobalDescriptorSets::BindGenericAndTextureData(logicalDevice, cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, staticGlobalSetIndex, frameIndex); // Bind camera data renderer->BindDescriptorSet(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, cameraSetIndex, frameIndex); @@ -209,7 +210,12 @@ namespace SHADE cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::CALCULATED_GLYPH_POSITION, comp.charPositionDataBuffer, 0); cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::GLYPH_INDEX, comp.indexingDataBuffer, 0); - cmdBuffer->SetPushConstantVariable("TestPushConstant.worldTransform", transform->GetTRS(), SH_PIPELINE_TYPE::GRAPHICS); + if (auto* uiComp = SHComponentManager::GetComponent_s(comp.GetEID())) + cmdBuffer->SetPushConstantVariable("TestPushConstant.worldTransform", uiComp->GetMatrix(), SH_PIPELINE_TYPE::GRAPHICS); + else + cmdBuffer->SetPushConstantVariable("TestPushConstant.worldTransform", transform->GetTRS(), SH_PIPELINE_TYPE::GRAPHICS); + + cmdBuffer->SetPushConstantVariable("TestPushConstant.eid", comp.GetEID(), SH_PIPELINE_TYPE::GRAPHICS); cmdBuffer->SetPushConstantVariable("TestPushConstant.textColor", SHVec3 (1.0f, 1.0f, 1.0f), SH_PIPELINE_TYPE::GRAPHICS); diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp index 0578e7a2..fd2f3ac7 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.cpp @@ -63,7 +63,7 @@ namespace SHADE isDirty = true; } - void SHTextureLibrary::BuildTextures(Handle device, Handle cmdBuffer, Handle graphicsQueue, Handle descPool) + void SHTextureLibrary::BuildTextures(Handle device, Handle cmdBuffer, Handle graphicsQueue, Handle descSet/*, Handle descPool*/) { // Don't do anything if there are no updates if (!isDirty) @@ -162,27 +162,28 @@ namespace SHADE /* Build Descriptor Set with all the Textures only if there are textures */ if (!texOrder.empty()) { - if (texDescriptors) - { - texDescriptors.Free(); - } - texDescriptors = descPool->Allocate - ( - { SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA) }, - { static_cast(texOrder.size()) } - ); -#ifdef _DEBUG - for (auto set : texDescriptors->GetVkHandle()) - SET_VK_OBJ_NAME(device, vk::ObjectType::eDescriptorSet, set, "[Descriptor Set] Static Globals"); -#endif + +// if (descSet) +// { +// descSet.Free(); +// } +// descSet = descPool->Allocate +// ( +// { SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::STATIC_DATA) }, +// { static_cast(texOrder.size()) } +// ); +//#ifdef _DEBUG +// for (auto set : descSet->GetVkHandle()) +// SET_VK_OBJ_NAME(device, vk::ObjectType::eDescriptorSet, set, "[Descriptor Set] Static Globals"); +//#endif static constexpr uint32_t TEX_DESCRIPTOR_SET_INDEX = 0; - texDescriptors->ModifyWriteDescImage + descSet->ModifyWriteDescImage ( TEX_DESCRIPTOR_SET_INDEX, SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA, combinedImageSamplers ); - texDescriptors->UpdateDescriptorSetImages + descSet->UpdateDescriptorSetImages ( TEX_DESCRIPTOR_SET_INDEX, SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h index 5b7e4914..bbc72a1a 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Textures/SHTextureLibrary.h @@ -66,6 +66,13 @@ namespace SHADE class SHTextureLibrary { public: + //! This exists because a poor decision was made to place the textures and + //! generic data as 2 bindings in a single layout. Because of this, the recreation + //! of the texture library would mean the recreation of the desc set that also + //! involves the generic data, which is bad bad bad. Solution is to separate the + //! 2 desc sets. + static constexpr uint32_t DEFAULT_MAX_TEXTURES = 2000; + /*-----------------------------------------------------------------------------*/ /* Usage Functions */ /*-----------------------------------------------------------------------------*/ @@ -112,7 +119,7 @@ namespace SHADE /*! \brief - Finalises all changes to the Texture Library into the GPU buffers. + Finalizes all changes to the Texture Library into the GPU buffers. \param device Device used to create and update the buffers. @@ -123,12 +130,12 @@ namespace SHADE queue. */ /***************************************************************************/ - void BuildTextures(Handle device, Handle cmdBuffer, Handle graphicsQueue, Handle descPool); + void BuildTextures(Handle device, Handle cmdBuffer, Handle graphicsQueue, Handle descSet/*, Handle descPool*/); /*-----------------------------------------------------------------------------*/ /* Getter Functions */ /*-----------------------------------------------------------------------------*/ - Handle GetTextureDescriptorSetGroup() const noexcept { return texDescriptors; } + //Handle GetTextureDescriptorSetGroup() const noexcept { return descSet; } /***************************************************************************/ /*! * @@ -173,8 +180,8 @@ namespace SHADE std::vector> texOrder; // CPU Storage std::vector, Handle, vk::ImageLayout>> combinedImageSamplers; - // GPU Storage - Handle texDescriptors; + //// GPU Storage + //Handle descSet; // Flags bool isDirty = true; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp index 740ffa92..802d085d 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/TrajectoryRendering/SHTrajectoryRenderingSubSystem.cpp @@ -164,7 +164,7 @@ namespace SHADE cmdBuffer->BindPipeline(pipeline); // Bind global data - SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, staticGlobalSetIndex); + SHGlobalDescriptorSets::BindGenericAndTextureData(logicalDevice, cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, staticGlobalSetIndex, frameIndex); // Bind camera data renderer->BindDescriptorSet(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, cameraSetIndex, frameIndex); diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp index 973ae72f..dd050627 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipeline.cpp @@ -235,6 +235,9 @@ namespace SHADE , pipelineLayout { inPipelineLayout } , created {false} { + if (pipelineLayout) + pipelineLayout->AddCallback([this]() {ConstructPipeline();}); + // We want to create a pipeline if (state != nullptr) { @@ -359,7 +362,10 @@ namespace SHADE { // if it was created before, destroy it if (created) + { + logicalDeviceHdl->WaitIdle(); logicalDeviceHdl->GetVkLogicalDevice().destroyPipeline(vkPipeline, nullptr); + } // Set to false again. If creation succeeds after this, this will be true created = false; diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp index 6a6ef879..fa9bf6bf 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.cpp @@ -298,6 +298,10 @@ namespace SHADE descriptorSetLayoutsAllocate.clear(); + dynamicBufferBindings.clear(); + + descriptorSetLayoutsPipeline.clear(); + // We don't need to use vulkan to destroy descriptor sets here since they are just owned by the container with handles vkDescriptorSetLayoutsAllocate.clear(); vkDescriptorSetLayoutsPipeline.clear(); @@ -450,6 +454,15 @@ namespace SHADE } else SHVulkanDebugUtil::ReportVkSuccess("Successfully created Pipeline Layout. "); + + // Call callbacks + for (auto& callback : onChangeCallbacks) + callback(); + } + + void SHVkPipelineLayout::AddCallback(ChangeCallback&& callback) noexcept + { + onChangeCallbacks.emplace_back(std::move(callback)); } std::vector> const& SHVkPipelineLayout::GetShaderModules(void) const noexcept diff --git a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h index e2af02a9..a856700b 100644 --- a/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h +++ b/SHADE_Engine/src/Graphics/Pipeline/SHVkPipelineLayout.h @@ -10,6 +10,9 @@ namespace SHADE class SHVkPipelineLayout { + public: + using ChangeCallback = std::function; + private: /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER VARIABLES */ @@ -51,6 +54,12 @@ namespace SHADE //! Store for pipeline layout recreation std::vector vkDescriptorSetLayoutsPipeline; + //! When pipeline layout needs to be recreated, this container could serve as an event + //! response to call all the functions that need to be called. Specifically + //! pipelines that need to use the new pipeline layout + std::vector onChangeCallbacks; + + /*-----------------------------------------------------------------------*/ /* PRIVATE MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ @@ -73,6 +82,7 @@ namespace SHADE /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ void RecreateIfNeeded (void) noexcept; + void AddCallback(ChangeCallback&& callback) noexcept; /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index c312535e..ea650274 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -512,8 +512,9 @@ namespace SHADE uint32_t h = static_cast(resource->GetHeight()); cmdBuffer->SetViewportScissor(static_cast(w), static_cast(h), w, h); - static constexpr uint32_t INPUT_IMAGE_SET_INDEX = 0; - newSubpass->BindInputDescriptorSets (cmdBuffer, INPUT_IMAGE_SET_INDEX, frameIndex); + //static constexpr uint32_t INPUT_IMAGE_SET_INDEX = 0; + auto const& mappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING); + newSubpass->BindInputDescriptorSets (cmdBuffer, mappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_RESOURCE), frameIndex); // draw a quad. cmdBuffer->DrawArrays(4, 1, 0, 0); @@ -570,9 +571,10 @@ namespace SHADE auto cmdBuffer = commandBuffers[frameIndex]; cmdBuffer->BeginLabeledSegment(name); - auto batchingSystemData = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING); + auto const& batchingSystemData = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING); - // Force bind pipeline layout + + // Force bind pipeline layout cmdBuffer->ForceSetPipelineLayout(batchingSystemData.dummyPipelineLayout, SH_PIPELINE_TYPE::GRAPHICS); cmdBuffer->ForceSetPipelineLayout(batchingSystemData.dummyPipelineLayout, SH_PIPELINE_TYPE::COMPUTE); @@ -584,7 +586,7 @@ namespace SHADE if (node->renderpass) { // bind static global data - SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA)); + SHGlobalDescriptorSets::BindGenericAndTextureData(renderGraphStorage->logicalDevice, cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA), frameIndex); // Bind all the buffers required for meshes for (auto& [buffer, bindingPoint] : MESH_DATA) diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index b0d83172..e5cc231c 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -184,12 +184,13 @@ namespace SHADE for (auto& inputAtt : subpass->inputReferences) { auto resource = attResources[inputAtt.attachment]; - if (resource->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT)) + auto typeFlags = resource->resourceTypeFlags; + if (typeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT)) { - if (resource->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR) || - resource->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) + if (typeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR) || + typeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) colorRead |= (1 << i); - else if (resource->resourceTypeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL)) + else if (typeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL) || typeFlags & static_cast(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH)) depthRead |= (1 << i); } else @@ -265,6 +266,7 @@ namespace SHADE // initialize input descriptors subpasses[i]->CreateInputDescriptors(); + subpasses[i]->GenerateDummyPipielineLayout(); ++i; } @@ -664,7 +666,7 @@ namespace SHADE commandBuffer->ForceSetPipelineLayout(SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::RENDER_GRAPH_NODE_COMPUTE).dummyPipelineLayout, SH_PIPELINE_TYPE::COMPUTE); // bind static global data - SHGlobalDescriptorSets::BindStaticGlobalData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA)); + SHGlobalDescriptorSets::BindGenericAndTextureData(graphStorage->logicalDevice, commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA), frameIndex); // bind lighting data SHGlobalDescriptorSets::BindLightingData(commandBuffer, SH_PIPELINE_TYPE::COMPUTE, descMappings.at(SHPredefinedDescriptorTypes::LIGHTS), frameIndex); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index 96207d7a..d45789ce 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -226,11 +226,15 @@ namespace SHADE commandBuffer->SetViewportScissor(static_cast(w), static_cast(h), w, h); } + commandBuffer->ForceSetPipelineLayout(dummyPipelineLayout, SH_PIPELINE_TYPE::GRAPHICS); + auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING); if (renderer) renderer->BindDescriptorSet(commandBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::CAMERA), frameIndex); + BindInputDescriptorSets (commandBuffer, descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_RESOURCE), frameIndex); + // If companion subpass is not a valid handle, render super batch normally if (!companionSubpass.companion) { @@ -439,6 +443,33 @@ namespace SHADE } } + /***************************************************************************/ + /*! + + \brief + Generates the dummy pipeline layout for subpass; specifically add the + input descriptor set layout if it exists. + + + \return + + */ + /***************************************************************************/ + void SHSubpass::GenerateDummyPipielineLayout(void) noexcept + { + auto const& batchingSystemData = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING); + std::vector newLayouts = batchingSystemData.descSetLayouts; + if (inputDescriptorLayout) + { + newLayouts.push_back(inputDescriptorLayout); + } + + dummyPipelineLayout = graphStorage->logicalDevice->CreatePipelineLayoutDummy + ( + SHPipelineLayoutParamsDummy{ newLayouts } + ); + } + /***************************************************************************/ /*! diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h index 811cc70c..1300ee2b 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.h @@ -22,6 +22,7 @@ namespace SHADE class SHRenderer; class SHViewport; class SHVkPipeline; + class SHVkPipelineLayout; class SH_API SHSubpass : public ISelfHandle { @@ -87,6 +88,12 @@ namespace SHADE std::vector> inputSamplers; + //! Dummy pipeline layout for subpass to bind before draw. + //! // IMPORTANT NOTE: After implementing input descriptors, every subpass differs in number input descriptors. + //! Before binding the input descriptors, a pipeline layout containing the desc set layouts + //! for the input descriptors is required, making this umbrella initial dummy bind invalid. + Handle dummyPipelineLayout; + ////! subpass compute image barriers. We do this because every frame has a different ////! swapchain image. If the resource we want to transition is not a swapchain image, @@ -146,6 +153,7 @@ namespace SHADE //void InitComputeBarriers (void) noexcept; void CreateInputDescriptors (void) noexcept; void UpdateWriteDescriptors (void) noexcept; + void GenerateDummyPipielineLayout (void) noexcept; private: /*-----------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.cpp b/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.cpp index fa6b3182..030909af 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.cpp +++ b/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.cpp @@ -7,20 +7,16 @@ namespace SHADE { - SHVkShaderModule::SHVkShaderModule(Handle const& inLogicalDeviceHdl, std::vector const& binaryData, std::string inEntryPoint, vk::ShaderStageFlagBits stage, std::string const& name) noexcept - : logicalDeviceHdl {inLogicalDeviceHdl} - , shaderStage {stage} - , entryPoint {inEntryPoint} - , vkShaderModule {nullptr} - , spirvBinary{} - , shaderName {name} - , reflectedData {} + void SHVkShaderModule::Recompile(void) noexcept { + if (vkShaderModule) + logicalDeviceHdl->GetVkLogicalDevice().destroyShaderModule(vkShaderModule, nullptr); + // Prepare the create info vk::ShaderModuleCreateInfo moduleCreateInfo { - .codeSize = binaryData.size() * sizeof (uint32_t), - .pCode = binaryData.data(), + .codeSize = spirvBinary.size() * sizeof(uint32_t), + .pCode = spirvBinary.data(), }; if (auto result = logicalDeviceHdl->GetVkLogicalDevice().createShaderModule(&moduleCreateInfo, nullptr, &vkShaderModule); result != vk::Result::eSuccess) @@ -30,10 +26,18 @@ namespace SHADE } else SHVulkanDebugUtil::ReportVkSuccess("Successfully created shader module."); + } - // TODO: Right now, this is doing a copy, we need to figure out if its better to just move from the resource management (source library) instead. The hope is that - // shader modules only need 1 of themselves. - spirvBinary = binaryData; + SHVkShaderModule::SHVkShaderModule(Handle const& inLogicalDeviceHdl, std::vector const& binaryData, std::string inEntryPoint, vk::ShaderStageFlagBits stage, std::string const& name) noexcept + : logicalDeviceHdl {inLogicalDeviceHdl} + , shaderStage {stage} + , entryPoint {inEntryPoint} + , vkShaderModule {nullptr} + , spirvBinary{binaryData} + , shaderName {name} + , reflectedData {} + { + Recompile(); } SHVkShaderModule::SHVkShaderModule(SHVkShaderModule&& rhs) noexcept @@ -81,13 +85,18 @@ namespace SHADE } } - void SHVkShaderModule::OnChange(void) noexcept + void SHVkShaderModule::OnChange(std::vector const& newBinaryData) noexcept { + // assign new binary data and recompile shader + spirvBinary = newBinaryData; + + Recompile(); + for (auto& callback : onChangeCallbacks) callback(); } - void SHVkShaderModule::AddCallback(SHShaderChangeCallback&& callback) noexcept + void SHVkShaderModule::AddCallback(ChangeCallback&& callback) noexcept { onChangeCallbacks.emplace_back(std::move(callback)); } @@ -112,4 +121,9 @@ namespace SHADE return reflectedData; } + std::string SHVkShaderModule::GetName(void) const noexcept + { + return shaderName; + } + } \ No newline at end of file diff --git a/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.h b/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.h index 492710f2..341b1706 100644 --- a/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.h +++ b/SHADE_Engine/src/Graphics/Shaders/SHVkShaderModule.h @@ -16,7 +16,7 @@ namespace SHADE /*-----------------------------------------------------------------------*/ /* TYPE DEFINITIONS */ /*-----------------------------------------------------------------------*/ - using SHShaderChangeCallback = std::function; + using ChangeCallback = std::function; private: /*-----------------------------------------------------------------------*/ @@ -47,12 +47,13 @@ namespace SHADE //! response to call all the functions that need to be called. Specifically //! pipeline layouts that need to re-parse the newly reflected data and create //! descriptor set layouts and push constant ranges. - std::vector onChangeCallbacks; + std::vector onChangeCallbacks; // #NoteToSelf: From Tomas module, pipeline shader stage create info isn't created here // because the struct allows specialization info which should not be part of a module itself. // This struct should be created in the pipeline instead. + void Recompile (void) noexcept; public: /*-----------------------------------------------------------------------*/ @@ -67,8 +68,8 @@ namespace SHADE /* PUBLIC MEMBER FUNCTIONS */ /*-----------------------------------------------------------------------*/ void Reflect (void) noexcept; - void OnChange (void) noexcept; - void AddCallback (SHShaderChangeCallback&& callback) noexcept; + void OnChange (std::vector const& newBinaryData) noexcept; + void AddCallback (ChangeCallback&& callback) noexcept; /*-----------------------------------------------------------------------*/ /* SETTERS AND GETTERS */ @@ -77,6 +78,7 @@ namespace SHADE vk::ShaderStageFlagBits GetShaderStageFlagBits (void) const noexcept; vk::ShaderModule GetVkShaderModule (void) const noexcept; SHShaderReflected const& GetReflectedData (void) const noexcept; + std::string GetName (void) const noexcept; }; }