Added full support for runtime editing of material properties #215

Merged
Pycorax merged 14 commits from SP3-1-MaterialEditSupport into main 2022-11-17 09:22:53 +08:00
5 changed files with 56 additions and 46 deletions
Showing only changes of commit 506b8836fe - Show all commits

View File

@ -12,9 +12,9 @@
namespace SHADE namespace SHADE
{ {
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Pipeline Functions */ /* Pipeline Functions */
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHMaterial::SetPipeline(Handle<SHVkPipeline> _pipeline) void SHMaterial::SetPipeline(Handle<SHVkPipeline> _pipeline)
{ {
// Reassignment, we ignore // Reassignment, we ignore
@ -24,13 +24,8 @@ namespace SHADE
pipeline = _pipeline; pipeline = _pipeline;
// Set up properties based on the pipeline // Set up properties based on the pipeline
if (!pipeline) if (pipeline)
{ {
// Clear memory and all that
propMemory.reset();
return;
}
// Allocate memory for properties // Allocate memory for properties
const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface(); const Handle<SHShaderBlockInterface> SHADER_INFO = GetShaderBlockInterface();
propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; propMemorySize = SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
@ -42,22 +37,13 @@ namespace SHADE
{ {
propMemory.reset(new char[propMemorySize]); propMemory.reset(new char[propMemorySize]);
} }
}
// Reset since pipeline changed
ResetProperties(); ResetProperties();
// Search all material instances for instances that use this base material // Mark changed so that we know to update dependent material instances
// to force a reset of properties propertiesChanged = true;
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem)
{
auto [matInstBegin, matInstEnd] = gfxSystem->GetAllMaterialInstances();
for (auto iter = matInstBegin; iter != matInstEnd; ++iter)
{
if (iter->GetBaseMaterial() == GetHandle())
{
iter->ResetProperties();
}
}
}
} }
Handle<SHVkPipeline> SHMaterial::GetPipeline() const Handle<SHVkPipeline> SHMaterial::GetPipeline() const
@ -65,9 +51,9 @@ namespace SHADE
return pipeline; return pipeline;
} }
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Property Functions */ /* Property Functions */
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHMaterial::ResetProperties() void SHMaterial::ResetProperties()
{ {
// Reset all the properties to default values // Reset all the properties to default values
@ -89,6 +75,8 @@ namespace SHADE
break; break;
} }
} }
propertiesChanged = true;
} }
void SHMaterial::ExportProperties(void* dest) const noexcept void SHMaterial::ExportProperties(void* dest) const noexcept
@ -103,9 +91,9 @@ namespace SHADE
return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0; return SHADER_INFO ? SHADER_INFO->GetBytesRequired() : 0;
} }
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterial::GetShaderBlockInterface() const noexcept Handle<SHShaderBlockInterface> SHMaterial::GetShaderBlockInterface() const noexcept
{ {
return pipeline->GetPipelineLayout()->GetShaderBlockInterface return pipeline->GetPipelineLayout()->GetShaderBlockInterface
@ -115,4 +103,12 @@ namespace SHADE
vk::ShaderStageFlagBits::eFragment vk::ShaderStageFlagBits::eFragment
); );
} }
/*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
void SHMaterial::ClearChangeFlag() noexcept
{
propertiesChanged = false;
}
} }

View File

@ -68,6 +68,10 @@ namespace SHADE
/* Query Functions */ /* Query Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> GetShaderBlockInterface() const noexcept; 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: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -76,6 +80,8 @@ namespace SHADE
Handle<SHVkPipeline> pipeline; Handle<SHVkPipeline> pipeline;
std::unique_ptr<char> propMemory; std::unique_ptr<char> propMemory;
Byte propMemorySize = 0; Byte propMemorySize = 0;
bool propertiesChanged = true;
bool pipelineChanged = true;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */

View File

@ -33,8 +33,7 @@ namespace SHADE
} }
// Get offset and modify the memory directly // Get offset and modify the memory directly
T* dataPtr = reinterpret_cast<T*>(propMemory.get() + PROP_INFO->offset); setPropertyUnsafe(PROP_INFO->offset, value);
*dataPtr = value;
} }
template<typename T> template<typename T>
@ -86,5 +85,6 @@ namespace SHADE
void SHMaterial::setPropertyUnsafe(uint32_t memOffset, const T& value) void SHMaterial::setPropertyUnsafe(uint32_t memOffset, const T& value)
{ {
(*reinterpret_cast<T*>(propMemory.get() + memOffset)) = value; (*reinterpret_cast<T*>(propMemory.get() + memOffset)) = value;
propertiesChanged = true;
} }
} }

View File

@ -62,12 +62,20 @@ namespace SHADE
} }
// Data was exported so unflag // Data was exported so unflag
//dataWasChanged = false; dataWasChanged = false;
} }
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Query Functions */
/*-----------------------------------------------------------------------------------*/
bool SHMaterialInstance::HasChanged() const noexcept
{
return dataWasChanged || (baseMaterial && baseMaterial->HasChanged());
}
/*-----------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*---------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
Handle<SHShaderBlockInterface> SHMaterialInstance::getShaderBlockInterface() const noexcept Handle<SHShaderBlockInterface> SHMaterialInstance::getShaderBlockInterface() const noexcept
{ {
return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface return baseMaterial->GetPipeline()->GetPipelineLayout()->GetShaderBlockInterface

View File

@ -69,7 +69,7 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHMaterial> GetBaseMaterial() const noexcept { return baseMaterial; } 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 bool IsBlank() const noexcept { return overrideData.empty(); } // No overrides
private: private: