Material data on the GPU is now updated when material data changes
This commit is contained in:
parent
32278e1564
commit
759c87e2a1
|
@ -58,6 +58,9 @@ namespace SHADE
|
|||
// Add renderable in
|
||||
subBatch->Renderables.insert(renderable);
|
||||
|
||||
// Also add material instance in
|
||||
referencedMatInstances.insert(renderable->GetMaterial());
|
||||
|
||||
// Mark all as dirty
|
||||
setAllDirtyFlags();
|
||||
}
|
||||
|
@ -76,6 +79,22 @@ namespace SHADE
|
|||
|
||||
subBatch->Renderables.erase(renderable);
|
||||
|
||||
// Check if other renderables in subBatches contain the same material instance
|
||||
bool matUnused = true;
|
||||
for (const auto& subBatch : subBatches)
|
||||
for (const auto& rend : subBatch.Renderables)
|
||||
{
|
||||
if (rend->GetMaterial() == renderable->GetMaterial())
|
||||
{
|
||||
matUnused = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Material is no longer in this library, so we remove it
|
||||
if (matUnused)
|
||||
referencedMatInstances.erase(renderable->GetMaterial());
|
||||
|
||||
// Mark all as dirty
|
||||
for (bool& dirt : isDirty)
|
||||
dirt = true;
|
||||
|
@ -101,6 +120,62 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHBatch::UpdateMaterialBuffer(uint32_t frameIndex)
|
||||
{
|
||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||
{
|
||||
SHLOG_WARNING("[SHBatch] Attempted to update transform buffers with an invalid frame index.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there are even material properties to update
|
||||
if (!matPropsData)
|
||||
return;
|
||||
|
||||
// Check if any materials have changed
|
||||
bool hasChanged = false;
|
||||
for (auto material : referencedMatInstances)
|
||||
{
|
||||
if (material->HasChanged())
|
||||
{
|
||||
hasChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We need to update all the material buffers if the materials have changed
|
||||
if (hasChanged)
|
||||
{
|
||||
for (auto& dirt : matBufferDirty)
|
||||
dirt = true;
|
||||
}
|
||||
|
||||
// Check if this frame's buffer is dirty
|
||||
if (!matBufferDirty[frameIndex])
|
||||
return;
|
||||
|
||||
// Build CPI Buffer
|
||||
uint32_t nextInstanceIndex = 0;
|
||||
char* propsCurrPtr = matPropsData.get();
|
||||
for (auto& subBatch : subBatches)
|
||||
for (const SHRenderable* renderable : subBatch.Renderables)
|
||||
{
|
||||
|
||||
renderable->GetMaterial()->ExportProperties(propsCurrPtr);
|
||||
propsCurrPtr += singleMatPropSize;
|
||||
}
|
||||
|
||||
// Transfer to GPU
|
||||
SHVkUtil::EnsureBufferAndCopyHostVisibleData
|
||||
(
|
||||
device, matPropsBuffer[frameIndex], matPropsData.get(), static_cast<uint32_t>(matPropsDataSize),
|
||||
vk::BufferUsageFlagBits::eStorageBuffer
|
||||
);
|
||||
|
||||
// This frame is updated
|
||||
matBufferDirty[frameIndex] = false;
|
||||
}
|
||||
|
||||
void SHBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
||||
{
|
||||
if (frameIndex >= SHGraphicsConstants::NUM_FRAME_BUFFERS)
|
||||
|
@ -169,7 +244,6 @@ namespace SHADE
|
|||
vk::ShaderStageFlagBits::eFragment
|
||||
);
|
||||
const bool EMPTY_MAT_PROPS = !SHADER_INFO;
|
||||
Byte singleMatPropSize = 0;
|
||||
Byte matPropTotalBytes = 0;
|
||||
if (!EMPTY_MAT_PROPS)
|
||||
{
|
||||
|
@ -252,6 +326,9 @@ namespace SHADE
|
|||
}
|
||||
|
||||
isDirty[frameIndex] = false;
|
||||
|
||||
// Save logical device
|
||||
this->device = device;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace SHADE
|
|||
class SHMesh;
|
||||
class SHRenderable;
|
||||
class SHVkLogicalDevice;
|
||||
class SHMaterialInstance;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -73,6 +74,7 @@ namespace SHADE
|
|||
void Add(const SHRenderable* renderable);
|
||||
void Remove(const SHRenderable* renderable);
|
||||
void Clear();
|
||||
void UpdateMaterialBuffer(uint32_t frameIndex);
|
||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex);
|
||||
|
@ -86,8 +88,12 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
// Resources
|
||||
Handle<SHVkLogicalDevice> device;
|
||||
// Batch Properties
|
||||
Handle<SHVkPipeline> pipeline;
|
||||
std::unordered_set<Handle<SHMaterialInstance>> referencedMatInstances;
|
||||
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> matBufferDirty;
|
||||
// Batch Tree
|
||||
std::vector<SHSubBatch> subBatches;
|
||||
std::array<bool, SHGraphicsConstants::NUM_FRAME_BUFFERS> isDirty;
|
||||
|
@ -96,6 +102,7 @@ namespace SHADE
|
|||
std::vector<SHMatrix> transformData;
|
||||
std::unique_ptr<char> matPropsData;
|
||||
Byte matPropsDataSize = 0;
|
||||
Byte singleMatPropSize = 0;
|
||||
bool isCPUBuffersDirty = true;
|
||||
// GPU Buffers
|
||||
std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS> drawDataBuffer;
|
||||
|
|
|
@ -109,11 +109,11 @@ namespace SHADE
|
|||
superBatches.clear();
|
||||
}
|
||||
|
||||
void SHBatcher::UpdateTransformBuffer(uint32_t frameIndex)
|
||||
{
|
||||
void SHBatcher::UpdateBuffers(uint32_t frameIndex)
|
||||
{
|
||||
for (auto& batch : superBatches)
|
||||
{
|
||||
batch->UpdateTransformBuffer(frameIndex);
|
||||
batch->UpdateBuffers(frameIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace SHADE
|
|||
void RemoveFromBatch(SHRenderable const* renderable);
|
||||
void FinaliseBatches(Handle<SHVkLogicalDevice> device, uint32_t frameIndex);
|
||||
void ClearBatches();
|
||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void UpdateBuffers(uint32_t frameIndex);
|
||||
void RegisterSuperBatch(Handle<SHSuperBatch> superBatch);
|
||||
void DeregisterSuperBatch(Handle<SHSuperBatch> superBatch);
|
||||
|
||||
|
|
|
@ -78,10 +78,11 @@ namespace SHADE
|
|||
batches.clear();
|
||||
}
|
||||
|
||||
void SHSuperBatch::UpdateTransformBuffer(uint32_t frameIndex)
|
||||
void SHSuperBatch::UpdateBuffers(uint32_t frameIndex)
|
||||
{
|
||||
for (auto& batch : batches)
|
||||
{
|
||||
batch.UpdateMaterialBuffer(frameIndex);
|
||||
batch.UpdateTransformBuffer(frameIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace SHADE
|
|||
void Add(const SHRenderable* renderable) noexcept;
|
||||
void Remove(const SHRenderable* renderable) noexcept;
|
||||
void Clear() noexcept;
|
||||
void UpdateTransformBuffer(uint32_t frameIndex);
|
||||
void UpdateBuffers(uint32_t frameIndex);
|
||||
void Build(Handle<SHVkLogicalDevice> device, uint32_t frameIndex) noexcept;
|
||||
void Draw(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace SHADE
|
|||
dataStore.reset();
|
||||
}
|
||||
|
||||
void SHMaterialInstance::ExportProperties(void* dest) const
|
||||
void SHMaterialInstance::ExportProperties(void* dest)
|
||||
{
|
||||
assert(dataStore != nullptr);
|
||||
|
||||
|
@ -62,6 +62,9 @@ namespace SHADE
|
|||
const auto DATA_OFFSET = variable->offset;
|
||||
memcpy(static_cast<char*>(dest) + DATA_OFFSET, dataStore.get() + data.StoredDataOffset, data.DataSize);
|
||||
}
|
||||
|
||||
// Data was exported so unflag
|
||||
dataWasChanged = false;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -62,12 +62,13 @@ namespace SHADE
|
|||
template<typename T>
|
||||
const T& GetProperty(const std::string& key) const;
|
||||
void ResetProperties() noexcept;
|
||||
void ExportProperties(void* dest) const;
|
||||
void ExportProperties(void* dest);
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHMaterial> GetBaseMaterial() const { return baseMaterial; }
|
||||
Handle<SHMaterial> GetBaseMaterial() const noexcept { return baseMaterial; }
|
||||
bool HasChanged() const noexcept { return dataWasChanged; }
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -77,6 +78,7 @@ namespace SHADE
|
|||
std::vector<OverrideData> overrideData;
|
||||
std::unique_ptr<char> dataStore;
|
||||
size_t dataStoreSize = 0;
|
||||
bool dataWasChanged = false;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
|
|
|
@ -53,6 +53,9 @@ namespace SHADE
|
|||
|
||||
// Save the override data information
|
||||
overrideData.emplace_back(std::move(od));
|
||||
|
||||
// Flag
|
||||
dataWasChanged = true;
|
||||
}
|
||||
template<typename T>
|
||||
T& SHMaterialInstance::GetProperty(const std::string& key)
|
||||
|
|
|
@ -348,8 +348,8 @@ namespace SHADE
|
|||
|
||||
void SHSubpass::Execute(Handle<SHVkCommandBuffer>& commandBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
// Ensure correct transforms are provided
|
||||
superBatch->UpdateTransformBuffer(frameIndex);
|
||||
// Ensure updated transforms and materials are provided
|
||||
superBatch->UpdateBuffers(frameIndex);
|
||||
|
||||
// Draw all the batches
|
||||
superBatch->Draw(commandBuffer, frameIndex);
|
||||
|
|
Loading…
Reference in New Issue