Implemented scanline and silhouette effect #363

Merged
Xenosas1337 merged 12 commits from SP3-1-Rendering into main 2023-02-24 17:20:46 +08:00
47 changed files with 813 additions and 85 deletions

View File

@ -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}

View File

@ -0,0 +1,3 @@
Name: ShinyHightlight
ID: 122370915
Type: 7

View File

@ -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}

View File

@ -0,0 +1,3 @@
Name: Silhouette
ID: 126391182
Type: 7

View File

@ -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

View File

@ -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));

View File

@ -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);
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: ShinyHighlight_FS
ID: 45685219
Type: 2

View File

@ -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);
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: ShinyHighlight_VS
ID: 37048829
Type: 2

View File

@ -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;
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: Silhouette_FS
ID: 42962441
Type: 2

View File

@ -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);
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: Silhouette_VS
ID: 38847805
Type: 2

View File

@ -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;

View File

@ -0,0 +1,20 @@
#pragma once
#include <string>
#include <vector>
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;
};
}

View File

@ -11,6 +11,7 @@
#include "SHpch.h"
#include "SHShaderSourceCompiler.h"
#include "shaderc/shaderc.hpp"
#include "Events/SHEventManager.hpp"
#include <fstream>
#include <sstream>

View File

@ -28,6 +28,8 @@
#include "Filesystem/SHFileSystem.h"
#include <rttr/registration.h>
#include "Assets/Events/SHAssetManagerEvents.h"
#include "Events/SHEventManager.hpp"
namespace SHADE
{
@ -39,7 +41,7 @@ namespace SHADE
std::vector<SHAssetLoader*> SHAssetManager::loaders(TYPE_COUNT);
std::unordered_map<AssetID, SHAsset> SHAssetManager::assetCollection;
std::unordered_map<AssetID, SHAssetData * const> SHAssetManager::assetData;
std::unordered_map<AssetID, SHAssetData *> 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<size_t>(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<SHCompileAssetEvent>(compileShaderEvent, SH_ASSET_COMPILE_EVENT);
}
FolderPointer SHAssetManager::GetRootFolder() noexcept

View File

@ -50,7 +50,7 @@ namespace SHADE
* \return const& to unordered_map<AssetName, AssetID>
****************************************************************************/
static std::vector<SHAsset> GetAllAssets() noexcept;
static std::optional<SHAsset> GetAsset(AssetID id) noexcept;
static std::optional<SHAsset> 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<AssetID, SHAsset> assetCollection;
static std::unordered_map<AssetID, SHAssetData * const> assetData;
static std::unordered_map<AssetID, SHAssetData *> assetData;
};
}

View File

@ -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 };

View File

@ -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<SHVkLogicalDevice> logicalDevice, Handle<SHVkDescriptorSetGroup> 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<Handle<SHVkBuffer>>{ 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;
}
}

View File

@ -0,0 +1,51 @@
#pragma once
#include <cstdint>
#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<SHVkBuffer> gpuBuffer;
//! gpu struct size for GPU to use
uint32_t alignedGpuStructSize;
public:
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkDescriptorSetGroup> 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;
};
}

View File

@ -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<SHVkDescriptorSetGroup> SHGlobalDescriptorSets::staticGlobalDataDescriptorSet;
Handle<SHVkDescriptorSetGroup> SHGlobalDescriptorSets::genericAndTextureDataDescSet;
Handle<SHLightingSubSystem> SHGlobalDescriptorSets::lightingSubSystem;
//void SHGlobalDescriptorSets::BindLightingData(Handle<SHVkCommandBuffer> cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t firstSet) noexcept
@ -20,11 +22,13 @@ namespace SHADE
lightingSubSystem->BindDescSet(cmdBuffer, setIndex, frameIndex);
}
void SHGlobalDescriptorSets::BindStaticGlobalData(Handle<SHVkCommandBuffer> cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t setIndex) noexcept
void SHGlobalDescriptorSets::BindGenericAndTextureData(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> 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<uint32_t, 1> 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<SHVkDescriptorSetGroup> staticGlobalDescSet) noexcept
void SHGlobalDescriptorSets::SetStaticGlobalDataDescriptorSet(Handle<SHVkDescriptorSetGroup> descSet) noexcept
{
staticGlobalDataDescriptorSet = staticGlobalDescSet;
genericAndTextureDataDescSet = descSet;
}
}

View File

@ -15,7 +15,7 @@ namespace SHADE
private:
//! Static global descriptor sets for miscellaneous data and textures
static Handle<SHVkDescriptorSetGroup> staticGlobalDataDescriptorSet;
static Handle<SHVkDescriptorSetGroup> genericAndTextureDataDescSet;
//! Lighting sub system required to get information to bind descriptor sets for light data
static Handle<SHLightingSubSystem> lightingSubSystem;
@ -25,7 +25,7 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
static void BindLightingData (Handle<SHVkCommandBuffer> cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t setIndex, uint32_t frameIndex) noexcept;
static void BindStaticGlobalData (Handle<SHVkCommandBuffer> cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t setIndex) noexcept;
static void BindGenericAndTextureData (Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, SH_PIPELINE_TYPE pipelineType, uint32_t setIndex, uint32_t frameIndex) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */

View File

@ -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

View File

@ -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
};
};

View File

@ -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<SHVkCommandBuffer> 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<SHEventReceiverSpec<SHGraphicsSystem>> thisReceiver
std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> lightEnableShadowReceiver
{
std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveLightEnableShadowEvent)
};
ReceiverPtr receiver = std::dynamic_pointer_cast<SHEventReceiver>(thisReceiver);
SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, receiver);
ReceiverPtr lightEnableShadowReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(lightEnableShadowReceiver);
SHEventManager::SubscribeTo(SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT, lightEnableShadowReceivePtr);
std::shared_ptr<SHEventReceiverSpec<SHGraphicsSystem>> compileAssetReceiever
{
std::make_shared<SHEventReceiverSpec<SHGraphicsSystem>>(this, &SHGraphicsSystem::ReceiveCompileAssetEvent)
};
ReceiverPtr compileAssetReceivePtr = std::dynamic_pointer_cast<SHEventReceiver>(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<SHCameraSystem>();
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<const SHEventSpec<SHCompileAssetEvent>*>(eventPtr.get())->data;
// check for asset type
if (EVENT_DATA->assetType == AssetType::SHADER)
{
// loop through all shaders
auto denseIterators = SHVkInstance::GetResourceManager().GetDenseAccess<SHVkShaderModule>();
for (auto it = denseIterators.first; it != denseIterators.second; ++it)
{
if (it->GetName() == EVENT_DATA->assetName)
{
auto* shaderAsset = SHAssetManager::GetData<SHShaderAsset>(EVENT_DATA->assetID);
it->OnChange(shaderAsset->spirvBinary);
break;
}
}
}
return eventPtr->handle;
}
Handle<SHMaterial> SHGraphicsSystem::AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> 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<SHTexture> 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<SHWindowResizeEvent>(newEvent, SH_WINDOW_RESIZE_EVENT);
#else
// Create new event and broadcast it
SHWindowResizeEvent newEvent;

View File

@ -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<SHVkPipeline> debugDrawFilledDepthPipeline;
Handle<SHVkPipeline> shadowMapPipeline; // initialized only when a shadow map is needed
Handle<SHVkDescriptorSetGroup> genericAndTextureDescSet;
// Built-In Textures
Handle<SHTexture> defaultTexture;

View File

@ -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<SHUIComponent>(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);

View File

@ -63,7 +63,7 @@ namespace SHADE
isDirty = true;
}
void SHTextureLibrary::BuildTextures(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool)
void SHTextureLibrary::BuildTextures(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorSetGroup> descSet/*, Handle<SHVkDescriptorPool> 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<uint32_t>(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<uint32_t>(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

View File

@ -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<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorPool> descPool);
void BuildTextures(Handle<SHVkLogicalDevice> device, Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHVkQueue> graphicsQueue, Handle<SHVkDescriptorSetGroup> descSet/*, Handle<SHVkDescriptorPool> descPool*/);
/*-----------------------------------------------------------------------------*/
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHVkDescriptorSetGroup> GetTextureDescriptorSetGroup() const noexcept { return texDescriptors; }
//Handle<SHVkDescriptorSetGroup> GetTextureDescriptorSetGroup() const noexcept { return descSet; }
/***************************************************************************/
/*!
*
@ -173,8 +180,8 @@ namespace SHADE
std::vector<Handle<SHTexture>> texOrder;
// CPU Storage
std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> combinedImageSamplers;
// GPU Storage
Handle<SHVkDescriptorSetGroup> texDescriptors;
//// GPU Storage
//Handle<SHVkDescriptorSetGroup> descSet;
// Flags
bool isDirty = true;

View File

@ -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);

View File

@ -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;

View File

@ -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<Handle<SHVkShaderModule>> const& SHVkPipelineLayout::GetShaderModules(void) const noexcept

View File

@ -10,6 +10,9 @@ namespace SHADE
class SHVkPipelineLayout
{
public:
using ChangeCallback = std::function<void()>;
private:
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
@ -51,6 +54,12 @@ namespace SHADE
//! Store for pipeline layout recreation
std::vector<vk::DescriptorSetLayout> 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<ChangeCallback> 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 */

View File

@ -512,8 +512,9 @@ namespace SHADE
uint32_t h = static_cast<uint32_t>(resource->GetHeight());
cmdBuffer->SetViewportScissor(static_cast<float>(w), static_cast<float>(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)

View File

@ -184,12 +184,13 @@ namespace SHADE
for (auto& inputAtt : subpass->inputReferences)
{
auto resource = attResources[inputAtt.attachment];
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT))
auto typeFlags = resource->resourceTypeFlags;
if (typeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT))
{
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR) ||
resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT))
if (typeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR) ||
typeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT))
colorRead |= (1 << i);
else if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL))
else if (typeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL) || typeFlags & static_cast<uint32_t>(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);

View File

@ -226,11 +226,15 @@ namespace SHADE
commandBuffer->SetViewportScissor(static_cast<float>(w), static_cast<float>(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 }
);
}
/***************************************************************************/
/*!

View File

@ -22,6 +22,7 @@ namespace SHADE
class SHRenderer;
class SHViewport;
class SHVkPipeline;
class SHVkPipelineLayout;
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
{
@ -87,6 +88,12 @@ namespace SHADE
std::vector<Handle<SHVkSampler>> 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<SHVkPipelineLayout> 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:
/*-----------------------------------------------------------------------*/

View File

@ -7,20 +7,16 @@
namespace SHADE
{
SHVkShaderModule::SHVkShaderModule(Handle<SHVkLogicalDevice> const& inLogicalDeviceHdl, std::vector<uint32_t> 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<SHVkLogicalDevice> const& inLogicalDeviceHdl, std::vector<uint32_t> 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<uint32_t> 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;
}
}

View File

@ -16,7 +16,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* TYPE DEFINITIONS */
/*-----------------------------------------------------------------------*/
using SHShaderChangeCallback = std::function<void()>;
using ChangeCallback = std::function<void()>;
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<SHShaderChangeCallback> onChangeCallbacks;
std::vector<ChangeCallback> 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<uint32_t> 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;
};
}