Fixed major bug when generating new meta files for materials #254

Merged
XiaoQiDigipen merged 5 commits from SP3-13-Assets-Manager into main 2022-11-22 21:55:22 +08:00
160 changed files with 5133 additions and 514 deletions
Showing only changes of commit 5024956c04 - Show all commits

View File

@ -0,0 +1,16 @@
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
12 13
13 14
14 15
15 16

BIN
Assets/Fonts/ALGER.shfont Normal file

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: ALGER
ID: 182525173
Type: 10

BIN
Assets/Fonts/ALGER.ttf Normal file

Binary file not shown.

BIN
Assets/Fonts/SegoeUI.shfont Normal file

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: SegoeUI
ID: 176667660
Type: 10

BIN
Assets/Fonts/SegoeUI.ttf Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
- VertexShader: 46580970
FragmentShader: 35983630
SubPass: G-Buffer Write
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: UIMat
ID: 129340704
Type: 7

104
Assets/Models/Quad.gltf Normal file
View File

@ -0,0 +1,104 @@
{
"asset" : {
"generator" : "Khronos glTF Blender I/O v3.3.27",
"version" : "2.0"
},
"scene" : 0,
"scenes" : [
{
"name" : "Scene",
"nodes" : [
0
]
}
],
"nodes" : [
{
"mesh" : 0,
"name" : "Quad"
}
],
"meshes" : [
{
"name" : "Plane",
"primitives" : [
{
"attributes" : {
"POSITION" : 0,
"NORMAL" : 1,
"TEXCOORD_0" : 2
},
"indices" : 3
}
]
}
],
"accessors" : [
{
"bufferView" : 0,
"componentType" : 5126,
"count" : 4,
"max" : [
0.5,
0.5,
3.774895063202166e-08
],
"min" : [
-0.5,
-0.5,
-3.774895063202166e-08
],
"type" : "VEC3"
},
{
"bufferView" : 1,
"componentType" : 5126,
"count" : 4,
"type" : "VEC3"
},
{
"bufferView" : 2,
"componentType" : 5126,
"count" : 4,
"type" : "VEC2"
},
{
"bufferView" : 3,
"componentType" : 5123,
"count" : 6,
"type" : "SCALAR"
}
],
"bufferViews" : [
{
"buffer" : 0,
"byteLength" : 48,
"byteOffset" : 0,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 48,
"byteOffset" : 48,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 32,
"byteOffset" : 96,
"target" : 34962
},
{
"buffer" : 0,
"byteLength" : 12,
"byteOffset" : 128,
"target" : 34963
}
],
"buffers" : [
{
"byteLength" : 140,
"uri" : "data:application/octet-stream;base64,AAAAvwAAAL9pISIzAAAAPwAAAL9pISIzAAAAvwAAAD9pISKzAAAAPwAAAD9pISKzAAAAAGkhojMAAIA/AAAAAGkhojMAAIA/AAAAAGkhojMAAIA/AAAAAGkhojMAAIA/AAAAAAAAgD8AAIA/AACAPwAAAAAAAAAAAACAPwAAAAAAAAEAAwAAAAMAAgA="
}
]
}

BIN
Assets/Models/Quad.shmodel Normal file

Binary file not shown.

View File

@ -0,0 +1,7 @@
Name: Quad
ID: 80501355
Type: 4
Sub Assets:
Name: Quad
ID: 141771688
Type: 8

View File

@ -15,6 +15,9 @@ layout(set = 2, binding = 0) uniform CameraData
{
vec4 position;
mat4 vpMat;
mat4 viewMat;
mat4 perspectiveMat;
mat4 orthoMat;
} cameraData;
void main()

View File

@ -34,7 +34,8 @@ layout(set = 2, binding = 0) uniform CameraData
vec4 position;
mat4 vpMat;
mat4 viewMat;
mat4 projMat;
mat4 perspectiveMat;
mat4 orthoMat;
} cameraData;
void main()

Binary file not shown.

View File

@ -0,0 +1,59 @@
#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;
int textureIndex;
float alpha;
vec3 beta;
};
layout(location = 0) in struct
{
vec4 vertPos; // location 0
vec2 uv; // location = 1
vec4 normal; // location = 2
} In;
// material stuff
layout(location = 3) flat in struct
{
uint eid;
vec3 textColor;
} In2;
layout(set = 4, binding = 0) uniform sampler2D fontBitmap;
layout(location = 0) out vec4 color;
layout(location = 1) out uint outEntityID;
float median(float r, float g, float b)
{
return max(min(r, g), min(max(r, g), b));
}
void main()
{
vec3 msd = texture (fontBitmap, In.uv).rgb;
float sd = median (msd.r, msd.g, msd.b);
float screenPxDistance = 2 * (sd - 0.5f);
float opacity = clamp (screenPxDistance + 0.5f, 0.0f, 2.0f);
vec4 fragColor;
if (opacity < 0.2f)
discard;
else
fragColor = mix(vec4(0.0f), vec4(In2.textColor, 1.0f), min (opacity, 1.0f));
// fragColor = vec4 (1.0f);
color = fragColor;
outEntityID = In2.eid;
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: Text_FS
ID: 38024754
Type: 2

101
Assets/Shaders/Text_VS.glsl Normal file
View File

@ -0,0 +1,101 @@
#version 450
#extension GL_KHR_vulkan_glsl : enable
//#include "ShaderDescriptorDefinitions.glsl"
// vertex inputs
layout(location = 0) in vec4 positionalOffset;
layout(location = 1) in uint glyphIndex;
// between shader stages
layout(location = 0) out struct
{
vec4 vertPos; // location 0
vec2 uv; // location = 1
vec4 normal; // location = 2
} Out;
// material stuff
layout(location = 3) out struct
{
uint eid;
vec3 textColor;
} Out2;
// Camera data
layout(set = 2, binding = 0) uniform CameraData
{
vec4 position;
mat4 vpMat;
mat4 viewMat;
mat4 perspectiveMat;
mat4 orthoMat;
} cameraData;
// push constants
layout(std140, push_constant) uniform TestPushConstant
{
mat4 worldTransform;
uint eid;
vec3 textColor;
} testPushConstant;
// Descriptor sets
layout(std430, set = 4, binding = 1) buffer GlyphTransforms
{
mat4 matrices[];
} glyphTransforms;
vec2 CreateQuad(in uint vertexID)
{
uint b = 1 << vertexID;
return vec2 ((0x3 & b) != 0, (0x9 & b) != 0);
}
void main()
{
// write EID data to FS
Out2.eid = testPushConstant.eid;
// local variable for font index
uint fontIndex = glyphIndex;
// get font data
mat4 fontData = glyphTransforms.matrices[fontIndex];
// Generate UV coords and vertex positions
Out.uv = CreateQuad(gl_VertexIndex);
vec3 vertexPos = vec3(Out.uv, 0.0f);
// Get the local matrices
mat4 localModel = testPushConstant.worldTransform;
//mat4 uiScale = mat4(1.0f);
//uiScale[0][0] = cameraData.cameraRight / 20.49f;
//uiScale[1][1] = cameraData.cameraTop / 11.323f;
// transform the UV to atlas space to sample the font bitmap correctly
Out.uv = vec2(mat3(fontData) * vec3(Out.uv, 1.0f));
// Matrix to transform the quad from local to font space (for a font to be of correct size)
mat3 toFontSpace = mat3(1.0f);
toFontSpace[0][0] = fontData[3][0];
toFontSpace[1][1] = fontData[3][1];
toFontSpace[2][0] = positionalOffset.x;
toFontSpace[2][1] = positionalOffset.y;
// Initialize variables for use in FS
//characterIndex = gl_InstanceID;
// Transform the vertices to font space
vertexPos = toFontSpace * vec3(vertexPos.xy, 1.0f);
Out2.textColor = testPushConstant.textColor;
// transform the vertex position to font space
gl_Position = cameraData.orthoMat * localModel * vec4(vertexPos, 1.0f);
// gl_Position = vec4(vertexPos, 1.0f);
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: Text_VS
ID: 39816727
Type: 2

View File

@ -0,0 +1,14 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_EXT_nonuniform_qualifier : require
layout (input_attachment_index = 0, set = 4, binding = 0) uniform subpassInput sceneTexture;
layout(location = 0) out vec4 fragColor;
void main()
{
fragColor = vec4 (subpassLoad(sceneTexture).rgb, 1.0f);
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: ToSwapchain_FS
ID: 36869006
Type: 2

View File

@ -0,0 +1,15 @@
#version 450
#extension GL_KHR_vulkan_glsl : enable
vec2 CreateQuad(in uint vertexID)
{
uint b = 1 << vertexID;
return vec2 ((0x3 & b) != 0, (0x9 & b) != 0);
}
void main()
{
vec2 vertexPos = 2 * (CreateQuad(gl_VertexIndex) - vec2(0.5f));
gl_Position = vec4 (vertexPos, 0.0f, 1.0f);
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: ToSwapchain_VS
ID: 48082949
Type: 2

50
Assets/Shaders/UI_FS.glsl Normal file
View File

@ -0,0 +1,50 @@
#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;
int textureIndex;
float alpha;
vec3 beta;
};
layout(location = 0) in struct
{
vec4 vertPos; // location 0
vec2 uv; // location = 1
vec4 normal; // location = 2
} In;
// material stuff
layout(location = 3) flat in struct
{
int materialIndex;
uint eid;
uint lightLayerIndex;
} In2;
layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global)
layout (std430, set = 3, 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;
void main()
{
position = In.vertPos;
normals = In.normal;
albedo = vec4(1.0f);
outEntityID = In2.eid;
lightLayerIndices = In2.lightLayerIndex;
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: UI_FS
ID: 35983630
Type: 2

66
Assets/Shaders/UI_VS.glsl Normal file
View File

@ -0,0 +1,66 @@
#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 = 0) out struct
{
vec4 vertPos; // location 0
vec2 uv; // location = 1
vec4 normal; // location = 2
} Out;
// material stuff
layout(location = 3) out struct
{
int materialIndex;
uint eid;
uint lightLayerIndex;
} Out2;
layout(set = 2, binding = 0) uniform CameraData
{
vec4 position;
mat4 vpMat;
mat4 viewMat;
mat4 perspectiveMat;
mat4 orthoMat;
} 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);
// 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.orthoMat * worldTransform * vec4 (aVertexPos, 1.0f);
gl_Position.z += 0.1f; // HAX
// gl_Position = vec4 (aVertexPos, 1.0f);
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: UI_VS
ID: 46580970
Type: 2

View File

@ -6,7 +6,7 @@ echo ---------------------------------------------------
echo "SHADE DEPENDENCIES (Default - All in 10 Seconds)"
echo "A - All"
echo "B - VMA"
echo "C - msdf"
echo "C - FontCompiler"
echo "D - ModelCompiler"
echo "E - spdlog"
echo "F - reactphysics3d"
@ -28,7 +28,7 @@ set _e=%ERRORLEVEL%
if %_e%==1 goto VMA
if %_e%==2 goto VMA
if %_e%==3 goto MSDF
if %_e%==3 goto FontCompiler
if %_e%==4 goto ModelCompiler
if %_e%==5 goto spdlog
if %_e%==6 goto reactphysics3d
@ -47,12 +47,13 @@ if %_e%==16 goto fmod
echo -----------------------VMA----------------------------
rmdir "Dependencies/VMA" /S /Q
git clone https://github.com/SHADE-DP/VulkanMemoryAllocator.git "Dependencies/VMA"
if %_e%==2 (goto :done) else (goto :MSDF)
if %_e%==2 (goto :done) else (goto :FontCompiler)
:MSDF
echo -----------------------MSDF----------------------------
rmdir "Dependencies/msdf" /S /Q
git clone --recurse-submodules https://github.com/SHADE-DP/msdf-atlas-gen.git "Dependencies/msdf"
:FontCompiler
echo -----------------------FontCompiler----------------------------
rmdir "Dependencies/FontCompiler" /S /Q
git clone https://github.com/SHADE-DP/FontCompiler.git "Dependencies/FontCompiler"
git clone --recurse-submodules https://github.com/SHADE-DP/msdf-atlas-gen "Dependencies/FontCompiler/Dependencies/msdf"
if %_e%==3 (goto :done) else (goto :ModelCompiler)
:ModelCompiler

View File

@ -3,8 +3,9 @@ IncludeDir["ModelCompiler"] = "%{wks.location}\\Dependencies\\ModelCompiler"
IncludeDir["imgui"] = "%{wks.location}\\Dependencies\\imgui"
IncludeDir["imguizmo"] = "%{wks.location}\\Dependencies\\imguizmo"
IncludeDir["imnodes"] = "%{wks.location}\\Dependencies\\imnodes"
IncludeDir["msdf_atlas_gen"] = "%{wks.location}\\Dependencies\\msdf"
IncludeDir["msdfgen"] = "%{wks.location}\\Dependencies\\msdf\\msdfgen"
IncludeDir["FontCompiler"] = "%{wks.location}\\Dependencies\\FontCompiler"
IncludeDir["msdf_atlas_gen"] = "%{wks.location}\\Dependencies\\FontCompiler\\Dependencies\\msdf"
IncludeDir["msdfgen"] = "%{wks.location}\\Dependencies\\FontCompiler\\Dependencies\\msdf\\msdfgen"
IncludeDir["spdlog"] = "%{wks.location}\\Dependencies\\spdlog"
IncludeDir["tracy"] = "%{wks.location}\\Dependencies\\tracy"
IncludeDir["VMA"] = "%{wks.location}\\Dependencies\\VMA"

View File

@ -38,7 +38,9 @@ project "SHADE_Application"
"%{IncludeDir.spdlog}/include",
"%{IncludeDir.tinyddsloader}",
"%{IncludeDir.reactphysics3d}\\include",
"%{IncludeDir.yamlcpp}"
"%{IncludeDir.yamlcpp}",
"%{IncludeDir.msdf_atlas_gen}",
"%{IncludeDir.msdfgen}"
}
externalwarnings "Off"
@ -76,7 +78,10 @@ project "SHADE_Application"
"26451",
"26437",
"4275",
"4635"
"4633",
"4634",
"4635",
"4638"
}
linkoptions { "-IGNORE:4006" }

View File

@ -80,9 +80,12 @@ namespace Sandbox
SHSystemManager::CreateSystem<SHCameraSystem>();
SHSystemManager::CreateSystem<SHUISystem>();
//std::system("FontCompiler.exe ../../Assets/Fonts/SegoeUI.ttf");
//std::system("FontCompiler.exe ../../Assets/Fonts/ALGER.ttf");
SHSystemManager::CreateSystem<SHGraphicsSystem>();
SHGraphicsSystem* graphicsSystem = static_cast<SHGraphicsSystem*>(SHSystemManager::GetSystem<SHGraphicsSystem>());
SHPhysicsSystem* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
// Link up SHDebugDraw
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
@ -140,7 +143,7 @@ namespace Sandbox
//SHComponentManager::CreateComponentSparseSet<SHCameraComponent>();
SHAssetManager::Load();
//auto font = SHAssetManager::GetData<SHFontAsset>(176667660);
SHSystemManager::RegisterRoutine<SHAudioSystem, SHAudioSystem::AudioRoutine>();
@ -160,26 +163,49 @@ namespace Sandbox
void SBApplication::Update(void)
{
SHGraphicsSystem* graphicsSystem = SHADE::SHSystemManager::GetSystem<SHGraphicsSystem>();
#ifdef SHEDITOR
SHEditor* editor = SHADE::SHSystemManager::GetSystem<SHEditor>();
#endif
//TODO: Change true to window is open
while (!window.WindowShouldClose())
{
SHFrameRateController::UpdateFRC();
SHInputManager::UpdateInput(SHFrameRateController::GetRawDeltaTime());
SHSceneManager::UpdateSceneManager();
#ifdef SHEDITOR
if(editor->editorState == SHEditor::State::PLAY)
SHSceneManager::SceneUpdate(0.016f);
#endif
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, 0.016f);
editor->PollPicking();
#endif
SHSceneManager::SceneUpdate(0.016f);
#ifdef SHEDITOR
SHSystemManager::RunRoutines(editor->editorState != SHEditor::State::PLAY, SHFrameRateController::GetRawDeltaTime());
editor->PollPicking();
#else
SHSystemManager::RunRoutines(false, SHFrameRateController::GetRawDeltaTime());
#endif
// TODO: Move into an Editor menu
static bool drawColliders = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
{
drawColliders = !drawColliders;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDER, drawColliders);
}
static bool drawRays = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F11))
{
drawRays = !drawRays;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
}
static bool drawContacts = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F9))
{
drawContacts = !drawContacts;
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_POINTS, drawContacts);
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_NORMALS, drawContacts);
}
}
// Finish all graphics jobs first
graphicsSystem->AwaitGraphicsExecution();

View File

@ -7,12 +7,14 @@
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
#include "Scene/SHSceneManager.h"
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "Physics/System/SHPhysicsSystem.h"
#include "Scripting/SHScriptEngine.h"
#include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
#include "Physics/Interface/SHRigidBodyComponent.h"
#include "Physics/Interface/SHColliderComponent.h"
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
#include "Assets/SHAssetManager.h"
#include "Camera/SHCameraComponent.h"
@ -41,6 +43,28 @@ namespace Sandbox
void SBMainScene::Init()
{
sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID);
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
if (!physicsSystem)
{
SHLOGV_CRITICAL("Failed to get the physics system for building the scene!")
return;
}
physicsSystem->BuildScene(SHSceneManager::GetCurrentSceneGraph());
/*-----------------------------------------------------------------------*/
/* TESTING CODE */
/*-----------------------------------------------------------------------*/
//testText = SHEntityManager::CreateEntity<SHTransformComponent, SHTextRendererComponent>(MAX_EID, "Test Text");
//auto gfxSystem =SHSystemManager::GetSystem<SHGraphicsSystem>();
//auto textComp = SHComponentManager::GetComponent<SHTextRendererComponent>(testText);
//textComp->SetFont(gfxSystem->GetFontLibrary().GetFonts()[0]);
/*-----------------------------------------------------------------------*/
/* TESTING CODE */
/*-----------------------------------------------------------------------*/
}
void SBMainScene::Update(float dt)

View File

@ -12,6 +12,8 @@ namespace Sandbox
EntityID testObj;
std::vector<EntityID> stressTestObjects;
EntityID testText;
public:
virtual void Load();
virtual void Init();

View File

@ -50,6 +50,9 @@ project "SHADE_CSharp"
function platformsElementCS(cfg)
_p(2,'<Platforms>x64</Platforms>')
end
function configElementCS(cfg)
_p(2,'<Configurations>Debug;Release;Publish</Configurations>')
end
function docsElementCS(cfg)
_p(2,'<GenerateDocumentationFile>true</GenerateDocumentationFile>')
end
@ -59,6 +62,6 @@ project "SHADE_CSharp"
premake.override(premake.vstudio.cs2005.elements, "projectProperties", function (oldfn, cfg)
return table.join(oldfn(cfg), {
platformsElementCS, docsElementCS, docsLocationElementCS,
platformsElementCS, configElementCS, docsElementCS, docsLocationElementCS,
})
end)

View File

@ -79,7 +79,10 @@ project "SHADE_Engine"
"26451",
"26437",
"4275",
"4635"
"4633",
"4634",
"4635",
"4638"
}
linkoptions { "-IGNORE:4006" }
@ -119,6 +122,7 @@ project "SHADE_Engine"
{
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Debug\\ModelCompiler.exe\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.FontCompiler}\\bin\\Debug\\FontCompiler.exe\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodL.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\""
}
@ -128,6 +132,7 @@ project "SHADE_Engine"
{
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Release\\ModelCompiler.exe\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.FontCompiler}\\bin\\Release\\FontCompiler.exe\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
}

View File

@ -0,0 +1,47 @@
#pragma once
#include "SHAssetData.h"
#include "SH_API.h"
#include <vector>
#include <string>
#include "msdf-atlas-gen/msdf-atlas-gen.h"
#include "math/SHMatrix.h"
namespace SHADE
{
struct SH_API SHFontAsset : SHAssetData
{
using GlyphData = SHMatrix;
static constexpr uint32_t NUM_CHANNELS = 3;
static constexpr uint32_t BYTES_PER_CHANNEL = 3;
static constexpr uint8_t BASELINE_LEFT_MATRIX_INDEX_ROW = 3;
static constexpr uint8_t BASELINE_LEFT_MATRIX_INDEX_COL = 2;
static constexpr uint8_t BASELINE_BOTTOM_MATRIX_INDEX_ROW = 3;
static constexpr uint8_t BASELINE_BOTTOM_MATRIX_INDEX_COL = 3;
/*-----------------------------------------------------------------------*/
/* MEMBER VARIABLES */
/*-----------------------------------------------------------------------*/
//! Name of the shader file (without parent path)
std::string fontName;
//! Glyphs. Corresponds to the transformation container below.
std::vector<msdf_atlas::unicode_t> glyphs;
//! Data containing character and uv transformation data and other misc data
std::vector<GlyphData> glyphTransformations;
//! The actual data of the atlas to go into the binary. Was unique_ptr, vector easier to copy.
std::vector<unsigned char> bitmapData;
//! Width of the bitmap
uint32_t bitmapWidth;
//! Height of the bitmap
uint32_t bitmapHeight;
//! Font geometry required to get kerning from
msdf_atlas::FontGeometry fontGeometry;
};
}

View File

@ -0,0 +1,83 @@
#include "SHpch.h"
#include "SHFontLoader.h"
#include "Assets/Asset Types/SHFontAsset.h"
#include "Graphics/MiddleEnd/TextRendering/SHFreetypeInstance.h"
#include "msdf-atlas-gen/msdf-atlas-gen.h"
#include <fstream>
#include <sstream>
#include <string>
#include <algorithm>
namespace SHADE
{
SHADE::SHAssetData* SHFontLoader::Load(AssetPath path)
{
auto newFontAsset = new SHFontAsset();
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
if (!file.is_open())
{
SHLOG_ERROR("Unable to open compiled font file: {}", path.string());
return nullptr;
}
// Attempt to load font geometry for advance data
auto ttfFilePath = path.string();
ttfFilePath = ttfFilePath.substr(0, ttfFilePath.find_last_of('.'));
ttfFilePath += TTF_EXTENSION.data();
msdfgen::FontHandle* fontHandle = nullptr;
fontHandle = msdfgen::loadFont(SHFreetypeInstance::GetFreetypeHandle(), ttfFilePath.c_str());
newFontAsset->fontGeometry.loadCharset(fontHandle, 1.0f, msdf_atlas::Charset::ASCII);
uint32_t numGlyphs = 0;
// read how many glyphs we have
file.read (reinterpret_cast<char*>(&numGlyphs), sizeof (uint32_t));
newFontAsset->glyphs.resize(numGlyphs);
newFontAsset->glyphTransformations.resize(numGlyphs);
for (uint32_t i = 0; i < numGlyphs; ++i)
{
// Read the data for the glyph
file.read(reinterpret_cast<char*>(&newFontAsset->glyphs[i]), sizeof(msdf_atlas::unicode_t));
}
for (uint32_t i = 0; i < numGlyphs; ++i)
{
// Read the data for the glyph transformations
file.read(reinterpret_cast<char*>(&newFontAsset->glyphTransformations[i]), sizeof(SHMatrix));
}
// read the width
file.read(reinterpret_cast<char*>(&newFontAsset->bitmapWidth), sizeof(SHFontAsset::bitmapWidth));
// read the height
file.read(reinterpret_cast<char*>(&newFontAsset->bitmapHeight), sizeof(SHFontAsset::bitmapHeight));
uint32_t bytesRequired = 0;
file.read(reinterpret_cast<char*>(&bytesRequired), sizeof(uint32_t));
// Read the bitmap
newFontAsset->bitmapData.resize(bytesRequired);
file.read(reinterpret_cast<char*>(newFontAsset->bitmapData.data()), bytesRequired);
file.close();
return newFontAsset;
}
void SHFontLoader::Write(SHAssetData const* data, AssetPath path)
{
/*
Stuff to write to binary file :
- Interleaved per character data
- codepoint (actual character)
- 4x4 Matrix data (stores UV transform + extra data)
- Actual atlas texture
*/
}
}

View File

@ -0,0 +1,24 @@
/*************************************************************************//**
* \file SHSFontLoader.h
* \author Loh Xiao Qi
* \date 23 10 2022
* \brief
*
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
*****************************************************************************/
#pragma once
#include "Assets/Libraries/Loaders/SHAssetLoader.h"
namespace SHADE
{
struct SHFontLoader : SHAssetLoader
{
SHAssetData* Load(AssetPath path) override;
void Write(SHAssetData const* data, AssetPath path) override;
};
}

View File

@ -67,8 +67,9 @@ constexpr std::string_view ASSET_ROOT {"../../Assets"};
constexpr std::string_view BUILT_IN_ASSET_ROOT{ "../../Built_In" };
#endif
// COMPILER PATHS
// COMPILER EXE
constexpr std::string_view MODEL_COMPILER_EXE{ "ModelCompiler.exe" };
constexpr std::string_view FONT_COMPILER_EXE{ "FontCompiler.exe" };
// INTERNAL ASSET PATHS
constexpr std::string_view SCENE_FOLDER{ "/Scenes/" };
@ -82,13 +83,13 @@ constexpr std::string_view AUDIO_EXTENSION {".ogg"};
constexpr std::string_view AUDIO_WAV_EXTENSION {".wav"};
constexpr std::string_view SHADER_EXTENSION{ ".shshader" };
constexpr std::string_view SHADER_BUILT_IN_EXTENSION{ ".shshaderb" };
constexpr std::string_view FONT_EXTENSION{ ".shfont" };
constexpr std::string_view SCRIPT_EXTENSION {".cs"};
constexpr std::string_view SCENE_EXTENSION {".shade"};
constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
constexpr std::string_view MODEL_EXTENSION{ ".shmodel" };
constexpr std::string_view FONT_EXTENSION{ ".shfont" };
constexpr std::string_view EXTENSIONS[] = {
AUDIO_EXTENSION,

View File

@ -20,6 +20,7 @@
#include "Libraries/Loaders/SHTextureLoader.h"
#include "Libraries/Loaders/SHShaderSourceLoader.h"
#include "Libraries/Loaders/SHTextBasedLoader.h"
#include "Libraries/Loaders/SHFontLoader.h"
//#include "Libraries/Compilers/SHMeshCompiler.h"
#include "Libraries/Compilers/SHTextureCompiler.h"
@ -392,7 +393,13 @@ namespace SHADE
auto const ext{ path.extension().string() };
if (ext == GLSL_EXTENSION.data())
{
newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
auto value { SHShaderSourceCompiler::LoadAndCompileShader(path) };
if (!value.has_value())
{
SHLOG_ERROR("Shader compile failed: {}", path.string());
return;
}
newPath = value.value();
}
else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
{
@ -414,6 +421,16 @@ namespace SHADE
}
newPath = pathGen.value();
}
else if (ext == TTF_EXTENSION.data())
{
std::string command = FONT_COMPILER_EXE.data();
command += " " + path.string();
std::system(command.c_str());
std::string fontPath = path.string().substr(0, path.string().find_last_of('.'));
fontPath += FONT_EXTENSION;
newPath = fontPath;
}
else
{
SHLOG_WARNING("[Asset Manager] File Type compilation not yet Implemented: {}", path.string());
@ -466,6 +483,8 @@ namespace SHADE
loaders[static_cast<size_t>(AssetType::PREFAB)] = loaders[static_cast<size_t>(AssetType::SCENE)];
loaders[static_cast<size_t>(AssetType::MATERIAL)] = loaders[static_cast<size_t>(AssetType::SCENE)];
loaders[static_cast<size_t>(AssetType::MESH)] = nullptr;
loaders[static_cast<size_t>(AssetType::SCRIPT)] = nullptr;
loaders[static_cast<size_t>(AssetType::FONT)] = dynamic_cast<SHAssetLoader*>(new SHFontLoader());
}
/****************************************************************************

View File

@ -43,7 +43,9 @@ namespace SHADE
if (!camComponent)
{
SHLOG_WARNING("Camera Director warning: Entity does not have a camera");
return nullptr;
}
return camComponent;
}

View File

@ -246,7 +246,7 @@ namespace SHADE
camera.orthoProjMatrix(2, 3) = -n / (f-n);
camera.orthoProjMatrix(3, 3) = 1.0f;
camera.orthoProjMatrix = SHMatrix::OrthographicRH(camera.GetWidth(), camera.GetHeight(), camera.GetNear(), camera.GetFar());
//camera.orthoProjMatrix = SHMatrix::OrthographicRH(camera.GetWidth(), camera.GetHeight(), camera.GetNear(), camera.GetFar());
//camera.projMatrix.Transpose();
camera.dirtyProj = false;

View File

@ -146,7 +146,7 @@ namespace SHADE
//Call all the children to Destroy themselves first before the parent is destroyed.
if (entityVec[eIndex])
{
auto& children = SHSceneManager::GetCurrentSceneGraph().GetChildren(eID);
auto children = SHSceneManager::GetCurrentSceneGraph().GetChildren(eID);
for (auto& child : children)
{
DestroyEntity(child->GetEntityID());

View File

@ -21,7 +21,7 @@ namespace SHADE
template<typename T>
static bool SetPayload(DragDropTag const& type, T* object, ImGuiCond const cond = 0)
{
ImGui::SetDragDropPayload(type.data(), static_cast<void*>(object), sizeof(T), cond);
hasDragDrop = ImGui::SetDragDropPayload(type.data(), static_cast<void*>(object), sizeof(T), cond);
hasDragDrop = true;
currentDragDropTag = type;

View File

@ -252,7 +252,7 @@ namespace SHADE
if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields
{
SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetGravityEnabled(value);}, "Gravity");
SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass");
//SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass");
}
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
{
@ -264,14 +264,19 @@ namespace SHADE
SHEditorWidgets::BeginPanel(std::format("{} Constraints", ICON_FA_LOCK).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
SHEditorWidgets::TextLabel("Freeze Position");
ImGui::PushID("FreezePos");
SHEditorWidgets::CheckBox("X", [component] {return component->GetFreezePositionX(); }, [component](bool const& value) {component->SetFreezePositionX(value); }, "Freeze Position - X"); ImGui::SameLine();
SHEditorWidgets::CheckBox("Y", [component] {return component->GetFreezePositionY(); }, [component](bool const& value) {component->SetFreezePositionY(value); }, "Freeze Position - Y"); ImGui::SameLine();
SHEditorWidgets::CheckBox("Z", [component] {return component->GetFreezePositionZ(); }, [component](bool const& value) {component->SetFreezePositionZ(value); }, "Freeze Position - Z");
ImGui::PopID();
SHEditorWidgets::TextLabel("Freeze Rotation");
ImGui::PushID("FreezeRot");
SHEditorWidgets::CheckBox("X", [component] {return component->GetFreezeRotationX(); }, [component](bool const& value) {component->SetFreezeRotationX(value); }, "Freeze Rotation - X"); ImGui::SameLine();
SHEditorWidgets::CheckBox("Y", [component] {return component->GetFreezeRotationY(); }, [component](bool const& value) {component->SetFreezeRotationY(value); }, "Freeze Rotation - Y"); ImGui::SameLine();
SHEditorWidgets::CheckBox("Z", [component] {return component->GetFreezeRotationZ(); }, [component](bool const& value) {component->SetFreezeRotationZ(value); }, "Freeze Rotation - Z");
ImGui::PopID();
SHEditorWidgets::EndPanel();
}
@ -279,6 +284,7 @@ namespace SHADE
//Debug Info (Read-Only)
if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields
{
SHEditorWidgets::DragFloat("Mass", [component] { return component->GetMass(); }, [](float value){}, "Mass", 0.1f, 0.0f, std::numeric_limits<float>::infinity(), "%.3f", ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
@ -490,4 +496,52 @@ namespace SHADE
}
ImGui::PopID();
}
template<>
static void DrawComponent(SHTextRenderableComponent* component)
{
if (!component)
return;
ImGui::PushID(SHFamilyID<SHComponent>::GetID<SHTextRenderableComponent>());
const auto componentType = rttr::type::get(*component);
SHEditorWidgets::CheckBox("##IsActive", [component]() {return component->isActive; }, [component](bool const& active) {component->isActive = active; }, "Is Component Active");
ImGui::SameLine();
if (ImGui::CollapsingHeader(componentType.get_name().data()))
{
DrawContextMenu(component);
Handle<SHFont> const& font = component->GetFont();
const auto FONT_NAME = SHResourceManager::GetAssetName<SHFont>(font).value_or("");
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Font", FONT_NAME, [component]()
{
Handle<SHFont> const& font = component->GetFont();
return SHResourceManager::GetAssetID<SHFont>(font).value_or(0);
},
[component](AssetID const& id)
{
if (SHAssetManager::GetType(id) != AssetType::FONT)
{
SHLOG_WARNING("Attempted to assign non font asset to TextRendererComponent Font property!")
return;
}
component->SetFont(SHResourceManager::LoadOrGet<SHFont>(id));
SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE);
SHEditorWidgets::InputText("Text",
[component](void)
{
return component->GetText();
},
[component](std::string const& val)
{
component->SetText(val);
}
);
}
else
{
DrawContextMenu(component);
}
ImGui::PopID();
}
}

View File

@ -22,6 +22,7 @@
#include "UI/SHCanvasComponent.h"
#include "SHEditorComponentView.h"
#include "AudioSystem/SHAudioListenerComponent.h"
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
namespace SHADE
{
@ -144,6 +145,10 @@ namespace SHADE
{
DrawComponent(uiComponent);
}
if (auto textRendererComponent = SHComponentManager::GetComponent_s<SHTextRenderableComponent>(eid))
{
DrawComponent(textRendererComponent);
}
ImGui::Separator();
// Render Scripts
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
@ -162,6 +167,7 @@ namespace SHADE
DrawAddComponentWithEnforcedComponentButton<SHRenderable, SHTransformComponent>(eid);
DrawAddComponentWithEnforcedComponentButton<SHRigidBodyComponent, SHTransformComponent>(eid);
DrawAddComponentWithEnforcedComponentButton<SHColliderComponent, SHTransformComponent>(eid);
DrawAddComponentWithEnforcedComponentButton<SHTextRenderableComponent, SHTransformComponent>(eid);
ImGui::EndMenu();

View File

@ -172,17 +172,24 @@ namespace SHADE
// Shader
bool shaderChanged = false;
const auto* SHADER_INFO = SHAssetManager::GetData<SHShaderAsset>(currentMatSpec->fragShader);
const std::string SHADER_NAME = SHADER_INFO ? SHADER_INFO->name : "Unknown Shader";
ImGui::BeginDisabled();
const auto* VERT_SHADER_INFO = SHAssetManager::GetData<SHShaderAsset>(currentMatSpec->vertexShader);
const std::string VERT_SHADER_NAME = VERT_SHADER_INFO ? VERT_SHADER_INFO->name : "Unknown Shader";
isDirty |= SHEditorWidgets::DragDropReadOnlyField<AssetID>
(
"Fragment Shader", SHADER_NAME.data(),
"Fragment Shader", VERT_SHADER_NAME.data(),
[this]() { return currentMatSpec->vertexShader; },
[this](const AssetID& id) { currentMatSpec->vertexShader = id; },
SHDragDrop::DRAG_RESOURCE
);
const auto* FRAG_SHADER_INFO = SHAssetManager::GetData<SHShaderAsset>(currentMatSpec->fragShader);
const std::string FRAG_SHADER_NAME = FRAG_SHADER_INFO ? FRAG_SHADER_INFO->name : "Unknown Shader";
isDirty |= SHEditorWidgets::DragDropReadOnlyField<AssetID>
(
"Fragment Shader", FRAG_SHADER_NAME.data(),
[this]() { return currentMatSpec->fragShader; },
[this](const AssetID& id) { currentMatSpec->fragShader = id; },
SHDragDrop::DRAG_RESOURCE
);
ImGui::EndDisabled();
// Load the shader to access it's data
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);

View File

@ -516,7 +516,7 @@ namespace SHADE
ImGui_ImplVulkan_DestroyFontUploadObjects();
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd)
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer>& cmd, uint32_t frameIndex)
{
cmd->BeginLabeledSegment("ImGui Draw");
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());

View File

@ -155,16 +155,23 @@ namespace SHADE
}
bool SHEditorUI::InputCheckbox(const std::string& label, bool& value, bool* isHovered)
{
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
return ImGui::Checkbox("##", &value);
}
bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
{
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
@ -177,7 +184,11 @@ namespace SHADE
bool SHEditorUI::InputUnsignedInt(const std::string& label, unsigned int& value, bool* isHovered)
{
int signedVal = static_cast<int>(value);
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
@ -190,8 +201,12 @@ namespace SHADE
return CHANGED;
}
bool SHEditorUI::InputFloat(const std::string& label, float& value, bool* isHovered)
{
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
@ -212,8 +227,12 @@ namespace SHADE
return CHANGED;
}
bool SHEditorUI::InputSlider(const std::string& label, int min, int max, int& value, bool* isHovered /*= nullptr*/)
{
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
@ -235,8 +254,12 @@ namespace SHADE
}
bool SHEditorUI::InputSlider(const std::string& label, float min, float max, float& value, bool* isHovered)
{
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
@ -272,7 +295,11 @@ namespace SHADE
{
std::array<char, TEXT_FIELD_MAX_LENGTH> buffer = { '\0' };
strcpy_s(buffer.data(), TEXT_FIELD_MAX_LENGTH, value.c_str());
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
@ -285,8 +312,12 @@ namespace SHADE
}
bool SHEditorUI::InputGameObjectField(const std::string& label, uint32_t& value, bool* isHovered, bool alwaysNull)
{
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();
@ -326,7 +357,11 @@ namespace SHADE
const std::string& INITIAL_NAME = v >= static_cast<int>(enumNames.size()) ? "Unknown" : enumNames[v];
bool b = false;
if (!label.empty())
{
ImGui::Text(label.c_str());
ImGui::SameLine();
}
if (isHovered)
*isHovered = ImGui::IsItemHovered();
ImGui::SameLine();

View File

@ -25,12 +25,9 @@ namespace SHADE
{
if (cmdBufferHdl && (bufferUsageFlags & vk::BufferUsageFlagBits::eTransferDst))
{
vk::BufferCopy copyRegion
{
.srcOffset = 0,
.dstOffset = 0,
.size = sizeStored,
};
vk::BufferCopy copyRegion{};
PrepareBufferCopy(copyRegion);
cmdBufferHdl->GetVkCommandBuffer().copyBuffer(stagingBuffer, vkBuffer, 1, &copyRegion);
}
}
@ -54,6 +51,13 @@ namespace SHADE
vmaFlushAllocation(vmaAllocator, alloc, srcOffset, dstOffset);
}
void SHVkBuffer::PrepareBufferCopy(vk::BufferCopy& bufferCopy) noexcept
{
bufferCopy.srcOffset = 0;
bufferCopy.dstOffset = 0;
bufferCopy.size = sizeStored;
}
vk::Buffer SHVkBuffer::GetVkBuffer(void) const noexcept
{
return vkBuffer;

View File

@ -106,6 +106,7 @@ namespace SHADE
void ResizeNoCopy (uint32_t newSize);
void ResizeReplace (uint32_t newSize, void* data, uint32_t srcSize);
void FlushAllocation (uint32_t srcOffset, uint32_t dstOffset) noexcept;
void PrepareBufferCopy (vk::BufferCopy& bufferCopy) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */

View File

@ -459,7 +459,7 @@ namespace SHADE
return SHVkInstance::GetResourceManager().Create<SHVkImage>(GetHandle(), &vmaAllocator, w, h, levels, format, usage, create);
}
Handle<SHVkImage> SHVkLogicalDevice::CreateImage(SHImageCreateParams const& imageDetails, unsigned char* data, uint32_t dataSize, std::span<uint32_t> inMipOffsets, VmaMemoryUsage memUsage, VmaAllocationCreateFlags allocFlags) noexcept
Handle<SHVkImage> SHVkLogicalDevice::CreateImage(SHImageCreateParams const& imageDetails, unsigned char* data, uint32_t dataSize, std::vector<uint32_t> const& inMipOffsets, VmaMemoryUsage memUsage, VmaAllocationCreateFlags allocFlags) noexcept
{
return SHVkInstance::GetResourceManager().Create<SHVkImage>(GetHandle(), &vmaAllocator, imageDetails, data, dataSize, inMipOffsets, memUsage, allocFlags);
}

View File

@ -162,7 +162,7 @@ namespace SHADE
SHImageCreateParams const& imageDetails,
unsigned char* data,
uint32_t dataSize,
std::span<uint32_t> inMipOffsets,
std::vector<uint32_t> const& inMipOffsets,
VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags
) noexcept;

View File

@ -123,7 +123,7 @@ namespace SHADE
SHImageCreateParams const& imageDetails,
const unsigned char* data,
uint32_t dataSize,
std::span<uint32_t> inMipOffsets,
std::vector<uint32_t> const& inMipOffsets,
VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags
) noexcept
@ -311,6 +311,22 @@ namespace SHADE
CreateFramebufferImage();
}
void SHVkImage::PrepareImageCopy(std::vector<vk::BufferImageCopy>& bufferImageCopy) noexcept
{
for (uint32_t i = 0; i < mipOffsets.size(); ++i)
{
bufferImageCopy[i].bufferOffset = mipOffsets[i];
bufferImageCopy[i].bufferRowLength = 0; // for padding
bufferImageCopy[i].bufferImageHeight = 0; // for padding
bufferImageCopy[i].imageSubresource.aspectMask = vk::ImageAspectFlagBits::eColor; // TODO: Need to change this to base it off image format.
bufferImageCopy[i].imageSubresource.mipLevel = i;
bufferImageCopy[i].imageSubresource.baseArrayLayer = 0; // TODO: Array textures not supported yet
bufferImageCopy[i].imageSubresource.layerCount = layerCount;
bufferImageCopy[i].imageOffset = vk::Offset3D{ 0,0,0 };
bufferImageCopy[i].imageExtent = vk::Extent3D{ width >> i, height >> i, 1 };
}
}
void SHVkImage::LinkWithExteriorImage(vk::Image inVkImage, vk::ImageType type, uint32_t inWidth, uint32_t inHeight, uint32_t inDepth, uint32_t layers, uint8_t levels, vk::Format format, vk::ImageUsageFlags flags) noexcept
{
vkImage = inVkImage;
@ -405,4 +421,9 @@ namespace SHADE
return height;
}
uint32_t SHVkImage::GetMipLevels(void) const noexcept
{
return mipLevelCount;
}
}

View File

@ -102,7 +102,7 @@ namespace SHADE
vk::Buffer stagingBuffer;
//! Mipmap offsets for initializing the vk::BufferImageCopy during transfer to GPU resource
std::span<uint32_t> mipOffsets;
std::vector<uint32_t> mipOffsets;
//! Handle to the device that creates these images
Handle<SHVkLogicalDevice> device;
@ -125,7 +125,7 @@ namespace SHADE
SHImageCreateParams const& imageDetails,
const unsigned char* data,
uint32_t dataSize,
std::span<uint32_t> inMipOffsets,
std::vector<uint32_t> const& inMipOffsets,
VmaMemoryUsage memUsage,
VmaAllocationCreateFlags allocFlags
) noexcept;
@ -142,6 +142,7 @@ namespace SHADE
void TransferToDeviceResource (Handle<SHVkCommandBuffer> cmdBufferHdl) noexcept;
void PrepareImageTransitionInfo (vk::ImageLayout oldLayout, vk::ImageLayout newLayout, vk::ImageMemoryBarrier& barrier) noexcept;
void HandleResizeFramebufferImage(uint32_t newWidth, uint32_t newHeight) noexcept;
void PrepareImageCopy (std::vector<vk::BufferImageCopy>& bufferImageCopy) noexcept;
/*-----------------------------------------------------------------------*/
/* GETTERS AND SETTERS */
@ -153,6 +154,7 @@ namespace SHADE
vk::Format GetImageFormat (void) const noexcept;
uint32_t GetWidth (void) const noexcept;
uint32_t GetHeight (void) const noexcept;
uint32_t GetMipLevels (void) const noexcept;
};
}

View File

@ -27,6 +27,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Math/Transform/SHTransformComponent.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Graphics/Descriptors/SHVkDescriptorPool.h"
#include "Scene/SHSceneManager.h"
#include "UI/SHUIComponent.h"
namespace SHADE
{
@ -49,7 +51,7 @@ namespace SHADE
, referencedMatInstances { std::move(rhs.referencedMatInstances) }
, matBufferDirty { std::move(rhs.matBufferDirty) }
, subBatches { std::move(rhs.subBatches) }
, drawData { std::move(drawData) }
, drawData { std::move(rhs.drawData) }
, transformData { std::move(rhs.transformData) }
, instancedIntegerData { std::move(rhs.instancedIntegerData) }
, matPropsData { std::move(rhs.matPropsData) }
@ -80,7 +82,7 @@ namespace SHADE
referencedMatInstances = std::move(rhs.referencedMatInstances);
matBufferDirty = std::move(rhs.matBufferDirty) ;
subBatches = std::move(rhs.subBatches) ;
drawData = std::move(drawData) ;
drawData = std::move(rhs.drawData) ;
transformData = std::move(rhs.transformData) ;
instancedIntegerData = std::move(rhs.instancedIntegerData) ;
matPropsData = std::move(rhs.matPropsData) ;
@ -218,9 +220,13 @@ namespace SHADE
for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i)
{
drawDataBuffer[i].Free();
drawDataBuffer[i] = {};
transformDataBuffer[i].Free();
transformDataBuffer[i] = {};
instancedIntegerBuffer[i].Free();
instancedIntegerBuffer[i] = {};
matPropsBuffer[i].Free();
matPropsBuffer[i] = {};
}
}
@ -302,9 +308,30 @@ namespace SHADE
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(rendId);
if (transform)
{
if (SHSceneManager::CheckNodeAndComponentsActive<SHRenderable>(rendId))
{
auto uiComp = SHComponentManager::GetComponent_s<SHUIComponent>(rendId);
if (uiComp)
{
transformData.emplace_back(uiComp->GetMatrix());
}
else
transformData.emplace_back(transform->GetTRS());
}
else
{
// Should be deactivated
static const SHMatrix ZERO_MTX =
{
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f
};
transformData.emplace_back(ZERO_MTX);
}
}
else
{
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
transformData.emplace_back();
@ -425,14 +452,29 @@ namespace SHADE
{
// Transform
auto transform = SHComponentManager::GetComponent_s<SHTransformComponent>(rendId);
if (!transform)
if (transform)
{
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
transformData.emplace_back();
if (SHSceneManager::CheckNodeAndComponentsActive<SHRenderable>(rendId))
{
transformData.emplace_back(transform->GetTRS());
}
else
{
transformData.emplace_back(transform->GetTRS());
// Should be deactivated
static const SHMatrix ZERO_MTX =
{
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f
};
transformData.emplace_back(ZERO_MTX);
}
}
else
{
SHLOG_WARNING("[SHBatch] Entity contianing a SHRenderable with no SHTransformComponent found!");
transformData.emplace_back();
}
const SHRenderable* renderable = SHComponentManager::GetComponent<SHRenderable>(rendId);
@ -507,9 +549,13 @@ namespace SHADE
return;
}
// Nothing to draw
if (subBatches.empty())
return;
// Bind all required objects before drawing
static std::array<uint32_t, 1> dynamicOffset{ 0 };
cmdBuffer->BeginLabeledSegment("SHBatch");
cmdBuffer->BeginLabeledSegment("SHBatch for Pipeline #" + std::to_string(pipeline.GetId().Data.Index));
cmdBuffer->BindPipeline(pipeline);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);

View File

@ -55,7 +55,8 @@ namespace SHADE
void SHSuperBatch::Remove(const SHRenderable* renderable) noexcept
{
const Handle<SHVkPipeline> PIPELINE = renderable->GetMaterial()->GetBaseMaterial()->GetPipeline();
Handle<SHMaterial> baseMat = (renderable->HasMaterialChanged() ? renderable->GetPrevMaterial() : renderable->GetMaterial())->GetBaseMaterial();
const Handle<SHVkPipeline> PIPELINE = baseMat->HasPipelineChanged() ? baseMat->GetPrevPipeline() : baseMat->GetPipeline();
// Check if we have a Batch with the same pipeline yet
auto batch = std::find_if(batches.begin(), batches.end(), [&](const SHBatch& batch)

View File

@ -97,6 +97,8 @@ namespace SHADE
Handle<SHVkDescriptorSetLayout> materialDataPerInstanceLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, { materialDataBinding });
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, materialDataPerInstanceLayout->GetVkHandle(), "[Descriptor Set Layout] Material Globals");
globalDescSetLayouts.push_back(staticGlobalLayout);
globalDescSetLayouts.push_back(dynamicGlobalLayout);
globalDescSetLayouts.push_back(cameraDataGlobalLayout);

View File

@ -90,7 +90,7 @@ namespace SHADE
auto const& RENDERERS = GFX_SYSTEM->GetDefaultViewport()->GetRenderers();
auto renderGraph = RENDERERS[SHGraphicsConstants::RenderGraphIndices::WORLD]->GetRenderGraph();
auto subPass = renderGraph->GetNode("Debug Draw")->GetSubpass("Debug Draw");
subPass->AddExteriorDrawCalls([this, GFX_SYSTEM](Handle<SHVkCommandBuffer>& cmdBuffer)
subPass->AddExteriorDrawCalls([this, GFX_SYSTEM](Handle<SHVkCommandBuffer>& cmdBuffer, uint32_t frameIndex)
{
// Get Current frame index
const uint32_t FRAME_IDX = GFX_SYSTEM->GetCurrentFrameIndex();
@ -106,7 +106,7 @@ namespace SHADE
}
});
auto subPassWithDepth = renderGraph->GetNode("Debug Draw with Depth")->GetSubpass("Debug Draw with Depth");
subPassWithDepth->AddExteriorDrawCalls([this, GFX_SYSTEM](Handle<SHVkCommandBuffer>& cmdBuffer)
subPassWithDepth->AddExteriorDrawCalls([this, GFX_SYSTEM](Handle<SHVkCommandBuffer>& cmdBuffer, uint32_t frameIndex)
{
// Get Current frame index
const uint32_t FRAME_IDX = GFX_SYSTEM->GetCurrentFrameIndex();

View File

@ -66,7 +66,9 @@ namespace SHADE
/***************************************************************************/
/*!
\brief
DescriptorSet Index for render graph resources.
DescriptorSet Index for render graph resources. Unlike the sets from
1 to 3 and 6, this set index does not have hard coded bindings and is
NOT part of the layouts included in the global data.
*/
/***************************************************************************/
static constexpr uint32_t RENDERGRAPH_RESOURCE = 4;
@ -75,13 +77,21 @@ namespace SHADE
\brief
DescriptorSet Index for render graph node compute resources. For data
that we wish to pass to compute shaders in the render graph, this is
the set to use. Unlike the sets from 1 to 3, this set index does not have
the set to use. Unlike the sets from 1 to 3 and 6, this set index does not have
hard coded bindings and is NOT part of the layouts included in the global
data.
*/
/***************************************************************************/
static constexpr uint32_t RENDERGRAPH_NODE_COMPUTE_RESOURCE = 5;
/***************************************************************************/
/*!
\brief
To store font data.
*/
/***************************************************************************/
static constexpr uint32_t FONT_DATA = 4;
};
struct DescriptorSetBindings
@ -107,7 +117,7 @@ namespace SHADE
/***************************************************************************/
/*!
\brief
DescriptorSet binding for combined image sampler data.
DescriptorSet binding for light data.
*/
/***************************************************************************/
@ -116,7 +126,7 @@ namespace SHADE
/***************************************************************************/
/*!
\brief
DescriptorSet binding for lights.
DescriptorSet binding for camera data.
*/
/***************************************************************************/
@ -130,6 +140,24 @@ namespace SHADE
/***************************************************************************/
static constexpr uint32_t BATCHED_PER_INST_DATA = 0;
/***************************************************************************/
/*!
\brief
Descriptor set binding for font bitmaps.
*/
/***************************************************************************/
static constexpr uint32_t FONT_BITMAP_DATA = 0;
/***************************************************************************/
/*!
\brief
Descriptor set binding for font matrix data.
*/
/***************************************************************************/
static constexpr uint32_t FONT_MATRIX_DATA = 1;
};
struct VertexBufferBindings
@ -177,6 +205,10 @@ namespace SHADE
/***************************************************************************/
static constexpr uint32_t INTEGER_DATA = 5;
static constexpr uint32_t CALCULATED_GLYPH_POSITION = 0;
static constexpr uint32_t GLYPH_INDEX = 1;
};
/*******************************************************************************/

View File

@ -42,6 +42,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/SHVkUtil.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "../Meshes/SHPrimitiveGenerator.h"
#include "Graphics/MiddleEnd/TextRendering/SHFreetypeInstance.h"
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.h"
namespace SHADE
{
@ -82,7 +84,7 @@ namespace SHADE
if (width == 0 || height == 0)
return;
PrepareResize(resizeWidth, resizeHeight);
PrepareResize(width, height);
});
window->RegisterWindowCloseCallback([&](void)
@ -115,6 +117,17 @@ namespace SHADE
// Create generic command buffer
graphicsCmdPool = device->CreateCommandPool(SH_QUEUE_FAMILY_ARRAY_INDEX::GRAPHICS, SH_CMD_POOL_RESET::POOL_BASED, true);
SHFreetypeInstance::Init();
//SHAssetManager::CompileAsset("../../Assets/Shaders/Text_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/Text_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/UI_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/UI_FS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Models/Quad.gltf", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/ToSwapchain_VS.glsl", false);
//SHAssetManager::CompileAsset("../../Assets/Shaders/ToSwapchain_FS.glsl", false);
// Load Built In Shaders
static constexpr AssetID VS_DEFAULT = 39210065; defaultVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEFAULT);
static constexpr AssetID FS_DEFAULT = 46377769; defaultFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEFAULT);
@ -123,6 +136,10 @@ namespace SHADE
static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(CS_COMPOSITE);
static constexpr AssetID SSAO = 38430899; ssaoShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO);
static constexpr AssetID SSAO_BLUR = 39760835; ssaoBlurShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO_BLUR);
static constexpr AssetID TEXT_VS = 39816727; textVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TEXT_VS);
static constexpr AssetID TEXT_FS = 38024754; textFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(TEXT_FS);
static constexpr AssetID RENDER_SC_VS = 48082949; renderToSwapchainVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(RENDER_SC_VS);
static constexpr AssetID RENDER_SC_FS = 36869006; renderToSwapchainFS = SHResourceManager::LoadOrGet<SHVkShaderModule>(RENDER_SC_FS);
}
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@ -149,6 +166,8 @@ namespace SHADE
worldCamera->SetLookAt(SHVec3(0.0f, 0.0f, 0.0f), SHVec3(0.0f, 0.0f, -2.0f), SHVec3(0.0f, 1.0f, 0.0f));
worldCamera->SetPerspective(90.0f, static_cast<float>(windowDims.first), static_cast<float>(windowDims.second), 0.0f, 100.0f);
worldCameraDirector = cameraSystem->CreateDirector();
// Create Default Viewport
worldViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(window->GetWindowSize().first), static_cast<float>(window->GetWindowSize().second), 0.0f, 1.0f));
@ -162,20 +181,21 @@ namespace SHADE
}
/*-----------------------------------------------------------------------*/
/* SCENE RENDER GRAPH RESOURCES */
/* WORLD RENDER GRAPH RESOURCES */
/*-----------------------------------------------------------------------*/
// Initialize world render graph
worldRenderGraph->Init("World Render Graph", device, swapchain);
worldRenderGraph->AddResource("Position", { 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);
worldRenderGraph->AddResource("Normals", { 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);
worldRenderGraph->Init("World Render Graph", device, swapchain, &resourceManager);
worldRenderGraph->AddResource("Position", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
worldRenderGraph->AddResource("Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, 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);
worldRenderGraph->AddResource("Albedo", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("SSAO", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
worldRenderGraph->AddResource("SSAO Blur", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
worldRenderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
worldRenderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->AddResource("Light Layer Indices", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
worldRenderGraph->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 }, windowDims.first, windowDims.second);
worldRenderGraph->AddResource("SSAO", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
worldRenderGraph->AddResource("SSAO Blur", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
/*-----------------------------------------------------------------------*/
/* MAIN NODE */
@ -205,7 +225,7 @@ namespace SHADE
gBufferSubpass->AddColorOutput("Normals");
//gBufferSubpass->AddColorOutput("Tangents");
gBufferSubpass->AddColorOutput("Albedo");
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL);
/*-----------------------------------------------------------------------*/
/* SSAO PASS AND DATA INIT */
@ -250,25 +270,66 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
gBufferNode->AddNodeCompute("Deferred Composite", deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene"});
// Dummy Node
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
dummySubpass->AddInput("Scene");
{
//// Dummy Node to transition scene render graph resource
//auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors
//auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
//dummySubpass->AddInput("Scene");
}
/*-----------------------------------------------------------------------*/
/* GENERATE RENDER GRAPH */
/* GENERATE WORLD RENDER GRAPH */
/*-----------------------------------------------------------------------*/
// Generate world render graph
worldRenderGraph->Generate();
/*-----------------------------------------------------------------------*/
/* SCREEN RENDER GRAPH */
/*-----------------------------------------------------------------------*/
// Initialize screen render graph
screenRenderGraph = resourceManager.Create<SHRenderGraph>();
screenRenderGraph->Init("Screen Render Graph", device, swapchain, &resourceManager);
screenRenderGraph->LinkNonOwningResource(worldRenderGraph, "Scene");
screenRenderGraph->LinkNonOwningResource(worldRenderGraph, "Entity ID");
screenRenderGraph->AddResource("Present", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
auto screenSpaceNode = screenRenderGraph->AddNode("Screen Space Pass", { "Scene", "Entity ID"}, {});
auto uiSubpass = screenSpaceNode->AddSubpass("UI");
uiSubpass->AddColorOutput("Scene");
uiSubpass->AddColorOutput("Entity ID");
uiSubpass->AddExteriorDrawCalls([=](Handle<SHVkCommandBuffer>& cmdBuffer, uint32_t frameIndex)
{
textRenderingSubSystem->Render(cmdBuffer, frameIndex);
});
#ifdef SHEDITOR
{
// Dummy Node to transition scene render graph resource
auto dummyNode = screenRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Screen Space Pass" }); // no predecessors
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
dummySubpass->AddInput("Scene");
}
#else
screenRenderGraph->AddRenderToSwapchainNode("Scene", "Present", {"Screen Space Pass"}, {renderToSwapchainVS, renderToSwapchainFS});
#endif
screenRenderGraph->Generate();
/*-----------------------------------------------------------------------*/
/* BIND RENDER GRAPH TO RENDERER */
/*-----------------------------------------------------------------------*/
// Add world renderer to default viewport
worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera);
worldRenderer->SetCameraDirector(worldCameraDirector);
// Add screen renderer to default viewport
screenRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], screenRenderGraph);
screenRenderer->SetCamera(screenCamera);
screenRenderer->SetCameraDirector(worldCameraDirector);
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
// Create debug draw pipeline
debugDrawPipeline = createDebugDrawPipeline(debugDrawNode->GetRenderpass(), debugDrawSubpass);
@ -315,6 +376,16 @@ namespace SHADE
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
lightingSubSystem->Init(device, descPool);
textRenderingSubSystem = resourceManager.Create<SHTextRenderingSubSystem>();
// initialize the text renderer
auto uiNode = screenRenderGraph->GetNode("Screen Space Pass");
textRenderingSubSystem->Init(device, uiNode->GetRenderpass(), uiNode->GetSubpass("UI"), descPool, textVS, textFS, [=](Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
{
screenRenderer->BindDescSet(cmdBuffer, frameIndex);
});
}
void SHGraphicsSystem::InitBuiltInResources(void)
@ -355,8 +426,8 @@ namespace SHADE
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
editorRenderGraph->Init("Editor Render Graph", device, swapchain);
editorRenderGraph->AddResource("Present", { SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
editorRenderGraph->Init("Editor Render Graph", device, swapchain, &resourceManager);
editorRenderGraph->AddResource("Present", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
auto imguiNode = editorRenderGraph->AddNode("ImGui Node", { "Present"}, {});
@ -385,6 +456,7 @@ namespace SHADE
void SHGraphicsSystem::Exit(void)
{
SHFreetypeInstance::Exit();
}
#pragma endregion INIT_EXIT
@ -454,6 +526,8 @@ namespace SHADE
#endif
}
textRenderingSubSystem->Run(frameIndex);
// For every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
{
@ -513,7 +587,7 @@ namespace SHADE
{
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY)
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, cameraSystem->GetEditorCamera()->GetViewMatrix(), cameraSystem->GetEditorCamera()->GetProjMatrix());
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, cameraSystem->GetEditorCamera()->GetViewMatrix(), cameraSystem->GetEditorCamera()->GetProjMatrix(), cameraSystem->GetEditorCamera()->GetOrthoMatrix());
else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
}
@ -761,7 +835,7 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/
Handle<SHTexture> SHGraphicsSystem::AddTexture(const SHTextureAsset& texAsset)
{
const int MIPS = texAsset.mipOffsets.size();
const int MIPS = static_cast<int> (texAsset.mipOffsets.size());
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams { .maxLod = static_cast<float>(MIPS) });
SET_VK_OBJ_NAME(device, vk::ObjectType::eSampler, sampler->GetVkSampler(), "[Sampler] Mips " + std::to_string(MIPS));
return texLibrary.Add(texAsset, sampler);
@ -769,7 +843,7 @@ namespace SHADE
SHADE::Handle<SHADE::SHTexture> SHGraphicsSystem::AddTexture(uint32_t pixelCount, const SHTexture::PixelChannel* const pixelData, uint32_t width, uint32_t height, SHTexture::TextureFormat format, std::vector<uint32_t> mipOffsets)
{
const int MIPS = mipOffsets.size();
const int MIPS = static_cast<int> (mipOffsets.size());
auto sampler = samplerCache.GetSampler(device, SHVkSamplerParams{ .maxLod = static_cast<float>(MIPS) });
SET_VK_OBJ_NAME(device, vk::ObjectType::eSampler, sampler->GetVkSampler(), "[Sampler] Mips " + std::to_string(MIPS));
return texLibrary.Add(pixelCount, pixelData, width, height, format, mipOffsets, sampler);
@ -798,6 +872,19 @@ namespace SHADE
return texLibrary.GetTextureHandle(textureId);
}
/*---------------------------------------------------------------------------------*/
/* Font Registration Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHFont> SHGraphicsSystem::AddFont(SHFontAsset const& fontAsset) noexcept
{
return fontLibrary.AddFont(device, resourceManager, fontAsset);
}
void SHGraphicsSystem::BuildFonts(void) noexcept
{
fontLibrary.BuildFonts(device, graphicsQueue, graphicsCmdPool, descPool, textRenderingSubSystem->GetFontDataDescSetLayout(), resourceManager);
}
#pragma endregion ADD_REMOVE
#pragma region ROUTINES
@ -890,7 +977,9 @@ namespace SHADE
Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial();
if (prevMaterial)
{
Handle<SHSuperBatch> oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
Handle<SHMaterial> baseMat = prevMaterial->GetBaseMaterial();
Handle<SHVkPipeline> prevPipeline = baseMat->HasPipelineChanged() ? baseMat->GetPrevPipeline() : baseMat->GetPipeline();
Handle<SHSuperBatch> oldSuperBatch = prevPipeline->GetPipelineState().GetSubpass()->GetSuperBatch();
oldSuperBatch->Remove(&renderable);
}
@ -905,11 +994,20 @@ namespace SHADE
// Unset change flag
renderable.ResetChangedFlag();
}
// Unset all material old pipeline since we would have finished processing
auto gfxSystem = reinterpret_cast<SHGraphicsSystem*>(system);
auto [matBegin, matEnd] = gfxSystem->resourceManager.GetDenseAccess<SHMaterial>();
for (auto iter = matBegin; iter != matEnd; ++iter)
{
iter->ForgetOldPipeline();
}
}
#pragma endregion ROUTINES
#pragma region MISC
void SHGraphicsSystem::PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept
{
resizeWidth = newWidth;
@ -936,7 +1034,12 @@ namespace SHADE
renderContext.HandleResize();
worldRenderGraph->HandleResize(resizeWidth, resizeHeight);
#ifdef SHEDITOR
editorRenderGraph->HandleResize(windowDims.first, windowDims.second);
#endif
screenRenderGraph->HandleResize(resizeWidth, resizeHeight);
mousePickSystem->HandleResize();
postOffscreenRender->HandleResize();
@ -944,7 +1047,8 @@ namespace SHADE
worldViewport->SetWidth(static_cast<float>(resizeWidth));
worldViewport->SetHeight(static_cast<float>(resizeHeight));
worldCamera->SetPerspective(90.0f, static_cast<float>(resizeWidth), static_cast<float>(resizeHeight), 0.0f, 100.0f);
//worldCamera->SetPerspective(90.0f, static_cast<float>(resizeWidth), static_cast<float>(resizeHeight), 0.0f, 100.0f);
//screenCamera->SetOrthographic(static_cast<float>(resizeWidth), static_cast<float>(resizeHeight), 0.01f, 100.0f);
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
#ifdef SHEDITOR
@ -956,8 +1060,6 @@ namespace SHADE
for (auto& semaHandle : graphSemaphores)
semaHandle = device->CreateSemaphore();
}
void SHGraphicsSystem::AwaitGraphicsExecution()
@ -976,6 +1078,11 @@ namespace SHADE
return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data());
}
SHADE::SHFontLibrary const& SHGraphicsSystem::GetFontLibrary(void) const noexcept
{
return fontLibrary;
}
Handle<SHVkPipeline> SHGraphicsSystem::createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass)
{
auto pipelineLayout = resourceManager.Create<SHVkPipelineLayout>

View File

@ -32,6 +32,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
#include "Graphics/MiddleEnd/PostProcessing/SHSSAO.h"
#include "Camera/SHCameraDirector.h"
#include "Graphics/MiddleEnd/TextRendering/SHFontLibrary.h"
namespace SHADE
{
@ -54,6 +56,7 @@ namespace SHADE
class SHMaterial;
class SHMaterialInstance;
class SHMousePickSystem;
class SHTextRenderingSubSystem;
/*---------------------------------------------------------------------------------*/
/* Type Definitions */
@ -326,6 +329,22 @@ namespace SHADE
*/
/***************************************************************************/
Handle<SHTexture> GetDefaultTexture() const noexcept { return defaultTexture; }
/***************************************************************************/
/*!
\brief
Adds a font into the font library.
\param fontAsset
Font asset to add.
\return
Handle to the new font.
*/
/***************************************************************************/
Handle<SHFont> AddFont (SHFontAsset const& fontAsset) noexcept;
void BuildFonts (void) noexcept;
void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept;
void HandleResize(void) noexcept;
@ -355,6 +374,7 @@ namespace SHADE
Handle<SHVkPipeline> GetDebugDrawPipeline(void) const noexcept { return debugDrawPipeline; }
Handle<SHVkPipeline> GetDebugDrawDepthPipeline(void) const noexcept { return debugDrawDepthPipeline; }
uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); }
SHFontLibrary const& GetFontLibrary (void) const noexcept;
/*-----------------------------------------------------------------------------*/
/* Getters */
@ -391,6 +411,7 @@ namespace SHADE
SHResourceHub resourceManager;
SHMeshLibrary meshLibrary;
SHTextureLibrary texLibrary;
SHFontLibrary fontLibrary;
SHSamplerCache samplerCache;
SHMaterialInstanceCache materialInstanceCache;
@ -398,18 +419,20 @@ namespace SHADE
#ifdef SHEDITOR
Handle<SHViewport> editorViewport;
Handle<SHRenderer> editorRenderer;
Handle<SHRenderGraph> editorRenderGraph;
#endif
Handle<SHViewport> worldViewport; // Whole screen
std::vector<Handle<SHViewport>> viewports; // Additional viewports
// Temp renderers
// Renderers
Handle<SHRenderer> worldRenderer;
Handle<SHRenderer> screenRenderer;
// Temp Cameras
Handle<SHCamera> worldCamera;
Handle<SHCamera> screenCamera;
DirectorHandle worldCameraDirector;
// Built-In Shaders
Handle<SHVkShaderModule> defaultVertShader;
@ -419,7 +442,13 @@ namespace SHADE
Handle<SHVkShaderModule> deferredCompositeShader;
Handle<SHVkShaderModule> ssaoShader;
Handle<SHVkShaderModule> ssaoBlurShader;
Handle<SHVkShaderModule> textVS;
Handle<SHVkShaderModule> textFS;
Handle<SHVkShaderModule> renderToSwapchainVS;
Handle<SHVkShaderModule> renderToSwapchainFS;
// Fonts
Handle<SHFont> testFont;
// Built-In Materials
Handle<SHMaterial> defaultMaterial;
@ -434,11 +463,16 @@ namespace SHADE
// Render Graphs
Handle<SHRenderGraph> worldRenderGraph;
Handle<SHRenderGraph> screenRenderGraph;
#ifdef SHEDITOR
Handle<SHRenderGraph> editorRenderGraph;
#endif
// Sub systems
Handle<SHMousePickSystem> mousePickSystem;
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
Handle<SHLightingSubSystem> lightingSubSystem;
Handle<SHTextRenderingSubSystem> textRenderingSubSystem;
Handle<SHSSAO> ssaoStorage;
uint32_t resizeWidth = 1;

View File

@ -21,6 +21,8 @@ namespace SHADE
if (_pipeline == pipeline)
return;
// Mark old pipeline and set new pipeline
oldPipeline = pipeline;
pipeline = _pipeline;
// Set up properties based on the pipeline
@ -41,9 +43,6 @@ namespace SHADE
// Reset since pipeline changed
ResetProperties();
// Mark changed so that we know to update dependent material instances
propertiesChanged = true;
}
Handle<SHVkPipeline> SHMaterial::GetPipeline() const
@ -111,4 +110,9 @@ namespace SHADE
{
propertiesChanged = false;
}
void SHMaterial::ForgetOldPipeline() noexcept
{
oldPipeline = {};
}
}

View File

@ -44,6 +44,7 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
void SetPipeline(Handle<SHVkPipeline> _pipeline);
Handle<SHVkPipeline> GetPipeline() const;
Handle<SHVkPipeline> GetPrevPipeline() const { return oldPipeline; };
/*-----------------------------------------------------------------------------*/
/* Property Functions */
@ -68,10 +69,11 @@ namespace SHADE
/* Query Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> GetShaderBlockInterface() const noexcept;
bool HasPipelineChanged() const noexcept { return pipelineChanged; }
bool HasPipelineChanged() const noexcept { return oldPipeline; }
bool HasPropertiesChanged() const noexcept { return propertiesChanged; }
bool HasChanged() const noexcept { return pipelineChanged || propertiesChanged; }
bool HasChanged() const noexcept { return oldPipeline || propertiesChanged; }
void ClearChangeFlag() noexcept;
void ForgetOldPipeline() noexcept;
private:
/*-----------------------------------------------------------------------------*/
@ -81,7 +83,7 @@ namespace SHADE
std::unique_ptr<char> propMemory;
Byte propMemorySize = 0;
bool propertiesChanged = true;
bool pipelineChanged = true;
Handle<SHVkPipeline> oldPipeline;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */

View File

@ -90,17 +90,22 @@ namespace SHADE
if (camera && cameraDirector)
{
//UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix()));
UpdateDataAndBind(cmdBuffer, frameIndex, cameraDirector->GetViewMatrix(), cameraDirector->GetProjMatrix());
UpdateDataAndBind(cmdBuffer, frameIndex, cameraDirector->GetViewMatrix(), cameraDirector->GetProjMatrix(), cameraDirector->GetOrthoMatrix());
}
}
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix, SHMatrix const& orthoMatrix) noexcept
{
SetViewProjectionMatrix(viewMatrix, projMatrix);
SetViewProjectionMatrix(viewMatrix, projMatrix, orthoMatrix);
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
BindDescSet(cmdBuffer, frameIndex);
}
void SHRenderer::BindDescSet(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
@ -111,12 +116,13 @@ namespace SHADE
{
}
void SHRenderer::SetViewProjectionMatrix(SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept
void SHRenderer::SetViewProjectionMatrix(SHMatrix const& viewMatrix, SHMatrix const& projMatrix, SHMatrix const& orthoMatrix) noexcept
{
//cpuCameraData.viewProjectionMatrix = camera->GetViewMatrix() * camera->GetProjectionMatrix();
cpuCameraData.viewProjectionMatrix = SHMatrix::Transpose(projMatrix * viewMatrix);
cpuCameraData.viewMatrix = SHMatrix::Transpose(viewMatrix);
cpuCameraData.projectionMatrix = SHMatrix::Transpose(projMatrix);
cpuCameraData.orthoMatrix = SHMatrix::Transpose (orthoMatrix);
}
Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept

View File

@ -48,6 +48,7 @@ namespace SHADE
SHMatrix viewProjectionMatrix;
SHMatrix viewMatrix;
SHMatrix projectionMatrix;
SHMatrix orthoMatrix;
};
/*---------------------------------------------------------------------------------*/
@ -63,6 +64,7 @@ namespace SHADE
/***********************************************************************************/
class SHRenderer
{
public:
/*-----------------------------------------------------------------------------*/
/* Constructor/Destructors */
@ -81,9 +83,10 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept;
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix, SHMatrix const& orthoMatrix) noexcept;
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void UpdateCameraDataToBuffer (void) noexcept;
void SetViewProjectionMatrix (SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept;
void SetViewProjectionMatrix (SHMatrix const& viewMatrix, SHMatrix const& projMatrix, SHMatrix const& orthoMatrix) noexcept;
/*-----------------------------------------------------------------------------*/
/* Setters and Getters */

View File

@ -423,9 +423,8 @@ namespace SHADE
/*!
\brief
Loops through every single light component and checks for dirty light
data. If light data is dirty, rewrite to the CPU container. We also want
to bind the descriptor set for the light data.
Loops through every single light component and writes light data to CPU
then GPU.
*/
/***************************************************************************/

View File

@ -76,7 +76,7 @@ namespace SHADE
};
uint32_t mipOffset = 0;
rotationVectorsImage = logicalDevice->CreateImage(imageDetails, reinterpret_cast<unsigned char*>( rotationVectors.data()), static_cast<uint32_t>(sizeof(rotationVectors)), {&mipOffset, 1}, VMA_MEMORY_USAGE_AUTO, {});
rotationVectorsImage = logicalDevice->CreateImage(imageDetails, reinterpret_cast<unsigned char*>(rotationVectors.data()), static_cast<uint32_t>(sizeof(rotationVectors)), { mipOffset }, VMA_MEMORY_USAGE_AUTO, {});
vk::ImageMemoryBarrier transferBarrier{};
rotationVectorsImage->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, transferBarrier);

View File

@ -0,0 +1,160 @@
#include "SHpch.h"
#include "SHFont.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/Images/SHVkSampler.h"
namespace SHADE
{
/***************************************************************************/
/*!
\brief
Non-default ctor. Prepares objects in staging buffers with data from
SHFontAsset.
\param inLogicalDeviceHdl
Logical device required for vulkan object creation.
\param asset
Font asset to copy data from.
*/
/***************************************************************************/
SHFont::SHFont(Handle<SHVkLogicalDevice> inLogicalDeviceHdl, SHFontAsset const& asset) noexcept
{
/*-----------------------------------------------------------------------*/
/* PREPARE GPU DATA */
/*-----------------------------------------------------------------------*/
// assign device for convenient usage
logicalDevice = inLogicalDeviceHdl;
// Copy the font data
fontAsset = asset;
SHImageCreateParams imageParams
{
.imageType = vk::ImageType::e2D,
.width = fontAsset.bitmapWidth,
.height = fontAsset.bitmapHeight,
.depth = 1,
.levels = 1,
.arrayLayers = 1,
.imageFormat = vk::Format::eR8G8B8A8Unorm,
//.imageFormat = vk::Format::eR32Sfloat,
//.imageFormat = vk::Format::eR32G32B32Sfloat,
.usageFlags = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst,
.createFlags = {}
};
uint32_t bytesRequired = asset.bitmapData.size();
uint32_t mipOffset = 0;
// Create the image
bitmapDataImage = logicalDevice->CreateImage(imageParams, fontAsset.bitmapData.data(), bytesRequired, { mipOffset }, VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO, {});
// Amount of data required to hold matrices for all glyphs
uint32_t glyphDataSize = fontAsset.glyphTransformations.size() * sizeof (SHMatrix);
// For indexing
for (uint32_t i = 0; i < fontAsset.glyphs.size(); ++i)
unicodeIndexing.emplace(fontAsset.glyphs[i], i);
// allocate GPU buffer for matrices
matrixDataBuffer = logicalDevice->CreateBuffer(glyphDataSize, fontAsset.glyphTransformations.data(), glyphDataSize, vk::BufferUsageFlagBits::eTransferDst | vk::BufferUsageFlagBits::eStorageBuffer, VMA_MEMORY_USAGE_AUTO, {});
sampler = logicalDevice->CreateSampler(SHVkSamplerParams{});
}
/***************************************************************************/
/*!
\brief
Transfers data from staging buffers to GPU. Does not issue any of the
barriers (we want this done outside).
\param commandBuffer
Command buffer used to
\return
*/
/***************************************************************************/
void SHFont::TransferToGPU(Handle<SHVkCommandBuffer> commandBuffer) noexcept
{
/*-----------------------------------------------------------------------*/
/* COMMANDS TO TRANSFER TO DEVICE MEMORY */
/*-----------------------------------------------------------------------*/
// Transfer to device memory
bitmapDataImage->TransferToDeviceResource(commandBuffer);
// Transfer to GPU buffer
matrixDataBuffer->TransferToDeviceResource(commandBuffer);
}
void SHFont::DoPostTransfer(Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> layout) noexcept
{
/*-----------------------------------------------------------------------*/
/* CREATE IMAGE VIEW */
/*-----------------------------------------------------------------------*/
// Create the image view to the device resource
SHImageViewDetails viewDetails
{
.viewType = vk::ImageViewType::e2D,
.format = bitmapDataImage->GetImageFormat(),
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
.baseMipLevel = 0,
.mipLevelCount = 1,
.baseArrayLayer = 0,
.layerCount = 1,
};
bitmapDataImageView = bitmapDataImage->CreateImageView(logicalDevice, bitmapDataImage, viewDetails);
/*-----------------------------------------------------------------------*/
/* DESCRIPTORS */
/*-----------------------------------------------------------------------*/
// allocate desc set for the bitmap and matrix data
descSet = descPool->Allocate({ layout }, { 1 });
auto viewLayoutSampler = std::make_tuple(bitmapDataImageView, sampler, vk::ImageLayout::eShaderReadOnlyOptimal);
descSet->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::FONT_DATA, SHGraphicsConstants::DescriptorSetBindings::FONT_BITMAP_DATA, {&viewLayoutSampler, 1});
descSet->ModifyWriteDescBuffer(SHGraphicsConstants::DescriptorSetIndex::FONT_DATA,
SHGraphicsConstants::DescriptorSetBindings::FONT_MATRIX_DATA, { &matrixDataBuffer, 1 }, 0, fontAsset.glyphTransformations.size() * sizeof(SHMatrix));
// Bind image and buffer to desc set.
descSet->UpdateDescriptorSetImages(SHGraphicsConstants::DescriptorSetIndex::FONT_DATA, SHGraphicsConstants::DescriptorSetBindings::FONT_BITMAP_DATA);
descSet->UpdateDescriptorSetBuffer(SHGraphicsConstants::DescriptorSetIndex::FONT_DATA, SHGraphicsConstants::DescriptorSetBindings::FONT_MATRIX_DATA);
}
std::unordered_map<msdfgen::unicode_t, uint32_t> SHFont::GetUnicodeIndexing(void) const noexcept
{
return unicodeIndexing;
}
SHFontAsset const& SHFont::GetFontAsset(void) const noexcept
{
return fontAsset;
}
Handle<SHVkImage> SHFont::GetImage(void) const noexcept
{
return bitmapDataImage;
}
Handle<SHVkBuffer> SHFont::GetMatrixBuffer(void) const noexcept
{
return matrixDataBuffer;
}
Handle<SHVkDescriptorSetGroup> SHFont::GetDescriptorSet(void) const noexcept
{
return descSet;
}
}

View File

@ -0,0 +1,72 @@
#pragma once
#include "Resource/SHHandle.h"
#include "msdf-atlas-gen/msdf-atlas-gen.h"
#include "Assets/Asset Types/SHFontAsset.h"
namespace SHADE
{
class SHVkLogicalDevice;
class SHVkDescriptorPool;
class SHVkDescriptorSetGroup;
class SHVkDescriptorSetLayout;
class SHVkCommandBuffer;
class SHVkCommandPool;
class SHVkImage;
class SHVkImageView;
class SHVkBuffer;
class SHVkQueue;
class SHVkSampler;
class SHFont
{
private:
//! Device for creation and destruction
Handle<SHVkLogicalDevice> logicalDevice;
//! Font asset contains exactly what we need, so we'll use it
SHFontAsset fontAsset;
//! Device memory that stores bitmap data
Handle<SHVkImage> bitmapDataImage;
//! View to device memory
Handle<SHVkImageView> bitmapDataImageView;
//! Device memory that stores matrix data
Handle<SHVkBuffer> matrixDataBuffer;
//! Descriptor set required to store the bitmap AND matrix data for the UV and quad transformation
Handle<SHVkDescriptorSetGroup> descSet;
Handle<SHVkSampler> sampler;
//! Used for getting the correct indices into the matrix data buffer
std::unordered_map<msdfgen::unicode_t, uint32_t> unicodeIndexing;
////! To transition images for transfer ops
//vk::ImageMemoryBarrier preTransferBarrier;
////! To transition images for shader reads
//vk::ImageMemoryBarrier postTransferBarrier;
public:
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
SHFont (Handle<SHVkLogicalDevice> inLogicalDeviceHdl, SHFontAsset const& asset) noexcept;
void TransferToGPU (Handle<SHVkCommandBuffer> commandBuffer) noexcept;
void DoPostTransfer (Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> layout) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
std::unordered_map<msdfgen::unicode_t, uint32_t> GetUnicodeIndexing (void) const noexcept;
SHFontAsset const& GetFontAsset (void) const noexcept;
Handle<SHVkImage> GetImage (void) const noexcept;
Handle<SHVkBuffer> GetMatrixBuffer (void) const noexcept;
Handle<SHVkDescriptorSetGroup> GetDescriptorSet (void) const noexcept;
};
}

View File

@ -0,0 +1,7 @@
#include "SHpch.h"
#include "SHFontAtlasData.h"
namespace SHADE
{
}

View File

@ -0,0 +1,7 @@
#pragma once
namespace SHADE
{
}

View File

@ -0,0 +1,108 @@
#include "SHpch.h"
#include "SHFontLibrary.h"
#include "Graphics/Images/SHVkImage.h"
#include "Graphics/Commands/SHVkCommandPool.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/Synchronization/SHVkFence.h"
#include "Graphics/Buffers/SHVkBuffer.h"
namespace SHADE
{
/***************************************************************************/
/*!
\brief
For adding fonts to the library
\param asset
The asset we want to create an SHFont from.
*/
/***************************************************************************/
Handle<SHFont> SHFontLibrary::AddFont(Handle<SHVkLogicalDevice> logicalDevice, SHResourceHub& resourceHub, SHFontAsset const& asset) noexcept
{
// Create new font
Handle<SHFont> newFont = resourceHub.Create<SHFont>(logicalDevice, asset);
// emplace new barriers and prepare them for transfer ops
preTransferBarriers.emplace_back();
postTransferBarriers.emplace_back();
newFont->GetImage()->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, preTransferBarriers[preTransferBarriers.size() - 1]);
newFont->GetImage()->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, postTransferBarriers[postTransferBarriers.size() - 1]);
unpreparedFonts.emplace_back (newFont);
return newFont;
}
/***************************************************************************/
/*!
\brief
Transfers staging buffer font memory to the GPU for optimized access.
\param cmdBuffer
Command buffer to record the transfer operations.
\param descPool
\return
*/
/***************************************************************************/
void SHFontLibrary::BuildFonts(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkQueue> queue, Handle<SHVkCommandPool> cmdPool, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> layout, SHResourceHub& resourceHub) noexcept
{
// create fence to wait on after transfer
Handle<SHVkFence> finishCopyFence = resourceHub.Create<SHVkFence>(logicalDevice);
finishCopyFence->Reset();
// allocate new command buffer
Handle<SHVkCommandBuffer> transferCommandBuffer = cmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
// Begin recording transfer ops
transferCommandBuffer->BeginRecording();
{
// Transition image to dst
transferCommandBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, preTransferBarriers);
// Transfer data from staging to image
for (auto& font : unpreparedFonts)
font->TransferToGPU(transferCommandBuffer);
// Transition dst to shader read
transferCommandBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eFragmentShader, {}, {}, {}, postTransferBarriers);
}
// End recording for transfer ops
transferCommandBuffer->EndRecording();
// Submit command buffer to queue
queue->SubmitCommandBuffer({transferCommandBuffer}, {}, {}, vk::PipelineStageFlagBits::eTransfer, finishCopyFence);
// wait for copy to finish
finishCopyFence->Wait(true, std::numeric_limits<uint32_t>::max());
// Prepare image views and desc sets
for (auto& font : unpreparedFonts)
font->DoPostTransfer(descPool, layout);
// Free the command buffer and fence
transferCommandBuffer.Free();
resourceHub.Free(finishCopyFence);
// Once unprepared fonts are now ready for use, push them into container
uint32_t i = static_cast<uint32_t> (unpreparedFonts.size());
std::copy (unpreparedFonts.begin(), unpreparedFonts.end(), std::back_inserter(fonts));
// All fonts have been prepared for GPU usage
unpreparedFonts.clear();
preTransferBarriers.clear();
postTransferBarriers.clear();
}
std::vector<Handle<SHFont>> const& SHFontLibrary::GetFonts(void) const noexcept
{
return fonts;
}
}

View File

@ -0,0 +1,36 @@
#pragma once
#include "SHFont.h"
#include <vector>
#include "Graphics/SHVulkanIncludes.h"
namespace SHADE
{
class SHVkLogicalDevice;
class SHVkDescriptorPool;
class SHVkCommandPool;
class SHVkCommandBuffer;
class SHVkQueue;
class SHVkDescriptorSetLayout;
class SH_API SHFontLibrary
{
private:
//! Handles to all the fonts usable in SHTextRendererComponents
std::vector<Handle<SHFont>> fonts;
//! Fonts that have yet to be properly prepared for usage
std::vector<Handle<SHFont>> unpreparedFonts;
//! For transitioning images for transfer operations
std::vector<vk::ImageMemoryBarrier> preTransferBarriers;
//! For transitioning images for shader reads
std::vector<vk::ImageMemoryBarrier> postTransferBarriers;
public:
Handle<SHFont> AddFont (Handle<SHVkLogicalDevice> logicalDevice, SHResourceHub& resourceHub, SHFontAsset const& asset) noexcept;
void BuildFonts (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkQueue> queue, Handle<SHVkCommandPool> cmdPool, Handle<SHVkDescriptorPool> descPool, Handle<SHVkDescriptorSetLayout> layout, SHResourceHub& resourceHub) noexcept;
std::vector<Handle<SHFont>> const& GetFonts (void) const noexcept;
};
}

View File

@ -0,0 +1,27 @@
#include "SHpch.h"
#include "SHFreetypeInstance.h"
#include "msdf-atlas-gen/msdf-atlas-gen.h"
#include "msdfgen-ext.h"
namespace SHADE
{
msdfgen::FreetypeHandle* SHFreetypeInstance::freetypeHandle = nullptr;
void SHFreetypeInstance::Init(void) noexcept
{
// initialize freetype
freetypeHandle = msdfgen::initializeFreetype();
}
void SHFreetypeInstance::Exit(void) noexcept
{
msdfgen::deinitializeFreetype(freetypeHandle);
}
msdfgen::FreetypeHandle* SHFreetypeInstance::GetFreetypeHandle(void) noexcept
{
return freetypeHandle;
}
}

View File

@ -0,0 +1,23 @@
#pragma once
namespace msdfgen
{
class FreetypeHandle;
}
namespace SHADE
{
class SHFreetypeInstance
{
private:
//! Only need this to be initialized once
static msdfgen::FreetypeHandle* freetypeHandle;
public:
static void Init (void) noexcept;
static void Exit (void) noexcept;
static msdfgen::FreetypeHandle* GetFreetypeHandle(void) noexcept;
};
}

View File

@ -0,0 +1,95 @@
#include "SHpch.h"
#include "SHTextRenderableComponent.h"
namespace SHADE
{
void SHTextRenderableComponent::MakeDirty(void) noexcept
{
requiresRecompute = true;
}
void SHTextRenderableComponent::Clean(void) noexcept
{
requiresRecompute = false;
}
/***************************************************************************/
/*!
\brief
On create the text has nothing.
*/
/***************************************************************************/
void SHTextRenderableComponent::OnCreate(void)
{
text = "My name is Brandon.";
requiresRecompute = true;
// Default white color.
color = SHColour::WHITE;
}
void SHTextRenderableComponent::OnDestroy(void)
{
}
/***************************************************************************/
/*!
\brief
Sets the text to be rendered.
\param newText
\return
*/
/***************************************************************************/
void SHTextRenderableComponent::SetText(std::string_view newText) noexcept
{
text = newText;
MakeDirty();
}
void SHTextRenderableComponent::SetFont(Handle<SHFont> font) noexcept
{
fontHandle = font;
MakeDirty();
}
/***************************************************************************/
/*!
\brief
Getter for the text required to render.
\return
*/
/***************************************************************************/
std::string const& SHTextRenderableComponent::GetText(void) const noexcept
{
return text;
}
Handle<SHFont> SHTextRenderableComponent::GetFont(void) const noexcept
{
return fontHandle;
}
}
namespace rttr
{
RTTR_REGISTRATION
{
using namespace SHADE;
registration::class_<SHTextRenderableComponent>("Text Renderer Component");
};
}

View File

@ -0,0 +1,65 @@
#pragma once
#include <string>
#include <string_view>
#include "ECS_Base/Components/SHComponent.h"
#include "Math/SHColour.h"
#include "Resource/SHHandle.h"
#include <rttr/registration>
namespace SHADE
{
class SHFont;
class SHVkDescriptorSetGroup;
class SHVkBuffer;
class SH_API SHTextRenderableComponent final : public SHComponent
{
public:
static constexpr uint32_t MAX_CHARACTERS = 500;
private:
using TextIndexingType = uint32_t;
private:
//! Text required to be rendered
std::string text;
//! Color of the text
SHColour color;
//! Requires to recompute the positions of each glyph/character
bool requiresRecompute;
//! Handle to the font used to render the text
Handle<SHFont> fontHandle;
//! We want to index into the buffer with matrices
Handle<SHVkBuffer> indexingDataBuffer;
//! character position data for each letter in the text
Handle<SHVkBuffer> charPositionDataBuffer;
void MakeDirty (void) noexcept;
void Clean (void) noexcept;
public:
void OnCreate(void) override final;
void OnDestroy(void) override final;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
void SetText (std::string_view newText) noexcept;
void SetFont (Handle<SHFont> font) noexcept;
std::string const& GetText (void) const noexcept;
Handle<SHFont> GetFont (void) const noexcept;
friend class SHTextRenderingSubSystem;
RTTR_ENABLE()
};
}

View File

@ -0,0 +1,242 @@
#include "SHpch.h"
#include "SHTextRenderingSubSystem.h"
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h"
#include "Math/Vector/SHVec4.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/MiddleEnd/TextRendering/SHFont.h"
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Graphics/Pipeline/SHVkPipeline.h"
#include "Graphics/SHVkUtil.h"
#include "Graphics/RenderGraph/SHSubpass.h"
#include "Math/Transform/SHTransformComponent.h"
namespace SHADE
{
void SHTextRenderingSubSystem::RecomputePositions(SHTextRenderableComponent& textComp) noexcept
{
if (textComp.text.empty() || !textComp.fontHandle)
return;
// Create the buffer
if (!textComp.indexingDataBuffer)
textComp.indexingDataBuffer = logicalDevice->CreateBuffer(SHTextRenderableComponent::MAX_CHARACTERS * sizeof(uint32_t), nullptr, SHTextRenderableComponent::MAX_CHARACTERS * sizeof(uint32_t), vk::BufferUsageFlagBits::eVertexBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT);
if (!textComp.charPositionDataBuffer)
textComp.charPositionDataBuffer = logicalDevice->CreateBuffer(SHTextRenderableComponent::MAX_CHARACTERS * sizeof(SHVec4), nullptr, SHTextRenderableComponent::MAX_CHARACTERS * sizeof(SHVec4), vk::BufferUsageFlagBits::eVertexBuffer, VMA_MEMORY_USAGE_AUTO, VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT);
// For indexing font transformation in the shader
std::vector <SHTextRenderableComponent::TextIndexingType> indexingData;
// For placing glyphs correctly
std::vector <SHVec4> charPositionData;
// Baseline relative to entity with this component
SHVec4 baselineOrigin{ 0.0f, 0.0f, 0.0f, 1.0f };
// Number of characters in the string
uint32_t numChars = static_cast<uint32_t>(textComp.text.size());
// Get a ref to the transform indices
auto const& glyphTransformIndices = textComp.fontHandle->GetUnicodeIndexing();
// Get a ref to the glyph transformations
auto const& glyphTransforms = textComp.fontHandle->GetFontAsset().glyphTransformations;
bool dueNextLine = false;
// for every character
for (uint32_t i = 0; i < numChars; ++i)
{
SHTextRenderableComponent::TextIndexingType index = glyphTransformIndices.at(textComp.text[i]);
// Copy baseline
SHVec4 characterPos = baselineOrigin;
// Get where to draw the glyph relative to the baseline
characterPos[0] += glyphTransforms[index].m[SHFontAsset::BASELINE_LEFT_MATRIX_INDEX_ROW][SHFontAsset::BASELINE_LEFT_MATRIX_INDEX_COL]; // Inside the matrix but not used in the shader so this value has no positional value
characterPos[1] += glyphTransforms[index].m[SHFontAsset::BASELINE_BOTTOM_MATRIX_INDEX_ROW][SHFontAsset::BASELINE_BOTTOM_MATRIX_INDEX_COL]; // Inside the matrix but not used in the shader so this value has no positional value
indexingData.push_back(index);
charPositionData.push_back(characterPos);
// if not the last character
if (i != numChars - 1)
{
// Get the advance and move the baseline
double advance = 0.0;
textComp.fontHandle->GetFontAsset().fontGeometry.getAdvance(advance, textComp.text[i], textComp.text[static_cast<uint64_t>(i) + 1]);
baselineOrigin[0] += static_cast<float>(advance);
//if (baselineOrigin[0] >= textComp.estimatedLineLength)
//{
// dueNextLine = true;
//}
}
//if (dueNextLine && textComp.renderedText[i] == ' ')
//{
// baselineOrigin[0] = 0.0f;
// baselineOrigin[1] -= textComp.lineSpacing;
// dueNextLine = false;
//}
}
textComp.indexingDataBuffer->WriteToMemory(indexingData.data(), static_cast<uint32_t>(indexingData.size()) * sizeof (SHTextRenderableComponent::TextIndexingType),0, 0);
textComp.charPositionDataBuffer->WriteToMemory(charPositionData.data(), static_cast<uint32_t>(charPositionData.size()) * sizeof (SHVec4), 0, 0);
indexingData.clear();
charPositionData.clear();
}
void SHTextRenderingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkRenderpass> compatibleRenderpass, Handle<SHSubpass> subpass, Handle<SHVkDescriptorPool> descPool, Handle<SHVkShaderModule> textVS, Handle<SHVkShaderModule> textFS, std::function<void(Handle<SHVkCommandBuffer>, uint32_t)> const& bindFunction) noexcept
{
SHComponentManager::CreateComponentSparseSet<SHTextRenderableComponent>();
cameraDescSetBind = bindFunction;
logicalDevice = device;
// prepare pipeline layout params
SHPipelineLayoutParams plParams
{
.shaderModules = {textVS, textFS},
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
};
pipelineLayout = logicalDevice->CreatePipelineLayout(plParams);
// Create pipeline
pipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, compatibleRenderpass, subpass);
// vertex input state of the pipeline
SHVertexInputState vertexInputState;
// Configure vertex attributes
vertexInputState.AddBinding(true, false, { SHVertexAttribute(SHAttribFormat::FLOAT_4D) }); // location = 0 (character position data)
vertexInputState.AddBinding(true, false, { SHVertexAttribute(SHAttribFormat::UINT32_1D) }); // location = 1 (glyph index to index matrices)
// Set vertex state for new pipeline
pipeline->GetPipelineState().SetVertexInputState(vertexInputState);
SHColorBlendState colorBlendState{};
colorBlendState.logic_op_enable = VK_FALSE;
colorBlendState.logic_op = vk::LogicOp::eCopy;
auto const& subpassColorReferences = subpass->GetColorAttachmentReferences();
colorBlendState.attachments.reserve(static_cast<uint32_t>(subpassColorReferences.size()));
for (auto& att : subpassColorReferences)
{
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
{
.blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(att.attachment)) ? true : false,
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
}
);
}
pipeline->GetPipelineState().SetColorBlenState(colorBlendState);
SHInputAssemblyState inputAssembly{};
inputAssembly.topology = vk::PrimitiveTopology::eTriangleFan;
pipeline->GetPipelineState().SetInputAssemblyState(inputAssembly);
SHRasterizationState rasterState{};
rasterState.frontFacingOrientation = vk::FrontFace::eClockwise;
pipeline->GetPipelineState().SetRasterizationState(rasterState);
// Construct pipeline
pipeline->ConstructPipeline();
SHVkDescriptorSetLayout::Binding fontBitmapBinding
{
.Type = vk::DescriptorType::eCombinedImageSampler,
.Stage = vk::ShaderStageFlagBits::eFragment,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::FONT_BITMAP_DATA,
.DescriptorCount = 1,
};
SHVkDescriptorSetLayout::Binding fontMatrixBinding
{
.Type = vk::DescriptorType::eStorageBuffer,
.Stage = vk::ShaderStageFlagBits::eVertex,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::FONT_MATRIX_DATA,
.DescriptorCount = 1,
};
fontDataDescSetLayout = logicalDevice->CreateDescriptorSetLayout(SHGraphicsConstants::DescriptorSetIndex::FONT_DATA, { fontBitmapBinding, fontMatrixBinding });
}
void SHTextRenderingSubSystem::Run(uint32_t frameIndex) noexcept
{
auto& textRendererComps = SHComponentManager::GetDense<SHTextRenderableComponent>();
for (auto& comp : textRendererComps)
{
// If the component is dirty
if (comp.requiresRecompute)
{
RecomputePositions(comp);
comp.Clean();
}
}
}
void SHTextRenderingSubSystem::Render(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
{
auto& textRendererComps = SHComponentManager::GetDense<SHTextRenderableComponent>();
for (auto& comp : textRendererComps)
{
auto* transform = SHComponentManager::GetComponent<SHTransformComponent>(comp.GetEID());
Handle<SHFont> fontHandle = comp.fontHandle;
if (fontHandle && transform)
{
// bind the pipeline
cmdBuffer->BindPipeline(pipeline);
// bind VBO (position and indices)
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::CALCULATED_GLYPH_POSITION, comp.charPositionDataBuffer, 0);
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::GLYPH_INDEX, comp.indexingDataBuffer, 0);
cameraDescSetBind(cmdBuffer, frameIndex);
// bind descriptors for font (matrices)
cmdBuffer->BindDescriptorSet(fontHandle->GetDescriptorSet(), SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::FONT_DATA, {});
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);
cmdBuffer->SubmitPushConstants(SH_PIPELINE_TYPE::GRAPHICS);
// call draw call
cmdBuffer->DrawArrays(4, comp.text.size(), 0, 0);
//glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, static_cast<GLsizei>(textComp.lastRenderedCharacterIndex) + 1);
}
}
}
void SHTextRenderingSubSystem::Exit(void) noexcept
{
}
Handle<SHVkDescriptorSetLayout> SHTextRenderingSubSystem::GetFontDataDescSetLayout(void) const noexcept
{
return fontDataDescSetLayout;
}
}

View File

@ -0,0 +1,65 @@
#pragma once
#include "Resource/SHHandle.h"
#include "Graphics/Pipeline/SHPipelineState.h"
#include "Math/SHMatrix.h"
#include "Math/Vector/SHVec3.h"
namespace SHADE
{
class SHVkLogicalDevice;
class SHVkDescriptorPool;
class SHVkDescriptorSetGroup;
class SHVkDescriptorSetLayout;
class SHVkBuffer;
class SHLightComponent;
class SHVkCommandBuffer;
class SHTextRenderableComponent;
class SHVkPipeline;
class SHVkPipelineLayout;
class SHVkRenderpass;
class SHSubpass;
class SHVkShaderModule;
class SHTextRenderingSubSystem
{
private:
struct ShaderPushConstantData
{
SHMatrix worldTransform;
uint32_t eid;
SHVec3 textColor;
};
//! Logical device for creation and destruction
Handle<SHVkLogicalDevice> logicalDevice;
//! Pipeline for rendering the text
Handle<SHVkPipeline> pipeline;
//! Pipeline layout for the pipeline
Handle<SHVkPipelineLayout> pipelineLayout;
//! Descriptor set for font data access in shaders
Handle<SHVkDescriptorSetLayout> fontDataDescSetLayout;
//! Super temporary. Global descriptor set needs to be revamped along with
//! entire graphics system.
std::function<void(Handle<SHVkCommandBuffer>, uint32_t)> cameraDescSetBind;
private:
void RecomputePositions(SHTextRenderableComponent& textComp) noexcept;
public:
void Init(Handle<SHVkLogicalDevice> device, Handle<SHVkRenderpass> compatibleRenderpass, Handle<SHSubpass> subpass, Handle<SHVkDescriptorPool> descPool, Handle<SHVkShaderModule> textVS, Handle<SHVkShaderModule> textFS, std::function<void(Handle<SHVkCommandBuffer>, uint32_t)> const& bindFunction) noexcept;
void Run(uint32_t frameIndex) noexcept;
void Render (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
void Exit(void) noexcept;
Handle<SHVkDescriptorSetLayout> GetFontDataDescSetLayout (void) const noexcept;
};
}

View File

@ -79,9 +79,9 @@ namespace SHADE
startOffset += pcInfo.size;
}
stageFlags |= shaderModule->GetShaderStageFlagBits();
}
stageFlags |= shaderModule->GetShaderStageFlagBits();
}
// After all the sizes of the push constant blocks have been added, record the size in the interface

View File

@ -3,7 +3,7 @@
namespace SHADE
{
// Used for attachment description creation for renderpass node
enum class SH_ATT_DESC_TYPE_FLAGS
enum class SH_RENDER_GRAPH_RESOURCE_FLAGS
{
COLOR = 0x01,
COLOR_PRESENT = 0x02,
@ -11,7 +11,8 @@ namespace SHADE
STENCIL = 0x08,
DEPTH_STENCIL = 0x10,
INPUT = 0x20,
STORAGE = 0x40
STORAGE = 0x40,
SHARED = 0x80 // if resource is meant to be used across render graphs, mark this flag
};
}

View File

@ -11,6 +11,9 @@
#include "SHAttachmentDescInitParams.h"
#include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "Tools/Utilities/SHUtilities.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Graphics/RenderGraph/SHRenderToSwapchainImageSystem.h"
namespace SHADE
{
@ -49,7 +52,7 @@ namespace SHADE
*/
/***************************************************************************/
void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/)
void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, uint32_t w /*= static_cast<uint32_t>(-1)*/, uint32_t h /*= static_cast<uint32_t>(-1)*/, vk::Format format/* = vk::Format::eB8G8R8A8Unorm*/, uint8_t levels /*= 1*/, vk::ImageUsageFlagBits usageFlags/* = {}*/, vk::ImageCreateFlagBits createFlags /*= {}*/)
{
// If we set to
if (w == static_cast<uint32_t>(-1) && h == static_cast<uint32_t>(-1))
@ -59,10 +62,41 @@ namespace SHADE
format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
}
auto resource = resourceManager->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags);
auto resource = renderGraphStorage->resourceHub->Create<SHRenderGraphResource>(renderGraphStorage, resourceName, typeFlags, format, w, h, levels, usageFlags, createFlags);
renderGraphStorage->graphResources->try_emplace(resourceName, resource);
}
void SHRenderGraph::LinkNonOwningResource(Handle<SHRenderGraph> resourceOrigin, std::string resourceName) noexcept
{
// resource to link
Handle<SHRenderGraphResource> resourceToLink = resourceOrigin->GetRenderGraphResource(resourceName);
if (!resourceToLink)
{
SHLOG_ERROR("Resource does not exist in render graph, cannot link resource.");
return;
}
// Get the final layout of the resource from the previous render graph
vk::ImageLayout finalLayout{vk::ImageLayout::eUndefined};
auto const& nodes = resourceOrigin->GetNodes();
for (auto& node : nodes)
{
if (vk::ImageLayout layout = resourceToLink->GetInfoTracker()->GetLayout(node, {}); layout != vk::ImageLayout::eUndefined)
finalLayout = layout;
for (auto& compute : node->nodeComputes)
{
if (vk::ImageLayout layout = resourceToLink->GetInfoTracker()->GetLayout(compute); layout != vk::ImageLayout::eUndefined)
finalLayout = layout;
}
}
renderGraphStorage->graphResources->try_emplace(resourceName, resourceToLink);
// add to this pool so that when we generate later, the attachment descriptions will make its initial layout the layout stored here
renderGraphStorage->nonOwningResourceInitialLayouts.emplace(resourceToLink.GetId().Raw, finalLayout);
}
/***************************************************************************/
/*!
@ -88,30 +122,59 @@ namespace SHADE
return;
}
// We first want to take all resources track their layout as undefined at the start of the node/renderpass
auto const resources = node->GetResources();
for (auto& resource : resources)
{
resource->GetInfoTracker()->TrackLayout(node, {}, vk::ImageLayout::eUndefined);
}
// attempt to get all final layouts for all resources
for (auto& subpass : node->subpasses)
{
for (auto& color : subpass->colorReferences)
{
// If final renderpass and attachment is a COLOR_PRESENT resource, make resource transition to present after last subpass
if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)))
if (i == nodes.size() - 1 && (node->attResources[color.attachment]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)))
resourceAttFinalLayouts[color.attachment] = vk::ImageLayout::ePresentSrcKHR;
else
resourceAttFinalLayouts[color.attachment] = color.layout;
node->attResources[color.attachment]->infoTracker->TrackLayout(node, subpass, color.layout);
}
for (auto& depth : subpass->depthReferences)
{
resourceAttFinalLayouts[depth.attachment] = depth.layout;
node->attResources[depth.attachment]->infoTracker->TrackLayout(node, subpass, depth.layout);
}
for (auto& input : subpass->inputReferences)
{
resourceAttFinalLayouts[input.attachment] = input.layout;
node->attResources[input.attachment]->infoTracker->TrackLayout(node, subpass, input.layout);
}
}
for (uint32_t j = 0; j < node->attachmentDescriptions.size(); ++j)
{
auto& att = node->attachmentDescriptions[j];
auto& resource = node->attResources[j];
// If resource is from another render graph, use the final layout it had when it was last used in that graph. This is initialized in LinkNonOwningResource.
// We also want to load the attachment, not "don't care".
if (resource->resourceTypeFlags & SHUtilities::ConvertEnum(SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED) &&
renderGraphStorage->nonOwningResourceInitialLayouts.contains(resource.GetId().Raw))
{
att.initialLayout = renderGraphStorage->nonOwningResourceInitialLayouts.at (resource.GetId().Raw);
att.loadOp = vk::AttachmentLoadOp::eLoad;
att.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
}
else
att.initialLayout = vk::ImageLayout::eUndefined;
att.finalLayout = resourceAttFinalLayouts[j];
resource->GetInfoTracker()->TrackLayout(node, {}, att.finalLayout);
}
++i;
}
@ -146,12 +209,13 @@ namespace SHADE
attDesc.stencilLoadOp = vk::AttachmentLoadOp::eLoad;
attDesc.stencilStoreOp = vk::AttachmentStoreOp::eStore;
// TODO: Stencil load and store
// When an image is done being used in a renderpass, the image layout will end up being the finalLayout
// value of the attachment description. We want this to carry over to the next renderpass; specifically
// to have the initialLayout of the attachment description in the next renderpass match the finalLayout in the previous.
attDesc.initialLayout = predAttDesc.finalLayout;
// We also want to track it
predResource->GetInfoTracker()->TrackLayout(node, {}, attDesc.initialLayout);
}
}
}
@ -225,12 +289,12 @@ namespace SHADE
for (auto& inputAtt : subpass->inputReferences)
{
auto resource = node->attResources[inputAtt.attachment];
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::INPUT))
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT))
{
if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR) ||
resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))
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))
colorRead |= (1 << i);
else if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL))
else if (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL))
depthRead |= (1 << i);
}
else
@ -323,6 +387,12 @@ namespace SHADE
}
}
void SHRenderGraph::ConfigureSubSystems(void) noexcept
{
if (renderToSwapchainImageSystem)
renderToSwapchainImageSystem->ConstructPipelines(renderGraphStorage->logicalDevice);
}
/***************************************************************************/
/*!
@ -354,17 +424,17 @@ namespace SHADE
*/
/***************************************************************************/
void SHRenderGraph::Init(std::string graphName, Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept
void SHRenderGraph::Init(std::string graphName, Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain, SHResourceHub* resourceHub) noexcept
{
resourceManager = std::make_shared<SHResourceHub>();
//resourceHub = std::make_shared<SHResourceHub>();
renderGraphStorage = resourceManager->Create<SHRenderGraphStorage>();
renderGraphStorage->graphResources = resourceManager->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
renderGraphStorage = resourceHub->Create<SHRenderGraphStorage>();
renderGraphStorage->graphResources = resourceHub->Create<std::unordered_map<std::string, Handle<SHRenderGraphResource>>>();
renderGraphStorage->logicalDevice = logicalDevice;
renderGraphStorage->swapchain = swapchain;
renderGraphStorage->resourceManager = resourceManager;
renderGraphStorage->resourceHub = resourceHub;
renderGraphStorage->descriptorPool = logicalDevice->CreateDescriptorPools();
name = std::move(graphName);
@ -384,7 +454,6 @@ namespace SHADE
SHRenderGraph::SHRenderGraph(void) noexcept
: renderGraphStorage{}
, nodes{}
, resourceManager{nullptr}
{
}
@ -392,7 +461,6 @@ namespace SHADE
: renderGraphStorage{ rhs.renderGraphStorage }
, nodeIndexing{ std::move(rhs.nodeIndexing) }
, nodes{ std::move(rhs.nodes) }
, resourceManager{ std::move(rhs.resourceManager) }
, name { std::move(rhs.name) }
{
@ -406,7 +474,6 @@ namespace SHADE
renderGraphStorage = rhs.renderGraphStorage;
nodeIndexing = std::move(rhs.nodeIndexing);
nodes = std::move(rhs.nodes);
resourceManager = std::move(rhs.resourceManager);
name = std::move(rhs.name);
return *this;
@ -472,11 +539,40 @@ namespace SHADE
}
}
auto node = nodes.emplace_back(resourceManager->Create<SHRenderGraphNode>(nodeName, renderGraphStorage, std::move(descInitParams), std::move(predecessors)));
auto node = nodes.emplace_back(renderGraphStorage->resourceHub->Create<SHRenderGraphNode>(nodeName, renderGraphStorage, std::move(descInitParams), std::move(predecessors)));
nodeIndexing.emplace(std::move(nodeName), static_cast<uint32_t>(nodes.size()) - 1u);
return node;
}
void SHRenderGraph::AddRenderToSwapchainNode(std::string toSwapchainResource, std::string swapchainResource, std::initializer_list<std::string> predecessorNodes, std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> shaderModules) noexcept
{
for (auto& node : predecessorNodes)
{
if (!nodeIndexing.contains(node))
return;
}
if (renderGraphStorage->graphResources->contains(toSwapchainResource) && renderGraphStorage->graphResources->contains(swapchainResource))
{
auto newNode = AddNode("Render To Present", { ResourceInstruction (toSwapchainResource.c_str()), ResourceInstruction(swapchainResource.c_str()) }, predecessorNodes);
auto newSubpass = newNode->AddSubpass("Render");
newSubpass->AddColorOutput(swapchainResource);
newSubpass->AddInput(toSwapchainResource);
renderToSwapchainImageSystem = renderGraphStorage->resourceHub->Create<SHRenderToSwapchainImageSystem> (newNode, newSubpass, shaderModules);
newSubpass->AddExteriorDrawCalls([=](Handle<SHVkCommandBuffer>& cmdBuffer, uint32_t frameIndex)
{
cmdBuffer->BindPipeline(renderToSwapchainImageSystem->GetPipeline());
newSubpass->BindDescriptorInputDescriptorSets (cmdBuffer, frameIndex);
// draw a quad.
cmdBuffer->DrawArrays(4, 1, 0, 0);
});
}
}
/***************************************************************************/
/*!
@ -497,6 +593,7 @@ namespace SHADE
ConfigureSubpasses();
ConfigureRenderpasses();
ConfigureFramebuffers();
ConfigureSubSystems();
}
/***************************************************************************/
@ -539,7 +636,10 @@ namespace SHADE
{
// resize resources
for (auto& [name, resource] : *renderGraphStorage->graphResources)
{
if (!renderGraphStorage->nonOwningResourceInitialLayouts.contains (resource.GetId().Raw))
resource->HandleResize(newWidth, newHeight);
}
for (auto& node : nodes)
{
@ -556,6 +656,11 @@ namespace SHADE
}
std::vector<Handle<SHRenderGraphNode>> const& SHRenderGraph::GetNodes(void) const noexcept
{
return nodes;
}
Handle<SHRenderGraphResource> SHRenderGraph::GetRenderGraphResource(std::string const& resourceName) const noexcept
{
if (renderGraphStorage->graphResources->contains(resourceName))

View File

@ -32,6 +32,7 @@ namespace SHADE
class SHGraphicsGlobalData;
class SHVkDescriptorPool;
class SHRenderGraphStorage;
class SHRenderToSwapchainImageSystem;
class SH_API SHRenderGraph
{
@ -52,6 +53,7 @@ namespace SHADE
void ConfigureAttachmentDescriptions (void) noexcept;
void ConfigureSubpasses (void) noexcept;
void ConfigureRenderpasses (void) noexcept;
void ConfigureSubSystems (void) noexcept;
void ConfigureFramebuffers (void) noexcept;
/*-----------------------------------------------------------------------*/
@ -66,12 +68,12 @@ namespace SHADE
//! Render graph nodes
std::vector<Handle<SHRenderGraphNode>> nodes;
//! Resource library for graph handles
std::shared_ptr<SHResourceHub> resourceManager;
//! Name of the RenderGraph
std::string name;
//! For rendering onto the swapchain
Handle<SHRenderToSwapchainImageSystem> renderToSwapchainImageSystem;
public:
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
@ -84,9 +86,11 @@ namespace SHADE
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void Init (std::string graphName, Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain) noexcept;
void AddResource(std::string resourceName, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
void Init (std::string graphName, Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkSwapchain> swapchain, SHResourceHub* resourceHub) noexcept;
void AddResource(std::string resourceName, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, uint32_t w = static_cast<uint32_t>(-1), uint32_t h = static_cast<uint32_t>(-1), vk::Format format = vk::Format::eB8G8R8A8Unorm, uint8_t levels = 1, vk::ImageUsageFlagBits usageFlags = {}, vk::ImageCreateFlagBits createFlags = {});
void LinkNonOwningResource (Handle<SHRenderGraph> resourceOrigin, std::string resourceName) noexcept;
Handle<SHRenderGraphNode> AddNode (std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::initializer_list<std::string> predecessorNodes) noexcept;
void AddRenderToSwapchainNode (std::string toSwapchainResource, std::string swapchainResource, std::initializer_list<std::string> predecessorNodes, std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> shaderModules) noexcept;
void Generate (void) noexcept;
void CheckForNodeComputes (void) noexcept;
@ -98,8 +102,29 @@ namespace SHADE
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
Handle<SHRenderGraphNode> GetNode (std::string const& nodeName) const noexcept;
std::vector<Handle<SHRenderGraphNode>> const& GetNodes (void) const noexcept;
Handle<SHRenderGraphResource> GetRenderGraphResource (std::string const& resourceName) const noexcept;
};
}
#endif
/* Some notes here:
* - The graph wasn't implemented with the intention of it being this versatile.
* - Graphs weren't meant to share resources and hence the generating of the render graph doesn't account for it.
* However, because it was eventually necessary that some resources had to be shared and its contents carried over to
* other graphs, the functionality was implemented through a link function in SHRenderGraph.cpp to facilitate this linkage.
* This should ideally be replaced by an implementation more self-contained, perhaps through a higher level class like a canvas
* that manage the resources instead and can facilitate such linking of resources. Either that, or we allow only 1 render graph,
* but different matrices (SHRenderer) can be used in different nodes.
* - There are also way too many hash maps created for ease of access. This definitely can be cut down.
* -
*
*/

View File

@ -46,7 +46,7 @@ namespace SHADE
for (uint32_t j = 0; j < attResources.size(); ++j)
{
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
@ -74,7 +74,7 @@ namespace SHADE
for (uint32_t j = 0; j < attResources.size(); ++j)
{
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
uint32_t imageViewIndex = (attResources[j]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
imageViews[j] = attResources[j]->imageViews[imageViewIndex];
// We want the minimum dimensions for the framebuffer because the image attachments referenced cannot have dimensions smaller than the framebuffer's
@ -160,7 +160,7 @@ namespace SHADE
newDesc.format = attResources[i]->resourceFormat;
if (attResources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT))
if (attResources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT))
containsSwapchainImage = true;
resourceAttachmentMapping->try_emplace(attResources[i].GetId().Raw, i);
@ -250,7 +250,7 @@ namespace SHADE
// Add subpass to container and create mapping for it
subpasses.emplace_back
(
graphStorage->resourceManager->Create<SHSubpass>
graphStorage->resourceHub->Create<SHSubpass>
(
subpassName,
graphStorage, GetHandle(), static_cast<uint32_t>(subpasses.size()),
@ -259,7 +259,7 @@ namespace SHADE
);
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);
Handle<SHSubpass> subpass = subpasses.back();
subpass->Init(*graphStorage->resourceManager);
subpass->Init(*graphStorage->resourceHub);
// Register the SuperBatch
batcher.RegisterSuperBatch(subpass->GetSuperBatch());
@ -279,10 +279,18 @@ namespace SHADE
nodeComputeResources.push_back(resource);
}
// need to use for tracking resources
std::vector<Handle<SHRenderGraphResource>> temp (nodeComputeResources);
// Create the subpass compute with the resources
auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(std::move(nodeName), graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty());
auto nodeCompute = graphStorage->resourceHub->Create<SHRenderGraphNodeCompute>(std::move(nodeName), graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty());
nodeComputes.push_back(nodeCompute);
for (auto& resource : temp)
{
resource->GetInfoTracker()->TrackLayout(nodeCompute);
}
return nodeCompute;
}
@ -405,4 +413,9 @@ namespace SHADE
return {};
}
std::vector<Handle<SHRenderGraphResource>> const& SHRenderGraphNode::GetResources(void) const noexcept
{
return attResources;
}
}

View File

@ -117,6 +117,7 @@ namespace SHADE
Handle<SHVkRenderpass> GetRenderpass(void) const noexcept;
Handle<SHSubpass> GetSubpass(std::string_view subpassName) const noexcept;
Handle<SHRenderGraphResource> GetResource (uint32_t resourceIndex) const noexcept;
std::vector<Handle<SHRenderGraphResource>> const& GetResources (void) const noexcept;
friend class SHRenderGraph;
};

View File

@ -45,6 +45,7 @@ namespace SHADE
// save the resources
resources = std::move (subpassComputeResources);
//Get the descriptor set layouts required to allocate. We only want the ones for allocate because
//global descriptors are already bound in the main system.
auto const& graphResourceLayout = computePipeline->GetPipelineLayout()->GetDescriptorSetLayoutsPipeline()[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE];
@ -65,7 +66,7 @@ namespace SHADE
if (layouts.size() == SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE + 1)
{
// create compute resources
computeResource = graphStorage->resourceManager->Create<ComputeResource>();
computeResource = graphStorage->resourceHub->Create<ComputeResource>();
auto computeResourceLayout = layouts[SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE];
computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, { 1 });
#ifdef _DEBUG
@ -119,7 +120,7 @@ namespace SHADE
// loop through bindings and write descriptor sets
for (auto& binding : pipelineDescSetLayouts->GetBindings())
{
uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0;
uint32_t imageIndex = (resources[i]->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? frameIndex : 0;
SHVkDescriptorSetGroup::viewSamplerLayout vsl = std::make_tuple(resources[i]->GetImageView(imageIndex), Handle<SHVkSampler>{}, vk::ImageLayout::eGeneral);
graphResourceDescSets[frameIndex]->ModifyWriteDescImage(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, binding.BindPoint, { &vsl, 1 });
@ -154,7 +155,7 @@ namespace SHADE
.newLayout = vk::ImageLayout::eGeneral,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = resource->GetImage((resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(),
.image = resource->GetImage((resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0)->GetVkImage(),
.subresourceRange = vk::ImageSubresourceRange
{
.aspectMask = resource->imageAspectFlags,

View File

@ -6,9 +6,41 @@
#include "Graphics/Buffers/SHVkBuffer.h"
#include "Graphics/SHVkUtil.h"
#include "SHRenderGraphStorage.h"
#include "Graphics/RenderGraph/SHSubpass.h"
#include "Graphics/RenderGraph/SHRenderGraphNode.h"
namespace SHADE
{
void SHRenderGraphResource::InfoTracker::TrackLayout(Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass, vk::ImageLayout layout) noexcept
{
NodeSubpassPair nodeSubpassPair = std::pair(node, subpass);
layoutTracker[std::hash<NodeSubpassPair>{}(nodeSubpassPair)] = layout;
}
void SHRenderGraphResource::InfoTracker::TrackLayout(Handle<SHRenderGraphNodeCompute> compute) noexcept
{
computeTracker.emplace (compute.GetId().Raw);
}
vk::ImageLayout SHRenderGraphResource::InfoTracker::GetLayout(Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass) const noexcept
{
NodeSubpassPair nodeSubpassPair = std::pair(node, subpass);
std::size_t hashedValue = std::hash<NodeSubpassPair>{}(nodeSubpassPair);
if (layoutTracker.contains(hashedValue))
return layoutTracker.at(hashedValue);
else
return vk::ImageLayout::eUndefined;
}
vk::ImageLayout SHRenderGraphResource::InfoTracker::GetLayout(Handle<SHRenderGraphNodeCompute> compute) const noexcept
{
if (computeTracker.contains (compute.GetId().Raw))
return vk::ImageLayout::eGeneral;
else
return vk::ImageLayout::eUndefined;
}
/***************************************************************************/
/*!
@ -46,7 +78,7 @@ namespace SHADE
*/
/***************************************************************************/
SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
SHRenderGraphResource::SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept
: graphStorage{renderGraphStorage}
, resourceTypeFlags{ }
, resourceFormat{ format }
@ -58,9 +90,9 @@ namespace SHADE
, resourceName{ name }
{
// If the resource type is an arbitrary image and not swapchain image
if (typeFlags.size() == 1 && *typeFlags.begin() == SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)
if (typeFlags.size() == 1 && *typeFlags.begin() == SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)
{
resourceTypeFlags |= static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT);
resourceTypeFlags |= static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT);
// Prepare image view details
SHImageViewDetails viewDetails
@ -98,30 +130,30 @@ namespace SHADE
// Check the resource type and set image usage flags and image aspect flags accordingly
switch (type)
{
case SH_ATT_DESC_TYPE_FLAGS::COLOR:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR:
usage |= vk::ImageUsageFlagBits::eColorAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eColor;
break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eDepth;
break;
case SH_ATT_DESC_TYPE_FLAGS::STENCIL:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil;
break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL:
usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment;
imageAspectFlags |= vk::ImageAspectFlagBits::eStencil | vk::ImageAspectFlagBits::eDepth;
break;
case SH_ATT_DESC_TYPE_FLAGS::INPUT:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT:
usage |= vk::ImageUsageFlagBits::eInputAttachment;
usage |= vk::ImageUsageFlagBits::eSampled;
break;
case SH_ATT_DESC_TYPE_FLAGS::STORAGE:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE:
usage |= vk::ImageUsageFlagBits::eStorage;
break;
case SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT:
{
SHLOG_ERROR ("COLOR_PRESENT cannot be with other resource type flags. ");
return;
@ -151,6 +183,8 @@ namespace SHADE
imageViews.push_back(imageView);
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eImageView, imageView->GetImageView(), "[Image View] " + resourceName);
}
infoTracker = renderGraphStorage->resourceHub->Create<InfoTracker>();
}
/***************************************************************************/
@ -175,6 +209,7 @@ namespace SHADE
, mipLevels{ rhs.mipLevels }
, imageAspectFlags{ rhs.imageAspectFlags }
, graphStorage{rhs.graphStorage}
, infoTracker {std::move (rhs.infoTracker)}
{
}
@ -207,6 +242,7 @@ namespace SHADE
mipLevels = rhs.mipLevels;
imageAspectFlags = rhs.imageAspectFlags;
graphStorage = rhs.graphStorage;
infoTracker = std::move(infoTracker);
return *this;
}
@ -229,7 +265,7 @@ namespace SHADE
width = newWidth;
height = newHeight;
if ((resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) == 0)
if ((resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) == 0)
{
// prepare image view details
SHImageViewDetails viewDetails
@ -347,4 +383,9 @@ namespace SHADE
return resourceName;
}
SHADE::Handle<SHADE::SHRenderGraphResource::InfoTracker> SHRenderGraphResource::GetInfoTracker(void) const noexcept
{
return infoTracker;
}
}

View File

@ -6,6 +6,7 @@
#include "Resource/SHHandle.h"
#include "Graphics/SHVulkanIncludes.h"
#include "SH_API.h"
#include <unordered_set>
namespace SHADE
{
@ -16,11 +17,41 @@ namespace SHADE
class SHVkCommandBuffer;
class SHVkBuffer;
class SHRenderGraphStorage;
class SHRenderGraphNode;
class SHSubpass;
class SHRenderGraphNodeCompute;
static constexpr uint32_t NON_SWAPCHAIN_RESOURCE_INDEX = 0;
class SH_API SHRenderGraphResource
{
public:
// For keeping track of resources as it gets passed down the pipeline (between multiple render graphs)
class InfoTracker
{
private:
using NodeSubpassPair = std::pair<Handle<SHRenderGraphNode>, Handle<SHSubpass>>;
//! key here is the render graph node and subpass name combined, value is the layout of the resource at that node and subpass
std::unordered_map<std::size_t, vk::ImageLayout> layoutTracker;
//! if a resource is involved in a compute process, record it here
std::unordered_set<uint64_t> computeTracker;
public:
/*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/
void TrackLayout (Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass, vk::ImageLayout layout) noexcept;
void TrackLayout (Handle<SHRenderGraphNodeCompute> compute) noexcept;
/*-----------------------------------------------------------------------*/
/* SETTERS AND GETTERS */
/*-----------------------------------------------------------------------*/
vk::ImageLayout GetLayout(Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass) const noexcept;
vk::ImageLayout GetLayout(Handle<SHRenderGraphNodeCompute> compute) const noexcept;
};
private:
/*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER VARIABLES */
@ -62,12 +93,14 @@ namespace SHADE
//! usage flags
vk::ImageUsageFlags usage = {};
//! For tracking resource states in stages of the render graphs
Handle<InfoTracker> infoTracker;
public:
/*-----------------------------------------------------------------------*/
/* CTORS AND DTORS */
/*-----------------------------------------------------------------------*/
SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_ATT_DESC_TYPE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
SHRenderGraphResource(Handle<SHRenderGraphStorage> renderGraphStorage, std::string const& name, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, vk::Format format, uint32_t w, uint32_t h, uint8_t levels, vk::ImageUsageFlagBits usageFlags, vk::ImageCreateFlagBits createFlags) noexcept;
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
~SHRenderGraphResource(void) noexcept;
@ -89,6 +122,7 @@ namespace SHADE
Handle<SHVkImage> GetImage (uint32_t index = NON_SWAPCHAIN_RESOURCE_INDEX) const noexcept;
uint8_t GetMipLevels (void) const noexcept;
std::string GetName (void) const noexcept;
Handle<InfoTracker> GetInfoTracker (void) const noexcept;
friend class SHRenderGraphNode;
friend class SHRenderGraph;

View File

@ -20,7 +20,7 @@ namespace SHADE
Handle<SHVkSwapchain> swapchain;
//! Resource manager for creation of objects
std::shared_ptr<SHResourceHub> resourceManager;
SHResourceHub* resourceHub;
//! Descriptor pool for the descriptor sets to be created in the subpasses
Handle<SHVkDescriptorPool> descriptorPool;
@ -28,6 +28,10 @@ namespace SHADE
//! For accessing resources anywhere in the graph
Handle<std::unordered_map<std::string, Handle<SHRenderGraphResource>>> graphResources;
//! HACK: Because there's no interface to specify a dependency between graphs, this will help attachment descriptions
//! use the correct layout, when a resource is shared between graphs
std::unordered_map<uint64_t, vk::ImageLayout> nonOwningResourceInitialLayouts{};
//SHRenderGraphStorage(void) noexcept;
//SHRenderGraphStorage(SHRenderGraphStorage&& rhs) noexcept;
//SHRenderGraphStorage& operator=(SHRenderGraphStorage&& rhs) noexcept;

View File

@ -0,0 +1,66 @@
#include "SHpch.h"
#include "SHRenderToSwapchainImageSystem.h"
#include "Graphics/Devices/SHVkLogicalDevice.h"
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsGlobalData.h"
#include "Graphics/RenderGraph/SHRenderGraphNode.h"
#include "Graphics/RenderGraph/SHSubpass.h"
#include "Graphics/SHVkUtil.h"
namespace SHADE
{
SHRenderToSwapchainImageSystem::SHRenderToSwapchainImageSystem(Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass, std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> shaders) noexcept
: renderGraphNode {node}
, subpass{subpass}
, shaderModules{shaders}
, pipeline{}
, pipelineLayout{}
{
}
void SHRenderToSwapchainImageSystem::ConstructPipelines(Handle<SHVkLogicalDevice> logicalDevice) noexcept
{
auto pipelineLayout = logicalDevice->CreatePipelineLayout(SHPipelineLayoutParams
{
.shaderModules = {shaderModules.first, shaderModules.second},
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts(),
});
pipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderGraphNode->GetRenderpass(), subpass);
SHInputAssemblyState inputAssembly{};
inputAssembly.topology = vk::PrimitiveTopology::eTriangleFan;
pipeline->GetPipelineState().SetInputAssemblyState(inputAssembly);
SHColorBlendState colorBlendState{};
colorBlendState.logic_op_enable = VK_FALSE;
colorBlendState.logic_op = vk::LogicOp::eCopy;
auto const& subpassColorReference = subpass->GetColorAttachmentReferences()[0];
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
{
.blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(subpassColorReference.attachment)),
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
.colorBlendOp = vk::BlendOp::eAdd,
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
.alphaBlendOp = vk::BlendOp::eAdd,
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
}
);
pipeline->GetPipelineState().SetColorBlenState(colorBlendState);
pipeline->ConstructPipeline();
}
Handle<SHVkPipeline> SHRenderToSwapchainImageSystem::GetPipeline(void) const noexcept
{
return pipeline;
}
}

View File

@ -0,0 +1,43 @@
#pragma once
#include "Resource/SHHandle.h"
#include <utility>
namespace SHADE
{
class SHVkPipeline;
class SHVkPipelineLayout;
class SHVkShaderModule;
class SHRenderGraphNode;
class SHSubpass;
class SHVkLogicalDevice;
class SHSubpass;
class SHRenderToSwapchainImageSystem
{
private:
//! Render Graph node to get the renderpass from to initialize the pipeline
Handle<SHRenderGraphNode> renderGraphNode;
//! Subpass to initialize the pipeline with
Handle<SHSubpass> subpass;
//! Shader module required to render the quad on screen
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> shaderModules;
//! pipeline required to draw the image
Handle<SHVkPipeline> pipeline;
//! Pipeline layout of the pipeline
Handle<SHVkPipelineLayout> pipelineLayout;
public:
SHRenderToSwapchainImageSystem (Handle<SHRenderGraphNode> node, Handle<SHSubpass> subpass, std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> shaders) noexcept;
void ConstructPipelines (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
Handle<SHVkPipeline> GetPipeline (void) const noexcept;
};
}

View File

@ -40,7 +40,7 @@ namespace SHADE
, inputReferences{}
, name { name }
, graphStorage{ renderGraphStorage }
, inputImageDescriptors {SHGraphicsConstants::NUM_FRAME_BUFFERS}
, inputImageDescriptorSets{}
{
}
@ -67,7 +67,7 @@ namespace SHADE
, exteriorDrawCalls{ std::move(rhs.exteriorDrawCalls) }
, graphStorage{ rhs.graphStorage }
, inputNames{ std::move(rhs.inputNames) }
, inputImageDescriptors{ std::move(rhs.inputImageDescriptors) }
, inputImageDescriptorSets{ std::move(rhs.inputImageDescriptorSets) }
, inputDescriptorLayout{ rhs.inputDescriptorLayout }
, inputSamplers{ rhs.inputSamplers }
, name { rhs.name }
@ -102,7 +102,7 @@ namespace SHADE
exteriorDrawCalls = std::move(rhs.exteriorDrawCalls);
graphStorage = rhs.graphStorage;
inputNames = std::move(rhs.inputNames);
inputImageDescriptors = std::move(rhs.inputImageDescriptors);
inputImageDescriptorSets = std::move(rhs.inputImageDescriptorSets);
inputDescriptorLayout = rhs.inputDescriptorLayout;
inputSamplers = rhs.inputSamplers;
name = std::move(rhs.name);
@ -148,18 +148,18 @@ namespace SHADE
*/
/***************************************************************************/
void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType) noexcept
void SHSubpass::AddDepthOutput(std::string resourceToReference, SH_RENDER_GRAPH_RESOURCE_FLAGS attachmentDescriptionType) noexcept
{
vk::ImageLayout imageLayout;
switch (attachmentDescriptionType)
{
case SH_ATT_DESC_TYPE_FLAGS::DEPTH:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH:
imageLayout = vk::ImageLayout::eDepthAttachmentOptimal;
break;
case SH_ATT_DESC_TYPE_FLAGS::STENCIL:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::STENCIL:
imageLayout = vk::ImageLayout::eStencilAttachmentOptimal;
break;
case SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL:
case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL:
imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
break;
default:
@ -202,6 +202,8 @@ namespace SHADE
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
{
commandBuffer->BeginLabeledSegment(name);
// Ensure correct transforms are provided
superBatch->UpdateBuffers(frameIndex, descPool);
@ -211,7 +213,7 @@ namespace SHADE
// Draw all the exterior draw calls
for (auto& drawCall : exteriorDrawCalls)
{
drawCall(commandBuffer);
drawCall(commandBuffer, frameIndex);
}
commandBuffer->EndLabeledSegment();
}
@ -221,7 +223,15 @@ namespace SHADE
UpdateWriteDescriptors();
}
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept
void SHSubpass::BindDescriptorInputDescriptorSets(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) const noexcept
{
if (!inputImageDescriptorSets.empty())
{
cmdBuffer->BindDescriptorSet(inputImageDescriptorSets[frameIndex], SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_RESOURCE, { });
}
}
void SHSubpass::AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&, uint32_t)> const& newDrawCall) noexcept
{
exteriorDrawCalls.push_back(newDrawCall);
}
@ -237,6 +247,8 @@ namespace SHADE
if (inputNames.empty())
return;
inputImageDescriptorSets.resize(SHGraphicsConstants::NUM_FRAME_BUFFERS);
std::vector<SHVkDescriptorSetLayout::Binding> bindings{};
for (auto& input : inputReferences)
@ -280,8 +292,8 @@ namespace SHADE
}
}
//// maybe do this in handle resize?
//UpdateWriteDescriptors();
// maybe do this in handle resize?
UpdateWriteDescriptors();
}
void SHSubpass::UpdateWriteDescriptors(void) noexcept
@ -296,7 +308,7 @@ namespace SHADE
// For every frame's descriptor set
for (auto& group : inputImageDescriptors)
for (auto& group : inputImageDescriptorSets)
{
if (group)
group.Free();
@ -315,7 +327,7 @@ namespace SHADE
auto resource = graphStorage->graphResources->at(inputNames[binding.BindPoint]);
// If resource is swapchain image, get the correct image, if not just get 0.
uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) ? i : 0;
uint32_t viewIndex = (resource->resourceTypeFlags & static_cast<uint32_t>(SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)) ? i : 0;
// layout is GENERAL if image is meant to be used as storage image, if not use SHADER_READ_ONLY_OPTINAL
vk::ImageLayout descriptorLayout = (binding.Type == vk::DescriptorType::eStorageImage) ? vk::ImageLayout::eGeneral : vk::ImageLayout::eShaderReadOnlyOptimal;

View File

@ -55,8 +55,11 @@ namespace SHADE
//! For getting attachment reference indices using handles
std::unordered_map<uint64_t, uint32_t> const* resourceAttachmentMapping;
//! Descriptor set group to hold the images for input
std::vector<Handle<SHVkDescriptorSetGroup>> inputImageDescriptors;
//! Descriptor set group to hold the images for input. We have 3 here just in case
//! one of the images is a swapchain image. Practically speaking its not likely not
//! swapchain images will end up being images used in descriptor sets, but this is
//! to have the support for it. The cost is not much.
std::vector<Handle<SHVkDescriptorSetGroup>> inputImageDescriptorSets;
//! Descriptor set layout for allocating descriptor set for inputs
Handle<SHVkDescriptorSetLayout> inputDescriptorLayout;
@ -76,7 +79,7 @@ namespace SHADE
//! after we draw everything from the batch. Because of this, these draw calls
//! are always the last things drawn, so DO NOT USE THIS FUNCTIONALITY FOR ANYTHING
//! COMPLEX.
std::vector<std::function<void(Handle<SHVkCommandBuffer>&)>> exteriorDrawCalls;
std::vector<std::function<void(Handle<SHVkCommandBuffer>&, uint32_t)>> exteriorDrawCalls;
/// For identifying subpasses
std::string name;
@ -95,15 +98,16 @@ namespace SHADE
// Preparation functions
void AddColorOutput(std::string resourceToReference) noexcept;
void AddGeneralColorOutput(std::string resourceToReference) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_ATT_DESC_TYPE_FLAGS attachmentDescriptionType = SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL) noexcept;
void AddDepthOutput(std::string resourceToReference, SH_RENDER_GRAPH_RESOURCE_FLAGS attachmentDescriptionType = SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL) noexcept;
void AddGeneralDepthOutput(std::string resourceToReference) noexcept;
void AddInput(std::string resourceToReference) noexcept;
void AddGeneralInput (std::string resourceToReference) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&)> const& newDrawCall) noexcept;
void AddExteriorDrawCalls(std::function<void(Handle<SHVkCommandBuffer>&, uint32_t)> const& newDrawCall) noexcept;
// Runtime functions
void Execute(Handle<SHVkCommandBuffer>& commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
void HandleResize (void) noexcept;
void BindDescriptorInputDescriptorSets (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) const noexcept;
void Init(SHResourceHub& resourceManager) noexcept;

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