Added full support for runtime editing of material properties #215
|
@ -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: ~
|
|
@ -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.
|
@ -0,0 +1,3 @@
|
|||
Name: Normals_FS
|
||||
ID: 48689301
|
||||
Type: 2
|
|
@ -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>();
|
||||
|
||||
|
|
|
@ -143,7 +143,17 @@ namespace SHADE
|
|||
return result;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
||||
/****************************************************************************
|
||||
* \brief Create record for new resource. CAN ONLY CREATE FOR CUSTOM
|
||||
|
|
|
@ -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);
|
||||
|
@ -458,13 +458,15 @@ 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]()
|
||||
{
|
||||
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
|
||||
if(!mat)
|
||||
return static_cast<AssetID>(0);
|
||||
return SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0);
|
||||
},
|
||||
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)
|
||||
return static_cast<AssetID>(0);
|
||||
return SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0);
|
||||
},
|
||||
[component](AssetID const& id)
|
||||
{
|
||||
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
@ -117,7 +122,7 @@ namespace SHADE
|
|||
std::unique_ptr<char> matPropsData;
|
||||
Byte matPropsDataSize = 0;
|
||||
Byte singleMatPropAlignedSize = 0;
|
||||
Byte singleMatPropSize = 0;
|
||||
Byte singleMatPropSize = 0;
|
||||
bool isCPUBuffersDirty = true;
|
||||
// GPU Buffers
|
||||
TripleBuffer drawDataBuffer;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -844,9 +877,12 @@ namespace SHADE
|
|||
|
||||
void SHGraphicsSystem::BatcherDispatcherRoutine::Execute(double) noexcept
|
||||
{
|
||||
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
|
||||
auto& renderables = SHComponentManager::GetDense<SHRenderable>();
|
||||
for (auto& renderable : renderables)
|
||||
{
|
||||
// Check if the material instance is now unused
|
||||
renderable.CleanUpMaterials();
|
||||
|
||||
if (!renderable.HasChanged())
|
||||
continue;
|
||||
|
||||
|
@ -858,8 +894,7 @@ 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
|
||||
// Add to new SuperBatch if there is a material and a mesh to render
|
||||
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
|
||||
if (newMatInstance && renderable.GetMesh())
|
||||
{
|
||||
|
|
|
@ -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<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); }
|
||||
|
@ -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.
|
||||
|
|
|
@ -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<SHVkPipeline> _pipeline)
|
||||
{
|
||||
pipeline = _pipeline;
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Pipeline Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void SHMaterial::SetPipeline(Handle<SHVkPipeline> _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<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
||||
if (propMemorySize <= 0)
|
||||
{
|
||||
propMemory.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
propMemory.reset(new char[propMemorySize]);
|
||||
}
|
||||
ResetProperties();
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> 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);
|
||||
|
||||
// Initialize Vectors to all 1.0 by default
|
||||
const Handle<SHShaderBlockInterface> 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;
|
||||
}
|
||||
}
|
||||
// Allocate memory for properties
|
||||
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
||||
if (propMemorySize <= 0)
|
||||
{
|
||||
propMemory.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
propMemory.reset(new char[propMemorySize]);
|
||||
}
|
||||
}
|
||||
|
||||
void SHMaterial::ExportProperties(void* dest) const noexcept
|
||||
{
|
||||
if (propMemory)
|
||||
memcpy(dest, propMemory.get(), propMemorySize);
|
||||
}
|
||||
// Reset since pipeline changed
|
||||
ResetProperties();
|
||||
|
||||
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
|
||||
{
|
||||
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
||||
}
|
||||
// Mark changed so that we know to update dependent material instances
|
||||
propertiesChanged = true;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHShaderBlockInterface> SHMaterial::GetShaderBlockInterface() const noexcept
|
||||
{
|
||||
return pipeline->GetPipelineLayout()->GetShaderBlockInterface
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE,
|
||||
SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA,
|
||||
vk::ShaderStageFlagBits::eFragment
|
||||
);
|
||||
}
|
||||
Handle<SHVkPipeline> 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<SHShaderBlockInterface> 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;
|
||||
}
|
||||
}
|
||||
|
||||
propertiesChanged = true;
|
||||
}
|
||||
|
||||
void SHMaterial::ExportProperties(void* dest) const noexcept
|
||||
{
|
||||
if (propMemory)
|
||||
memcpy(dest, propMemory.get(), propMemorySize);
|
||||
}
|
||||
|
||||
size_t SHMaterial::GetPropertiesMemorySize() const noexcept
|
||||
{
|
||||
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
|
||||
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
Handle<SHShaderBlockInterface> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<SHShaderBlockInterface> SHMaterialInstance::getShaderBlockInterface() const noexcept
|
||||
{
|
||||
return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface
|
||||
|
|
|
@ -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:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,17 +29,26 @@ 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>
|
||||
template<typename T = void>
|
||||
struct SHResourceLoader { using AssetType = void; };
|
||||
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshData; };
|
||||
template<> struct SHResourceLoader<SHMesh> { using AssetType = SHMeshData; };
|
||||
template<> struct SHResourceLoader<SHTexture> { using AssetType = SHTextureAsset; };
|
||||
template<> struct SHResourceLoader<SHVkShaderModule> { using AssetType = SHShaderAsset; };
|
||||
template<> struct SHResourceLoader<SHMaterialSpec> { using AssetType = SHMaterialAsset; };
|
||||
template<> struct SHResourceLoader<SHMaterial> { using AssetType = SHMaterialSpec; };
|
||||
/// <summary>
|
||||
|
||||
/// <summary>
|
||||
/// Static class responsible for loading and caching runtime resources from their
|
||||
/// serialised Asset IDs.
|
||||
/// </summary>
|
||||
|
@ -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:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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() };
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue