start work on shaders and compiling. move compilation to general function, support include directories.
This commit is contained in:
parent
8aa57b4187
commit
6fe98cdb5b
|
|
@ -8,6 +8,12 @@ file(GLOB_RECURSE sourceFiles "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp" "${CMAKE_C
|
||||||
find_package(Vulkan REQUIRED)
|
find_package(Vulkan REQUIRED)
|
||||||
find_package(glfw3 CONFIG REQUIRED)
|
find_package(glfw3 CONFIG REQUIRED)
|
||||||
find_package(VulkanUtilityLibraries CONFIG REQUIRED)
|
find_package(VulkanUtilityLibraries CONFIG REQUIRED)
|
||||||
|
find_package(spirv_cross_core CONFIG REQUIRED)
|
||||||
|
find_package(spirv_cross_glsl CONFIG REQUIRED)
|
||||||
|
find_package(spirv_cross_hlsl CONFIG REQUIRED)
|
||||||
|
find_package(spirv_cross_msl CONFIG REQUIRED)
|
||||||
|
find_package(spirv_cross_reflect CONFIG REQUIRED)
|
||||||
|
find_package(spirv_cross_util CONFIG REQUIRED)
|
||||||
|
|
||||||
foreach (file ${sourceFiles})
|
foreach (file ${sourceFiles})
|
||||||
message("Source File Found ${file}")
|
message("Source File Found ${file}")
|
||||||
|
|
@ -20,3 +26,4 @@ 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)
|
||||||
37
inc/dyn/core/file.h
Normal file
37
inc/dyn/core/file.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 5/22/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace dyn::core {
|
||||||
|
class file {
|
||||||
|
public:
|
||||||
|
file(const std::string& path);
|
||||||
|
~file() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] std::string text() const { return _contents; }
|
||||||
|
[[nodiscard]] std::vector<uint8_t> bytes() const { return std::vector<uint8_t>(_contents.begin(), _contents.end()); }
|
||||||
|
|
||||||
|
[[nodiscard]] static bool exists(const std::string& path);
|
||||||
|
|
||||||
|
void write(const std::string& text);
|
||||||
|
void write(const std::vector<uint8_t>& bytes);
|
||||||
|
|
||||||
|
void append(const std::string& text);
|
||||||
|
void append(const std::vector<uint8_t>& bytes);
|
||||||
|
|
||||||
|
void close();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::fstream _file;
|
||||||
|
std::string _file_path;
|
||||||
|
|
||||||
|
std::string _contents;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -42,5 +42,6 @@ namespace dyn::core {
|
||||||
GLFWwindow* _window;
|
GLFWwindow* _window;
|
||||||
|
|
||||||
friend class vulkan_context;
|
friend class vulkan_context;
|
||||||
|
friend class vulkan_swapchain;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
#include <dyn/renderer/render_context.h>
|
#include <dyn/renderer/render_context.h>
|
||||||
|
|
||||||
#include "vulkan_devices.h"
|
#include "vulkan_devices.h"
|
||||||
|
#include "vulkan_swapchain.h"
|
||||||
|
|
||||||
namespace dyn::core {
|
namespace dyn::core {
|
||||||
|
|
||||||
|
|
@ -29,19 +30,23 @@ namespace dyn::core {
|
||||||
|
|
||||||
[[nodiscard]] VkInstance get_instance() const { return _instance; }
|
[[nodiscard]] VkInstance get_instance() const { return _instance; }
|
||||||
|
|
||||||
VkSurfaceKHR& get_surface();
|
VkSurfaceKHR get_surface() const;
|
||||||
|
|
||||||
[[nodiscard]] static bool check_api_version_support(uint32_t api_version);
|
[[nodiscard]] static bool check_api_version_support(uint32_t api_version);
|
||||||
|
|
||||||
[[nodiscard]] static ref<vulkan_device> get_last_selected_logical_device() { return s_current_device; }
|
[[nodiscard]] static ref<vulkan_device> get_last_selected_logical_device() { return s_current_device; }
|
||||||
|
|
||||||
void single_cmd(std::function<void(VkCommandBuffer)> cmdFunc);
|
[[nodiscard]] ref<vulkan_device> get_current_device() { return _device; }
|
||||||
|
|
||||||
|
void single_cmd(const std::function<void(VkCommandBuffer)>& cmd_func);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkInstance _instance = nullptr;
|
VkInstance _instance = nullptr;
|
||||||
ref<vulkan_physical_device> _physical_device;
|
ref<vulkan_physical_device> _physical_device;
|
||||||
ref<vulkan_device> _device;
|
ref<vulkan_device> _device;
|
||||||
|
|
||||||
|
ref<vulkan_swapchain> _swap_chain;
|
||||||
|
|
||||||
VkCommandPool _command_pool = nullptr;
|
VkCommandPool _command_pool = nullptr;
|
||||||
|
|
||||||
VkDebugUtilsMessengerEXT _debug_messenger = nullptr;
|
VkDebugUtilsMessengerEXT _debug_messenger = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -55,10 +55,13 @@ namespace dyn::core {
|
||||||
[[nodiscard]] VkQueue get_graphics_queue() const { return _graphics_queue; }
|
[[nodiscard]] VkQueue get_graphics_queue() const { return _graphics_queue; }
|
||||||
[[nodiscard]] VkQueue get_present_queue() const { return _present_queue; }
|
[[nodiscard]] VkQueue get_present_queue() const { return _present_queue; }
|
||||||
|
|
||||||
|
[[nodiscard]] ref<vulkan_physical_device> get_physical_device() const { return _physical_device; };
|
||||||
|
|
||||||
static ref<vulkan_device> create(const std::shared_ptr<vulkan_physical_device>& device, const VkPhysicalDeviceFeatures& device_features);
|
static ref<vulkan_device> create(const std::shared_ptr<vulkan_physical_device>& device, const VkPhysicalDeviceFeatures& device_features);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VkDevice _device = nullptr;
|
VkDevice _device = nullptr;
|
||||||
|
ref<vulkan_physical_device> _physical_device;
|
||||||
|
|
||||||
VkQueue _graphics_queue = VK_NULL_HANDLE;
|
VkQueue _graphics_queue = VK_NULL_HANDLE;
|
||||||
VkQueue _present_queue = VK_NULL_HANDLE;
|
VkQueue _present_queue = VK_NULL_HANDLE;
|
||||||
|
|
|
||||||
32
inc/dyn/platform/vulkan/vulkan_shader.h
Normal file
32
inc/dyn/platform/vulkan/vulkan_shader.h
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 5/22/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
#include "dyn/renderer/shader.h"
|
||||||
|
#include <dyn/core/file.h>
|
||||||
|
|
||||||
|
#include "vulkan_context.h"
|
||||||
|
|
||||||
|
namespace dyn::core {
|
||||||
|
class vulkan_shader : public shader {
|
||||||
|
public:
|
||||||
|
|
||||||
|
vulkan_shader(const std::string& source, const std::string& filename, shader_type type, const ref<vulkan_context>& ctx);
|
||||||
|
~vulkan_shader();
|
||||||
|
|
||||||
|
[[nodiscard]] VkShaderModule get_handle() const { return _shader; }
|
||||||
|
[[nodiscard]] VkPipelineShaderStageCreateInfo get_stage_info() const { return _pipeline_ci; }
|
||||||
|
|
||||||
|
[[nodiscard]] bool is_usable() const override { return _usable; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<uint32_t> _binary;
|
||||||
|
ref<vulkan_context> _ctx;
|
||||||
|
bool _usable = false;
|
||||||
|
VkShaderModule _shader = VK_NULL_HANDLE;
|
||||||
|
VkPipelineShaderStageCreateInfo _pipeline_ci = {};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -4,25 +4,45 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <dyn/platform/vulkan/vulkan_swapchain.h>
|
#include <dyn/platform/vulkan/vulkan_swapchain.h>
|
||||||
|
|
||||||
#include "dyn/renderer/swapchain.h"
|
#include "dyn/renderer/swapchain.h"
|
||||||
|
|
||||||
namespace dyn::core {
|
namespace dyn::core {
|
||||||
|
struct swap_chain_support_details {
|
||||||
|
VkSurfaceCapabilitiesKHR capabilities;
|
||||||
|
std::vector<VkSurfaceFormatKHR> formats;
|
||||||
|
std::vector<VkPresentModeKHR> present_modes;
|
||||||
|
};
|
||||||
|
|
||||||
class vulkan_swapchain : public swapchain {
|
class vulkan_swapchain : public swapchain {
|
||||||
public:
|
public:
|
||||||
explicit vulkan_swapchain(const ref<vulkan_context>& ctx);
|
explicit vulkan_swapchain(const ref<vulkan_context>& ctx);
|
||||||
~vulkan_swapchain() override;
|
~vulkan_swapchain() override;
|
||||||
|
|
||||||
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]; }
|
||||||
|
|
||||||
|
static ref<vulkan_swapchain> create(const ref<vulkan_context>& ctx);
|
||||||
|
|
||||||
|
[[nodiscard]] static swap_chain_support_details get_support_details(VkSurfaceKHR surface, VkPhysicalDevice physical_device);
|
||||||
|
[[nodiscard]] static VkSurfaceFormatKHR get_format(const std::vector<VkSurfaceFormatKHR>& formats);
|
||||||
|
[[nodiscard]] static VkPresentModeKHR get_present_mode(const std::vector<VkPresentModeKHR>& modes);
|
||||||
|
[[nodiscard]] static VkExtent2D get_extent(ref<vulkan_context> ctx, const VkSurfaceCapabilitiesKHR& capabilities);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void rebuild();
|
|
||||||
|
void build_swap_images();
|
||||||
|
|
||||||
|
void rebuild() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct swap_image {
|
struct swap_image {
|
||||||
|
|
@ -30,11 +50,15 @@ namespace dyn::core {
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
};
|
};
|
||||||
std::vector<swap_image> _swap_images;
|
std::vector<swap_image> _swap_images;
|
||||||
|
VkFormat _image_format;
|
||||||
|
VkExtent2D _extent;
|
||||||
|
|
||||||
std::vector<VkCommandBuffer> _command_buffers;
|
std::vector<VkCommandBuffer> _command_buffers;
|
||||||
uint32_t _current_frame = 0;
|
uint32_t _current_frame = 0;
|
||||||
|
|
||||||
VkSwapchainKHR _swapchain;
|
VkSwapchainKHR _swap_chain;
|
||||||
ref<vulkan_context> _ctx;
|
ref<vulkan_context> _ctx;
|
||||||
|
|
||||||
|
friend class vulkan_context;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
43
inc/dyn/renderer/shader.h
Normal file
43
inc/dyn/renderer/shader.h
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 5/21/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "dyn/core/base.h"
|
||||||
|
#include <shaderc/shaderc.hpp>
|
||||||
|
|
||||||
|
namespace dyn::core {
|
||||||
|
class render_context;
|
||||||
|
|
||||||
|
class shader {
|
||||||
|
public:
|
||||||
|
enum shader_type {
|
||||||
|
SHADER_VERTEX,
|
||||||
|
SHADER_FRAGMENT,
|
||||||
|
SHADER_GEOMETRY,
|
||||||
|
SHADER_COMPUTE
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] shaderc_shader_kind convert_shader_type(shader_type type) const noexcept {
|
||||||
|
switch (type) {
|
||||||
|
case SHADER_VERTEX:
|
||||||
|
return shaderc_vertex_shader;
|
||||||
|
case SHADER_FRAGMENT:
|
||||||
|
return shaderc_fragment_shader;
|
||||||
|
case SHADER_GEOMETRY:
|
||||||
|
return shaderc_geometry_shader;
|
||||||
|
case SHADER_COMPUTE:
|
||||||
|
return shaderc_compute_shader;
|
||||||
|
}
|
||||||
|
return shaderc_vertex_shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[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);
|
||||||
|
static ref<shader> create_from_file(const std::string& filename, shader_type type, const ref<render_context>& context);
|
||||||
|
};
|
||||||
|
}
|
||||||
52
src/core/file.cpp
Normal file
52
src/core/file.cpp
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 5/22/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <ios>
|
||||||
|
#include <dyn/core/file.h>
|
||||||
|
|
||||||
|
namespace dyn::core {
|
||||||
|
file::file(const std::string &path) : _file(path, std::ios::in | std::ios::binary | std::ios::out), _file_path(path) {
|
||||||
|
_file >> _contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
void file::write(const std::string &text) {
|
||||||
|
_file << text;
|
||||||
|
|
||||||
|
_contents.resize(text.size());
|
||||||
|
_contents.assign(text.begin(), text.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void file::write(const std::vector<uint8_t> &bytes) {
|
||||||
|
_file << std::string(bytes.begin(), bytes.end());
|
||||||
|
|
||||||
|
_contents.resize(bytes.size());
|
||||||
|
_contents.assign(bytes.begin(), bytes.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void file::append(const std::string &text) {
|
||||||
|
std::string out = _contents;
|
||||||
|
out += text;
|
||||||
|
_file << out;
|
||||||
|
|
||||||
|
_contents.resize(out.size());
|
||||||
|
_contents.assign(out.begin(), out.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void file::append(const std::vector<uint8_t> &bytes) {
|
||||||
|
std::string out = _contents;
|
||||||
|
out += std::string(bytes.begin(), bytes.end());
|
||||||
|
_file << out;
|
||||||
|
|
||||||
|
_contents.resize(out.size());
|
||||||
|
_contents.assign(out.begin(), out.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void file::close() {
|
||||||
|
_file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool file::exists(const std::string &path) {
|
||||||
|
return std::filesystem::exists(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -104,6 +104,10 @@ namespace dyn::core {
|
||||||
s_current_device = _device;
|
s_current_device = _device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
_swap_chain = vulkan_swapchain::create(self);
|
||||||
|
}
|
||||||
|
|
||||||
// command pool
|
// command pool
|
||||||
{
|
{
|
||||||
VkCommandPoolCreateInfo create_info{};
|
VkCommandPoolCreateInfo create_info{};
|
||||||
|
|
@ -124,7 +128,7 @@ namespace dyn::core {
|
||||||
void vulkan_context::cmd_end() {
|
void vulkan_context::cmd_end() {
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSurfaceKHR& vulkan_context::get_surface() {
|
VkSurfaceKHR vulkan_context::get_surface() const {
|
||||||
return _surface;
|
return _surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,7 +143,7 @@ namespace dyn::core {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vulkan_context::single_cmd(std::function<void(VkCommandBuffer)> cmdFunc) {
|
void vulkan_context::single_cmd(const std::function<void(VkCommandBuffer)>& cmd_func) {
|
||||||
VkCommandBufferAllocateInfo cmd_allocate_info{};
|
VkCommandBufferAllocateInfo cmd_allocate_info{};
|
||||||
cmd_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
cmd_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||||
cmd_allocate_info.commandPool = _command_pool;
|
cmd_allocate_info.commandPool = _command_pool;
|
||||||
|
|
@ -155,7 +159,7 @@ namespace dyn::core {
|
||||||
|
|
||||||
vkBeginCommandBuffer(cmd_buffer, &begin_info);
|
vkBeginCommandBuffer(cmd_buffer, &begin_info);
|
||||||
|
|
||||||
cmdFunc(cmd_buffer);
|
cmd_func(cmd_buffer);
|
||||||
|
|
||||||
vkEndCommandBuffer(cmd_buffer);
|
vkEndCommandBuffer(cmd_buffer);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "dyn/platform/vulkan/vulkan.h"
|
#include "dyn/platform/vulkan/vulkan.h"
|
||||||
#include "dyn/platform/vulkan/vulkan_context.h"
|
#include "dyn/platform/vulkan/vulkan_context.h"
|
||||||
#include "dyn/platform/vulkan/vulkan_devices.h"
|
#include "dyn/platform/vulkan/vulkan_devices.h"
|
||||||
|
#include "dyn/platform/vulkan/vulkan_swapchain.h"
|
||||||
|
|
||||||
namespace dyn::core {
|
namespace dyn::core {
|
||||||
vulkan_physical_device::vulkan_physical_device(const ref<vulkan_context>& ctx) :
|
vulkan_physical_device::vulkan_physical_device(const ref<vulkan_context>& ctx) :
|
||||||
|
|
@ -73,8 +74,18 @@ namespace dyn::core {
|
||||||
const VkSurfaceKHR &surface) {
|
const VkSurfaceKHR &surface) {
|
||||||
uint32_t prev_score = 0;
|
uint32_t prev_score = 0;
|
||||||
VkPhysicalDevice current_device = VK_NULL_HANDLE;
|
VkPhysicalDevice current_device = VK_NULL_HANDLE;
|
||||||
|
|
||||||
for (const auto& device : available_devices) {
|
for (const auto& device : available_devices) {
|
||||||
if (queue_families::find(device, surface).is_complete() && check_extension_support(device)) {
|
auto is_suitable = [device, surface] {
|
||||||
|
bool good_swap_chain = false;
|
||||||
|
if (check_extension_support(device)) {
|
||||||
|
swap_chain_support_details details = vulkan_swapchain::get_support_details(surface, device);
|
||||||
|
good_swap_chain = !details.formats.empty() && !details.present_modes.empty();
|
||||||
|
DYN_DEBUG_LOG("is swap chain good?", good_swap_chain ? "yes!" : "no!");
|
||||||
|
}
|
||||||
|
return queue_families::find(device, surface).is_complete() && good_swap_chain;
|
||||||
|
};
|
||||||
|
if (is_suitable()) {
|
||||||
auto score = score_device(device);
|
auto score = score_device(device);
|
||||||
if (prev_score < score) {
|
if (prev_score < score) {
|
||||||
prev_score = score;
|
prev_score = score;
|
||||||
|
|
@ -123,7 +134,7 @@ namespace dyn::core {
|
||||||
|
|
||||||
auto device_extensions = utils::vk_device_extensions;
|
auto device_extensions = utils::vk_device_extensions;
|
||||||
std::set<std::string> exts{device_extensions.begin(), device_extensions.end()};
|
std::set<std::string> exts{device_extensions.begin(), device_extensions.end()};
|
||||||
for (const auto &required_extension : exts) {
|
for (const auto &required_extension : device_extensions) {
|
||||||
exts.erase(required_extension);
|
exts.erase(required_extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,7 +145,7 @@ namespace dyn::core {
|
||||||
return create_ref<vulkan_physical_device>(ctx);
|
return create_ref<vulkan_physical_device>(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
vulkan_device::vulkan_device(const ref<vulkan_physical_device> &physical_device, VkPhysicalDeviceFeatures device_Features) {
|
vulkan_device::vulkan_device(const ref<vulkan_physical_device> &physical_device, VkPhysicalDeviceFeatures device_Features) : _physical_device(physical_device) {
|
||||||
vulkan_physical_device::queue_families families = physical_device->get_queue_families();
|
vulkan_physical_device::queue_families families = physical_device->get_queue_families();
|
||||||
|
|
||||||
std::set queue_family_indices = {families.graphics_family.value(), families.present_family.value()};
|
std::set queue_family_indices = {families.graphics_family.value(), families.present_family.value()};
|
||||||
|
|
|
||||||
51
src/platform/vulkan/vulkan_shader.cpp
Normal file
51
src/platform/vulkan/vulkan_shader.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 5/22/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <dyn/platform/vulkan/vulkan_shader.h>
|
||||||
|
|
||||||
|
#include "dyn/core/debug.h"
|
||||||
|
#include "dyn/platform/vulkan/vulkan.h"
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
shaderc::Compiler compiler;
|
||||||
|
auto compile_result = compiler.CompileGlslToSpv(
|
||||||
|
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() {
|
||||||
|
if (_shader != VK_NULL_HANDLE) {
|
||||||
|
vkDestroyShaderModule(_ctx->get_current_device()->get_handle(), _shader, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
195
src/platform/vulkan/vulkan_swapchain.cpp
Normal file
195
src/platform/vulkan/vulkan_swapchain.cpp
Normal file
|
|
@ -0,0 +1,195 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 5/14/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <dyn/platform/vulkan/vulkan_swapchain.h>
|
||||||
|
|
||||||
|
#include "dyn/platform/vulkan/vulkan.h"
|
||||||
|
#include "dyn/platform/vulkan/vulkan_context.h"
|
||||||
|
|
||||||
|
namespace dyn::core {
|
||||||
|
vulkan_swapchain::vulkan_swapchain(const ref<vulkan_context> &ctx) : _ctx(ctx) {
|
||||||
|
auto phy_device = _ctx->get_current_device()->get_physical_device();
|
||||||
|
auto logical_device = _ctx->get_current_device();
|
||||||
|
|
||||||
|
auto support_details = vulkan_swapchain::get_support_details(
|
||||||
|
_ctx->get_surface(),
|
||||||
|
phy_device->get_handle());
|
||||||
|
|
||||||
|
auto surface_format = get_format(support_details.formats);
|
||||||
|
auto present_mode = get_present_mode(support_details.present_modes);
|
||||||
|
auto extent = get_extent(_ctx, support_details.capabilities);
|
||||||
|
|
||||||
|
uint32_t image_count = support_details.capabilities.minImageCount + 2;
|
||||||
|
if (support_details.capabilities.maxImageCount > 0 && image_count > support_details.capabilities.maxImageCount) {
|
||||||
|
image_count = support_details.capabilities.maxImageCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
_swap_images.resize(image_count);
|
||||||
|
|
||||||
|
VkSwapchainCreateInfoKHR create_info = {};
|
||||||
|
create_info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
|
create_info.surface = ctx->get_surface();
|
||||||
|
create_info.minImageCount = image_count;
|
||||||
|
create_info.imageFormat = surface_format.format;
|
||||||
|
create_info.imageColorSpace = surface_format.colorSpace;
|
||||||
|
create_info.imageExtent = extent;
|
||||||
|
create_info.presentMode = present_mode;
|
||||||
|
create_info.imageArrayLayers = 1;
|
||||||
|
create_info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
|
||||||
|
auto indices = phy_device->get_queue_families();
|
||||||
|
uint32_t family_indices[] = {indices.graphics_family.value(), indices.present_family.value()};
|
||||||
|
|
||||||
|
if (indices.graphics_family.value() != indices.present_family.value()) {
|
||||||
|
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
create_info.queueFamilyIndexCount = 2;
|
||||||
|
create_info.pQueueFamilyIndices = family_indices;
|
||||||
|
} else {
|
||||||
|
create_info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
create_info.queueFamilyIndexCount = 0;
|
||||||
|
create_info.pQueueFamilyIndices = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_info.preTransform = support_details.capabilities.currentTransform;
|
||||||
|
create_info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
|
create_info.presentMode = present_mode;
|
||||||
|
create_info.clipped = VK_TRUE;
|
||||||
|
create_info.oldSwapchain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
_image_format = surface_format.format;
|
||||||
|
_extent = extent;
|
||||||
|
|
||||||
|
dyn_vk_verify(vkCreateSwapchainKHR(logical_device->get_handle(), &create_info, nullptr, &_swap_chain));
|
||||||
|
|
||||||
|
// create swap chain images
|
||||||
|
build_swap_images();
|
||||||
|
}
|
||||||
|
|
||||||
|
vulkan_swapchain::~vulkan_swapchain() {
|
||||||
|
auto dev_handle = _ctx->get_current_device()->get_handle();
|
||||||
|
vkDestroySwapchainKHR(dev_handle, _swap_chain, nullptr);
|
||||||
|
|
||||||
|
for (auto img : _swap_images) {
|
||||||
|
vkDestroyImageView(dev_handle, img.view, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swap_chain_support_details vulkan_swapchain::get_support_details(VkSurfaceKHR surface, VkPhysicalDevice physical_device) {
|
||||||
|
swap_chain_support_details details{};
|
||||||
|
|
||||||
|
dyn_vk_verify(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
|
||||||
|
physical_device,
|
||||||
|
surface,
|
||||||
|
&details.capabilities
|
||||||
|
));
|
||||||
|
|
||||||
|
uint32_t format_count;
|
||||||
|
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, nullptr);
|
||||||
|
|
||||||
|
if (format_count != 0) {
|
||||||
|
details.formats.resize(format_count);
|
||||||
|
vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &format_count, details.formats.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t present_mode_count;
|
||||||
|
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, nullptr);
|
||||||
|
|
||||||
|
if (present_mode_count != 0) {
|
||||||
|
details.present_modes.resize(present_mode_count);
|
||||||
|
vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &present_mode_count, details.present_modes.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkSurfaceFormatKHR vulkan_swapchain::get_format(const std::vector<VkSurfaceFormatKHR> &formats) {
|
||||||
|
for (const auto &format : formats) {
|
||||||
|
if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return formats[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPresentModeKHR vulkan_swapchain::get_present_mode(const std::vector<VkPresentModeKHR> &modes) {
|
||||||
|
for (const auto &mode : modes) {
|
||||||
|
// mailbox khr is preferred.
|
||||||
|
if (mode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fifo khr default
|
||||||
|
return VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkExtent2D vulkan_swapchain::get_extent(ref<vulkan_context> ctx, const VkSurfaceCapabilitiesKHR &capabilities) {
|
||||||
|
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
|
||||||
|
return capabilities.currentExtent;
|
||||||
|
} else {
|
||||||
|
int32_t width, height;
|
||||||
|
glfwGetFramebufferSize(
|
||||||
|
ctx->get_window()->get_window_handle(),
|
||||||
|
&width, &height);
|
||||||
|
|
||||||
|
VkExtent2D actual_extent = {
|
||||||
|
static_cast<uint32_t>(width),
|
||||||
|
static_cast<uint32_t>(height),
|
||||||
|
};
|
||||||
|
|
||||||
|
actual_extent.width = std::clamp(
|
||||||
|
actual_extent.width,
|
||||||
|
capabilities.minImageExtent.width,
|
||||||
|
capabilities.maxImageExtent.width);
|
||||||
|
|
||||||
|
actual_extent.height = std::clamp(
|
||||||
|
actual_extent.height,
|
||||||
|
capabilities.minImageExtent.height,
|
||||||
|
capabilities.maxImageExtent.height);
|
||||||
|
|
||||||
|
return actual_extent;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void vulkan_swapchain::build_swap_images() {
|
||||||
|
auto hlogical_device = _ctx->get_current_device()->get_handle();
|
||||||
|
|
||||||
|
uint32_t image_count = static_cast<uint32_t>(_swap_images.size());
|
||||||
|
|
||||||
|
std::vector<VkImage> temp_img_buf;
|
||||||
|
vkGetSwapchainImagesKHR(hlogical_device, _swap_chain, &image_count, nullptr);
|
||||||
|
temp_img_buf.resize(image_count);
|
||||||
|
vkGetSwapchainImagesKHR(hlogical_device, _swap_chain, &image_count, temp_img_buf.data());
|
||||||
|
|
||||||
|
_swap_images.resize(image_count);
|
||||||
|
for (uint32_t i = 0; i < image_count; i++) {
|
||||||
|
_swap_images[i].image = temp_img_buf[i];
|
||||||
|
|
||||||
|
VkImageViewCreateInfo create_info = {};
|
||||||
|
create_info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
create_info.image = _swap_images[i].image;
|
||||||
|
create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
create_info.format = _image_format;
|
||||||
|
|
||||||
|
create_info.components.r = VK_COMPONENT_SWIZZLE_R;
|
||||||
|
create_info.components.g = VK_COMPONENT_SWIZZLE_G;
|
||||||
|
create_info.components.b = VK_COMPONENT_SWIZZLE_B;
|
||||||
|
create_info.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||||
|
|
||||||
|
create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
create_info.subresourceRange.baseMipLevel = 0;
|
||||||
|
create_info.subresourceRange.levelCount = 1;
|
||||||
|
create_info.subresourceRange.baseArrayLayer = 0;
|
||||||
|
create_info.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
dyn_vk_verify(vkCreateImageView(hlogical_device, &create_info, nullptr, &_swap_images[i].view));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ref<vulkan_swapchain> vulkan_swapchain::create(const ref<vulkan_context> &ctx) {
|
||||||
|
return create_ref<vulkan_swapchain>(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
src/renderer/shader.cpp
Normal file
9
src/renderer/shader.cpp
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
//
|
||||||
|
// Created by nepge on 5/31/2025.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <dyn/renderer/shader.h>
|
||||||
|
|
||||||
|
namespace dyn::core {
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user