Added controls to adjust editor camera movement speed and turn speed #216

Merged
srishamharan merged 5 commits from SP3-4-Editor into main 2022-11-17 17:12:16 +08:00
36 changed files with 639 additions and 336 deletions
Showing only changes of commit 920e977232 - Show all commits

View File

@ -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
@ -182,45 +47,3 @@
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: ~

View File

@ -0,0 +1,50 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_ARB_shading_language_420pack : enable
#extension GL_EXT_nonuniform_qualifier : require
struct MatPropData
{
vec4 color;
int textureIndex;
float alpha;
vec3 beta;
};
layout(location = 0) in struct
{
vec4 vertPos; // location 0
vec2 uv; // location = 1
vec4 normal; // location = 2
} In;
// material stuff
layout(location = 3) flat in struct
{
int materialIndex;
uint eid;
uint lightLayerIndex;
} In2;
layout (set = 0, binding = 1) uniform sampler2D textures[]; // for textures (global)
layout (std430, set = 3, binding = 0) buffer MaterialProperties // For materials
{
MatPropData data[];
} MatProp;
layout(location = 0) out vec4 position;
layout(location = 1) out uint outEntityID;
layout(location = 2) out uint lightLayerIndices;
layout(location = 3) out vec4 normals;
layout(location = 4) out vec4 albedo;
void main()
{
position = In.vertPos;
normals = In.normal;
albedo = normals * texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) * MatProp.data[In2.materialIndex].color;
outEntityID = In2.eid;
lightLayerIndices = In2.lightLayerIndex;
}

Binary file not shown.

View File

@ -0,0 +1,3 @@
Name: Normals_FS
ID: 48689301
Type: 2

View File

@ -115,6 +115,7 @@ namespace Sandbox
SHSystemManager::RegisterRoutine<SHDebugDrawSystem, SHDebugDrawSystem::ProcessPointsRoutine>();
SHSystemManager::RegisterRoutine<SHScriptEngine, SHScriptEngine::GizmosDrawRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::PrepareRenderRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BatcherDispatcherRoutine>();
SHSystemManager::RegisterRoutine<SHGraphicsSystem, SHGraphicsSystem::BeginRoutine>();

View File

@ -155,6 +155,16 @@ namespace SHADE
return AssetType::INVALID;
}
std::optional<SHADE::SHAsset> 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.

View File

@ -50,6 +50,7 @@ namespace SHADE
* \return const& to unordered_map<AssetName, AssetID>
****************************************************************************/
static std::vector<SHAsset> GetAllAssets() noexcept;
static std::optional<SHAsset> GetAsset(AssetID id) noexcept;
static AssetType GetType(AssetID id) noexcept;

View File

@ -446,8 +446,8 @@ namespace SHADE
DrawContextMenu(component);
Handle<SHMesh> const& mesh = component->GetMesh();
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Mesh", std::to_string(SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0)).data(), [component]()
const auto MESH_NAME = SHResourceManager::GetAssetName<SHMesh>(mesh).value_or("");
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Mesh", MESH_NAME, [component]()
{
Handle<SHMesh> const& mesh = component->GetMesh();
return SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0);
@ -463,7 +463,9 @@ namespace SHADE
SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE);
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", mat ? std::to_string(SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0)).data() : "", [component]()
const auto MAT_NAME = mat ? SHResourceManager::GetAssetName<SHMaterial>(mat->GetBaseMaterial()).value_or("") : "";
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", MAT_NAME,
[component]()
{
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
if (!mat)

View File

@ -78,7 +78,26 @@ namespace SHADE
ImGui::BeginDisabled(!isDirty);
if(ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
{
//save
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
// Replace Material if it's been instantiated
auto matHandle = SHResourceManager::Get<SHMaterial>(currentViewedMaterial);
if (matHandle)
{
// - Get Shader Modules
auto vertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->vertexShader);
auto fragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(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<SHMaterialAsset>(currentViewedMaterial))
{
YAML::Emitter out;
@ -102,7 +121,20 @@ namespace SHADE
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<float>());
break;
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<int>());
{
Handle<SHTexture> texture = SHResourceManager::LoadOrGet<SHTexture>(PROP_NODE.as<int>());
// 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<SHVec2>());
@ -136,12 +168,38 @@ namespace SHADE
{
/*if(!shaderModule)
return;*/
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
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<int>(interface->GetVariableCount());
// Shader
bool shaderChanged = false;
const auto* SHADER_INFO = SHAssetManager::GetData<SHShaderAsset>(currentMatSpec->fragShader);
const std::string SHADER_NAME = SHADER_INFO ? SHADER_INFO->name : "Unknown Shader";
ImGui::BeginDisabled();
isDirty |= SHEditorWidgets::DragDropReadOnlyField<AssetID>
(
"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<SHVkShaderModule>(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<int>(interface->GetVariableCount());
for (int i = 0; i < varCount; ++i)
{
auto variable = interface->GetVariable(i);

View File

@ -38,11 +38,11 @@ namespace SHADE
/// </summary>
std::vector<vk::DescriptorPoolSize> 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 }
};
/// <summary>
/// Maximum number of descriptor sets allowed

View File

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

View File

@ -71,6 +71,11 @@ namespace SHADE
/* Constructor/Destructors */
/*-----------------------------------------------------------------------------*/
SHBatch(Handle<SHVkPipeline> pipeline);
SHBatch(const SHBatch&) = delete;
SHBatch(SHBatch&& rhs);
SHBatch& operator=(const SHBatch&) = delete;
SHBatch& operator=(SHBatch&& rhs);
~SHBatch();
/*-----------------------------------------------------------------------------*/
/* Usage Functions */

View File

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

View File

@ -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<SHMaterialInstance>(materialInst->GetBaseMaterial());
}
std::pair<typename SHResourceHub::dense_iterator<SHMaterialInstance>, typename SHResourceHub::dense_iterator<SHMaterialInstance>> SHGraphicsSystem::GetAllMaterialInstances()
{
return resourceManager.GetDenseAccess<SHMaterialInstance>();
}
void SHGraphicsSystem::RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance)
{
resourceManager.Free(materialInstance);
@ -807,7 +810,7 @@ namespace SHADE
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{
SHResourceManager::FinaliseChanges();
// Begin rendering
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
}
@ -833,6 +836,36 @@ namespace SHADE
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
// Reset all material isDirty
auto gfxSystem = reinterpret_cast<SHGraphicsSystem*>(system);
auto [matBegin, matEnd] = gfxSystem->resourceManager.GetDenseAccess<SHMaterial>();
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<SHGraphicsSystem*>(system);
auto [matInstBegin, matInstEnd] = gfxSystem->resourceManager.GetDenseAccess<SHMaterialInstance>();
for (auto iter = matInstBegin; iter != matInstEnd; ++iter)
{
auto baseMat = iter->GetBaseMaterial();
if (baseMat && baseMat->HasPipelineChanged())
{
iter->ResetProperties();
}
}
}
/*-----------------------------------------------------------------------------------*/
@ -847,6 +880,9 @@ namespace SHADE
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
for (auto& renderable : renderables)
{
// Check if the material instance is now unused
renderable.CleanUpMaterials();
if (!renderable.HasChanged())
continue;
@ -858,7 +894,6 @@ namespace SHADE
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
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
if (newMatInstance && renderable.GetMesh())

View File

@ -110,6 +110,12 @@ namespace SHADE
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:
@ -156,6 +162,7 @@ namespace SHADE
Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance();
Handle<SHMaterialInstance> AddOrGetBaseMaterialInstance(Handle<SHMaterial> material);
Handle<SHMaterialInstance> AddMaterialInstanceCopy(Handle<SHMaterialInstance> materialInst);
std::pair<typename SHResourceHub::dense_iterator<SHMaterialInstance>, typename SHResourceHub::dense_iterator<SHMaterialInstance>> GetAllMaterialInstances();
void RemoveMaterialInstance(Handle<SHMaterialInstance> materialInstance);
Handle<SHMaterial> GetDefaultMaterial() { return defaultMaterial; }
Handle<SHMaterialInstance> GetDefaultMaterialInstance() { return AddOrGetBaseMaterialInstance(defaultMaterial); }

View File

@ -6,24 +6,26 @@
#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<SHVkPipeline> _pipeline)
{
// Reassignment, we ignore
if (_pipeline == pipeline)
return;
pipeline = _pipeline;
// Set up properties based on the pipeline
if (!pipeline)
if (pipeline)
{
// Clear memory and all that
propMemory.reset();
return;
}
// Allocate memory for properties
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
@ -35,7 +37,13 @@ namespace SHADE
{
propMemory.reset(new char[propMemorySize]);
}
}
// Reset since pipeline changed
ResetProperties();
// Mark changed so that we know to update dependent material instances
propertiesChanged = true;
}
Handle<SHVkPipeline> SHMaterial::GetPipeline() const
@ -43,9 +51,9 @@ namespace SHADE
return pipeline;
}
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Property Functions */
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
void SHMaterial::ResetProperties()
{
// Reset all the properties to default values
@ -67,6 +75,8 @@ namespace SHADE
break;
}
}
propertiesChanged = true;
}
void SHMaterial::ExportProperties(void* dest) const noexcept
@ -81,9 +91,9 @@ namespace SHADE
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
}
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterial::GetShaderBlockInterface() const noexcept
{
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
@ -93,4 +103,12 @@ namespace SHADE
vk::ShaderStageFlagBits::eFragment
);
}
/*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
void SHMaterial::ClearChangeFlag() noexcept
{
propertiesChanged = false;
}
}

View File

@ -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<SHMaterial>
{
public:
/*-----------------------------------------------------------------------------*/
@ -68,6 +68,10 @@ namespace SHADE
/* Query Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> 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<SHVkPipeline> pipeline;
std::unique_ptr<char> propMemory;
Byte propMemorySize = 0;
bool propertiesChanged = true;
bool pipelineChanged = true;
/*-----------------------------------------------------------------------------*/
/* Helper Functions */

View File

@ -33,8 +33,7 @@ namespace SHADE
}
// Get offset and modify the memory directly
T* dataPtr = reinterpret_cast<T*>(propMemory.get() + PROP_INFO->offset);
*dataPtr = value;
setPropertyUnsafe(PROP_INFO->offset, value);
}
template<typename T>
@ -85,6 +84,12 @@ namespace SHADE
template<typename T>
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<T*>(propMemory.get() + memOffset)) = value;
propertiesChanged = true;
}
}

View File

@ -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;
}
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
bool SHMaterialInstance::HasChanged() const noexcept
{
return dataWasChanged || (baseMaterial && baseMaterial->HasChanged());
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterialInstance::getShaderBlockInterface() const noexcept
{
return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface

View File

@ -69,7 +69,8 @@ namespace SHADE
/* Getter Functions */
/*-----------------------------------------------------------------------------*/
Handle<SHMaterial> 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:
/*-----------------------------------------------------------------------------*/

View File

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

View File

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

View File

@ -53,6 +53,10 @@ namespace SHADE
Handle<SHMaterialInstance> GetModifiableMaterial();
Handle<SHMaterialInstance> GetPrevMaterial() const noexcept { return oldMaterial; }
bool HasMaterialChanged() const noexcept { return matChanged; }
/// <summary>
/// Clears the modifiable material if it is unused.
/// </summary>
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:

View File

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

View File

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

View File

@ -124,7 +124,7 @@ namespace SHADE
, framebuffers{}
, prereqNodes{ std::move(predecessors) }
, attachmentDescriptions{}
, resourceAttachmentMapping{}
, resourceAttachmentMapping { new std::unordered_map<uint64_t, uint32_t> }
, attResources{ }
, subpasses{}
, executed{ false }
@ -163,7 +163,7 @@ namespace SHADE
if (attResources[i]->resourceTypeFlags & static_cast<uint32_t>(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<uint32_t>(subpasses.size()),
&resourceAttachmentMapping
resourceAttachmentMapping.get()
)
);
subpassIndexing.try_emplace(subpassName, static_cast<uint32_t>(subpasses.size()) - 1u);

View File

@ -60,7 +60,7 @@ namespace SHADE
std::vector<vk::SubpassDependency> spDeps;
//! For indexing resources fast
std::unordered_map<uint64_t, uint32_t> resourceAttachmentMapping;
std::unique_ptr<std::unordered_map<uint64_t, uint32_t>> resourceAttachmentMapping;
//! For indexing subpasses
std::map<std::string, uint32_t> subpassIndexing;

View File

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

View File

@ -86,9 +86,17 @@ namespace SHADE
{
if (bufferHandle)
{
// Resize
// 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
{
// Create new
@ -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
{

View File

@ -38,6 +38,11 @@ namespace SHADE
class SHResourceLibrary : public SHResourceLibraryBase
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
using dense_iterator = typename SparseSet<T>::dense_iterator;
/*-----------------------------------------------------------------------------*/
/* Constructor */
/*-----------------------------------------------------------------------------*/
@ -74,6 +79,16 @@ namespace SHADE
/// <returns>Read-only reference to the resource object.</returns>
const T& Get(Handle<T> handle) const;
/*-----------------------------------------------------------------------------*/
/* Direct Dense Access Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Provides access to the dense array of the SparseSet.
/// These iterators should not be used to manipulate the underlying vector.
/// </summary>
/// <returns>Pair of begin and end iterators to the dense vector.</returns>
std::pair<dense_iterator, dense_iterator> GetDenseAccess();
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
@ -96,6 +111,12 @@ namespace SHADE
class SHResourceHub final
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
template<typename T>
using dense_iterator = typename SHResourceLibrary<T>::dense_iterator;
/*-----------------------------------------------------------------------------*/
/* Constructors/Destructors */
/*-----------------------------------------------------------------------------*/
@ -138,6 +159,18 @@ namespace SHADE
template<typename T>
const T& Get(Handle<T> handle) const;
/*-----------------------------------------------------------------------------*/
/* Direct Dense Access Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Provides access to the dense array of the SparseSet.
/// These iterators should not be used to manipulate the underlying vector.
/// </summary>
/// <typeparam name="T">Type of resource to access.</typeparam>
/// <returns>Pair of begin and end iterators to the dense vector.</returns>
template <typename T>
std::pair<dense_iterator<T>, dense_iterator<T>> GetDenseAccess();
private:
/*-----------------------------------------------------------------------------*/
/* Type Definition */

View File

@ -79,6 +79,15 @@ namespace SHADE
return objects[handle.GetId().Data.Index];
}
/*---------------------------------------------------------------------------------*/
/* ResourceLibrary - Direct Dense Access Functions */
/*---------------------------------------------------------------------------------*/
template<typename T>
std::pair<typename SHResourceLibrary<T>::dense_iterator, typename SHResourceLibrary<T>::dense_iterator> SHResourceLibrary<T>::GetDenseAccess()
{
return objects.GetDenseAccess();
}
/*---------------------------------------------------------------------------------*/
/* ResourceLibrary - Helper Functions */
/*---------------------------------------------------------------------------------*/
@ -105,7 +114,7 @@ namespace SHADE
}
/*---------------------------------------------------------------------------------*/
/* ResourceManager - Usage Functions */
/* ResourceHub - Usage Functions */
/*---------------------------------------------------------------------------------*/
template <typename T, typename ... Args>
Handle<T> SHResourceHub::Create(Args&&... args)
@ -132,7 +141,7 @@ namespace SHADE
}
/*-----------------------------------------------------------------------------*/
/* ResourceManager - Helper Functions */
/* ResourceHub - Helper Functions */
/*-----------------------------------------------------------------------------*/
template <typename T>
SHResourceLibrary<T>& SHResourceHub::getLibrary()
@ -161,4 +170,13 @@ namespace SHADE
{
return const_cast<SHResourceHub*>(this).getLibrary<T>();
}
/*---------------------------------------------------------------------------------*/
/* ResourceHub - Direct Dense Access Functions */
/*---------------------------------------------------------------------------------*/
template <typename T>
std::pair<typename SHResourceHub::dense_iterator<T>, typename SHResourceHub::dense_iterator<T>> SHResourceHub::GetDenseAccess()
{
return getLibrary<T>().GetDenseAccess();
}
}

View File

@ -103,4 +103,17 @@ namespace SHADE
return {};
}
std::optional<std::string> SHResourceManager::GetAssetName(Handle<void> 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 {};
}
}

View File

@ -13,8 +13,6 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes
#include <unordered_map>
namespace SHADE { class SHMaterial; }
// Project Includes
#include "SH_API.h"
#include "SHResourceLibrary.h"
@ -31,6 +29,14 @@ namespace SHADE { class SHMaterial; }
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Forward Declarations */
/*-----------------------------------------------------------------------------------*/
class SHMaterial;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/// <summary>
/// Template structs that maps a resource to their loaded asset representation type.
/// </summary>
@ -41,6 +47,7 @@ namespace SHADE
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
/// <summary>
/// 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.
/// </summary>
/// <typeparam name="ResourceType">
/// Type of resource to load.
/// </typeparam>
/// <typeparam name="ResourceType">Type of resource to load.</typeparam>
/// <param name="assetId">Asset ID of the resource to load.</param>
/// <returns>Handle to a loaded runtime asset.</returns>
template<typename ResourceType>
@ -67,6 +72,17 @@ namespace SHADE
template<>
static inline Handle<SHMaterial> LoadOrGet<SHMaterial>(AssetID assetId);
/// <summary>
/// Retrieves an existing loaded object of the specified type if it has already been
/// loaded prior.
/// </summary>
/// <typeparam name="ResourceType">Type of resource to load.</typeparam>
/// <param name="assetId">Asset ID of the resource to retrieve.</param>
/// <returns>
/// Handle to a loaded runtime asset. Null handle if not loaded before.
/// </returns>
template<typename ResourceType>
static Handle<ResourceType> Get(AssetID assetId);
/// <summary>
/// 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.
/// </return>
static std::optional<AssetID> GetAssetID(Handle<void> handle);
/// <summary>
/// Retrieves the name associated with the AssetID that is associated with the
/// specified Handle.
/// Faster than the untemplated version.
/// </summary>
/// <typeparam name="ResourceType">Type of resource to get the name of.</typeparam>
/// <param name="handle">Handle to get the name of.</param>
/// <return>
/// Name for the specified Handle. If the Handle is invalid, there will be no
/// value.
/// </return>
template<typename T>
static std::optional<std::string> GetAssetName(Handle<T> handle);
/// <summary>
/// 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.
/// </summary>
/// <param name="handle">Handle to get the name of.</param>
/// <return>
/// Name for the specified Handle. If the Handle is invalid, there will be no
/// value.
/// </return>
static std::optional<std::string> GetAssetName(Handle<void> handle);
private:
/*---------------------------------------------------------------------------------*/

View File

@ -93,6 +93,16 @@ namespace SHADE
return handle;
}
template<typename ResourceType>
Handle<ResourceType> SHResourceManager::Get(AssetID assetId)
{
auto [typedHandleMap, typedAssetIdMap] = getAssetHandleMap<ResourceType>();
if (typedHandleMap.get().contains(assetId))
return Handle<ResourceType>(typedHandleMap.get()[assetId]);
else
return Handle<ResourceType>();
}
template<typename ResourceType>
void SHResourceManager::Unload(Handle<ResourceType> asset)
{
@ -139,6 +149,18 @@ namespace SHADE
return {};
}
template<typename T>
std::optional<std::string> SHADE::SHResourceManager::GetAssetName(Handle<T> handle)
{
auto assetId = GetAssetID<T>(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 */

View File

@ -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<T>::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
/// </exception>
const T& operator[](index_type idx) const;
/*-----------------------------------------------------------------------------*/
/* Direct Dense Access Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Provides access to the dense array of the SparseSet.
/// These iterators should not be used to manipulate the underlying vector.
/// </summary>
/// <returns>Pair of begin and end iterators to the dense vector.</returns>
std::pair<dense_iterator, dense_iterator> GetDenseAccess();
protected:
/*-----------------------------------------------------------------------------*/
/* Constants */

View File

@ -143,4 +143,13 @@ namespace SHADE
{
return at(idx);
}
/*---------------------------------------------------------------------------------*/
/* Direct Dense Access Functions */
/*---------------------------------------------------------------------------------*/
template<typename T>
std::pair<typename SparseSet<T>::dense_iterator, typename SparseSet<T>::dense_iterator> SparseSet<T>::GetDenseAccess()
{
return { denseArray.begin(), denseArray.end() };
}
}