Implemented a custom physics engine #316
|
@ -7,6 +7,7 @@
|
|||
Translate: {x: 0, y: 0.304069757, z: 1.73034382}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Camera Component:
|
||||
Position: {x: 0, y: 0.304069757, z: 1.73034382}
|
||||
Pitch: 0
|
||||
|
@ -17,6 +18,7 @@
|
|||
Near: 0.00999999978
|
||||
Far: 10000
|
||||
Perspective: true
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 1
|
||||
Name: Raccoon
|
||||
|
@ -24,12 +26,14 @@
|
|||
NumberOfChildren: 1
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Translate: {x: -1.86388135, y: 0.0544953719, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 149697411
|
||||
Material: 126974645
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 3
|
||||
Name: Bag
|
||||
|
@ -40,9 +44,11 @@
|
|||
Translate: {x: 0.006237939, y: -0.000393368304, z: 0}
|
||||
Rotate: {x: -0, y: 2.79945588, z: 0}
|
||||
Scale: {x: 1.0000881, y: 1, z: 1.0000881}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 2
|
||||
Name: DirectionalLight
|
||||
|
@ -50,12 +56,13 @@
|
|||
NumberOfChildren: 0
|
||||
Components:
|
||||
Light Component:
|
||||
Position: {x: 0, y: 0, z: 0}
|
||||
Position: {x: 3, y: 4.5, z: 7}
|
||||
Type: Directional
|
||||
Direction: {x: 0, y: 0, z: 1}
|
||||
Direction: {x: -0.298000008, y: 0.522498012, z: 0.798600018}
|
||||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 4
|
||||
Name: AmbientLight
|
||||
|
@ -69,4 +76,20 @@
|
|||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0.600000024
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 5
|
||||
Name: Floor
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0.0810000002, z: 0}
|
||||
Rotate: {x: -1.57079637, y: 0, z: 0}
|
||||
Scale: {x: 50, y: 50, z: 50}
|
||||
IsActive: true
|
||||
Renderable Component:
|
||||
Mesh: 141771688
|
||||
Material: 124370424
|
||||
IsActive: true
|
||||
Scripts: ~
|
|
@ -6,6 +6,8 @@ struct DirectionalLightStruct
|
|||
uint isActive;
|
||||
uint cullingMask;
|
||||
vec4 diffuseColor;
|
||||
mat4 pvMatrix;
|
||||
uint shadowData;
|
||||
};
|
||||
|
||||
struct AmbientLightStruct
|
||||
|
@ -22,7 +24,10 @@ layout(set = 3, binding = 1, rgba32f) uniform image2D normals;
|
|||
layout(set = 3, binding = 2, rgba8) uniform image2D albedo;
|
||||
layout(set = 3, binding = 3, r32ui) uniform uimage2D lightLayerData;
|
||||
layout(set = 3, binding = 4, r8) uniform image2D ssaoBlurredImage;
|
||||
layout(set = 3, binding = 5, rgba8) uniform image2D targetImage;
|
||||
layout(set = 3, binding = 5, rgba8) uniform image2D positionWorldSpace;
|
||||
layout(set = 3, binding = 6, rgba8) uniform image2D targetImage;
|
||||
|
||||
layout (set = 4, binding = 0) uniform sampler2D shadowMaps[]; // for textures (global)
|
||||
|
||||
layout(set = 1, binding = 0) uniform LightCounts
|
||||
{
|
||||
|
@ -43,6 +48,25 @@ layout(std430, set = 1, binding = 4) buffer AmbientLightData
|
|||
AmbientLightStruct aLightData[];
|
||||
} AmbLightData;
|
||||
|
||||
float CalcShadowValue (sampler2D shadowMap, vec4 worldSpaceFragPos, mat4 lightPV)
|
||||
{
|
||||
vec4 fragPosLightPOV = lightPV * worldSpaceFragPos;
|
||||
vec3 converted = (fragPosLightPOV.xyz / fragPosLightPOV.w) * vec3(0.5f) + vec3(0.5f);
|
||||
|
||||
float sampledDepth = texture(shadowMap, converted.xy).r;
|
||||
|
||||
if (converted.x < 0.0f || converted.x > 1.0f || converted.y < 0.0f || converted.y > 1.0f)
|
||||
return 1.0f;
|
||||
|
||||
if (fragPosLightPOV.z > sampledDepth && fragPosLightPOV.w > 0.0f)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
else
|
||||
return 1.0f;
|
||||
// return step (fragPosLightPOV.z, );
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
// convenient variables
|
||||
|
@ -52,6 +76,9 @@ void main()
|
|||
vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb;
|
||||
|
||||
// Get position of fragment in world space
|
||||
vec4 positionWorld = vec4 (imageLoad (positionWorldSpace, globalThread).rgb, 1.0f);
|
||||
|
||||
// Get position of fragment in view spacee
|
||||
vec3 positionView = imageLoad (positions, globalThread).rgb;
|
||||
|
||||
// normal of fragment
|
||||
|
@ -62,6 +89,18 @@ void main()
|
|||
|
||||
vec3 fragColor = vec3 (0.0f);
|
||||
|
||||
vec4 shadowMapColor = vec4 (1.0f);
|
||||
|
||||
for (int i = 0; i < lightCounts.ambientLights; ++i)
|
||||
{
|
||||
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
|
||||
{
|
||||
// Just do some add
|
||||
//fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f);
|
||||
fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < lightCounts.directionalLights; ++i)
|
||||
{
|
||||
if ((lightLayer & DirLightData.dLightData[i].cullingMask) != 0)
|
||||
|
@ -74,16 +113,13 @@ void main()
|
|||
|
||||
// Calculate the fragment color
|
||||
fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < lightCounts.ambientLights; ++i)
|
||||
// If the shadow map is enabled (test the bit)
|
||||
if ((DirLightData.dLightData[i].shadowData & uint(1)) == 1)
|
||||
{
|
||||
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
|
||||
{
|
||||
// Just do some add
|
||||
//fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f);
|
||||
fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength);
|
||||
// calculate shadow map here
|
||||
fragColor *= CalcShadowValue (shadowMaps[0], positionWorld, DirLightData.dLightData[i].pvMatrix).xxx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,6 +128,12 @@ void main()
|
|||
|
||||
// store result into result image
|
||||
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f));
|
||||
//imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(ssaoVal.rrr, 1.0f));
|
||||
|
||||
// vec2 normTexCoords = vec2 (gl_GlobalInvocationID.xy) / vec2 (1024.0f);
|
||||
// vec4 shadowMapVal = texture(shadowMaps[0], normTexCoords);
|
||||
// if (normTexCoords.x > 1.0f || normTexCoords.y > 1.0f)
|
||||
// shadowMapVal = vec4(0.0f);
|
||||
|
||||
// imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), shadowMapVal.xxxx);
|
||||
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
#version 450
|
||||
#extension GL_KHR_vulkan_glsl : enable
|
||||
|
||||
//#include "ShaderDescriptorDefinitions.glsl"
|
||||
|
||||
|
||||
layout(location = 0) in vec3 aVertexPos;
|
||||
layout(location = 4) in mat4 worldTransform;
|
||||
|
||||
layout(set = 1, binding = 0) uniform CameraData
|
||||
{
|
||||
vec4 position;
|
||||
mat4 vpMat;
|
||||
mat4 viewMat;
|
||||
mat4 projMat;
|
||||
} cameraData;
|
||||
|
||||
void main()
|
||||
{
|
||||
// clip space for rendering
|
||||
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Name: ShadowMap_VS
|
||||
ID: 44646107
|
||||
Type: 2
|
|
@ -16,11 +16,12 @@ layout(location = 0) in struct
|
|||
vec4 vertPos; // location 0
|
||||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
|
||||
} In;
|
||||
|
||||
// material stuff
|
||||
layout(location = 3) flat in struct
|
||||
layout(location = 4) flat in struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
|
@ -38,12 +39,14 @@ layout(location = 1) out uint outEntityID;
|
|||
layout(location = 2) out uint lightLayerIndices;
|
||||
layout(location = 3) out vec4 normals;
|
||||
layout(location = 4) out vec4 albedo;
|
||||
layout(location = 5) out vec4 worldSpacePosition;
|
||||
|
||||
void main()
|
||||
{
|
||||
position = In.vertPos;
|
||||
normals = In.normal;
|
||||
albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) * MatProp.data[In2.materialIndex].color;
|
||||
worldSpacePosition = In.worldPos;
|
||||
|
||||
outEntityID = In2.eid;
|
||||
lightLayerIndices = In2.lightLayerIndex;
|
||||
|
|
Binary file not shown.
|
@ -17,11 +17,12 @@ layout(location = 0) out struct
|
|||
vec4 vertPos; // location 0
|
||||
vec2 uv; // location = 1
|
||||
vec4 normal; // location = 2
|
||||
vec4 worldPos; // location = 3
|
||||
|
||||
} Out;
|
||||
|
||||
// material stuff
|
||||
layout(location = 3) out struct
|
||||
layout(location = 4) out struct
|
||||
{
|
||||
int materialIndex;
|
||||
uint eid;
|
||||
|
@ -49,6 +50,8 @@ void main()
|
|||
// gBuffer position will be in view space
|
||||
Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f);
|
||||
|
||||
Out.worldPos = worldTransform * vec4 (aVertexPos, 1.0f);
|
||||
|
||||
// uvs for texturing in fragment shader
|
||||
Out.uv = aUV;
|
||||
|
||||
|
|
Binary file not shown.
|
@ -270,8 +270,12 @@ namespace SHADE
|
|||
camera.viewMatrix(1, 3) = -UP.Dot(camera.position + camera.offset);
|
||||
camera.viewMatrix(2, 3) = -view.Dot(camera.position + camera.offset);
|
||||
|
||||
//SHVec3 target{ 0.0f,0.0f,-1.0f };
|
||||
//target = SHVec3::RotateX(target, SHMath::DegreesToRadians(camera.pitch));
|
||||
//target = SHVec3::RotateY(target, SHMath::DegreesToRadians(camera.yaw));
|
||||
//target += camera.position;
|
||||
|
||||
|
||||
//camera.viewMatrix = SHMatrix::Transpose(SHMatrix::LookAtLH(camera.position, target, SHVec3(0.0f, -1.0f, 0.0f)));
|
||||
|
||||
camera.dirtyView = false;
|
||||
}
|
||||
|
@ -309,7 +313,9 @@ 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.perspProjMatrix = SHMatrix::OrthographicLH(9.0f, 9.0f, 0.1f, 20.0f);
|
||||
camera.orthoProjMatrix = SHMatrix::OrthographicRH(camera.GetWidth(), camera.GetHeight(), camera.GetNear(), camera.GetFar());
|
||||
//camera.perspProjMatrix = SHMatrix::OrthographicLH(5.0f, 5.0f, 0.1f, 20.0f);
|
||||
//camera.projMatrix.Transpose();
|
||||
|
||||
camera.dirtyProj = false;
|
||||
|
|
|
@ -262,6 +262,13 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
if (ImGui::IsItemHovered())
|
||||
{
|
||||
ImGui::BeginTooltip();
|
||||
ImGui::Text("AssetID: %zu | Path: %s", asset->id, asset->path.c_str());
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
|
||||
//TODO: Combine Draw asset and Draw Folder recursive drawing
|
||||
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
|
||||
const float horizontalOffset = 0.0f;
|
||||
|
|
|
@ -489,7 +489,7 @@ namespace SHADE
|
|||
|
||||
//auto const& renderers = gfxSystem->GetDefaultViewport()->GetRenderers();
|
||||
auto renderGraph = gfxSystem->GetRenderGraph();
|
||||
auto renderPass = renderGraph->GetNode("ImGui Node")->GetRenderpass();
|
||||
auto renderPass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::IMGUI_PASS.data())->GetRenderpass();
|
||||
|
||||
if(ImGui_ImplVulkan_Init(&initInfo, renderPass->GetVkRenderpass()) == false)
|
||||
{
|
||||
|
@ -508,7 +508,7 @@ namespace SHADE
|
|||
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
|
||||
renderGraph->GetNode("ImGui Node")->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer> cmd, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::IMGUI_PASS.data())->GetSubpass("ImGui Draw")->AddExteriorDrawCalls([](Handle<SHVkCommandBuffer> cmd, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||
{
|
||||
cmd->BeginLabeledSegment("ImGui Draw");
|
||||
ImGui_ImplVulkan_RenderDrawData(ImGui::GetDrawData(), cmd->GetVkCommandBuffer());
|
||||
|
|
|
@ -175,6 +175,27 @@ namespace SHADE
|
|||
writeInfo.descImageInfos[i].sampler = sampler ? sampler->GetVkSampler() : nullptr;
|
||||
writeInfo.descImageInfos[i].imageLayout = layout;
|
||||
}
|
||||
|
||||
// Rest is not used, so it doesn't matter what's in them, we just want to pacify Vulkan
|
||||
for (uint32_t i = imageViewsAndSamplers.size(); i < writeInfo.descImageInfos.size(); ++i)
|
||||
{
|
||||
writeInfo.descImageInfos[i].sampler = std::get<Handle<SHVkSampler>>(imageViewsAndSamplers.back())->GetVkSampler();
|
||||
}
|
||||
}
|
||||
|
||||
void SHVkDescriptorSetGroup::ModifyWriteDescImage(uint32_t set, uint32_t binding, std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& imageViewAndSampler, uint32_t descIndex) noexcept
|
||||
{
|
||||
// Find the target writeDescSet
|
||||
BindingAndSetHash writeHash = binding;
|
||||
writeHash |= static_cast<uint64_t>(set) << 32;
|
||||
auto& writeInfo = updater.writeInfos[updater.writeHashMap.at(writeHash)];
|
||||
|
||||
// write sampler and image view
|
||||
auto& [view, sampler, layout] = imageViewAndSampler;
|
||||
writeInfo.descImageInfos[descIndex].imageView = view->GetImageView();
|
||||
writeInfo.descImageInfos[descIndex].sampler = sampler ? sampler->GetVkSampler() : nullptr;
|
||||
writeInfo.descImageInfos[descIndex].imageLayout = layout;
|
||||
|
||||
}
|
||||
|
||||
void SHVkDescriptorSetGroup::ModifyWriteDescBuffer(uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept
|
||||
|
@ -200,6 +221,28 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
void SHVkDescriptorSetGroup::UpdateDescriptorSetImage(uint32_t set, uint32_t binding, uint32_t descArrayIndex) noexcept
|
||||
{
|
||||
vk::WriteDescriptorSet writeDescSet{};
|
||||
|
||||
// Get binding + set hash
|
||||
BindingAndSetHash bsHash = SHVkUtil::GenBindingSetHash(set, binding);
|
||||
|
||||
// to index a write for a binding
|
||||
uint32_t writeInfoIndex = updater.writeHashMap[bsHash];
|
||||
|
||||
// Initialize info for write
|
||||
writeDescSet.descriptorType = layoutsUsed[set]->GetBindings()[binding].Type;
|
||||
writeDescSet.dstArrayElement = descArrayIndex;
|
||||
writeDescSet.dstSet = descSets[set];
|
||||
writeDescSet.dstBinding = binding;
|
||||
|
||||
writeDescSet.pImageInfo = updater.writeInfos[writeInfoIndex].descImageInfos.data() + descArrayIndex;
|
||||
writeDescSet.descriptorCount = 1u;
|
||||
|
||||
device->UpdateDescriptorSet(writeDescSet);
|
||||
}
|
||||
|
||||
void SHVkDescriptorSetGroup::UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept
|
||||
{
|
||||
vk::WriteDescriptorSet writeDescSet{};
|
||||
|
|
|
@ -63,10 +63,12 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
/* Public member functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
void UpdateDescriptorSetImage (uint32_t set, uint32_t binding, uint32_t descArrayIndex) noexcept;
|
||||
void UpdateDescriptorSetImages(uint32_t set, uint32_t binding) noexcept;
|
||||
void UpdateDescriptorSetBuffer(uint32_t set, uint32_t binding) noexcept;
|
||||
|
||||
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::span<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> const& imageViewsAndSamplers) noexcept;
|
||||
void ModifyWriteDescImage(uint32_t set, uint32_t binding, std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& imageViewAndSampler, uint32_t descIndex) noexcept;
|
||||
void ModifyWriteDescBuffer (uint32_t set, uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
|
||||
|
||||
|
||||
|
|
|
@ -183,33 +183,43 @@ namespace SHADE
|
|||
/*if (!extensionsSupported)
|
||||
SHUtil::ReportWarning("Some of the required extensions cannot be found on the physical device. ");*/
|
||||
|
||||
vk::PhysicalDeviceFeatures features{}; // ADD MORE FEATURES HERE IF NEEDED
|
||||
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature
|
||||
{
|
||||
.shaderSampledImageArrayNonUniformIndexing = VK_TRUE,
|
||||
.descriptorBindingPartiallyBound = VK_TRUE,
|
||||
.descriptorBindingVariableDescriptorCount = VK_TRUE,
|
||||
.runtimeDescriptorArray = VK_TRUE,
|
||||
};
|
||||
|
||||
vk::PhysicalDeviceRobustness2FeaturesEXT robustFeatures
|
||||
{
|
||||
.nullDescriptor = VK_TRUE,
|
||||
};
|
||||
|
||||
robustFeatures.pNext = &descIndexingFeature;
|
||||
|
||||
vk::PhysicalDeviceFeatures2 features{}; // ADD MORE FEATURES HERE IF NEEDED
|
||||
|
||||
// point and lines fill mode
|
||||
features.fillModeNonSolid = VK_TRUE;
|
||||
features.samplerAnisotropy = VK_TRUE;
|
||||
features.multiDrawIndirect = VK_TRUE;
|
||||
features.independentBlend = VK_TRUE;
|
||||
features.features.fillModeNonSolid = VK_TRUE;
|
||||
features.features.samplerAnisotropy = VK_TRUE;
|
||||
features.features.multiDrawIndirect = VK_TRUE;
|
||||
features.features.independentBlend = VK_TRUE;
|
||||
features.features.wideLines = VK_TRUE;
|
||||
|
||||
// for wide lines
|
||||
features.wideLines = true;
|
||||
|
||||
vk::PhysicalDeviceDescriptorIndexingFeatures descIndexingFeature{};
|
||||
descIndexingFeature.descriptorBindingVariableDescriptorCount = true;
|
||||
descIndexingFeature.shaderSampledImageArrayNonUniformIndexing = true;
|
||||
descIndexingFeature.runtimeDescriptorArray = true;
|
||||
features.pNext = &robustFeatures;
|
||||
|
||||
// Prepare to create the device
|
||||
vk::DeviceCreateInfo deviceCreateInfo
|
||||
{
|
||||
.pNext = &descIndexingFeature,
|
||||
.pNext = &features,
|
||||
.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size()),
|
||||
.pQueueCreateInfos = queueCreateInfos.data(),
|
||||
.enabledLayerCount = 0, // deprecated and ignored
|
||||
.ppEnabledLayerNames = nullptr, // deprecated and ignored
|
||||
.enabledExtensionCount = !extensionsSupported ? 0 : static_cast<uint32_t>(requiredExtensions.size()),
|
||||
.ppEnabledExtensionNames = !extensionsSupported ? nullptr : requiredExtensions.data(),
|
||||
.pEnabledFeatures = &features
|
||||
//.pEnabledFeatures = &features
|
||||
};
|
||||
|
||||
// Actually create the device
|
||||
|
|
|
@ -10,5 +10,8 @@ namespace SHADE
|
|||
{
|
||||
//! We need to get the light component and initialize the relevant variables.
|
||||
EntityID lightEntity;
|
||||
|
||||
//! Generate a renderer for the light component
|
||||
bool generateRenderer;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ namespace SHADE
|
|||
.maxAnisotropy = 1.0f,
|
||||
.minLod = params.minLod,
|
||||
.maxLod = params.maxLod,
|
||||
.borderColor = vk::BorderColor::eFloatOpaqueWhite
|
||||
};
|
||||
|
||||
// Create the sampler
|
||||
|
|
|
@ -551,7 +551,7 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
/* SHBatch - Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
||||
void SHBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline/* = true*/)
|
||||
{
|
||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||
{
|
||||
|
@ -566,7 +566,10 @@ namespace SHADE
|
|||
// Bind all required objects before drawing
|
||||
static std::array<uint32_t, 1> dynamicOffset{ 0 };
|
||||
cmdBuffer->BeginLabeledSegment("SHBatch for Pipeline #" + std::to_string(pipeline.GetId().Data.Index));
|
||||
|
||||
if (bindBatchPipeline)
|
||||
cmdBuffer->BindPipeline(pipeline);
|
||||
|
||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::TRANSFORM, transformDataBuffer[frameIndex], 0);
|
||||
cmdBuffer->BindVertexBuffer(SHGraphicsConstants::VertexBufferBindings::INTEGER_DATA, instancedIntegerBuffer[frameIndex], 0);
|
||||
if (matPropsDescSet[frameIndex])
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace SHADE
|
|||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void UpdateInstancedIntegerBuffer(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) ;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline = true);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
|
|
|
@ -107,12 +107,12 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
void SHSuperBatch::Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline /*= true*/) noexcept
|
||||
{
|
||||
// Build all batches
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.Draw(cmdBuffer, frameIndex);
|
||||
batch.Draw(cmdBuffer, frameIndex, bindBatchPipeline);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ namespace SHADE
|
|||
void Clear() noexcept;
|
||||
void UpdateBuffers(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
void Build(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, bool bindBatchPipeline = true) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
|
|
|
@ -13,6 +13,8 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> SHGraphicsPredefinedData::predefinedLayouts;
|
||||
SHVertexInputState SHGraphicsPredefinedData::defaultVertexInputState;
|
||||
SHVertexInputState SHGraphicsPredefinedData::shadowMapVertexInputState;
|
||||
|
||||
std::vector<SHGraphicsPredefinedData::PerSystem> SHGraphicsPredefinedData::perSystemData;
|
||||
|
||||
//SHGraphicsPredefinedData::PerSystem SHGraphicsPredefinedData::batchingSystemData;
|
||||
|
@ -150,12 +152,26 @@ namespace SHADE
|
|||
Handle<SHVkDescriptorSetLayout> fontDataDescSetLayout = logicalDevice->CreateDescriptorSetLayout({ fontBitmapBinding, fontMatrixBinding });
|
||||
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, fontDataDescSetLayout->GetVkHandle(), "[Descriptor Set Layout] Font Data");
|
||||
|
||||
// descriptor binding for storing shadow maps
|
||||
SHVkDescriptorSetLayout::Binding shadowMapBinding
|
||||
{
|
||||
.Type = vk::DescriptorType::eCombinedImageSampler,
|
||||
.Stage = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eFragment | vk::ShaderStageFlagBits::eCompute,
|
||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::IMAGE_AND_SAMPLERS_DATA,
|
||||
.DescriptorCount = 200, // we can have up to 200 textures for now
|
||||
.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount,
|
||||
};
|
||||
|
||||
// For global data (generic data and textures)
|
||||
Handle<SHVkDescriptorSetLayout> shadowMapDescLayout = logicalDevice->CreateDescriptorSetLayout({ shadowMapBinding });
|
||||
SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSetLayout, shadowMapDescLayout->GetVkHandle(), "[Descriptor Set Layout] Shadow Maps");
|
||||
|
||||
predefinedLayouts.push_back(staticGlobalLayout);
|
||||
predefinedLayouts.push_back(lightDataDescSetLayout);
|
||||
predefinedLayouts.push_back(cameraDataGlobalLayout);
|
||||
predefinedLayouts.push_back(materialDataPerInstanceLayout);
|
||||
predefinedLayouts.push_back(fontDataDescSetLayout);
|
||||
predefinedLayouts.push_back(shadowMapDescLayout);
|
||||
|
||||
perSystemData[SHUtilities::ConvertEnum(SystemType::BATCHING)].descSetLayouts = GetPredefinedDescSetLayouts
|
||||
(
|
||||
|
@ -179,7 +195,7 @@ namespace SHADE
|
|||
);
|
||||
}
|
||||
|
||||
void SHGraphicsPredefinedData::InitDefaultVertexInputState(void) noexcept
|
||||
void SHGraphicsPredefinedData::InitPredefinedVertexInputState(void) noexcept
|
||||
{
|
||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // positions at binding 0
|
||||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_2D) }); // UVs at binding 1
|
||||
|
@ -187,13 +203,16 @@ namespace SHADE
|
|||
defaultVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D) }); // Tangents at binding 3
|
||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }); // Transform at binding 4 - 7 (4 slots)
|
||||
defaultVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::UINT32_2D) }); // Instanced integer data at index 8
|
||||
|
||||
shadowMapVertexInputState.AddBinding(false, false, { SHVertexAttribute(SHAttribFormat::FLOAT_3D)});
|
||||
shadowMapVertexInputState.AddBinding(true, true, { SHVertexAttribute(SHAttribFormat::MAT_4D) }, 4, 4); // Transform at binding 4 - 7 (4 slots)
|
||||
}
|
||||
|
||||
void SHGraphicsPredefinedData::Init(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||
{
|
||||
perSystemData.resize(SHUtilities::ConvertEnum(SystemType::NUM_TYPES));
|
||||
InitDescSetLayouts(logicalDevice);
|
||||
InitDefaultVertexInputState();
|
||||
InitPredefinedVertexInputState();
|
||||
InitDescMappings();
|
||||
InitDummyPipelineLayouts (logicalDevice);
|
||||
}
|
||||
|
@ -217,6 +236,11 @@ namespace SHADE
|
|||
}
|
||||
|
||||
|
||||
SHVertexInputState const& SHGraphicsPredefinedData::GetShadowMapViState(void) noexcept
|
||||
{
|
||||
return shadowMapVertexInputState;
|
||||
}
|
||||
|
||||
SHGraphicsPredefinedData::PerSystem const& SHGraphicsPredefinedData::GetSystemData(SystemType systemType) noexcept
|
||||
{
|
||||
return perSystemData[static_cast<uint32_t>(systemType)];
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace SHADE
|
|||
CAMERA = 0x04,
|
||||
MATERIALS = 0x08,
|
||||
FONT = 0x10,
|
||||
SHADOW = 0x20,
|
||||
};
|
||||
|
||||
enum class SystemType
|
||||
|
@ -57,6 +58,9 @@ namespace SHADE
|
|||
//! Default vertex input state (used by everything).
|
||||
static SHVertexInputState defaultVertexInputState;
|
||||
|
||||
//! vertex input state for shadow mapping
|
||||
static SHVertexInputState shadowMapVertexInputState;
|
||||
|
||||
//! Predefined data for each type of system
|
||||
static std::vector<PerSystem> perSystemData;
|
||||
|
||||
|
@ -72,7 +76,7 @@ namespace SHADE
|
|||
static void InitDescMappings (void) noexcept;
|
||||
static void InitDummyPipelineLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
static void InitDescSetLayouts (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
static void InitDefaultVertexInputState (void) noexcept;
|
||||
static void InitPredefinedVertexInputState (void) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -90,6 +94,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
static std::vector<Handle<SHVkDescriptorSetLayout>> GetPredefinedDescSetLayouts (SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes types) noexcept;
|
||||
static SHVertexInputState const& GetDefaultViState (void) noexcept;
|
||||
static SHVertexInputState const& GetShadowMapViState (void) noexcept;
|
||||
static PerSystem const& GetSystemData (SystemType systemType) noexcept;
|
||||
static SHDescriptorMappings::MapType const& GetMappings (SystemType systemType) noexcept;
|
||||
//static PerSystem const& GetBatchingSystemData(void) noexcept;
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace SHADE
|
|||
CAMERA,
|
||||
MATERIALS,
|
||||
FONT,
|
||||
RENDER_GRAPH_RESOURCE,
|
||||
RENDER_GRAPH_NODE_COMPUTE_RESOURCE,
|
||||
RENDER_GRAPH_RESOURCE,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace SHADE
|
|||
// Register function for subpass
|
||||
//auto const& RENDERERS = gfxSystem->GetDefaultViewport()->GetRenderers();
|
||||
auto renderGraph = gfxSystem->GetRenderGraph();
|
||||
auto subPass = renderGraph->GetNode("Debug Draw")->GetSubpass("Debug Draw");
|
||||
auto subPass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data())->GetSubpass("Debug Draw");
|
||||
subPass->AddExteriorDrawCalls([this](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||
{
|
||||
// Set line width first
|
||||
|
@ -129,7 +129,7 @@ namespace SHADE
|
|||
}
|
||||
cmdBuffer->EndLabeledSegment();
|
||||
});
|
||||
auto subPassWithDepth = renderGraph->GetNode("Debug Draw with Depth")->GetSubpass("Debug Draw with Depth");
|
||||
auto subPassWithDepth = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data())->GetSubpass("Debug Draw with Depth");
|
||||
subPassWithDepth->AddExteriorDrawCalls([this](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||
{
|
||||
// Set line width first
|
||||
|
|
|
@ -31,68 +31,91 @@ namespace SHADE
|
|||
static constexpr uint32_t EDITOR = 0;
|
||||
};
|
||||
|
||||
//struct DescriptorSetIndex
|
||||
//{
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for static global values like generic data, and
|
||||
// texture samplers
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t STATIC_GLOBALS = 0;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for dynamic global values like lights.
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t DYNAMIC_GLOBALS = 1;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for high frequency changing global values like
|
||||
// camera matrices.
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t HIGH_FREQUENCY_GLOBALS = 2;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// DescriptorSet Index for per-instance/material changing values.
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t PER_INSTANCE = 3;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// 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;
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \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 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;
|
||||
struct RenderGraphEntityNames
|
||||
{
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
// /***************************************************************************/
|
||||
// /*!
|
||||
// \brief
|
||||
// To store font data.
|
||||
//
|
||||
// */
|
||||
// /***************************************************************************/
|
||||
// static constexpr uint32_t FONT_DATA = 4;
|
||||
//};
|
||||
\brief
|
||||
Name of G-Buffer render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view GBUFFER_PASS = "G-Buffer";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of shadow map render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view SHADOW_MAP_PASS = "Shadow Map Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of deferred composite render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view DEFERRED_COMPOSITE_PASS = "Deferred Comp Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of Debug Draw with Depth render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view DEBUG_DRAW_DEPTH_PASS = "Debug Draw with Depth Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of Debug Draw render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view DEBUG_DRAW = "Debug Draw Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of screen space pass render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view SCREEN_SPACE_PASS = "Screen Space Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of ImGui pass render graph node.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view IMGUI_PASS = "ImGui Pass";
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Name of deferred composite compute.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr std::string_view DEFERRED_COMPOSITE_COMPUTE = "Deferred Composite";
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct DescriptorSetBindings
|
||||
{
|
||||
|
@ -158,6 +181,16 @@ namespace SHADE
|
|||
/***************************************************************************/
|
||||
static constexpr uint32_t FONT_MATRIX_DATA = 1;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Descriptor set binding for shadow map images.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t SHADOW_MAP_IMAGE_SAMPLER_DATA = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct VertexBufferBindings
|
||||
|
|
|
@ -44,6 +44,9 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Graphics/MiddleEnd/TextRendering/SHFreetypeInstance.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderingSubSystem.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGlobalDescriptorSets.h"
|
||||
#include "Events/SHEvent.h"
|
||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||
#include "Input/SHInputManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -124,6 +127,13 @@ namespace SHADE
|
|||
|
||||
SHFreetypeInstance::Init();
|
||||
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/DeferredComposite_CS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAO_CS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/SSAOBlur_CS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/PureCopy_CS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_VS.glsl", false);
|
||||
SHAssetManager::CompileAsset("../../Assets/Shaders/TestCube_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);
|
||||
|
@ -137,6 +147,8 @@ namespace SHADE
|
|||
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);
|
||||
static constexpr AssetID SHADOW_MAP_VS = 44646107; shadowMapVS = SHResourceManager::LoadOrGet<SHVkShaderModule>(SHADOW_MAP_VS);
|
||||
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::InitRenderGraph(void) noexcept
|
||||
|
@ -169,6 +181,8 @@ namespace SHADE
|
|||
// 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));
|
||||
|
||||
shadowMapViewport = AddViewport(vk::Viewport(0.0f, 0.0f, static_cast<float>(SHLightingSubSystem::SHADOW_MAP_WIDTH), static_cast<float>(SHLightingSubSystem::SHADOW_MAP_HEIGHT), 0.0f, 1.0f));
|
||||
|
||||
std::vector<Handle<SHVkCommandPool>> renderContextCmdPools{ swapchain->GetNumImages() };
|
||||
for (uint32_t i = 0; i < renderContextCmdPools.size(); ++i)
|
||||
{
|
||||
|
@ -183,22 +197,24 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
// Initialize world render graph
|
||||
renderGraph->Init("World Render Graph", device, swapchain, &resourceManager, renderContextCmdPools);
|
||||
renderGraph->AddResource("Position", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Position", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Position World Space", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Normals", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
//worldRenderGraph->AddResource("Tangents", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
renderGraph->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);
|
||||
renderGraph->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);
|
||||
renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, windowDims.first, windowDims.second);
|
||||
renderGraph->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);
|
||||
renderGraph->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);
|
||||
renderGraph->AddResource("Present", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT }, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Albedo", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("Depth Buffer", { SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL }, true, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
renderGraph->AddResource("Entity ID", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Light Layer Indices", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
renderGraph->AddResource("Scene", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE, SH_RENDER_GRAPH_RESOURCE_FLAGS::SHARED }, true, windowDims.first, windowDims.second);
|
||||
renderGraph->AddResource("SSAO", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
renderGraph->AddResource("SSAO Blur", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT, SH_RENDER_GRAPH_RESOURCE_FLAGS::STORAGE }, true, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
renderGraph->AddResource("Present", { SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT }, true, windowDims.first, windowDims.second);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* MAIN NODE */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
auto gBufferNode = renderGraph->AddNode("G-Buffer",
|
||||
auto gBufferNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(),
|
||||
//auto gBufferNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphNodeNames::GBUFFER_PASS.data()
|
||||
{
|
||||
"Position",
|
||||
"Entity ID",
|
||||
|
@ -207,7 +223,8 @@ namespace SHADE
|
|||
"Albedo",
|
||||
"Depth Buffer",
|
||||
"SSAO",
|
||||
"SSAO Blur"
|
||||
"SSAO Blur",
|
||||
"Position World Space"
|
||||
},
|
||||
{}); // no predecessors
|
||||
|
||||
|
@ -220,6 +237,7 @@ namespace SHADE
|
|||
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
||||
gBufferSubpass->AddColorOutput("Normals");
|
||||
gBufferSubpass->AddColorOutput("Albedo");
|
||||
gBufferSubpass->AddColorOutput("Position World Space");
|
||||
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH_STENCIL);
|
||||
|
||||
|
||||
|
@ -254,53 +272,52 @@ namespace SHADE
|
|||
// Add another pass to blur SSAO
|
||||
Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute("SSAO Blur Step", ssaoBlurShader, { "SSAO", "SSAO Blur" });
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SHADOW MAP PASS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Shadow map pass will have no resources bound at first. Lighting system will add resources to the node.
|
||||
// It will initially also not have any subpasses since they will be added for each light that casts shadows.
|
||||
//auto shadowMapPass = renderGraph->AddNode("Shadow Map Pass", {}, {});
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEFERRED COMPOSITE NODE */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// This pass will facilitate both lighting and shadows in 1 single pass.
|
||||
auto deferredCompositeNode = renderGraph->AddNode("Deferred Comp Pass",
|
||||
auto deferredCompositeNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(),
|
||||
{
|
||||
"Position",
|
||||
"Light Layer Indices",
|
||||
"Normals",
|
||||
"Albedo",
|
||||
"Scene",
|
||||
"SSAO Blur"
|
||||
"SSAO Blur",
|
||||
"Position World Space"
|
||||
},
|
||||
{"G-Buffer"});
|
||||
{ SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS .data()});
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEFERRED COMPOSITE SUBPASS INIT */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
deferredCompositeNode->AddNodeCompute("Deferred Composite", deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" });
|
||||
auto deferredCompositeCompute = deferredCompositeNode->AddNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data(), deferredCompositeShader, {"Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Position World Space", "Scene"}, {}, SHLightingSubSystem::MAX_SHADOWS);
|
||||
deferredCompositeCompute->AddPreComputeFunction([=](Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex)
|
||||
{
|
||||
lightingSubSystem->PrepareShadowMapsForRead(cmdBuffer);
|
||||
});
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEBUG DRAW PASS INIT */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Set up Debug Draw Passes
|
||||
// - Depth Tested
|
||||
auto debugDrawNodeDepth = renderGraph->AddNode("Debug Draw with Depth", { "Scene", "Depth Buffer" }, {"G-Buffer", "Deferred Comp Pass"});
|
||||
auto debugDrawNodeDepth = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data(), {"Scene", "Depth Buffer"}, {SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data()});
|
||||
auto debugDrawDepthSubpass = debugDrawNodeDepth->AddSubpass("Debug Draw with Depth", worldViewport, worldRenderer);
|
||||
debugDrawDepthSubpass->AddColorOutput("Scene");
|
||||
debugDrawDepthSubpass->AddDepthOutput("Depth Buffer");
|
||||
// - No Depth Test
|
||||
auto debugDrawNode = renderGraph->AddNode("Debug Draw", { "Scene" }, { "Debug Draw with Depth" });
|
||||
auto debugDrawNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data(), {"Scene"}, {SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data()});
|
||||
auto debugDrawSubpass = debugDrawNode->AddSubpass("Debug Draw", worldViewport, worldRenderer);
|
||||
debugDrawSubpass->AddColorOutput("Scene");
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SCREEN SPACE PASS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
auto screenSpaceNode = renderGraph->AddNode("Screen Space Pass", { "Scene", "Entity ID" }, {"Deferred Comp Pass", "G-Buffer", "Debug Draw" });
|
||||
auto screenSpaceNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data(), {"Scene", "Entity ID"}, {SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data(), SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data()});
|
||||
auto uiSubpass = screenSpaceNode->AddSubpass("UI", worldViewport, screenRenderer);
|
||||
uiSubpass->AddColorOutput("Scene");
|
||||
uiSubpass->AddColorOutput("Entity ID");
|
||||
|
@ -315,16 +332,16 @@ namespace SHADE
|
|||
#ifdef SHEDITOR
|
||||
{
|
||||
// Dummy Node to transition scene render graph resource
|
||||
auto dummyNode = renderGraph->AddNode("Dummy Pass", { "Scene" }, { "Screen Space Pass" });
|
||||
auto dummyNode = renderGraph->AddNode("Dummy Pass", { "Scene" }, { SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS .data()});
|
||||
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass", {}, {});
|
||||
dummySubpass->AddInput("Scene");
|
||||
|
||||
auto imGuiNode = renderGraph->AddNode("ImGui Node", { "Present" }, {});
|
||||
auto imGuiNode = renderGraph->AddNode(SHGraphicsConstants::RenderGraphEntityNames::IMGUI_PASS.data(), {"Present"}, {});
|
||||
auto imGuiSubpass = imGuiNode->AddSubpass("ImGui Draw", {}, {});
|
||||
imGuiSubpass->AddColorOutput("Present");
|
||||
}
|
||||
#else
|
||||
renderGraph->AddRenderToSwapchainNode("Scene", "Present", { "Screen Space Pass" }, { renderToSwapchainVS, renderToSwapchainFS });
|
||||
renderGraph->AddRenderToSwapchainNode("Scene", "Present", { SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS .data()}, {renderToSwapchainVS, renderToSwapchainFS});
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -393,12 +410,16 @@ namespace SHADE
|
|||
postOffscreenRenderSubSystem->Init(device, renderGraph->GetRenderGraphResource("Scene"), descPool);
|
||||
|
||||
lightingSubSystem = resourceManager.Create<SHLightingSubSystem>();
|
||||
lightingSubSystem->Init(device, descPool);
|
||||
lightingSubSystem->Init(device, descPool, &resourceManager, samplerCache.GetSampler (device, SHVkSamplerParams
|
||||
{
|
||||
.addressMode = vk::SamplerAddressMode::eClampToBorder,
|
||||
})
|
||||
);
|
||||
|
||||
textRenderingSubSystem = resourceManager.Create<SHTextRenderingSubSystem>();
|
||||
|
||||
// initialize the text renderer
|
||||
auto uiNode = renderGraph->GetNode("Screen Space Pass");
|
||||
auto uiNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SCREEN_SPACE_PASS.data());
|
||||
textRenderingSubSystem->Init(device, uiNode->GetRenderpass(), uiNode->GetSubpass("UI"), descPool, textVS, textFS);
|
||||
|
||||
SHGlobalDescriptorSets::SetLightingSubSystem(lightingSubSystem);
|
||||
|
@ -426,7 +447,7 @@ namespace SHADE
|
|||
defaultMaterial = AddMaterial
|
||||
(
|
||||
defaultVertShader, defaultFragShader,
|
||||
renderGraph->GetNode("G-Buffer")->GetSubpass("G-Buffer Write")
|
||||
renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass("G-Buffer Write")
|
||||
);
|
||||
defaultMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex);
|
||||
}
|
||||
|
@ -451,6 +472,7 @@ namespace SHADE
|
|||
InitMiddleEnd();
|
||||
InitSubsystems();
|
||||
InitBuiltInResources();
|
||||
InitEvents();
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::Exit(void)
|
||||
|
@ -546,6 +568,15 @@ namespace SHADE
|
|||
#endif
|
||||
}
|
||||
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::B))
|
||||
{
|
||||
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||
for (auto& comp : lightComps)
|
||||
{
|
||||
comp.SetEnableShadow(true);
|
||||
}
|
||||
}
|
||||
|
||||
renderGraph->Begin(frameIndex);
|
||||
auto cmdBuffer = renderGraph->GetCommandBuffer(frameIndex);
|
||||
|
||||
|
@ -726,16 +757,61 @@ namespace SHADE
|
|||
renderers.erase(iter);
|
||||
}
|
||||
|
||||
SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr event) noexcept
|
||||
SHEventHandle SHGraphicsSystem::ReceiveLightEnableShadowEvent(SHEventPtr eventPtr) noexcept
|
||||
{
|
||||
// we need to wait for the device to finish using the graph first
|
||||
device->WaitIdle();
|
||||
|
||||
auto const& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHLightEnableShadowEvent>*>(eventPtr.get())->data;
|
||||
auto* lightComp = SHComponentManager::GetComponent<SHLightComponent>(EVENT_DATA->lightEntity);
|
||||
std::string resourceName = "ShadowMap " + std::to_string(EVENT_DATA->lightEntity);
|
||||
Handle<SHSubpass> companionSubpass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data())->GetSubpass("G-Buffer Write");
|
||||
|
||||
if (EVENT_DATA->generateRenderer)
|
||||
{
|
||||
// Create new renderer for the light component and give it to the light component
|
||||
Handle<SHRenderer> newRenderer = resourceManager.Create<SHRenderer>(device, swapchain->GetNumImages(), descPool, SHRenderer::PROJECTION_TYPE::ORTHOGRAPHIC);
|
||||
lightComp->SetRenderer (newRenderer);
|
||||
|
||||
// assign shadow map index to light component
|
||||
lightComp->SetShadowMapIndex (lightingSubSystem->GetNumShadowMaps());
|
||||
}
|
||||
|
||||
// Add the shadow map resource to the graph
|
||||
renderGraph->AddResource(resourceName, {SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH, SH_RENDER_GRAPH_RESOURCE_FLAGS::INPUT}, false, SHLightingSubSystem::SHADOW_MAP_WIDTH, SHLightingSubSystem::SHADOW_MAP_HEIGHT, vk::Format::eD32Sfloat);
|
||||
|
||||
// link resource to node. This means linking the resource and regenerating the node's renderpass and framebuffer.
|
||||
auto shadowMapNode = renderGraph->AddNodeAfter(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data() + resourceName, {resourceName.c_str()}, SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data());
|
||||
|
||||
// Add a subpass to render to that shadow map
|
||||
auto newSubpass = shadowMapNode->RuntimeAddSubpass(resourceName + " Subpass", shadowMapViewport, lightComp->GetRenderer());
|
||||
newSubpass->AddDepthOutput(resourceName, SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH);
|
||||
|
||||
//renderGraph->GetNode ();
|
||||
return event->handle;
|
||||
// regenerate the node
|
||||
shadowMapNode->RuntimeStandaloneRegenerate();
|
||||
|
||||
// Create pipeline from new renderpass and subpass if it's not created yet
|
||||
if (!shadowMapPipeline)
|
||||
{
|
||||
SHPipelineLibrary tempLibrary{};
|
||||
Handle<SHRenderGraphNode> rgNode = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::SHADOW_MAP_PASS.data());
|
||||
|
||||
SHRasterizationState rasterState{};
|
||||
rasterState.cull_mode = vk::CullModeFlagBits::eBack;
|
||||
|
||||
tempLibrary.Init(device);
|
||||
tempLibrary.CreateGraphicsPipelines({ shadowMapVS, {} }, shadowMapNode->GetRenderpass(), newSubpass, SHGraphicsPredefinedData::GetShadowMapViState(), rasterState);
|
||||
shadowMapPipeline = tempLibrary.GetGraphicsPipeline({ shadowMapVS, {} });
|
||||
}
|
||||
newSubpass->SetCompanionSubpass(companionSubpass, shadowMapPipeline); // set companion subpass and pipeline
|
||||
|
||||
// add the shadow map to the lighting system
|
||||
uint32_t const NEW_SHADOW_MAP_INDEX = lightingSubSystem->AddShadowMap(renderGraph->GetRenderGraphResource(resourceName), EVENT_DATA->lightEntity);
|
||||
|
||||
auto nodeCompute = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data());
|
||||
nodeCompute->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, lightingSubSystem->GetViewSamplerLayout(NEW_SHADOW_MAP_INDEX), NEW_SHADOW_MAP_INDEX);
|
||||
|
||||
return eventPtr->handle;
|
||||
}
|
||||
|
||||
Handle<SHMaterial> SHGraphicsSystem::AddMaterial(Handle<SHVkShaderModule> vertShader, Handle<SHVkShaderModule> fragShader, Handle<SHSubpass> subpass)
|
||||
|
@ -1047,6 +1123,7 @@ namespace SHADE
|
|||
|
||||
mousePickSubSystem->HandleResize();
|
||||
postOffscreenRenderSubSystem->HandleResize();
|
||||
//lightingSubSystem->HandleResize(renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_PASS.data())->GetNodeCompute(SHGraphicsConstants::RenderGraphEntityNames::DEFERRED_COMPOSITE_COMPUTE.data()));
|
||||
|
||||
worldViewport->SetWidth(static_cast<float>(resizeWidth));
|
||||
worldViewport->SetHeight(static_cast<float>(resizeHeight));
|
||||
|
@ -1079,7 +1156,7 @@ namespace SHADE
|
|||
|
||||
Handle<SHRenderGraphNode> SHGraphicsSystem::GetPrimaryRenderpass() const noexcept
|
||||
{
|
||||
return renderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data());
|
||||
return renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::GBUFFER_PASS.data());
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHGraphicsSystem::GetDebugDrawPipeline(DebugDrawPipelineType type) const noexcept
|
||||
|
|
|
@ -178,7 +178,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
/* Light functions */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr event) noexcept;
|
||||
SHEventHandle ReceiveLightEnableShadowEvent (SHEventPtr eventPtr) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Material Functions */
|
||||
|
@ -406,10 +406,6 @@ namespace SHADE
|
|||
SHWindow* GetWindow() noexcept { return window; }
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Constants */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static constexpr std::string_view G_BUFFER_RENDER_GRAPH_NODE_NAME = "G-Buffer";
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
|
@ -446,6 +442,7 @@ namespace SHADE
|
|||
#endif
|
||||
|
||||
Handle<SHViewport> worldViewport; // Whole screen
|
||||
Handle<SHViewport> shadowMapViewport;
|
||||
std::vector<Handle<SHViewport>> viewports; // Additional viewports
|
||||
|
||||
// Renderers
|
||||
|
@ -469,6 +466,7 @@ namespace SHADE
|
|||
Handle<SHVkShaderModule> textFS;
|
||||
Handle<SHVkShaderModule> renderToSwapchainVS;
|
||||
Handle<SHVkShaderModule> renderToSwapchainFS;
|
||||
Handle<SHVkShaderModule> shadowMapVS;
|
||||
|
||||
// Fonts
|
||||
Handle<SHFont> testFont;
|
||||
|
@ -483,6 +481,7 @@ namespace SHADE
|
|||
Handle<SHVkPipeline> debugDrawWireMeshDepthPipeline;
|
||||
Handle<SHVkPipeline> debugDrawFilledPipeline;
|
||||
Handle<SHVkPipeline> debugDrawFilledDepthPipeline;
|
||||
Handle<SHVkPipeline> shadowMapPipeline; // initialized only when a shadow map is needed
|
||||
|
||||
// Built-In Textures
|
||||
Handle<SHTexture> defaultTexture;
|
||||
|
|
|
@ -122,4 +122,9 @@ namespace SHADE
|
|||
return cameraDirector;
|
||||
}
|
||||
|
||||
SHShaderCameraData SHRenderer::GetCPUCameraData(void) const noexcept
|
||||
{
|
||||
return cpuCameraData;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,9 +18,9 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// Project Includes
|
||||
#include "SHCamera.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraph.h"
|
||||
#include "Math/SHMath.h"
|
||||
#include <vector>
|
||||
#include "Graphics/Pipeline/SHPipelineType.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -93,6 +93,7 @@ namespace SHADE
|
|||
/* Setters and Getters */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHCameraDirector> GetCameraDirector (void) const noexcept;
|
||||
SHShaderCameraData GetCPUCameraData (void) const noexcept;
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "SHLightComponent.h"
|
||||
#include "Graphics/Events/SHGraphicsEvents.h"
|
||||
#include "Events/SHEventManager.hpp"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -14,6 +15,7 @@ namespace SHADE
|
|||
//indexInBuffer = std::numeric_limits<uint32_t>::max();
|
||||
isActive = true;
|
||||
//Unbind();
|
||||
renderer = {};
|
||||
}
|
||||
|
||||
|
||||
|
@ -116,11 +118,22 @@ namespace SHADE
|
|||
// Create new event and broadcast it
|
||||
SHLightEnableShadowEvent newEvent;
|
||||
newEvent.lightEntity = GetEID();
|
||||
newEvent.generateRenderer = static_cast<bool>(!renderer);
|
||||
|
||||
SHEventManager::BroadcastEvent<SHLightEnableShadowEvent>(newEvent, SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT);
|
||||
}
|
||||
}
|
||||
|
||||
void SHLightComponent::SetRenderer(Handle<SHRenderer> newRenderer) noexcept
|
||||
{
|
||||
renderer = newRenderer;
|
||||
}
|
||||
|
||||
void SHLightComponent::SetShadowMapIndex(uint32_t index) noexcept
|
||||
{
|
||||
lightData.shadowMapIndex = index;
|
||||
}
|
||||
|
||||
SHLightData const& SHLightComponent::GetLightData(void) const noexcept
|
||||
{
|
||||
return lightData;
|
||||
|
@ -172,6 +185,11 @@ namespace SHADE
|
|||
return lightData.strength;
|
||||
}
|
||||
|
||||
Handle<SHRenderer> SHLightComponent::GetRenderer(void) const noexcept
|
||||
{
|
||||
return renderer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RTTR_REGISTRATION
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
#include <rttr/registration>
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "SHLightData.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHRenderer;
|
||||
|
||||
class SH_API SHLightComponent final : public SHComponent
|
||||
{
|
||||
|
@ -14,6 +16,9 @@ namespace SHADE
|
|||
//! GPU depends on the type of the light.
|
||||
SHLightData lightData;
|
||||
|
||||
//! Renderer to calculate light world to projection matrix
|
||||
Handle<SHRenderer> renderer;
|
||||
|
||||
//! Since the lighting system is gonna be self contained and light weight, we store this
|
||||
//! so that we only write this to the CPU buffer when this light component change, we don't
|
||||
//! rewrite everything. However we still write to the GPU buffer when everything changes.
|
||||
|
@ -49,6 +54,8 @@ namespace SHADE
|
|||
//void SetBound (uint32_t inIndexInBuffer) noexcept;
|
||||
void SetStrength (float value) noexcept; // serialized
|
||||
void SetEnableShadow (bool flag) noexcept;
|
||||
void SetRenderer (Handle<SHRenderer> newRenderer) noexcept;
|
||||
void SetShadowMapIndex (uint32_t index) noexcept;
|
||||
|
||||
|
||||
SHLightData const& GetLightData (void) const noexcept;
|
||||
|
@ -61,6 +68,7 @@ namespace SHADE
|
|||
//bool GetBound (void) const noexcept;
|
||||
//uint32_t GetIndexInBuffer (void) const noexcept;
|
||||
float GetStrength (void) const noexcept;
|
||||
Handle<SHRenderer> GetRenderer (void) const noexcept;
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,6 +10,13 @@
|
|||
#include "SHLightComponent.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Graphics/Images/SHVkImageView.h"
|
||||
#include "Graphics/MiddleEnd/Textures/SHVkSamplerCache.h"
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
#include "Graphics/Events/SHGraphicsEvents.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderer.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -50,6 +57,19 @@ namespace SHADE
|
|||
//lightPtr->direction = lightData.direction;
|
||||
lightPtr->diffuseColor = lightData.color;
|
||||
lightPtr->active = lightComp->isActive;
|
||||
|
||||
// write view projection matrix if renderer is available
|
||||
auto lightRenderer = lightComp->GetRenderer();
|
||||
if (lightRenderer)
|
||||
{
|
||||
lightPtr->pvMatrix = lightRenderer->GetCPUCameraData().viewProjectionMatrix;
|
||||
|
||||
// Boolean to cast shadows in first 8 bits (1 byte)
|
||||
lightPtr->shadowData = lightData.castShadows;
|
||||
|
||||
// Next 24 bits for shadow map index
|
||||
lightPtr->shadowData |= (lightData.shadowMapIndex << 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SH_LIGHT_TYPE::POINT:
|
||||
|
@ -365,6 +385,32 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHLightingSubSystem::UpdateShadowMapDesc(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SHMatrix SHLightingSubSystem::GetViewMatrix(SHLightComponent* lightComp) noexcept
|
||||
{
|
||||
switch (lightComp->GetLightData().type)
|
||||
{
|
||||
case SH_LIGHT_TYPE::DIRECTIONAL:
|
||||
return SHMatrix::Transpose(SHMatrix::LookAtLH(lightComp->GetLightData().position, SHVec3::Normalise (lightComp->GetLightData().direction), SHVec3(0.0f, -1.0f, 0.0f)));
|
||||
//return SHMatrix::Transpose(SHMatrix::LookAtLH(/*lightComp->GetLightData().position*/SHVec3(1.27862f, 4.78952f, 4.12811f), SHVec3(-0.280564f, -0.66262f, -0.69422f), SHVec3(0.0f, -1.0f, 0.0f)));
|
||||
case SH_LIGHT_TYPE::POINT:
|
||||
return {};
|
||||
case SH_LIGHT_TYPE::SPOT:
|
||||
return {};
|
||||
case SH_LIGHT_TYPE::AMBIENT:
|
||||
return {};
|
||||
case SH_LIGHT_TYPE::NUM_TYPES:
|
||||
return {};
|
||||
default:
|
||||
return {};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -375,13 +421,15 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept
|
||||
void SHLightingSubSystem::Init(Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, SHResourceHub* rh, Handle<SHVkSampler> inShadowMapSampler) noexcept
|
||||
{
|
||||
SHComponentManager::CreateComponentSparseSet<SHLightComponent>();
|
||||
|
||||
logicalDevice = device;
|
||||
resourceHub = rh;
|
||||
uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ConvertEnum(SH_LIGHT_TYPE::NUM_TYPES);
|
||||
|
||||
#pragma region LIGHTING
|
||||
std::vector<uint32_t> variableSizes{ NUM_LIGHT_TYPES };
|
||||
std::fill (variableSizes.begin(), variableSizes.end(), 1);
|
||||
|
||||
|
@ -418,7 +466,22 @@ namespace SHADE
|
|||
dynamicOffsets[i].resize(NUM_LIGHT_TYPES + 1); // +1 for the count
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region SHADOWS
|
||||
//std::vector<uint32_t> shadowDescVariableSizes{ MAX_SHADOWS };
|
||||
//shadowMapDescriptorSet = descPool->Allocate({SHGraphicsPredefinedData::GetPredefinedDescSetLayouts(SHGraphicsPredefinedData::PredefinedDescSetLayoutTypes::SHADOW)}, shadowDescVariableSizes);
|
||||
|
||||
//#ifdef _DEBUG
|
||||
// const auto& SHADOW_MAP_DESC_SETS = shadowMapDescriptorSet->GetVkHandle();
|
||||
// for (int i = 0; i < static_cast<int>(SHADOW_MAP_DESC_SETS.size()); ++i)
|
||||
// SET_VK_OBJ_NAME(logicalDevice, vk::ObjectType::eDescriptorSet, SHADOW_MAP_DESC_SETS[i], "[Descriptor Set] Shadow Map Data Frame #" + std::to_string(i));
|
||||
//#endif
|
||||
|
||||
shadowMapSampler = inShadowMapSampler;
|
||||
shadowMaps.clear();
|
||||
//numLightComponents = 0;
|
||||
#pragma endregion
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -452,6 +515,12 @@ namespace SHADE
|
|||
|
||||
for (auto& light : lightComps)
|
||||
{
|
||||
if (auto renderer = light.GetRenderer())
|
||||
{
|
||||
//SHMatrix orthoMatrix = SHMatrix::OrthographicRH()
|
||||
renderer->UpdateDataManual(frameIndex, GetViewMatrix(&light), SHMatrix::OrthographicLH(10.0f, 10.0f, 1.0f, 50.0f));
|
||||
}
|
||||
|
||||
auto enumValue = SHUtilities::ConvertEnum(light.GetLightData().type);
|
||||
|
||||
// First we want to make sure the light is already bound to the system. if it
|
||||
|
@ -503,7 +572,6 @@ namespace SHADE
|
|||
// so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing.
|
||||
ComputeDynamicOffsets();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -526,9 +594,101 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
uint32_t SHLightingSubSystem::AddShadowMap(Handle<SHRenderGraphResource> newShadowMap, EntityID lightEntity) noexcept
|
||||
{
|
||||
// Add to container of shadow maps
|
||||
shadowMapIndexing.emplace(lightEntity, static_cast<uint32_t> (shadowMaps.size()));
|
||||
shadowMaps.emplace_back(newShadowMap);
|
||||
|
||||
// Just use the image view stored in the resource
|
||||
Handle<SHVkImageView> const NEW_IMAGE_VIEW = newShadowMap->GetImageView();
|
||||
|
||||
// Prepare to write to descriptor
|
||||
shadowMapImageSamplers.emplace_back(NEW_IMAGE_VIEW, shadowMapSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
|
||||
// Update descriptor set
|
||||
//static constexpr uint32_t SHADOW_MAP_DESC_SET_INDEX = 0;
|
||||
//uint32_t const SHADOW_MAP_DESC_ARRAY_INDEX = static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
|
||||
//shadowMapDescriptorSet->ModifyWriteDescImage
|
||||
//(
|
||||
// SHADOW_MAP_DESC_SET_INDEX,
|
||||
// SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA,
|
||||
// shadowMapImageSamplers[SHADOW_MAP_DESC_ARRAY_INDEX],
|
||||
// SHADOW_MAP_DESC_ARRAY_INDEX
|
||||
//);
|
||||
|
||||
//// TODO: Definitely can be optimized by writing a function that modifies a specific descriptor in the array
|
||||
//shadowMapDescriptorSet->UpdateDescriptorSetImages
|
||||
//(
|
||||
// SHADOW_MAP_DESC_SET_INDEX,
|
||||
// SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA
|
||||
//);
|
||||
|
||||
// add to barriers
|
||||
shadowMapMemoryBarriers.push_back (vk::ImageMemoryBarrier
|
||||
{
|
||||
.srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead,
|
||||
.oldLayout = vk::ImageLayout::eDepthAttachmentOptimal,
|
||||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.image = newShadowMap->GetImage()->GetVkImage(),
|
||||
.subresourceRange = vk::ImageSubresourceRange
|
||||
{
|
||||
.aspectMask = vk::ImageAspectFlagBits::eDepth,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
}
|
||||
});
|
||||
|
||||
// return new index of shadow map
|
||||
return static_cast<uint32_t>(shadowMapImageSamplers.size()) - 1u;
|
||||
}
|
||||
|
||||
void SHLightingSubSystem::PrepareShadowMapsForRead(Handle<SHVkCommandBuffer> cmdBuffer) noexcept
|
||||
{
|
||||
// Issue barrier to transition shadow maps for reading in compute shader
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eEarlyFragmentTests | vk::PipelineStageFlagBits::eLateFragmentTests, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, shadowMapMemoryBarriers);
|
||||
}
|
||||
|
||||
//void SHLightingSubSystem::HandleResize(Handle<SHRenderGraphNodeCompute> compute) noexcept
|
||||
//{
|
||||
// uint32_t const NUM_SHADOW_MAPS = static_cast<uint32_t>(shadowMaps.size());
|
||||
// for (uint32_t i = 0; i < NUM_SHADOW_MAPS; ++i)
|
||||
// {
|
||||
// // Just use the image view stored in the resource
|
||||
// Handle<SHVkImageView> const NEW_IMAGE_VIEW = shadowMaps[i]->GetImageView();
|
||||
|
||||
// // set new image view
|
||||
// std::get<Handle<SHVkImageView>>(shadowMapImageSamplers[i]) = NEW_IMAGE_VIEW;
|
||||
|
||||
// // Set image for barrier
|
||||
// shadowMapMemoryBarriers[i].image = shadowMaps[i]->GetImage()->GetVkImage();
|
||||
// }
|
||||
|
||||
// if (NUM_SHADOW_MAPS > 0)
|
||||
// {
|
||||
// // modify descriptors in render graph node compute
|
||||
// compute->ModifyWriteDescImageComputeResource (SHGraphicsConstants::DescriptorSetBindings::SHADOW_MAP_IMAGE_SAMPLER_DATA, shadowMapImageSamplers);
|
||||
// }
|
||||
//}
|
||||
|
||||
Handle<SHVkDescriptorSetGroup> SHLightingSubSystem::GetLightDataDescriptorSet(void) const noexcept
|
||||
{
|
||||
return lightingDataDescSet;
|
||||
}
|
||||
|
||||
std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& SHLightingSubSystem::GetViewSamplerLayout(uint32_t index) const noexcept
|
||||
{
|
||||
return shadowMapImageSamplers[index];
|
||||
}
|
||||
|
||||
uint32_t SHLightingSubSystem::GetNumShadowMaps(void) const noexcept
|
||||
{
|
||||
return static_cast<uint32_t>(shadowMaps.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,9 +3,13 @@
|
|||
#include "Resource/SHHandle.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "SHLightData.h"
|
||||
#include <array>
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsConstants.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraphResource.h"
|
||||
#include "ECS_Base/SHECSMacros.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -16,6 +20,10 @@ namespace SHADE
|
|||
class SHVkBuffer;
|
||||
class SHLightComponent;
|
||||
class SHVkCommandBuffer;
|
||||
class SHSamplerCache;
|
||||
class SHVkImageView;
|
||||
class SHVkSampler;
|
||||
class SHRenderGraphNodeCompute;
|
||||
|
||||
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
|
||||
struct SHDirectionalLightData
|
||||
|
@ -34,6 +42,12 @@ namespace SHADE
|
|||
//! Diffuse color emitted by the light
|
||||
alignas (16) SHVec4 diffuseColor;
|
||||
|
||||
//! Matrix for world to projection from light's perspective
|
||||
SHMatrix pvMatrix;
|
||||
|
||||
//! Represents boolean for casting shadows in first byte and shadow map index in the other 3.
|
||||
uint32_t shadowData;
|
||||
|
||||
};
|
||||
|
||||
// Represents how the data will be interpreted in GPU. we want to copy to a container of these before passing to GPU.
|
||||
|
@ -52,19 +66,22 @@ namespace SHADE
|
|||
//! when a fragment is being evaluated, the shader will use the fragment's
|
||||
//! layer value to AND with the light's. If result is 1, do lighting calculations.
|
||||
uint32_t cullingMask;
|
||||
|
||||
|
||||
};
|
||||
|
||||
class SH_API SHLightingSubSystem
|
||||
{
|
||||
public:
|
||||
using DynamicOffsetArray = std::array<std::vector<uint32_t>, static_cast<uint32_t>(SHGraphicsConstants::NUM_FRAME_BUFFERS)>;
|
||||
|
||||
static constexpr uint32_t MAX_SHADOWS = 200;
|
||||
static constexpr uint32_t SHADOW_MAP_WIDTH = 1024;
|
||||
static constexpr uint32_t SHADOW_MAP_HEIGHT = 1024;
|
||||
|
||||
private:
|
||||
class PerTypeData
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* STATIC MEMBER VARIABLES */
|
||||
|
@ -123,6 +140,10 @@ namespace SHADE
|
|||
};
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* STATIC MEMBER VARIABLES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
|
||||
//! logical device used for creation
|
||||
Handle<SHVkLogicalDevice> logicalDevice;
|
||||
|
@ -150,24 +171,59 @@ namespace SHADE
|
|||
//! don't do anything.
|
||||
//uint32_t numLightComponents;
|
||||
|
||||
//! Handle to sampler that all shadow map descriptors will use
|
||||
Handle<SHVkSampler> shadowMapSampler;
|
||||
|
||||
//! For indexing shadow maps
|
||||
std::unordered_map<EntityID, uint32_t> shadowMapIndexing;
|
||||
|
||||
//! Shadow maps for every light that casts a shadow Order here doesn't matter. We just want to store it
|
||||
std::vector<Handle<SHRenderGraphResource>> shadowMaps;
|
||||
|
||||
//! Descriptor sets required to be given to the compute shader for shadow calculation. This will be a descriptor array.
|
||||
//! It will also be preallocated.
|
||||
//Handle<SHVkDescriptorSetGroup> shadowMapDescriptorSet;
|
||||
|
||||
//! Combined image samplers for the texture descriptors
|
||||
std::vector<std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout>> shadowMapImageSamplers;
|
||||
|
||||
//! Barriers required to transition the resources from whatever layout they are in (probably from VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
|
||||
//! to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
|
||||
std::vector<vk::ImageMemoryBarrier> shadowMapMemoryBarriers;
|
||||
|
||||
//! Resource hub from Graphics System
|
||||
SHResourceHub* resourceHub;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void UpdateDescSet (uint32_t binding) noexcept;
|
||||
void ComputeDynamicOffsets (void) noexcept;
|
||||
void ResetNumLights (void) noexcept;
|
||||
void UpdateShadowMapDesc (void) noexcept;
|
||||
SHMatrix GetViewMatrix (SHLightComponent* lightComp) noexcept;
|
||||
|
||||
public:
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool, SHResourceHub* rh, Handle<SHVkSampler> inShadowMapSampler) noexcept;
|
||||
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
|
||||
void Exit (void) noexcept;
|
||||
|
||||
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) noexcept;
|
||||
uint32_t AddShadowMap (Handle<SHRenderGraphResource> newShadowMap, EntityID lightEntity) noexcept;
|
||||
void PrepareShadowMapsForRead (Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||
//void HandleResize (Handle<SHRenderGraphNodeCompute> compute) noexcept;
|
||||
//void RemoveShadowMap (uint32_t index) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHVkDescriptorSetGroup> GetLightDataDescriptorSet (void) const noexcept;
|
||||
std::tuple<Handle<SHVkImageView>, Handle<SHVkSampler>, vk::ImageLayout> const& GetViewSamplerLayout (uint32_t index) const noexcept;
|
||||
uint32_t GetNumShadowMaps (void) const noexcept;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHPipelineLibrary.h"
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h"
|
||||
#include "Graphics/RenderGraph/SHSubpass.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass) noexcept
|
||||
Handle<SHVkPipeline> SHPipelineLibrary::CreateGraphicsPipelines(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHVkRenderpass> renderpass, Handle<SHSubpass> subpass, SHVertexInputState const& viState/* = SHGraphicsPredefinedData::GetDefaultViState()*/, SHRasterizationState const& rasterState) noexcept
|
||||
{
|
||||
std::vector<Handle<SHVkShaderModule>> modules{};
|
||||
if (vsFsPair.first)
|
||||
modules.push_back(vsFsPair.first);
|
||||
if (vsFsPair.second)
|
||||
modules.push_back(vsFsPair.second);
|
||||
|
||||
SHPipelineLayoutParams params
|
||||
{
|
||||
.shaderModules = {vsFsPair.first, vsFsPair.second},
|
||||
.shaderModules = std::move(modules),
|
||||
.predefinedDescSetLayouts = SHGraphicsPredefinedData::GetSystemData(SHGraphicsPredefinedData::SystemType::BATCHING).descSetLayouts
|
||||
};
|
||||
|
||||
|
@ -21,7 +26,7 @@ namespace SHADE
|
|||
|
||||
// Create the pipeline and configure the default vertex input state
|
||||
auto newPipeline = logicalDevice->CreateGraphicsPipeline(pipelineLayout, nullptr, renderpass, subpass);
|
||||
newPipeline->GetPipelineState().SetVertexInputState(SHGraphicsPredefinedData::GetDefaultViState());
|
||||
newPipeline->GetPipelineState().SetVertexInputState(viState);
|
||||
|
||||
SHColorBlendState colorBlendState{};
|
||||
colorBlendState.logic_op_enable = VK_FALSE;
|
||||
|
@ -30,6 +35,7 @@ namespace SHADE
|
|||
auto const& subpassColorReferences = subpass->GetColorAttachmentReferences();
|
||||
colorBlendState.attachments.reserve(subpassColorReferences.size());
|
||||
|
||||
|
||||
for (auto& att : subpassColorReferences)
|
||||
{
|
||||
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
|
||||
|
@ -48,6 +54,8 @@ namespace SHADE
|
|||
|
||||
newPipeline->GetPipelineState().SetColorBlenState(colorBlendState);
|
||||
|
||||
newPipeline->GetPipelineState().SetRasterizationState(rasterState);
|
||||
|
||||
// Actually construct the pipeline
|
||||
newPipeline->ConstructPipeline();
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <unordered_map>
|
||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||
#include "Graphics/Pipeline/SHVkPipeline.h"
|
||||
#include "Graphics/MiddleEnd/GlobalData/SHGraphicsPredefinedData.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -32,7 +33,9 @@ namespace SHADE
|
|||
Handle<SHVkPipeline> CreateGraphicsPipelines (
|
||||
std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair,
|
||||
Handle<SHVkRenderpass> renderpass,
|
||||
Handle<SHSubpass> subpass
|
||||
Handle<SHSubpass> subpass,
|
||||
SHVertexInputState const& viState = SHGraphicsPredefinedData::GetDefaultViState(),
|
||||
SHRasterizationState const& rasterState = SHRasterizationState{}
|
||||
) noexcept;
|
||||
Handle<SHVkPipeline> GetGraphicsPipeline (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
|
||||
bool CheckGraphicsPipelineExistence (std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair) noexcept;
|
||||
|
|
|
@ -195,7 +195,7 @@ namespace SHADE
|
|||
return *this;
|
||||
}
|
||||
|
||||
void SHVertexInputState::AddBinding(bool instanced, bool calcOffset, std::initializer_list<SHVertexAttribute> inAttribs) noexcept
|
||||
void SHVertexInputState::AddBinding(bool instanced, bool calcOffset, std::initializer_list<SHVertexAttribute> inAttribs, uint32_t fixedBinding /*= static_cast<uint32_t>(-1)*/, uint32_t fixedAttributeLocation/* = static_cast<uint32_t>(-1)*/) noexcept
|
||||
{
|
||||
// add a binding and get ref to it
|
||||
bindings.emplace_back();
|
||||
|
@ -210,7 +210,7 @@ namespace SHADE
|
|||
// Offset is 0 at first (for first element)
|
||||
uint32_t offset = 0;
|
||||
|
||||
binding.binding = static_cast<uint32_t>(bindings.size() - 1);
|
||||
binding.binding = (fixedBinding != static_cast<uint32_t>(-1)) ? fixedBinding : static_cast<uint32_t>(bindings.size() - 1);
|
||||
|
||||
// for every attribute passed in
|
||||
for (auto const& attrib : inAttribs)
|
||||
|
@ -226,10 +226,11 @@ namespace SHADE
|
|||
auto& vertexAttrib = attributes.back();
|
||||
|
||||
// The binding for that attribute description is index of the new binding created earlier in this function
|
||||
vertexAttrib.binding = static_cast<uint32_t>(bindings.size() - 1);
|
||||
vertexAttrib.binding = (fixedBinding != static_cast<uint32_t>(-1)) ? fixedBinding : static_cast<uint32_t>(bindings.size() - 1);
|
||||
|
||||
// Attribute location. New index is simply + 1 of the previous. Starts from 0 obviously
|
||||
vertexAttrib.location = static_cast<uint32_t>(attributes.size () - 1);
|
||||
//Attribute location. New index is simply + 1 of the previous. Starts from 0 obviously
|
||||
vertexAttrib.location = (fixedAttributeLocation != static_cast<uint32_t>(-1)) ? fixedAttributeLocation + i : static_cast<uint32_t>(attributes.size () - 1);
|
||||
//vertexAttrib.location = static_cast<uint32_t>(attributes.size() - 1);
|
||||
|
||||
// Get the vkFormat associated with the SHAttribFormat
|
||||
vertexAttrib.format = format;
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace SHADE
|
|||
SHVertexInputState& operator= (SHVertexInputState const& rhs) noexcept;
|
||||
SHVertexInputState& operator= (SHVertexInputState&& rhs) noexcept;
|
||||
|
||||
void AddBinding(bool instanced, bool calcOffset, std::initializer_list<SHVertexAttribute> inAttribs) noexcept;
|
||||
void AddBinding(bool instanced, bool calcOffset, std::initializer_list<SHVertexAttribute> inAttribs, uint32_t fixedBinding = static_cast<uint32_t>(-1), uint32_t fixedAttributeLocation = static_cast<uint32_t>(-1)) noexcept;
|
||||
|
||||
friend class SHVkPipelineState;
|
||||
friend class SHVkPipeline;
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace SHADE
|
|||
vk::ShaderStageFlags stageFlags;
|
||||
|
||||
for (auto& shaderModule : shaderModules)
|
||||
{
|
||||
if (shaderModule)
|
||||
{
|
||||
// References for convenience
|
||||
auto const& reflectedData = shaderModule->GetReflectedData();
|
||||
|
@ -81,7 +83,7 @@ namespace SHADE
|
|||
|
||||
stageFlags |= shaderModule->GetShaderStageFlagBits();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// After all the sizes of the push constant blocks have been added, record the size in the interface
|
||||
|
@ -132,6 +134,9 @@ namespace SHADE
|
|||
//! Now we take descriptor set info from all shaders and prepare some bindings for the descriptor set
|
||||
for (auto& shaderModule : shaderModules)
|
||||
{
|
||||
if (!shaderModule)
|
||||
continue;
|
||||
|
||||
auto const& descBindingInfo = shaderModule->GetReflectedData().GetDescriptorBindingInfo();
|
||||
auto const& reflectedSets = descBindingInfo.GetReflectedSets();
|
||||
|
||||
|
@ -200,11 +205,13 @@ namespace SHADE
|
|||
newBinding.DescriptorCount = SHVkDescriptorSetLayout::Binding::VARIABLE_DESCRIPTOR_UPPER_BOUND;
|
||||
|
||||
// Set the flags for variable bindings
|
||||
newBinding.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount;
|
||||
newBinding.flags = vk::DescriptorBindingFlagBits::eVariableDescriptorCount | vk::DescriptorBindingFlagBits::ePartiallyBound;
|
||||
}
|
||||
else
|
||||
{
|
||||
SHLOG_ERROR("Variable size binding is detected, but the binding is not the last binding of the set and is therefore invalid. ");
|
||||
}
|
||||
}
|
||||
|
||||
setsWithBindings[CURRENT_SET].emplace_back(newBinding);
|
||||
}
|
||||
|
@ -326,11 +333,10 @@ namespace SHADE
|
|||
{
|
||||
for (auto& mod : shaderModules)
|
||||
{
|
||||
mod->AddCallback([this]()
|
||||
if (mod)
|
||||
{
|
||||
RecreateIfNeeded();
|
||||
mod->AddCallback([this]() { RecreateIfNeeded(); });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
RecreateIfNeeded ();
|
||||
|
|
|
@ -54,7 +54,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
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 /*= {}*/)
|
||||
void SHRenderGraph::AddResource(std::string resourceName, std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags, bool resizeWithWindow, 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))
|
||||
|
@ -64,7 +64,7 @@ namespace SHADE
|
|||
format = renderGraphStorage->swapchain->GetSurfaceFormatKHR().format;
|
||||
}
|
||||
|
||||
auto resource = renderGraphStorage->resourceHub->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, resizeWithWindow);
|
||||
renderGraphStorage->graphResources->try_emplace(resourceName, resource);
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,9 @@ namespace SHADE
|
|||
|
||||
for (auto& affectedNode : affectedNodes)
|
||||
nodes[affectedNode]->CreateFramebuffer();
|
||||
|
||||
renderGraphStorage->graphResources->at(resourceName).Free();
|
||||
renderGraphStorage->graphResources->erase (resourceName);
|
||||
/*
|
||||
* IMPORTANT NOTES
|
||||
*
|
||||
|
@ -166,68 +169,7 @@ namespace SHADE
|
|||
|
||||
for (uint32_t i = 0; auto& node : nodes)
|
||||
{
|
||||
// key is handle ID, value is final layout.
|
||||
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
|
||||
if (node->subpasses.empty())
|
||||
{
|
||||
SHLOG_ERROR("Node does not contain a subpass. Cannot configure attachment descriptions as a result. ");
|
||||
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_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);
|
||||
}
|
||||
node->StandaloneConfigureAttDesc(i == nodes.size() - 1);
|
||||
++i;
|
||||
}
|
||||
|
||||
|
@ -333,6 +275,17 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHRenderGraph::ReindexNodes(void) noexcept
|
||||
{
|
||||
nodeIndexing.clear();
|
||||
uint32_t i = 0;
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
nodeIndexing.emplace (node->name, i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -473,6 +426,65 @@ namespace SHADE
|
|||
return node;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
This function is purely used for dynamic nodes (if such a thing were to
|
||||
exist in our architecture). In other words, don't use this function unless
|
||||
the new node is fully standalone and does not rely or is a prereq of
|
||||
other nodes.
|
||||
|
||||
\param nodeName
|
||||
Name of new node
|
||||
|
||||
\param resourceInstruction
|
||||
Resources for the node
|
||||
|
||||
\param nodeToAddAfter
|
||||
The node to add the new node after.
|
||||
|
||||
\return
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHRenderGraphNode> SHRenderGraph::AddNodeAfter(std::string nodeName, std::initializer_list<ResourceInstruction> resourceInstruction, std::string nodeToAddAfter) noexcept
|
||||
{
|
||||
if (nodeIndexing.contains(nodeName))
|
||||
{
|
||||
SHLOG_ERROR("Node already exists, cannot add node. ");
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<SHAttachmentDescInitParams> descInitParams;
|
||||
for (auto const& instruction : resourceInstruction)
|
||||
{
|
||||
// If the resource that the new node is requesting for exists, allow the graph to reference it
|
||||
if (renderGraphStorage->graphResources->contains(instruction.resourceName))
|
||||
{
|
||||
descInitParams.push_back(
|
||||
{
|
||||
.resourceHdl = renderGraphStorage->graphResources->at(instruction.resourceName),
|
||||
.dontClearOnLoad = instruction.dontClearOnLoad,
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
SHLOG_ERROR("Resource doesn't exist in graph yet. Cannot create new node.");
|
||||
return{};
|
||||
}
|
||||
}
|
||||
|
||||
// get target node
|
||||
auto targetNode = nodes.begin() + nodeIndexing.at(nodeToAddAfter);
|
||||
|
||||
auto node = nodes.insert(targetNode, renderGraphStorage->resourceHub->Create<SHRenderGraphNode>(nodeName, renderGraphStorage, std::move(descInitParams), std::vector<Handle<SHRenderGraphNode>>()));
|
||||
ReindexNodes ();
|
||||
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)
|
||||
|
@ -532,10 +544,6 @@ namespace SHADE
|
|||
ConfigureSubSystems();
|
||||
}
|
||||
|
||||
void SHRenderGraph::Regenerate(void) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
@ -571,12 +579,15 @@ namespace SHADE
|
|||
auto const& descMappings = SHGraphicsPredefinedData::GetMappings(SHGraphicsPredefinedData::SystemType::BATCHING);
|
||||
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
if (node->renderpass)
|
||||
{
|
||||
// bind static global data
|
||||
SHGlobalDescriptorSets::BindStaticGlobalData(cmdBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::STATIC_DATA));
|
||||
|
||||
node->Execute(cmdBuffer, descPool, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
cmdBuffer->EndLabeledSegment();
|
||||
}
|
||||
|
@ -604,10 +615,13 @@ namespace SHADE
|
|||
{
|
||||
// resize resources
|
||||
for (auto& [name, resource] : *renderGraphStorage->graphResources)
|
||||
{
|
||||
if (resource->resizeWithWindow)
|
||||
{
|
||||
if (!renderGraphStorage->nonOwningResourceInitialLayouts.contains (resource.GetId().Raw))
|
||||
resource->HandleResize(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& node : nodes)
|
||||
{
|
||||
|
|
|
@ -55,6 +55,7 @@ namespace SHADE
|
|||
void ConfigureRenderpasses (void) noexcept;
|
||||
void ConfigureSubSystems (void) noexcept;
|
||||
void ConfigureFramebuffers (void) noexcept;
|
||||
void ReindexNodes (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
|
@ -101,6 +102,7 @@ namespace SHADE
|
|||
(
|
||||
std::string resourceName,
|
||||
std::initializer_list<SH_RENDER_GRAPH_RESOURCE_FLAGS> typeFlags,
|
||||
bool resizeWithWindow = true,
|
||||
uint32_t w = static_cast<uint32_t>(-1),
|
||||
uint32_t h = static_cast<uint32_t>(-1),
|
||||
vk::Format format = vk::Format::eB8G8R8A8Unorm,
|
||||
|
@ -123,6 +125,12 @@ namespace SHADE
|
|||
std::initializer_list<ResourceInstruction> resourceInstruction,
|
||||
std::initializer_list<std::string> predecessorNodes
|
||||
) noexcept;
|
||||
Handle<SHRenderGraphNode> AddNodeAfter
|
||||
(
|
||||
std::string nodeName,
|
||||
std::initializer_list<ResourceInstruction> resourceInstruction,
|
||||
std::string nodeToAddAfter
|
||||
) noexcept;
|
||||
|
||||
void AddRenderToSwapchainNode
|
||||
(
|
||||
|
@ -134,7 +142,6 @@ namespace SHADE
|
|||
) noexcept;
|
||||
|
||||
void Generate (void) noexcept;
|
||||
void Regenerate (void) noexcept;
|
||||
void CheckForNodeComputes (void) noexcept;
|
||||
void Execute (uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void Begin (uint32_t frameIndex) noexcept;
|
||||
|
@ -165,7 +172,14 @@ namespace SHADE
|
|||
* 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.
|
||||
* -
|
||||
* - In hindsight there should have been a distinction between static and dynamic nodes. Static nodes are the ones that are accounted
|
||||
* for in the generation of the render graph. Dynamic nodes begin with nothing at first, but allows for linking of resources and subpasses
|
||||
* while the render graph is executing. The resources here should also be dynamic, which means it should never be used in anywhere else other
|
||||
* than in the node that is using it. This would mean its initial layouts are always specified as undefined and final layouts specified as
|
||||
* whatever the last subpass that is using that resource specifies in the node. Dynamic nodes are meant to render to resources that would later
|
||||
* be used externally, as descriptors for example (the descriptors can be used in a render graph node compute for example). Dynamic nodes run as
|
||||
* if they are the only nodes in the graph, because their resources are not used in other nodes and are thus not predecessors or successors of any
|
||||
* other node.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
@ -32,9 +32,12 @@ namespace SHADE
|
|||
renderpass.Free();
|
||||
}
|
||||
|
||||
if (!spDescs.empty())
|
||||
{
|
||||
renderpass = graphStorage->logicalDevice->CreateRenderpass(attachmentDescriptions, spDescs, spDeps);
|
||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eRenderPass, renderpass->GetVkRenderpass(), "[RenderPass] " + name);
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
@ -45,6 +48,8 @@ namespace SHADE
|
|||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::CreateFramebuffer(void) noexcept
|
||||
{
|
||||
if (renderpass)
|
||||
{
|
||||
if (!framebuffers.empty())
|
||||
{
|
||||
|
@ -78,8 +83,11 @@ namespace SHADE
|
|||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eFramebuffer, framebuffers[i]->GetVkFramebuffer(), "[Framebuffer] " + name + std::to_string(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::HandleResize(void) noexcept
|
||||
{
|
||||
if (renderpass)
|
||||
{
|
||||
renderpass->HandleResize();
|
||||
|
||||
|
@ -114,23 +122,32 @@ namespace SHADE
|
|||
nodeCompute->HandleResize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::ConfigureSubpasses(void) noexcept
|
||||
{
|
||||
if (subpasses.empty())
|
||||
return;
|
||||
|
||||
uint32_t numValidSubpasses = std::count_if(subpasses.begin(), subpasses.end(), [](Handle<SHSubpass> subpass) {return !subpass->HasNoAttachments();});
|
||||
|
||||
// Create subpass description and dependencies based on number of subpasses
|
||||
spDescs.resize(subpasses.size());
|
||||
spDeps.resize(subpasses.size());
|
||||
spDescs.resize(numValidSubpasses);
|
||||
spDeps.resize(numValidSubpasses);
|
||||
|
||||
// Now we want to loop through all attachments in all subpasses in the node and query
|
||||
// the resources being used. For each resource we want to query the type and record it
|
||||
// in bit fields (1 bit for each subpass).
|
||||
uint32_t colorRead = 0, colorWrite = 0, depthRead = 0, depthWrite = 0, inputDependencies = 0;
|
||||
|
||||
uint32_t i = 0;
|
||||
|
||||
// For all subpasses (see above description about bit field for this).
|
||||
for (auto& subpass : subpasses)
|
||||
for (uint32_t i = 0; auto& subpass : subpasses)
|
||||
{
|
||||
// skip if subpass is not valid
|
||||
if (subpass->HasNoAttachments())
|
||||
continue;
|
||||
|
||||
// Configure subpass description
|
||||
auto& desc = spDescs[i];
|
||||
desc.pColorAttachments = subpass->colorReferences.data();
|
||||
|
@ -186,8 +203,11 @@ namespace SHADE
|
|||
|
||||
// Loop through all subpasses again but this time we use the bit field to initialize
|
||||
// the dependencies.
|
||||
for (i = 0; i < subpasses.size(); ++i)
|
||||
for (uint32_t i = 0; auto & subpass : subpasses)
|
||||
{
|
||||
if (subpass->HasNoAttachments())
|
||||
continue;
|
||||
|
||||
vk::PipelineStageFlags srcStage;
|
||||
vk::PipelineStageFlags dstStage;
|
||||
vk::AccessFlags srcAccess;
|
||||
|
@ -245,6 +265,8 @@ namespace SHADE
|
|||
|
||||
// initialize input descriptors
|
||||
subpasses[i]->CreateInputDescriptors();
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,6 +365,7 @@ namespace SHADE
|
|||
, spDeps{ std::move(rhs.spDeps) }
|
||||
, nodeComputes{ std::move(rhs.nodeComputes) }
|
||||
, name { std::move(rhs.name) }
|
||||
, ISelfHandle<SHRenderGraphNode>{std::move(rhs)}
|
||||
|
||||
{
|
||||
rhs.renderpass = {};
|
||||
|
@ -419,7 +442,7 @@ namespace SHADE
|
|||
return subpass;
|
||||
}
|
||||
|
||||
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, float numWorkGroupScale/* = 1.0f*/) noexcept
|
||||
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, uint32_t variableDescCount/* = 0*/, float numWorkGroupScale/* = 1.0f*/) noexcept
|
||||
{
|
||||
// Look for the required resources in the graph
|
||||
std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
|
||||
|
@ -435,7 +458,7 @@ namespace SHADE
|
|||
std::vector<Handle<SHRenderGraphResource>> temp (nodeComputeResources);
|
||||
|
||||
// Create the subpass compute with the resources
|
||||
auto nodeCompute = graphStorage->resourceHub->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(), variableDescCount);
|
||||
nodeComputes.push_back(nodeCompute);
|
||||
|
||||
for (auto& resource : temp)
|
||||
|
@ -483,6 +506,68 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::StandaloneConfigureAttDesc(bool isLastNode) noexcept
|
||||
{
|
||||
// key is handle ID, value is final layout.
|
||||
std::unordered_map<uint32_t, vk::ImageLayout> resourceAttFinalLayouts;
|
||||
if (!subpasses.empty())
|
||||
{
|
||||
// We first want to take all resources track their layout as undefined at the start of the node/renderpass
|
||||
for (auto& resource : attResources)
|
||||
{
|
||||
resource->GetInfoTracker()->TrackLayout(GetHandle(), {}, vk::ImageLayout::eUndefined);
|
||||
}
|
||||
|
||||
// attempt to get all final layouts for all resources
|
||||
for (auto& subpass : 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 (isLastNode && (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;
|
||||
|
||||
attResources[color.attachment]->infoTracker->TrackLayout(GetHandle(), subpass, color.layout);
|
||||
}
|
||||
|
||||
for (auto& depth : subpass->depthReferences)
|
||||
{
|
||||
resourceAttFinalLayouts[depth.attachment] = depth.layout;
|
||||
attResources[depth.attachment]->infoTracker->TrackLayout(GetHandle(), subpass, depth.layout);
|
||||
}
|
||||
|
||||
for (auto& input : subpass->inputReferences)
|
||||
{
|
||||
resourceAttFinalLayouts[input.attachment] = input.layout;
|
||||
attResources[input.attachment]->infoTracker->TrackLayout(GetHandle(), subpass, input.layout);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < attachmentDescriptions.size(); ++j)
|
||||
{
|
||||
auto& att = attachmentDescriptions[j];
|
||||
auto& resource = 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) &&
|
||||
graphStorage->nonOwningResourceInitialLayouts.contains(resource.GetId().Raw))
|
||||
{
|
||||
att.initialLayout = graphStorage->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(GetHandle(), {}, att.finalLayout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -509,14 +594,14 @@ namespace SHADE
|
|||
// remove attachment reference
|
||||
attachmentDescriptions.erase (attachmentDescriptions.begin() + index);
|
||||
|
||||
// erase from mapping as well
|
||||
resourceAttachmentMapping->erase(resourceHandleID);
|
||||
|
||||
// Remove footprint of attachment from all subpasses as well
|
||||
for (auto it = subpasses.begin(); it != subpasses.end(); ++it)
|
||||
{
|
||||
// attempt to detach resource from subpass
|
||||
(*it)->DetachResource(resourceName, index);
|
||||
|
||||
// If the subpass ends up having no attachments after, erase it from the node
|
||||
if ((*it)->HasNoAttachments())
|
||||
// If the subpass uses the resource, just remove the subpass since the subpass will be invalid
|
||||
if ((*it)->UsesResource(index))
|
||||
{
|
||||
// erase from indexing
|
||||
subpassIndexing.erase((*it)->GetName());
|
||||
|
@ -530,12 +615,32 @@ namespace SHADE
|
|||
for (uint32_t i = 0; i < subpasses.size(); ++i)
|
||||
subpasses[i]->SetIndex(i);
|
||||
|
||||
// remove node computes using the resource
|
||||
for (auto it = nodeComputes.begin(); it != nodeComputes.end(); ++it)
|
||||
{
|
||||
if ((*it)->UsesResource(resourceHandleID))
|
||||
{
|
||||
it = nodeComputes.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// recompute the barriers for the other computes
|
||||
for (auto it = nodeComputes.begin(); it != nodeComputes.end(); ++it)
|
||||
{
|
||||
if (it == nodeComputes.begin())
|
||||
(*it)->SetFollowingEndRenderpass(true);
|
||||
|
||||
(*it)->InitializeBarriers();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SHRenderGraphNode::Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept
|
||||
{
|
||||
if (renderpass)
|
||||
{
|
||||
uint32_t framebufferIndex = (framebuffers.size() > 1) ? frameIndex : 0;
|
||||
commandBuffer->BeginRenderpass(renderpass, framebuffers[framebufferIndex]);
|
||||
|
@ -545,7 +650,7 @@ namespace SHADE
|
|||
subpasses[i]->Execute(commandBuffer, descPool, frameIndex);
|
||||
|
||||
// Go to next subpass if not last subpass
|
||||
if (i != static_cast<uint32_t>(subpasses.size()) - 1u)
|
||||
if (i != static_cast<uint32_t>(subpasses.size()) - 1u && !subpasses[i]->HasNoAttachments())
|
||||
commandBuffer->NextSubpass();
|
||||
}
|
||||
|
||||
|
@ -569,6 +674,7 @@ namespace SHADE
|
|||
for (auto& sbCompute : nodeComputes)
|
||||
sbCompute->Execute(commandBuffer, frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHRenderGraphNode::GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept
|
||||
{
|
||||
|
@ -599,6 +705,77 @@ namespace SHADE
|
|||
batcher.FinaliseBatches(graphStorage->logicalDevice, descPool, frameIndex);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
This function simply appends to the container of VkAttachmentDescription
|
||||
and attResources. It will assume the resource is used standalone in the
|
||||
node and will not account for its usage in other nodes. As such its
|
||||
initialLayout will always be UNDEFINED and its finalLayout will be
|
||||
whatever is calculated if the node is regenerated using
|
||||
StandaloneRegnerate. This function also does not affect the render graph
|
||||
while its running since the 2 containers above have already been copied
|
||||
to the GPU.
|
||||
|
||||
\param resourceName
|
||||
The name of the resource for getting the resource.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::RuntimeLinkResource(std::string resourceName) noexcept
|
||||
{
|
||||
// Get new resource
|
||||
Handle<SHRenderGraphResource> newResource = graphStorage->graphResources->at(resourceName);
|
||||
|
||||
// append new resource to container
|
||||
attResources.push_back(newResource);
|
||||
|
||||
attachmentDescriptions.push_back(vk::AttachmentDescription
|
||||
{
|
||||
.format = newResource->GetResourceFormat(),
|
||||
.samples = vk::SampleCountFlagBits::e1,
|
||||
.loadOp = vk::AttachmentLoadOp::eClear,
|
||||
.storeOp = vk::AttachmentStoreOp::eStore,
|
||||
.stencilLoadOp = vk::AttachmentLoadOp::eClear,
|
||||
.stencilStoreOp = vk::AttachmentStoreOp::eStore,
|
||||
});
|
||||
|
||||
resourceAttachmentMapping->try_emplace(newResource.GetId().Raw, attachmentDescriptions.size() - 1);
|
||||
}
|
||||
|
||||
Handle<SHSubpass> SHRenderGraphNode::RuntimeAddSubpass(std::string subpassName, Handle<SHViewport> viewport, Handle<SHRenderer> renderer) noexcept
|
||||
{
|
||||
return AddSubpass(std::move (subpassName), viewport, renderer);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
USE WITH CAUTION because the function does not reevaluate resource
|
||||
layouts in attachment descriptions. All resources here will start at
|
||||
UNDEFINED and end at whatever the last subpass using the attachment
|
||||
specifies. It will also not support render graph node computes given its
|
||||
complexity if it has to be accounted for.
|
||||
|
||||
IN SHORT, IT GENERATES A RENDERPASS AS IF ITS THE ONLY NODE
|
||||
IN THE RENDER GRAPH. SEE NOTES IN SHRenderGraph.h
|
||||
|
||||
This function is mainly meant for nodes that are dynamic (in hindsight,
|
||||
there really should have been a distinction between static and dynamic
|
||||
nodes).
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHRenderGraphNode::RuntimeStandaloneRegenerate(void) noexcept
|
||||
{
|
||||
StandaloneConfigureAttDesc(false);
|
||||
ConfigureSubpasses();
|
||||
CreateRenderpass();
|
||||
CreateFramebuffer();
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
@ -633,4 +810,15 @@ namespace SHADE
|
|||
return attResources;
|
||||
}
|
||||
|
||||
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::GetNodeCompute(std::string nodeComputeName) const noexcept
|
||||
{
|
||||
for (auto nc : nodeComputes)
|
||||
{
|
||||
if (nc->name == nodeComputeName)
|
||||
return nc;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
|
@ -93,6 +93,9 @@ namespace SHADE
|
|||
void CreateFramebuffer(void) noexcept;
|
||||
void HandleResize (void) noexcept;
|
||||
void ConfigureSubpasses (void) noexcept;
|
||||
bool DetachResource(std::string const& resourceName, uint64_t resourceHandleID) noexcept;
|
||||
void AddDummySubpassIfNeeded(void) noexcept;
|
||||
void StandaloneConfigureAttDesc (bool isLastNode) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -106,15 +109,17 @@ namespace SHADE
|
|||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHSubpass> AddSubpass(std::string subpassName, Handle<SHViewport> viewport, Handle<SHRenderer> renderer) noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings = {}, float numWorkGroupScale = 1.0f) noexcept;
|
||||
void AddDummySubpassIfNeeded (void) noexcept;
|
||||
bool DetachResource (std::string const& resourceName, uint64_t resourceHandleID) noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> AddNodeCompute(std::string nodeName, Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings = {}, uint32_t variableDescCount = 0, float numWorkGroupScale = 1.0f) noexcept;
|
||||
|
||||
// TODO: RemoveSubpass()
|
||||
void Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
Handle<SHVkPipeline> GetOrCreatePipeline(std::pair<Handle<SHVkShaderModule>, Handle<SHVkShaderModule>> const& vsFsPair, Handle<SHSubpass> subpass) noexcept;
|
||||
void FinaliseBatch(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool);
|
||||
|
||||
// Runtime functions that don't affect the renderpass
|
||||
void RuntimeLinkResource(std::string resourceName) noexcept;
|
||||
Handle<SHSubpass> RuntimeAddSubpass(std::string subpassName, Handle<SHViewport> viewport, Handle<SHRenderer> renderer) noexcept;
|
||||
void RuntimeStandaloneRegenerate (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -122,6 +127,7 @@ namespace SHADE
|
|||
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;
|
||||
Handle<SHRenderGraphNodeCompute> GetNodeCompute (std::string nodeComputeName) const noexcept;
|
||||
friend class SHRenderGraph;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,56 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale/* = 1.0f*/) noexcept
|
||||
|
||||
bool SHRenderGraphNodeCompute::UsesResource(uint64_t resourceHandleID) const noexcept
|
||||
{
|
||||
for (auto& resource : resources)
|
||||
{
|
||||
if (resource.GetId().Raw == resourceHandleID)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::InitializeBarriers(void) noexcept
|
||||
{
|
||||
for (uint32_t i = 0; auto & barriers : memoryBarriers)
|
||||
{
|
||||
barriers.clear();
|
||||
|
||||
for (auto& resource : resources)
|
||||
{
|
||||
vk::AccessFlags srcAccessMask = (followingEndRenderpass) ? vk::AccessFlagBits::eInputAttachmentRead : (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite);
|
||||
barriers.push_back(vk::ImageMemoryBarrier
|
||||
{
|
||||
.srcAccessMask = srcAccessMask,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.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,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = resource->mipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
}
|
||||
});
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::SetFollowingEndRenderpass(uint32_t flag) noexcept
|
||||
{
|
||||
followingEndRenderpass = flag;
|
||||
}
|
||||
|
||||
|
||||
SHRenderGraphNodeCompute::SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, uint32_t variableDescCount, float inNumWorkGroupScale/* = 1.0f*/) noexcept
|
||||
: computePipeline{}
|
||||
, pipelineLayout{}
|
||||
, resources{}
|
||||
|
@ -68,10 +117,12 @@ namespace SHADE
|
|||
// check if all layouts are there
|
||||
if (layouts.size() == descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE) + 1)
|
||||
{
|
||||
Handle<SHVkDescriptorSetLayout> computeResourceLayout = {};
|
||||
computeResourceLayout = layouts[descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE)];
|
||||
|
||||
// create compute resources
|
||||
computeResource = graphStorage->resourceHub->Create<ComputeResource>();
|
||||
auto computeResourceLayout = layouts[descMappings.at(SHPredefinedDescriptorTypes::RENDER_GRAPH_NODE_COMPUTE_RESOURCE)];
|
||||
computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, { 1 });
|
||||
computeResource->descSet = graphStorage->descriptorPool->Allocate({ computeResourceLayout }, {variableDescCount});
|
||||
#ifdef _DEBUG
|
||||
for (auto set : computeResource->descSet->GetVkHandle())
|
||||
SET_VK_OBJ_NAME(graphStorage->logicalDevice, vk::ObjectType::eDescriptorSet, set, "[Descriptor Set] " + name + " Resources");
|
||||
|
@ -91,6 +142,11 @@ namespace SHADE
|
|||
|
||||
void SHRenderGraphNodeCompute::Execute(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
for (auto& fn : preComputeFunctions)
|
||||
{
|
||||
fn (cmdBuffer, frameIndex);
|
||||
}
|
||||
|
||||
// bind the compute pipeline
|
||||
cmdBuffer->BindPipeline(computePipeline);
|
||||
|
||||
|
@ -157,35 +213,7 @@ namespace SHADE
|
|||
groupSizeX = maxWidth / workGroupSizeX;
|
||||
groupSizeY = maxHeight / workGroupSizeY;
|
||||
|
||||
for (uint32_t i = 0; auto& barriers : memoryBarriers)
|
||||
{
|
||||
barriers.clear();
|
||||
|
||||
for (auto& resource : resources)
|
||||
{
|
||||
vk::AccessFlags srcAccessMask = (followingEndRenderpass) ? vk::AccessFlagBits::eInputAttachmentRead : (vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite);
|
||||
barriers.push_back(vk::ImageMemoryBarrier
|
||||
{
|
||||
.srcAccessMask = srcAccessMask,
|
||||
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
|
||||
.oldLayout = vk::ImageLayout::eGeneral,
|
||||
.newLayout = vk::ImageLayout::eGeneral,
|
||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||
.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,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = resource->mipLevels,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
InitializeBarriers();
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::SetDynamicOffsets(std::span<uint32_t> perFrameSizes) noexcept
|
||||
|
@ -219,4 +247,17 @@ namespace SHADE
|
|||
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::ModifyWriteDescImageComputeResource(uint32_t binding, SHVkDescriptorSetGroup::viewSamplerLayout const& viewSamplerLayout, uint32_t descArrayIndex) noexcept
|
||||
{
|
||||
static constexpr uint32_t COMPUTE_RESOURCE_SET_INDEX = 0;
|
||||
computeResource->descSet->ModifyWriteDescImage(COMPUTE_RESOURCE_SET_INDEX, binding, viewSamplerLayout, descArrayIndex);
|
||||
computeResource->descSet->UpdateDescriptorSetImage(COMPUTE_RESOURCE_SET_INDEX, binding, descArrayIndex);
|
||||
|
||||
}
|
||||
|
||||
void SHRenderGraphNodeCompute::AddPreComputeFunction(PreComputeFunction const& fn) noexcept
|
||||
{
|
||||
preComputeFunctions.push_back(fn);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,10 @@ namespace SHADE
|
|||
|
||||
class SHRenderGraphNodeCompute
|
||||
{
|
||||
public:
|
||||
using PreComputeFunction = std::function<void(Handle<SHVkCommandBuffer>, uint32_t)>;
|
||||
|
||||
|
||||
private:
|
||||
// Binding of set SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE
|
||||
struct ComputeResource
|
||||
|
@ -73,8 +77,23 @@ namespace SHADE
|
|||
//! Name of this node
|
||||
std::string name;
|
||||
|
||||
std::vector<PreComputeFunction> preComputeFunctions;
|
||||
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
bool UsesResource (uint64_t resourceHandleID) const noexcept;
|
||||
void InitializeBarriers (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void SetFollowingEndRenderpass (uint32_t flag) noexcept;
|
||||
|
||||
public:
|
||||
SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, float inNumWorkGroupScale = 1.0f) noexcept;
|
||||
SHRenderGraphNodeCompute(std::string nodeName, Handle<SHRenderGraphStorage> graphStorage, Handle<SHVkShaderModule> computeShaderModule, std::vector<Handle<SHRenderGraphResource>>&& subpassComputeResources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, bool followingEndRP, uint32_t variableDescCount, float inNumWorkGroupScale = 1.0f) noexcept;
|
||||
|
||||
void Execute (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
void HandleResize (void) noexcept;
|
||||
|
@ -84,7 +103,9 @@ namespace SHADE
|
|||
|
||||
void ModifyWriteDescBufferComputeResource (uint32_t binding, std::span<Handle<SHVkBuffer>> const& buffers, uint32_t offset, uint32_t range) noexcept;
|
||||
void ModifyWriteDescImageComputeResource(uint32_t binding, std::span<SHVkDescriptorSetGroup::viewSamplerLayout> const& viewSamplerLayouts) noexcept;
|
||||
void ModifyWriteDescImageComputeResource(uint32_t binding, SHVkDescriptorSetGroup::viewSamplerLayout const& viewSamplerLayout, uint32_t descArrayIndex) noexcept;
|
||||
|
||||
void AddPreComputeFunction (PreComputeFunction const& fn) noexcept;
|
||||
|
||||
friend class SHRenderGraph;
|
||||
friend class SHRenderGraphNode;
|
||||
|
|
|
@ -78,7 +78,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
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
|
||||
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, bool inResizeWithWindow) noexcept
|
||||
: graphStorage{renderGraphStorage}
|
||||
, resourceTypeFlags{ }
|
||||
, resourceFormat{ format }
|
||||
|
@ -88,6 +88,7 @@ namespace SHADE
|
|||
, height{ h }
|
||||
, mipLevels{ levels }
|
||||
, resourceName{ name }
|
||||
, resizeWithWindow { inResizeWithWindow }
|
||||
{
|
||||
// If the resource type is an arbitrary image and not swapchain image
|
||||
if (typeFlags.size() == 1 && *typeFlags.begin() == SH_RENDER_GRAPH_RESOURCE_FLAGS::COLOR_PRESENT)
|
||||
|
@ -210,6 +211,7 @@ namespace SHADE
|
|||
, imageAspectFlags{ rhs.imageAspectFlags }
|
||||
, graphStorage{rhs.graphStorage}
|
||||
, infoTracker {std::move (rhs.infoTracker)}
|
||||
, resizeWithWindow{rhs.resizeWithWindow}
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -242,7 +244,8 @@ namespace SHADE
|
|||
mipLevels = rhs.mipLevels;
|
||||
imageAspectFlags = rhs.imageAspectFlags;
|
||||
graphStorage = rhs.graphStorage;
|
||||
infoTracker = std::move(infoTracker);
|
||||
infoTracker = std::move(rhs.infoTracker);
|
||||
resizeWithWindow = rhs.resizeWithWindow;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
|
|
@ -96,11 +96,14 @@ namespace SHADE
|
|||
//! For tracking resource states in stages of the render graphs
|
||||
Handle<InfoTracker> infoTracker;
|
||||
|
||||
//! Whether or not to resize (recreate vulkan image) when window resizes
|
||||
bool resizeWithWindow;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* CTORS AND DTORS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
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(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, bool inResizeWithWindow) noexcept;
|
||||
SHRenderGraphResource(SHRenderGraphResource&& rhs) noexcept;
|
||||
SHRenderGraphResource& operator=(SHRenderGraphResource&& rhs) noexcept;
|
||||
~SHRenderGraphResource(void) noexcept;
|
||||
|
|
|
@ -77,6 +77,7 @@ namespace SHADE
|
|||
, name { rhs.name }
|
||||
, viewport {rhs.viewport}
|
||||
, renderer {rhs.renderer}
|
||||
, companionSubpass {rhs.companionSubpass}
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -113,6 +114,7 @@ namespace SHADE
|
|||
name = std::move(rhs.name);
|
||||
renderer = rhs.renderer;
|
||||
viewport = rhs.viewport;
|
||||
companionSubpass = rhs.companionSubpass;
|
||||
|
||||
|
||||
return *this;
|
||||
|
@ -162,7 +164,7 @@ namespace SHADE
|
|||
switch (attachmentDescriptionType)
|
||||
{
|
||||
case SH_RENDER_GRAPH_RESOURCE_FLAGS::DEPTH:
|
||||
imageLayout = vk::ImageLayout::eDepthAttachmentOptimal;
|
||||
imageLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
|
||||
break;
|
||||
case SH_RENDER_GRAPH_RESOURCE_FLAGS::STENCIL:
|
||||
imageLayout = vk::ImageLayout::eStencilAttachmentOptimal;
|
||||
|
@ -211,6 +213,8 @@ namespace SHADE
|
|||
{
|
||||
commandBuffer->BeginLabeledSegment(name);
|
||||
|
||||
if (!HasNoAttachments())
|
||||
{
|
||||
// Ensure correct transforms are provided
|
||||
superBatch->UpdateBuffers(frameIndex, descPool);
|
||||
|
||||
|
@ -227,8 +231,19 @@ namespace SHADE
|
|||
if (renderer)
|
||||
renderer->BindDescriptorSet(commandBuffer, SH_PIPELINE_TYPE::GRAPHICS, descMappings.at(SHPredefinedDescriptorTypes::CAMERA), frameIndex);
|
||||
|
||||
// If companion subpass is not a valid handle, render super batch normally
|
||||
if (!companionSubpass.companion)
|
||||
{
|
||||
// Draw all the batches
|
||||
superBatch->Draw(commandBuffer, frameIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not bind pipeline for companion and and execute draw command
|
||||
commandBuffer->BindPipeline(companionSubpass.pipeline);
|
||||
companionSubpass.companion->superBatch->Draw(commandBuffer, frameIndex, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw all the exterior draw calls
|
||||
for (auto& drawCall : exteriorDrawCalls)
|
||||
|
@ -265,43 +280,27 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHSubpass::DetachResource(std::string const& resourceName, uint32_t attachmentIndex) noexcept
|
||||
bool SHSubpass::UsesResource(uint32_t attachmentIndex) noexcept
|
||||
{
|
||||
for (uint32_t i = 0; i < colorReferences.size(); ++i)
|
||||
{
|
||||
if (colorReferences[i].attachment == attachmentIndex)
|
||||
{
|
||||
colorReferences.erase (colorReferences.begin() + i);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < depthReferences.size(); ++i)
|
||||
{
|
||||
if (depthReferences[i].attachment == attachmentIndex)
|
||||
{
|
||||
depthReferences.erase(depthReferences.begin() + i);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < inputReferences.size(); ++i)
|
||||
{
|
||||
if (inputReferences[i].attachment == attachmentIndex)
|
||||
{
|
||||
inputReferences.erase(inputReferences.begin() + i);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < inputNames.size(); ++i)
|
||||
{
|
||||
if (inputNames[i] == resourceName)
|
||||
{
|
||||
inputNames.erase(inputNames.begin() + i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SHSubpass::HasNoAttachments(void) const noexcept
|
||||
|
@ -458,6 +457,12 @@ namespace SHADE
|
|||
subpassIndex = index;
|
||||
}
|
||||
|
||||
void SHSubpass::SetCompanionSubpass(Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept
|
||||
{
|
||||
companionSubpass.companion = companion;
|
||||
companionSubpass.pipeline = pipeline;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
|
|
@ -21,12 +21,23 @@ namespace SHADE
|
|||
class SHVkSampler;
|
||||
class SHRenderer;
|
||||
class SHViewport;
|
||||
class SHVkPipeline;
|
||||
|
||||
class SH_API SHSubpass : public ISelfHandle<SHSubpass>
|
||||
{
|
||||
public:
|
||||
using ExteriorDrawCallFunction = std::function<void(Handle<SHVkCommandBuffer>, Handle<SHRenderer>, uint32_t)>;
|
||||
|
||||
// Allows for subpasses to run using a companions data
|
||||
struct CompanionSubpass
|
||||
{
|
||||
// subpass whose data will be borrowed to draw
|
||||
Handle<SHSubpass> companion;
|
||||
|
||||
// Pipeline that will be used for all the draw calls from all batches of the companion subpass
|
||||
Handle<SHVkPipeline> pipeline;
|
||||
};
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER VARIABLES */
|
||||
|
@ -94,6 +105,15 @@ namespace SHADE
|
|||
// For identifying subpasses
|
||||
std::string name;
|
||||
|
||||
//! Optional component to a companion subpass. If the subpass handle of this object
|
||||
//! is valid, the subpass will be drawn using this companion's data.
|
||||
CompanionSubpass companionSubpass;
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
bool UsesResource(uint32_t attachmentIndex) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
@ -119,7 +139,6 @@ namespace SHADE
|
|||
void Execute(Handle<SHVkCommandBuffer> commandBuffer, Handle<SHVkDescriptorPool> descPool, uint32_t frameIndex) noexcept;
|
||||
void HandleResize (void) noexcept;
|
||||
void BindInputDescriptorSets (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t setIndex, uint32_t frameIndex) const noexcept;
|
||||
void DetachResource (std::string const& resourceName, uint32_t attachmentIndex) noexcept;
|
||||
bool HasNoAttachments (void) const noexcept;
|
||||
|
||||
void Init(SHResourceHub& resourceManager) noexcept;
|
||||
|
@ -128,13 +147,18 @@ namespace SHADE
|
|||
void CreateInputDescriptors (void) noexcept;
|
||||
void UpdateWriteDescriptors (void) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* GETTERS AND SETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
private:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE GETTERS AND SETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void SetIndex (uint32_t index) noexcept;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC SETTERS AND GETTERS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void SetCompanionSubpass (Handle<SHSubpass> companion, Handle<SHVkPipeline> pipeline) noexcept;
|
||||
|
||||
Handle<SHRenderGraphNode> const& GetParentNode(void) const noexcept;
|
||||
SHSubPassIndex GetIndex() const noexcept;
|
||||
Handle<SHSuperBatch> GetSuperBatch(void) const noexcept;
|
||||
|
|
Loading…
Reference in New Issue