Implemented ShaderConductor into Shaders

- glShader now uses ShaderConductor and compiles from .hlsl files
- Added Shader::Stage enum
- Removed .glsl files
- Improvements to CMakeLists files
- Maintenance
This commit is contained in:
Light 2021-09-13 12:17:26 +04:30
parent 35663cd3c4
commit eb00566953
19 changed files with 214 additions and 284 deletions

View file

@ -1,24 +1,22 @@
cmake_minimum_required(VERSION 3.21.2)
project(Light VERSION 1.0.0)
add_subdirectory(Dependencies/ShaderConductor)
set(CMAKE_CXX_STANDARD 17)
# target_compile_features(Light PUBLIC cxx_std_17)
# set_property(TARGET Light CXX_STANDARD 17)
add_subdirectory(Dependencies/ShaderConductor) # <-- this project should not use "cxx_standard 17"
# directories
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(MIRROR_DIR ${CMAKE_BINARY_DIR}/../Mirror/)
set(ENGINE_DIR ${CMAKE_BINARY_DIR}/../Engine/)
set(DEPENDENCIES_DIR ${CMAKE_BINARY_DIR}/../Dependencies/)
# MIRROR
# projects
set(CMAKE_CXX_STANDARD 17)
add_compile_definitions(LIGHT_PLATFORM_WINDOWS)
# projects
add_subdirectory(${ENGINE_DIR}/)
add_subdirectory(${MIRROR_DIR}/)
@ -40,4 +38,8 @@ target_link_libraries(Engine ShaderConductor)
target_link_libraries(imgui glad)
target_link_libraries(imgui glfw)
target_link_libraries(Mirror Engine)
target_link_libraries(Mirror Engine)
if(MSVC)
set_property(DIRECTORY ${CMAE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Mirror)
endif()

View file

@ -1,42 +1,40 @@
cmake_minimum_required(VERSION 3.21.2)
message("______________________________________________________________________")
message("Building Engine...")
if (CMAKE_COMPILER_IS_GNUCC)
add_compile_options(-w)
add_compile_options(-w)
endif()
if(MSVC)
add_compile_options(/MP)
add_compile_options(/W0)
add_compile_options(/MP)
add_compile_options(/W0)
endif()
file(GLOB_RECURSE ENGINE_ALL_FILES true ABSOLUTE ${ENGINE_DIR}src/*)
file(GLOB_RECURSE ENGINE_RES_FILES true ABSOLUTE ${ENGINE_DIR}res/*)
list(LENGTH ENGINE_ALL_FILES ENGINE_ALL_FILES_COUNT)
message("Found " ${ENGINE_ALL_FILES_COUNT} " files in Engine")
if(NOT WIN32)
set (DX_DIR ${ENGINE_DIR}src/Platform/GraphicsAPI/DirectX/)
set (WIN_DIR ${ENGINE_DIR}src/Platform/OS/Windows/)
list(REMOVE_ITEM ENGINE_ALL_FILES
${DX_DIR}dxBlender.cpp
${DX_DIR}dxBuffers.cpp
${DX_DIR}dxFramebuffer.cpp
${DX_DIR}dxGraphicsContext.cpp
${DX_DIR}dxRenderCommand.cpp
${DX_DIR}dxShader.cpp
${DX_DIR}dxSharedContext.cpp
${DX_DIR}dxTexture.cpp
${DX_DIR}dxUserInterface.cpp
${DX_DIR}dxVertexLayout.cpp
${WIN_DIR}wWindow.cpp)
${DX_DIR}dxBlender.cpp
${DX_DIR}dxBuffers.cpp
${DX_DIR}dxFramebuffer.cpp
${DX_DIR}dxGraphicsContext.cpp
${DX_DIR}dxRenderCommand.cpp
${DX_DIR}dxShader.cpp
${DX_DIR}dxSharedContext.cpp
${DX_DIR}dxTexture.cpp
${DX_DIR}dxUserInterface.cpp
${DX_DIR}dxVertexLayout.cpp
${WIN_DIR}wWindow.cpp)
else()
file(GLOB_RECURSE HLSL_FILES true ABSOLUTE ${ENGINE_DIR}res/*.hlsl)
set_source_files_properties(${HLSL_FILES} PROPERTIES VS_TOOL_OVERRIDE "None")
endif()
list(LENGTH ENGINE_ALL_FILES ENGINE_ALL_FILES_COUNT)
message(${ENGINE_ALL_FILES_COUNT} " files left in Engine after excludes")
include_directories(
${ENGINE_DIR}src/Engine/
@ -47,8 +45,9 @@ ${DEPENDENCIES_DIR}GLAD/include/
${DEPENDENCIES_DIR}GLFW/include/
${DEPENDENCIES_DIR}glm/
${DEPENDENCIES_DIR}imgui/
${DEPENDENCIES_DIR}spdlog/include
${DEPENDENCIES_DIR}spdlog/include/
${DEPENDENCIES_DIR}stb_image/
${DEPENDENCIES_DIR}ShaderConductor/Include/
)
source_group(TREE ${ENGINE_DIR} FILES ${ENGINE_ALL_FILES} ${ENGINE_RES_FILES})
@ -58,6 +57,4 @@ if(WIN32)
target_link_libraries(Engine d3d11)
target_link_libraries(Engine dxguid)
target_link_libraries(Engine D3DCompiler)
endif()
message("______________________________________________________________________")
endif()

View file

@ -1,10 +0,0 @@
#version 440 core
in vec4 vso_FragmentColor;
out vec4 fso_FragmentColor;
void main()
{
fso_FragmentColor = vso_FragmentColor;
}

View file

@ -1,17 +0,0 @@
#version 440 core
layout(location = 0) in vec4 a_Position;
layout(location = 1) in vec4 a_Color;
layout(std140, binding = 0) uniform ub_ViewProjection
{
mat4 viewProjection;
};
out vec4 vso_FragmentColor;
void main()
{
gl_Position = viewProjection * a_Position;
vso_FragmentColor = a_Color;
}

View file

@ -1,12 +0,0 @@
#version 440 core
in vec2 vso_TexCoord;
uniform sampler2D u_Texture;
out vec4 fso_FragmentColor;
void main()
{
fso_FragmentColor = texture(u_Texture, vso_TexCoord);
}

View file

@ -1,18 +0,0 @@
#version 440 core
layout(location = 0) in vec4 a_Position;
layout(location = 1) in vec2 a_TexCoord;
layout(std140, binding = 0) uniform ub_ViewProjection
{
mat4 u_ViewProjection;
};
out vec2 vso_TexCoord;
void main()
{
gl_Position = u_ViewProjection * a_Position;
vso_TexCoord = a_TexCoord;
}

View file

@ -1,13 +0,0 @@
#version 440 core
in vec4 vso_Tint;
in vec2 vso_TexCoord;
uniform sampler2D u_Texture;
out vec4 fso_FragmentColor;
void main()
{
fso_FragmentColor = texture(u_Texture, vso_TexCoord) * vso_Tint;
}

View file

@ -1,21 +0,0 @@
#version 440 core
layout(location = 0) in vec4 a_Position;
layout(location = 1) in vec4 a_Tint;
layout(location = 2) in vec2 a_TexCoord;
layout(std140, binding = 0) uniform ub_ViewProjection
{
mat4 u_ViewProjection;
};
out vec4 vso_Tint;
out vec2 vso_TexCoord;
void main()
{
gl_Position = u_ViewProjection * a_Position;
vso_Tint = a_Tint;
vso_TexCoord = a_TexCoord;
}

View file

@ -21,7 +21,7 @@ namespace Light {
m_MaxVertices(maxVertices)
{
// #todo: don't use relative path
ResourceManager::LoadShader("LT_ENGINE_RESOURCES_QUAD_SHADER", "../../Engine/res/Shaders/Quad/Quad_VS", "../../Engine//res/Shaders/Quad/Quad_PS");
ResourceManager::LoadShader("LT_ENGINE_RESOURCES_QUAD_SHADER", "../../Engine/res/Shaders/Quad/Quad_VS.hlsl", "../../Engine//res/Shaders/Quad/Quad_PS.hlsl");
m_Shader = ResourceManager::GetShader("LT_ENGINE_RESOURCES_QUAD_SHADER");
m_VertexBuffer = Ref<VertexBuffer>(VertexBuffer::Create(nullptr, sizeof(QuadVertexData), maxVertices, sharedContext));

View file

@ -21,7 +21,7 @@ namespace Light {
m_MaxVertices(maxVertices)
{
// #todo: don't use relative path
ResourceManager::LoadShader("LT_ENGINE_RESOURCES_TEXTURE_SHADER", "../../Engine/res/Shaders/Texture/Texture_VS", "../../Engine/res/Shaders/Texture/Texture_PS");
ResourceManager::LoadShader("LT_ENGINE_RESOURCES_TEXTURE_SHADER", "../../Engine/res/Shaders/Texture/Texture_VS.hlsl", "../../Engine/res/Shaders/Texture/Texture_PS.hlsl");
m_Shader = ResourceManager::GetShader("LT_ENGINE_RESOURCES_TEXTURE_SHADER");
m_VertexBuffer = Ref<VertexBuffer>(VertexBuffer::Create(nullptr, sizeof(TextureVertexData), maxVertices, sharedContext));

View file

@ -21,7 +21,7 @@ namespace Light {
m_MaxVertices(maxVertices)
{
// #todo: don't use relative path
ResourceManager::LoadShader("LT_ENGINE_RESOURCES_TINTED_TEXTURE_SHADER", "../../Engine/res/Shaders/TintedTexture/TintedTexture_VS", "../../Engine/res/Shaders/TintedTexture/TintedTexture_PS");
ResourceManager::LoadShader("LT_ENGINE_RESOURCES_TINTED_TEXTURE_SHADER", "../../Engine/res/Shaders/TintedTexture/TintedTexture_VS.hlsl", "../../Engine/res/Shaders/TintedTexture/TintedTexture_PS.hlsl");
m_Shader = ResourceManager::GetShader("LT_ENGINE_RESOURCES_TINTED_TEXTURE_SHADER");
m_VertexBuffer = Ref<VertexBuffer>(VertexBuffer::Create(nullptr, sizeof(TintedTextureVertexData), maxVertices, sharedContext));

View file

@ -11,16 +11,16 @@
namespace Light {
Ref<Shader> Shader::Create(const std::string& vertexSource, const std::string& pixelSource, Ref<SharedContext> sharedContext)
Ref<Shader> Shader::Create(const std::vector<uint8_t>& vertexBlob, const std::vector<uint8_t>& pixelBlob, const std::string& vertexFileName, const std::string& pixelFileName, Ref<SharedContext> sharedContext)
{
// load shader source
switch (GraphicsContext::GetGraphicsAPI())
{
case GraphicsAPI::OpenGL:
return CreateRef<glShader>(vertexSource, pixelSource);
return CreateRef<glShader>(vertexBlob, pixelBlob, vertexFileName, pixelFileName);
case GraphicsAPI::DirectX: LT_WIN(
return CreateRef<dxShader>(vertexSource, pixelSource, std::static_pointer_cast<dxSharedContext>(sharedContext));)
return CreateRef<dxShader>(vertexBlob, pixelBlob, std::static_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "Shader::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());

View file

@ -11,7 +11,16 @@ namespace Light {
class Shader
{
public:
static Ref<Shader> Create(const std::string& vertexPath, const std::string& pixelPath, Ref<SharedContext> sharedContext);
enum Stage
{
NONE = 0,
VERTEX = 1,
PIXEL = 2,
GEOMETRY = 3
};
public:
static Ref<Shader> Create(const std::vector<uint8_t>& vertexBlob, const std::vector<uint8_t>& pixelBlob, const std::string& vertexFileName, const std::string& pixelFileName, Ref<SharedContext> sharedContext);
virtual ~Shader() = default;

View file

@ -27,52 +27,41 @@ namespace Light {
stbi_set_flip_vertically_on_load(true);
}
void ResourceManager::CreateShaderImpl(const std::string& name, const std::string& vertexSource, const std::string& pixelSource)
{
// delim
std::string delim = GraphicsContext::GetGraphicsAPI() == GraphicsAPI::OpenGL ? "GLSL" :
GraphicsContext::GetGraphicsAPI() == GraphicsAPI::DirectX ? "HLSL" : "";
// check
LT_ENGINE_ASSERT(!vertexSource.empty(), "ResourceManager::CreateShaderImpl: 'vertexSource' is empty");
LT_ENGINE_ASSERT(!vertexSource.empty(), "ResourceManager::CreateShaderImpl: 'pixelSource' is empty");
LT_ENGINE_ASSERT(!delim.empty(), "ResourceManager::CreateShaderImpl: invalid/unsupported 'GraphicsAPI': {}", GraphicsContext::GetGraphicsAPI());
// save to string
std::string vsSource = vertexSource;
std::string psSource = pixelSource;
// extract shader source
ResourceManager::ExtractShaderSource(vsSource, delim);
ResourceManager::ExtractShaderSource(psSource, delim);
// create shader
m_Shaders[name] = Ref<Shader>(Shader::Create(vsSource, psSource, m_SharedGraphicsContext));
}
void ResourceManager::LoadShaderImpl(const std::string& name, const std::string& vertexPath, const std::string& pixelPath)
{
// check
LT_ENGINE_ASSERT(!vertexPath.empty(), "ResourceManager::LoadShaderImpl: 'vertexPath' is empty");
LT_ENGINE_ASSERT(!pixelPath.empty(), "ResourceManager::LoadShaderImpl: 'pixelPath' is empty");
std::vector<uint8_t> vertexFile, pixelFile;
std::string vPath = vertexPath + (GraphicsContext::GetGraphicsAPI() == GraphicsAPI::OpenGL ? ".glsl" : ".hlsl");
std::string pPath = pixelPath + (GraphicsContext::GetGraphicsAPI() == GraphicsAPI::OpenGL ? ".glsl" : ".hlsl");
std::ifstream file;
std::ios_base::openmode mode = std::ios_base::in;
// read vertex shader file
file.open(vertexPath.c_str(), mode);
LT_ENGINE_ASSERT(file, "ResourceManager::LoadShaderImpl: failed to load vertex shader at path: {}", vertexPath);
if (file)
{
file.seekg(0, std::ios::end);
vertexFile.resize(static_cast<size_t>(file.tellg()));
file.seekg(0, std::ios::beg);
file.read(reinterpret_cast<char*>(vertexFile.data()), vertexFile.size());
vertexFile.resize(static_cast<size_t>(file.gcount()));
file.close();
}
// initialize
std::ifstream vsStream(vPath), psStream(pPath);
std::stringstream vsSS, psSS; // pss pss pss pss :D
std::string line;
// read
while (std::getline(vsStream, line))
vsSS << line << '\n';
while (std::getline(psStream, line))
psSS << line << '\n';
// read pixel shader file
file.open(pixelPath.c_str(), mode);
LT_ENGINE_ASSERT(file, "ResourceManager::LoadShaderImpl: failed to load vertex shader at path: {}", vertexPath);
if (file)
{
file.seekg(0, std::ios::end);
pixelFile.resize(static_cast<size_t>(file.tellg()));
file.seekg(0, std::ios::beg);
file.read(reinterpret_cast<char*>(pixelFile.data()), pixelFile.size());
pixelFile.resize(static_cast<size_t>(file.gcount()));
file.close();
}
// create shader
m_Shaders[name] = Ref<Shader>(Shader::Create(vsSS.str(), psSS.str(), m_SharedGraphicsContext));
m_Shaders[name] = Ref<Shader>(Shader::Create(vertexFile, pixelFile, vertexPath, pixelPath, m_SharedGraphicsContext));
}
void ResourceManager::LoadTextureImpl(const std::string& name, const std::string& path, unsigned int desiredComponents /* = 4u */)
@ -104,26 +93,4 @@ namespace Light {
m_Textures[name] = nullptr;
}
void ResourceManager::ExtractShaderSource(std::string& src, const std::string& delim)
{
size_t begDelimPos, endDelimPos;
// find begin and end delimiter (eg. +GLSL ... -GLSL )
begDelimPos = src.find('+' + delim) + 5;
endDelimPos = src.find('-' + delim);
// check
LT_ENGINE_ASSERT(begDelimPos != std::string::npos + 5,
"Shader::ExtractShaderSource: failed to find the start delimeter in shader source, delim: {}, shader:\n{}",
delim, src);
LT_ENGINE_ASSERT(endDelimPos != std::string::npos,
"Shader::ExtractShaderSource: failed to find the end delimeter in shader source, delim: {}, shader:\n{}",
delim, src);
// extract the shader
src = src.substr(begDelimPos, endDelimPos - begDelimPos);
}
}

View file

@ -24,7 +24,6 @@ namespace Light {
static Scope<ResourceManager> Create(Ref<SharedContext> sharedContext);
// #todo: add geometry shader support
static inline void CreateShader(const std::string& name, const std::string& vertexSource, const std::string& pixelSource) { s_Context->CreateShaderImpl(name, vertexSource, pixelSource); }
static inline void LoadShader(const std::string& name, const std::string& vertexPath, const std::string& pixelPath) { s_Context->LoadShaderImpl(name, vertexPath, pixelPath); }
static inline void LoadTexture(const std::string& name, const std::string& path, unsigned int desiredComponents = 4u) { s_Context->LoadTextureImpl(name, path, desiredComponents); }
@ -37,15 +36,11 @@ namespace Light {
private:
ResourceManager(Ref<SharedContext> sharedContext);
void CreateShaderImpl(const std::string& name, const std::string& vertexSource, const std::string& pixelSource);
void LoadShaderImpl(const std::string& name, const std::string& vertexPath, const std::string& pixelPath);
void LoadTextureImpl(const std::string& name, const std::string& path, unsigned int desiredComponents = 4u);
void ReleaseTextureImpl(const std::string& name);
private:
void ExtractShaderSource(std::string& src, const std::string& delim);
};
}

View file

@ -6,7 +6,7 @@
namespace Light {
dxShader::dxShader(const std::string& vertexSource, const std::string& pixelSource, Ref<dxSharedContext> sharedContext)
dxShader::dxShader(const std::vector<uint8_t>& vertexBlob, const std::vector<uint8_t> pixelBlob, Ref<dxSharedContext> sharedContext)
: m_Context(sharedContext),
m_VertexShader(nullptr),
m_PixelShader(nullptr),
@ -14,9 +14,9 @@ namespace Light {
{
Microsoft::WRL::ComPtr<ID3DBlob> ps = nullptr, vsErr = nullptr, psErr = nullptr;
// compile shaders (we don't use DXC here because if D3DCompile fails it throws a dxException without logging the vsErr/psErr)
D3DCompile(vertexSource.c_str(), vertexSource.length(), NULL, nullptr, nullptr, "main", "vs_4_0", NULL, NULL, &m_VertexBlob, &vsErr);
D3DCompile(pixelSource.c_str(), pixelSource.length(), NULL, nullptr, nullptr, "main", "ps_4_0", NULL, NULL, &ps, &psErr);
// compile shaders (we don't use DXC here because if D3DCompile fails it throws a dxException without logging the vsErr/psErr
D3DCompile(vertexBlob.data(), vertexBlob.size(), NULL, nullptr, nullptr, "main", "vs_4_0", NULL, NULL, &m_VertexBlob, &vsErr);
D3DCompile(pixelBlob.data(), pixelBlob.size(), NULL, nullptr, nullptr, "main", "ps_4_0", NULL, NULL, &ps, &psErr);
// check
LT_ENGINE_ASSERT(!vsErr.Get(), "dxShader::dxShader: vertex shader compile error: {}", (char*)vsErr->GetBufferPointer());

View file

@ -22,7 +22,7 @@ namespace Light {
Microsoft::WRL::ComPtr<ID3DBlob> m_VertexBlob;
public:
dxShader(const std::string& vertexSource, const std::string& pixelSource, Ref<dxSharedContext> sharedContext);
dxShader(const std::vector<uint8_t>& vertexBlob, const std::vector<uint8_t> pixelBlob, Ref<dxSharedContext> sharedContext);
~dxShader();
void Bind() override;

View file

@ -7,104 +7,43 @@
#include <glm/matrix.hpp>
#include <glm/gtc/matrix_transform.hpp>
namespace Light {
glShader::glShader(const std::string& vertexSource, const std::string& fragmentSource)
glShader::glShader(const std::vector<uint8_t>& vertexBlob, const std::vector<uint8_t>& pixelBlob, const std::string& vertexFileName, const std::string& pixelFileName)
: m_ShaderID(NULL)
{
// create
m_ShaderID = glCreateProgram();
// create shaders
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
// compile hlsl to glsl
ShaderConductor::Compiler::ResultDesc vertexResult = CompileHLSL(vertexBlob, vertexFileName, Shader::Stage::VERTEX);
ShaderConductor::Compiler::ResultDesc pixelResult = CompileHLSL(pixelBlob, pixelFileName, Shader::Stage::PIXEL);
// &(address of) needs an lvalue
const char* lVertexSource = vertexSource.c_str();
const char* lFragmentSource = fragmentSource.c_str();
LT_ENGINE_ASSERT(!vertexResult.hasError, "glShader::glShader: failed to compile hlsl vertex shader: {}", vertexFileName);
LT_ENGINE_ASSERT(!pixelResult.hasError, "glShader::glShader: failed to compile hlsl pixel shader: {}", pixelFileName);
// set shaders' source code
glShaderSource(vertexShader, 1, &lVertexSource, NULL);
glShaderSource(fragmentShader, 1, &lFragmentSource, NULL);
// extract glsl source
std::string vertexSource = std::string(reinterpret_cast<const char*>(vertexResult.target.Data()));
vertexSource.resize(vertexResult.target.Size());
// compile shaders
glCompileShader(vertexShader);
glCompileShader(fragmentShader);
/* #TEMP_HANDLE_SHADER_COMPILE_FAILURE# */
int isCompiled = 0;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
int logLength = 0;
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength);
char* errorLog = (char*)alloca(logLength);
glGetShaderInfoLog(vertexShader, logLength, &logLength, &errorLog[0]);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
LT_ENGINE_ASSERT(false, "glShader::glShader: failed to compile vertex shader:\n {}", errorLog);
return;
}
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
int logLength = 0;
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &logLength);
char* errorLog = (char*)alloca(logLength);
glGetShaderInfoLog(fragmentShader, logLength, &logLength, &errorLog[0]);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
LT_ENGINE_ASSERT(false, "glShader::glShader: failed to compile fragment shader:\n {}", errorLog);
return;
}
/* #TEMP_HANDLE_SHADER_COMPILE_FAILURE# */
#ifdef LIGHT_OPENGL_ENABLE_SHADER_INFO_LOG
{
int logLength = 0;
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength);
if(logLength)
{
char* infoLog = (char*)alloca(logLength);
glGetShaderInfoLog(vertexShader, logLength, &logLength, &infoLog[0]);
LT_ENGINE_TRACE(infoLog);
}
}
{
int logLength = 0;
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength)
{
char* infoLog = (char*)alloca(logLength);
glGetShaderInfoLog(fragmentShader, logLength, &logLength, &infoLog[0]);
LT_ENGINE_TRACE(infoLog);
}
}
#endif
std::string pixelSource = std::string(reinterpret_cast<const char*>(pixelResult.target.Data()));
pixelSource.resize(pixelResult.target.Size());
// compile glsl
unsigned int vertexShader = CompileShader(vertexSource, Shader::Stage::VERTEX);
unsigned int pixelShader = CompileShader(pixelSource, Shader::Stage::PIXEL);
// attach shaders
glAttachShader(m_ShaderID, vertexShader);
glAttachShader(m_ShaderID, fragmentShader);
glAttachShader(m_ShaderID, pixelShader);
// link shader program
glLinkProgram(m_ShaderID);
// delete shaders (free memory)
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(pixelShader);
}
glShader::~glShader()
@ -122,4 +61,109 @@ namespace Light {
glUseProgram(NULL);
}
ShaderConductor::Compiler::ResultDesc glShader::CompileHLSL(std::vector<uint8_t> blob, std::string fileName, Shader::Stage stage)
{
// check
LT_ENGINE_ASSERT(!blob.empty(), "glShader::CompileHLSL: 'blob' is empty");
LT_ENGINE_ASSERT(!fileName.empty(), "glShader::CompileHLSL: 'fileName' is empty");
LT_ENGINE_ASSERT(stage, "glShader::CompileHLSL: 'stage' is invalid: None");
// compiler options
ShaderConductor::Compiler::Options options = {};
options.packMatricesInRowMajor = true;
options.enableDebugInfo = true;
options.disableOptimizations = true;
options.inheritCombinedSamplerBindings = true;
options.shaderModel = { 4, 5 };
// compiler target descriptor
ShaderConductor::Compiler::TargetDesc targetDesc = {};
targetDesc.language = ShaderConductor::ShadingLanguage::Glsl;
targetDesc.version = "440 core";
targetDesc.asModule = false;
// compiler source descriptor
ShaderConductor::Compiler::SourceDesc sourceDesc = {};
std::string source = std::string(reinterpret_cast<char*>(blob.data()), blob.size());
sourceDesc.source = source.c_str();
sourceDesc.fileName = fileName.c_str();
sourceDesc.entryPoint = "main";
sourceDesc.stage = stage == Shader::Stage::VERTEX ? ShaderConductor::ShaderStage::VertexShader :
stage == Shader::Stage::PIXEL ? ShaderConductor::ShaderStage::PixelShader :
ShaderConductor::ShaderStage::GeometryShader;
sourceDesc.defines = nullptr;
sourceDesc.numDefines = 0u;
sourceDesc.loadIncludeCallback = nullptr;
// compilation result
ShaderConductor::Compiler::ResultDesc result = ShaderConductor::Compiler::Compile(sourceDesc, options, targetDesc);
// log info
LT_ENGINE_INFO("_______________________________________");
LT_ENGINE_INFO("Compiled with ShaderConductor:");
LT_ENGINE_INFO(" hasError: {}", result.hasError);
LT_ENGINE_INFO(" isText: {}", result.isText);
if (result.errorWarningMsg.Size() != 0u)
{
const char* errorStr = reinterpret_cast<const char*>(result.errorWarningMsg.Data());
LT_ENGINE_ERROR(" errorWarningMsg: \n{}", errorStr);
}
if (result.target.Size() != 0u)
{
const char* targetStr = reinterpret_cast<const char*>(result.target.Data());
LT_ENGINE_INFO(" target: \n{}", targetStr);
}
LT_ENGINE_INFO("_______________________________________");
return result;
}
unsigned int glShader::CompileShader(const std::string& source, Shader::Stage stage)
{
// &(address of) needs an lvalue
const char* lvalue_source = reinterpret_cast<const char*>(source.c_str());
unsigned int shader = glCreateShader(stage == Shader::Stage::VERTEX ? GL_VERTEX_SHADER :
stage == Shader::Stage::PIXEL ? GL_FRAGMENT_SHADER :
stage == Shader::Stage::GEOMETRY ? GL_GEOMETRY_SHADER :
NULL);
// compile
glShaderSource(shader, 1, &lvalue_source, NULL);
glCompileShader(shader);
// check
int isCompiled = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
int logLength = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
char* errorLog = (char*)alloca(logLength);
glGetShaderInfoLog(shader, logLength, &logLength, &errorLog[0]);
LT_ENGINE_ASSERT(false, "glShader::glShader: failed to compile vertex shader:\n {}", errorLog);
return NULL;
}
#ifdef LIGHT_OPENGL_ENABLE_SHADER_INFO_LOG
// info log
{
int logLength = 0;
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength);
if (logLength)
{
char* infoLog = (char*)alloca(logLength);
glGetShaderInfoLog(vertexShader, logLength, &logLength, &infoLog[0]);
LT_ENGINE_TRACE(infoLog);
}
}
#endif
return shader;
}
}

View file

@ -4,6 +4,8 @@
#include "Base/Base.h"
#include <ShaderConductor/ShaderConductor.hpp>
namespace Light {
class glShader : public Shader
@ -12,11 +14,16 @@ namespace Light {
unsigned int m_ShaderID;
public:
glShader(const std::string& vetexSource, const std::string& fragmentSource);
glShader(const std::vector<uint8_t>& vertexBlob, const std::vector<uint8_t>& pixelBlob, const std::string& vertexFileName, const std::string& pixelFileName);
~glShader();
void Bind() override;
void UnBind() override;
private:
ShaderConductor::Compiler::ResultDesc CompileHLSL(std::vector<uint8_t> blob, std::string fileName, Shader::Stage stage);
unsigned int CompileShader(const std::string& source, Shader::Stage stage);
};
}