From f6ebbc2067581f75357024a0ed9744882b2d6c81 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Tue, 18 Jun 2024 19:19:05 +0200 Subject: [PATCH] Adding bindless material descriptors --- res/shaders/BasePass.slang | 2 +- res/shaders/lib/Material.slang | 32 ++++ res/shaders/lib/Scene.slang | 3 + src/Editor/Asset/MaterialLoader.cpp | 52 ++---- src/Editor/Asset/MeshLoader.cpp | 45 ++--- src/Engine/Graphics/Descriptor.h | 2 + src/Engine/Graphics/Initializer.h | 6 + src/Engine/Graphics/RenderPass/BasePass.cpp | 13 +- src/Engine/Graphics/Shader.cpp | 1 - src/Engine/Graphics/VertexData.cpp | 5 + src/Engine/Graphics/VertexData.h | 3 + src/Engine/Graphics/Vulkan/Command.cpp | 2 +- src/Engine/Graphics/Vulkan/Descriptor.cpp | 63 ++++++- src/Engine/Graphics/Vulkan/Descriptor.h | 2 + src/Engine/Graphics/Vulkan/Graphics.cpp | 8 + src/Engine/Graphics/Vulkan/PipelineCache.cpp | 4 +- src/Engine/Graphics/slang-compile.cpp | 13 +- src/Engine/Material/Material.cpp | 170 ++++++++++++------- src/Engine/Material/Material.h | 28 ++- src/Engine/Material/MaterialInstance.cpp | 56 ++---- src/Engine/Material/MaterialInstance.h | 25 ++- src/Engine/Material/ShaderExpression.cpp | 84 +++++---- src/Engine/Material/ShaderExpression.h | 42 +++-- 23 files changed, 387 insertions(+), 274 deletions(-) diff --git a/res/shaders/BasePass.slang b/res/shaders/BasePass.slang index 7f9cb74..49dd3c9 100644 --- a/res/shaders/BasePass.slang +++ b/res/shaders/BasePass.slang @@ -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; diff --git a/res/shaders/lib/Material.slang b/res/shaders/lib/Material.slang index 5ffd3ed..92e9c04 100644 --- a/res/shaders/lib/Material.slang +++ b/res/shaders/lib/Material.slang @@ -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 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] + ); +} diff --git a/res/shaders/lib/Scene.slang b/res/shaders/lib/Scene.slang index 918ba1c..5666d2b 100644 --- a/res/shaders/lib/Scene.slang +++ b/res/shaders/lib/Scene.slang @@ -60,6 +60,9 @@ struct MeshletCullingInfo struct DrawCallOffsets { uint32_t instanceOffset; + uint textureOffset; + uint samplerOffset; + uint floatOffset; }; layout(push_constant) ConstantBuffer pOffsets; diff --git a/src/Editor/Asset/MaterialLoader.cpp b/src/Editor/Asset/MaterialLoader.cpp index 7d1eec1..323e808 100644 --- a/src/Editor/Asset/MaterialLoader.cpp +++ b/src/Editor/Asset/MaterialLoader.cpp @@ -44,14 +44,13 @@ void MaterialLoader::import(MaterialImportArgs args, PMaterialAsset asset) { json j; jsonstream >> j; std::string materialName = j["name"].get() + "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 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(); 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()); } - 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().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(); @@ -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(); diff --git a/src/Editor/Asset/MeshLoader.cpp b/src/Editor/Asset/MeshLoader.cpp index 9794d61..09eb525 100644 --- a/src/Editor/Asset/MeshLoader.cpp +++ b/src/Editor/Asset/MeshLoader.cpp @@ -111,32 +111,23 @@ void MeshLoader::loadMaterials(const aiScene* scene, const Array& 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 expressions; Array 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& 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& 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& 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& 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); diff --git a/src/Engine/Graphics/Descriptor.h b/src/Engine/Graphics/Descriptor.h index ae46c30..0df592e 100644 --- a/src/Engine/Graphics/Descriptor.h +++ b/src/Engine/Graphics/Descriptor.h @@ -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 texture) = 0; bool operator<(PDescriptorSet other); diff --git a/src/Engine/Graphics/Initializer.h b/src/Engine/Graphics/Initializer.h index 3aef7dc..c8a9672 100644 --- a/src/Engine/Graphics/Initializer.h +++ b/src/Engine/Graphics/Initializer.h @@ -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 { diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index ae823e9..3ba806d 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -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 { diff --git a/src/Engine/Graphics/Shader.cpp b/src/Engine/Graphics/Shader.cpp index 2b045ec..1a7fb2c 100644 --- a/src/Engine/Graphics/Shader.cpp +++ b/src/Engine/Graphics/Shader.cpp @@ -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)); }); diff --git a/src/Engine/Graphics/VertexData.cpp b/src/Engine/Graphics/VertexData.cpp index 57e168b..3444871 100644 --- a/src/Engine/Graphics/VertexData.cpp +++ b/src/Engine/Graphics/VertexData.cpp @@ -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 loadedIndices, Array loadedMeshlets) { diff --git a/src/Engine/Graphics/VertexData.h b/src/Engine/Graphics/VertexData.h index 5883b7a..4d57f1b 100644 --- a/src/Engine/Graphics/VertexData.h +++ b/src/Engine/Graphics/VertexData.h @@ -22,6 +22,9 @@ class VertexData { public: struct DrawCallOffsets { uint32 instanceOffset = 0; + uint32 textureOffset = 0; + uint32 samplerOffset = 0; + uint32 floatOffset = 0; }; struct MeshletCullingInfo { diff --git a/src/Engine/Graphics/Vulkan/Command.cpp b/src/Engine/Graphics/Vulkan/Command.cpp index 401b53b..0c2b640 100644 --- a/src/Engine/Graphics/Vulkan/Command.cpp +++ b/src/Engine/Graphics/Vulkan/Command.cpp @@ -316,7 +316,7 @@ void RenderCommand::drawMeshIndirect(Gfx::PShaderBuffer buffer, uint64 offset, u vkCmdDrawMeshTasksIndirectEXT(handle, buffer.cast()->getHandle(), offset, drawCount, stride); } -void RenderCommand::traceRays() { vkCmdTraceRaysKHR(handle, ); } +void RenderCommand::traceRays() { } ComputeCommand::ComputeCommand(PGraphics graphics, VkCommandPool cmdPool) : graphics(graphics), owner(cmdPool) { VkCommandBufferAllocateInfo allocInfo = { diff --git a/src/Engine/Graphics/Vulkan/Descriptor.cpp b/src/Engine/Graphics/Vulkan/Descriptor.cpp index fc87df6..f6f6ee4 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.cpp +++ b/src/Engine/Graphics/Vulkan/Descriptor.cpp @@ -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 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(); + 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().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().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 textures) { // maybe make this a parameter? uint32 arrayElement = 0; diff --git a/src/Engine/Graphics/Vulkan/Descriptor.h b/src/Engine/Graphics/Vulkan/Descriptor.h index 8b3fc5c..bae44d9 100644 --- a/src/Engine/Graphics/Vulkan/Descriptor.h +++ b/src/Engine/Graphics/Vulkan/Descriptor.h @@ -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 texture) override; constexpr bool isCurrentlyInUse() const { return currentlyInUse; } diff --git a/src/Engine/Graphics/Vulkan/Graphics.cpp b/src/Engine/Graphics/Vulkan/Graphics.cpp index 9d5b328..8a29dd6 100644 --- a/src/Engine/Graphics/Vulkan/Graphics.cpp +++ b/src/Engine/Graphics/Vulkan/Graphics.cpp @@ -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 = { diff --git a/src/Engine/Graphics/Vulkan/PipelineCache.cpp b/src/Engine/Graphics/Vulkan/PipelineCache.cpp index 3dc0690..fe4d641 100644 --- a/src/Engine/Graphics/Vulkan/PipelineCache.cpp +++ b/src/Engine/Graphics/Vulkan/PipelineCache.cpp @@ -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; } diff --git a/src/Engine/Graphics/slang-compile.cpp b/src/Engine/Graphics/slang-compile.cpp index 5a37d3b..b2c29d0 100644 --- a/src/Engine/Graphics/slang-compile.cpp +++ b/src/Engine/Graphics/slang-compile.cpp @@ -108,14 +108,11 @@ Slang::ComPtr 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; } diff --git a/src/Engine/Material/Material.cpp b/src/Engine/Material/Material.cpp index 5be1a2d..2d27941 100644 --- a/src/Engine/Material/Material.cpp +++ b/src/Engine/Material/Material.cpp @@ -7,92 +7,141 @@ #include "Window/WindowManager.h" #include - using namespace Seele; +Array Material::textures; +Array Material::samplers; +Gfx::OShaderBuffer Material::floatBuffer; +Array Material::floatData; +Gfx::ODescriptorLayout Material::layout; +Gfx::PDescriptorSet Material::set; std::atomic_uint64_t Material::materialIdCounter = 0; Array Material::materials; Material::Material() {} -Material::Material(Gfx::PGraphics graphics, Gfx::ODescriptorLayout layout, uint32 uniformDataSize, uint32 uniformBinding, - std::string materialName, Array expressions, Array 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 expressions, Array 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 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); } + diff --git a/src/Engine/Material/Material.h b/src/Engine/Material/Material.h index 660a4ca..07b427e 100644 --- a/src/Engine/Material/Material.h +++ b/src/Engine/Material/Material.h @@ -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 expressions, Array 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 codeExpressions; Array parameters; MaterialNode brdf; + static Array textures; + static Array samplers; + static Gfx::OShaderBuffer floatBuffer; + static Array floatData; + static Gfx::ODescriptorLayout layout; + static Gfx::PDescriptorSet set; static std::atomic_uint64_t materialIdCounter; static Array materials; }; diff --git a/src/Engine/Material/MaterialInstance.cpp b/src/Engine/Material/MaterialInstance.cpp index 913e989..5a2052e 100644 --- a/src/Engine/Material/MaterialInstance.cpp +++ b/src/Engine/Material/MaterialInstance.cpp @@ -8,18 +8,11 @@ using namespace Seele; MaterialInstance::MaterialInstance() {} MaterialInstance::MaterialInstance(uint64 id, Gfx::PGraphics graphics, Array& expressions, Array 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, ArraygetMaterial()->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); } diff --git a/src/Engine/Material/MaterialInstance.h b/src/Engine/Material/MaterialInstance.h index 7ea01c2..e7093a7 100644 --- a/src/Engine/Material/MaterialInstance.h +++ b/src/Engine/Material/MaterialInstance.h @@ -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& expressions, Array 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 uniformData; - uint32 uniformBinding; - Gfx::OUniformBuffer uniformBuffer; Array parameters; + uint32 numTextures; + uint32 numSamplers; + uint32 numFloats; + uint32 texturesOffset; + uint32 samplersOffset; + uint32 floatBufferOffset; Gfx::PDescriptorSet descriptor; PMaterialAsset baseMaterial; uint64 id; diff --git a/src/Engine/Material/ShaderExpression.cpp b/src/Engine/Material/ShaderExpression.cpp index 31281bc..b626cb4 100644 --- a/src/Engine/Material/ShaderExpression.cpp +++ b/src/Engine/Material/ShaderExpression.cpp @@ -4,10 +4,10 @@ #include "Graphics/Descriptor.h" #include "Graphics/Graphics.h" #include "Graphics/Resources.h" +#include "Material/Material.h" #include #include - 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& 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& 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& 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& 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& 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& varState) const { return ""; } void CombinedTextureParameter::save(ArchiveBuffer& buffer) const { ShaderParameter::save(buffer); diff --git a/src/Engine/Material/ShaderExpression.h b/src/Engine/Material/ShaderExpression.h index a70dd23..2547284 100644 --- a/src/Engine/Material/ShaderExpression.h +++ b/src/Engine/Material/ShaderExpression.h @@ -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& varState) const override; + virtual std::string evaluate(Map& 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& 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& 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& 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& 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& varState) const override; virtual uint64 getIdentifier() const override { return IDENTIFIER; } virtual void save(ArchiveBuffer& buffer) const override; virtual void load(ArchiveBuffer& buffer) override;