shaders are at a good state. starting work on the graphics pipeline.
This commit is contained in:
parent
6fe98cdb5b
commit
4e8f3292bd
|
|
@ -14,6 +14,7 @@ find_package(spirv_cross_hlsl CONFIG REQUIRED)
|
||||||
find_package(spirv_cross_msl CONFIG REQUIRED)
|
find_package(spirv_cross_msl CONFIG REQUIRED)
|
||||||
find_package(spirv_cross_reflect CONFIG REQUIRED)
|
find_package(spirv_cross_reflect CONFIG REQUIRED)
|
||||||
find_package(spirv_cross_util CONFIG REQUIRED)
|
find_package(spirv_cross_util CONFIG REQUIRED)
|
||||||
|
find_package(unofficial-shaderc CONFIG REQUIRED)
|
||||||
|
|
||||||
foreach (file ${sourceFiles})
|
foreach (file ${sourceFiles})
|
||||||
message("Source File Found ${file}")
|
message("Source File Found ${file}")
|
||||||
|
|
@ -26,4 +27,5 @@ target_include_directories(Dyn PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/inc")
|
||||||
target_link_libraries(Dyn PRIVATE Vulkan::Vulkan)
|
target_link_libraries(Dyn PRIVATE Vulkan::Vulkan)
|
||||||
target_link_libraries(Dyn PRIVATE glfw)
|
target_link_libraries(Dyn PRIVATE glfw)
|
||||||
target_link_libraries(Dyn PRIVATE Vulkan::SafeStruct Vulkan::LayerSettings Vulkan::UtilityHeaders Vulkan::CompilerConfiguration)
|
target_link_libraries(Dyn PRIVATE Vulkan::SafeStruct Vulkan::LayerSettings Vulkan::UtilityHeaders Vulkan::CompilerConfiguration)
|
||||||
target_link_libraries(Dyn PRIVATE spirv-cross-core spirv-cross-glsl spirv-cross-hlsl spirv-cross-msl spirv-cross-reflect spirv-cross-util)
|
target_link_libraries(Dyn PRIVATE spirv-cross-core spirv-cross-glsl spirv-cross-hlsl spirv-cross-msl spirv-cross-reflect spirv-cross-util)
|
||||||
|
target_link_libraries(Dyn PRIVATE unofficial::shaderc::shaderc)
|
||||||
|
|
@ -20,6 +20,19 @@ namespace dyn {
|
||||||
return std::make_shared<T>(std::forward<Args>(args)...);
|
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
using scoped = std::unique_ptr<T>;
|
||||||
|
|
||||||
|
template <typename To, typename From>
|
||||||
|
scoped<To> scoped_as(scoped<From> from) {
|
||||||
|
return std::unique_ptr<To>(static_cast<To*>(from.release()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename ...Args>
|
||||||
|
scoped<T> create_scoped(Args&&... args) {
|
||||||
|
return std::make_unique<T>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
namespace core {
|
namespace core {
|
||||||
enum class RenderPlatform {
|
enum class RenderPlatform {
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,14 @@ namespace dyn::core {
|
||||||
class file {
|
class file {
|
||||||
public:
|
public:
|
||||||
file(const std::string& path);
|
file(const std::string& path);
|
||||||
|
file(const std::filesystem::path& path);
|
||||||
~file() = default;
|
~file() = default;
|
||||||
|
|
||||||
[[nodiscard]] std::string text() const { return _contents; }
|
[[nodiscard]] std::string text() const { return _contents; }
|
||||||
[[nodiscard]] std::vector<uint8_t> bytes() const { return std::vector<uint8_t>(_contents.begin(), _contents.end()); }
|
[[nodiscard]] std::vector<uint8_t> bytes() const { return std::vector<uint8_t>(_contents.begin(), _contents.end()); }
|
||||||
|
[[nodiscard]] size_t size() const { return _contents.size(); }
|
||||||
|
[[nodiscard]] bool empty() const { return _contents.empty(); }
|
||||||
|
[[nodiscard]] std::string path() const { return _file_path; }
|
||||||
|
|
||||||
[[nodiscard]] static bool exists(const std::string& path);
|
[[nodiscard]] static bool exists(const std::string& path);
|
||||||
|
|
||||||
|
|
|
||||||
43
inc/dyn/platform/vulkan/vulkan_graphics_pipeline.h
Normal file
43
inc/dyn/platform/vulkan/vulkan_graphics_pipeline.h
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 6/1/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dyn/renderer/graphics_pipeline.h"
|
||||||
|
|
||||||
|
namespace dyn::core {
|
||||||
|
inline static std::vector<VkDynamicState> g_vulkan_dynamic_states = {
|
||||||
|
VK_DYNAMIC_STATE_VIEWPORT,
|
||||||
|
VK_DYNAMIC_STATE_SCISSOR,
|
||||||
|
};
|
||||||
|
|
||||||
|
class vulkan_graphics_pipeline : public graphics_pipeline {
|
||||||
|
public:
|
||||||
|
vulkan_graphics_pipeline();
|
||||||
|
~vulkan_graphics_pipeline();
|
||||||
|
|
||||||
|
void set_polygon_mode(PolygonMode mode) override;
|
||||||
|
void set_line_width(float line_width) override;
|
||||||
|
void set_msaa_samples(MSAASamples samples) override;
|
||||||
|
void set_cull_mode(CullMode mode, FrontFace face) override;
|
||||||
|
void set_depth_bias_enabled(bool enable) override;
|
||||||
|
void set_depth_bias_options(float constant, float clamp, float slope) override;
|
||||||
|
|
||||||
|
void attach_shader(const ref<shader> &shader) override;
|
||||||
|
|
||||||
|
void build(const ref<render_context> &ctx) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VkPipelineDynamicStateCreateInfo _dynamic_state_ci{};
|
||||||
|
VkPipelineVertexInputStateCreateInfo _vertex_input_ci{};
|
||||||
|
VkPipelineInputAssemblyStateCreateInfo _input_assembly_ci{};
|
||||||
|
VkViewport _viewport{};
|
||||||
|
VkRect2D _scissor{};
|
||||||
|
VkPipelineViewportStateCreateInfo _viewport_state_ci{};
|
||||||
|
VkPipelineRasterizationStateCreateInfo _rasterization_state_ci{};
|
||||||
|
VkPipelineMultisampleStateCreateInfo _multisample_state_ci{};
|
||||||
|
VkPipelineColorBlendStateCreateInfo _color_blend_state_ci{};
|
||||||
|
|
||||||
|
VkPipeline _pipleine = VK_NULL_HANDLE;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -14,18 +14,25 @@ namespace dyn::core {
|
||||||
class vulkan_shader : public shader {
|
class vulkan_shader : public shader {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
vulkan_shader(const std::string& source, const std::string& filename, shader_type type, const ref<vulkan_context>& ctx);
|
vulkan_shader(const std::vector<uint32_t>& source, const std::string& filename, ShaderType type);
|
||||||
~vulkan_shader();
|
~vulkan_shader();
|
||||||
|
|
||||||
|
[[nodiscard]] static VkShaderStageFlagBits vulkan_stage_from_type(ShaderType type);
|
||||||
|
|
||||||
[[nodiscard]] VkShaderModule get_handle() const { return _shader; }
|
[[nodiscard]] VkShaderModule get_handle() const { return _shader; }
|
||||||
[[nodiscard]] VkPipelineShaderStageCreateInfo get_stage_info() const { return _pipeline_ci; }
|
[[nodiscard]] VkPipelineShaderStageCreateInfo get_stage_info() const { return _pipeline_ci; }
|
||||||
|
|
||||||
[[nodiscard]] bool is_usable() const override { return _usable; }
|
[[nodiscard]] bool is_usable() const override { return _usable; }
|
||||||
|
|
||||||
|
void build(const ref<render_context> &context) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<uint32_t> _binary;
|
std::vector<uint32_t> _binary;
|
||||||
ref<vulkan_context> _ctx;
|
ref<vulkan_context> _ctx = nullptr;
|
||||||
bool _usable = false;
|
bool _usable = false;
|
||||||
|
std::string _filename;
|
||||||
|
ShaderType _type;
|
||||||
|
VkShaderStageFlagBits _stage;
|
||||||
VkShaderModule _shader = VK_NULL_HANDLE;
|
VkShaderModule _shader = VK_NULL_HANDLE;
|
||||||
VkPipelineShaderStageCreateInfo _pipeline_ci = {};
|
VkPipelineShaderStageCreateInfo _pipeline_ci = {};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ namespace dyn::core {
|
||||||
void prepare() override {}
|
void prepare() override {}
|
||||||
void present() override {}
|
void present() override {}
|
||||||
|
|
||||||
void resize(uint32_t width, uint32_t height) override {}
|
void resize(uint32_t _width, uint32_t _height) override {}
|
||||||
|
|
||||||
[[nodiscard]] VkCommandBuffer current_cmd_buffer() const { return _command_buffers[_current_frame]; }
|
[[nodiscard]] VkCommandBuffer current_cmd_buffer() const { return _command_buffers[_current_frame]; }
|
||||||
|
|
||||||
|
|
|
||||||
50
inc/dyn/renderer/graphics_pipeline.h
Normal file
50
inc/dyn/renderer/graphics_pipeline.h
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 6/1/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <vulkan/vulkan_core.h>
|
||||||
|
|
||||||
|
#include <dyn/renderer/shader.h>
|
||||||
|
|
||||||
|
namespace dyn::core {
|
||||||
|
enum class PolygonMode {
|
||||||
|
FILL,
|
||||||
|
LINE,
|
||||||
|
POINT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class MSAASamples {
|
||||||
|
SAMPLES_1,
|
||||||
|
SAMPLES_2,
|
||||||
|
SAMPLES_4,
|
||||||
|
SAMPLES_8,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class CullMode {
|
||||||
|
FRONT,
|
||||||
|
BACK,
|
||||||
|
FRONT_AND_BACK,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class FrontFace {
|
||||||
|
CLOCKWISE,
|
||||||
|
COUNTERCLOCKWISE,
|
||||||
|
};
|
||||||
|
|
||||||
|
class graphics_pipeline {
|
||||||
|
public:
|
||||||
|
virtual ~graphics_pipeline() = default;
|
||||||
|
|
||||||
|
virtual void set_polygon_mode(PolygonMode mode) = 0;
|
||||||
|
virtual void set_line_width(float line_width = 1.0f) = 0;
|
||||||
|
virtual void set_msaa_samples(MSAASamples samples) = 0;
|
||||||
|
virtual void set_cull_mode(CullMode mode, FrontFace face) = 0;
|
||||||
|
virtual void set_depth_bias_enabled(bool enable) = 0;
|
||||||
|
virtual void set_depth_bias_options(float constant, float clamp, float slope) = 0;
|
||||||
|
|
||||||
|
virtual void attach_shader(const ref<shader>& shader) = 0;
|
||||||
|
|
||||||
|
virtual void build(const ref<render_context>& ctx) = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -6,30 +6,53 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#ifndef DYN_SHADER_INCLUDE_PATH
|
||||||
|
#define DYN_SHADER_INCLUDE_PATH "resources/shaders/"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "dyn/core/base.h"
|
#include "dyn/core/base.h"
|
||||||
|
#include "dyn/core/debug.h"
|
||||||
|
#include "dyn/core/file.h"
|
||||||
#include <shaderc/shaderc.hpp>
|
#include <shaderc/shaderc.hpp>
|
||||||
|
|
||||||
namespace dyn::core {
|
namespace dyn::core {
|
||||||
class render_context;
|
class render_context;
|
||||||
|
|
||||||
|
class shader_includer : public shaderc::CompileOptions::IncluderInterface {
|
||||||
|
public:
|
||||||
|
struct inclusion_data {
|
||||||
|
std::string path;
|
||||||
|
std::string contents;
|
||||||
|
};
|
||||||
|
explicit shader_includer(const std::string& base) : _base(base) {}
|
||||||
|
shaderc_include_result* GetInclude(const char *requested_source, shaderc_include_type type,
|
||||||
|
const char *requesting_source, size_t include_depth) override;
|
||||||
|
|
||||||
|
void ReleaseInclude(shaderc_include_result *data) override;
|
||||||
|
private:
|
||||||
|
std::filesystem::path _base;
|
||||||
|
};
|
||||||
|
|
||||||
class shader {
|
class shader {
|
||||||
public:
|
public:
|
||||||
enum shader_type {
|
virtual ~shader() = default;
|
||||||
SHADER_VERTEX,
|
|
||||||
SHADER_FRAGMENT,
|
enum ShaderType {
|
||||||
SHADER_GEOMETRY,
|
VERTEX,
|
||||||
SHADER_COMPUTE
|
FRAGMENT,
|
||||||
|
GEOMETRY,
|
||||||
|
COMPUTE
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] shaderc_shader_kind convert_shader_type(shader_type type) const noexcept {
|
[[nodiscard]] static shaderc_shader_kind convert_shader_type(ShaderType type) noexcept {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case SHADER_VERTEX:
|
case VERTEX:
|
||||||
return shaderc_vertex_shader;
|
return shaderc_vertex_shader;
|
||||||
case SHADER_FRAGMENT:
|
case FRAGMENT:
|
||||||
return shaderc_fragment_shader;
|
return shaderc_fragment_shader;
|
||||||
case SHADER_GEOMETRY:
|
case GEOMETRY:
|
||||||
return shaderc_geometry_shader;
|
return shaderc_geometry_shader;
|
||||||
case SHADER_COMPUTE:
|
case COMPUTE:
|
||||||
return shaderc_compute_shader;
|
return shaderc_compute_shader;
|
||||||
}
|
}
|
||||||
return shaderc_vertex_shader;
|
return shaderc_vertex_shader;
|
||||||
|
|
@ -37,7 +60,11 @@ namespace dyn::core {
|
||||||
|
|
||||||
[[nodiscard]] virtual bool is_usable() const = 0;
|
[[nodiscard]] virtual bool is_usable() const = 0;
|
||||||
|
|
||||||
static ref<shader> create_from_string(const std::string& code, shader_type type, const ref<render_context>& context);
|
virtual void build(const ref<render_context>& context) = 0;
|
||||||
static ref<shader> create_from_file(const std::string& filename, shader_type type, const ref<render_context>& context);
|
|
||||||
|
static ref<shader> create_from_string(const std::string& code, ShaderType type, const std::string& filename = "inline-source");
|
||||||
|
static ref<shader> create_from_file(const std::string& filename, ShaderType type);
|
||||||
|
|
||||||
|
static std::vector<uint32_t> compile_hlsl(const std::string& code, ShaderType type, const std::string& filename, std::string include_path);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
9
resources/shaders/basic.vert.glsl
Normal file
9
resources/shaders/basic.vert.glsl
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
#version 450
|
||||||
|
#extension GL_GOOGLE_include_directive : require
|
||||||
|
#include "test.glsl"
|
||||||
|
|
||||||
|
layout(location = 0) out vec3 fragColor;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(1.0, 1.0, 0.0, 1.0);
|
||||||
|
}
|
||||||
3
resources/shaders/test.glsl
Normal file
3
resources/shaders/test.glsl
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
float add(float a, float b) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
@ -7,7 +7,12 @@
|
||||||
|
|
||||||
namespace dyn::core {
|
namespace dyn::core {
|
||||||
file::file(const std::string &path) : _file(path, std::ios::in | std::ios::binary | std::ios::out), _file_path(path) {
|
file::file(const std::string &path) : _file(path, std::ios::in | std::ios::binary | std::ios::out), _file_path(path) {
|
||||||
_file >> _contents;
|
std::stringstream ss;
|
||||||
|
ss << _file.rdbuf();
|
||||||
|
_contents = ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
file::file(const std::filesystem::path &path) : file(path.string()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void file::write(const std::string &text) {
|
void file::write(const std::string &text) {
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,14 @@ namespace dyn::core {
|
||||||
static_cast<int>(spec.height),
|
static_cast<int>(spec.height),
|
||||||
spec.title.c_str(),
|
spec.title.c_str(),
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
|
|
||||||
|
auto monitor = glfwGetPrimaryMonitor();
|
||||||
|
auto vidMode = glfwGetVideoMode(monitor);
|
||||||
|
|
||||||
|
auto x = (vidMode->width/2) - spec.width/2;
|
||||||
|
auto y = (vidMode->height/2) - spec.height/2;
|
||||||
|
glfwSetWindowPos(_window, x, y);
|
||||||
|
|
||||||
DYN_ASSERT(_window != nullptr, "Failed to create GLFW window");
|
DYN_ASSERT(_window != nullptr, "Failed to create GLFW window");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
17
src/main.cpp
17
src/main.cpp
|
|
@ -1,23 +1,13 @@
|
||||||
#include <functional>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <dyn/core/logging.h>
|
|
||||||
#include <dyn/core/command_queue.h>
|
|
||||||
|
|
||||||
#include "../inc/dyn/core/debug.h"
|
|
||||||
#include "dyn/core/window.h"
|
#include "dyn/core/window.h"
|
||||||
#include "dyn/platform/vulkan/vulkan.h"
|
|
||||||
#include "dyn/platform/vulkan/vulkan_context.h"
|
#include "dyn/platform/vulkan/vulkan_context.h"
|
||||||
#include "dyn/renderer/render_context.h"
|
#include "dyn/renderer/render_context.h"
|
||||||
|
#include "dyn/renderer/shader.h"
|
||||||
|
|
||||||
using namespace dyn;
|
using namespace dyn;
|
||||||
using namespace dyn::core;
|
using namespace dyn::core;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
render_context::set_api(RenderPlatform::Vulkan);
|
render_context::set_api(RenderPlatform::Vulkan);
|
||||||
// ref<render_context> ctx = render_context::create();
|
|
||||||
//
|
|
||||||
// ctx->init();
|
|
||||||
|
|
||||||
ref<window> win = window::create({
|
ref<window> win = window::create({
|
||||||
.width = 1280,
|
.width = 1280,
|
||||||
|
|
@ -29,4 +19,9 @@ int main() {
|
||||||
ref<render_context> ctx = render_context::create(win);
|
ref<render_context> ctx = render_context::create(win);
|
||||||
ctx->init();
|
ctx->init();
|
||||||
|
|
||||||
|
|
||||||
|
ref<shader> test_shader = shader::create_from_file("resources/shaders/basic.vert.glsl", shader::VERTEX);
|
||||||
|
if (test_shader != nullptr) {
|
||||||
|
test_shader->build(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
43
src/platform/vulkan/vulkan_graphics_pipeline.cpp
Normal file
43
src/platform/vulkan/vulkan_graphics_pipeline.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 6/1/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <dyn/platform/vulkan/vulkan_graphics_pipeline.h>
|
||||||
|
|
||||||
|
namespace dyn::core {
|
||||||
|
vulkan_graphics_pipeline::vulkan_graphics_pipeline() {
|
||||||
|
_dynamic_state_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||||
|
_dynamic_state_ci.dynamicStateCount = static_cast<uint32_t>(g_vulkan_dynamic_states.size());
|
||||||
|
_dynamic_state_ci.pDynamicStates = g_vulkan_dynamic_states.data();
|
||||||
|
|
||||||
|
_vertex_input_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||||
|
_vertex_input_ci.vertexBindingDescriptionCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vulkan_graphics_pipeline::~vulkan_graphics_pipeline() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_graphics_pipeline::set_polygon_mode(PolygonMode mode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_graphics_pipeline::set_line_width(float line_width) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_graphics_pipeline::set_msaa_samples(MSAASamples samples) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_graphics_pipeline::set_cull_mode(CullMode mode, FrontFace face) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_graphics_pipeline::set_depth_bias_enabled(bool enable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_graphics_pipeline::set_depth_bias_options(float constant, float clamp, float slope) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_graphics_pipeline::attach_shader(const ref<shader> &shader) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_graphics_pipeline::build(const ref<render_context> &ctx) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,44 +8,52 @@
|
||||||
#include "dyn/platform/vulkan/vulkan.h"
|
#include "dyn/platform/vulkan/vulkan.h"
|
||||||
|
|
||||||
namespace dyn::core {
|
namespace dyn::core {
|
||||||
vulkan_shader::vulkan_shader(const std::string &source, const std::string& filename, shader_type type, const ref<vulkan_context>& ctx) : _ctx(ctx) {
|
vulkan_shader::vulkan_shader(
|
||||||
|
const std::vector<uint32_t>&source,
|
||||||
shaderc::Compiler compiler;
|
const std::string& filename, ShaderType type)
|
||||||
auto compile_result = compiler.CompileGlslToSpv(
|
: _binary(source.begin(), source.end()), _filename(filename), _type(type), _stage(vulkan_stage_from_type(type)) {}
|
||||||
source.data(), source.length(),
|
|
||||||
shader::convert_shader_type(type),
|
|
||||||
filename.data());
|
|
||||||
auto result = compile_result.GetCompilationStatus();
|
|
||||||
if (result != shaderc_compilation_status_success) {
|
|
||||||
DYN_ERROR_LOG("Failed to compile shader: {}", filename);
|
|
||||||
DYN_ERROR_LOG("Shader Errors: {}", compile_result.GetNumErrors());
|
|
||||||
DYN_ERROR_LOG("Shader Warnings: {}", compile_result.GetNumWarnings());
|
|
||||||
DYN_ERROR_LOG("Shader Compilation Error Message:");
|
|
||||||
DYN_ERROR_LOG(compile_result.GetErrorMessage());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_binary = std::vector(compile_result.begin(), compile_result.end());
|
|
||||||
|
|
||||||
VkShaderModuleCreateInfo module_create_info = {};
|
|
||||||
module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
|
||||||
module_create_info.pNext = nullptr;
|
|
||||||
module_create_info.codeSize = _binary.size();
|
|
||||||
module_create_info.pCode = _binary.data();
|
|
||||||
|
|
||||||
auto vk_res = vkCreateShaderModule(ctx->get_current_device()->get_handle(), &module_create_info, nullptr, &_shader);
|
|
||||||
if (vk_res != VK_SUCCESS) {
|
|
||||||
DYN_ERROR_LOG("Failed to create shader module: {}", string_VkResult(vk_res));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_usable = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
vulkan_shader::~vulkan_shader() {
|
vulkan_shader::~vulkan_shader() {
|
||||||
if (_shader != VK_NULL_HANDLE) {
|
if (_shader != VK_NULL_HANDLE) {
|
||||||
vkDestroyShaderModule(_ctx->get_current_device()->get_handle(), _shader, nullptr);
|
vkDestroyShaderModule(_ctx->get_current_device()->get_handle(), _shader, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkShaderStageFlagBits vulkan_shader::vulkan_stage_from_type(ShaderType type) {
|
||||||
|
switch (type) {
|
||||||
|
case VERTEX:
|
||||||
|
return VK_SHADER_STAGE_VERTEX_BIT;
|
||||||
|
case FRAGMENT:
|
||||||
|
return VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||||
|
case GEOMETRY:
|
||||||
|
return VK_SHADER_STAGE_GEOMETRY_BIT;
|
||||||
|
case COMPUTE:
|
||||||
|
return VK_SHADER_STAGE_COMPUTE_BIT;
|
||||||
|
}
|
||||||
|
return static_cast<VkShaderStageFlagBits>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_shader::build(const ref<render_context> &ctx) {
|
||||||
|
_ctx = ref_as<vulkan_context>(ctx);
|
||||||
|
|
||||||
|
VkShaderModuleCreateInfo module_create_info = {};
|
||||||
|
module_create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||||
|
module_create_info.pNext = nullptr;
|
||||||
|
// times by four as thats the requirement for vulkan shaders
|
||||||
|
module_create_info.codeSize = _binary.size()*4;
|
||||||
|
module_create_info.pCode = static_cast<const uint32_t*>(_binary.data());
|
||||||
|
|
||||||
|
auto vk_res = vkCreateShaderModule(_ctx->get_current_device()->get_handle(), &module_create_info, nullptr, &_shader);
|
||||||
|
if (vk_res != VK_SUCCESS) {
|
||||||
|
DYN_ERROR_LOG("Failed to create shader module: {}", string_VkResult(vk_res));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_pipeline_ci.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||||
|
_pipeline_ci.stage = _stage;
|
||||||
|
_pipeline_ci.module = _shader;
|
||||||
|
_pipeline_ci.pName = "main";
|
||||||
|
|
||||||
|
_usable = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,92 @@
|
||||||
|
|
||||||
#include <dyn/renderer/shader.h>
|
#include <dyn/renderer/shader.h>
|
||||||
|
|
||||||
namespace dyn::core {
|
#include "dyn/platform/vulkan/vulkan_shader.h"
|
||||||
|
#include "dyn/renderer/render_context.h"
|
||||||
|
|
||||||
}
|
namespace dyn::core {
|
||||||
|
shaderc_include_result * shader_includer::GetInclude(const char *requested_source, shaderc_include_type type,
|
||||||
|
const char *requesting_source, size_t) {
|
||||||
|
auto path = _base / requested_source;
|
||||||
|
DYN_DEBUG_LOG("Source file \"", requesting_source, "\" included/requested file: \"", path.string(), "\".");
|
||||||
|
if (file::exists(path.string())) {
|
||||||
|
file source{ path };
|
||||||
|
|
||||||
|
inclusion_data* data = new inclusion_data{
|
||||||
|
source.path(),
|
||||||
|
source.text()
|
||||||
|
};
|
||||||
|
|
||||||
|
return new shaderc_include_result {
|
||||||
|
data->path.data(), data->path.size(),
|
||||||
|
data->contents.data(), data->contents.size(),
|
||||||
|
data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
DYN_ERROR_LOG("Requested file to include \"", requested_source, "\" not found.");
|
||||||
|
return new shaderc_include_result {
|
||||||
|
"", 0, "", 0,
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void shader_includer::ReleaseInclude(shaderc_include_result *data) {
|
||||||
|
if (data->user_data != nullptr) {
|
||||||
|
delete static_cast<inclusion_data*>(data->user_data);
|
||||||
|
}
|
||||||
|
delete data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ref<shader> shader::create_from_string(const std::string &code, ShaderType type, const std::string &filename) {
|
||||||
|
auto compiled = compile_hlsl(code, type, filename, DYN_SHADER_INCLUDE_PATH);
|
||||||
|
if (compiled.empty()) {
|
||||||
|
DYN_ERROR_LOG("Shader compiled code is empty. Returning nullptr");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
DYN_PLATFORM_CREATE_BEGIN(render_context::get_api())
|
||||||
|
DYN_PLATFORM_CREATE_VK(vulkan_shader, compiled, filename, type);
|
||||||
|
DYN_PLATFORM_CREATE_END(shader)
|
||||||
|
}
|
||||||
|
|
||||||
|
ref<shader> shader::create_from_file(const std::string &filename, ShaderType type) {
|
||||||
|
file source { filename };
|
||||||
|
|
||||||
|
return shader::create_from_string(source.text(), type, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> shader::compile_hlsl(const std::string &code, ShaderType type, const std::string& filename, std::string include_path) {
|
||||||
|
DYN_DEBUG_LOG("Compiling Shader \"", filename, "\".");
|
||||||
|
|
||||||
|
shaderc::Compiler compiler;
|
||||||
|
|
||||||
|
shaderc::CompileOptions options;
|
||||||
|
options.SetSourceLanguage(shaderc_source_language_glsl);
|
||||||
|
switch (render_context::get_api()) {
|
||||||
|
case RenderPlatform::Vulkan:
|
||||||
|
options.SetTargetEnvironment(shaderc_target_env_vulkan, VK_VERSION_1_2);
|
||||||
|
break;
|
||||||
|
default:;
|
||||||
|
}
|
||||||
|
options.SetIncluder(create_scoped<shader_includer>(DYN_SHADER_INCLUDE_PATH));
|
||||||
|
|
||||||
|
auto compile_result = compiler.CompileGlslToSpv(
|
||||||
|
code.data(), code.length(),
|
||||||
|
convert_shader_type(type),
|
||||||
|
filename.data(), options);
|
||||||
|
|
||||||
|
auto result = compile_result.GetCompilationStatus();
|
||||||
|
if (result != shaderc_compilation_status_success) {
|
||||||
|
DYN_ERROR_LOG("Failed to compile shader:", filename);
|
||||||
|
DYN_ERROR_LOG("Shader Errors:", compile_result.GetNumErrors());
|
||||||
|
DYN_ERROR_LOG("Shader Warnings:", compile_result.GetNumWarnings());
|
||||||
|
DYN_ERROR_LOG("Shader Compilation Error Message:");
|
||||||
|
DYN_ERROR_LOG(compile_result.GetErrorMessage());
|
||||||
|
|
||||||
|
return std::vector<uint32_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
DYN_INFO_LOG("Successfully compiled shader:", filename);
|
||||||
|
|
||||||
|
return {compile_result.begin(), compile_result.end()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user