fix: alot of stuff changed. Mostly bugfixxes / architechture changes
This commit is contained in:
@@ -4,36 +4,58 @@
|
||||
#include <destrum/Graphics/Util.h>
|
||||
|
||||
#include "spdlog/spdlog.h"
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
void MaterialCache::init(
|
||||
GfxDevice& gfxDevice,
|
||||
MaterialDefaultTextures defaults)
|
||||
{
|
||||
defaultTextures = defaults;
|
||||
try {
|
||||
defaultTextures = defaults;
|
||||
device = &gfxDevice;
|
||||
|
||||
materialDataBuffer = gfxDevice.createBuffer(
|
||||
MAX_MATERIALS * sizeof(MaterialData),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT);
|
||||
materialDataBuffer = gfxDevice.createBuffer(
|
||||
MAX_MATERIALS * sizeof(MaterialData),
|
||||
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT,
|
||||
VMA_MEMORY_USAGE_CPU_TO_GPU);
|
||||
|
||||
vkutil::addDebugLabel(
|
||||
gfxDevice.getDevice(),
|
||||
materialDataBuffer.buffer,
|
||||
"material data");
|
||||
vkutil::addDebugLabel(
|
||||
gfxDevice.getDevice(),
|
||||
materialDataBuffer.buffer,
|
||||
"material data");
|
||||
|
||||
Material placeholderMaterial{};
|
||||
placeholderMaterial.name = "PLACEHOLDER_MATERIAL";
|
||||
placeholderMaterial.diffuseTexture = defaultTextures.white;
|
||||
Material placeholderMaterial{};
|
||||
placeholderMaterial.name = "PLACEHOLDER_MATERIAL";
|
||||
placeholderMaterial.diffuseTexture = defaultTextures.white;
|
||||
|
||||
placeholderMaterialId = addMaterial(placeholderMaterial);
|
||||
placeholderMaterialId = addMaterial(placeholderMaterial);
|
||||
gfxDevice.getMemoryManager().flushAllocation(materialDataBuffer);
|
||||
} catch (...) {
|
||||
cleanup(gfxDevice);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialCache::cleanup(GfxDevice& gfxDevice)
|
||||
{
|
||||
gfxDevice.destroyBuffer(materialDataBuffer);
|
||||
materialDataBuffer = {};
|
||||
materials.clear();
|
||||
materialKeys.clear();
|
||||
placeholderMaterialId = NULL_MATERIAL_ID;
|
||||
device = nullptr;
|
||||
}
|
||||
|
||||
MaterialID MaterialCache::addMaterial(Material material)
|
||||
{
|
||||
if (!materials.empty() && device != nullptr) {
|
||||
// The material buffer is shared by all in-flight frames. A newly
|
||||
// appended entry may be written while an older frame is reading it.
|
||||
device->waitIdle();
|
||||
}
|
||||
|
||||
const auto getTextureOrElse = [](ImageID imageId, ImageID placeholder)
|
||||
{
|
||||
return imageId != NULL_IMAGE_ID ? imageId : placeholder;
|
||||
@@ -42,7 +64,12 @@ MaterialID MaterialCache::addMaterial(Material material)
|
||||
MaterialData* data = static_cast<MaterialData*>(materialDataBuffer.info.pMappedData);
|
||||
|
||||
const auto id = getFreeMaterialId();
|
||||
assert(id < MAX_MATERIALS);
|
||||
if (id >= MAX_MATERIALS) {
|
||||
throw std::runtime_error("MaterialCache capacity exhausted");
|
||||
}
|
||||
if (data == nullptr) {
|
||||
throw std::runtime_error("MaterialCache material buffer is not mapped");
|
||||
}
|
||||
|
||||
data[id] = MaterialData{
|
||||
.baseColor = glm::vec4(material.baseColor, 1.0f),
|
||||
@@ -66,10 +93,30 @@ MaterialID MaterialCache::addMaterial(Material material)
|
||||
|
||||
.emissiveTex = defaultTextures.emissive,
|
||||
};
|
||||
device->getMemoryManager().flushAllocation(
|
||||
materialDataBuffer,
|
||||
static_cast<VkDeviceSize>(id) * sizeof(MaterialData),
|
||||
sizeof(MaterialData));
|
||||
|
||||
// The caller may update multiple materials in one frame; the range flush is
|
||||
// cheap for coherent allocations and required for non-coherent memory.
|
||||
// The cache does not own a device reference, so the renderer flushes the
|
||||
// exact range after batching updates.
|
||||
|
||||
const auto materialId = static_cast<MaterialID>(materials.size());
|
||||
std::string key = material.name.empty()
|
||||
? "material:" + std::to_string(materialId)
|
||||
: material.name;
|
||||
const std::string baseKey = key;
|
||||
std::size_t suffix = 1;
|
||||
while (std::find(materialKeys.begin(), materialKeys.end(), key) != materialKeys.end()) {
|
||||
key = baseKey + "#" + std::to_string(suffix++);
|
||||
}
|
||||
|
||||
materials.push_back(std::move(material));
|
||||
materialKeys.push_back(std::move(key));
|
||||
|
||||
return id;
|
||||
return materialId;
|
||||
}
|
||||
|
||||
MaterialID MaterialCache::addSimpleTextureMaterial(ImageID textureID)
|
||||
@@ -88,9 +135,23 @@ const Material& MaterialCache::getMaterial(MaterialID id) const
|
||||
return materials.at(id);
|
||||
}
|
||||
|
||||
const std::string& MaterialCache::getMaterialKey(MaterialID id) const
|
||||
{
|
||||
return materialKeys.at(id);
|
||||
}
|
||||
|
||||
std::optional<MaterialID> MaterialCache::findMaterialByKey(std::string_view key) const
|
||||
{
|
||||
const auto it = std::find(materialKeys.begin(), materialKeys.end(), key);
|
||||
if (it == materialKeys.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<MaterialID>(std::distance(materialKeys.begin(), it));
|
||||
}
|
||||
|
||||
MaterialID MaterialCache::getFreeMaterialId() const
|
||||
{
|
||||
return materials.size();
|
||||
return static_cast<MaterialID>(materials.size());
|
||||
}
|
||||
|
||||
MaterialID MaterialCache::getPlaceholderMaterialId() const
|
||||
@@ -136,4 +197,8 @@ void MaterialCache::updateMaterialGPU(MaterialID id)
|
||||
.metallicRoughnessTex = defaultTextures.metallicRoughness,
|
||||
.emissiveTex = defaultTextures.emissive,
|
||||
};
|
||||
device->getMemoryManager().flushAllocation(
|
||||
materialDataBuffer,
|
||||
static_cast<VkDeviceSize>(id) * sizeof(MaterialData),
|
||||
sizeof(MaterialData));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user