diff --git a/Assets/Scenes/M2Scene.shade b/Assets/Scenes/M2Scene.shade index bf910737..8b61dc67 100644 --- a/Assets/Scenes/M2Scene.shade +++ b/Assets/Scenes/M2Scene.shade @@ -21,141 +21,6 @@ Layer: 4294967295 Strength: 0 Scripts: ~ -- EID: 1 - Name: Floor - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: -1.440328, y: -4.41369677, z: -5} - Rotate: {x: -0, y: 0, z: -0} - Scale: {x: 49.4798889, y: 0.5, z: 17.5} - Renderable Component: - Mesh: 149697411 - Material: 126974645 - RigidBody Component: - Type: Static - Mass: 1 - Drag: 0.00999999978 - Angular Drag: 0.00999999978 - Use Gravity: true - Interpolate: true - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: false - Freeze Rotation Y: false - Freeze Rotation Z: false - Collider Component: - Colliders: - - Is Trigger: false - Type: Box - Half Extents: {x: 1, y: 1, z: 1} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0, z: 0} - Scripts: ~ -- EID: 10 - Name: Default - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: -4.40482807, y: 2.57871056, z: -5.21213436} - Rotate: {x: -0.361265004, y: 1.11661232, z: -0.626627684} - Scale: {x: 0.999982238, y: 0.999987125, z: 0.999981165} - RigidBody Component: - Type: Dynamic - Mass: 1 - Drag: 0 - Angular Drag: 0 - Use Gravity: true - Interpolate: true - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: false - Freeze Rotation Y: false - Freeze Rotation Z: false - Collider Component: - Colliders: - - Is Trigger: false - Type: Box - Half Extents: {x: 1, y: 1, z: 1} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0, z: 0} - Scripts: ~ -- EID: 3 - Name: Empty - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: -0.0094268322, y: 0, z: 0} - Rotate: {x: -0, y: 0, z: -0} - Scale: {x: 1, y: 1, z: 1} - Scripts: ~ -- EID: 4 - Name: Empty2 - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 0, y: 0, z: 0} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 1, y: 1, z: 1} - Scripts: ~ -- EID: 9 - Name: Bag - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 0, y: 0, z: 0} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 1, y: 1, z: 1} - Renderable Component: - Mesh: 144838771 - Material: 123745521 - Scripts: ~ -- EID: 6 - Name: AI - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: -8, y: -2, z: 2.5} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 1, y: 1, z: 1} - Renderable Component: - Mesh: 149697411 - Material: 126974645 - RigidBody Component: - Type: Dynamic - Mass: 1 - Drag: 0 - Angular Drag: 0 - Use Gravity: true - Interpolate: false - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: true - Freeze Rotation Y: true - Freeze Rotation Z: true - Collider Component: - Colliders: - - Is Trigger: false - Type: Box - Half Extents: {x: 0.5, y: 0.5, z: 0.5} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0.5, z: 0} - Scripts: ~ - EID: 7 Name: BigBoi IsActive: true @@ -181,46 +46,4 @@ Color: {x: 1, y: 1, z: 1, w: 1} Layer: 4294967295 Strength: 0.25 - Scripts: ~ -- EID: 5 - Name: item - IsActive: true - NumberOfChildren: 0 - Components: - Transform Component: - Translate: {x: 0, y: -2, z: -5} - Rotate: {x: 0, y: 0, z: 0} - Scale: {x: 2, y: 2, z: 2} - Renderable Component: - Mesh: 144838771 - Material: 123745521 - RigidBody Component: - Type: Dynamic - Mass: 1 - Drag: 0 - Angular Drag: 0 - Use Gravity: true - Interpolate: false - Freeze Position X: false - Freeze Position Y: false - Freeze Position Z: false - Freeze Rotation X: true - Freeze Rotation Y: true - Freeze Rotation Z: true - Collider Component: - Colliders: - - Is Trigger: false - Type: Box - Half Extents: {x: 1, y: 1, z: 1} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0.5, z: 0} - - Is Trigger: true - Type: Box - Half Extents: {x: 2, y: 2, z: 2} - Friction: 0.400000006 - Bounciness: 0 - Density: 1 - Position Offset: {x: 0, y: 0.5, z: 0} Scripts: ~ \ No newline at end of file diff --git a/Assets/Shaders/Normals_FS.glsl b/Assets/Shaders/Normals_FS.glsl new file mode 100644 index 00000000..ba260d82 --- /dev/null +++ b/Assets/Shaders/Normals_FS.glsl @@ -0,0 +1,50 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable +#extension GL_EXT_nonuniform_qualifier : require + +struct MatPropData +{ + vec4 color; + int textureIndex; + float alpha; + vec3 beta; +}; + +layout(location = 0) in struct +{ + vec4 vertPos; // location 0 + vec2 uv; // location = 1 + vec4 normal; // location = 2 + +} In; + +// material stuff +layout(location = 3) flat in struct +{ + int materialIndex; + uint eid; + uint lightLayerIndex; +} In2; + +layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global) +layout (std430, set = 3, binding = 0) buffer MaterialProperties // For materials +{ + MatPropData data[]; +} MatProp; + +layout(location = 0) out vec4 position; +layout(location = 1) out uint outEntityID; +layout(location = 2) out uint lightLayerIndices; +layout(location = 3) out vec4 normals; +layout(location = 4) out vec4 albedo; + +void main() +{ + position = In.vertPos; + normals = In.normal; + albedo = normals * texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) * MatProp.data[In2.materialIndex].color; + + outEntityID = In2.eid; + lightLayerIndices = In2.lightLayerIndex; +} \ No newline at end of file diff --git a/Assets/Shaders/Normals_FS.shshaderb b/Assets/Shaders/Normals_FS.shshaderb new file mode 100644 index 00000000..7595ece9 Binary files /dev/null and b/Assets/Shaders/Normals_FS.shshaderb differ diff --git a/Assets/Shaders/Normals_FS.shshaderb.shmeta b/Assets/Shaders/Normals_FS.shshaderb.shmeta new file mode 100644 index 00000000..38544c0a --- /dev/null +++ b/Assets/Shaders/Normals_FS.shshaderb.shmeta @@ -0,0 +1,3 @@ +Name: Normals_FS +ID: 48689301 +Type: 2 diff --git a/SHADE_Application/src/Application/SBApplication.cpp b/SHADE_Application/src/Application/SBApplication.cpp index 1095f965..fdfcc08b 100644 --- a/SHADE_Application/src/Application/SBApplication.cpp +++ b/SHADE_Application/src/Application/SBApplication.cpp @@ -115,6 +115,7 @@ namespace Sandbox SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); + SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); SHSystemManager::RegisterRoutine(); diff --git a/SHADE_Engine/src/Assets/SHAssetManager.cpp b/SHADE_Engine/src/Assets/SHAssetManager.cpp index b4ea7d35..f9b5cf41 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.cpp +++ b/SHADE_Engine/src/Assets/SHAssetManager.cpp @@ -143,7 +143,17 @@ namespace SHADE return result; } - /**************************************************************************** + std::optional SHAssetManager::GetAsset(AssetID id) noexcept + { + if (assetCollection.contains(id)) + { + return assetCollection[id]; + } + + return {}; + } + + /**************************************************************************** * \brief Create record for new asset. CAN ONLY CREATE FOR CUSTOM * ASSETS CREATED BY THE ENGINE. * diff --git a/SHADE_Engine/src/Assets/SHAssetManager.h b/SHADE_Engine/src/Assets/SHAssetManager.h index f6ecb3a3..9d0a0bf4 100644 --- a/SHADE_Engine/src/Assets/SHAssetManager.h +++ b/SHADE_Engine/src/Assets/SHAssetManager.h @@ -50,6 +50,7 @@ namespace SHADE * \return const& to unordered_map ****************************************************************************/ static std::vector GetAllAssets() noexcept; + static std::optional GetAsset(AssetID id) noexcept; /**************************************************************************** * \brief Create record for new resource. CAN ONLY CREATE FOR CUSTOM diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp index 895237ad..1044cc1a 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorComponentView.hpp @@ -447,8 +447,8 @@ namespace SHADE DrawContextMenu(component); Handle const& mesh = component->GetMesh(); Handle const& mat = component->GetMaterial(); - - SHEditorWidgets::DragDropReadOnlyField("Mesh", std::to_string(SHResourceManager::GetAssetID(mesh).value_or(0)).data(), [component]() + const auto MESH_NAME = SHResourceManager::GetAssetName(mesh).value_or(""); + SHEditorWidgets::DragDropReadOnlyField("Mesh", MESH_NAME, [component]() { Handle const& mesh = component->GetMesh(); return SHResourceManager::GetAssetID(mesh).value_or(0); @@ -459,13 +459,15 @@ namespace SHADE SHResourceManager::FinaliseChanges(); }, SHDragDrop::DRAG_RESOURCE); - SHEditorWidgets::DragDropReadOnlyField("Material", mat ? std::to_string(SHResourceManager::GetAssetID(mat->GetBaseMaterial()).value_or(0)).data() : "", [component]() - { - Handle const& mat = component->GetMaterial(); - if(!mat) - return static_cast(0); - return SHResourceManager::GetAssetID(mat->GetBaseMaterial()).value_or(0); - }, + const auto MAT_NAME = mat ? SHResourceManager::GetAssetName(mat->GetBaseMaterial()).value_or("") : ""; + SHEditorWidgets::DragDropReadOnlyField("Material", MAT_NAME, + [component]() + { + Handle const& mat = component->GetMaterial(); + if (!mat) + return static_cast(0); + return SHResourceManager::GetAssetID(mat->GetBaseMaterial()).value_or(0); + }, [component](AssetID const& id) { auto gfxSystem = SHSystemManager::GetSystem(); diff --git a/SHADE_Engine/src/Editor/EditorWindow/MaterialInspector/SHMaterialInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/MaterialInspector/SHMaterialInspector.cpp index 13ecb9fa..88de7b73 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/MaterialInspector/SHMaterialInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/MaterialInspector/SHMaterialInspector.cpp @@ -78,7 +78,26 @@ namespace SHADE ImGui::BeginDisabled(!isDirty); if(ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data())) { - //save + auto gfxSystem = SHSystemManager::GetSystem(); + // Replace Material if it's been instantiated + auto matHandle = SHResourceManager::Get(currentViewedMaterial); + if (matHandle) + { + // - Get Shader Modules + auto vertShader = SHResourceManager::LoadOrGet(currentMatSpec->vertexShader); + auto fragShader = SHResourceManager::LoadOrGet(currentMatSpec->fragShader); + if (vertShader && fragShader && gfxSystem) + { + // - Retrieve pipeline from pipeline library + auto renderPass = gfxSystem->GetPrimaryRenderpass(); + auto subPass = renderPass->GetSubpass(currentMatSpec->subpassName); + auto pipeline = renderPass->GetOrCreatePipeline({ vertShader, fragShader }, subPass); + // - Set Pipeline + matHandle->SetPipeline(pipeline); + } + } + + // Save Properties if(auto matAsset = SHAssetManager::GetData(currentViewedMaterial)) { YAML::Emitter out; @@ -102,7 +121,20 @@ namespace SHADE currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as()); break; case SHADE::SHShaderBlockInterface::Variable::Type::INT: - currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as()); + { + Handle texture = SHResourceManager::LoadOrGet(PROP_NODE.as()); + // HACK: Need to split this out to a separate pass before loading the materials and subsequently, the scenes + gfxSystem->BuildTextures(); + if (texture) + { + matHandle->SetProperty(VARIABLE->offset, texture->TextureArrayIndex); + } + else + { + SHLOG_WARNING("[] Attempted to load invalid texture! Setting to 0."); + matHandle->SetProperty(VARIABLE->offset, 0); + } + } break; case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2: currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as()); @@ -136,12 +168,38 @@ namespace SHADE { /*if(!shaderModule) return;*/ - auto gfxSystem = SHSystemManager::GetSystem(); - auto interface = gfxSystem->GetDefaultMaterialInstance()->GetBaseMaterial()->GetShaderBlockInterface(); //auto interface = shaderModule->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA); - int const varCount = static_cast(interface->GetVariableCount()); + // Shader + bool shaderChanged = false; + const auto* SHADER_INFO = SHAssetManager::GetData(currentMatSpec->fragShader); + const std::string SHADER_NAME = SHADER_INFO ? SHADER_INFO->name : "Unknown Shader"; + ImGui::BeginDisabled(); + isDirty |= SHEditorWidgets::DragDropReadOnlyField + ( + "Fragment Shader", SHADER_NAME.data(), + [this]() { return currentMatSpec->fragShader; }, + [this](const AssetID& id) { currentMatSpec->fragShader = id; }, + SHDragDrop::DRAG_RESOURCE + ); + ImGui::EndDisabled(); + // Load the shader to access it's data + auto fragShader = SHResourceManager::LoadOrGet(currentMatSpec->fragShader); + if (!fragShader) + return; + + // Get interface for the shader combination + auto interface = fragShader->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface + ( + SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, + SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA + ); + if (!interface) + return; + + // Properties + int const varCount = static_cast(interface->GetVariableCount()); for (int i = 0; i < varCount; ++i) { auto variable = interface->GetVariable(i); diff --git a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h index c822829a..1e8d6a3e 100644 --- a/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h +++ b/SHADE_Engine/src/Graphics/Descriptors/SHVkDescriptorPool.h @@ -38,11 +38,11 @@ namespace SHADE /// std::vector Limits = { - { vk::DescriptorType::eCombinedImageSampler, 100 }, - { vk::DescriptorType::eUniformBuffer, 100 }, - { vk::DescriptorType::eUniformBufferDynamic, 100 }, - { vk::DescriptorType::eStorageImage, 100}, - { vk::DescriptorType::eStorageBufferDynamic, 100 } + { vk::DescriptorType::eCombinedImageSampler, 1000 }, + { vk::DescriptorType::eUniformBuffer, 1000 }, + { vk::DescriptorType::eUniformBufferDynamic, 1000 }, + { vk::DescriptorType::eStorageImage, 1000 }, + { vk::DescriptorType::eStorageBufferDynamic, 1000 } }; /// /// Maximum number of descriptor sets allowed diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp index 1829096f..2a2b66d4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.cpp @@ -43,6 +43,85 @@ namespace SHADE setAllDirtyFlags(); } + SHBatch::SHBatch(SHBatch&& rhs) + : device { rhs.device } + , pipeline { rhs.pipeline } + , referencedMatInstances { std::move(rhs.referencedMatInstances) } + , matBufferDirty { std::move(rhs.matBufferDirty) } + , subBatches { std::move(rhs.subBatches) } + , drawData { std::move(drawData) } + , transformData { std::move(rhs.transformData) } + , instancedIntegerData { std::move(rhs.instancedIntegerData) } + , matPropsData { std::move(rhs.matPropsData) } + , matPropsDataSize { rhs.matPropsDataSize } + , singleMatPropAlignedSize { rhs.singleMatPropAlignedSize } + , singleMatPropSize { rhs.singleMatPropSize } + , isCPUBuffersDirty { rhs.isCPUBuffersDirty } + , drawDataBuffer { rhs.drawDataBuffer } + , transformDataBuffer { rhs.transformDataBuffer } + , instancedIntegerBuffer { rhs.instancedIntegerBuffer } + , matPropsBuffer { rhs.matPropsBuffer } + , matPropsDescSet { rhs.matPropsDescSet } + { + rhs.drawDataBuffer = {}; + rhs.transformDataBuffer = {}; + rhs.instancedIntegerBuffer = {}; + rhs.matPropsBuffer = {}; + rhs.matPropsDescSet = {}; + } + + SHBatch& SHBatch::operator=(SHBatch&& rhs) + { + if (this == &rhs) + return *this; + + device = rhs.device ; + pipeline = rhs.pipeline ; + referencedMatInstances = std::move(rhs.referencedMatInstances); + matBufferDirty = std::move(rhs.matBufferDirty) ; + subBatches = std::move(rhs.subBatches) ; + drawData = std::move(drawData) ; + transformData = std::move(rhs.transformData) ; + instancedIntegerData = std::move(rhs.instancedIntegerData) ; + matPropsData = std::move(rhs.matPropsData) ; + matPropsDataSize = rhs.matPropsDataSize ; + singleMatPropAlignedSize = rhs.singleMatPropAlignedSize ; + singleMatPropSize = rhs.singleMatPropSize ; + isCPUBuffersDirty = rhs.isCPUBuffersDirty ; + drawDataBuffer = rhs.drawDataBuffer ; + transformDataBuffer = rhs.transformDataBuffer ; + instancedIntegerBuffer = rhs.instancedIntegerBuffer ; + matPropsBuffer = rhs.matPropsBuffer ; + matPropsDescSet = rhs.matPropsDescSet ; + + // Unset values + rhs.drawDataBuffer = {}; + rhs.transformDataBuffer = {}; + rhs.instancedIntegerBuffer = {}; + rhs.matPropsBuffer = {}; + rhs.matPropsDescSet = {}; + + return *this; + } + + SHBatch::~SHBatch() + { + // Free GPU buffers + for (int i = 0; i < SHGraphicsConstants::NUM_FRAME_BUFFERS; ++i) + { + if (drawDataBuffer[i]) + drawDataBuffer[i].Free(); + if (transformDataBuffer[i]) + transformDataBuffer[i].Free(); + if (instancedIntegerBuffer[i]) + instancedIntegerBuffer[i].Free(); + if (matPropsBuffer[i]) + matPropsBuffer[i].Free(); + if (matPropsDescSet[i]) + matPropsDescSet[i].Free(); + } + } + void SHBatch::Add(const SHRenderable* renderable) { // Ignore if null diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h index c9dd4eda..dd4d33fd 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHBatch.h @@ -71,6 +71,11 @@ namespace SHADE /* Constructor/Destructors */ /*-----------------------------------------------------------------------------*/ SHBatch(Handle pipeline); + SHBatch(const SHBatch&) = delete; + SHBatch(SHBatch&& rhs); + SHBatch& operator=(const SHBatch&) = delete; + SHBatch& operator=(SHBatch&& rhs); + ~SHBatch(); /*-----------------------------------------------------------------------------*/ /* Usage Functions */ @@ -117,7 +122,7 @@ namespace SHADE std::unique_ptr matPropsData; Byte matPropsDataSize = 0; Byte singleMatPropAlignedSize = 0; - Byte singleMatPropSize = 0; + Byte singleMatPropSize = 0; bool isCPUBuffersDirty = true; // GPU Buffers TripleBuffer drawDataBuffer; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp index b827652e..6760d937 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Batching/SHSuperBatch.cpp @@ -69,9 +69,9 @@ namespace SHADE batch->Remove(renderable); - // If batch is empty, remove batch - if (batch->IsEmpty()) - batches.erase(batch); + // TODO: If the pipeline is unloaded, we remove the batch + /*if (batch->IsEmpty() && !batch->GetPipeline()) + batches.erase(batch);*/ } void SHSuperBatch::Clear() noexcept diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index 15c8ec5d..ff265c49 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -570,13 +570,6 @@ namespace SHADE return; } - // Finalise all batches - for (auto vp : viewports) - for (auto renderer : vp->GetRenderers()) - { - renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame(), descPool); - } - // Resize auto windowDims = window->GetWindowSize(); if (renderContext.GetResizeAndReset()) @@ -591,6 +584,13 @@ namespace SHADE // #BackEndTest: For for the fence initialized by queue submit renderContext.WaitForFence(); + // Finalise all batches + for (auto vp : viewports) + for (auto renderer : vp->GetRenderers()) + { + renderer->GetRenderGraph()->FinaliseBatch(renderContext.GetCurrentFrame(), descPool); + } + // #BackEndTest: Acquire the next image in the swapchain available renderContext.AcquireNextIamge(); const uint32_t CURR_FRAME_IDX_2 = renderContext.GetCurrentFrame(); @@ -602,8 +602,6 @@ namespace SHADE if (currFrameData.cmdPoolHdls.empty()) throw std::runtime_error("No command pools available!"); currFrameData.cmdPoolHdls[0]->Reset(); - - } /***************************************************************************/ @@ -710,6 +708,11 @@ namespace SHADE return resourceManager.Create(materialInst->GetBaseMaterial()); } + std::pair, typename SHResourceHub::dense_iterator> SHGraphicsSystem::GetAllMaterialInstances() + { + return resourceManager.GetDenseAccess(); + } + void SHGraphicsSystem::RemoveMaterialInstance(Handle materialInstance) { resourceManager.Free(materialInstance); @@ -807,7 +810,7 @@ namespace SHADE void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept { - SHResourceManager::FinaliseChanges(); + // Begin rendering reinterpret_cast(system)->BeginRender(); } @@ -833,8 +836,38 @@ namespace SHADE void SHGraphicsSystem::EndRoutine::Execute(double) noexcept { reinterpret_cast(system)->EndRender(); + + // Reset all material isDirty + auto gfxSystem = reinterpret_cast(system); + auto [matBegin, matEnd] = gfxSystem->resourceManager.GetDenseAccess(); + for (auto iter = matBegin; iter != matEnd; ++iter) + { + iter->ClearChangeFlag(); + } } - + + SHGraphicsSystem::PrepareRenderRoutine::PrepareRenderRoutine() + : SHSystemRoutine("Graphics System Pre-Render", true) + {} + + void SHGraphicsSystem::PrepareRenderRoutine::Execute(double) noexcept + { + // Finish up, loading, unloading any resources + SHResourceManager::FinaliseChanges(); + + // Clean up and update all materials + auto gfxSystem = reinterpret_cast(system); + auto [matInstBegin, matInstEnd] = gfxSystem->resourceManager.GetDenseAccess(); + for (auto iter = matInstBegin; iter != matInstEnd; ++iter) + { + auto baseMat = iter->GetBaseMaterial(); + if (baseMat && baseMat->HasPipelineChanged()) + { + iter->ResetProperties(); + } + } + } + /*-----------------------------------------------------------------------------------*/ /* System Routine Functions - BatcherDispatcherRoutine */ /*-----------------------------------------------------------------------------------*/ @@ -844,11 +877,14 @@ namespace SHADE void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept { - auto& renderables = SHComponentManager::GetDense(); + auto& renderables = SHComponentManager::GetDense(); for (auto& renderable : renderables) { + // Check if the material instance is now unused + renderable.CleanUpMaterials(); + if (!renderable.HasChanged()) - continue; + continue; // Remove from the SuperBatch it is previously in (prevMat if mat has changed) Handle prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial(); @@ -857,9 +893,8 @@ namespace SHADE Handle oldSuperBatch = prevMaterial->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); oldSuperBatch->Remove(&renderable); } - - // Add to new SuperBatch if there is a material - // Add to new SuperBatch if there is a material and a mesh to render + + // Add to new SuperBatch if there is a material and a mesh to render Handle newMatInstance = renderable.GetMaterial(); if (newMatInstance && renderable.GetMesh()) { diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index a5a5ada0..2a186041 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -95,25 +95,31 @@ namespace SHADE class SH_API BeginRoutine final : public SHSystemRoutine { public: - BeginRoutine(); + BeginRoutine(); virtual void Execute(double dt) noexcept override final; }; class SH_API RenderRoutine final : public SHSystemRoutine { public: - RenderRoutine(); + RenderRoutine(); virtual void Execute(double dt) noexcept override final; }; class SH_API EndRoutine final : public SHSystemRoutine { public: - EndRoutine(); + EndRoutine(); + virtual void Execute(double dt) noexcept override final; + }; + class SH_API PrepareRenderRoutine final : public SHSystemRoutine + { + public: + PrepareRenderRoutine(); virtual void Execute(double dt) noexcept override final; }; class SH_API BatcherDispatcherRoutine final : public SHSystemRoutine { public: - BatcherDispatcherRoutine(); + BatcherDispatcherRoutine(); virtual void Execute(double dt) noexcept override final; }; @@ -156,6 +162,7 @@ namespace SHADE Handle AddOrGetBaseMaterialInstance(); Handle AddOrGetBaseMaterialInstance(Handle material); Handle AddMaterialInstanceCopy(Handle materialInst); + std::pair, typename SHResourceHub::dense_iterator> GetAllMaterialInstances(); void RemoveMaterialInstance(Handle materialInstance); Handle GetDefaultMaterial() { return defaultMaterial; } Handle GetDefaultMaterialInstance() { return AddOrGetBaseMaterialInstance(defaultMaterial); } @@ -166,10 +173,10 @@ namespace SHADE /*******************************************************************************/ /*! - \brief - Adds a mesh to the Mesh Library. But this does not mean that the meshes have - been added yet. A call to "BuildBuffers()" is required to transfer all - meshes into the GPU. + \brief + Adds a mesh to the Mesh Library. But this does not mean that the meshes have + been added yet. A call to "BuildBuffers()" is required to transfer all + meshes into the GPU. \param vertexCount Number of vertices in this Mesh. diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp index b27f48b9..7ca7c394 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.cpp @@ -6,91 +6,109 @@ #include "Graphics/Shaders/BlockInterface/SHShaderBlockInterface.h" #include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec4.h" +#include "ECS_Base/Managers/SHSystemManager.h" +#include "SHGraphicsSystem.h" +#include "SHMaterialInstance.h" namespace SHADE { - /*---------------------------------------------------------------------------------*/ - /* Pipeline Functions */ - /*---------------------------------------------------------------------------------*/ - void SHMaterial::SetPipeline(Handle _pipeline) - { - pipeline = _pipeline; + /*-----------------------------------------------------------------------------------*/ + /* Pipeline Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHMaterial::SetPipeline(Handle _pipeline) + { + // Reassignment, we ignore + if (_pipeline == pipeline) + return; - // Set up properties based on the pipeline - if (!pipeline) - { - // Clear memory and all that - propMemory.reset(); - return; - } + pipeline = _pipeline; - // Allocate memory for properties - const Handle SHADER_INFO = GetShaderBlockInterface(); - propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; - if (propMemorySize <= 0) - { - propMemory.reset(); - } - else - { - propMemory.reset(new char[propMemorySize]); - } - ResetProperties(); - } - - Handle SHMaterial::GetPipeline() const - { - return pipeline; - } - - /*---------------------------------------------------------------------------------*/ - /* Property Functions */ - /*---------------------------------------------------------------------------------*/ - void SHMaterial::ResetProperties() + // Set up properties based on the pipeline + if (pipeline) { - // Reset all the properties to default values - if (propMemory) - memset(propMemory.get(), 0, propMemorySize); + // Allocate memory for properties + const Handle SHADER_INFO = GetShaderBlockInterface(); + propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; + if (propMemorySize <= 0) + { + propMemory.reset(); + } + else + { + propMemory.reset(new char[propMemorySize]); + } + } + + // Reset since pipeline changed + ResetProperties(); - // Initialize Vectors to all 1.0 by default - const Handle SHADER_INFO = GetShaderBlockInterface(); - for (int i = 0; i < SHADER_INFO->GetVariableCount(); ++i) - { - const auto& VAR = SHADER_INFO->GetVariable(i); - switch (VAR->type) - { - case SHShaderBlockInterface::Variable::Type::VECTOR3: - setPropertyUnsafe(VAR->offset, SHVec3::One); - break; - case SHShaderBlockInterface::Variable::Type::VECTOR4: - setPropertyUnsafe(VAR->offset, SHVec4::One); - break; - } - } + // Mark changed so that we know to update dependent material instances + propertiesChanged = true; + } + + Handle SHMaterial::GetPipeline() const + { + return pipeline; + } + + /*-----------------------------------------------------------------------------------*/ + /* Property Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHMaterial::ResetProperties() + { + // Reset all the properties to default values + if (propMemory) + memset(propMemory.get(), 0, propMemorySize); + + // Initialize Vectors to all 1.0 by default + const Handle SHADER_INFO = GetShaderBlockInterface(); + for (int i = 0; i < SHADER_INFO->GetVariableCount(); ++i) + { + const auto& VAR = SHADER_INFO->GetVariable(i); + switch (VAR->type) + { + case SHShaderBlockInterface::Variable::Type::VECTOR3: + setPropertyUnsafe(VAR->offset, SHVec3::One); + break; + case SHShaderBlockInterface::Variable::Type::VECTOR4: + setPropertyUnsafe(VAR->offset, SHVec4::One); + break; + } } - void SHMaterial::ExportProperties(void* dest) const noexcept - { - if (propMemory) - memcpy(dest, propMemory.get(), propMemorySize); - } + propertiesChanged = true; + } - size_t SHMaterial::GetPropertiesMemorySize() const noexcept - { - const Handle SHADER_INFO = GetShaderBlockInterface(); - return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; - } + void SHMaterial::ExportProperties(void* dest) const noexcept + { + if (propMemory) + memcpy(dest, propMemory.get(), propMemorySize); + } - /*---------------------------------------------------------------------------------*/ - /* Helper Functions */ - /*---------------------------------------------------------------------------------*/ - Handle SHMaterial::GetShaderBlockInterface() const noexcept - { - return pipeline->GetPipelineLayout()->GetShaderBlockInterface - ( - SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, - SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, - vk::ShaderStageFlagBits::eFragment - ); - } + size_t SHMaterial::GetPropertiesMemorySize() const noexcept + { + const Handle SHADER_INFO = GetShaderBlockInterface(); + return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; + } + + /*-----------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------------*/ + Handle SHMaterial::GetShaderBlockInterface() const noexcept + { + return pipeline->GetPipelineLayout()->GetShaderBlockInterface + ( + SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, + SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA, + vk::ShaderStageFlagBits::eFragment + ); + } + + /*-----------------------------------------------------------------------------------*/ + /* Query Functions */ + /*-----------------------------------------------------------------------------------*/ + void SHMaterial::ClearChangeFlag() noexcept + { + propertiesChanged = false; + } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h index ac793089..c75692f2 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.h @@ -36,7 +36,7 @@ namespace SHADE Describes a Pipeline along with it's associated properties for this instance. */ /***********************************************************************************/ - class SH_API SHMaterial + class SH_API SHMaterial : public ISelfHandle { public: /*-----------------------------------------------------------------------------*/ @@ -68,6 +68,10 @@ namespace SHADE /* Query Functions */ /*-----------------------------------------------------------------------------*/ Handle GetShaderBlockInterface() const noexcept; + bool HasPipelineChanged() const noexcept { return pipelineChanged; } + bool HasPropertiesChanged() const noexcept { return propertiesChanged; } + bool HasChanged() const noexcept { return pipelineChanged || propertiesChanged; } + void ClearChangeFlag() noexcept; private: /*-----------------------------------------------------------------------------*/ @@ -76,6 +80,8 @@ namespace SHADE Handle pipeline; std::unique_ptr propMemory; Byte propMemorySize = 0; + bool propertiesChanged = true; + bool pipelineChanged = true; /*-----------------------------------------------------------------------------*/ /* Helper Functions */ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp index f81cfa5c..880fba69 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterial.hpp @@ -33,8 +33,7 @@ namespace SHADE } // Get offset and modify the memory directly - T* dataPtr = reinterpret_cast(propMemory.get() + PROP_INFO->offset); - *dataPtr = value; + setPropertyUnsafe(PROP_INFO->offset, value); } template @@ -85,6 +84,12 @@ namespace SHADE template void SHMaterial::setPropertyUnsafe(uint32_t memOffset, const T& value) { + // Size check + if (memOffset + sizeof(T) > propMemorySize) + { + throw std::runtime_error("Attempted to write to out of bounds MaterialInstance properties memory"); + } (*reinterpret_cast(propMemory.get() + memOffset)) = value; + propertiesChanged = true; } } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp index ff7084c2..7526538f 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.cpp @@ -31,11 +31,11 @@ namespace SHADE /*-----------------------------------------------------------------------------------*/ void SHMaterialInstance::ResetProperties() noexcept { - // Reset all the properties to default values memset(dataStore.get(), 0, dataStoreSize); overrideData.clear(); dataStore.reset(); + dataWasChanged = true; } void SHMaterialInstance::ExportProperties(void* dest) @@ -65,9 +65,17 @@ namespace SHADE dataWasChanged = false; } - /*---------------------------------------------------------------------------------*/ - /* Helper Functions */ - /*---------------------------------------------------------------------------------*/ + /*-----------------------------------------------------------------------------------*/ + /* Query Functions */ + /*-----------------------------------------------------------------------------------*/ + bool SHMaterialInstance::HasChanged() const noexcept + { + return dataWasChanged || (baseMaterial && baseMaterial->HasChanged()); + } + + /*-----------------------------------------------------------------------------------*/ + /* Helper Functions */ + /*-----------------------------------------------------------------------------------*/ Handle SHMaterialInstance::getShaderBlockInterface() const noexcept { return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h index 1e8136cc..57e3dfce 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.h @@ -69,7 +69,8 @@ namespace SHADE /* Getter Functions */ /*-----------------------------------------------------------------------------*/ Handle GetBaseMaterial() const noexcept { return baseMaterial; } - bool HasChanged() const noexcept { return dataWasChanged; } + bool HasChanged() const noexcept; + bool IsBlank() const noexcept { return overrideData.empty(); } // No overrides private: /*-----------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp index 3805cc72..7bd1c106 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHMaterialInstance.hpp @@ -59,6 +59,12 @@ namespace SHADE od.StoredDataOffset = lastInsertedData.StoredDataOffset + lastInsertedData.DataSize; } + // Size check + if (od.StoredDataOffset + sizeof(T) > dataStoreSize) + { + throw std::runtime_error("Attempted to write to out of bounds MaterialInstance properties memory"); + } + // Save the override data information overrideData.emplace_back(std::move(od)); existingOverride = overrideData.end() - 1; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp index c743c019..e22de5ab 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.cpp @@ -97,6 +97,14 @@ namespace SHADE return material; } + void SHRenderable::CleanUpMaterials() noexcept + { + if (material && material->IsBlank()) + { + SetMaterial(sharedMaterial); + } + } + /*-----------------------------------------------------------------------------------*/ /* Mesh Functions */ /*-----------------------------------------------------------------------------------*/ @@ -115,6 +123,20 @@ namespace SHADE return lightLayer; } + bool SHRenderable::HasChanged() const noexcept + { + if (matChanged || meshChanged) + return true; + + // If the underlying material has changed + auto mat = GetMaterial(); + if (mat) + { + return mat->HasChanged(); + } + return false; + } + /*-----------------------------------------------------------------------------------*/ /* Batcher Dispatcher Functions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h index 8893c43b..f1455ef4 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHRenderable.h @@ -53,6 +53,10 @@ namespace SHADE Handle GetModifiableMaterial(); Handle GetPrevMaterial() const noexcept { return oldMaterial; } bool HasMaterialChanged() const noexcept { return matChanged; } + /// + /// Clears the modifiable material if it is unused. + /// + void CleanUpMaterials() noexcept; /*-------------------------------------------------------------------------------*/ /* Mesh Functions */ @@ -70,7 +74,7 @@ namespace SHADE /*-------------------------------------------------------------------------------*/ /* Batcher Dispatcher Functions */ /*-------------------------------------------------------------------------------*/ - bool HasChanged() const noexcept { return matChanged || meshChanged; } // Whether or not the mesh or material has changed + bool HasChanged() const noexcept; // Whether or not the mesh or material has changed void ResetChangedFlag(); // TODO: Lock it so that only SHBatcherDispatcher can access this private: diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp index 495a3d37..05bd8813 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Pipeline/SHPipelineLibrary.cpp @@ -34,7 +34,7 @@ namespace SHADE { colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState { - .blendEnable = SHVkUtil::IsBlendCompatible (subpass->GetFormatFromAttachmentReference(att.attachment)) ? true : false, + .blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(att.attachment)), .srcColorBlendFactor = vk::BlendFactor::eSrcAlpha, .dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha, .colorBlendOp = vk::BlendOp::eAdd, diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp index d9c7f17a..e798bfe7 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraph.cpp @@ -129,11 +129,11 @@ namespace SHADE for (auto& predResource : prereq->attResources) { // if a predecessor's resource is used by this node, we want to copy the final layout from the pred to the initial of this node - if (uint64_t resourceID = predResource.GetId().Raw; node->resourceAttachmentMapping.contains(resourceID)) + if (uint64_t resourceID = predResource.GetId().Raw; node->resourceAttachmentMapping->contains(resourceID)) { // Get the resource's attachment index in BOTH the predecessor and the current node - uint32_t prereqResourceAttIndex = prereq->resourceAttachmentMapping[resourceID]; - uint32_t resourceAttIndex = node->resourceAttachmentMapping[resourceID]; + uint32_t prereqResourceAttIndex = prereq->resourceAttachmentMapping->at(resourceID); + uint32_t resourceAttIndex = node->resourceAttachmentMapping->at(resourceID); // Use the resource attachment index to get the attachment description in the renderpass auto& attDesc = node->attachmentDescriptions[resourceAttIndex]; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp index b3b5b58b..3f6be1d9 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.cpp @@ -124,7 +124,7 @@ namespace SHADE , framebuffers{} , prereqNodes{ std::move(predecessors) } , attachmentDescriptions{} - , resourceAttachmentMapping{} + , resourceAttachmentMapping { new std::unordered_map } , attResources{ } , subpasses{} , executed{ false } @@ -163,7 +163,7 @@ namespace SHADE if (attResources[i]->resourceTypeFlags & static_cast(SH_ATT_DESC_TYPE_FLAGS::COLOR_PRESENT)) containsSwapchainImage = true; - resourceAttachmentMapping.try_emplace(attResources[i].GetId().Raw, i); + resourceAttachmentMapping->try_emplace(attResources[i].GetId().Raw, i); } if (!containsSwapchainImage) @@ -254,7 +254,7 @@ namespace SHADE ( subpassName, graphStorage, GetHandle(), static_cast(subpasses.size()), - &resourceAttachmentMapping + resourceAttachmentMapping.get() ) ); subpassIndexing.try_emplace(subpassName, static_cast(subpasses.size()) - 1u); diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h index 4fdac45c..299578f2 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHRenderGraphNode.h @@ -60,7 +60,7 @@ namespace SHADE std::vector spDeps; //! For indexing resources fast - std::unordered_map resourceAttachmentMapping; + std::unique_ptr> resourceAttachmentMapping; //! For indexing subpasses std::map subpassIndexing; diff --git a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp index 2ed84d92..dfa5977b 100644 --- a/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp +++ b/SHADE_Engine/src/Graphics/RenderGraph/SHSubpass.cpp @@ -97,7 +97,7 @@ namespace SHADE colorReferences = std::move(rhs.colorReferences); depthReferences = std::move(rhs.depthReferences); inputReferences = std::move(rhs.inputReferences); - resourceAttachmentMapping = rhs.resourceAttachmentMapping; + resourceAttachmentMapping = std::move(rhs.resourceAttachmentMapping); descriptorSetLayout = rhs.descriptorSetLayout; exteriorDrawCalls = std::move(rhs.exteriorDrawCalls); graphStorage = rhs.graphStorage; diff --git a/SHADE_Engine/src/Graphics/SHVkUtil.cpp b/SHADE_Engine/src/Graphics/SHVkUtil.cpp index a9ac543f..3a405e0d 100644 --- a/SHADE_Engine/src/Graphics/SHVkUtil.cpp +++ b/SHADE_Engine/src/Graphics/SHVkUtil.cpp @@ -86,8 +86,16 @@ namespace SHADE { if (bufferHandle) { - // Resize - bufferHandle->ResizeReplace(size, src, size); + // Resize if we need to resize + if (bufferHandle->GetSizeStored() < size) + { + bufferHandle->ResizeReplace(size, src, size); + } + // Otherwise just copy the data over + else + { + bufferHandle->MapWriteUnmap(src, size, 0, 0); + } } else { @@ -113,8 +121,16 @@ namespace SHADE { if (bufferHandle) { - // Resize - bufferHandle->ResizeReplace(size, src, size); // TODO: Set to host visible method? + // Resize if we need to resize + if (bufferHandle->GetSizeStored() < size) + { + bufferHandle->ResizeReplace(size, src, size); + } + // Otherwise just copy the data over + else + { + bufferHandle->MapWriteUnmap(src, size, 0, 0); + } } else { diff --git a/SHADE_Engine/src/Resource/SHResourceLibrary.h b/SHADE_Engine/src/Resource/SHResourceLibrary.h index 46ae4572..a6f772fe 100644 --- a/SHADE_Engine/src/Resource/SHResourceLibrary.h +++ b/SHADE_Engine/src/Resource/SHResourceLibrary.h @@ -38,6 +38,11 @@ namespace SHADE class SHResourceLibrary : public SHResourceLibraryBase { public: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + using dense_iterator = typename SparseSet::dense_iterator; + /*-----------------------------------------------------------------------------*/ /* Constructor */ /*-----------------------------------------------------------------------------*/ @@ -74,6 +79,16 @@ namespace SHADE /// Read-only reference to the resource object. const T& Get(Handle handle) const; + /*-----------------------------------------------------------------------------*/ + /* Direct Dense Access Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Provides access to the dense array of the SparseSet. + /// These iterators should not be used to manipulate the underlying vector. + /// + /// Pair of begin and end iterators to the dense vector. + std::pair GetDenseAccess(); + private: /*-----------------------------------------------------------------------------*/ /* Data Members */ @@ -96,6 +111,12 @@ namespace SHADE class SHResourceHub final { public: + /*-----------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------*/ + template + using dense_iterator = typename SHResourceLibrary::dense_iterator; + /*-----------------------------------------------------------------------------*/ /* Constructors/Destructors */ /*-----------------------------------------------------------------------------*/ @@ -138,6 +159,18 @@ namespace SHADE template const T& Get(Handle handle) const; + /*-----------------------------------------------------------------------------*/ + /* Direct Dense Access Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Provides access to the dense array of the SparseSet. + /// These iterators should not be used to manipulate the underlying vector. + /// + /// Type of resource to access. + /// Pair of begin and end iterators to the dense vector. + template + std::pair, dense_iterator> GetDenseAccess(); + private: /*-----------------------------------------------------------------------------*/ /* Type Definition */ diff --git a/SHADE_Engine/src/Resource/SHResourceLibrary.hpp b/SHADE_Engine/src/Resource/SHResourceLibrary.hpp index 411f6bf5..98ad91a3 100644 --- a/SHADE_Engine/src/Resource/SHResourceLibrary.hpp +++ b/SHADE_Engine/src/Resource/SHResourceLibrary.hpp @@ -79,6 +79,15 @@ namespace SHADE return objects[handle.GetId().Data.Index]; } + /*---------------------------------------------------------------------------------*/ + /* ResourceLibrary - Direct Dense Access Functions */ + /*---------------------------------------------------------------------------------*/ + template + std::pair::dense_iterator, typename SHResourceLibrary::dense_iterator> SHResourceLibrary::GetDenseAccess() + { + return objects.GetDenseAccess(); + } + /*---------------------------------------------------------------------------------*/ /* ResourceLibrary - Helper Functions */ /*---------------------------------------------------------------------------------*/ @@ -105,7 +114,7 @@ namespace SHADE } /*---------------------------------------------------------------------------------*/ - /* ResourceManager - Usage Functions */ + /* ResourceHub - Usage Functions */ /*---------------------------------------------------------------------------------*/ template Handle SHResourceHub::Create(Args&&... args) @@ -132,7 +141,7 @@ namespace SHADE } /*-----------------------------------------------------------------------------*/ - /* ResourceManager - Helper Functions */ + /* ResourceHub - Helper Functions */ /*-----------------------------------------------------------------------------*/ template SHResourceLibrary& SHResourceHub::getLibrary() @@ -161,4 +170,13 @@ namespace SHADE { return const_cast(this).getLibrary(); } + + /*---------------------------------------------------------------------------------*/ + /* ResourceHub - Direct Dense Access Functions */ + /*---------------------------------------------------------------------------------*/ + template + std::pair, typename SHResourceHub::dense_iterator> SHResourceHub::GetDenseAccess() + { + return getLibrary().GetDenseAccess(); + } } diff --git a/SHADE_Engine/src/Resource/SHResourceManager.cpp b/SHADE_Engine/src/Resource/SHResourceManager.cpp index dad9fd9f..077835f5 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.cpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.cpp @@ -103,4 +103,17 @@ namespace SHADE return {}; } + + std::optional SHResourceManager::GetAssetName(Handle handle) + { + const Handle GENERIC_HANDLE = Handle(handle); + auto assetId = GetAssetID(GENERIC_HANDLE); + if (assetId.has_value()) + { + const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value()); + if (ASSET_INFO.has_value()) + return ASSET_INFO.value().name; + } + return {}; + } } diff --git a/SHADE_Engine/src/Resource/SHResourceManager.h b/SHADE_Engine/src/Resource/SHResourceManager.h index d660ada7..dae20f99 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.h +++ b/SHADE_Engine/src/Resource/SHResourceManager.h @@ -13,8 +13,6 @@ of DigiPen Institute of Technology is prohibited. // STL Includes #include - -namespace SHADE { class SHMaterial; } // Project Includes #include "SH_API.h" #include "SHResourceLibrary.h" @@ -31,17 +29,26 @@ namespace SHADE { class SHMaterial; } namespace SHADE { + /*-----------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-----------------------------------------------------------------------------------*/ + class SHMaterial; + + /*-----------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-----------------------------------------------------------------------------------*/ /// /// Template structs that maps a resource to their loaded asset representation type. /// template struct SHResourceLoader { using AssetType = void; }; - template<> struct SHResourceLoader { using AssetType = SHMeshData; }; + template<> struct SHResourceLoader { using AssetType = SHMeshData; }; template<> struct SHResourceLoader { using AssetType = SHTextureAsset; }; template<> struct SHResourceLoader { using AssetType = SHShaderAsset; }; template<> struct SHResourceLoader { using AssetType = SHMaterialAsset; }; template<> struct SHResourceLoader { using AssetType = SHMaterialSpec; }; -/// + + /// /// Static class responsible for loading and caching runtime resources from their /// serialised Asset IDs. /// @@ -57,9 +64,7 @@ namespace SHADE /// Note that for specific types, the retrieved Handle may not be valid until after /// FinaliseChanges() is called. /// - /// - /// Type of resource to load. - /// + /// Type of resource to load. /// Asset ID of the resource to load. /// Handle to a loaded runtime asset. template @@ -67,6 +72,17 @@ namespace SHADE template<> static inline Handle LoadOrGet(AssetID assetId); /// + /// Retrieves an existing loaded object of the specified type if it has already been + /// loaded prior. + /// + /// Type of resource to load. + /// Asset ID of the resource to retrieve. + /// + /// Handle to a loaded runtime asset. Null handle if not loaded before. + /// + template + static Handle Get(AssetID assetId); + /// /// Unloads an existing loaded asset. Attempting to unload an invalid Handle will /// simply do nothing except emit a warning. /// Faster than the untemplated version. @@ -114,6 +130,31 @@ namespace SHADE /// value. /// static std::optional GetAssetID(Handle handle); + /// + /// Retrieves the name associated with the AssetID that is associated with the + /// specified Handle. + /// Faster than the untemplated version. + /// + /// Type of resource to get the name of. + /// Handle to get the name of. + /// + /// Name for the specified Handle. If the Handle is invalid, there will be no + /// value. + /// + template + static std::optional GetAssetName(Handle handle); + /// + /// Retrieves the name associated with the AssetID that is associated with the + /// specified Handle. + /// Compared to the templated version, this function is slower as it requires + /// searching through the storage of all resource types. + /// + /// Handle to get the name of. + /// + /// Name for the specified Handle. If the Handle is invalid, there will be no + /// value. + /// + static std::optional GetAssetName(Handle handle); private: /*---------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Resource/SHResourceManager.hpp b/SHADE_Engine/src/Resource/SHResourceManager.hpp index 1e3b958d..d0488e66 100644 --- a/SHADE_Engine/src/Resource/SHResourceManager.hpp +++ b/SHADE_Engine/src/Resource/SHResourceManager.hpp @@ -93,6 +93,16 @@ namespace SHADE return handle; } + template + Handle SHResourceManager::Get(AssetID assetId) + { + auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap(); + if (typedHandleMap.get().contains(assetId)) + return Handle(typedHandleMap.get()[assetId]); + else + return Handle(); + } + template void SHResourceManager::Unload(Handle asset) { @@ -139,6 +149,18 @@ namespace SHADE return {}; } + template + std::optional SHADE::SHResourceManager::GetAssetName(Handle handle) + { + auto assetId = GetAssetID(handle); + if (assetId.has_value()) + { + const auto ASSET_INFO = SHAssetManager::GetAsset(assetId.value()); + if (ASSET_INFO.has_value()) + return ASSET_INFO.value().name; + } + return {}; + } /*-----------------------------------------------------------------------------------*/ /* Helper Functions */ diff --git a/SHADE_Engine/src/Resource/SparseSet.h b/SHADE_Engine/src/Resource/SparseSet.h index fb4a8311..3d763b01 100644 --- a/SHADE_Engine/src/Resource/SparseSet.h +++ b/SHADE_Engine/src/Resource/SparseSet.h @@ -49,6 +49,7 @@ namespace SHADE using const_pointer = const T*; using reference = T&; using const_reference = const T&; + using dense_iterator = typename std::vector::iterator; /*-----------------------------------------------------------------------------*/ /* Constructors/Destructors */ @@ -59,10 +60,6 @@ namespace SHADE SparseSet(); ~SparseSet() = default; - //// Disallow moving or copying - //SparseSet(const SparseSet&) = delete; - //SparseSet(SparseSet&&) = delete; - /*-----------------------------------------------------------------------------*/ /* Usage Functions */ /*-----------------------------------------------------------------------------*/ @@ -192,6 +189,16 @@ namespace SHADE /// const T& operator[](index_type idx) const; + /*-----------------------------------------------------------------------------*/ + /* Direct Dense Access Functions */ + /*-----------------------------------------------------------------------------*/ + /// + /// Provides access to the dense array of the SparseSet. + /// These iterators should not be used to manipulate the underlying vector. + /// + /// Pair of begin and end iterators to the dense vector. + std::pair GetDenseAccess(); + protected: /*-----------------------------------------------------------------------------*/ /* Constants */ diff --git a/SHADE_Engine/src/Resource/SparseSet.hpp b/SHADE_Engine/src/Resource/SparseSet.hpp index 816ca432..b6c7a511 100644 --- a/SHADE_Engine/src/Resource/SparseSet.hpp +++ b/SHADE_Engine/src/Resource/SparseSet.hpp @@ -143,4 +143,13 @@ namespace SHADE { return at(idx); } + + /*---------------------------------------------------------------------------------*/ + /* Direct Dense Access Functions */ + /*---------------------------------------------------------------------------------*/ + template + std::pair::dense_iterator, typename SparseSet::dense_iterator> SparseSet::GetDenseAccess() + { + return { denseArray.begin(), denseArray.end() }; + } } \ No newline at end of file