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(glfw3 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})
|
||||
message("Source File Found ${file}")
|
||||
|
|
@ -19,4 +25,5 @@ target_include_directories(Dyn PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/inc")
|
|||
|
||||
target_link_libraries(Dyn PRIVATE Vulkan::Vulkan)
|
||||
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;
|
||||
|
||||
friend class vulkan_context;
|
||||
friend class vulkan_swapchain;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include <dyn/renderer/render_context.h>
|
||||
|
||||
#include "vulkan_devices.h"
|
||||
#include "vulkan_swapchain.h"
|
||||
|
||||
namespace dyn::core {
|
||||
|
||||
|
|
@ -29,19 +30,23 @@ namespace dyn::core {
|
|||
|
||||
[[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 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:
|
||||
VkInstance _instance = nullptr;
|
||||
ref<vulkan_physical_device> _physical_device;
|
||||
ref<vulkan_device> _device;
|
||||
|
||||
ref<vulkan_swapchain> _swap_chain;
|
||||
|
||||
VkCommandPool _command_pool = nullptr;
|
||||
|
||||
VkDebugUtilsMessengerEXT _debug_messenger = nullptr;
|
||||
|
|
|
|||
|
|
@ -55,10 +55,13 @@ namespace dyn::core {
|
|||
[[nodiscard]] VkQueue get_graphics_queue() const { return _graphics_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);
|
||||
|
||||
private:
|
||||
VkDevice _device = nullptr;
|
||||
ref<vulkan_physical_device> _physical_device;
|
||||
|
||||
VkQueue _graphics_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
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
#include <dyn/platform/vulkan/vulkan_swapchain.h>
|
||||
|
||||
#include "dyn/renderer/swapchain.h"
|
||||
|
||||
namespace dyn::core {
|
||||
struct swap_chain_support_details {
|
||||
VkSurfaceCapabilitiesKHR capabilities;
|
||||
std::vector<VkSurfaceFormatKHR> formats;
|
||||
std::vector<VkPresentModeKHR> present_modes;
|
||||
};
|
||||
|
||||
class vulkan_swapchain : public swapchain {
|
||||
public:
|
||||
explicit vulkan_swapchain(const ref<vulkan_context>& ctx);
|
||||
~vulkan_swapchain() override;
|
||||
|
||||
void prepare() override;
|
||||
void present() override;
|
||||
void prepare() 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]; }
|
||||
|
||||
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:
|
||||
void rebuild();
|
||||
|
||||
void build_swap_images();
|
||||
|
||||
void rebuild() {}
|
||||
|
||||
private:
|
||||
struct swap_image {
|
||||
|
|
@ -30,11 +50,15 @@ namespace dyn::core {
|
|||
VkImageView view;
|
||||
};
|
||||
std::vector<swap_image> _swap_images;
|
||||
VkFormat _image_format;
|
||||
VkExtent2D _extent;
|
||||
|
||||
std::vector<VkCommandBuffer> _command_buffers;
|
||||
uint32_t _current_frame = 0;
|
||||
|
||||
VkSwapchainKHR _swapchain;
|
||||
VkSwapchainKHR _swap_chain;
|
||||
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;
|
||||
}
|
||||
|
||||
{
|
||||
_swap_chain = vulkan_swapchain::create(self);
|
||||
}
|
||||
|
||||
// command pool
|
||||
{
|
||||
VkCommandPoolCreateInfo create_info{};
|
||||
|
|
@ -124,7 +128,7 @@ namespace dyn::core {
|
|||
void vulkan_context::cmd_end() {
|
||||
}
|
||||
|
||||
VkSurfaceKHR& vulkan_context::get_surface() {
|
||||
VkSurfaceKHR vulkan_context::get_surface() const {
|
||||
return _surface;
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +143,7 @@ namespace dyn::core {
|
|||
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{};
|
||||
cmd_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
||||
cmd_allocate_info.commandPool = _command_pool;
|
||||
|
|
@ -155,7 +159,7 @@ namespace dyn::core {
|
|||
|
||||
vkBeginCommandBuffer(cmd_buffer, &begin_info);
|
||||
|
||||
cmdFunc(cmd_buffer);
|
||||
cmd_func(cmd_buffer);
|
||||
|
||||
vkEndCommandBuffer(cmd_buffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "dyn/platform/vulkan/vulkan.h"
|
||||
#include "dyn/platform/vulkan/vulkan_context.h"
|
||||
#include "dyn/platform/vulkan/vulkan_devices.h"
|
||||
#include "dyn/platform/vulkan/vulkan_swapchain.h"
|
||||
|
||||
namespace dyn::core {
|
||||
vulkan_physical_device::vulkan_physical_device(const ref<vulkan_context>& ctx) :
|
||||
|
|
@ -73,8 +74,18 @@ namespace dyn::core {
|
|||
const VkSurfaceKHR &surface) {
|
||||
uint32_t prev_score = 0;
|
||||
VkPhysicalDevice current_device = VK_NULL_HANDLE;
|
||||
|
||||
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);
|
||||
if (prev_score < score) {
|
||||
prev_score = score;
|
||||
|
|
@ -123,7 +134,7 @@ namespace dyn::core {
|
|||
|
||||
auto device_extensions = utils::vk_device_extensions;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +145,7 @@ namespace dyn::core {
|
|||
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();
|
||||
|
||||
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