Generalised SHResourceManager

This commit is contained in:
Kah Wei 2022-10-28 21:32:05 +08:00
parent ade24b904f
commit e4394b6170
13 changed files with 221 additions and 173 deletions

Binary file not shown.

View File

@ -1,3 +1,3 @@
Name: Kirsch_CS
ID: 19931255
ID: 39301863
Type: 2

Binary file not shown.

View File

@ -1,3 +1,3 @@
Name: PureCopy_CS
ID: 29659779
ID: 34987209
Type: 2

Binary file not shown.

View File

@ -1,3 +1,3 @@
Name: TestCube_FS
ID: 18415057
ID: 37450402
Type: 2

Binary file not shown.

View File

@ -1,3 +1,3 @@
Name: TestCube_VS
ID: 29315909
ID: 41688429
Type: 2

View File

@ -10,6 +10,7 @@
*****************************************************************************/
#pragma once
#include <vulkan/vulkan.hpp>
#include "SHAssetData.h"
#include "SH_API.h"
#include <vector>
@ -17,12 +18,14 @@
namespace SHADE
{
//! Tighter control over types of shaders. Maps directly to their
//! equivalent vk::ShaderStageFlagBits.
enum class SH_SHADER_TYPE : uint8_t
{
VERTEX,
FRAGMENT,
COMPUTE,
INAVLID_TYPE
VERTEX = static_cast<uint8_t>(vk::ShaderStageFlagBits::eVertex),
FRAGMENT = static_cast<uint8_t>(vk::ShaderStageFlagBits::eFragment),
COMPUTE = static_cast<uint8_t>(vk::ShaderStageFlagBits::eCompute),
INAVLID_TYPE = std::numeric_limits<uint8_t>::max()
};
struct SH_API SHShaderAsset : SHAssetData

View File

@ -19,144 +19,145 @@
namespace SHADE
{
std::string SHShaderSourceCompiler::CompileShaderSourceToBinary(AssetPath path, SHShaderAsset const& data) noexcept
{
std::string newPath{ path.string() };
std::string SHShaderSourceCompiler::CompileShaderSourceToBinary(AssetPath path, SHShaderAsset const& data) noexcept
{
std::string newPath{ path.string() };
newPath = newPath.substr(0, newPath.find_last_of('.'));
newPath += SHADER_BUILT_IN_EXTENSION.data();
std::ofstream file{ newPath, std::ios::binary | std::ios::out | std::ios::trunc };
std::ofstream file{ newPath, std::ios::binary | std::ios::out | std::ios::trunc };
file.write(
reinterpret_cast<char const*>(& data.shaderType), sizeof(uint8_t)
);
file.write(
reinterpret_cast<char const*>(& data.shaderType), sizeof(uint8_t)
);
size_t const byteCount = sizeof(uint32_t) * data.spirvBinary.size();
size_t const byteCount = sizeof(uint32_t) * data.spirvBinary.size();
file.write(
reinterpret_cast<char const*>(&byteCount), sizeof(size_t)
);
file.write(
reinterpret_cast<char const*>(&byteCount), sizeof(size_t)
);
file.write(
reinterpret_cast<char const*>(data.spirvBinary.data()), byteCount
);
file.write(
reinterpret_cast<char const*>(data.spirvBinary.data()), byteCount
);
file.close();
file.close();
return newPath;
}
return newPath;
}
SHShaderAsset const* SHShaderSourceCompiler::CompileShaderSourceToMemory(std::string const& data, std::string const& name, SH_SHADER_TYPE type) noexcept
{
// shaderc compiler
shaderc::Compiler compiler;
shaderc::CompileOptions options;
SHShaderAsset const* SHShaderSourceCompiler::CompileShaderSourceToMemory(std::string const& data, std::string const& name, SH_SHADER_TYPE type) noexcept
{
// shaderc compiler
shaderc::Compiler compiler;
shaderc::CompileOptions options;
options.AddMacroDefinition("MY_DEFINE", "1");
options.AddMacroDefinition("MY_DEFINE", "1");
//TODO: Check if we need optimisation levels when compiling into spirv
// Set optimization levels
//if (opLevel != shaderc_optimization_level_zero)
// options.SetOptimizationLevel(opLevel);
//TODO: Check if we need optimisation levels when compiling into spirv
// Set optimization levels
//if (opLevel != shaderc_optimization_level_zero)
// options.SetOptimizationLevel(opLevel);
// Attempt to get the shaderc equivalent shader stage
shaderc_shader_kind shaderKind;
switch (type)
{
case SH_SHADER_TYPE::VERTEX:
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
break;
case SH_SHADER_TYPE::FRAGMENT:
shaderKind = shaderc_shader_kind::shaderc_glsl_fragment_shader;
break;
case SH_SHADER_TYPE::COMPUTE:
shaderKind = shaderc_shader_kind::shaderc_glsl_compute_shader;
break;
default:
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
break;
}
// Attempt to get the shaderc equivalent shader stage
shaderc_shader_kind shaderKind;
switch (type)
{
case SH_SHADER_TYPE::VERTEX:
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
break;
case SH_SHADER_TYPE::FRAGMENT:
shaderKind = shaderc_shader_kind::shaderc_glsl_fragment_shader;
break;
case SH_SHADER_TYPE::COMPUTE:
shaderKind = shaderc_shader_kind::shaderc_glsl_compute_shader;
break;
default:
shaderKind = shaderc_shader_kind::shaderc_glsl_vertex_shader;
break;
}
// Compile the shader and get the result
shaderc::SpvCompilationResult compileResult = compiler.CompileGlslToSpv(data, shaderKind, name.c_str(), options);
// Compile the shader and get the result
shaderc::SpvCompilationResult compileResult = compiler.CompileGlslToSpv(data, shaderKind, name.c_str(), options);
if (compileResult.GetCompilationStatus() != shaderc_compilation_status_success)
{
SHLOG_ERROR("Shaderc failed to compile GLSL shader to binary | " + compileResult.GetErrorMessage());
return nullptr;
}
if (compileResult.GetCompilationStatus() != shaderc_compilation_status_success)
{
SHLOG_ERROR("Shaderc failed to compile GLSL shader to binary | " + compileResult.GetErrorMessage());
return nullptr;
}
auto result = new SHShaderAsset();
result->spirvBinary.resize(compileResult.end() - compileResult.begin());
auto result = new SHShaderAsset();
result->spirvBinary.resize(compileResult.end() - compileResult.begin());
std::ranges::copy(compileResult.begin(), compileResult.end(), result->spirvBinary.data());
std::ranges::copy(compileResult.begin(), compileResult.end(), result->spirvBinary.data());
result->name = name;
result->shaderType = type;
return result;
}
return result;
}
SH_SHADER_TYPE SHShaderSourceCompiler::GetShaderTypeFromFilename(std::string name) noexcept
{
for (auto i { 0}; i < SHADER_TYPE_MAX_COUNT; ++i)
{
if (name.find(SHADER_IDENTIFIERS[i].data()) != std::string::npos)
{
return static_cast<SH_SHADER_TYPE>(i);
}
}
SH_SHADER_TYPE SHShaderSourceCompiler::GetShaderTypeFromFilename(std::string name) noexcept
{
for (auto i { 0 }; i < SHADER_TYPE_MAX_COUNT; ++i)
{
const auto& [SHADER_SUFFIX, SHADER_TYPE] = SHADER_IDENTIFIERS[i];
if (name.find(SHADER_SUFFIX.data()) != std::string::npos)
{
return SHADER_TYPE;
}
}
return SH_SHADER_TYPE::INAVLID_TYPE;
}
return SH_SHADER_TYPE::INAVLID_TYPE;
}
std::optional<AssetPath> SHShaderSourceCompiler::LoadAndCompileShader(AssetPath path) noexcept
{
auto type = GetShaderTypeFromFilename(path.filename().string());
{
auto type = GetShaderTypeFromFilename(path.filename().string());
if (type == SH_SHADER_TYPE::INAVLID_TYPE)
{
SHLOG_ERROR("Invalid filename for shaders, follow suffix in SHAssetMacros.h: {}", path.string());
return {};
}
if (type == SH_SHADER_TYPE::INAVLID_TYPE)
{
SHLOG_ERROR("Invalid filename for shaders, follow suffix in SHAssetMacros.h: {}", path.string());
return {};
}
path.make_preferred();
std::ifstream file{ path.string(), std::ios::in };
std::ifstream file{ path.string(), std::ios::in };
if (file.is_open())
{
std::stringstream stream;
if (file.is_open())
{
std::stringstream stream;
stream << file.rdbuf();
stream << file.rdbuf();
std::string const content = stream.str();
std::string const content = stream.str();
auto data = CompileShaderSourceToMemory(content, path.filename().string(), type);
auto data = CompileShaderSourceToMemory(content, path.filename().string(), type);
if (data == nullptr)
{
return{};
}
if (data == nullptr)
{
return{};
}
return CompileShaderSourceToBinary(path, *data);
}
return CompileShaderSourceToBinary(path, *data);
}
SHLOG_ERROR("Unable to open shader file: {}", path.string());
SHLOG_ERROR("Unable to open shader file: {}", path.string());
return {};
}
return {};
}
std::optional<AssetPath> SHShaderSourceCompiler::CompileShaderFromString
(std::string const& string, AssetPath path, SH_SHADER_TYPE type) noexcept
{
auto const data = CompileShaderSourceToMemory(string, path.filename().string(), type);
std::optional<AssetPath> SHShaderSourceCompiler::CompileShaderFromString
(std::string const& string, AssetPath path, SH_SHADER_TYPE type) noexcept
{
auto const data = CompileShaderSourceToMemory(string, path.filename().string(), type);
if (data == nullptr)
{
return{};
}
if (data == nullptr)
{
return{};
}
return CompileShaderSourceToBinary(path, *data);
}
return CompileShaderSourceToBinary(path, *data);
}
}

View File

@ -13,6 +13,7 @@
#include <cstdint>
#include <string>
#include <filesystem>
#include "Asset Types/SHShaderAsset.h"
// FMOD Fwd Declare
namespace FMOD
@ -103,10 +104,10 @@ constexpr std::string_view VERTEX_SHADER{ "_VS" };
constexpr std::string_view FRAGMENT_SHADER{ "_FS" };
constexpr std::string_view COMPUTER_SHADER{ "_CS" };
constexpr std::string_view SHADER_IDENTIFIERS[] = {
VERTEX_SHADER,
FRAGMENT_SHADER,
COMPUTER_SHADER
constexpr std::pair<std::string_view, SHADE::SH_SHADER_TYPE> SHADER_IDENTIFIERS[] = {
std::make_pair(VERTEX_SHADER, SHADE::SH_SHADER_TYPE::VERTEX),
std::make_pair(FRAGMENT_SHADER, SHADE::SH_SHADER_TYPE::FRAGMENT),
std::make_pair(COMPUTER_SHADER, SHADE::SH_SHADER_TYPE::COMPUTE)
};
constexpr size_t SHADER_TYPE_MAX_COUNT{ 3 };

View File

@ -17,9 +17,37 @@ of DigiPen Institute of Technology is prohibited.
#include "SH_API.h"
#include "SHResourceLibrary.h"
#include "Assets/SHAssetMacros.h"
#include "Assets/Asset Types/SHMeshAsset.h"
#include "Assets/Asset Types/SHTextureAsset.h"
#include "Assets/Asset Types/SHShaderAsset.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
#include "Graphics/MiddleEnd/Textures/SHTextureLibrary.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
namespace SHADE
{
template<typename T = void>
struct SHResourceLoader
{
using AssetType = void;
};
template<>
struct SHResourceLoader<SHMesh>
{
using AssetType = SHMeshAsset;
};
template<>
struct SHResourceLoader<SHTexture>
{
using AssetType = SHTextureAsset;
};
template<>
struct SHResourceLoader<SHVkShaderModule>
{
using AssetType = SHShaderAsset;
};
/// <summary>
/// Static class responsible for loading and caching runtime resources from their
/// serialised Asset IDs.
@ -124,6 +152,14 @@ namespace SHADE
/// <returns>Reference to the AssetHandleMap of the specified type.</returns>
template<typename ResourceType>
static std::pair<AssetHandleMapRef, HandleAssetMapRef> getAssetHandleMap();
/// <summary>
///
/// </summary>
/// <typeparam name="ResourceType"></typeparam>
/// <param name="assetData"></param>
/// <returns></returns>
template<typename ResourceType>
static Handle<ResourceType> load(AssetID assetId, const typename SHResourceLoader<ResourceType>::AssetType& assetData);
};
}

View File

@ -3,7 +3,7 @@
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Oct 21, 2022
\brief Contains the definition of the function templates of the
\brief Contains the definition of the function templates of the
SHResourceManager static class.
Copyright (C) 2022 DigiPen Institute of Technology.
@ -19,6 +19,7 @@ of DigiPen Institute of Technology is prohibited.
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Tools/SHLog.h"
#include "Graphics/Shaders/SHVkShaderModule.h"
namespace SHADE
{
@ -40,67 +41,19 @@ namespace SHADE
return Handle<ResourceType>(typedHandleMap.get()[assetId]);
/* Otherwise, we need to load it! */
// Meshes
if constexpr (std::is_same_v<ResourceType, SHMesh>)
// Load Asset Data
const auto* assetData = SHAssetManager::GetData<SHResourceLoader<ResourceType>::AssetType>(assetId);
if (assetData == nullptr)
{
// Get system
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Load
const SHMeshAsset* assetData = SHAssetManager::GetData<SHMeshAsset>(assetId);
if (assetData == nullptr)
{
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
return {};
}
loadedAssetData.emplace_back(assetId);
Handle<SHMesh> meshHandle = gfxSystem->AddMesh
(
assetData->vertexPosition.size(),
assetData->vertexPosition.data(),
assetData->texCoords.data(),
assetData->vertexTangent.data(),
assetData->vertexNormal.data(),
assetData->indices.size(),
assetData->indices.data()
);
Handle genericHandle = Handle(meshHandle);
typedHandleMap.get().emplace(assetId, genericHandle);
typedAssetIdMap.get().emplace(genericHandle, assetId);
return meshHandle;
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
return {};
}
// Textures
else if constexpr (std::is_same_v<ResourceType, SHTexture>)
{
// Get system
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Load
const SHTextureAsset* assetData = SHAssetManager::GetData<SHTextureAsset>(assetId);
if (assetData == nullptr)
{
SHLog::Warning("[SHResourceManager] Attempted to load an asset with an invalid Asset ID.");
return {};
}
loadedAssetData.emplace_back(assetId);
Handle<SHTexture> texHandle = gfxSystem->AddTexture
(
assetData->numBytes,
assetData->pixelData,
assetData->width,
assetData->height,
assetData->format,
assetData->mipOffsets
);
typedHandleMap.get().emplace(assetId, Handle(texHandle));
return texHandle;
}
auto handle = load<ResourceType>(assetId, *assetData);
Handle genericHandle = Handle();
typedHandleMap.get().emplace(assetId, genericHandle);
typedAssetIdMap.get().emplace(genericHandle, assetId);
return handle;
}
template<typename ResourceType>
@ -152,7 +105,7 @@ namespace SHADE
template<typename ResourceType>
std::pair<SHResourceManager::AssetHandleMapRef, SHResourceManager::HandleAssetMapRef> SHResourceManager::getAssetHandleMap()
{
const std::type_index TYPE = typeid(ResourceType);
const std::type_index TYPE = typeid(ResourceType);
if (!handlesMap.contains(TYPE))
{
@ -160,7 +113,7 @@ namespace SHADE
assetIdMap.emplace(TYPE, HandleAssetMap{});
typedFreeFuncMap.emplace
(
TYPE,
TYPE,
[TYPE](AssetID assetId)
{
static_cast<Handle<ResourceType>>(SHResourceManager::handlesMap[TYPE][assetId]).Free();
@ -169,4 +122,58 @@ namespace SHADE
}
return std::make_pair(std::ref(handlesMap[TYPE]), std::ref(assetIdMap[TYPE]));
}
template<typename ResourceType>
Handle<ResourceType> SHResourceManager::load(AssetID assetId, const typename SHResourceLoader<ResourceType>::AssetType& assetData)
{
// Get system
SHGraphicsSystem* gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
if (gfxSystem == nullptr)
throw std::runtime_error("[SHResourceManager] Attempted to load graphics resource without a SHGraphicsSystem installed.");
// Meshes
if constexpr (std::is_same_v<ResourceType, SHMesh>)
{
loadedAssetData.emplace_back(assetId);
return gfxSystem->AddMesh
(
assetData.vertexPosition.size(),
assetData.vertexPosition.data(),
assetData.texCoords.data(),
assetData.vertexTangent.data(),
assetData.vertexNormal.data(),
assetData.indices.size(),
assetData.indices.data()
);
}
// Textures
else if constexpr (std::is_same_v<ResourceType, SHTexture>)
{
loadedAssetData.emplace_back(assetId);
return gfxSystem->AddTexture
(
assetData.numBytes,
assetData.pixelData,
assetData.width,
assetData.height,
assetData.format,
assetData.mipOffsets
);
}
// Shaders
else if constexpr (std::is_same_v<ResourceType, SHVkShaderModule>)
{
return gfxSystem->GetDevice()->CreateShaderModule
(
assetData.spirvBinary,
"main",
static_cast<vk::ShaderStageFlagBits>(assetData.shaderType),
assetData.name
);
}
// Materials
}
}