Improving Material shader code generation
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include "Asset.h"
|
||||
#include "AssetRegistry.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
@@ -11,9 +12,18 @@ Asset::Asset()
|
||||
{
|
||||
}
|
||||
Asset::Asset(const std::filesystem::path& path)
|
||||
: fullPath(std::filesystem::absolute(path))
|
||||
, status(Status::Uninitialized)
|
||||
: status(Status::Uninitialized)
|
||||
{
|
||||
if(path.is_absolute())
|
||||
{
|
||||
fullPath = path;
|
||||
}
|
||||
else
|
||||
{
|
||||
fullPath = AssetRegistry::getRootFolder();
|
||||
fullPath.append(path.generic_string());
|
||||
}
|
||||
|
||||
fullPath.make_preferred();
|
||||
parentDir = fullPath.parent_path();
|
||||
name = fullPath.stem();
|
||||
@@ -49,15 +59,15 @@ std::ofstream &Asset::getWriteStream()
|
||||
return outStream;
|
||||
}
|
||||
|
||||
std::string Asset::getFileName()
|
||||
std::string Asset::getFileName() const
|
||||
{
|
||||
return name.generic_string();
|
||||
}
|
||||
std::string Asset::getFullPath()
|
||||
std::string Asset::getFullPath() const
|
||||
{
|
||||
return fullPath.generic_string();
|
||||
}
|
||||
std::string Asset::getExtension()
|
||||
std::string Asset::getExtension() const
|
||||
{
|
||||
return extension.generic_string();
|
||||
}
|
||||
@@ -23,11 +23,11 @@ public:
|
||||
virtual void load() = 0;
|
||||
|
||||
// returns the name of the file, without extension
|
||||
std::string getFileName();
|
||||
std::string getFileName() const;
|
||||
// returns the full absolute path, from root to extension
|
||||
std::string getFullPath();
|
||||
std::string getFullPath() const;
|
||||
// returns the file extension, without preceding dot
|
||||
std::string getExtension();
|
||||
std::string getExtension() const;
|
||||
inline Status getStatus()
|
||||
{
|
||||
std::scoped_lock lck(lock);
|
||||
@@ -44,6 +44,7 @@ protected:
|
||||
std::ofstream& getWriteStream();
|
||||
private:
|
||||
Status status;
|
||||
// Path relative to the project root
|
||||
std::filesystem::path fullPath;
|
||||
std::filesystem::path parentDir;
|
||||
std::filesystem::path name;
|
||||
|
||||
@@ -28,16 +28,16 @@ void AssetRegistry::importFile(const std::string &filePath)
|
||||
if (extension.compare(".fbx") == 0
|
||||
|| extension.compare(".obj") == 0)
|
||||
{
|
||||
get().registerMesh(fsPath);
|
||||
get().importMesh(fsPath);
|
||||
}
|
||||
if (extension.compare(".png") == 0
|
||||
|| extension.compare(".jpg") == 0)
|
||||
{
|
||||
get().registerTexture(fsPath);
|
||||
get().importTexture(fsPath);
|
||||
}
|
||||
if (extension.compare(".semat") == 0)
|
||||
{
|
||||
get().registerMaterial(fsPath);
|
||||
get().importMaterial(fsPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,16 @@ PMaterialAsset AssetRegistry::findMaterial(const std::string &filePath)
|
||||
return get().materials[filePath];
|
||||
}
|
||||
|
||||
std::ofstream AssetRegistry::createWriteStream(const std::string& relativePath, std::ios_base::openmode openmode)
|
||||
{
|
||||
return get().internalCreateWriteStream(relativePath, openmode);
|
||||
}
|
||||
|
||||
std::ifstream AssetRegistry::createReadStream(const std::string& relativePath, std::ios_base::openmode openmode)
|
||||
{
|
||||
return get().internalCreateReadStream(relativePath, openmode);
|
||||
}
|
||||
|
||||
PTextureAsset AssetRegistry::findTexture(const std::string &filePath)
|
||||
{
|
||||
return get().textures[filePath];
|
||||
@@ -75,17 +85,49 @@ void AssetRegistry::init(const std::filesystem::path &rootFolder, Gfx::PGraphics
|
||||
reg.materialLoader = new MaterialLoader(graphics);
|
||||
}
|
||||
|
||||
void AssetRegistry::registerMesh(const std::filesystem::path &filePath)
|
||||
std::string AssetRegistry::getRootFolder()
|
||||
{
|
||||
return get().rootFolder.generic_string();
|
||||
}
|
||||
|
||||
void AssetRegistry::importMesh(const std::filesystem::path &filePath)
|
||||
{
|
||||
meshLoader->importAsset(filePath);
|
||||
}
|
||||
|
||||
void AssetRegistry::registerTexture(const std::filesystem::path &filePath)
|
||||
void AssetRegistry::importTexture(const std::filesystem::path &filePath)
|
||||
{
|
||||
textureLoader->importAsset(filePath);
|
||||
}
|
||||
|
||||
void AssetRegistry::registerMaterial(const std::filesystem::path &filePath)
|
||||
void AssetRegistry::importMaterial(const std::filesystem::path &filePath)
|
||||
{
|
||||
materialLoader->queueAsset(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRegistry::registerMesh(PMeshAsset mesh)
|
||||
{
|
||||
PMeshAsset existingMesh = meshes[mesh->getFileName()];
|
||||
if(existingMesh != nullptr)
|
||||
{
|
||||
auto newMeshes = mesh->getMeshes();
|
||||
for(uint32 i = 0; i < newMeshes.size(); ++i)
|
||||
{
|
||||
existingMesh->addMesh(newMeshes[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
meshes[mesh->getFileName()] = mesh;
|
||||
}
|
||||
}
|
||||
|
||||
std::ofstream AssetRegistry::internalCreateWriteStream(const std::string& relativePath, std::ios_base::openmode openmode)
|
||||
{
|
||||
return std::ofstream(rootFolder.generic_string().append(relativePath), openmode);
|
||||
}
|
||||
|
||||
std::ifstream AssetRegistry::internalCreateReadStream(const std::string& relativePath, std::ios_base::openmode openmode)
|
||||
{
|
||||
return std::ifstream(rootFolder.generic_string().append(relativePath), openmode);
|
||||
}
|
||||
|
||||
@@ -18,21 +18,33 @@ public:
|
||||
~AssetRegistry();
|
||||
static void init(const std::string& rootFolder);
|
||||
|
||||
static std::string getRootFolder();
|
||||
|
||||
static void importFile(const std::string& filePath);
|
||||
|
||||
static PMeshAsset findMesh(const std::string& filePath);
|
||||
static PTextureAsset findTexture(const std::string& filePath);
|
||||
static PMaterialAsset findMaterial(const std::string& filePath);
|
||||
|
||||
static std::ofstream createWriteStream(const std::string& relativePath, std::ios_base::openmode openmode = 0);
|
||||
static std::ifstream createReadStream(const std::string& relativePath, std::ios_base::openmode openmode = 0);
|
||||
private:
|
||||
static AssetRegistry& get();
|
||||
|
||||
AssetRegistry();
|
||||
void init(const std::filesystem::path& rootFolder, Gfx::PGraphics graphics);
|
||||
|
||||
void registerMesh(const std::filesystem::path& filePath);
|
||||
void registerTexture(const std::filesystem::path& filePath);
|
||||
void registerMaterial(const std::filesystem::path& filePath);
|
||||
|
||||
void importMesh(const std::filesystem::path& filePath);
|
||||
void importTexture(const std::filesystem::path& filePath);
|
||||
void importMaterial(const std::filesystem::path& filePath);
|
||||
|
||||
void registerMesh(PMeshAsset mesh);
|
||||
void registerTexture(PTextureAsset texture);
|
||||
void registerMaterial(PMaterialAsset material);
|
||||
|
||||
std::ofstream internalCreateWriteStream(const std::string& relativePath, std::ios_base::openmode openmode = 0);
|
||||
std::ifstream internalCreateReadStream(const std::string& relaitvePath, std::ios_base::openmode openmode = 0);
|
||||
|
||||
std::filesystem::path rootFolder;
|
||||
Map<std::string, PTextureAsset> textures;
|
||||
Map<std::string, PMeshAsset> meshes;
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
using namespace Seele;
|
||||
|
||||
MaterialLoader::MaterialLoader(Gfx::PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
placeholderMaterial = new Material("shaders/Placeholder.semat");
|
||||
placeholderMaterial = new Material(std::filesystem::absolute("./shaders/Placeholder.asset"));
|
||||
placeholderMaterial->compile();
|
||||
graphics->getShaderCompiler()->registerMaterial(placeholderMaterial);
|
||||
}
|
||||
|
||||
MaterialLoader::~MaterialLoader()
|
||||
@@ -17,6 +19,8 @@ MaterialLoader::~MaterialLoader()
|
||||
PMaterial MaterialLoader::queueAsset(const std::filesystem::path& filePath)
|
||||
{
|
||||
PMaterial result = new Material(filePath);
|
||||
result->compile();
|
||||
graphics->getShaderCompiler()->registerMaterial(result);
|
||||
// TODO: There is actually no real reason to import a standalone material,
|
||||
// maybe in the future there could be a substance loader or something
|
||||
return result;
|
||||
|
||||
@@ -16,6 +16,7 @@ public:
|
||||
~MaterialLoader();
|
||||
PMaterial queueAsset(const std::filesystem::path& filePath);
|
||||
private:
|
||||
Gfx::PGraphics graphics;
|
||||
List<std::future<void>> futures;
|
||||
PMaterial placeholderMaterial;
|
||||
};
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
#include "Graphics/Graphics.h"
|
||||
#include "MeshAsset.h"
|
||||
#include "Graphics/Mesh.h"
|
||||
#include "Graphics/StaticMeshVertexInput.h"
|
||||
#include "AssetRegistry.h"
|
||||
#include "Material/Material.h"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <stb_image_write.h>
|
||||
#include <assimp/config.h>
|
||||
@@ -27,7 +29,8 @@ MeshLoader::~MeshLoader()
|
||||
|
||||
void MeshLoader::importAsset(const std::filesystem::path &path)
|
||||
{
|
||||
futures.add(std::async(std::launch::async, &MeshLoader::import, this, path));
|
||||
//futures.add(std::async(std::launch::async, &MeshLoader::import, this, path));
|
||||
import(path);
|
||||
}
|
||||
|
||||
void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials, Gfx::PGraphics graphics)
|
||||
@@ -52,7 +55,7 @@ void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials,
|
||||
matCode["params"]["diffuseTexture"] =
|
||||
{
|
||||
{"type", "Texture2D"},
|
||||
{"default", texFilename}
|
||||
{"default", texPath.C_Str()}
|
||||
};
|
||||
code.push_back("result.baseColor = diffuseTexture.Sample(textureSampler, geometry.texCoord).xyz;\n");
|
||||
}
|
||||
@@ -62,7 +65,7 @@ void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials,
|
||||
matCode["params"]["specularTexture"] =
|
||||
{
|
||||
{"type", "Texture2D"},
|
||||
{"default", texFilename}
|
||||
{"default", texPath.C_Str()}
|
||||
};
|
||||
code.push_back("result.specular = specularTexture.Sample(textureSampler, geometry.texCoord).xyz;\n");
|
||||
}
|
||||
@@ -72,7 +75,7 @@ void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials,
|
||||
matCode["params"]["normalTexture"] =
|
||||
{
|
||||
{"type", "Texture2D"},
|
||||
{"default", texFilename}
|
||||
{"default", texPath.C_Str()}
|
||||
};
|
||||
code.push_back("float3 bumpMapNormal = normalTexture.Sample(textureSampler, geometry.texCoord).xyz;\n");
|
||||
code.push_back("bumpMapNormal = 2.0 * bumpMapNormal - float3(1.0f, 1.0f, 1.0f);\n");
|
||||
@@ -80,10 +83,15 @@ void loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials,
|
||||
}
|
||||
code.push_back("return result;\n");
|
||||
matCode["code"] = code;
|
||||
std::ofstream outMatFile("testMat.asset");
|
||||
std::string outMatFilename = matCode["name"].get<std::string>().append(".asset");
|
||||
std::ofstream outMatFile = AssetRegistry::createWriteStream(outMatFilename);
|
||||
outMatFile << std::setw(4) << matCode;
|
||||
outMatFile.flush();
|
||||
PMaterial asset = new Material("testMat.asset");
|
||||
outMatFile.close();
|
||||
//TODO: let the material loader handle this instead
|
||||
std::cout << matCode["name"] << std::endl;
|
||||
AssetRegistry::importFile(outMatFilename);
|
||||
PMaterialAsset asset = AssetRegistry::findMaterial(outMatFilename);
|
||||
globalMaterials[i] = asset;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +116,7 @@ void loadToBuffer(Array<Vector>& buffer, const aiVector3D* sourceData, uint32 si
|
||||
buffer[i] = Vector(sourceData[i].x, sourceData[i].y, sourceData[i].z);
|
||||
}
|
||||
}
|
||||
Gfx::VertexStream createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::PGraphics graphics)
|
||||
VertexStreamComponent createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::PGraphics graphics)
|
||||
{
|
||||
Array<Vector> buffer(size);
|
||||
for(uint32 i = 0; i < size; ++i)
|
||||
@@ -121,12 +129,10 @@ Gfx::VertexStream createVertexStream(uint32 size, aiVector3D* sourceData, Gfx::P
|
||||
vbInfo.resourceData.data = (uint8 *)buffer.data();
|
||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
vbInfo.resourceData.size = buffer.size();
|
||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
auto stream = Gfx::VertexStream(vbInfo.vertexSize, 0, false, vertexBuffer);
|
||||
stream.addVertexElement(Gfx::VertexElement(0, Gfx::SE_FORMAT_R32G32_SFLOAT, 0));
|
||||
return stream;
|
||||
const Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32B32_SFLOAT);
|
||||
}
|
||||
Gfx::VertexStream createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics)
|
||||
VertexStreamComponent createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::PGraphics graphics)
|
||||
{
|
||||
Array<Vector2> buffer(size);
|
||||
for(uint32 i = 0; i < size; ++i)
|
||||
@@ -140,9 +146,7 @@ Gfx::VertexStream createVertexStream(uint32 size, aiVector2D* sourceData, Gfx::P
|
||||
vbInfo.resourceData.owner = Gfx::QueueType::DEDICATED_TRANSFER;
|
||||
vbInfo.resourceData.size = buffer.size();
|
||||
Gfx::PVertexBuffer vertexBuffer = graphics->createVertexBuffer(vbInfo);
|
||||
auto stream = Gfx::VertexStream(vbInfo.vertexSize, 0, false, vertexBuffer);
|
||||
stream.addVertexElement(Gfx::VertexElement(0, Gfx::SE_FORMAT_R32G32B32_SFLOAT, 0));
|
||||
return stream;
|
||||
return VertexStreamComponent(vertexBuffer, 0, vbInfo.vertexSize, Gfx::SE_FORMAT_R32G32_SFLOAT);
|
||||
}
|
||||
void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, Array<PMaterialAsset> materials, Gfx::PGraphics graphics)
|
||||
{
|
||||
@@ -150,32 +154,29 @@ void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, Array<PM
|
||||
{
|
||||
aiMesh *mesh = scene->mMeshes[meshIndex];
|
||||
|
||||
MeshDescription description;
|
||||
Gfx::PVertexDeclaration declaration = new Gfx::VertexDeclaration();
|
||||
declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics));
|
||||
description.layout.add(Gfx::VertexAttribute::POSITION);
|
||||
PStaticMeshVertexInput vertexShaderInput = new StaticMeshVertexInput(std::string(mesh->mName.C_Str()));
|
||||
VertexStreamComponent positionStream = createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics);
|
||||
vertexShaderInput->setPositionStream(positionStream);
|
||||
|
||||
for(uint32 i = 0; i < MAX_TEX_CHANNELS; ++i)
|
||||
for(uint32 i = 0; i < MAX_TEXCOORDS; ++i)
|
||||
{
|
||||
if(mesh->HasTextureCoords(i))
|
||||
{
|
||||
declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mTextureCoords[i], graphics));
|
||||
description.layout.add(Gfx::VertexAttribute::TEXCOORD);
|
||||
VertexStreamComponent texCoordStream = createVertexStream(mesh->mNumVertices, mesh->mTextureCoords[i], graphics);
|
||||
vertexShaderInput->setTexCoordStream(i, texCoordStream);
|
||||
}
|
||||
}
|
||||
if(mesh->HasNormals())
|
||||
{
|
||||
declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mNormals, graphics));
|
||||
description.layout.add(Gfx::VertexAttribute::NORMAL);
|
||||
VertexStreamComponent normalStream = createVertexStream(mesh->mNumVertices, mesh->mNormals, graphics);
|
||||
vertexShaderInput->setTangentXStream(normalStream);
|
||||
}
|
||||
if(mesh->HasTangentsAndBitangents())
|
||||
{
|
||||
declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics));
|
||||
declaration->addVertexStream(createVertexStream(mesh->mNumVertices, mesh->mVertices, graphics));
|
||||
description.layout.add(Gfx::VertexAttribute::TANGENT);
|
||||
description.layout.add(Gfx::VertexAttribute::BITANGENT);
|
||||
//TODO: use bitangent to calculate sign for 4th coordinate of tangentstream
|
||||
VertexStreamComponent tangentStream = createVertexStream(mesh->mNumVertices, mesh->mTangents, graphics);
|
||||
vertexShaderInput->setTangentZStream(tangentStream);
|
||||
}
|
||||
description.declaration = declaration;
|
||||
|
||||
Array<uint32> indices(mesh->mNumFaces * 3);
|
||||
for (uint32 faceIndex = 0; faceIndex < mesh->mNumFaces; ++faceIndex)
|
||||
@@ -192,7 +193,7 @@ void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, Array<PM
|
||||
Gfx::PIndexBuffer indexBuffer = graphics->createIndexBuffer(idxInfo);
|
||||
indexBuffer->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
|
||||
globalMeshes[meshIndex] = new Mesh(description, indexBuffer);
|
||||
globalMeshes[meshIndex] = new Mesh(vertexShaderInput, indexBuffer);
|
||||
globalMeshes[meshIndex]->referencedMaterial = materials[mesh->mMaterialIndex];
|
||||
}
|
||||
}
|
||||
@@ -247,23 +248,27 @@ void MeshLoader::import(const std::filesystem::path &path)
|
||||
aiProcess_FindDegenerates |
|
||||
aiProcess_EmbedTextures);
|
||||
const aiScene *scene = importer.ApplyPostProcessing(aiProcess_CalcTangentSpace);
|
||||
Array<PMesh> globalMeshes(scene->mNumMeshes);
|
||||
|
||||
Array<PMaterialAsset> globalMaterials(scene->mNumMaterials);
|
||||
loadMaterials(scene, globalMaterials, graphics);
|
||||
loadGlobalMeshes(scene, globalMeshes, globalMaterials, graphics);
|
||||
loadTextures(scene, graphics, path);
|
||||
loadMaterials(scene, globalMaterials, graphics);
|
||||
|
||||
Array<PMesh> globalMeshes(scene->mNumMeshes);
|
||||
loadGlobalMeshes(scene, globalMeshes, globalMaterials, graphics);
|
||||
|
||||
|
||||
List<aiNode *> meshNodes;
|
||||
findMeshRoots(scene->mRootNode, meshNodes);
|
||||
std::filesystem::path filePath = path.filename();
|
||||
filePath.replace_extension("asset");
|
||||
PMeshAsset meshAsset = new MeshAsset(filePath.generic_string());
|
||||
for (auto meshNode : meshNodes)
|
||||
{
|
||||
std::string fileName = std::string("arissa").append(".asset");
|
||||
PMeshAsset meshAsset = new MeshAsset(fileName);
|
||||
for(uint32 i = 0; i < meshNode->mNumMeshes; ++i)
|
||||
{
|
||||
meshAsset->addMesh(globalMeshes[meshNode->mMeshes[i]]);
|
||||
}
|
||||
meshAsset->save();
|
||||
AssetRegistry::get().meshes[meshAsset->getFileName()] = meshAsset;
|
||||
}
|
||||
meshAsset->save();
|
||||
AssetRegistry::get().registerMesh(meshAsset);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,7 @@ using namespace Seele;
|
||||
TextureLoader::TextureLoader(Gfx::PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
import("textures/placeholder.png");
|
||||
placeholderTexture = AssetRegistry::findTexture("textures/placeholder.png");
|
||||
placeholderTexture = import("./textures/placeholder.png");
|
||||
}
|
||||
|
||||
TextureLoader::~TextureLoader()
|
||||
@@ -22,15 +21,20 @@ TextureLoader::~TextureLoader()
|
||||
|
||||
void TextureLoader::importAsset(const std::filesystem::path& filePath)
|
||||
{
|
||||
futures.add(std::async(std::launch::async, &TextureLoader::import, this, filePath));
|
||||
auto assetFileName = filePath;
|
||||
PTextureAsset asset = new TextureAsset(assetFileName.replace_extension("asset").filename().generic_string());
|
||||
asset->setStatus(Asset::Status::Loading);
|
||||
asset->setTexture(placeholderTexture);
|
||||
AssetRegistry::get().textures[filePath.string()] = asset;
|
||||
futures.add(std::async(std::launch::async, [this, filePath, asset] () mutable {
|
||||
Gfx::PTexture2D texture = import(filePath);
|
||||
asset->setTexture(texture);
|
||||
asset->setStatus(Asset::Status::Ready);
|
||||
}));
|
||||
}
|
||||
|
||||
void TextureLoader::import(const std::filesystem::path& path)
|
||||
Gfx::PTexture2D TextureLoader::import(const std::filesystem::path& path)
|
||||
{
|
||||
auto assetFileName = path;
|
||||
std::filesystem::path assetPath = AssetRegistry::get().rootFolder.append(assetFileName.replace_extension("asset").filename().string());
|
||||
PTextureAsset asset = new TextureAsset(assetPath);
|
||||
asset->setStatus(Asset::Status::Loading);
|
||||
int x, y, n;
|
||||
unsigned char* data = stbi_load(path.string().c_str(), &x, &y, &n, 4);
|
||||
TextureCreateInfo createInfo;
|
||||
@@ -43,7 +47,5 @@ void TextureLoader::import(const std::filesystem::path& path)
|
||||
Gfx::PTexture2D texture = graphics->createTexture2D(createInfo);
|
||||
stbi_image_free(data);
|
||||
texture->transferOwnership(Gfx::QueueType::GRAPHICS);
|
||||
asset->setTexture(texture);
|
||||
asset->setStatus(Asset::Status::Ready);
|
||||
AssetRegistry::get().textures[path.string()] = asset;
|
||||
return texture;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ namespace Seele
|
||||
{
|
||||
DECLARE_REF(TextureAsset);
|
||||
DECLARE_NAME_REF(Gfx, Graphics);
|
||||
DECLARE_NAME_REF(Gfx, Texture2D);
|
||||
class TextureLoader
|
||||
{
|
||||
public:
|
||||
@@ -16,10 +17,10 @@ public:
|
||||
~TextureLoader();
|
||||
void importAsset(const std::filesystem::path& filePath);
|
||||
private:
|
||||
void import(const std::filesystem::path& path);
|
||||
Gfx::PTexture2D import(const std::filesystem::path& path);
|
||||
Gfx::PGraphics graphics;
|
||||
List<std::future<void>> futures;
|
||||
PTextureAsset placeholderTexture;
|
||||
Gfx::PTexture2D placeholderTexture;
|
||||
};
|
||||
DEFINE_REF(TextureLoader);
|
||||
} // namespace Seele
|
||||
@@ -163,7 +163,14 @@ public:
|
||||
{
|
||||
prev->next = next;
|
||||
}
|
||||
next->prev = prev;
|
||||
if(next == nullptr)
|
||||
{
|
||||
root = prev;
|
||||
}
|
||||
else
|
||||
{
|
||||
next->prev = prev;
|
||||
}
|
||||
delete pos.node;
|
||||
refreshIterators();
|
||||
return Iterator(next);
|
||||
|
||||
@@ -11,16 +11,22 @@ target_sources(SeeleEngine
|
||||
MeshBatch.h
|
||||
RenderCore.h
|
||||
RenderCore.cpp
|
||||
RenderMaterial.h
|
||||
RenderMaterial.cpp
|
||||
RenderPath.h
|
||||
RenderPath.cpp
|
||||
SceneView.h
|
||||
SceneView.cpp
|
||||
SceneRenderPath.h
|
||||
SceneRenderPath.cpp
|
||||
ShaderCompiler.h
|
||||
ShaderCompiler.cpp
|
||||
View.h
|
||||
View.cpp
|
||||
VertexShaderInput.h
|
||||
VertexShaderInput.cpp
|
||||
StaticMeshVertexInput.h
|
||||
StaticMeshVertexInput.cpp
|
||||
Window.cpp
|
||||
Window.h
|
||||
WindowManager.h
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#include "Graphics.h"
|
||||
#include <map>
|
||||
#include "ShaderCompiler.h"
|
||||
|
||||
using namespace Seele::Gfx;
|
||||
|
||||
Graphics::Graphics()
|
||||
{
|
||||
shaderCompiler = new ShaderCompiler(this);
|
||||
}
|
||||
|
||||
Graphics::~Graphics()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "GraphicsResources.h"
|
||||
#include "Containers/Array.h"
|
||||
#include "VertexShaderInput.h"
|
||||
#include "ShaderCompiler.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
@@ -19,6 +20,11 @@ public:
|
||||
{
|
||||
return queueMapping;
|
||||
}
|
||||
|
||||
PShaderCompiler getShaderCompiler() const
|
||||
{
|
||||
return shaderCompiler;
|
||||
}
|
||||
|
||||
virtual PWindow createWindow(const WindowCreateInfo &createInfo) = 0;
|
||||
virtual PViewport createViewport(PWindow owner, const ViewportCreateInfo &createInfo) = 0;
|
||||
@@ -47,6 +53,7 @@ public:
|
||||
|
||||
protected:
|
||||
QueueFamilyMapping queueMapping;
|
||||
PShaderCompiler shaderCompiler;
|
||||
friend class Window;
|
||||
};
|
||||
DEFINE_REF(Graphics);
|
||||
|
||||
@@ -100,6 +100,7 @@ struct ShaderCreateInfo
|
||||
Array<std::string> shaderCode;
|
||||
std::string entryPoint;
|
||||
Array<const char*> typeParameter;
|
||||
Map<const char*, const char*> defines;
|
||||
};
|
||||
|
||||
namespace Gfx
|
||||
|
||||
@@ -42,18 +42,37 @@ ShaderCollection& ShaderMap::createShaders(
|
||||
PGraphics graphics,
|
||||
RenderPassType renderPass,
|
||||
PMaterial material,
|
||||
PVertexShaderInput vertexInput,
|
||||
VertexInputType* vertexInput,
|
||||
bool bPositionOnly)
|
||||
{
|
||||
ShaderCollection& collection = shaders.add();
|
||||
collection.vertexDeclaration = bPositionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration();
|
||||
//collection.vertexDeclaration = bPositionOnly ? vertexInput->getPositionDeclaration() : vertexInput->getDeclaration();
|
||||
|
||||
ShaderCreateInfo createInfo;
|
||||
createInfo.entryPoint = "vertexMain";
|
||||
createInfo.typeParameter = {material->getMaterialName().c_str(), vertexInput->getName().c_str()};
|
||||
createInfo.typeParameter = {material->getName().c_str()};
|
||||
createInfo.defines["VERTEX_INPUT_IMPORT"] = vertexInput->getShaderFilename();
|
||||
createInfo.defines["MATERIAL_IMPORT"] = material->getName().c_str();
|
||||
createInfo.defines["NUM_MATERIAL_TEXCOORDS"] = "1";
|
||||
createInfo.defines["USE_INSTANCING"] = "0";
|
||||
|
||||
std::ifstream codeStream("./shaders/" + getShaderNameFromRenderPassType(renderPass), std::ios::ate);
|
||||
auto fileSize = codeStream.tellg();
|
||||
codeStream.seekg(0);
|
||||
Array<char> buffer(static_cast<uint32>(fileSize));
|
||||
codeStream.read(buffer.data(), fileSize);
|
||||
|
||||
createInfo.shaderCode.add(std::string(buffer.data()));
|
||||
|
||||
collection.vertexShader = graphics->createVertexShader(createInfo);
|
||||
|
||||
if(renderPass != RenderPassType::DepthPrepass)
|
||||
{
|
||||
createInfo.entryPoint = "fragmentMain";
|
||||
|
||||
collection.fragmentShader = graphics->createFragmentShader(createInfo);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
void DescriptorLayout::addDescriptorBinding(uint32 bindingIndex, SeDescriptorType type, uint32 arrayCount)
|
||||
@@ -108,8 +127,8 @@ void PipelineLayout::addPushConstants(const SePushConstantRange &pushConstant)
|
||||
pushConstants.add(pushConstant);
|
||||
}
|
||||
|
||||
QueueOwnedResource::QueueOwnedResource(PGraphics graphics, QueueType startQueueType)
|
||||
: graphics(graphics)
|
||||
QueueOwnedResource::QueueOwnedResource(QueueFamilyMapping mapping, QueueType startQueueType)
|
||||
: mapping(mapping)
|
||||
, currentOwner(startQueueType)
|
||||
{
|
||||
}
|
||||
@@ -120,15 +139,15 @@ QueueOwnedResource::~QueueOwnedResource()
|
||||
|
||||
void QueueOwnedResource::transferOwnership(QueueType newOwner)
|
||||
{
|
||||
if(graphics->getFamilyMapping().needsTransfer(currentOwner, newOwner))
|
||||
if(mapping.needsTransfer(currentOwner, newOwner))
|
||||
{
|
||||
executeOwnershipBarrier(newOwner);
|
||||
currentOwner = newOwner;
|
||||
}
|
||||
}
|
||||
|
||||
Buffer::Buffer(PGraphics graphics, QueueType startQueue)
|
||||
: QueueOwnedResource(graphics, startQueue)
|
||||
Buffer::Buffer(QueueFamilyMapping mapping, QueueType startQueue)
|
||||
: QueueOwnedResource(mapping, startQueue)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -136,31 +155,32 @@ Buffer::~Buffer()
|
||||
{
|
||||
}
|
||||
|
||||
UniformBuffer::UniformBuffer(PGraphics graphics, QueueType startQueueType)
|
||||
: Buffer(graphics, startQueueType)
|
||||
UniformBuffer::UniformBuffer(QueueFamilyMapping mapping, QueueType startQueueType)
|
||||
: Buffer(mapping, startQueueType)
|
||||
{
|
||||
}
|
||||
|
||||
UniformBuffer::~UniformBuffer()
|
||||
{
|
||||
}
|
||||
StructuredBuffer::StructuredBuffer(PGraphics graphics, QueueType startQueueType)
|
||||
: Buffer(graphics, startQueueType)
|
||||
StructuredBuffer::StructuredBuffer(QueueFamilyMapping mapping, QueueType startQueueType)
|
||||
: Buffer(mapping, startQueueType)
|
||||
{
|
||||
}
|
||||
StructuredBuffer::~StructuredBuffer()
|
||||
{
|
||||
}
|
||||
VertexBuffer::VertexBuffer(PGraphics graphics, uint32 numVertices, uint32 vertexSize, QueueType startQueueType)
|
||||
: Buffer(graphics, startQueueType)
|
||||
, numVertices(numVertices), vertexSize(vertexSize)
|
||||
VertexBuffer::VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType)
|
||||
: Buffer(mapping, startQueueType)
|
||||
, numVertices(numVertices)
|
||||
, vertexSize(vertexSize)
|
||||
{
|
||||
}
|
||||
VertexBuffer::~VertexBuffer()
|
||||
{
|
||||
}
|
||||
IndexBuffer::IndexBuffer(PGraphics graphics, uint32 size, Gfx::SeIndexType indexType, QueueType startQueueType)
|
||||
: Buffer(graphics, startQueueType)
|
||||
IndexBuffer::IndexBuffer(QueueFamilyMapping mapping, uint32 size, Gfx::SeIndexType indexType, QueueType startQueueType)
|
||||
: Buffer(mapping, startQueueType)
|
||||
, indexType(indexType)
|
||||
{
|
||||
switch (indexType)
|
||||
@@ -179,8 +199,8 @@ IndexBuffer::~IndexBuffer()
|
||||
}
|
||||
VertexStream::VertexStream()
|
||||
{}
|
||||
VertexStream::VertexStream(uint32 stride, uint32 offset, uint8 instanced, Gfx::PVertexBuffer vertexBuffer)
|
||||
: stride(stride), instanced(instanced), offset(offset), vertexBuffer(vertexBuffer)
|
||||
VertexStream::VertexStream(uint32 stride, uint32 offset, uint8 instanced)
|
||||
: stride(stride), instanced(instanced), offset(offset)
|
||||
{
|
||||
}
|
||||
VertexStream::~VertexStream()
|
||||
@@ -200,19 +220,19 @@ VertexDeclaration::VertexDeclaration()
|
||||
VertexDeclaration::~VertexDeclaration()
|
||||
{
|
||||
}
|
||||
uint32 VertexDeclaration::addVertexStream(const VertexStream &element)
|
||||
uint32 VertexDeclaration::addVertexStream(const VertexStreamComponent &element)
|
||||
{
|
||||
uint32 currIndex = vertexStreams.size();
|
||||
vertexStreams.add(element);
|
||||
return currIndex;
|
||||
VertexStream& stream = vertexStreams.add();
|
||||
stream.addVertexElement(VertexElement(element.streamOffset, element.type, element.offset));
|
||||
return stream.vertexDescription.size() - 1;
|
||||
}
|
||||
const Array<VertexStream> &VertexDeclaration::getVertexStreams() const
|
||||
{
|
||||
return vertexStreams;
|
||||
}
|
||||
|
||||
Texture::Texture(PGraphics graphics, Gfx::QueueType startQueueType)
|
||||
: QueueOwnedResource(graphics, startQueueType)
|
||||
Texture::Texture(QueueFamilyMapping mapping, Gfx::QueueType startQueueType)
|
||||
: QueueOwnedResource(mapping, startQueueType)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -220,8 +240,8 @@ Texture::~Texture()
|
||||
{
|
||||
}
|
||||
|
||||
Texture2D::Texture2D(PGraphics graphics, Gfx::QueueType startQueueType)
|
||||
: Texture(graphics, startQueueType)
|
||||
Texture2D::Texture2D(QueueFamilyMapping mapping, Gfx::QueueType startQueueType)
|
||||
: Texture(mapping, startQueueType)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,16 @@
|
||||
#include "MeshBatch.h"
|
||||
#include <boost/crc.hpp>
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define ENABLE_VALIDATION
|
||||
|
||||
#ifdef DEBUG
|
||||
#endif
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
struct VertexInputStream;
|
||||
struct VertexStreamComponent;
|
||||
class VertexInputType;
|
||||
namespace Gfx
|
||||
{
|
||||
DECLARE_REF(Graphics);
|
||||
@@ -111,7 +114,7 @@ struct PermutationId
|
||||
struct ShaderCollection
|
||||
{
|
||||
PermutationId id;
|
||||
PVertexDeclaration vertexDeclaration;
|
||||
//PVertexDeclaration vertexDeclaration;
|
||||
PVertexShader vertexShader;
|
||||
PControlShader controlShader;
|
||||
PEvaluationShader evalutionShader;
|
||||
@@ -128,7 +131,7 @@ public:
|
||||
PGraphics graphics,
|
||||
RenderPassType passName,
|
||||
PMaterial material,
|
||||
PVertexShaderInput vertexInput,
|
||||
VertexInputType* vertexInput,
|
||||
bool bPositionOnly);
|
||||
private:
|
||||
Array<ShaderCollection> shaders;
|
||||
@@ -272,7 +275,7 @@ struct QueueFamilyMapping
|
||||
class QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
QueueOwnedResource(PGraphics graphics, QueueType startQueueType);
|
||||
QueueOwnedResource(QueueFamilyMapping mapping, QueueType startQueueType);
|
||||
virtual ~QueueOwnedResource();
|
||||
|
||||
//Preliminary checks to see if the barrier should be executed at all
|
||||
@@ -281,14 +284,20 @@ public:
|
||||
protected:
|
||||
virtual void executeOwnershipBarrier(QueueType newOwner) = 0;
|
||||
Gfx::QueueType currentOwner;
|
||||
PGraphics graphics;
|
||||
QueueFamilyMapping mapping;
|
||||
};
|
||||
DEFINE_REF(QueueOwnedResource);
|
||||
|
||||
// IMPORTANT!!
|
||||
// WHEN DERIVING FROM ANY Gfx:: BASE CLASSES WITH MULTIPLE INHERITANCE
|
||||
// ALWAYS PUT THE Gfx:: BASE CLASS FIRST
|
||||
// This is because the refcounting object is unique per allocation, so
|
||||
// the base address of both the Gfx:: and the implementation class
|
||||
// need to match for it to work
|
||||
class Buffer : public QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
Buffer(PGraphics graphics, QueueType startQueueType);
|
||||
Buffer(QueueFamilyMapping mapping, QueueType startQueueType);
|
||||
virtual ~Buffer();
|
||||
|
||||
protected:
|
||||
@@ -299,7 +308,7 @@ protected:
|
||||
class UniformBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
UniformBuffer(PGraphics graphics, QueueType startQueueType);
|
||||
UniformBuffer(QueueFamilyMapping mapping, QueueType startQueueType);
|
||||
virtual ~UniformBuffer();
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
@@ -310,7 +319,7 @@ DEFINE_REF(UniformBuffer);
|
||||
class VertexBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
VertexBuffer(PGraphics graphics, uint32 numVertices, uint32 vertexSize, QueueType startQueueType);
|
||||
VertexBuffer(QueueFamilyMapping mapping, uint32 numVertices, uint32 vertexSize, QueueType startQueueType);
|
||||
virtual ~VertexBuffer();
|
||||
inline uint32 getNumVertices()
|
||||
{
|
||||
@@ -333,7 +342,7 @@ DEFINE_REF(VertexBuffer);
|
||||
class IndexBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
IndexBuffer(PGraphics graphics, uint32 size, Gfx::SeIndexType index, QueueType startQueueType);
|
||||
IndexBuffer(QueueFamilyMapping mapping, uint32 size, Gfx::SeIndexType index, QueueType startQueueType);
|
||||
virtual ~IndexBuffer();
|
||||
inline uint32 getNumIndices() const
|
||||
{
|
||||
@@ -355,7 +364,7 @@ DEFINE_REF(IndexBuffer);
|
||||
class StructuredBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
StructuredBuffer(PGraphics graphics, QueueType startQueueType);
|
||||
StructuredBuffer(QueueFamilyMapping mapping, QueueType startQueueType);
|
||||
virtual ~StructuredBuffer();
|
||||
protected:
|
||||
// Inherited via QueueOwnedResource
|
||||
@@ -367,7 +376,7 @@ class VertexStream
|
||||
{
|
||||
public:
|
||||
VertexStream();
|
||||
VertexStream(uint32 stride, uint32 offset, uint8 instanced, Gfx::PVertexBuffer vertexBuffer);
|
||||
VertexStream(uint32 stride, uint32 offset, uint8 instanced);
|
||||
~VertexStream();
|
||||
void addVertexElement(VertexElement element);
|
||||
const Array<VertexElement> getVertexDescriptions() const;
|
||||
@@ -377,7 +386,6 @@ public:
|
||||
uint32 offset;
|
||||
Array<VertexElement> vertexDescription;
|
||||
uint8 instanced;
|
||||
PVertexBuffer vertexBuffer;
|
||||
};
|
||||
DEFINE_REF(VertexStream);
|
||||
class VertexDeclaration
|
||||
@@ -385,7 +393,7 @@ class VertexDeclaration
|
||||
public:
|
||||
VertexDeclaration();
|
||||
~VertexDeclaration();
|
||||
uint32 addVertexStream(const VertexStream &vertexStream);
|
||||
uint32 addVertexStream(const VertexStreamComponent &vertexStream);
|
||||
const Array<VertexStream> &getVertexStreams() const;
|
||||
|
||||
private:
|
||||
@@ -404,10 +412,17 @@ protected:
|
||||
GraphicsPipelineCreateInfo createInfo;
|
||||
};
|
||||
DEFINE_REF(GraphicsPipeline);
|
||||
|
||||
// IMPORTANT!!
|
||||
// WHEN DERIVING FROM ANY Gfx:: BASE CLASSES WITH MULTIPLE INHERITANCE
|
||||
// ALWAYS PUT THE Gfx:: BASE CLASS FIRST
|
||||
// This is because the refcounting object is unique per allocation, so
|
||||
// the base address of both the Gfx:: and the implementation class
|
||||
// need to match for it to work
|
||||
class Texture : public QueueOwnedResource
|
||||
{
|
||||
public:
|
||||
Texture(PGraphics graphics, QueueType startQueueType);
|
||||
Texture(QueueFamilyMapping mapping, QueueType startQueueType);
|
||||
virtual ~Texture();
|
||||
|
||||
virtual SeFormat getFormat() const = 0;
|
||||
@@ -422,7 +437,7 @@ DEFINE_REF(Texture);
|
||||
class Texture2D : public Texture
|
||||
{
|
||||
public:
|
||||
Texture2D(PGraphics graphics, QueueType startQueueType);
|
||||
Texture2D(QueueFamilyMapping mapping, QueueType startQueueType);
|
||||
virtual ~Texture2D();
|
||||
|
||||
virtual SeFormat getFormat() const = 0;
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Mesh::Mesh(MeshDescription description, Gfx::PIndexBuffer indexBuffer)
|
||||
: description(description)
|
||||
Mesh::Mesh(PVertexShaderInput vertexInput, Gfx::PIndexBuffer indexBuffer)
|
||||
: vertexInput(vertexInput)
|
||||
, indexBuffer(indexBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
#define MAX_TEX_CHANNELS 8
|
||||
/*#define MAX_TEX_CHANNELS 8
|
||||
struct MeshDescription
|
||||
{
|
||||
Array<Gfx::VertexAttribute> layout;
|
||||
@@ -41,23 +41,22 @@ struct MeshDescription
|
||||
ar & layout;
|
||||
//TODO declaration
|
||||
}
|
||||
};
|
||||
};*/
|
||||
DECLARE_REF(MaterialAsset);
|
||||
class Mesh
|
||||
{
|
||||
public:
|
||||
Mesh(MeshDescription description, Gfx::PIndexBuffer indexBuffer);
|
||||
Mesh(PVertexShaderInput vertexInput, Gfx::PIndexBuffer indexBuffer);
|
||||
~Mesh();
|
||||
|
||||
Gfx::PIndexBuffer indexBuffer;
|
||||
MeshDescription description;
|
||||
PVertexShaderInput vertexInput;
|
||||
PMaterialAsset referencedMaterial;
|
||||
private:
|
||||
friend class boost::serialization::access;
|
||||
template<class Archive>
|
||||
void serialize(Archive& ar, const unsigned int version)
|
||||
{
|
||||
ar & description;
|
||||
ar & referencedMaterial->getFullPath();
|
||||
//TODO:
|
||||
}
|
||||
|
||||
@@ -12,21 +12,6 @@ Seele::RenderCore::~RenderCore()
|
||||
|
||||
void Seele::RenderCore::init()
|
||||
{
|
||||
WindowCreateInfo mainWindowInfo;
|
||||
mainWindowInfo.title = "SeeleEngine";
|
||||
mainWindowInfo.width = 1280;
|
||||
mainWindowInfo.height = 720;
|
||||
mainWindowInfo.bFullscreen = false;
|
||||
mainWindowInfo.numSamples = 1;
|
||||
mainWindowInfo.pixelFormat = Gfx::SE_FORMAT_R8G8B8_UNORM;
|
||||
auto window = windowManager->addWindow(mainWindowInfo);
|
||||
ViewportCreateInfo sceneViewInfo;
|
||||
sceneViewInfo.sizeX = 1280;
|
||||
sceneViewInfo.sizeY = 720;
|
||||
sceneViewInfo.offsetX = 0;
|
||||
sceneViewInfo.offsetY = 0;
|
||||
PSceneView sceneView = new SceneView(windowManager->getGraphics(), window, sceneViewInfo);
|
||||
window->addView(sceneView);
|
||||
}
|
||||
|
||||
void Seele::RenderCore::renderLoop()
|
||||
@@ -34,6 +19,7 @@ void Seele::RenderCore::renderLoop()
|
||||
while (windowManager->isActive())
|
||||
{
|
||||
windowManager->beginFrame();
|
||||
windowManager->render();
|
||||
windowManager->endFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ public:
|
||||
void renderLoop();
|
||||
void shutdown();
|
||||
|
||||
PWindowManager getWindowManager() const { return windowManager; };
|
||||
private:
|
||||
PScene scene;
|
||||
PWindowManager windowManager;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#include "RenderMaterial.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Gfx;
|
||||
@@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
#include "GraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
namespace Gfx
|
||||
{
|
||||
class MaterialShaderMap;//TODO implement
|
||||
class MaterialRenderContext;
|
||||
struct UniformExpressionCache
|
||||
{
|
||||
Gfx::PUniformBuffer uniformBuffer;
|
||||
uint8 bUpToDate;
|
||||
|
||||
const MaterialShaderMap* cachedUniformExpressionShaderMap;
|
||||
};
|
||||
class Material;
|
||||
class RenderMaterial
|
||||
{
|
||||
public:
|
||||
mutable UniformExpressionCache uniformExpressionCache;
|
||||
RenderMaterial();
|
||||
virtual ~RenderMaterial();
|
||||
|
||||
void evaluateUniformExpressions(UniformExpressionCache& outUniforExpressionCache, const MaterialRenderContext& context);
|
||||
|
||||
void cacheUniformExpressions(bool bRecreatueUniformBuffer);
|
||||
|
||||
void invalidateUniformExpressionCache(bool bRecreateUniformBuffer);
|
||||
|
||||
void updateUniformExpressionCacheIfNeeded() const;
|
||||
|
||||
const Material* getMaterial() const
|
||||
{
|
||||
const RenderMaterial* unused = nullptr;
|
||||
return &getMaterialWithFallback(unused);
|
||||
}
|
||||
|
||||
virtual const Material& getMaterialWithFallback(const RenderMaterial*& outFallbackRenderMaterial) const = 0;
|
||||
|
||||
virtual Material* getMaterialNoFallback() const { return nullptr; }
|
||||
};
|
||||
} // namespace Gfx
|
||||
} // namespace Seele
|
||||
@@ -27,7 +27,8 @@ void BasePassMeshProcessor::addMeshBatch(
|
||||
|
||||
//TODO query tesselation
|
||||
|
||||
const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput);
|
||||
const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType());
|
||||
assert(collection != nullptr);
|
||||
Gfx::PRenderCommand renderCommand = graphics->createRenderCommand();
|
||||
buildMeshDrawCommand(batch,
|
||||
primitiveComponent,
|
||||
@@ -79,12 +80,9 @@ void BasePass::render()
|
||||
{
|
||||
processor->clearCommands();
|
||||
graphics->beginRenderPass(renderPass);
|
||||
for (auto &&primitive : scene->getPrimitives())
|
||||
for (auto &&primitive : scene->getStaticMeshes())
|
||||
{
|
||||
for (auto &&meshBatch : primitive->staticMeshes)
|
||||
{
|
||||
processor->addMeshBatch(meshBatch, primitive, renderPass);
|
||||
}
|
||||
processor->addMeshBatch(primitive, nullptr, renderPass);
|
||||
}
|
||||
graphics->executeCommands(processor->getRenderCommands());
|
||||
graphics->endRenderPass();
|
||||
|
||||
@@ -5,14 +5,11 @@
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
SceneRenderPath::SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target)
|
||||
SceneRenderPath::SceneRenderPath(PScene scene, Gfx::PGraphics graphics, Gfx::PViewport target)
|
||||
: RenderPath(graphics, target)
|
||||
, basePass(new BasePass(scene, graphics, target))
|
||||
, scene(scene)
|
||||
{
|
||||
scene = new Scene();
|
||||
PMeshAsset asset = AssetRegistry::findMesh("Unbenannt");
|
||||
PActor rootActor = new Actor();
|
||||
PPrimitiveComponent primitiveComponent = new PrimitiveComponent();
|
||||
basePass = new BasePass(scene, graphics, target);
|
||||
}
|
||||
|
||||
SceneRenderPath::~SceneRenderPath()
|
||||
|
||||
@@ -8,7 +8,7 @@ DECLARE_REF(Scene);
|
||||
class SceneRenderPath : public RenderPath
|
||||
{
|
||||
public:
|
||||
SceneRenderPath(Gfx::PGraphics graphics, Gfx::PViewport target);
|
||||
SceneRenderPath(PScene scene, Gfx::PGraphics graphics, Gfx::PViewport target);
|
||||
virtual ~SceneRenderPath();
|
||||
void setTargetScene(PScene scene);
|
||||
virtual void init();
|
||||
|
||||
@@ -8,7 +8,8 @@ using namespace Seele;
|
||||
Seele::SceneView::SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo)
|
||||
: View(graphics, owner, createInfo)
|
||||
{
|
||||
renderer = new SceneRenderPath(graphics, viewport);
|
||||
scene = new Scene(graphics);
|
||||
renderer = new SceneRenderPath(scene, graphics, viewport);
|
||||
}
|
||||
|
||||
Seele::SceneView::~SceneView()
|
||||
|
||||
@@ -2,11 +2,15 @@
|
||||
#include "View.h"
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Scene);
|
||||
class SceneView : public View
|
||||
{
|
||||
public:
|
||||
SceneView(Gfx::PGraphics graphics, PWindow owner, const ViewportCreateInfo &createInfo);
|
||||
~SceneView();
|
||||
PScene getScene() const { return scene; }
|
||||
private:
|
||||
PScene scene;
|
||||
};
|
||||
DEFINE_REF(SceneView);
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "ShaderCompiler.h"
|
||||
#include "Material/Material.h"
|
||||
#include "VertexShaderInput.h"
|
||||
|
||||
using namespace Seele;
|
||||
using namespace Seele::Gfx;
|
||||
|
||||
ShaderCompiler::ShaderCompiler(PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ShaderCompiler::~ShaderCompiler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ShaderCompiler::registerMaterial(PMaterial material)
|
||||
{
|
||||
for(auto type : VertexInputType::getTypeList())
|
||||
{
|
||||
material->createShaders(graphics, Gfx::RenderPassType::DepthPrepass, type);
|
||||
material->createShaders(graphics, Gfx::RenderPassType::BasePass, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "GraphicsResources.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(Material);
|
||||
DECLARE_NAME_REF(Gfx, Graphics);
|
||||
namespace Gfx
|
||||
{
|
||||
class ShaderCompiler
|
||||
{
|
||||
public:
|
||||
ShaderCompiler(PGraphics graphics);
|
||||
~ShaderCompiler();
|
||||
void registerMaterial(PMaterial material);
|
||||
private:
|
||||
Array<PMaterial> pendingCompiles;
|
||||
PGraphics graphics;
|
||||
};
|
||||
DEFINE_REF(ShaderCompiler);
|
||||
} // namespace Gfx
|
||||
} // namespace Seele
|
||||
@@ -0,0 +1,48 @@
|
||||
#include "StaticMeshVertexInput.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
StaticMeshVertexInput::StaticMeshVertexInput(std::string name)
|
||||
: VertexShaderInput(name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
StaticMeshVertexInput::~StaticMeshVertexInput()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void StaticMeshVertexInput::setPositionStream(const VertexStreamComponent& positionStream)
|
||||
{
|
||||
declaration->addVertexStream(positionStream);
|
||||
positionDeclaration->addVertexStream(positionStream);
|
||||
data.positionStream = positionStream;
|
||||
}
|
||||
|
||||
void StaticMeshVertexInput::setTangentXStream(const VertexStreamComponent& tangentXStream)
|
||||
{
|
||||
declaration->addVertexStream(tangentXStream);
|
||||
data.tangentBasisComponents[0] = tangentXStream;
|
||||
}
|
||||
|
||||
void StaticMeshVertexInput::setTangentZStream(const VertexStreamComponent& tangentZStream)
|
||||
{
|
||||
declaration->addVertexStream(tangentZStream);
|
||||
data.tangentBasisComponents[1] = tangentZStream;
|
||||
}
|
||||
|
||||
void StaticMeshVertexInput::setTexCoordStream(uint32 index, const VertexStreamComponent& textureStream)
|
||||
{
|
||||
//TODO: replace add with proper indexing
|
||||
declaration->addVertexStream(textureStream);
|
||||
data.textureCoordinates.add(textureStream);
|
||||
}
|
||||
|
||||
void StaticMeshVertexInput::setColorStream(const VertexStreamComponent& colorStream)
|
||||
{
|
||||
declaration->addVertexStream(colorStream);
|
||||
data.colorComponent = colorStream;
|
||||
}
|
||||
|
||||
IMPLEMENT_VERTEX_INPUT_TYPE(StaticMeshVertexInput, "StaticMeshVertexInput");
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "VertexShaderInput.h"
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
enum { MAX_TEXCOORDS = 4 };
|
||||
struct StaticMeshDataType
|
||||
{
|
||||
VertexStreamComponent positionStream;
|
||||
VertexStreamComponent tangentBasisComponents[2];
|
||||
|
||||
//Dont forget these are 4 component vectors
|
||||
Array<VertexStreamComponent> textureCoordinates;
|
||||
|
||||
VertexStreamComponent colorComponent;
|
||||
};
|
||||
class StaticMeshVertexInput : public VertexShaderInput
|
||||
{
|
||||
DECLARE_VERTEX_INPUT_TYPE(StaticMeshVertexInput);
|
||||
public:
|
||||
StaticMeshVertexInput(std::string name);
|
||||
virtual ~StaticMeshVertexInput();
|
||||
void setPositionStream(const VertexStreamComponent& positionStream);
|
||||
void setTangentXStream(const VertexStreamComponent& tangentXStream);
|
||||
void setTangentZStream(const VertexStreamComponent& tangentZStream);
|
||||
void setTexCoordStream(uint32 index, const VertexStreamComponent& textureStream);
|
||||
void setColorStream(const VertexStreamComponent& colorStream);
|
||||
private:
|
||||
StaticMeshDataType data;
|
||||
};
|
||||
DEFINE_REF(StaticMeshVertexInput);
|
||||
}
|
||||
@@ -5,49 +5,64 @@
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
List<PVertexShaderInput> VertexShaderInput::registeredInputs;
|
||||
std::mutex VertexShaderInput::registeredInputsLock;
|
||||
List<VertexInputType*> VertexInputType::globalTypeList;
|
||||
|
||||
List<VertexInputType*> VertexInputType::getTypeList()
|
||||
{
|
||||
return globalTypeList;
|
||||
}
|
||||
|
||||
VertexInputType* VertexInputType::getVertexInputByName(const std::string& name)
|
||||
{
|
||||
for(auto type : globalTypeList)
|
||||
{
|
||||
if(name.compare(type->getName()) == 0)
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VertexInputType::VertexInputType(const char* name,
|
||||
const char* shaderFilename)
|
||||
: name(name)
|
||||
, shaderFilename(shaderFilename)
|
||||
{
|
||||
globalTypeList.add(this);
|
||||
}
|
||||
|
||||
VertexInputType::~VertexInputType()
|
||||
{
|
||||
globalTypeList.remove(globalTypeList.find(this));
|
||||
}
|
||||
|
||||
const char* VertexInputType::getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
const char* VertexInputType::getShaderFilename()
|
||||
{
|
||||
return shaderFilename;
|
||||
}
|
||||
|
||||
VertexShaderInput::VertexShaderInput(std::string name)
|
||||
: name(name)
|
||||
{
|
||||
std::scoped_lock lock(registeredInputsLock);
|
||||
registeredInputs.add(this);
|
||||
}
|
||||
|
||||
VertexShaderInput::VertexShaderInput(MeshDescription description, std::string name)
|
||||
: declaration(description.declaration)
|
||||
, layout(description.layout)
|
||||
, name(name)
|
||||
{
|
||||
auto declStreams = declaration->getVertexStreams();
|
||||
std::copy(declStreams.begin(), declStreams.end(), streams.begin());
|
||||
|
||||
uint32 positionStreamIndex = 0;
|
||||
declaration = new Gfx::VertexDeclaration();
|
||||
positionDeclaration = new Gfx::VertexDeclaration();
|
||||
for (uint32 i = 0; i < declStreams.size(); i++)
|
||||
{
|
||||
if(description.layout[i] == Gfx::VertexAttribute::POSITION)
|
||||
{
|
||||
positionStreams[positionStreamIndex++] = declStreams[i];
|
||||
positionDeclaration->addVertexStream(declStreams[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::scoped_lock lock(registeredInputsLock);
|
||||
registeredInputs.add(this);
|
||||
}
|
||||
|
||||
VertexShaderInput::~VertexShaderInput()
|
||||
{
|
||||
registeredInputs.remove(registeredInputs.find(this));
|
||||
}
|
||||
|
||||
void VertexShaderInput::getStreams(VertexInputStreamArray& outVertexStreams) const
|
||||
{
|
||||
for(uint32 i = 0; i < streams.size(); ++i)
|
||||
{
|
||||
const Gfx::VertexStream& stream = streams[i];
|
||||
const VertexInputStream& stream = streams[i];
|
||||
if(stream.vertexBuffer == nullptr)
|
||||
{
|
||||
outVertexStreams.add(VertexInputStream(i, 0, nullptr));
|
||||
@@ -63,7 +78,7 @@ void VertexShaderInput::getPositionOnlyStream(VertexInputStreamArray& outVertexS
|
||||
{
|
||||
for (uint32 i = 0; i < positionStreams.size(); ++i)
|
||||
{
|
||||
const Gfx::VertexStream& stream = positionStreams[i];
|
||||
const VertexInputStream& stream = positionStreams[i];
|
||||
outVertexStreams.add(VertexInputStream(i, stream.offset, stream.vertexBuffer));
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
// Minimal vertex source used for building commands
|
||||
struct VertexInputStream
|
||||
{
|
||||
uint32 streamIndex : 4;
|
||||
@@ -35,33 +36,103 @@ struct VertexInputStream
|
||||
return !(*this == rhs);
|
||||
}
|
||||
};
|
||||
typedef Array<VertexInputStream> VertexInputStreamArray; //TODO inline allocation
|
||||
|
||||
// Typed data source for a vertex factory
|
||||
struct VertexStreamComponent
|
||||
{
|
||||
// Source vertex buffer
|
||||
Gfx::PVertexBuffer vertexBuffer = nullptr;
|
||||
|
||||
// Offset to the start of the vertex buffer fetch
|
||||
uint32 streamOffset = 0;
|
||||
|
||||
// Offset of the data, relative to the beginnning of each element in the vertex buffer
|
||||
uint32 offset = 0;
|
||||
|
||||
// Stride of the data
|
||||
uint32 stride = 0;
|
||||
|
||||
Gfx::SeFormat type = Gfx::SE_FORMAT_UNDEFINED;
|
||||
|
||||
VertexStreamComponent()
|
||||
{}
|
||||
|
||||
VertexStreamComponent(const Gfx::PVertexBuffer vertexBuffer, uint32 offset, uint32 stride, Gfx::SeFormat type)
|
||||
: vertexBuffer(vertexBuffer)
|
||||
, streamOffset(0)
|
||||
, offset(offset)
|
||||
, stride(stride)
|
||||
, type(type)
|
||||
{}
|
||||
|
||||
VertexStreamComponent(const Gfx::PVertexBuffer vertexBuffer, uint32 streamOffset, uint32 offset, uint32 stride, Gfx::SeFormat type)
|
||||
: vertexBuffer(vertexBuffer)
|
||||
, streamOffset(streamOffset)
|
||||
, offset(offset)
|
||||
, stride(stride)
|
||||
, type(type)
|
||||
{}
|
||||
};
|
||||
|
||||
#define STRUCTMEMBER_VERTEXSTREAMCOMPONENT(vertexBuffer, vertexType, member, memberType) \
|
||||
VertexStreamComponent(vertexBuffer, offsetof(vertexType, member), sizeof(vertexType), memberType)
|
||||
|
||||
class VertexInputType
|
||||
{
|
||||
public:
|
||||
static List<VertexInputType*> getTypeList();
|
||||
static VertexInputType* getVertexInputByName(const std::string& name);
|
||||
|
||||
VertexInputType(
|
||||
const char* name,
|
||||
const char* shaderFilename
|
||||
);
|
||||
virtual ~VertexInputType();
|
||||
|
||||
const char* getName();
|
||||
const char* getShaderFilename();
|
||||
private:
|
||||
const char* name;
|
||||
const char* shaderFilename;
|
||||
|
||||
static List<VertexInputType*> globalTypeList;
|
||||
};
|
||||
|
||||
#define DECLARE_VERTEX_INPUT_TYPE(inputClass) \
|
||||
public: \
|
||||
static VertexInputType staticType; \
|
||||
virtual VertexInputType* getType() const override;
|
||||
|
||||
#define IMPLEMENT_VERTEX_INPUT_TYPE(inputClass, shaderFilename) \
|
||||
VertexInputType inputClass::staticType( \
|
||||
#inputClass, \
|
||||
shaderFilename); \
|
||||
VertexInputType* inputClass::getType() const { return &staticType; }
|
||||
|
||||
typedef Array<VertexInputStream> VertexInputStreamArray;
|
||||
struct MeshDescription;
|
||||
DECLARE_REF(VertexShaderInput);
|
||||
class VertexShaderInput
|
||||
{
|
||||
public:
|
||||
VertexShaderInput(std::string name);
|
||||
VertexShaderInput(MeshDescription description, std::string name);
|
||||
~VertexShaderInput();
|
||||
virtual ~VertexShaderInput();
|
||||
void getStreams(VertexInputStreamArray& outVertexStreams) const;
|
||||
void getPositionOnlyStream(VertexInputStreamArray& outVertexStreams) const;
|
||||
virtual bool supportsTesselation() { return false; }
|
||||
virtual VertexInputType* getType() const { return nullptr; }
|
||||
Gfx::PVertexDeclaration getDeclaration() const {return declaration;}
|
||||
Gfx::PVertexDeclaration getPositionDeclaration() const {return positionDeclaration;}
|
||||
std::string getName() const { return name; }
|
||||
std::string getCode() const { return code; }
|
||||
private:
|
||||
protected:
|
||||
static List<PVertexShaderInput> registeredInputs;
|
||||
static std::mutex registeredInputsLock;
|
||||
Array<Gfx::VertexAttribute> layout;
|
||||
StaticArray<Gfx::VertexStream, 16> streams;
|
||||
StaticArray<Gfx::VertexStream, 16> positionStreams;
|
||||
StaticArray<VertexInputStream, 16> streams;
|
||||
StaticArray<VertexInputStream, 16> positionStreams;
|
||||
Gfx::PVertexDeclaration declaration;
|
||||
Gfx::PVertexDeclaration positionDeclaration;
|
||||
std::string name;
|
||||
std::string code;
|
||||
};
|
||||
DEFINE_REF(VertexShaderInput);
|
||||
} // namespace Seele
|
||||
|
||||
@@ -114,7 +114,7 @@ PSubAllocation Allocation::getSuballocation(VkDeviceSize requestedSize, VkDevice
|
||||
void Allocation::markFree(SubAllocation *allocation)
|
||||
{
|
||||
// Dont free if it is already a free allocation, since they also mark themselves on deletion
|
||||
if(freeRanges.find(allocation->allocatedOffset) != nullptr)
|
||||
if (freeRanges.find(allocation->allocatedOffset) != nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -286,6 +286,8 @@ void StagingManager::clearPending()
|
||||
|
||||
PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageFlags usage, bool bCPURead)
|
||||
{
|
||||
|
||||
std::unique_lock l(lock);
|
||||
for (auto it = freeBuffers.begin(); it != freeBuffers.end(); ++it)
|
||||
{
|
||||
auto freeBuffer = *it;
|
||||
@@ -296,6 +298,7 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF
|
||||
return freeBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
PStagingBuffer stagingBuffer = new StagingBuffer();
|
||||
VkBufferCreateInfo stagingBufferCreateInfo = init::BufferCreateInfo(usage, size);
|
||||
VkDevice vulkanDevice = graphics->getDevice();
|
||||
@@ -322,11 +325,13 @@ PStagingBuffer StagingManager::allocateStagingBuffer(uint32 size, VkBufferUsageF
|
||||
vkBindBufferMemory(graphics->getDevice(), stagingBuffer->buffer, stagingBuffer->getMemoryHandle(), stagingBuffer->getOffset());
|
||||
|
||||
activeBuffers.add(stagingBuffer.getHandle());
|
||||
|
||||
return stagingBuffer;
|
||||
}
|
||||
|
||||
void StagingManager::releaseStagingBuffer(PStagingBuffer buffer)
|
||||
{
|
||||
std::unique_lock l(lock);
|
||||
freeBuffers.add(buffer);
|
||||
activeBuffers.remove(activeBuffers.find(buffer.getHandle()));
|
||||
}
|
||||
@@ -213,6 +213,7 @@ private:
|
||||
PAllocator allocator;
|
||||
Array<PStagingBuffer> freeBuffers;
|
||||
Array<StagingBuffer *> activeBuffers;
|
||||
std::mutex lock;
|
||||
};
|
||||
DEFINE_REF(StagingManager);
|
||||
} // namespace Vulkan
|
||||
|
||||
@@ -14,9 +14,9 @@ struct PendingBuffer
|
||||
bool bWriteOnly;
|
||||
};
|
||||
|
||||
static Map<Buffer *, PendingBuffer> pendingBuffers;
|
||||
static Map<ShaderBuffer *, PendingBuffer> pendingBuffers;
|
||||
|
||||
Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType)
|
||||
ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType)
|
||||
: graphics(graphics), currentBuffer(0), size(size), currentOwner(queueType)
|
||||
{
|
||||
if (usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ||
|
||||
@@ -56,21 +56,22 @@ Buffer::Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::Q
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
}
|
||||
|
||||
Buffer::~Buffer()
|
||||
ShaderBuffer::~ShaderBuffer()
|
||||
{
|
||||
auto fence = graphics->getQueueCommands(currentOwner)->getCommands()->getFence();
|
||||
auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||
auto &deletionQueue = graphics->getDeletionQueue();
|
||||
VkDevice device = graphics->getDevice();
|
||||
VkBuffer buf[Gfx::numFramesBuffered];
|
||||
for (uint32 i = 0; i < numBuffers; ++i)
|
||||
{
|
||||
buf[i] = buffers[i].buffer;
|
||||
deletionQueue.addPendingDelete(fence, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); });
|
||||
deletionQueue.addPendingDelete(cmdBuffer, [device, buf, i]() { vkDestroyBuffer(device, buf[i], nullptr); });
|
||||
buffers[i].allocation = nullptr;
|
||||
}
|
||||
graphics = nullptr;
|
||||
}
|
||||
|
||||
void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
void ShaderBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
VkBufferMemoryBarrier barrier =
|
||||
init::BufferMemoryBarrier();
|
||||
@@ -137,7 +138,7 @@ void Buffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
currentOwner = newOwner;
|
||||
}
|
||||
|
||||
void *Buffer::lock(bool bWriteOnly)
|
||||
void *ShaderBuffer::lock(bool bWriteOnly)
|
||||
{
|
||||
void *data = nullptr;
|
||||
|
||||
@@ -208,7 +209,7 @@ void *Buffer::lock(bool bWriteOnly)
|
||||
return data;
|
||||
}
|
||||
|
||||
void Buffer::unlock()
|
||||
void ShaderBuffer::unlock()
|
||||
{
|
||||
auto found = pendingBuffers.find(this);
|
||||
if (found != pendingBuffers.end())
|
||||
@@ -233,8 +234,8 @@ void Buffer::unlock()
|
||||
}
|
||||
|
||||
UniformBuffer::UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData)
|
||||
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, resourceData.owner)
|
||||
, Gfx::UniformBuffer(graphics, resourceData.owner)
|
||||
: Vulkan::ShaderBuffer(graphics, resourceData.size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, resourceData.owner)
|
||||
, Gfx::UniformBuffer(graphics->getFamilyMapping(), resourceData.owner)
|
||||
{
|
||||
if (resourceData.data != nullptr)
|
||||
{
|
||||
@@ -251,12 +252,12 @@ UniformBuffer::~UniformBuffer()
|
||||
void UniformBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
{
|
||||
Gfx::QueueOwnedResource::transferOwnership(newOwner);
|
||||
Buffer::currentOwner = newOwner;
|
||||
Vulkan::ShaderBuffer::currentOwner = newOwner;
|
||||
}
|
||||
|
||||
void UniformBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
Buffer::executeOwnershipBarrier(newOwner);
|
||||
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
|
||||
}
|
||||
|
||||
VkAccessFlags UniformBuffer::getSourceAccessMask()
|
||||
@@ -270,8 +271,8 @@ VkAccessFlags UniformBuffer::getDestAccessMask()
|
||||
}
|
||||
|
||||
StructuredBuffer::StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData)
|
||||
: Buffer(graphics, resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, resourceData.owner)
|
||||
, Gfx::StructuredBuffer(graphics, resourceData.owner)
|
||||
: Vulkan::ShaderBuffer(graphics, resourceData.size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, resourceData.owner)
|
||||
, Gfx::StructuredBuffer(graphics->getFamilyMapping(), resourceData.owner)
|
||||
{
|
||||
if (resourceData.data != nullptr)
|
||||
{
|
||||
@@ -292,7 +293,7 @@ void StructuredBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
|
||||
void StructuredBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
Buffer::executeOwnershipBarrier(newOwner);
|
||||
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
|
||||
}
|
||||
|
||||
VkAccessFlags StructuredBuffer::getSourceAccessMask()
|
||||
@@ -306,8 +307,8 @@ VkAccessFlags StructuredBuffer::getDestAccessMask()
|
||||
}
|
||||
|
||||
VertexBuffer::VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData)
|
||||
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner)
|
||||
, Gfx::VertexBuffer(graphics, resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner)
|
||||
: Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, resourceData.resourceData.owner)
|
||||
, Gfx::VertexBuffer(graphics->getFamilyMapping(), resourceData.numVertices, resourceData.vertexSize, resourceData.resourceData.owner)
|
||||
{
|
||||
if (resourceData.resourceData.data != nullptr)
|
||||
{
|
||||
@@ -328,7 +329,7 @@ void VertexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
|
||||
void VertexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
Buffer::executeOwnershipBarrier(newOwner);
|
||||
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
|
||||
}
|
||||
|
||||
VkAccessFlags VertexBuffer::getSourceAccessMask()
|
||||
@@ -342,8 +343,8 @@ VkAccessFlags VertexBuffer::getDestAccessMask()
|
||||
}
|
||||
|
||||
IndexBuffer::IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData)
|
||||
: Buffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner)
|
||||
, Gfx::IndexBuffer(graphics, resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner)
|
||||
: Vulkan::ShaderBuffer(graphics, resourceData.resourceData.size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, resourceData.resourceData.owner)
|
||||
, Gfx::IndexBuffer(graphics->getFamilyMapping(), resourceData.resourceData.size, resourceData.indexType, resourceData.resourceData.owner)
|
||||
{
|
||||
if (resourceData.resourceData.data != nullptr)
|
||||
{
|
||||
@@ -364,7 +365,7 @@ void IndexBuffer::requestOwnershipTransfer(Gfx::QueueType newOwner)
|
||||
|
||||
void IndexBuffer::executeOwnershipBarrier(Gfx::QueueType newOwner)
|
||||
{
|
||||
Buffer::executeOwnershipBarrier(newOwner);
|
||||
Vulkan::ShaderBuffer::executeOwnershipBarrier(newOwner);
|
||||
}
|
||||
|
||||
VkAccessFlags IndexBuffer::getSourceAccessMask()
|
||||
|
||||
@@ -22,8 +22,8 @@ CmdBufferBase::~CmdBufferBase()
|
||||
graphics = nullptr;
|
||||
}
|
||||
|
||||
CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool)
|
||||
: CmdBufferBase(graphics, cmdPool), renderPass(nullptr), framebuffer(nullptr), subpassIndex(0)
|
||||
CmdBuffer::CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager)
|
||||
: CmdBufferBase(graphics, cmdPool), renderPass(nullptr), framebuffer(nullptr), subpassIndex(0), manager(manager)
|
||||
{
|
||||
VkCommandBufferAllocateInfo allocInfo =
|
||||
init::CommandBufferAllocateInfo(cmdPool,
|
||||
@@ -120,6 +120,11 @@ PFence CmdBuffer::getFence()
|
||||
return fence;
|
||||
}
|
||||
|
||||
PCommandBufferManager CmdBuffer::getManager()
|
||||
{
|
||||
return manager;
|
||||
}
|
||||
|
||||
SecondaryCmdBuffer::SecondaryCmdBuffer(PGraphics graphics, VkCommandPool cmdPool)
|
||||
: CmdBufferBase(graphics, cmdPool)
|
||||
{
|
||||
@@ -195,8 +200,9 @@ CommandBufferManager::CommandBufferManager(PGraphics graphics, PQueue queue)
|
||||
|
||||
VK_CHECK(vkCreateCommandPool(graphics->getDevice(), &info, nullptr, &commandPool));
|
||||
|
||||
activeCmdBuffer = new CmdBuffer(graphics, commandPool);
|
||||
activeCmdBuffer = new CmdBuffer(graphics, commandPool, this);
|
||||
activeCmdBuffer->begin();
|
||||
std::lock_guard lock(allocatedBufferLock);
|
||||
allocatedBuffers.add(activeCmdBuffer);
|
||||
}
|
||||
|
||||
@@ -236,6 +242,7 @@ void CommandBufferManager::submitCommands(PSemaphore signalSemaphore)
|
||||
queue->submitCommandBuffer(activeCmdBuffer);
|
||||
}
|
||||
}
|
||||
std::lock_guard lock(allocatedBufferLock);
|
||||
for (uint32 i = 0; i < allocatedBuffers.size(); ++i)
|
||||
{
|
||||
PCmdBuffer cmdBuffer = allocatedBuffers[i];
|
||||
@@ -251,7 +258,7 @@ void CommandBufferManager::submitCommands(PSemaphore signalSemaphore)
|
||||
assert(cmdBuffer->state == CmdBuffer::State::Submitted);
|
||||
}
|
||||
}
|
||||
activeCmdBuffer = new CmdBuffer(graphics, commandPool);
|
||||
activeCmdBuffer = new CmdBuffer(graphics, commandPool, this);
|
||||
allocatedBuffers.add(activeCmdBuffer);
|
||||
activeCmdBuffer->begin();
|
||||
}
|
||||
|
||||
@@ -30,10 +30,11 @@ protected:
|
||||
DEFINE_REF(CmdBufferBase);
|
||||
|
||||
DECLARE_REF(SecondaryCmdBuffer);
|
||||
DECLARE_REF(CommandBufferManager);
|
||||
class CmdBuffer : public CmdBufferBase
|
||||
{
|
||||
public:
|
||||
CmdBuffer(PGraphics graphics, VkCommandPool cmdPool);
|
||||
CmdBuffer(PGraphics graphics, VkCommandPool cmdPool, PCommandBufferManager manager);
|
||||
virtual ~CmdBuffer();
|
||||
void begin();
|
||||
void end();
|
||||
@@ -43,6 +44,7 @@ public:
|
||||
void addWaitSemaphore(VkPipelineStageFlags stages, PSemaphore waitSemaphore);
|
||||
void refreshFence();
|
||||
PFence getFence();
|
||||
PCommandBufferManager getManager();
|
||||
enum State
|
||||
{
|
||||
ReadyBegin,
|
||||
@@ -53,6 +55,7 @@ public:
|
||||
};
|
||||
|
||||
private:
|
||||
PCommandBufferManager manager;
|
||||
PRenderPass renderPass;
|
||||
PFramebuffer framebuffer;
|
||||
PFence fence;
|
||||
@@ -105,6 +108,7 @@ private:
|
||||
PQueue queue;
|
||||
uint32 queueFamilyIndex;
|
||||
PCmdBuffer activeCmdBuffer;
|
||||
std::mutex allocatedBufferLock;
|
||||
Array<PCmdBuffer> allocatedBuffers;
|
||||
};
|
||||
DEFINE_REF(CommandBufferManager);
|
||||
|
||||
@@ -49,4 +49,5 @@ Framebuffer::Framebuffer(PGraphics graphics, PRenderPass renderPass, Gfx::PRende
|
||||
Framebuffer::~Framebuffer()
|
||||
{
|
||||
vkDestroyFramebuffer(graphics->getDevice(), handle, nullptr);
|
||||
graphics = nullptr;
|
||||
}
|
||||
@@ -64,6 +64,7 @@ void Graphics::beginRenderPass(Gfx::PRenderPass renderPass)
|
||||
if (found == allocatedFramebuffers.end())
|
||||
{
|
||||
framebuffer = new Framebuffer(this, rp, rp->getLayout());
|
||||
allocatedFramebuffers[framebufferHash] = framebuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -23,10 +23,10 @@ QueueOwnedResourceDeletion::~QueueOwnedResourceDeletion()
|
||||
worker.join();
|
||||
}
|
||||
|
||||
void QueueOwnedResourceDeletion::addPendingDelete(PFence fence, std::function<void()> func)
|
||||
void QueueOwnedResourceDeletion::addPendingDelete(PCmdBuffer cmdbuffer, std::function<void()> func)
|
||||
{
|
||||
PendingItem item;
|
||||
item.fence = fence;
|
||||
item.cmdBuffer = cmdbuffer;
|
||||
item.func = func;
|
||||
deletionQueue.add(item);
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
@@ -40,13 +40,12 @@ void QueueOwnedResourceDeletion::run()
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
cv.wait(lock);
|
||||
auto entry = deletionQueue.begin();
|
||||
PFence fence = entry->fence;
|
||||
fence->wait(1000ull);
|
||||
if (fence->isSignaled())
|
||||
{
|
||||
entry->func();
|
||||
deletionQueue.remove(entry);
|
||||
}
|
||||
PCmdBuffer cmdBuffer = entry->cmdBuffer;
|
||||
//cmdBuffer->getManager()->waitForCommands(cmdBuffer);
|
||||
//cmdBuffer->begin();
|
||||
|
||||
//entry->func();
|
||||
deletionQueue.remove(entry);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Vulkan
|
||||
|
||||
DECLARE_REF(DescriptorAllocator);
|
||||
DECLARE_REF(CommandBufferManager);
|
||||
DECLARE_REF(CmdBuffer);
|
||||
DECLARE_REF(Graphics);
|
||||
DECLARE_REF(SubAllocation);
|
||||
class Semaphore
|
||||
@@ -57,7 +58,7 @@ class QueueOwnedResourceDeletion
|
||||
public:
|
||||
QueueOwnedResourceDeletion();
|
||||
virtual ~QueueOwnedResourceDeletion();
|
||||
static void addPendingDelete(PFence fence, std::function<void()> function);
|
||||
static void addPendingDelete(PCmdBuffer fence, std::function<void()> function);
|
||||
|
||||
private:
|
||||
std::thread worker;
|
||||
@@ -65,7 +66,7 @@ private:
|
||||
static void run();
|
||||
struct PendingItem
|
||||
{
|
||||
PFence fence;
|
||||
PCmdBuffer cmdBuffer;
|
||||
std::function<void()> func;
|
||||
};
|
||||
static std::mutex mutex;
|
||||
@@ -73,11 +74,11 @@ private:
|
||||
static List<PendingItem> deletionQueue;
|
||||
};
|
||||
|
||||
class Buffer
|
||||
class ShaderBuffer
|
||||
{
|
||||
public:
|
||||
Buffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType);
|
||||
virtual ~Buffer();
|
||||
ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags usage, Gfx::QueueType queueType);
|
||||
virtual ~ShaderBuffer();
|
||||
VkBuffer getHandle() const
|
||||
{
|
||||
return buffers[currentBuffer].buffer;
|
||||
@@ -108,9 +109,9 @@ protected:
|
||||
virtual VkAccessFlags getSourceAccessMask() = 0;
|
||||
virtual VkAccessFlags getDestAccessMask() = 0;
|
||||
};
|
||||
DEFINE_REF(Buffer);
|
||||
DEFINE_REF(ShaderBuffer);
|
||||
|
||||
class UniformBuffer : public Buffer, public Gfx::UniformBuffer
|
||||
class UniformBuffer : public Gfx::UniformBuffer, public ShaderBuffer
|
||||
{
|
||||
public:
|
||||
UniformBuffer(PGraphics graphics, const BulkResourceData &resourceData);
|
||||
@@ -126,7 +127,7 @@ protected:
|
||||
};
|
||||
DEFINE_REF(UniformBuffer);
|
||||
|
||||
class StructuredBuffer : public Buffer, public Gfx::StructuredBuffer
|
||||
class StructuredBuffer : public Gfx::StructuredBuffer, public ShaderBuffer
|
||||
{
|
||||
public:
|
||||
StructuredBuffer(PGraphics graphics, const BulkResourceData &resourceData);
|
||||
@@ -142,7 +143,7 @@ protected:
|
||||
};
|
||||
DEFINE_REF(StructuredBuffer);
|
||||
|
||||
class VertexBuffer : public Buffer, public Gfx::VertexBuffer
|
||||
class VertexBuffer : public Gfx::VertexBuffer, public ShaderBuffer
|
||||
{
|
||||
public:
|
||||
VertexBuffer(PGraphics graphics, const VertexBufferCreateInfo &resourceData);
|
||||
@@ -158,7 +159,7 @@ protected:
|
||||
};
|
||||
DEFINE_REF(VertexBuffer);
|
||||
|
||||
class IndexBuffer : public Buffer, public Gfx::IndexBuffer
|
||||
class IndexBuffer : public Gfx::IndexBuffer, public ShaderBuffer
|
||||
{
|
||||
public:
|
||||
IndexBuffer(PGraphics graphics, const IndexBufferCreateInfo &resourceData);
|
||||
@@ -249,7 +250,7 @@ protected:
|
||||
};
|
||||
DEFINE_REF(TextureBase);
|
||||
|
||||
class Texture2D : public TextureBase, public Gfx::Texture2D
|
||||
class Texture2D : public Gfx::Texture2D, public TextureBase
|
||||
{
|
||||
public:
|
||||
Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage = VK_NULL_HANDLE);
|
||||
|
||||
@@ -242,7 +242,6 @@ PGraphicsPipeline PipelineCache::createPipeline(const GraphicsPipelineCreateInfo
|
||||
0
|
||||
);
|
||||
|
||||
|
||||
createInfo.pStages = stageInfos;
|
||||
createInfo.pVertexInputState = &vertexInput;
|
||||
createInfo.pInputAssemblyState = &assemblyInfo;
|
||||
|
||||
@@ -55,7 +55,6 @@ void Shader::create(const ShaderCreateInfo& createInfo)
|
||||
int targetIndex = spAddCodeGenTarget(request, SLANG_SPIRV);
|
||||
spSetTargetProfile(request, targetIndex, spFindProfile(session, "glsl_vk"));
|
||||
spSetDumpIntermediates(request, true);
|
||||
|
||||
int translationUnitIndex = spAddTranslationUnit(request, SLANG_SOURCE_LANGUAGE_SLANG, "");
|
||||
|
||||
for(auto code : createInfo.shaderCode)
|
||||
@@ -67,15 +66,20 @@ void Shader::create(const ShaderCreateInfo& createInfo)
|
||||
code.data()
|
||||
);
|
||||
}
|
||||
for(auto define : createInfo.defines)
|
||||
{
|
||||
spAddPreprocessorDefine(request, define.key, define.value);
|
||||
}
|
||||
spAddSearchPath(request, "shaders/lib/");
|
||||
spAddSearchPath(request, "shaders/generated/");
|
||||
|
||||
spSetGlobalGenericArgs(request, createInfo.typeParameter.size(), createInfo.typeParameter.data());
|
||||
|
||||
int entryPointIndex = spAddEntryPoint(request, translationUnitIndex, entryPointName.c_str(), getStageFromShaderType(type));
|
||||
if(spCompile(request))
|
||||
{
|
||||
char const* diagnostice = spGetDiagnosticOutput(request);
|
||||
std::cout << diagnostice << std::endl;
|
||||
char const* diagnostics = spGetDiagnosticOutput(request);
|
||||
std::cout << diagnostics << std::endl;
|
||||
}
|
||||
|
||||
ShaderReflection* reflection = slang::ShaderReflection::get(request);
|
||||
|
||||
@@ -154,12 +154,12 @@ TextureHandle::TextureHandle(PGraphics graphics, VkImageViewType viewType,
|
||||
TextureHandle::~TextureHandle()
|
||||
{
|
||||
auto &deletionQueue = graphics->getDeletionQueue();
|
||||
auto fence = graphics->getQueueCommands(currentOwner)->getCommands()->getFence();
|
||||
auto cmdBuffer = graphics->getQueueCommands(currentOwner)->getCommands();
|
||||
VkDevice device = graphics->getDevice();
|
||||
VkImageView view = defaultView;
|
||||
VkImage img = image;
|
||||
deletionQueue.addPendingDelete(fence, [device, view]() { vkDestroyImageView(device, view, nullptr); });
|
||||
deletionQueue.addPendingDelete(fence, [device, img]() { vkDestroyImage(device, img, nullptr); });
|
||||
deletionQueue.addPendingDelete(cmdBuffer, [device, view]() { vkDestroyImageView(device, view, nullptr); });
|
||||
deletionQueue.addPendingDelete(cmdBuffer, [device, img]() { vkDestroyImage(device, img, nullptr); });
|
||||
}
|
||||
|
||||
void TextureHandle::changeLayout(VkImageLayout newLayout)
|
||||
@@ -243,7 +243,7 @@ void TextureBase::changeLayout(VkImageLayout newLayout)
|
||||
}
|
||||
|
||||
Texture2D::Texture2D(PGraphics graphics, const TextureCreateInfo& createInfo, VkImage existingImage)
|
||||
: Gfx::Texture2D(graphics, createInfo.resourceData.owner)
|
||||
: Gfx::Texture2D(graphics->getFamilyMapping(), createInfo.resourceData.owner)
|
||||
{
|
||||
textureHandle = new TextureHandle(graphics, createInfo.bArray ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
|
||||
createInfo, existingImage);
|
||||
|
||||
@@ -42,6 +42,14 @@ void Seele::WindowManager::beginFrame()
|
||||
}
|
||||
}
|
||||
|
||||
void WindowManager::render()
|
||||
{
|
||||
for(auto window : windows)
|
||||
{
|
||||
window->render();
|
||||
}
|
||||
}
|
||||
|
||||
void Seele::WindowManager::endFrame()
|
||||
{
|
||||
for (auto window : windows)
|
||||
|
||||
@@ -13,6 +13,7 @@ public:
|
||||
~WindowManager();
|
||||
PWindow addWindow(const WindowCreateInfo &createInfo);
|
||||
void beginFrame();
|
||||
void render();
|
||||
void endFrame();
|
||||
static Gfx::PGraphics getGraphics()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
#include "BRDF.h"
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using namespace Seele;
|
||||
using json = nlohmann::json;
|
||||
|
||||
List<BRDF*> BRDF::globalBRDFList;
|
||||
|
||||
BRDF::BRDF(const char* name)
|
||||
: name(name)
|
||||
{
|
||||
globalBRDFList.add(this);
|
||||
}
|
||||
|
||||
BRDF::~BRDF()
|
||||
{
|
||||
globalBRDFList.remove(globalBRDFList.find(this));
|
||||
}
|
||||
|
||||
|
||||
BRDF* BRDF::getBRDFByName(const std::string& name)
|
||||
{
|
||||
for(auto brdf : globalBRDFList)
|
||||
{
|
||||
if(name.compare(brdf->name) == 0)
|
||||
{
|
||||
return brdf;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
List<BRDF*> BRDF::getBRDFList()
|
||||
{
|
||||
return globalBRDFList;
|
||||
}
|
||||
|
||||
BlinnPhong::BlinnPhong(const char* name)
|
||||
: BRDF(name)
|
||||
{
|
||||
}
|
||||
|
||||
BlinnPhong::~BlinnPhong()
|
||||
{
|
||||
}
|
||||
|
||||
void BlinnPhong::generateMaterialCode(std::ofstream& codeStream, json codeJson)
|
||||
{
|
||||
std::stringstream accessorStream;
|
||||
|
||||
auto generateAccessor = [codeJson](std::stringstream& accessorStream, const std::string& key, const std::string& defaultVal)
|
||||
{
|
||||
if(codeJson.contains(key))
|
||||
{
|
||||
for(auto code : codeJson[key].items())
|
||||
{
|
||||
accessorStream << code.value().get<std::string>() << ";" << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
accessorStream << "return " << defaultVal << ";";
|
||||
}
|
||||
|
||||
};
|
||||
accessorStream << "float3 getBaseColor(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "baseColor", "float3(0, 0, 0)");
|
||||
accessorStream << "}";
|
||||
|
||||
accessorStream << "float getMetallic(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "metallic", "0.f");
|
||||
accessorStream << "}";
|
||||
|
||||
accessorStream << "float3 getNormal(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "normal", "float3(0, 1, 0)");
|
||||
accessorStream << "}";
|
||||
|
||||
accessorStream << "float getSpecular(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "specular", "0.f");
|
||||
accessorStream << "}";
|
||||
|
||||
accessorStream << "float getRoughness(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "roughness", "0.f");
|
||||
accessorStream << "}";
|
||||
|
||||
accessorStream << "float getSheen(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "sheen", "0.f");
|
||||
accessorStream << "}";
|
||||
|
||||
/*accessorStream << "float getSpecularTint(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "specularTint", "0.f");
|
||||
accessorStream << "}";
|
||||
|
||||
accessorStream << "float getAnisotropic(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "anisotropic", "0.f");
|
||||
accessorStream << "}";
|
||||
|
||||
|
||||
accessorStream << "float getSheenTint(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "sheenTint", "0.f");
|
||||
accessorStream << "}";
|
||||
|
||||
accessorStream << "float getClearCoat(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "clearCoat", "0.f");
|
||||
accessorStream << "}";
|
||||
|
||||
accessorStream << "float getClearCoatGloss(MaterialFragmentParameter input) {\n";
|
||||
generateAccessor(accessorStream, "clearCoatGloss", "0.f");
|
||||
accessorStream << "}";*/
|
||||
|
||||
accessorStream << "float3 getWorldOffset() {\n";
|
||||
generateAccessor(accessorStream, "worldOffset", "0.f");
|
||||
accessorStream << "}";
|
||||
|
||||
codeStream << accessorStream.str();
|
||||
|
||||
codeStream << "typedef " << name << " BRDF;" << std::endl;
|
||||
codeStream << name << " prepare(MaterialFragmentParameter geometry){" << std::endl;
|
||||
codeStream << name << " result;" << std::endl;
|
||||
codeStream << "result.baseColor = getBaseColor(geometry);" << std::endl;
|
||||
codeStream << "result.metallic = getMetallic(geometry);" << std::endl;
|
||||
codeStream << "result.normal = geometry.transformNormalTexture(getNormal(geometry));" << std::endl;
|
||||
codeStream << "result.specular = getSpecular(geometry);" << std::endl;
|
||||
codeStream << "result.roughness = getRoughness(geometry);" << std::endl;
|
||||
codeStream << "result.sheen = getSheen(geometry);" << std::endl;
|
||||
codeStream << "return result;" << std::endl;
|
||||
codeStream << "}" << std::endl;
|
||||
}
|
||||
|
||||
IMPLEMENT_BRDF(BlinnPhong);
|
||||
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "MinimalEngine.h"
|
||||
#include "Containers/List.h"
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
class BRDF
|
||||
{
|
||||
public:
|
||||
static BRDF* getBRDFByName(const std::string& name);
|
||||
static List<BRDF*> getBRDFList();
|
||||
|
||||
virtual void generateMaterialCode(std::ofstream& codeStream, nlohmann::json codeJson) = 0;
|
||||
protected:
|
||||
BRDF(const char* name);
|
||||
virtual ~BRDF();
|
||||
static List<BRDF*> globalBRDFList;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
#define DECLARE_BRDF(inputClass) \
|
||||
public: \
|
||||
static inputClass staticType;
|
||||
|
||||
#define IMPLEMENT_BRDF(inputClass) \
|
||||
inputClass inputClass::staticType( \
|
||||
#inputClass);
|
||||
|
||||
class BlinnPhong : public BRDF
|
||||
{
|
||||
DECLARE_BRDF(BlinnPhong);
|
||||
public:
|
||||
virtual void generateMaterialCode(std::ofstream& codeStream, nlohmann::json codeJson);
|
||||
protected:
|
||||
BlinnPhong(const char* name);
|
||||
virtual ~BlinnPhong();
|
||||
};
|
||||
} // namespace Seele
|
||||
@@ -1,5 +1,7 @@
|
||||
target_sources(SeeleEngine
|
||||
PRIVATE
|
||||
BRDF.h
|
||||
BRDF.cpp
|
||||
Material.h
|
||||
Material.cpp
|
||||
MaterialAsset.h
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "Material.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
#include "Graphics/VertexShaderInput.h"
|
||||
#include "BRDF.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
@@ -45,13 +46,15 @@ void Material::compile()
|
||||
auto& stream = getReadStream();
|
||||
json j;
|
||||
stream >> j;
|
||||
std::stringstream codeStream;
|
||||
materialName = j["name"].get<std::string>();
|
||||
std::ofstream codeStream("./shaders/generated/"+materialName+".slang");
|
||||
std::string profile = j["profile"].get<std::string>();
|
||||
|
||||
codeStream << "import VERTEX_INPUT_IMPORT;" << std::endl;
|
||||
codeStream << "import LightEnv;" << std::endl;
|
||||
codeStream << "import Material;" << std::endl;
|
||||
codeStream << "import BRDF;" << std::endl;
|
||||
codeStream << "import InputGeometry;" << std::endl;
|
||||
codeStream << "import MaterialParameter;" << std::endl;
|
||||
|
||||
codeStream << "struct " << materialName << ": IMaterial {" << std::endl;
|
||||
for(auto param : j["params"].items())
|
||||
@@ -62,6 +65,7 @@ void Material::compile()
|
||||
if(type.compare("float") == 0)
|
||||
{
|
||||
PFloatParameter p = new FloatParameter();
|
||||
p->name = param.key();
|
||||
if(default != param.value().end())
|
||||
{
|
||||
p->defaultValue = std::stof(default.value().get<std::string>());
|
||||
@@ -71,6 +75,7 @@ void Material::compile()
|
||||
else if(type.compare("float3") == 0)
|
||||
{
|
||||
PVectorParameter p = new VectorParameter();
|
||||
p->name = param.key();
|
||||
if(default != param.value().end())
|
||||
{
|
||||
p->defaultValue = parseVector(default.value().get<std::string>().c_str());
|
||||
@@ -80,6 +85,7 @@ void Material::compile()
|
||||
else if(type.compare("Texture2D") == 0)
|
||||
{
|
||||
PTextureParameter p = new TextureParameter();
|
||||
p->name = param.key();
|
||||
if(default != param.value().end())
|
||||
{
|
||||
|
||||
@@ -89,37 +95,32 @@ void Material::compile()
|
||||
else if(type.compare("SamplerState") == 0)
|
||||
{
|
||||
PSamplerParameter p = new SamplerParameter();
|
||||
p->name = param.key();
|
||||
parameters.add(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error unsupported parameter type" << std::endl;
|
||||
}
|
||||
codeStream << type << " " << param.key();
|
||||
codeStream << type << " " << param.key() << ";\n";
|
||||
}
|
||||
codeStream << "typedef " << profile << " BRDF;" << std::endl;
|
||||
codeStream << profile << " prepare(MaterialPixelParameter geometry){" << std::endl;
|
||||
codeStream << profile << " result;" << std::endl;
|
||||
for(auto c : j["code"].items())
|
||||
{
|
||||
codeStream << c.value().get<std::string>() << std::endl;
|
||||
}
|
||||
|
||||
codeStream << "}};" << std::endl;
|
||||
materialCode = codeStream.str();
|
||||
BRDF* brdf = BRDF::getBRDFByName(profile);
|
||||
brdf->generateMaterialCode(codeStream, j["code"]);
|
||||
codeStream << "};";
|
||||
codeStream.close();
|
||||
}
|
||||
|
||||
const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput) const
|
||||
const Gfx::ShaderCollection* Material::getShaders(Gfx::RenderPassType renderPass, VertexInputType* vertexInput) const
|
||||
{
|
||||
Gfx::ShaderPermutation permutation;
|
||||
std::string materialName = getMaterialName();
|
||||
std::string materialName = getFileName();
|
||||
std::string vertexInputName = vertexInput->getName();
|
||||
std::memcpy(permutation.materialName, materialName.c_str(), sizeof(permutation.materialName));
|
||||
std::memcpy(permutation.materialName, vertexInputName.c_str(), sizeof(permutation.materialName));
|
||||
return shaderMap.findShaders(Gfx::PermutationId(permutation));
|
||||
}
|
||||
|
||||
Gfx::ShaderCollection& Material::createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput)
|
||||
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);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
namespace Seele
|
||||
{
|
||||
|
||||
class VertexInputType;
|
||||
class Material : public MaterialAsset
|
||||
{
|
||||
public:
|
||||
@@ -14,18 +14,17 @@ public:
|
||||
~Material();
|
||||
virtual void save() override;
|
||||
virtual void load() override;
|
||||
virtual std::string getMaterialName() const { return materialName; }
|
||||
inline std::string getCode() const { return materialCode; }
|
||||
virtual PMaterial getRenderMaterial() { return this; }
|
||||
const std::string& getName() {return materialName;}
|
||||
|
||||
const Gfx::ShaderCollection* getShaders(Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput) const;
|
||||
Gfx::ShaderCollection& createShaders(Gfx::PGraphics graphics, Gfx::RenderPassType renderPass, PVertexShaderInput vertexInput);
|
||||
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;
|
||||
|
||||
void compile();
|
||||
std::string materialName;
|
||||
std::string materialCode;
|
||||
friend class MaterialLoader;
|
||||
};
|
||||
DEFINE_REF(Material);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
namespace Seele
|
||||
{
|
||||
DECLARE_REF(VertexShaderInput);
|
||||
DECLARE_REF(Material);
|
||||
class MaterialAsset : public Asset
|
||||
{
|
||||
public:
|
||||
@@ -15,7 +16,7 @@ public:
|
||||
~MaterialAsset();
|
||||
virtual void save() = 0;
|
||||
virtual void load() = 0;
|
||||
virtual std::string getMaterialName() const = 0;
|
||||
virtual PMaterial getRenderMaterial() = 0;
|
||||
Gfx::SeBlendOp getBlendMode() const {return Gfx::SE_BLEND_OP_END_RANGE;}
|
||||
Gfx::MaterialShadingModel getShadingModel() const {return Gfx::MaterialShadingModel::DefaultLit;}
|
||||
|
||||
|
||||
@@ -31,9 +31,9 @@ void MaterialInstance::load()
|
||||
|
||||
}
|
||||
|
||||
inline std::string MaterialInstance::getMaterialName() const
|
||||
PMaterial MaterialInstance::getRenderMaterial()
|
||||
{
|
||||
return baseMaterial->getMaterialName();
|
||||
return baseMaterial;
|
||||
}
|
||||
|
||||
PMaterial MaterialInstance::getBaseMaterial() const
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
~MaterialInstance();
|
||||
virtual void save() override;
|
||||
virtual void load() override;
|
||||
inline std::string getMaterialName() const;
|
||||
virtual PMaterial getRenderMaterial();
|
||||
PMaterial getBaseMaterial() const;
|
||||
Gfx::PDescriptorSet getDescriptor();
|
||||
private:
|
||||
|
||||
@@ -48,7 +48,10 @@ public:
|
||||
}
|
||||
~RefObject()
|
||||
{
|
||||
registeredObjects.erase(handle);
|
||||
{
|
||||
std::scoped_lock lock(registeredObjectsLock);
|
||||
registeredObjects.erase(handle);
|
||||
}
|
||||
// we cant always have the definition of every class
|
||||
#pragma warning(disable : 4150)
|
||||
delete handle;
|
||||
@@ -122,7 +125,9 @@ public:
|
||||
}
|
||||
RefPtr(T *ptr)
|
||||
{
|
||||
std::unique_lock l(registeredObjectsLock);
|
||||
auto registeredObj = registeredObjects.find(ptr);
|
||||
l.unlock();
|
||||
if (registeredObj == registeredObjects.end())
|
||||
{
|
||||
object = new RefObject<T>(ptr);
|
||||
@@ -155,7 +160,7 @@ public:
|
||||
RefPtr(const RefPtr<F> &other)
|
||||
{
|
||||
F *f = other.getObject()->getHandle();
|
||||
static_cast<T *>(f);
|
||||
T* t = static_cast<T *>(f);
|
||||
object = (RefObject<T> *)other.getObject();
|
||||
object->addRef();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,29 @@ PrimitiveComponent::PrimitiveComponent()
|
||||
|
||||
PrimitiveComponent::PrimitiveComponent(PMeshAsset asset)
|
||||
{
|
||||
auto assetMeshes = asset->getMeshes();
|
||||
staticMeshes.resize(assetMeshes.size());
|
||||
for (uint32 i = 0; i < assetMeshes.size(); i++)
|
||||
{
|
||||
auto& batch = staticMeshes[i];
|
||||
batch.material = assetMeshes[i]->referencedMaterial->getRenderMaterial();
|
||||
batch.isBackfaceCullingDisabled = false;
|
||||
batch.isCastingShadow = true;
|
||||
batch.primitiveComponent = this;
|
||||
batch.topology = Gfx::SE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
batch.useReverseCulling = false;
|
||||
batch.useWireframe = false;
|
||||
batch.vertexInput = assetMeshes[i]->vertexInput;
|
||||
auto& batchElement = batch.elements.add();
|
||||
batchElement.baseVertexIndex = 0;
|
||||
batchElement.firstIndex = 0;
|
||||
batchElement.indexBuffer = assetMeshes[i]->indexBuffer;
|
||||
batchElement.indirectArgsBuffer = nullptr;
|
||||
batchElement.instanceRuns = nullptr;
|
||||
batchElement.isInstanced = false;
|
||||
batchElement.numInstances = 1;
|
||||
batchElement.numPrimitives = assetMeshes[i]->indexBuffer->getNumIndices() / 3; //TODO: hardcoded
|
||||
}
|
||||
}
|
||||
|
||||
PrimitiveComponent::~PrimitiveComponent()
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Seele
|
||||
struct PrimitiveUniformBuffer
|
||||
{
|
||||
Matrix4 localToWorld;
|
||||
Vector4 worldToLocal;
|
||||
Matrix4 worldToLocal;
|
||||
Vector4 actorWorldPosition;
|
||||
};
|
||||
} // namespace Seele
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#include "Scene.h"
|
||||
#include "Components/PrimitiveComponent.h"
|
||||
#include "Components/PrimitiveUniformBufferLayout.h"
|
||||
#include "Material/MaterialInstance.h"
|
||||
#include "Material/Material.h"
|
||||
#include "Graphics/Graphics.h"
|
||||
|
||||
using namespace Seele;
|
||||
|
||||
Scene::Scene()
|
||||
Scene::Scene(Gfx::PGraphics graphics)
|
||||
: graphics(graphics)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -30,4 +33,21 @@ void Scene::addActor(PActor actor)
|
||||
void Scene::addPrimitiveComponent(PPrimitiveComponent comp)
|
||||
{
|
||||
primitives.add(comp);
|
||||
for(auto batch : comp->staticMeshes)
|
||||
{
|
||||
PrimitiveUniformBuffer data;
|
||||
data.actorWorldPosition = Vector4(comp->getTransform().getPosition(), 1);
|
||||
data.localToWorld = comp->getRenderMatrix();
|
||||
data.worldToLocal = glm::inverse(data.localToWorld);
|
||||
BulkResourceData createInfo;
|
||||
createInfo.data = reinterpret_cast<uint8*>(&data);
|
||||
createInfo.owner = Gfx::QueueType::GRAPHICS;
|
||||
createInfo.size = sizeof(data);
|
||||
Gfx::PUniformBuffer uniformBuffer = graphics->createUniformBuffer(createInfo);
|
||||
for(auto& element : batch.elements)
|
||||
{
|
||||
element.uniformBuffer = uniformBuffer;
|
||||
}
|
||||
staticMeshes.add(batch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,17 +13,18 @@ DECLARE_REF(Material);
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
Scene();
|
||||
Scene(Gfx::PGraphics graphics);
|
||||
~Scene();
|
||||
void tick(float deltaTime);
|
||||
void addActor(PActor actor);
|
||||
void addPrimitiveComponent(PPrimitiveComponent comp);
|
||||
|
||||
const Array<PPrimitiveComponent>& getPrimitives() const { return primitives; }
|
||||
const Array<MeshBatch>& getStaticMeshes() const { return staticMeshes; }
|
||||
private:
|
||||
Array<MeshBatch> meshBatches;
|
||||
Array<MeshBatch> staticMeshes;
|
||||
Array<PActor> rootActors;
|
||||
Array<PPrimitiveComponent> primitives;
|
||||
public:
|
||||
Gfx::PGraphics graphics;
|
||||
};
|
||||
} // namespace Seele
|
||||
@@ -1,12 +1,30 @@
|
||||
#include "Graphics/RenderCore.h"
|
||||
#include "Graphics/SceneView.h"
|
||||
#include "Asset/AssetRegistry.h"
|
||||
using namespace Seele;
|
||||
int main()
|
||||
{
|
||||
RenderCore core;
|
||||
core.init();
|
||||
WindowCreateInfo mainWindowInfo;
|
||||
mainWindowInfo.title = "SeeleEngine";
|
||||
mainWindowInfo.width = 1280;
|
||||
mainWindowInfo.height = 720;
|
||||
mainWindowInfo.bFullscreen = false;
|
||||
mainWindowInfo.numSamples = 1;
|
||||
mainWindowInfo.pixelFormat = Gfx::SE_FORMAT_R8G8B8_UNORM;
|
||||
auto window = core.getWindowManager()->addWindow(mainWindowInfo);
|
||||
ViewportCreateInfo sceneViewInfo;
|
||||
sceneViewInfo.sizeX = 1280;
|
||||
sceneViewInfo.sizeY = 720;
|
||||
sceneViewInfo.offsetX = 0;
|
||||
sceneViewInfo.offsetY = 0;
|
||||
PSceneView sceneView = new SceneView(core.getWindowManager()->getGraphics(), window, sceneViewInfo);
|
||||
window->addView(sceneView);
|
||||
AssetRegistry::init("D:\\Private\\Programming\\C++\\TestSeeleProject");
|
||||
AssetRegistry::importFile("D:\\Private\\Programming\\Unreal Engine\\Assets\\Arissa\\Arissa.fbx");
|
||||
PPrimitiveComponent arissa = new PrimitiveComponent(AssetRegistry::findMesh("Arissa"));
|
||||
sceneView->getScene()->addPrimitiveComponent(arissa);
|
||||
core.renderLoop();
|
||||
core.shutdown();
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user