Adding bindless material descriptors
This commit is contained in:
@@ -17,7 +17,7 @@ float4 fragmentMain(in FragmentParameter params) : SV_Target
|
||||
{
|
||||
LightingParameter lightingParams = params.getLightingParameter();
|
||||
MaterialParameter materialParams = params.getMaterialParameter();
|
||||
let brdf = pMaterial.prepare(materialParams);
|
||||
let brdf = Material.prepare(materialParams);
|
||||
uint2 tileIndex = uint2(floor(params.position_CS.xy / BLOCK_SIZE));
|
||||
uint startOffset = pLightCullingData.lightGrid[tileIndex].x;
|
||||
uint lightCount = pLightCullingData.lightGrid[tileIndex].y;
|
||||
|
||||
@@ -1,9 +1,41 @@
|
||||
import Common;
|
||||
import BRDF;
|
||||
import MaterialParameter;
|
||||
import Scene;
|
||||
|
||||
//interface IMaterial
|
||||
//{
|
||||
// associatedtype BRDF : IBRDF;
|
||||
// BRDF prepare(MaterialParameter input);
|
||||
//};
|
||||
|
||||
layout(set=4, binding=0)
|
||||
Texture2D textureArray[];
|
||||
layout(set=4, binding=1)
|
||||
SamplerState samplerArray[];
|
||||
layout(set=4, binding=2)
|
||||
StructuredBuffer<float> floatArray;
|
||||
|
||||
Texture2D getMaterialTextureParameter(uint index)
|
||||
{
|
||||
return textureArray[pOffsets.textureOffset + index];
|
||||
}
|
||||
|
||||
SamplerState getMaterialSamplerParameter(uint index)
|
||||
{
|
||||
return samplerArray[pOffsets.samplerOffset + index];
|
||||
}
|
||||
|
||||
float getMaterialFloatParameter(uint index)
|
||||
{
|
||||
return floatArray[pOffsets.floatOffset + index];
|
||||
}
|
||||
|
||||
float3 getMaterialVectorParameter(uint index)
|
||||
{
|
||||
return float3(
|
||||
floatArray[pOffsets.floatOffset + index],
|
||||
floatArray[pOffsets.floatOffset + index + 1],
|
||||
floatArray[pOffsets.floatOffset + index + 2]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,9 @@ struct MeshletCullingInfo
|
||||
struct DrawCallOffsets
|
||||
{
|
||||
uint32_t instanceOffset;
|
||||
uint textureOffset;
|
||||
uint samplerOffset;
|
||||
uint floatOffset;
|
||||
};
|
||||
layout(push_constant)
|
||||
ConstantBuffer<DrawCallOffsets> pOffsets;
|
||||
|
||||
@@ -44,14 +44,13 @@ void MaterialLoader::import(MaterialImportArgs args, PMaterialAsset asset) {
|
||||
json j;
|
||||
jsonstream >> j;
|
||||
std::string materialName = j["name"].get<std::string>() + "Material";
|
||||
Gfx::ODescriptorLayout layout = graphics->createDescriptorLayout("pMaterial");
|
||||
// Shader file needs to conform to the slang standard, which prohibits _
|
||||
materialName.erase(std::remove(materialName.begin(), materialName.end(), '_'), materialName.end());
|
||||
materialName.erase(std::remove(materialName.begin(), materialName.end(), '-'), materialName.end());
|
||||
|
||||
uint32 uniformBufferOffset = 0;
|
||||
uint32 bindingCounter = 0; // Uniform buffers are always binding 0
|
||||
int32 uniformBinding = -1;
|
||||
uint32 numTextures = 0;
|
||||
uint32 numSamplers = 0;
|
||||
uint32 numFloats = 0;
|
||||
Array<OShaderExpression> expressions;
|
||||
uint32 key = 0;
|
||||
uint32 auxKey = 0;
|
||||
@@ -59,39 +58,22 @@ void MaterialLoader::import(MaterialImportArgs args, PMaterialAsset asset) {
|
||||
for (auto& param : j["params"].items()) {
|
||||
std::string type = param.value()["type"].get<std::string>();
|
||||
auto defaultValue = param.value().find("default");
|
||||
// TODO: ALIGNMENT RULES
|
||||
if (type.compare("float") == 0) {
|
||||
float defaultData = 0.f;
|
||||
if (defaultValue != param.value().end()) {
|
||||
defaultData = std::stof(defaultValue.value().get<std::string>());
|
||||
}
|
||||
OFloatParameter p = new FloatParameter(param.key(), defaultData, uniformBufferOffset, uniformBinding);
|
||||
if (uniformBinding == -1) {
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = bindingCounter,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
});
|
||||
uniformBinding = bindingCounter++;
|
||||
}
|
||||
uniformBufferOffset += 4;
|
||||
OFloatParameter p = new FloatParameter(param.key(), defaultData, numFloats++);
|
||||
parameters.add(p->key);
|
||||
expressions.add(std::move(p));
|
||||
}
|
||||
// TODO: ALIGNMENT RULES
|
||||
else if (type.compare("float3") == 0) {
|
||||
Vector defaultData = Vector(0, 0, 0);
|
||||
if (defaultValue != param.value().end()) {
|
||||
defaultData = parseVector(defaultValue.value().get<std::string>().c_str());
|
||||
}
|
||||
OVectorParameter p = new VectorParameter(param.key(), defaultData, uniformBufferOffset, uniformBinding);
|
||||
if (uniformBinding == -1) {
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = bindingCounter,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
});
|
||||
uniformBinding = bindingCounter++;
|
||||
}
|
||||
uniformBufferOffset += 16;
|
||||
OVectorParameter p = new VectorParameter(param.key(), defaultData, numFloats);
|
||||
numFloats += 3;
|
||||
parameters.add(p->key);
|
||||
expressions.add(std::move(p));
|
||||
} else if (type.compare("Texture2D") == 0) {
|
||||
@@ -110,19 +92,11 @@ void MaterialLoader::import(MaterialImportArgs args, PMaterialAsset asset) {
|
||||
if (texture == nullptr) {
|
||||
texture = AssetRegistry::findTexture("", ""); // this will return placeholder texture
|
||||
}
|
||||
OTextureParameter p = new TextureParameter(param.key(), texture, bindingCounter);
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = bindingCounter++,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
});
|
||||
OTextureParameter p = new TextureParameter(param.key(), texture, numTextures++);
|
||||
parameters.add(p->key);
|
||||
expressions.add(std::move(p));
|
||||
} else if (type.compare("Sampler") == 0) {
|
||||
OSamplerParameter p = new SamplerParameter(param.key(), graphics->createSampler({}), bindingCounter);
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = bindingCounter++,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
||||
});
|
||||
OSamplerParameter p = new SamplerParameter(param.key(), graphics->createSampler({}), numSamplers++);
|
||||
parameters.add(p->key);
|
||||
expressions.add(std::move(p));
|
||||
} else if (type.compare("Sampler2D") == 0) {
|
||||
@@ -141,18 +115,13 @@ void MaterialLoader::import(MaterialImportArgs args, PMaterialAsset asset) {
|
||||
if (texture == nullptr) {
|
||||
texture = AssetRegistry::findTexture("", ""); // this will return placeholder texture
|
||||
}
|
||||
OCombinedTextureParameter p = new CombinedTextureParameter(param.key(), texture, graphics->createSampler({}), bindingCounter);
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = bindingCounter++,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
||||
});
|
||||
OCombinedTextureParameter p = new CombinedTextureParameter(param.key(), texture, graphics->createSampler({}), numTextures++);
|
||||
parameters.add(p->key);
|
||||
expressions.add(std::move(p));
|
||||
} else {
|
||||
std::cout << "Error unsupported parameter type" << std::endl;
|
||||
}
|
||||
}
|
||||
uint32 uniformDataSize = uniformBufferOffset;
|
||||
auto referenceExpression = [¶meters, &auxKey, &expressions](json obj) -> std::string {
|
||||
if (obj.is_string()) {
|
||||
std::string str = obj.get<std::string>();
|
||||
@@ -233,8 +202,7 @@ void MaterialLoader::import(MaterialImportArgs args, PMaterialAsset asset) {
|
||||
}
|
||||
}
|
||||
}
|
||||
layout->create();
|
||||
asset->material = new Material(graphics, std::move(layout), uniformDataSize, uniformBinding, materialName, std::move(expressions),
|
||||
asset->material = new Material(graphics, numTextures, numSamplers, numFloats, materialName, std::move(expressions),
|
||||
std::move(parameters), std::move(mat));
|
||||
|
||||
asset->material->compile();
|
||||
|
||||
@@ -111,32 +111,23 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
||||
materialName.end()); // dots break adding the .asset extension later
|
||||
materialName.erase(std::remove(materialName.begin(), materialName.end(), ')'),
|
||||
materialName.end()); // dots break adding the .asset extension later
|
||||
Gfx::ODescriptorLayout materialLayout = graphics->createDescriptorLayout("pMaterial");
|
||||
Array<OShaderExpression> expressions;
|
||||
Array<std::string> parameters;
|
||||
|
||||
materialLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
|
||||
});
|
||||
|
||||
size_t uniformSize = 0;
|
||||
uint32 bindingCounter = 1;
|
||||
uint32 numTextures = 0;
|
||||
uint32 numSamplers = 0;
|
||||
uint32 numFloats = 0;
|
||||
auto addScalarParameter = [&](std::string paramKey, const char* matKey, int type, int index) {
|
||||
float scalar;
|
||||
material->Get(matKey, type, index, scalar);
|
||||
expressions.add(new FloatParameter(paramKey, scalar, uniformSize, 0));
|
||||
uniformSize += sizeof(float);
|
||||
expressions.add(new FloatParameter(paramKey, scalar, numFloats++));
|
||||
parameters.add(paramKey);
|
||||
};
|
||||
|
||||
auto addVectorParameter = [&](std::string paramKey, const char* matKey, int type, int index) {
|
||||
aiColor3D color;
|
||||
material->Get(matKey, type, index, color);
|
||||
uniformSize = (uniformSize + sizeof(Vector4) - 1) / sizeof(Vector4) * sizeof(Vector4);
|
||||
expressions.add(new VectorParameter(paramKey, Vector(color.r, color.g, color.b), uniformSize, 0));
|
||||
uniformSize += sizeof(Vector);
|
||||
expressions.add(new VectorParameter(paramKey, Vector(color.r, color.g, color.b), numFloats));
|
||||
numFloats += 3;
|
||||
parameters.add(paramKey);
|
||||
};
|
||||
|
||||
@@ -181,15 +172,8 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
||||
std::cout << "couldnt find " << texPath.C_Str() << std::endl;
|
||||
return;
|
||||
}
|
||||
expressions.add(new TextureParameter(textureKey, texture, bindingCounter));
|
||||
materialLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = bindingCounter,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.textureType = Gfx::SE_IMAGE_VIEW_TYPE_2D,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
|
||||
});
|
||||
expressions.add(new TextureParameter(textureKey, texture, numTextures++));
|
||||
parameters.add(textureKey);
|
||||
bindingCounter++;
|
||||
|
||||
std::string samplerKey = fmt::format("{0}Sampler{1}", paramKey, index);
|
||||
SamplerCreateInfo samplerInfo = {};
|
||||
@@ -215,14 +199,8 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
||||
samplerInfo.addressModeW = Gfx::SE_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT;
|
||||
break;
|
||||
}
|
||||
expressions.add(new SamplerParameter(samplerKey, graphics->createSampler(samplerInfo), bindingCounter));
|
||||
materialLayout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = bindingCounter,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
|
||||
});
|
||||
expressions.add(new SamplerParameter(samplerKey, graphics->createSampler(samplerInfo), numSamplers++));
|
||||
parameters.add(samplerKey);
|
||||
bindingCounter++;
|
||||
|
||||
std::string sampleKey = fmt::format("{0}Sample{1}", paramKey, index);
|
||||
expressions.add(new SampleExpression());
|
||||
@@ -242,8 +220,7 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
||||
return;
|
||||
}
|
||||
std::string blendFactorKey = fmt::format("{0}BlendFactor{1}", paramKey, index);
|
||||
expressions.add(new FloatParameter(blendFactorKey, blend, uniformSize, 0));
|
||||
uniformSize += sizeof(float);
|
||||
expressions.add(new FloatParameter(blendFactorKey, blend, numFloats++));
|
||||
parameters.add(blendFactorKey);
|
||||
|
||||
std::string strengthKey = fmt::format("{0}Strength{1}", paramKey, index);
|
||||
@@ -396,10 +373,8 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array<PTextureAsset>&
|
||||
break;
|
||||
};
|
||||
|
||||
materialLayout->create();
|
||||
|
||||
OMaterialAsset baseMat = new MaterialAsset(importPath, materialName);
|
||||
baseMat->material = new Material(graphics, std::move(materialLayout), uniformSize, 0, materialName, std::move(expressions),
|
||||
baseMat->material = new Material(graphics, numTextures, numSamplers, numFloats, materialName, std::move(expressions),
|
||||
std::move(parameters), std::move(brdf));
|
||||
baseMat->material->compile();
|
||||
graphics->getShaderCompiler()->registerMaterial(baseMat->material);
|
||||
|
||||
@@ -64,7 +64,9 @@ class DescriptorSet {
|
||||
virtual void updateBuffer(uint32 binding, PShaderBuffer ShaderBuffer) = 0;
|
||||
virtual void updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer uniformBuffer) = 0;
|
||||
virtual void updateSampler(uint32 binding, PSampler sampler) = 0;
|
||||
virtual void updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState) = 0;
|
||||
virtual void updateTexture(uint32 binding, PTexture texture, PSampler samplerState = nullptr) = 0;
|
||||
virtual void updateTexture(uint32 binding, uint32 dstArrayIndex, PTexture texture) = 0;
|
||||
virtual void updateTextureArray(uint32_t binding, Array<PTexture> texture) = 0;
|
||||
bool operator<(PDescriptorSet other);
|
||||
|
||||
|
||||
@@ -194,6 +194,12 @@ DECLARE_REF(TaskShader)
|
||||
DECLARE_REF(MeshShader)
|
||||
DECLARE_REF(FragmentShader)
|
||||
DECLARE_REF(ComputeShader)
|
||||
DECLARE_REF(RayGenShader)
|
||||
DECLARE_REF(ClosestHitShader)
|
||||
DECLARE_REF(AnyHitShader)
|
||||
DECLARE_REF(IntersectionShader)
|
||||
DECLARE_REF(MissShader)
|
||||
DECLARE_REF(CallableShader)
|
||||
DECLARE_REF(RenderPass)
|
||||
DECLARE_REF(PipelineLayout)
|
||||
struct LegacyPipelineCreateInfo {
|
||||
|
||||
@@ -21,6 +21,7 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics,
|
||||
|
||||
basePassLayout->addDescriptorLayout(viewParamsLayout);
|
||||
basePassLayout->addDescriptorLayout(scene->getLightEnvironment()->getDescriptorLayout());
|
||||
basePassLayout->addDescriptorLayout(Material::getDescriptorLayout());
|
||||
|
||||
lightCullingLayout = graphics->createDescriptorLayout("pLightCullingData");
|
||||
// oLightIndexList
|
||||
@@ -37,7 +38,7 @@ BasePass::BasePass(Gfx::PGraphics graphics, PScene scene) : RenderPass(graphics,
|
||||
|
||||
basePassLayout->addDescriptorLayout(lightCullingLayout);
|
||||
basePassLayout->addPushConstants(Gfx::SePushConstantRange{
|
||||
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT,
|
||||
.stageFlags = Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT | Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
|
||||
.offset = 0,
|
||||
.size = sizeof(VertexData::DrawCallOffsets),
|
||||
});
|
||||
@@ -162,12 +163,12 @@ void BasePass::render() {
|
||||
Gfx::PGraphicsPipeline pipeline = graphics->createGraphicsPipeline(std::move(pipelineInfo));
|
||||
command->bindPipeline(pipeline);
|
||||
}
|
||||
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(),
|
||||
scene->getLightEnvironment()->getDescriptorSet(), Material::getDescriptorSet(), opaqueCulling});
|
||||
for (const auto& drawCall : materialData.instances) {
|
||||
command->bindDescriptor({viewParamsSet, vertexData->getVertexDataSet(), vertexData->getInstanceDataSet(),
|
||||
scene->getLightEnvironment()->getDescriptorSet(), drawCall.materialInstance->getDescriptorSet(),
|
||||
opaqueCulling});
|
||||
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT, 0,
|
||||
sizeof(VertexData::DrawCallOffsets), &drawCall.offsets);
|
||||
command->pushConstants(Gfx::SE_SHADER_STAGE_TASK_BIT_EXT | Gfx::SE_SHADER_STAGE_VERTEX_BIT |
|
||||
Gfx::SE_SHADER_STAGE_FRAGMENT_BIT,
|
||||
0, sizeof(VertexData::DrawCallOffsets), &drawCall.offsets);
|
||||
if (graphics->supportMeshShading()) {
|
||||
command->drawMesh(drawCall.instanceMeshData.size(), 1, 1);
|
||||
} else {
|
||||
|
||||
@@ -65,7 +65,6 @@ void ShaderCompiler::compile() {
|
||||
OPipelineLayout layout = graphics->createPipelineLayout(pass.baseLayout->getName(), pass.baseLayout);
|
||||
layout->addDescriptorLayout(vd->getVertexDataLayout());
|
||||
layout->addDescriptorLayout(vd->getInstanceDataLayout());
|
||||
layout->addDescriptorLayout(mat->getDescriptorLayout());
|
||||
permutation.setMaterial(mat->getName());
|
||||
createShaders(permutation, std::move(layout));
|
||||
});
|
||||
|
||||
@@ -107,6 +107,10 @@ void VertexData::createDescriptors() {
|
||||
for (auto& mat : materialData) {
|
||||
for (auto& instance : mat.instances) {
|
||||
instance.offsets.instanceOffset = instanceData.size();
|
||||
MaterialOffsets offsets = instance.materialInstance->getMaterialOffsets();
|
||||
instance.offsets.textureOffset = offsets.textureOffset;
|
||||
instance.offsets.samplerOffset = offsets.samplerOffset;
|
||||
instance.offsets.floatOffset = offsets.floatOffset;
|
||||
// instance.offsets.cullingCounterOffset = cullingOffsets.size();
|
||||
// instance.numMeshlets = 0;
|
||||
for (size_t i = 0; i < instance.instanceData.size(); ++i) {
|
||||
@@ -161,6 +165,7 @@ void VertexData::createDescriptors() {
|
||||
descriptorSet->updateBuffer(3, primitiveIndicesBuffer);
|
||||
descriptorSet->updateBuffer(4, vertexIndicesBuffer);
|
||||
descriptorSet->updateBuffer(5, cullingOffsetBuffer);
|
||||
Material::updateDescriptor();
|
||||
}
|
||||
|
||||
void VertexData::loadMesh(MeshId id, Array<uint32> loadedIndices, Array<Meshlet> loadedMeshlets) {
|
||||
|
||||
@@ -22,6 +22,9 @@ class VertexData {
|
||||
public:
|
||||
struct DrawCallOffsets {
|
||||
uint32 instanceOffset = 0;
|
||||
uint32 textureOffset = 0;
|
||||
uint32 samplerOffset = 0;
|
||||
uint32 floatOffset = 0;
|
||||
};
|
||||
|
||||
struct MeshletCullingInfo {
|
||||
|
||||
@@ -316,7 +316,7 @@ void RenderCommand::drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, u
|
||||
vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast<ShaderBuffer>()->getHandle(), offset, drawCount, stride);
|
||||
}
|
||||
|
||||
void RenderCommand::traceRays() { vkCmdTraceRaysKHR(handle, ); }
|
||||
void RenderCommand::traceRays() { }
|
||||
|
||||
ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) {
|
||||
VkCommandBufferAllocateInfo allocInfo = {
|
||||
|
||||
@@ -45,7 +45,7 @@ void DescriptorLayout::create() {
|
||||
VkDescriptorSetLayoutCreateInfo createInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.pNext = &bindingFlagsInfo,
|
||||
.flags = 0,
|
||||
.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
|
||||
.bindingCount = (uint32)bindings.size(),
|
||||
.pBindings = bindings.data(),
|
||||
};
|
||||
@@ -67,7 +67,7 @@ DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout)
|
||||
for (uint32 i = 0; i < layout->getBindings().size(); ++i) {
|
||||
auto& binding = layout->getBindings()[i];
|
||||
int typeIndex = binding.descriptorType;
|
||||
perTypeSizes[typeIndex] += 256;
|
||||
perTypeSizes[typeIndex] += 512;
|
||||
}
|
||||
Array<VkDescriptorPoolSize> poolSizes;
|
||||
for (uint32 i = 0; i < VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT; ++i) {
|
||||
@@ -81,7 +81,7 @@ DescriptorPool::DescriptorPool(PGraphics graphics, PDescriptorLayout layout)
|
||||
VkDescriptorPoolCreateInfo createInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.flags = 0,
|
||||
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
|
||||
.maxSets = maxSets * Gfx::numFramesBuffered,
|
||||
.poolSizeCount = (uint32)poolSizes.size(),
|
||||
.pPoolSizes = poolSizes.data(),
|
||||
@@ -275,6 +275,34 @@ void DescriptorSet::updateSampler(uint32_t binding, Gfx::PSampler samplerState)
|
||||
boundResources[binding] = vulkanSampler->getHandle();
|
||||
}
|
||||
|
||||
void DescriptorSet::updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState)
|
||||
{
|
||||
PSampler vulkanSampler = samplerState.cast<Sampler>();
|
||||
if (boundResources[binding] == vulkanSampler->getHandle()) {
|
||||
return;
|
||||
}
|
||||
|
||||
imageInfos.add(VkDescriptorImageInfo{
|
||||
.sampler = vulkanSampler->getSampler(),
|
||||
.imageView = VK_NULL_HANDLE,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
});
|
||||
|
||||
writeDescriptors.add(VkWriteDescriptorSet{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.pNext = nullptr,
|
||||
.dstSet = setHandle,
|
||||
.dstBinding = binding,
|
||||
.dstArrayElement = dstArrayIndex,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.pImageInfo = &imageInfos.back(),
|
||||
});
|
||||
|
||||
boundResources[binding] = vulkanSampler->getHandle();
|
||||
}
|
||||
|
||||
|
||||
void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler samplerState) {
|
||||
TextureBase* vulkanTexture = texture.cast<TextureBase>().getHandle();
|
||||
if (boundResources[binding] == vulkanTexture->getHandle()) {
|
||||
@@ -306,6 +334,35 @@ void DescriptorSet::updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::
|
||||
|
||||
boundResources[binding] = vulkanTexture->getHandle();
|
||||
}
|
||||
|
||||
void DescriptorSet::updateTexture(uint32 binding, uint32 dstArrayIndex, Gfx::PTexture texture)
|
||||
{
|
||||
TextureBase* vulkanTexture = texture.cast<TextureBase>().getHandle();
|
||||
if (boundResources[binding] == vulkanTexture->getHandle()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// It is assumed that the image is in the correct layout
|
||||
imageInfos.add(VkDescriptorImageInfo{
|
||||
.sampler = VK_NULL_HANDLE,
|
||||
.imageView = vulkanTexture->getView(),
|
||||
.imageLayout = cast(vulkanTexture->getLayout()),
|
||||
});
|
||||
writeDescriptors.add(VkWriteDescriptorSet{
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.pNext = nullptr,
|
||||
.dstSet = setHandle,
|
||||
.dstBinding = binding,
|
||||
.dstArrayElement = dstArrayIndex,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.pImageInfo = &imageInfos.back(),
|
||||
});
|
||||
|
||||
boundResources[binding] = vulkanTexture->getHandle();
|
||||
}
|
||||
|
||||
|
||||
void DescriptorSet::updateTextureArray(uint32_t binding, Array<Gfx::PTexture> textures) {
|
||||
// maybe make this a parameter?
|
||||
uint32 arrayElement = 0;
|
||||
|
||||
@@ -52,7 +52,9 @@ class DescriptorSet : public Gfx::DescriptorSet, public CommandBoundResource {
|
||||
virtual void updateBuffer(uint32_t binding, Gfx::PShaderBuffer uniformBuffer) override;
|
||||
virtual void updateBuffer(uint32_t binding, uint32 index, Gfx::PShaderBuffer uniformBuffer) override;
|
||||
virtual void updateSampler(uint32_t binding, Gfx::PSampler samplerState) override;
|
||||
virtual void updateSampler(uint32_t binding, uint32 dstArrayIndex, Gfx::PSampler samplerState) override;
|
||||
virtual void updateTexture(uint32_t binding, Gfx::PTexture texture, Gfx::PSampler sampler = nullptr) override;
|
||||
virtual void updateTexture(uint32 binding, uint32 dstArrayIndex, Gfx::PTexture texture) override;
|
||||
virtual void updateTextureArray(uint32_t binding, Array<Gfx::PTexture> texture) override;
|
||||
|
||||
constexpr bool isCurrentlyInUse() const { return currentlyInUse; }
|
||||
|
||||
@@ -528,6 +528,14 @@ void Graphics::pickPhysicalDevice() {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||
.pNext = &meshShaderFeatures,
|
||||
.storageBuffer8BitAccess = true,
|
||||
.shaderUniformBufferArrayNonUniformIndexing = true,
|
||||
.shaderSampledImageArrayNonUniformIndexing = true,
|
||||
.shaderStorageBufferArrayNonUniformIndexing = true,
|
||||
.descriptorBindingUniformBufferUpdateAfterBind = true,
|
||||
.descriptorBindingSampledImageUpdateAfterBind = true,
|
||||
.descriptorBindingStorageBufferUpdateAfterBind = true,
|
||||
.descriptorBindingPartiallyBound = true,
|
||||
.runtimeDescriptorArray = true,
|
||||
.bufferDeviceAddress = true,
|
||||
};
|
||||
features = {
|
||||
|
||||
@@ -466,6 +466,4 @@ PComputePipeline PipelineCache::createPipeline(Gfx::ComputePipelineCreateInfo co
|
||||
return result;
|
||||
}
|
||||
|
||||
PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateInfo createInfo) {
|
||||
|
||||
}
|
||||
PRayTracingPipeline PipelineCache::createPipeline(Gfx::RayTracingPipelineCreateInfo createInfo) { return nullptr; }
|
||||
|
||||
@@ -108,14 +108,11 @@ Slang::ComPtr<slang::IBlob> Seele::generateShader(const ShaderCreateInfo& create
|
||||
CHECK_DIAGNOSTICS();
|
||||
for (size_t i = 0; i < signature->getParameterCount(); ++i) {
|
||||
auto param = signature->getParameterByIndex(i);
|
||||
// workaround
|
||||
if (std::strcmp(param->getName(), "pVertexData") == 0) {
|
||||
paramMapping[param->getName()] = 1;
|
||||
} else if (std::strcmp(param->getName(), "pMaterial") == 0) {
|
||||
paramMapping[param->getName()] = 4;
|
||||
} else {
|
||||
paramMapping[param->getName()] = param->getBindingIndex();
|
||||
}
|
||||
paramMapping[param->getName()] = param->getBindingIndex();
|
||||
}
|
||||
|
||||
// workaround
|
||||
paramMapping["pVertexData"] = 1;
|
||||
paramMapping["pMaterial"] = 4;
|
||||
return kernelBlob;
|
||||
}
|
||||
|
||||
@@ -7,92 +7,141 @@
|
||||
#include "Window/WindowManager.h"
|
||||
#include <fstream>
|
||||
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Array<Gfx::PTexture2D> Material::textures;
|
||||
Array<Gfx::PSampler> Material::samplers;
|
||||
Gfx::OShaderBuffer Material::floatBuffer;
|
||||
Array<float> Material::floatData;
|
||||
Gfx::ODescriptorLayout Material::layout;
|
||||
Gfx::PDescriptorSet Material::set;
|
||||
std::atomic_uint64_t Material::materialIdCounter = 0;
|
||||
Array<PMaterial> Material::materials;
|
||||
|
||||
Material::Material() {}
|
||||
|
||||
Material::Material(Gfx::PGraphics graphics, Gfx::ODescriptorLayout layout, uint32 uniformDataSize, uint32 uniformBinding,
|
||||
std::string materialName, Array<OShaderExpression> expressions, Array<std::string> parameter, MaterialNode brdf)
|
||||
: graphics(graphics), uniformDataSize(uniformDataSize), uniformBinding(uniformBinding), instanceId(0), layout(std::move(layout)),
|
||||
Material::Material(Gfx::PGraphics graphics, uint32 numTextures, uint32 numSamplers, uint32 numFloats, std::string materialName,
|
||||
Array<OShaderExpression> expressions, Array<std::string> parameter, MaterialNode brdf)
|
||||
: graphics(graphics), numTextures(numTextures), numSamplers(numSamplers), numFloats(numFloats), instanceId(0),
|
||||
materialName(materialName), codeExpressions(std::move(expressions)), parameters(std::move(parameter)), brdf(std::move(brdf)),
|
||||
materialId(materialIdCounter++) {
|
||||
if (layout == nullptr) {
|
||||
init(graphics);
|
||||
}
|
||||
materials.add(this);
|
||||
}
|
||||
|
||||
Material::~Material() {}
|
||||
|
||||
void Material::init(Gfx::PGraphics graphics) {
|
||||
layout = graphics->createDescriptorLayout("pMaterial");
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 0,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
|
||||
.descriptorCount = 2000,
|
||||
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | Gfx::SE_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
|
||||
});
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 1,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_SAMPLER,
|
||||
.descriptorCount = 2000,
|
||||
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | Gfx::SE_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
|
||||
});
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = 2,
|
||||
.descriptorType = Gfx::SE_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.bindingFlags = Gfx::SE_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | Gfx::SE_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT,
|
||||
.shaderStages = Gfx::SE_SHADER_STAGE_FRAGMENT_BIT | Gfx::SE_SHADER_STAGE_CLOSEST_HIT_BIT_KHR,
|
||||
});
|
||||
layout->create();
|
||||
floatBuffer = graphics->createShaderBuffer(ShaderBufferCreateInfo{
|
||||
.dynamic = true,
|
||||
.name = "MaterialFloatBuffer",
|
||||
});
|
||||
}
|
||||
|
||||
void Material::updateDescriptor() {
|
||||
floatBuffer->rotateBuffer(floatData.size() * sizeof(float));
|
||||
floatBuffer->updateContents(ShaderBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = floatData.size() * sizeof(float),
|
||||
},
|
||||
});
|
||||
floatBuffer->pipelineBarrier(Gfx::SE_ACCESS_TRANSFER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_TRANSFER_BIT, Gfx::SE_ACCESS_SHADER_READ_BIT,
|
||||
Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
layout->reset();
|
||||
set = layout->allocateDescriptorSet();
|
||||
for (uint32 i = 0; i < textures.size(); ++i)
|
||||
{
|
||||
set->updateTexture(0, i, textures[i]);
|
||||
}
|
||||
for (uint32 i = 0; i < samplers.size(); ++i)
|
||||
{
|
||||
set->updateSampler(1, i, samplers[i]);
|
||||
}
|
||||
set->updateBuffer(2, floatBuffer);
|
||||
set->writeChanges();
|
||||
}
|
||||
|
||||
void Material::updateTexture(uint32 index, Gfx::PTexture2D texture) { textures[index] = texture; }
|
||||
|
||||
void Material::updateSampler(uint32 index, Gfx::PSampler sampler) { samplers[index] = sampler; }
|
||||
|
||||
void Material::updateFloatData(uint32 offset, uint32 numFloats, float* data) {
|
||||
std::memcpy(floatData.data() + offset, data, numFloats * sizeof(float));
|
||||
}
|
||||
|
||||
uint32 Material::addTextures(uint32 numTextures) {
|
||||
uint32 textureOffset = textures.size();
|
||||
textures.resize(textures.size() + numTextures);
|
||||
return textureOffset;
|
||||
}
|
||||
|
||||
uint32 Material::addSamplers(uint32 numSamplers) {
|
||||
uint32 samplerOffset = samplers.size();
|
||||
samplers.resize(samplers.size() + numSamplers);
|
||||
return samplerOffset;
|
||||
}
|
||||
|
||||
uint32 Material::addFloats(uint32 numFloats) {
|
||||
uint32 floatOffset = floatData.size();
|
||||
floatData.resize(floatData.size() + numFloats);
|
||||
return floatOffset;
|
||||
}
|
||||
|
||||
OMaterialInstance Material::instantiate() {
|
||||
return new MaterialInstance(instanceId++, graphics, codeExpressions, parameters, uniformBinding, uniformDataSize);
|
||||
return new MaterialInstance(instanceId++, graphics, codeExpressions, parameters, numTextures, numSamplers, numFloats);
|
||||
}
|
||||
|
||||
void Material::save(ArchiveBuffer& buffer) const {
|
||||
Serialization::save(buffer, uniformDataSize);
|
||||
Serialization::save(buffer, uniformBinding);
|
||||
Serialization::save(buffer, numTextures);
|
||||
Serialization::save(buffer, numSamplers);
|
||||
Serialization::save(buffer, numFloats);
|
||||
Serialization::save(buffer, instanceId);
|
||||
Serialization::save(buffer, materialName);
|
||||
Serialization::save(buffer, codeExpressions);
|
||||
Serialization::save(buffer, parameters);
|
||||
Serialization::save(buffer, brdf);
|
||||
Serialization::save(buffer, layout->getName());
|
||||
const auto& bindings = layout->getBindings();
|
||||
Serialization::save(buffer, bindings.size());
|
||||
for (const auto& binding : bindings) {
|
||||
Serialization::save(buffer, binding.binding);
|
||||
Serialization::save(buffer, binding.descriptorType);
|
||||
Serialization::save(buffer, binding.textureType);
|
||||
Serialization::save(buffer, binding.descriptorCount);
|
||||
Serialization::save(buffer, binding.bindingFlags);
|
||||
Serialization::save(buffer, binding.shaderStages);
|
||||
}
|
||||
}
|
||||
|
||||
void Material::load(ArchiveBuffer& buffer) {
|
||||
graphics = buffer.getGraphics();
|
||||
Serialization::load(buffer, uniformDataSize);
|
||||
Serialization::load(buffer, uniformBinding);
|
||||
if (layout == nullptr)
|
||||
{
|
||||
init(graphics);
|
||||
}
|
||||
Serialization::load(buffer, numTextures);
|
||||
Serialization::load(buffer, numSamplers);
|
||||
Serialization::load(buffer, numFloats);
|
||||
Serialization::load(buffer, instanceId);
|
||||
Serialization::load(buffer, materialName);
|
||||
Serialization::load(buffer, codeExpressions);
|
||||
Serialization::load(buffer, parameters);
|
||||
Serialization::load(buffer, brdf);
|
||||
std::string descriptorName;
|
||||
Serialization::load(buffer, descriptorName);
|
||||
uint64 numBindings;
|
||||
Serialization::load(buffer, numBindings);
|
||||
layout = graphics->createDescriptorLayout(descriptorName);
|
||||
for (uint64 i = 0; i < numBindings; ++i) {
|
||||
uint32 binding;
|
||||
Serialization::load(buffer, binding);
|
||||
|
||||
Gfx::SeDescriptorType descriptorType;
|
||||
Serialization::load(buffer, descriptorType);
|
||||
|
||||
Gfx::SeImageViewType textureType;
|
||||
Serialization::load(buffer, textureType);
|
||||
|
||||
uint32 descriptorCount;
|
||||
Serialization::load(buffer, descriptorCount);
|
||||
|
||||
Gfx::SeDescriptorBindingFlags bindingFlags;
|
||||
Serialization::load(buffer, bindingFlags);
|
||||
|
||||
Gfx::SeShaderStageFlags shaderStages;
|
||||
Serialization::load(buffer, shaderStages);
|
||||
|
||||
layout->addDescriptorBinding(Gfx::DescriptorBinding{
|
||||
.binding = binding,
|
||||
.descriptorType = descriptorType,
|
||||
.textureType = textureType,
|
||||
.descriptorCount = descriptorCount,
|
||||
.bindingFlags = bindingFlags,
|
||||
.shaderStages = shaderStages,
|
||||
});
|
||||
}
|
||||
layout->create();
|
||||
materialId = materialIdCounter++;
|
||||
}
|
||||
|
||||
@@ -100,14 +149,10 @@ void Material::compile() {
|
||||
std::ofstream codeStream("./shaders/generated/" + materialName + ".slang");
|
||||
codeStream << "import BRDF;\n";
|
||||
codeStream << "import MaterialParameter;\n";
|
||||
codeStream << "struct " << materialName << "{\n";
|
||||
for (const auto& parameter : parameters) {
|
||||
PShaderParameter handle =
|
||||
PShaderExpression(*codeExpressions.find([¶meter](const OShaderExpression& exp) { return exp->key == parameter; }));
|
||||
handle->generateDeclaration(codeStream);
|
||||
}
|
||||
codeStream << "import Material;\n";
|
||||
codeStream << "struct Material{\n";
|
||||
codeStream << "\ttypedef " << brdf.profile << " BRDF;\n";
|
||||
codeStream << "\t" << brdf.profile << " prepare(MaterialParameter input) {\n";
|
||||
codeStream << "\tstatic " << brdf.profile << " prepare(MaterialParameter input) {\n";
|
||||
codeStream << "\t\t" << brdf.profile << " result;\n";
|
||||
Map<std::string, std::string> varState;
|
||||
// initialize variable state
|
||||
@@ -120,7 +165,6 @@ void Material::compile() {
|
||||
codeStream << "\t\treturn result;\n";
|
||||
codeStream << "\t}\n";
|
||||
codeStream << "};\n";
|
||||
codeStream << "layout(set=4)";
|
||||
codeStream << "ParameterBlock<" << materialName << "> pMaterial;";
|
||||
graphics->getShaderCompiler()->registerMaterial(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,14 +5,24 @@
|
||||
|
||||
namespace Seele {
|
||||
DECLARE_REF(MaterialInstance)
|
||||
DECLARE_NAME_REF(Gfx, Texture2D)
|
||||
DECLARE_NAME_REF(Gfx, Sampler)
|
||||
class Material {
|
||||
public:
|
||||
Material();
|
||||
Material(Gfx::PGraphics graphics, Gfx::ODescriptorLayout layout, uint32 uniformDataSize, uint32 uniformBinding,
|
||||
Material(Gfx::PGraphics graphics, uint32 numTextures, uint32 numSamplers, uint32 numFloats,
|
||||
std::string materialName, Array<OShaderExpression> expressions, Array<std::string> parameter, MaterialNode brdf);
|
||||
~Material();
|
||||
const Gfx::PDescriptorLayout getDescriptorLayout() const { return layout; }
|
||||
Gfx::PDescriptorLayout getDescriptorLayout() { return layout; }
|
||||
static void init(Gfx::PGraphics graphics);
|
||||
static Gfx::PDescriptorLayout getDescriptorLayout() { return layout; }
|
||||
static Gfx::PDescriptorSet getDescriptorSet() { return set; }
|
||||
static void updateDescriptor();
|
||||
static void updateTexture(uint32 index, Gfx::PTexture2D texture);
|
||||
static void updateSampler(uint32 index, Gfx::PSampler sampler);
|
||||
static void updateFloatData(uint32 offset, uint32 numFloats, float* data);
|
||||
static uint32 addTextures(uint32 numTextures);
|
||||
static uint32 addSamplers(uint32 numSamplers);
|
||||
static uint32 addFloats(uint32 numFloats);
|
||||
OMaterialInstance instantiate();
|
||||
const std::string& getName() const { return materialName; }
|
||||
constexpr uint64 getId() const { return materialId; }
|
||||
@@ -25,15 +35,21 @@ class Material {
|
||||
|
||||
private:
|
||||
Gfx::PGraphics graphics;
|
||||
uint32 uniformDataSize;
|
||||
uint32 uniformBinding;
|
||||
uint32 numTextures;
|
||||
uint32 numSamplers;
|
||||
uint32 numFloats;
|
||||
uint64 instanceId;
|
||||
uint64 materialId;
|
||||
Gfx::ODescriptorLayout layout;
|
||||
std::string materialName;
|
||||
Array<OShaderExpression> codeExpressions;
|
||||
Array<std::string> parameters;
|
||||
MaterialNode brdf;
|
||||
static Array<Gfx::PTexture2D> textures;
|
||||
static Array<Gfx::PSampler> samplers;
|
||||
static Gfx::OShaderBuffer floatBuffer;
|
||||
static Array<float> floatData;
|
||||
static Gfx::ODescriptorLayout layout;
|
||||
static Gfx::PDescriptorSet set;
|
||||
static std::atomic_uint64_t materialIdCounter;
|
||||
static Array<PMaterial> materials;
|
||||
};
|
||||
|
||||
@@ -8,18 +8,11 @@ using namespace Seele;
|
||||
MaterialInstance::MaterialInstance() {}
|
||||
|
||||
MaterialInstance::MaterialInstance(uint64 id, Gfx::PGraphics graphics, Array<OShaderExpression>& expressions, Array<std::string> params,
|
||||
uint32 uniformBinding, uint32 uniformSize)
|
||||
: graphics(graphics), uniformBinding(uniformBinding), id(id) {
|
||||
if (uniformSize > 0) {
|
||||
uniformBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = uniformSize,
|
||||
},
|
||||
.dynamic = true,
|
||||
});
|
||||
}
|
||||
uniformData.resize(uniformSize);
|
||||
uint32 numTextures, uint32 numSamplers, uint32 numFloats)
|
||||
: graphics(graphics), numTextures(numTextures), numSamplers(numSamplers), numFloats(numFloats), id(id) {
|
||||
texturesOffset = Material::addTextures(numTextures);
|
||||
samplersOffset = Material::addSamplers(numSamplers);
|
||||
floatBufferOffset = Material::addFloats(numFloats);
|
||||
ArchiveBuffer buffer(graphics);
|
||||
parameters.reserve(params.size());
|
||||
for (size_t i = 0; i < params.size(); ++i) {
|
||||
@@ -36,47 +29,30 @@ MaterialInstance::MaterialInstance(uint64 id, Gfx::PGraphics graphics, Array<OSh
|
||||
MaterialInstance::~MaterialInstance() {}
|
||||
|
||||
void MaterialInstance::updateDescriptor() {
|
||||
Gfx::PDescriptorLayout layout = baseMaterial->getMaterial()->getDescriptorLayout();
|
||||
descriptor = layout->allocateDescriptorSet();
|
||||
for (auto& param : parameters) {
|
||||
param->updateDescriptorSet(descriptor, uniformData.data());
|
||||
for (auto& p : parameters) {
|
||||
p->updateDescriptorSet(texturesOffset, samplersOffset, floatBufferOffset);
|
||||
}
|
||||
if (uniformData.size() > 0) {
|
||||
uniformBuffer->updateContents(DataSource{
|
||||
.size = uniformData.size(),
|
||||
.data = uniformData.data(),
|
||||
});
|
||||
descriptor->updateBuffer(uniformBinding, uniformBuffer);
|
||||
}
|
||||
descriptor->writeChanges();
|
||||
}
|
||||
|
||||
Gfx::PDescriptorSet MaterialInstance::getDescriptorSet() const { return descriptor; }
|
||||
|
||||
void MaterialInstance::setBaseMaterial(PMaterialAsset asset) {
|
||||
if (uniformData.size() > 0) {
|
||||
uniformBuffer = graphics->createUniformBuffer(UniformBufferCreateInfo{
|
||||
.sourceData =
|
||||
{
|
||||
.size = uniformData.size(),
|
||||
},
|
||||
.dynamic = true,
|
||||
});
|
||||
}
|
||||
baseMaterial = asset;
|
||||
}
|
||||
|
||||
void MaterialInstance::save(ArchiveBuffer& buffer) const {
|
||||
Serialization::save(buffer, uniformData);
|
||||
Serialization::save(buffer, uniformBinding);
|
||||
Serialization::save(buffer, numTextures);
|
||||
Serialization::save(buffer, numSamplers);
|
||||
Serialization::save(buffer, numFloats);
|
||||
Serialization::save(buffer, parameters);
|
||||
Serialization::save(buffer, id);
|
||||
}
|
||||
|
||||
void MaterialInstance::load(ArchiveBuffer& buffer) {
|
||||
graphics = buffer.getGraphics();
|
||||
Serialization::load(buffer, uniformData);
|
||||
Serialization::load(buffer, uniformBinding);
|
||||
Serialization::load(buffer, numTextures);
|
||||
Serialization::load(buffer, numSamplers);
|
||||
Serialization::load(buffer, numFloats);
|
||||
Serialization::load(buffer, parameters);
|
||||
Serialization::load(buffer, id);
|
||||
texturesOffset = Material::addTextures(numTextures);
|
||||
samplersOffset = Material::addSamplers(numSamplers);
|
||||
floatBufferOffset = Material::addFloats(numFloats);
|
||||
}
|
||||
|
||||
@@ -3,30 +3,43 @@
|
||||
#include "Graphics/Buffer.h"
|
||||
#include "Material.h"
|
||||
|
||||
|
||||
namespace Seele {
|
||||
struct MaterialOffsets {
|
||||
uint32 textureOffset;
|
||||
uint32 samplerOffset;
|
||||
uint32 floatOffset;
|
||||
};
|
||||
class MaterialInstance {
|
||||
public:
|
||||
MaterialInstance();
|
||||
MaterialInstance(uint64 id, Gfx::PGraphics graphics, Array<OShaderExpression>& expressions, Array<std::string> params,
|
||||
uint32 uniformBinding, uint32 uniformSize);
|
||||
uint32 numTextures, uint32 numSamplers, uint32 numFloats);
|
||||
~MaterialInstance();
|
||||
void updateDescriptor();
|
||||
Gfx::PDescriptorSet getDescriptorSet() const;
|
||||
PMaterial getBaseMaterial() const { return baseMaterial->getMaterial(); }
|
||||
uint64 getId() const { return id; }
|
||||
|
||||
void setBaseMaterial(PMaterialAsset asset);
|
||||
MaterialOffsets getMaterialOffsets() const {
|
||||
return MaterialOffsets{
|
||||
.textureOffset = texturesOffset,
|
||||
.samplerOffset = samplersOffset,
|
||||
.floatOffset = floatBufferOffset,
|
||||
};
|
||||
}
|
||||
|
||||
void save(ArchiveBuffer& buffer) const;
|
||||
void load(ArchiveBuffer& buffer);
|
||||
|
||||
private:
|
||||
Gfx::PGraphics graphics;
|
||||
Array<uint8> uniformData;
|
||||
uint32 uniformBinding;
|
||||
Gfx::OUniformBuffer uniformBuffer;
|
||||
Array<OShaderParameter> parameters;
|
||||
uint32 numTextures;
|
||||
uint32 numSamplers;
|
||||
uint32 numFloats;
|
||||
uint32 texturesOffset;
|
||||
uint32 samplersOffset;
|
||||
uint32 floatBufferOffset;
|
||||
Gfx::PDescriptorSet descriptor;
|
||||
PMaterialAsset baseMaterial;
|
||||
uint64 id;
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
#include "Graphics/Descriptor.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "Graphics/Resources.h"
|
||||
#include "Material/Material.h"
|
||||
#include <fmt/core.h>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
void ExpressionInput::save(ArchiveBuffer& buffer) const {
|
||||
@@ -48,36 +48,38 @@ void ShaderExpression::load(ArchiveBuffer& buffer) {
|
||||
Serialization::load(buffer, key);
|
||||
}
|
||||
|
||||
ShaderParameter::ShaderParameter(std::string name, uint32 byteOffset, uint32 binding)
|
||||
: ShaderExpression(name), byteOffset(byteOffset), binding(binding) {}
|
||||
ShaderParameter::ShaderParameter(std::string name, uint32 index) : ShaderExpression(name), index(index) {}
|
||||
|
||||
ShaderParameter::~ShaderParameter() {}
|
||||
|
||||
std::string ShaderParameter::evaluate(Map<std::string, std::string>& varState) const {
|
||||
varState[key] = key;
|
||||
return "";
|
||||
}
|
||||
|
||||
void ShaderParameter::save(ArchiveBuffer& buffer) const {
|
||||
ShaderExpression::save(buffer);
|
||||
Serialization::save(buffer, byteOffset);
|
||||
Serialization::save(buffer, binding);
|
||||
Serialization::save(buffer, index);
|
||||
}
|
||||
|
||||
void ShaderParameter::load(ArchiveBuffer& buffer) {
|
||||
ShaderExpression::load(buffer);
|
||||
Serialization::load(buffer, byteOffset);
|
||||
Serialization::load(buffer, binding);
|
||||
Serialization::load(buffer, index);
|
||||
}
|
||||
|
||||
FloatParameter::FloatParameter(std::string name, float data, uint32 byteOffset, uint32 binding)
|
||||
: ShaderParameter(name, byteOffset, binding), data(data) {
|
||||
FloatParameter::FloatParameter(std::string name, float data, uint32 index) : ShaderParameter(name, index), data(data) {
|
||||
output.name = name;
|
||||
output.type = ExpressionType::FLOAT;
|
||||
}
|
||||
|
||||
FloatParameter::~FloatParameter() {}
|
||||
|
||||
void FloatParameter::updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) {
|
||||
Material::updateFloatData(floatOffset + index, 1, &data);
|
||||
}
|
||||
|
||||
std::string FloatParameter::evaluate(Map<std::string, std::string>& varState) const
|
||||
{
|
||||
std::string varName = fmt::format("exp_{}", key);
|
||||
varState[key] = varName;
|
||||
return fmt::format("let {} = getMaterialFloatParameter({});\n", varName, index);
|
||||
}
|
||||
|
||||
void FloatParameter::save(ArchiveBuffer& buffer) const {
|
||||
ShaderParameter::save(buffer);
|
||||
Serialization::save(buffer, data);
|
||||
@@ -88,21 +90,23 @@ void FloatParameter::load(ArchiveBuffer& buffer) {
|
||||
Serialization::load(buffer, data);
|
||||
}
|
||||
|
||||
void FloatParameter::updateDescriptorSet(Gfx::PDescriptorSet, uint8* dst) { std::memcpy(dst + byteOffset, &data, sizeof(float)); }
|
||||
|
||||
void FloatParameter::generateDeclaration(std::ofstream& stream) const { stream << "\tfloat " << key << ";\n"; }
|
||||
|
||||
VectorParameter::VectorParameter(std::string name, Vector data, uint32 byteOffset, uint32 binding)
|
||||
: ShaderParameter(name, byteOffset, binding), data(data) {
|
||||
VectorParameter::VectorParameter(std::string name, Vector data, uint32 index)
|
||||
: ShaderParameter(name, index), data(data) {
|
||||
output.name = name;
|
||||
output.type = ExpressionType::FLOAT3;
|
||||
}
|
||||
|
||||
VectorParameter::~VectorParameter() {}
|
||||
|
||||
void VectorParameter::updateDescriptorSet(Gfx::PDescriptorSet, uint8* dst) { std::memcpy(dst + byteOffset, &data, sizeof(Vector)); }
|
||||
void VectorParameter::updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) {
|
||||
Material::updateFloatData(floatOffset + index, 3, (float*) & data);
|
||||
}
|
||||
|
||||
void VectorParameter::generateDeclaration(std::ofstream& stream) const { stream << "\tfloat3 " << key << ";\n"; }
|
||||
std::string VectorParameter::evaluate(Map<std::string, std::string>& varState) const {
|
||||
std::string varName = fmt::format("exp_{}", key);
|
||||
varState[key] = varName;
|
||||
return fmt::format("let {} = getMaterialVectorParameter({});\n", varName, index);
|
||||
}
|
||||
|
||||
void VectorParameter::save(ArchiveBuffer& buffer) const {
|
||||
ShaderParameter::save(buffer);
|
||||
@@ -114,18 +118,22 @@ void VectorParameter::load(ArchiveBuffer& buffer) {
|
||||
Serialization::load(buffer, data);
|
||||
}
|
||||
|
||||
TextureParameter::TextureParameter(std::string name, PTextureAsset asset, uint32 binding) : ShaderParameter(name, 0, binding), data(asset) {
|
||||
TextureParameter::TextureParameter(std::string name, PTextureAsset asset, uint32 index) : ShaderParameter(name, index), data(asset) {
|
||||
output.name = name;
|
||||
output.type = ExpressionType::TEXTURE;
|
||||
}
|
||||
|
||||
TextureParameter::~TextureParameter() {}
|
||||
|
||||
void TextureParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8*) {
|
||||
descriptorSet->updateTexture(binding, data->getTexture());
|
||||
void TextureParameter::updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) {
|
||||
Material::updateTexture(textureOffset + index, data->getTexture());
|
||||
}
|
||||
|
||||
void TextureParameter::generateDeclaration(std::ofstream& stream) const { stream << "\tTexture2D " << key << ";\n"; }
|
||||
std::string TextureParameter::evaluate(Map<std::string, std::string>& varState) const {
|
||||
std::string varName = fmt::format("exp_{}", key);
|
||||
varState[key] = varName;
|
||||
return fmt::format("let {} = getMaterialTextureParameter({});\n", varName, index);
|
||||
}
|
||||
|
||||
void TextureParameter::save(ArchiveBuffer& buffer) const {
|
||||
ShaderParameter::save(buffer);
|
||||
@@ -142,17 +150,23 @@ void TextureParameter::load(ArchiveBuffer& buffer) {
|
||||
data = AssetRegistry::findTexture(folder, filename);
|
||||
}
|
||||
|
||||
SamplerParameter::SamplerParameter(std::string name, Gfx::OSampler sampler, uint32 binding)
|
||||
: ShaderParameter(name, 0, binding), data(std::move(sampler)) {
|
||||
SamplerParameter::SamplerParameter(std::string name, Gfx::OSampler sampler, uint32 index)
|
||||
: ShaderParameter(name, index), data(std::move(sampler)) {
|
||||
output.name = name;
|
||||
output.type = ExpressionType::SAMPLER;
|
||||
}
|
||||
|
||||
SamplerParameter::~SamplerParameter() {}
|
||||
|
||||
void SamplerParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8*) { descriptorSet->updateSampler(binding, data); }
|
||||
void SamplerParameter::updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) {
|
||||
Material::updateSampler(samplerOffset + index, data);
|
||||
}
|
||||
|
||||
void SamplerParameter::generateDeclaration(std::ofstream& stream) const { stream << "\tSamplerState " << key << ";\n"; }
|
||||
std::string SamplerParameter::evaluate(Map<std::string, std::string>& varState) const {
|
||||
std::string varName = fmt::format("exp_{}", key);
|
||||
varState[key] = varName;
|
||||
return fmt::format("let {} = getMaterialSamplerParameter({});\n", varName, index);
|
||||
}
|
||||
|
||||
void SamplerParameter::save(ArchiveBuffer& buffer) const { ShaderParameter::save(buffer); }
|
||||
|
||||
@@ -161,19 +175,17 @@ void SamplerParameter::load(ArchiveBuffer& buffer) {
|
||||
data = buffer.getGraphics()->createSampler(SamplerCreateInfo{});
|
||||
}
|
||||
|
||||
CombinedTextureParameter::CombinedTextureParameter(std::string name, PTextureAsset data, Gfx::OSampler sampler, uint32 binding)
|
||||
: ShaderParameter(name, 0, binding), data(data), sampler(std::move(sampler)) {
|
||||
CombinedTextureParameter::CombinedTextureParameter(std::string name, PTextureAsset data, Gfx::OSampler sampler, uint32 index)
|
||||
: ShaderParameter(name, index), data(data), sampler(std::move(sampler)) {
|
||||
output.name = name;
|
||||
output.type = ExpressionType::TEXTURE;
|
||||
}
|
||||
|
||||
CombinedTextureParameter::~CombinedTextureParameter() {}
|
||||
|
||||
void CombinedTextureParameter::updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8*) {
|
||||
descriptorSet->updateTexture(binding, data->getTexture(), sampler);
|
||||
}
|
||||
void CombinedTextureParameter::updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) { assert(false); }
|
||||
|
||||
void CombinedTextureParameter::generateDeclaration(std::ofstream& stream) const { stream << "\tSampler2D " << key << ";\n"; }
|
||||
std::string CombinedTextureParameter::evaluate(Map<std::string, std::string>& varState) const { return ""; }
|
||||
|
||||
void CombinedTextureParameter::save(ArchiveBuffer& buffer) const {
|
||||
ShaderParameter::save(buffer);
|
||||
|
||||
@@ -43,18 +43,14 @@ class ShaderExpression {
|
||||
};
|
||||
DEFINE_REF(ShaderExpression)
|
||||
|
||||
DECLARE_NAME_REF(Gfx, DescriptorSet)
|
||||
struct ShaderParameter : public ShaderExpression {
|
||||
uint32 byteOffset = 0;
|
||||
uint32 binding = 0;
|
||||
uint32 index = 0;
|
||||
ShaderParameter() {}
|
||||
ShaderParameter(std::string name, uint32 byteOffset, uint32 binding);
|
||||
ShaderParameter(std::string name, uint32 index);
|
||||
virtual ~ShaderParameter();
|
||||
// update a descriptorset, in case of a uniform buffer, copy the data to the dst + byteOffset
|
||||
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) = 0;
|
||||
virtual void generateDeclaration(std::ofstream& stream) const = 0;
|
||||
virtual void updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) = 0;
|
||||
virtual uint64 getIdentifier() const override = 0;
|
||||
virtual std::string evaluate(Map<std::string, std::string>& varState) const override;
|
||||
virtual std::string evaluate(Map<std::string, std::string>& varState) const = 0;
|
||||
virtual void save(ArchiveBuffer& buffer) const override;
|
||||
virtual void load(ArchiveBuffer& buffer) override;
|
||||
};
|
||||
@@ -63,10 +59,10 @@ struct FloatParameter : public ShaderParameter {
|
||||
static constexpr uint64 IDENTIFIER = 0x01;
|
||||
float data = 0.0f;
|
||||
FloatParameter() {}
|
||||
FloatParameter(std::string name, float data, uint32 byteOffset, uint32 binding);
|
||||
FloatParameter(std::string name, float data, uint32 index);
|
||||
virtual ~FloatParameter();
|
||||
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override;
|
||||
virtual void generateDeclaration(std::ofstream& stream) const override;
|
||||
virtual void updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) override;
|
||||
virtual std::string evaluate(Map<std::string, std::string>& varState) const override;
|
||||
virtual uint64 getIdentifier() const override { return IDENTIFIER; }
|
||||
virtual void save(ArchiveBuffer& buffer) const override;
|
||||
virtual void load(ArchiveBuffer& buffer) override;
|
||||
@@ -76,10 +72,10 @@ struct VectorParameter : public ShaderParameter {
|
||||
static constexpr uint64 IDENTIFIER = 0x02;
|
||||
Vector data = Vector();
|
||||
VectorParameter() {}
|
||||
VectorParameter(std::string name, Vector data, uint32 byteOffset, uint32 binding);
|
||||
VectorParameter(std::string name, Vector data, uint32 index);
|
||||
virtual ~VectorParameter();
|
||||
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override;
|
||||
virtual void generateDeclaration(std::ofstream& stream) const override;
|
||||
virtual void updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) override;
|
||||
virtual std::string evaluate(Map<std::string, std::string>& varState) const override;
|
||||
virtual uint64 getIdentifier() const override { return IDENTIFIER; }
|
||||
virtual void save(ArchiveBuffer& buffer) const override;
|
||||
virtual void load(ArchiveBuffer& buffer) override;
|
||||
@@ -89,10 +85,10 @@ struct TextureParameter : public ShaderParameter {
|
||||
static constexpr uint64 IDENTIFIER = 0x04;
|
||||
PTextureAsset data = nullptr;
|
||||
TextureParameter() {}
|
||||
TextureParameter(std::string name, PTextureAsset data, uint32 binding);
|
||||
TextureParameter(std::string name, PTextureAsset data, uint32 index);
|
||||
virtual ~TextureParameter();
|
||||
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override;
|
||||
virtual void generateDeclaration(std::ofstream& stream) const override;
|
||||
virtual void updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) override;
|
||||
virtual std::string evaluate(Map<std::string, std::string>& varState) const override;
|
||||
virtual uint64 getIdentifier() const override { return IDENTIFIER; }
|
||||
virtual void save(ArchiveBuffer& buffer) const override;
|
||||
virtual void load(ArchiveBuffer& buffer) override;
|
||||
@@ -103,10 +99,10 @@ struct SamplerParameter : public ShaderParameter {
|
||||
static constexpr uint64 IDENTIFIER = 0x08;
|
||||
Gfx::OSampler data = nullptr;
|
||||
SamplerParameter() {}
|
||||
SamplerParameter(std::string name, Gfx::OSampler sampler, uint32 binding);
|
||||
SamplerParameter(std::string name, Gfx::OSampler sampler, uint32 index);
|
||||
virtual ~SamplerParameter();
|
||||
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override;
|
||||
virtual void generateDeclaration(std::ofstream& stream) const override;
|
||||
virtual void updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) override;
|
||||
virtual std::string evaluate(Map<std::string, std::string>& varState) const override;
|
||||
virtual uint64 getIdentifier() const override { return IDENTIFIER; }
|
||||
virtual void save(ArchiveBuffer& buffer) const override;
|
||||
virtual void load(ArchiveBuffer& buffer) override;
|
||||
@@ -117,10 +113,10 @@ struct CombinedTextureParameter : public ShaderParameter {
|
||||
PTextureAsset data = nullptr;
|
||||
Gfx::OSampler sampler = nullptr;
|
||||
CombinedTextureParameter() {}
|
||||
CombinedTextureParameter(std::string name, PTextureAsset data, Gfx::OSampler sampler, uint32 binding);
|
||||
CombinedTextureParameter(std::string name, PTextureAsset data, Gfx::OSampler sampler, uint32 index);
|
||||
virtual ~CombinedTextureParameter();
|
||||
virtual void updateDescriptorSet(Gfx::PDescriptorSet descriptorSet, uint8* dst) override;
|
||||
virtual void generateDeclaration(std::ofstream& stream) const override;
|
||||
virtual void updateDescriptorSet(uint32 textureOffset, uint32 samplerOffset, uint32 floatOffset) override;
|
||||
virtual std::string evaluate(Map<std::string, std::string>& varState) const override;
|
||||
virtual uint64 getIdentifier() const override { return IDENTIFIER; }
|
||||
virtual void save(ArchiveBuffer& buffer) const override;
|
||||
virtual void load(ArchiveBuffer& buffer) override;
|
||||
|
||||
Reference in New Issue
Block a user