Finished writeup and fixed crashes

This commit is contained in:
Dynamitos
2021-10-19 23:04:38 +02:00
parent a0693daa67
commit 451572f254
36 changed files with 295 additions and 375 deletions
-4
View File
@@ -2,11 +2,7 @@ target_sources(SeeleEngine
PRIVATE
BRDF.h
BRDF.cpp
Material.h
Material.cpp
MaterialAsset.h
MaterialAsset.cpp
MaterialInstance.h
MaterialInstance.cpp
ShaderExpression.h
ShaderExpression.cpp)
-162
View File
@@ -1,162 +0,0 @@
#include "Material.h"
#include "Asset/AssetRegistry.h"
#include "Graphics/VertexShaderInput.h"
#include "BRDF.h"
#include "Window/WindowManager.h"
#include <nlohmann/json.hpp>
#include <sstream>
#include <iostream>
Gfx::ShaderMap Material::shaderMap;
std::mutex Material::shaderMapLock;
using namespace Seele;
using json = nlohmann::json;
Material::Material()
{
}
Material::Material(const std::string& directory, const std::string& name)
: MaterialAsset(directory, name)
{
}
Material::Material(const std::filesystem::path& fullPath)
: MaterialAsset(fullPath)
{
}
Material::~Material()
{
}
void Material::save()
{
}
void Material::load()
{
}
void Material::compile()
{
setStatus(Status::Loading);
auto& stream = getReadStream();
json j;
stream >> j;
materialName = j["name"].get<std::string>();
layout = WindowManager::getGraphics()->createDescriptorLayout(materialName + "Layout");
//Shader file needs to conform to the slang standard, which prohibits _
materialName.erase(std::remove(materialName.begin(), materialName.end(), '_'), materialName.end());
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
std::string profile = j["profile"].get<std::string>();
codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl;
codeStream << "import Material;" << std::endl;
codeStream << "import BRDF;" << std::endl;
codeStream << "import MaterialParameter;" << std::endl << std::endl;
codeStream << "struct " << materialName << " : IMaterial {" << std::endl;
uint32 uniformBufferOffset = 0;
uint32 bindingCounter = 0; // Uniform buffers are always binding 0
uniformBinding = -1;
for(auto param : j["params"].items())
{
std::string type = param.value()["type"].get<std::string>();
auto defaultValue = param.value().find("default");
if(type.compare("float") == 0)
{
PFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, 0);
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
if(uniformBinding == -1)
{
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformBinding = bindingCounter++;
}
uniformBufferOffset += 4;
if(defaultValue != param.value().end())
{
p->data = std::stof(defaultValue.value().get<std::string>());
}
parameters.add(p);
}
else if(type.compare("float3") == 0)
{
PVectorParameter p = new VectorParameter(param.key(), uniformBufferOffset, 0);
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
if(uniformBinding == -1)
{
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformBinding = bindingCounter++;
}
uniformBufferOffset += 12;
if(defaultValue != param.value().end())
{
p->data = parseVector(defaultValue.value().get<std::string>().c_str());
}
parameters.add(p);
}
else if(type.compare("Texture2D") == 0)
{
PTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter);
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
if(defaultValue != param.value().end())
{
std::string defaultString = defaultValue.value().get<std::string>();
p->data = AssetRegistry::findTexture(defaultString);
}
else
{
p->data = AssetRegistry::findTexture(""); // this will return placeholder texture
}
assert(p->data != nullptr);
parameters.add(p);
}
else if(type.compare("SamplerState") == 0)
{
PSamplerParameter p = new SamplerParameter(param.key(), 0, bindingCounter);
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
SamplerCreateInfo createInfo;
p->data = WindowManager::getGraphics()->createSamplerState(createInfo);
parameters.add(p);
}
else
{
std::cout << "Error unsupported parameter type" << std::endl;
}
codeStream << "\t" << type << " " << param.key() << ";\n";
}
uniformDataSize = uniformBufferOffset;
if(uniformDataSize != 0)
{
uniformData = new uint8[uniformDataSize];
UniformBufferCreateInfo uniformInitializer;
uniformInitializer.resourceData.data = uniformData;
uniformInitializer.resourceData.size = uniformDataSize;
uniformBuffer = WindowManager::getGraphics()->createUniformBuffer(uniformInitializer);
}
BRDF* brdf = BRDF::getBRDFByName(profile);
brdf->generateMaterialCode(codeStream, j["code"]);
codeStream << "};";
codeStream.close();
layout->create();
setStatus(Status::Ready);
}
const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
{
Gfx::ShaderPermutation permutation;
permutation.passType = renderPass;
std::string vertexInputName = vertexInput->getName();
std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName));
std::memcpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName));
return shaderMap.findShaders(Gfx::PermutationId(permutation));
}
Gfx::ShaderCollection& Material::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
{
std::lock_guard lock(shaderMapLock);
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
}
-34
View File
@@ -1,34 +0,0 @@
#pragma once
#include "MinimalEngine.h"
#include "MaterialAsset.h"
namespace Seele
{
class VertexInputType;
class Material : public MaterialAsset
{
public:
Material();
Material(const std::string &directory, const std::string &name);
Material(const std::filesystem::path& fullPath);
~Material();
virtual void save() override;
virtual void load() override;
virtual const Material* getRenderMaterial() const { return this; }
Gfx::PDescriptorLayout getDescriptorLayout() const { return layout; }
// The name of the generated material shader, opposed to the name of the .asset file
const std::string& getName() {return materialName;}
const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const;
Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput);
void compile();
private:
static Gfx::ShaderMap shaderMap;
static std::mutex shaderMapLock;
std::string materialName;
friend class MaterialLoader;
friend class MaterialInstance;
};
DEFINE_REF(Material)
} // namespace Seele
+137 -3
View File
@@ -1,5 +1,16 @@
#include "MaterialAsset.h"
#include "Window/WindowManager.h"
#include "Asset/AssetRegistry.h"
#include "BRDF.h"
#include <nlohmann/json.hpp>
#include <sstream>
#include <iostream>
Gfx::ShaderMap MaterialAsset::shaderMap;
std::mutex MaterialAsset::shaderMapLock;
using namespace Seele;
using json = nlohmann::json;
using namespace Seele;
@@ -21,6 +32,118 @@ MaterialAsset::~MaterialAsset()
{
}
void MaterialAsset::save()
{
assert(false && "TODO");
}
void MaterialAsset::load()
{
setStatus(Status::Loading);
auto& stream = getReadStream();
json j;
stream >> j;
materialName = j["name"].get<std::string>();
layout = WindowManager::getGraphics()->createDescriptorLayout(materialName + "Layout");
//Shader file needs to conform to the slang standard, which prohibits _
materialName.erase(std::remove(materialName.begin(), materialName.end(), '_'), materialName.end());
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
std::string profile = j["profile"].get<std::string>();
codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl;
codeStream << "import Material;" << std::endl;
codeStream << "import BRDF;" << std::endl;
codeStream << "import MaterialParameter;" << std::endl << std::endl;
codeStream << "struct " << materialName << " : IMaterial {" << std::endl;
uint32 uniformBufferOffset = 0;
uint32 bindingCounter = 0; // Uniform buffers are always binding 0
uniformBinding = -1;
for(auto param : j["params"].items())
{
std::string type = param.value()["type"].get<std::string>();
auto defaultValue = param.value().find("default");
if(type.compare("float") == 0)
{
PFloatParameter p = new FloatParameter(param.key(), uniformBufferOffset, 0);
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
if(uniformBinding == -1)
{
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformBinding = bindingCounter++;
}
uniformBufferOffset += 4;
if(defaultValue != param.value().end())
{
p->data = std::stof(defaultValue.value().get<std::string>());
}
parameters.add(p);
}
else if(type.compare("float3") == 0)
{
PVectorParameter p = new VectorParameter(param.key(), uniformBufferOffset, 0);
codeStream << "\tlayout(offset = " << uniformBufferOffset << ")";
if(uniformBinding == -1)
{
layout->addDescriptorBinding(bindingCounter, Gfx::SE_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
uniformBinding = bindingCounter++;
}
uniformBufferOffset += 12;
if(defaultValue != param.value().end())
{
p->data = parseVector(defaultValue.value().get<std::string>().c_str());
}
parameters.add(p);
}
else if(type.compare("Texture2D") == 0)
{
PTextureParameter p = new TextureParameter(param.key(), 0, bindingCounter);
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
if(defaultValue != param.value().end())
{
std::string defaultString = defaultValue.value().get<std::string>();
p->data = AssetRegistry::findTexture(defaultString);
}
else
{
p->data = AssetRegistry::findTexture(""); // this will return placeholder texture
}
assert(p->data != nullptr);
parameters.add(p);
}
else if(type.compare("SamplerState") == 0)
{
PSamplerParameter p = new SamplerParameter(param.key(), 0, bindingCounter);
layout->addDescriptorBinding(bindingCounter++, Gfx::SE_DESCRIPTOR_TYPE_SAMPLER);
SamplerCreateInfo createInfo;
p->data = WindowManager::getGraphics()->createSamplerState(createInfo);
parameters.add(p);
}
else
{
std::cout << "Error unsupported parameter type" << std::endl;
}
codeStream << "\t" << type << " " << param.key() << ";\n";
}
uniformDataSize = uniformBufferOffset;
if(uniformDataSize != 0)
{
uniformData = new uint8[uniformDataSize];
UniformBufferCreateInfo uniformInitializer;
uniformInitializer.resourceData.data = uniformData;
uniformInitializer.resourceData.size = uniformDataSize;
uniformBuffer = WindowManager::getGraphics()->createUniformBuffer(uniformInitializer);
}
BRDF* brdf = BRDF::getBRDFByName(profile);
brdf->generateMaterialCode(codeStream, j["code"]);
codeStream << "};";
codeStream.close();
layout->create();
setStatus(Status::Ready);
}
void MaterialAsset::beginFrame()
{
}
@@ -48,7 +171,18 @@ void MaterialAsset::updateDescriptorData()
descriptorSet->writeChanges();
}
const Gfx::PDescriptorSet MaterialAsset::getDescriptor() const
const Gfx::ShaderCollection* MaterialAsset::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
{
return descriptorSet;
}
Gfx::ShaderPermutation permutation;
permutation.passType = renderPass;
std::string vertexInputName = vertexInput->getName();
std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName));
std::memcpy(permutation.vertexInputName, vertexInputName.c_str(), sizeof(permutation.vertexInputName));
return shaderMap.findShaders(Gfx::PermutationId(permutation));
}
Gfx::ShaderCollection& MaterialAsset::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput)
{
std::unique_lock lock(shaderMapLock);
return shaderMap.createShaders(graphics, renderPass, this, vertexInput, false);
}
+14 -6
View File
@@ -6,7 +6,6 @@
namespace Seele
{
DECLARE_REF(VertexShaderInput)
DECLARE_REF(Material)
class MaterialAsset : public Asset
{
public:
@@ -16,18 +15,26 @@ public:
~MaterialAsset();
virtual void beginFrame();
virtual void endFrame();
virtual void save() = 0;
virtual void load() = 0;
virtual const Material* getRenderMaterial() const = 0;
virtual void save() override;
virtual void load() override;
Gfx::SeBlendOp getBlendMode() const {return Gfx::SE_BLEND_OP_END_RANGE;}
Gfx::MaterialShadingModel getShadingModel() const {return Gfx::MaterialShadingModel::DefaultLit;}
// This needs to be called while the descriptorset is unused
void updateDescriptorData();
void resetDescriptorSet();
const Gfx::PDescriptorSet getDescriptor() const;
const Gfx::PDescriptorSet getDescriptor() const { return descriptorSet; };
Gfx::PDescriptorLayout getDescriptorLayout() const { return layout; }
// The name of the generated material shader, opposed to the name of the .asset file
const std::string& getName() {return materialName;}
const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const;
Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, VertexInputType* vertexInput);
private:
static Gfx::ShaderMap shaderMap;
static std::mutex shaderMapLock;
protected:
//For now its simply the collection of parameters, since there is no point for expressions
Array<PShaderParameter> parameters;
Gfx::PDescriptorSet descriptorSet;
@@ -36,6 +43,7 @@ protected:
uint32 uniformDataSize;
uint8* uniformData;
int32 uniformBinding;
std::string materialName;
};
DEFINE_REF(MaterialAsset)
} // namespace Seele
-42
View File
@@ -1,42 +0,0 @@
#include "MaterialInstance.h"
#include "Material.h"
#include "Window/WindowManager.h"
using namespace Seele;
MaterialInstance::MaterialInstance()
{
}
MaterialInstance::MaterialInstance(const std::string& directory, const std::string& name)
: MaterialAsset(directory, name)
{
}
MaterialInstance::MaterialInstance(const std::filesystem::path& fullPath)
: MaterialAsset(fullPath)
{
}
MaterialInstance::~MaterialInstance()
{
}
void MaterialInstance::save()
{
}
void MaterialInstance::load()
{
baseMaterial = nullptr; // TODO: actually load the file
UniformBufferCreateInfo uniformInitializer;
uniformInitializer.resourceData.size = baseMaterial->uniformDataSize;
uniformInitializer.resourceData.data = nullptr;
uniformBuffer = WindowManager::getGraphics()->createUniformBuffer(uniformInitializer);
}
const Material* MaterialInstance::getRenderMaterial() const
{
return baseMaterial;
}
-22
View File
@@ -1,22 +0,0 @@
#pragma once
#include "MaterialAsset.h"
namespace Seele
{
DECLARE_NAME_REF(Gfx, DescriptorSet)
DECLARE_REF(Material)
class MaterialInstance : public MaterialAsset
{
public:
MaterialInstance();
MaterialInstance(const std::string& directory, const std::string& name);
MaterialInstance(const std::filesystem::path& fullPath);
~MaterialInstance();
virtual void save() override;
virtual void load() override;
virtual const Material* getRenderMaterial() const;
private:
Material* baseMaterial;
};
DEFINE_REF(MaterialInstance)
} // namespace Seele