kaliber/src/engine/asset/shader_source.cc

117 lines
3.0 KiB
C++
Raw Normal View History

2023-06-25 15:10:34 +00:00
#include "engine/asset/shader_source.h"
2020-04-13 11:24:53 +00:00
#include <cstring>
#include "base/log.h"
#include "engine/engine.h"
#include "engine/platform/asset_file.h"
2020-04-13 11:24:53 +00:00
2020-12-24 23:22:41 +00:00
namespace {
// Helper macros for our glsl shaders. Makes it possible to write generic code
// that compiles both for OpenGL and Vulkan.
const char kVertexShaderMacros[] = R"(
#if defined(VULKAN)
#define UNIFORM_BEGIN layout(push_constant) uniform Params {
#define UNIFORM_V(X) X;
#define UNIFORM_F(X) X;
#define UNIFORM_END } params;
#define IN(X) layout(location = X) in
#define OUT(X) layout(location = X) out
#define PARAM(X) params.X
#else
#define UNIFORM_BEGIN
#define UNIFORM_V(X) uniform X;
#define UNIFORM_F(X)
#define UNIFORM_END
#define IN(X) attribute
#define OUT(X) varying
#define PARAM(X) X
#endif
)";
const char kFragmentShaderMacros[] = R"(
#if defined(VULKAN)
#define UNIFORM_BEGIN layout(push_constant) uniform Params {
#define UNIFORM_V(X) X;
#define UNIFORM_F(X) X;
#define UNIFORM_END } params;
#define SAMPLER(N, X) layout(set = N, binding = 0) uniform X;
2020-12-24 23:22:41 +00:00
#define IN(X) layout(location = X) in
#define OUT(X) layout(location = X) out
#define FRAG_COLOR_OUT(X) layout(location = 0) out vec4 X;
#define FRAG_COLOR(X) X
#define PARAM(X) params.X
#define TEXTURE texture
#else
#define UNIFORM_BEGIN
#define UNIFORM_V(X)
#define UNIFORM_F(X) uniform X;
#define UNIFORM_END
#define SAMPLER(N, X) uniform X;
2020-12-24 23:22:41 +00:00
#define IN(X) varying
#define OUT(X) varying
#define FRAG_COLOR_OUT(X)
#define FRAG_COLOR(X) gl_FragColor
#define PARAM(X) X
#define TEXTURE texture2D
#endif
)";
template <size_t N>
constexpr size_t length(char const (&)[N]) {
return N - 1;
}
constexpr size_t kVertexShaderMacrosLen = length(kVertexShaderMacros);
constexpr size_t kFragmentShaderMacrosLen = length(kFragmentShaderMacros);
} // namespace
2020-04-13 11:24:53 +00:00
namespace eng {
bool ShaderSource::Load(const std::string& name) {
name_ = name;
2020-04-13 11:24:53 +00:00
2020-12-24 23:22:41 +00:00
vertex_source_size_ =
LoadInternal(name + "_vertex", vertex_source_, kVertexShaderMacros,
kVertexShaderMacrosLen);
if (!vertex_source_)
2020-04-13 11:24:53 +00:00
return false;
2020-12-24 23:22:41 +00:00
fragment_source_size_ =
LoadInternal(name + "_fragment", fragment_source_, kFragmentShaderMacros,
kFragmentShaderMacrosLen);
if (!fragment_source_)
2020-04-13 11:24:53 +00:00
return false;
LOG << "Loaded " << name;
2020-04-13 11:24:53 +00:00
return true;
}
2020-12-24 23:22:41 +00:00
size_t ShaderSource::LoadInternal(const std::string& name,
std::unique_ptr<char[]>& dst,
const char* inject,
size_t inject_len) {
size_t size;
auto source = AssetFile::ReadWholeFile(
name.c_str(), Engine::Get().GetRootPath().c_str(), &size, true);
if (!source) {
LOG << "Failed to read file: " << name;
return 0;
}
// Inject macros.
size++; // Include the null-terminator.
size_t total_size = inject_len + size + 1;
dst = std::make_unique<char[]>(total_size);
memcpy(dst.get(), inject, inject_len);
memcpy(dst.get() + inject_len, source.get(), size);
return total_size;
}
2020-04-13 11:24:53 +00:00
} // namespace eng