From 9d7a6ec8c02513150c7633f71e1786de375ef618 Mon Sep 17 00:00:00 2001 From: Luna Date: Fri, 18 Apr 2025 06:18:45 +0200 Subject: [PATCH] initial --- .gitignore | 4 + CMakeLists.txt | 9 ++ main.cpp | 255 ++++++++++++++++++++++++++++++++++++++++++ shaders/fragment.frag | 9 ++ shaders/fragment.spv | Bin 0 -> 572 bytes shaders/vertex.spv | Bin 0 -> 1504 bytes shaders/vertex.vert | 24 ++++ 7 files changed, 301 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 main.cpp create mode 100644 shaders/fragment.frag create mode 100644 shaders/fragment.spv create mode 100644 shaders/vertex.spv create mode 100644 shaders/vertex.vert diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..382721e --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/.DS_Store +/.vscode +/build +/dependencies \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..cbe1643 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.10.0) +project(vk_test VERSION 0.1.0 LANGUAGES C CXX) +set(CMAKE_CXX_STANDARD 23) + +find_package(Vulkan REQUIRED) + +add_executable(vk_test main.cpp) + +target_link_libraries(vk_test glfw Vulkan::Vulkan) \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..2fe9edf --- /dev/null +++ b/main.cpp @@ -0,0 +1,255 @@ +#define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 +#include +VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE +#include +#include +#include +#include + +std::vector read_file(const char *filename) +{ + std::ifstream file(filename); + file.seekg(0,std::ios::end); + std::streampos length = file.tellg(); + file.seekg(0,std::ios::beg); + std::vector buffer(length); + file.read(&buffer[0],length); + + return buffer; +} + +GLFWwindow *create_window(int width, int height, const char *title) +{ + glfwInit(); + + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + + GLFWwindow *window = glfwCreateWindow(width, height, title, nullptr, nullptr); + + if (!window) + { + std::println("GLFW window creation failed!"); + return nullptr; + } + return window; +} + +int main() +{ + GLFWwindow *window = create_window(800, 800, "hello"); + + if (!window) + return -1; + + vk::detail::DynamicLoader dl; + PFN_vkGetInstanceProcAddr pfnVkGetInstanceProcAddr = dl.getProcAddress("vkGetInstanceProcAddr"); + VULKAN_HPP_DEFAULT_DISPATCHER.init(pfnVkGetInstanceProcAddr); + + vk::ApplicationInfo appinfo = vk::ApplicationInfo("Test_vk", VK_MAKE_VERSION(0,1,0), NULL, VK_MAKE_VERSION(0,1,0), VK_API_VERSION_1_4); + + uint32_t extension_count = 0; + const char **glfwextensions = glfwGetRequiredInstanceExtensions(&extension_count); + std::println("GLFW requested extensions:"); + std::vector extensions; + std::vector layers; + for (int i = 0; i < extension_count;i++) + { + extensions.push_back(glfwextensions[i]); + std::println("{}", glfwextensions[i]); + } + #ifdef __APPLE__ + extensions.push_back("VK_KHR_portability_enumeration"); + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); //Apple silicon extensions + #endif + //layers.push_back("VK_LAYER_KHRONOS_validation"); + + vk::InstanceCreateInfo createinfo = vk::InstanceCreateInfo( + vk::InstanceCreateFlags(VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR), + &appinfo,layers.size(), layers.data(), + extensions.size(), extensions.data()); + vk::Instance instance = vk::createInstance(createinfo); + + VULKAN_HPP_DEFAULT_DISPATCHER.init(instance); + + uint32_t count = 0; + VkResult res = vkEnumeratePhysicalDevices(instance, &count, nullptr); + if (res != VK_SUCCESS) + { + std::println("Enumerating physical devices failed!"); + return -1; + } + std::println("Physical devices available {}", count); + std::vector devices; + devices.resize(count); + VkResult res2 = vkEnumeratePhysicalDevices(instance, &count, devices.data()); + if (res2 != VK_SUCCESS) + { + std::println("Enumerating physical devices failed!"); + return -1; + } + + vk::PhysicalDevice selected_physical_device; + for (auto device: devices) + { + VkPhysicalDeviceProperties dev_prop = {}; + vkGetPhysicalDeviceProperties(device, &dev_prop); + std::println("{}", dev_prop.deviceName); + selected_physical_device = device; + } + + std::vector queue_families = selected_physical_device.getQueueFamilyProperties(); + + uint32_t graphics_queue_index = 0; + + for (uint32_t i = 0; i < queue_families.size(); i++) + { + if (queue_families[i].queueFlags & vk::QueueFlagBits::eGraphics) + { + graphics_queue_index = i; + break; + } + } + float queue_priority = 1.0f; + vk::DeviceQueueCreateInfo queue_info = vk::DeviceQueueCreateInfo(vk::DeviceQueueCreateFlags(), graphics_queue_index, 1, &queue_priority); + + + uint32_t device_extension_count = 2; + char *device_extension_names[device_extension_count]; + device_extension_names[0] = (char *)"VK_KHR_swapchain"; + device_extension_names[1] = (char *)"VK_EXT_shader_object"; + vk::PhysicalDeviceFeatures device_features = vk::PhysicalDeviceFeatures(); + vk::PhysicalDeviceShaderObjectFeaturesEXT shader_features = vk::PhysicalDeviceShaderObjectFeaturesEXT(true); + + vk::DeviceCreateInfo device_info = vk::DeviceCreateInfo(vk::DeviceCreateFlags(), 1, &queue_info, 0, nullptr, device_extension_count, device_extension_names, &device_features); + device_info.pNext = &shader_features; + + vk::Device device = selected_physical_device.createDevice(device_info); + + auto dldi = vk::detail::DispatchLoaderDynamic(instance, pfnVkGetInstanceProcAddr, device); + + VkSurfaceKHR raw_surface; + glfwCreateWindowSurface(instance, window, nullptr, &raw_surface); + vk::SurfaceKHR surface = raw_surface; + + VkBool32 surface_supported = selected_physical_device.getSurfaceSupportKHR(graphics_queue_index, surface); + + if (surface_supported == VK_TRUE) + std::println("Surface supported!"); + else + std::println("Surface unsupported!"); + + vk::SurfaceCapabilitiesKHR surface_capabilities = selected_physical_device.getSurfaceCapabilitiesKHR(surface); + int width = 0; + int height = 0; + if (surface_capabilities.currentExtent.height == UINT32_MAX || surface_capabilities.currentExtent.width == UINT32_MAX) + { + glfwGetFramebufferSize(window, &width, &height); + width = std::clamp((uint32_t)width, surface_capabilities.minImageExtent.width, surface_capabilities.maxImageExtent.width); + height = std::clamp((uint32_t)height, surface_capabilities.minImageExtent.height, surface_capabilities.maxImageExtent.height); + } + else + { + width = surface_capabilities.currentExtent.width; + height = surface_capabilities.currentExtent.height; + } + vk::Extent2D framebuffer_extension = vk::Extent2D(width, height); + std::println("Extents width {} height {}", width, height); + + std::vector surface_formats = selected_physical_device.getSurfaceFormatsKHR(surface); + + vk::SurfaceFormatKHR format; + for (auto form: surface_formats) + { + if (form.format == vk::Format::eB8G8R8A8Srgb && form.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) + { + format = form; + break; + } + } + + std::vector present_modes = selected_physical_device.getSurfacePresentModesKHR(surface); + vk::PresentModeKHR mode = vk::PresentModeKHR::eFifo; + if (std::find(present_modes.begin(), present_modes.end(), vk::PresentModeKHR::eFifoRelaxed) != present_modes.end()) + { + mode = vk::PresentModeKHR::eFifoRelaxed; + std::println("Selected relaxed FIFO"); + } + + vk::SwapchainCreateInfoKHR swapchain_info = vk::SwapchainCreateInfoKHR(vk::SwapchainCreateFlagsKHR(), surface, 2, format.format, format.colorSpace, framebuffer_extension, + 1, vk::ImageUsageFlagBits::eColorAttachment, vk::SharingMode::eExclusive); + swapchain_info.preTransform = surface_capabilities.currentTransform; + swapchain_info.presentMode = mode; + swapchain_info.clipped = VK_TRUE; + swapchain_info.oldSwapchain = vk::SwapchainKHR(nullptr); + swapchain_info.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque; + + + vk::SwapchainKHR swapchain = device.createSwapchainKHR(swapchain_info); + + std::vector images = device.getSwapchainImagesKHR(swapchain); + std::println("Got {} images from swapchain", images.size()); + + std::vector image_views; + for (auto &image: images) + { + vk::ImageViewCreateInfo image_view_info = {}; + image_view_info.image = image; + image_view_info.viewType = vk::ImageViewType::e2D; + image_view_info.format = format.format; + image_view_info.components.r = vk::ComponentSwizzle::eIdentity; + image_view_info.components.g = vk::ComponentSwizzle::eIdentity; + image_view_info.components.b = vk::ComponentSwizzle::eIdentity; + image_view_info.components.a = vk::ComponentSwizzle::eIdentity; + image_view_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor; + image_view_info.subresourceRange.baseMipLevel = 0; + image_view_info.subresourceRange.levelCount = 1; + image_view_info.subresourceRange.baseArrayLayer = 0; + image_view_info.subresourceRange.layerCount = 1; + + image_views.push_back(device.createImageView(image_view_info)); + } + + + std::vector vertex_source = read_file("../shaders/vertex.spv"); + vk::ShaderCreateInfoEXT vertex_info = {}; + vertex_info.setFlags(vk::ShaderCreateFlagsEXT(vk::ShaderCreateFlagBitsEXT::eLinkStage)); + vertex_info.setStage(vk::ShaderStageFlagBits::eVertex); + vertex_info.setNextStage(vk::ShaderStageFlagBits::eFragment); + vertex_info.setCodeType(vk::ShaderCodeTypeEXT::eSpirv); + vertex_info.setCodeSize(vertex_source.size()); + vertex_info.setPCode(vertex_source.data()); + vertex_info.setPName("main"); + + std::vector fragment_source = read_file("../shaders/fragment.spv"); + vk::ShaderCreateInfoEXT fragment_info = {}; + fragment_info.setFlags(vk::ShaderCreateFlagsEXT(vk::ShaderCreateFlagBitsEXT::eLinkStage)); + fragment_info.setStage(vk::ShaderStageFlagBits::eFragment); + fragment_info.setCodeType(vk::ShaderCodeTypeEXT::eSpirv); + fragment_info.setCodeSize(fragment_source.size()); + fragment_info.setPCode(fragment_source.data()); + fragment_info.setPName("main"); + + std::vector shader_infos; + shader_infos.push_back(vertex_info); + shader_infos.push_back(fragment_info); + + auto shader_result = device.createShadersEXT(shader_infos, nullptr, dldi); + std::vector shaders; + if (shader_result.result == vk::Result::eSuccess) + { + shaders = shader_result.value; + std::println("Shaders succesfully loaded!"); + } + + while(!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + } + device.destroySwapchainKHR(swapchain); + instance.destroySurfaceKHR(surface); + device.destroy(); + instance.destroy(); + glfwTerminate(); + return 0; +} diff --git a/shaders/fragment.frag b/shaders/fragment.frag new file mode 100644 index 0000000..02a2b45 --- /dev/null +++ b/shaders/fragment.frag @@ -0,0 +1,9 @@ +#version 450 + +layout(location = 0) in vec3 in_color; +layout(location = 0) out vec4 out_color; + +void main() +{ + out_color = vec4(in_color, 1.0); +} \ No newline at end of file diff --git a/shaders/fragment.spv b/shaders/fragment.spv new file mode 100644 index 0000000000000000000000000000000000000000..782c404c1bb50d695218f562a042a094c51bcc77 GIT binary patch literal 572 zcmYk2PfNo<6vUrR)7IAhv!FMrcod2UErO^g$t6(553op*Lm;N5O$Bd$Hb0dY!TH6s zWMT65&Cc7Ijn}wnn;lrs`ZlruHMWKr6W1zh5Wa@9O%czoZ>~@b%qxXxhSs*GDtLcO za}ExLBVi;RybQGSbgS97hMLy3AaucE5rj`JTCLos_{KT%S$o|mbu+@EOQ5;ql2 zrRPob_)qoisPb3f@2VaTIP_gr^z`U^s`?crkDi_kaF^=Q4g|BW$GP4>9=urG@gv4p xy%)>feS!HGvCIxDPG!%HDh`jGZd`HP|E%=nKNgrr&pA0B60nK=B1!QGu8kHAYD_*#ry;UmMbG%p|qD*%qUI@}HUb ztNdc(dD@vxhuppQoO^EP-kG7@+MY6I!pxdEb7bnZWLjd3xK8Dx-dV3(l>P3(;XaCa z)2@VQ7R+=NPwMyUh0Ot5vK`qoSzCWC`9Bg*ni&)I;^^cg>K(_)a2OZmk1UNdo2PN# zj?$#G-%@nb4V}%C?6Th!1X48j3rt|HYLDTdu%#X3g<>>o^2s0@j6?*QB^3UW#i!}$ zJROzkcR{f=PfX5zLhMwfXU2-Rd3k1ksyk}x9CIo6KC{CQwkR+1Bpv5CA##^lHqHe) z3(kf`Kb(;?bu*vxJ{>U&=VtS`Y8`E)x=^0|J}OVlnyuZKqgOb**HHsUKb|9o;|wGH z(g*ml!|cByV=Ze}zOktN+tRAF)}!n}x3#@coGiel>5g=gfcfeVG% zoA1HDa+v#sqaHseV|hGZ!{2*455Bb^Lj&(Mi;A`0dd-pm9Ok)eim9o&PSwM*FyBK@ zo*A#p(}$m7MKPS8Vb$f~nE}lEYtC>(*qC4Hr&HD56oR8~%=5P#_BqerZfMEDv){Um zZ&8Pae(%V$H+SssfIH=Fa0hqg$-`|Z3gvwbIgGp6lxOBp#$4bn860=LEg#AzWb6aJ zCu326U!EL1_23=Hk$if literal 0 HcmV?d00001 diff --git a/shaders/vertex.vert b/shaders/vertex.vert new file mode 100644 index 0000000..c2f3b56 --- /dev/null +++ b/shaders/vertex.vert @@ -0,0 +1,24 @@ +#version 450 + +// x -> -1 (left) 1(right) +// y -> -1 (top) 1(bottom) + +vec2 positions[3] = vec2[]( + vec2(0.0, -0.5), + vec2(0.5, 0.5), + vec2(-0.5, 0.5) +); + +vec3 colors[3] = vec3[]( + vec3(1.0, 0.0, 0.0), + vec3(0.0, 1.0, 0.0), + vec3(0.0, 0.0, 1.0) +); + +layout(location = 0) out vec3 in_color; + +void main() +{ + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + in_color = colors[gl_VertexIndex]; +} \ No newline at end of file