├── .gitignore ├── .gitmodules ├── README.md ├── deps └── windows │ └── glfw3 │ ├── COPYING.txt │ ├── README.md │ ├── include │ └── GLFW │ │ ├── glfw3.h │ │ └── glfw3native.h │ └── lib │ └── glfw3.lib ├── include ├── application.h ├── buffer.h ├── command_buffers.h ├── descriptor_sets.h ├── device.h ├── frame_buffer.h ├── graphics_pipeline.h ├── image.h ├── instance.h ├── queue.h ├── render_pass.h ├── shader.h ├── simple_vulkan.h ├── swapchain.h └── utility.h ├── premake4.lua ├── shader ├── triangle.frag └── triangle.vert ├── src ├── application.cpp ├── buffer.cpp ├── command_buffers.cpp ├── descriptor_sets.cpp ├── device.cpp ├── frame_buffer.cpp ├── graphics_pipeline.cpp ├── image.cpp ├── instance.cpp ├── main.cpp ├── queue.cpp ├── render_pass.cpp ├── shader.cpp └── swapchain.cpp └── tools └── win └── premake5.exe /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /obj 3 | .* 4 | !.gitignore 5 | Makefile 6 | *.make 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/vkcpp"] 2 | path = deps/vkcpp 3 | url = https://github.com/nvpro-pipeline/vkcpp.git 4 | [submodule "deps/glfw3"] 5 | path = deps/glfw3 6 | url = https://github.com/glfw/glfw.git 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SimpleVulkan 2 | 3 | SimpleVulkan is simple vulkan framework. 4 | 5 | ## Dependecies 6 | 7 | * LunarG Vulkan SDK 1.0.11+ 8 | * glfw 3.2+ 9 | * Precompiled binary is privided in `deps/windows/glfw3/` for Windows platform. 10 | * vkcpp 11 | 12 | ## Supported platform 13 | 14 | * [x] Linux 15 | * [x] Windows 64bit 16 | * Visual Studio 2013 + x64 17 | 18 | ## Build 19 | 20 | ### Windows 21 | 22 | First checkout dependent libraries(e.g. vkcpp). 23 | 24 | $ git submodule update --init 25 | 26 | Set `VULKAN_SDK` environment variable to the path to Vulkan SDK. 27 | 28 | Build glfw3 library. 29 | 30 | Then, 31 | 32 | $ ./tools/win/premake5.exe vs2013 33 | 34 | Build .sln with Visual Studio 2013. 35 | (Only 64bit build is supported). 36 | 37 | ## Run 38 | 39 | Compile `shaders/triangle.frag` and `shaders/triangle.vert` with `glslangValidator -V`, and put `frag.spv` and `vert.spv` to working directory. 40 | 41 | Then, 42 | 43 | $ ./vulkan_test 44 | 45 | In default, Vulkan validation layer + debug report is enabled. Disable validation layer with `-novalidate` argument. 46 | 47 | ## License 48 | 49 | `SimpleVulkan` is licensed under MIT license 50 | -------------------------------------------------------------------------------- /deps/windows/glfw3/COPYING.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2002-2006 Marcus Geelnard 2 | Copyright (c) 2006-2010 Camilla Berglund 3 | 4 | This software is provided 'as-is', without any express or implied 5 | warranty. In no event will the authors be held liable for any damages 6 | arising from the use of this software. 7 | 8 | Permission is granted to anyone to use this software for any purpose, 9 | including commercial applications, and to alter it and redistribute it 10 | freely, subject to the following restrictions: 11 | 12 | 1. The origin of this software must not be misrepresented; you must not 13 | claim that you wrote the original software. If you use this software 14 | in a product, an acknowledgment in the product documentation would 15 | be appreciated but is not required. 16 | 17 | 2. Altered source versions must be plainly marked as such, and must not 18 | be misrepresented as being the original software. 19 | 20 | 3. This notice may not be removed or altered from any source 21 | distribution. 22 | 23 | -------------------------------------------------------------------------------- /deps/windows/glfw3/README.md: -------------------------------------------------------------------------------- 1 | Precompiled glfw3 x64 binary. 2 | 3 | RelWithDebInfo + Visual Studio 2013 4 | -------------------------------------------------------------------------------- /deps/windows/glfw3/include/GLFW/glfw3native.h: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | * GLFW 3.2 - www.glfw.org 3 | * A library for OpenGL, window and input 4 | *------------------------------------------------------------------------ 5 | * Copyright (c) 2002-2006 Marcus Geelnard 6 | * Copyright (c) 2006-2010 Camilla Berglund 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgment in the product documentation would 19 | * be appreciated but is not required. 20 | * 21 | * 2. Altered source versions must be plainly marked as such, and must not 22 | * be misrepresented as being the original software. 23 | * 24 | * 3. This notice may not be removed or altered from any source 25 | * distribution. 26 | * 27 | *************************************************************************/ 28 | 29 | #ifndef _glfw3_native_h_ 30 | #define _glfw3_native_h_ 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | 37 | /************************************************************************* 38 | * Doxygen documentation 39 | *************************************************************************/ 40 | 41 | /*! @file glfw3native.h 42 | * @brief The header of the native access functions. 43 | * 44 | * This is the header file of the native access functions. See @ref native for 45 | * more information. 46 | */ 47 | /*! @defgroup native Native access 48 | * 49 | * **By using the native access functions you assert that you know what you're 50 | * doing and how to fix problems caused by using them. If you don't, you 51 | * shouldn't be using them.** 52 | * 53 | * Before the inclusion of @ref glfw3native.h, you may define exactly one 54 | * window system API macro and zero or more context creation API macros. 55 | * 56 | * The chosen backends must match those the library was compiled for. Failure 57 | * to do this will cause a link-time error. 58 | * 59 | * The available window API macros are: 60 | * * `GLFW_EXPOSE_NATIVE_WIN32` 61 | * * `GLFW_EXPOSE_NATIVE_COCOA` 62 | * * `GLFW_EXPOSE_NATIVE_X11` 63 | * * `GLFW_EXPOSE_NATIVE_WAYLAND` 64 | * * `GLFW_EXPOSE_NATIVE_MIR` 65 | * 66 | * The available context API macros are: 67 | * * `GLFW_EXPOSE_NATIVE_WGL` 68 | * * `GLFW_EXPOSE_NATIVE_NSGL` 69 | * * `GLFW_EXPOSE_NATIVE_GLX` 70 | * * `GLFW_EXPOSE_NATIVE_EGL` 71 | * 72 | * These macros select which of the native access functions that are declared 73 | * and which platform-specific headers to include. It is then up your (by 74 | * definition platform-specific) code to handle which of these should be 75 | * defined. 76 | */ 77 | 78 | 79 | /************************************************************************* 80 | * System headers and types 81 | *************************************************************************/ 82 | 83 | #if defined(GLFW_EXPOSE_NATIVE_WIN32) 84 | // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for 85 | // example to allow applications to correctly declare a GL_ARB_debug_output 86 | // callback) but windows.h assumes no one will define APIENTRY before it does 87 | #undef APIENTRY 88 | #include 89 | #elif defined(GLFW_EXPOSE_NATIVE_COCOA) 90 | #include 91 | #if defined(__OBJC__) 92 | #import 93 | #else 94 | typedef void* id; 95 | #endif 96 | #elif defined(GLFW_EXPOSE_NATIVE_X11) 97 | #include 98 | #include 99 | #elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) 100 | #include 101 | #elif defined(GLFW_EXPOSE_NATIVE_MIR) 102 | #include 103 | #endif 104 | 105 | #if defined(GLFW_EXPOSE_NATIVE_WGL) 106 | /* WGL is declared by windows.h */ 107 | #endif 108 | #if defined(GLFW_EXPOSE_NATIVE_NSGL) 109 | /* NSGL is declared by Cocoa.h */ 110 | #endif 111 | #if defined(GLFW_EXPOSE_NATIVE_GLX) 112 | #include 113 | #endif 114 | #if defined(GLFW_EXPOSE_NATIVE_EGL) 115 | #include 116 | #endif 117 | 118 | 119 | /************************************************************************* 120 | * Functions 121 | *************************************************************************/ 122 | 123 | #if defined(GLFW_EXPOSE_NATIVE_WIN32) 124 | /*! @brief Returns the adapter device name of the specified monitor. 125 | * 126 | * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`) 127 | * of the specified monitor, or `NULL` if an [error](@ref error_handling) 128 | * occurred. 129 | * 130 | * @thread_safety This function may be called from any thread. Access is not 131 | * synchronized. 132 | * 133 | * @since Added in version 3.1. 134 | * 135 | * @ingroup native 136 | */ 137 | GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor); 138 | 139 | /*! @brief Returns the display device name of the specified monitor. 140 | * 141 | * @return The UTF-8 encoded display device name (for example 142 | * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an 143 | * [error](@ref error_handling) occurred. 144 | * 145 | * @thread_safety This function may be called from any thread. Access is not 146 | * synchronized. 147 | * 148 | * @since Added in version 3.1. 149 | * 150 | * @ingroup native 151 | */ 152 | GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor); 153 | 154 | /*! @brief Returns the `HWND` of the specified window. 155 | * 156 | * @return The `HWND` of the specified window, or `NULL` if an 157 | * [error](@ref error_handling) occurred. 158 | * 159 | * @thread_safety This function may be called from any thread. Access is not 160 | * synchronized. 161 | * 162 | * @since Added in version 3.0. 163 | * 164 | * @ingroup native 165 | */ 166 | GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window); 167 | #endif 168 | 169 | #if defined(GLFW_EXPOSE_NATIVE_WGL) 170 | /*! @brief Returns the `HGLRC` of the specified window. 171 | * 172 | * @return The `HGLRC` of the specified window, or `NULL` if an 173 | * [error](@ref error_handling) occurred. 174 | * 175 | * @thread_safety This function may be called from any thread. Access is not 176 | * synchronized. 177 | * 178 | * @since Added in version 3.0. 179 | * 180 | * @ingroup native 181 | */ 182 | GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window); 183 | #endif 184 | 185 | #if defined(GLFW_EXPOSE_NATIVE_COCOA) 186 | /*! @brief Returns the `CGDirectDisplayID` of the specified monitor. 187 | * 188 | * @return The `CGDirectDisplayID` of the specified monitor, or 189 | * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. 190 | * 191 | * @thread_safety This function may be called from any thread. Access is not 192 | * synchronized. 193 | * 194 | * @since Added in version 3.1. 195 | * 196 | * @ingroup native 197 | */ 198 | GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor); 199 | 200 | /*! @brief Returns the `NSWindow` of the specified window. 201 | * 202 | * @return The `NSWindow` of the specified window, or `nil` if an 203 | * [error](@ref error_handling) occurred. 204 | * 205 | * @thread_safety This function may be called from any thread. Access is not 206 | * synchronized. 207 | * 208 | * @since Added in version 3.0. 209 | * 210 | * @ingroup native 211 | */ 212 | GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window); 213 | #endif 214 | 215 | #if defined(GLFW_EXPOSE_NATIVE_NSGL) 216 | /*! @brief Returns the `NSOpenGLContext` of the specified window. 217 | * 218 | * @return The `NSOpenGLContext` of the specified window, or `nil` if an 219 | * [error](@ref error_handling) occurred. 220 | * 221 | * @thread_safety This function may be called from any thread. Access is not 222 | * synchronized. 223 | * 224 | * @since Added in version 3.0. 225 | * 226 | * @ingroup native 227 | */ 228 | GLFWAPI id glfwGetNSGLContext(GLFWwindow* window); 229 | #endif 230 | 231 | #if defined(GLFW_EXPOSE_NATIVE_X11) 232 | /*! @brief Returns the `Display` used by GLFW. 233 | * 234 | * @return The `Display` used by GLFW, or `NULL` if an 235 | * [error](@ref error_handling) occurred. 236 | * 237 | * @thread_safety This function may be called from any thread. Access is not 238 | * synchronized. 239 | * 240 | * @since Added in version 3.0. 241 | * 242 | * @ingroup native 243 | */ 244 | GLFWAPI Display* glfwGetX11Display(void); 245 | 246 | /*! @brief Returns the `RRCrtc` of the specified monitor. 247 | * 248 | * @return The `RRCrtc` of the specified monitor, or `None` if an 249 | * [error](@ref error_handling) occurred. 250 | * 251 | * @thread_safety This function may be called from any thread. Access is not 252 | * synchronized. 253 | * 254 | * @since Added in version 3.1. 255 | * 256 | * @ingroup native 257 | */ 258 | GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor); 259 | 260 | /*! @brief Returns the `RROutput` of the specified monitor. 261 | * 262 | * @return The `RROutput` of the specified monitor, or `None` if an 263 | * [error](@ref error_handling) occurred. 264 | * 265 | * @thread_safety This function may be called from any thread. Access is not 266 | * synchronized. 267 | * 268 | * @since Added in version 3.1. 269 | * 270 | * @ingroup native 271 | */ 272 | GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor); 273 | 274 | /*! @brief Returns the `Window` of the specified window. 275 | * 276 | * @return The `Window` of the specified window, or `None` if an 277 | * [error](@ref error_handling) occurred. 278 | * 279 | * @thread_safety This function may be called from any thread. Access is not 280 | * synchronized. 281 | * 282 | * @since Added in version 3.0. 283 | * 284 | * @ingroup native 285 | */ 286 | GLFWAPI Window glfwGetX11Window(GLFWwindow* window); 287 | #endif 288 | 289 | #if defined(GLFW_EXPOSE_NATIVE_GLX) 290 | /*! @brief Returns the `GLXContext` of the specified window. 291 | * 292 | * @return The `GLXContext` of the specified window, or `NULL` if an 293 | * [error](@ref error_handling) occurred. 294 | * 295 | * @thread_safety This function may be called from any thread. Access is not 296 | * synchronized. 297 | * 298 | * @since Added in version 3.0. 299 | * 300 | * @ingroup native 301 | */ 302 | GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); 303 | 304 | /*! @brief Returns the `GLXWindow` of the specified window. 305 | * 306 | * @return The `GLXWindow` of the specified window, or `None` if an 307 | * [error](@ref error_handling) occurred. 308 | * 309 | * @thread_safety This function may be called from any thread. Access is not 310 | * synchronized. 311 | * 312 | * @since Added in version 3.2. 313 | * 314 | * @ingroup native 315 | */ 316 | GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); 317 | #endif 318 | 319 | #if defined(GLFW_EXPOSE_NATIVE_WAYLAND) 320 | /*! @brief Returns the `struct wl_display*` used by GLFW. 321 | * 322 | * @return The `struct wl_display*` used by GLFW, or `NULL` if an 323 | * [error](@ref error_handling) occurred. 324 | * 325 | * @thread_safety This function may be called from any thread. Access is not 326 | * synchronized. 327 | * 328 | * @since Added in version 3.2. 329 | * 330 | * @ingroup native 331 | */ 332 | GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); 333 | 334 | /*! @brief Returns the `struct wl_output*` of the specified monitor. 335 | * 336 | * @return The `struct wl_output*` of the specified monitor, or `NULL` if an 337 | * [error](@ref error_handling) occurred. 338 | * 339 | * @thread_safety This function may be called from any thread. Access is not 340 | * synchronized. 341 | * 342 | * @since Added in version 3.2. 343 | * 344 | * @ingroup native 345 | */ 346 | GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); 347 | 348 | /*! @brief Returns the main `struct wl_surface*` of the specified window. 349 | * 350 | * @return The main `struct wl_surface*` of the specified window, or `NULL` if 351 | * an [error](@ref error_handling) occurred. 352 | * 353 | * @thread_safety This function may be called from any thread. Access is not 354 | * synchronized. 355 | * 356 | * @since Added in version 3.2. 357 | * 358 | * @ingroup native 359 | */ 360 | GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); 361 | #endif 362 | 363 | #if defined(GLFW_EXPOSE_NATIVE_MIR) 364 | /*! @brief Returns the `MirConnection*` used by GLFW. 365 | * 366 | * @return The `MirConnection*` used by GLFW, or `NULL` if an 367 | * [error](@ref error_handling) occurred. 368 | * 369 | * @thread_safety This function may be called from any thread. Access is not 370 | * synchronized. 371 | * 372 | * @since Added in version 3.2. 373 | * 374 | * @ingroup native 375 | */ 376 | GLFWAPI MirConnection* glfwGetMirDisplay(void); 377 | 378 | /*! @brief Returns the Mir output ID of the specified monitor. 379 | * 380 | * @return The Mir output ID of the specified monitor, or zero if an 381 | * [error](@ref error_handling) occurred. 382 | * 383 | * @thread_safety This function may be called from any thread. Access is not 384 | * synchronized. 385 | * 386 | * @since Added in version 3.2. 387 | * 388 | * @ingroup native 389 | */ 390 | GLFWAPI int glfwGetMirMonitor(GLFWmonitor* monitor); 391 | 392 | /*! @brief Returns the `MirSurface*` of the specified window. 393 | * 394 | * @return The `MirSurface*` of the specified window, or `NULL` if an 395 | * [error](@ref error_handling) occurred. 396 | * 397 | * @thread_safety This function may be called from any thread. Access is not 398 | * synchronized. 399 | * 400 | * @since Added in version 3.2. 401 | * 402 | * @ingroup native 403 | */ 404 | GLFWAPI MirSurface* glfwGetMirWindow(GLFWwindow* window); 405 | #endif 406 | 407 | #if defined(GLFW_EXPOSE_NATIVE_EGL) 408 | /*! @brief Returns the `EGLDisplay` used by GLFW. 409 | * 410 | * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an 411 | * [error](@ref error_handling) occurred. 412 | * 413 | * @thread_safety This function may be called from any thread. Access is not 414 | * synchronized. 415 | * 416 | * @since Added in version 3.0. 417 | * 418 | * @ingroup native 419 | */ 420 | GLFWAPI EGLDisplay glfwGetEGLDisplay(void); 421 | 422 | /*! @brief Returns the `EGLContext` of the specified window. 423 | * 424 | * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an 425 | * [error](@ref error_handling) occurred. 426 | * 427 | * @thread_safety This function may be called from any thread. Access is not 428 | * synchronized. 429 | * 430 | * @since Added in version 3.0. 431 | * 432 | * @ingroup native 433 | */ 434 | GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window); 435 | 436 | /*! @brief Returns the `EGLSurface` of the specified window. 437 | * 438 | * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an 439 | * [error](@ref error_handling) occurred. 440 | * 441 | * @thread_safety This function may be called from any thread. Access is not 442 | * synchronized. 443 | * 444 | * @since Added in version 3.0. 445 | * 446 | * @ingroup native 447 | */ 448 | GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window); 449 | #endif 450 | 451 | #ifdef __cplusplus 452 | } 453 | #endif 454 | 455 | #endif /* _glfw3_native_h_ */ 456 | 457 | -------------------------------------------------------------------------------- /deps/windows/glfw3/lib/glfw3.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lighttransport/simple_vulkan/a7ece2f02ed32ca4d3910a21140d13701454b5d6/deps/windows/glfw3/lib/glfw3.lib -------------------------------------------------------------------------------- /include/application.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace simpleVulkan 7 | { 8 | class Application 9 | { 10 | private: 11 | uint32_t m_width = 400; 12 | uint32_t m_height = 400; 13 | GLFWwindow* m_window; 14 | std::chrono::milliseconds m_interval; 15 | bool m_validate; // Enable Vulkan validation layer + debug report? 16 | 17 | public: 18 | Application(); 19 | virtual ~Application(); 20 | 21 | bool create(std::string windowName,uint32_t width,uint32_t height, bool validate = false); 22 | void destroy(); 23 | bool run(); 24 | protected: 25 | std::chrono::microseconds getInterval(); 26 | void setInterval(std::chrono::milliseconds interval); 27 | uint32_t getWidth(); 28 | void setSize(uint32_t width,uint32_t height); 29 | uint32_t getHeight(); 30 | void setHeight(uint32_t height); 31 | bool getValidateFlag(); 32 | void setValidateFlag(bool validate); 33 | void closeWindow(); 34 | private: 35 | virtual bool initialize( 36 | const std::vector& glfwExtensions, 37 | GLFWwindow* window) = 0; 38 | virtual void finalize() = 0; 39 | virtual bool render() = 0; 40 | }; 41 | } 42 | -------------------------------------------------------------------------------- /include/buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include"device.h" 4 | 5 | namespace simpleVulkan 6 | { 7 | class Buffer 8 | { 9 | vk::Device m_device; 10 | vk::BufferUsageFlags m_usage; 11 | size_t m_size; 12 | vk::Buffer m_buffer; 13 | vk::DeviceMemory m_memory; 14 | public: 15 | Buffer(); 16 | ~Buffer(); 17 | 18 | Result create(vk::PhysicalDevice physicalDevice,vk::Device device,vk::BufferUsageFlags usage,size_t size); 19 | void destroy(); 20 | void write(const void* pData); 21 | 22 | size_t getSize(); 23 | vk::BufferUsageFlags getUsage(); 24 | 25 | vk::Buffer& getVkBuffer(); 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /include/command_buffers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #include"device.h" 6 | 7 | namespace simpleVulkan 8 | { 9 | class CommandBuffers 10 | { 11 | private: 12 | vk::Device m_device; 13 | vk::CommandPool m_cmdPool; 14 | std::vector m_cmdBuffers; 15 | public: 16 | CommandBuffers(); 17 | ~CommandBuffers(); 18 | 19 | Result create(vk::Device device,size_t count); 20 | void destroy(); 21 | 22 | vk::CommandPool& getVkCommandPool(); 23 | vk::CommandBuffer& getVkCommandBuffer(size_t index); 24 | const std::vector& getVkCommandBuffers(); 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /include/descriptor_sets.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | #include"device.h" 8 | 9 | namespace simpleVulkan 10 | { 11 | class DescriptorSets 12 | { 13 | vk::Device m_device; 14 | vk::DescriptorPool m_descriptorPool; 15 | vk::DescriptorSetLayout m_descriptorSetLayout; 16 | std::vector m_descriptorSets; 17 | public: 18 | DescriptorSets(); 19 | ~DescriptorSets(); 20 | 21 | Result create( 22 | vk::Device device, 23 | const std::vector& descriptorBindings, 24 | uint32_t setsCount); 25 | void destroy(); 26 | 27 | vk::DescriptorSet& getVkDescriptorSet(size_t index); 28 | vk::DescriptorSetLayout& getVkDescriptorSetLayout(); 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /include/device.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include"instance.h" 7 | 8 | namespace simpleVulkan 9 | { 10 | class Device 11 | { 12 | private: 13 | std::vector m_physicalDevices; 14 | std::vector m_devices; 15 | public: 16 | Device(); 17 | ~Device(); 18 | 19 | Result create(vk::Instance instance, bool validate); 20 | void destroy(); 21 | 22 | vk::PhysicalDevice& getVkPhysicalDevice(size_t index); 23 | vk::Device& getVkDevice(size_t index); 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /include/frame_buffer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include"device.h" 4 | #include"image.h" 5 | #include"render_pass.h" 6 | 7 | namespace simpleVulkan 8 | { 9 | class Framebuffer 10 | { 11 | vk::Device m_device; 12 | vk::Framebuffer m_framebuffer; 13 | public: 14 | Framebuffer(); 15 | ~Framebuffer(); 16 | 17 | virtual Result create( 18 | vk::Device device, 19 | uint32_t width, 20 | uint32_t height, 21 | vk::ImageView colorImageView, 22 | vk::ImageView depthImageView, 23 | vk::RenderPass renderPass); 24 | virtual void destroy(); 25 | 26 | vk::Framebuffer& getVkFrameBuffer(); 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /include/graphics_pipeline.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include"device.h" 4 | #include"shader.h" 5 | #include"render_pass.h" 6 | 7 | namespace simpleVulkan 8 | { 9 | class GraphicsPipeline 10 | { 11 | vk::Device m_device; 12 | vk::PipelineCache m_pipelineCache; 13 | vk::PipelineLayout m_pipelineLayout; 14 | vk::Pipeline m_pipeline; 15 | public: 16 | GraphicsPipeline(); 17 | ~GraphicsPipeline(); 18 | Result create( 19 | vk::Device device, 20 | vk::ShaderModule vertexShader, 21 | vk::ShaderModule fragmentShader, 22 | vk::DescriptorSetLayout setLayout, 23 | const std::vector& vertexBindings, 24 | const std::vector& vertexAttributes, 25 | vk::Viewport viewport, 26 | vk::Rect2D scissor, 27 | vk::RenderPass renderPass); 28 | void destroy(); 29 | 30 | vk::PipelineLayout& getVkPipelineLayout(); 31 | vk::Pipeline& getVkPipeline(); 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /include/image.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include"device.h" 4 | #include"swapchain.h" 5 | 6 | namespace simpleVulkan 7 | { 8 | class Image 9 | { 10 | vk::Device m_device; 11 | vk::DeviceMemory m_deviceMemory; 12 | vk::Image m_image; 13 | vk::ImageView m_imageView; 14 | 15 | vk::Format m_format; 16 | vk::ImageUsageFlags m_usage; 17 | int32_t m_width; 18 | int32_t m_height; 19 | public: 20 | Image(); 21 | ~Image(); 22 | 23 | Result create( 24 | vk::Device device, 25 | vk::Format format, 26 | vk::ImageUsageFlags usage, 27 | uint32_t width, 28 | uint32_t height); 29 | void destroy(); 30 | 31 | vk::Format getFormat(); 32 | int32_t getWidth(); 33 | int32_t getHeight(); 34 | 35 | vk::Image& getVkImage(); 36 | vk::ImageView& getVkImageView(); 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /include/instance.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | namespace simpleVulkan 10 | { 11 | using Result = vk::Result; 12 | class Instance 13 | { 14 | vk::Instance m_instance; 15 | public: 16 | Instance(); 17 | ~Instance(); 18 | 19 | Result create( 20 | std::string applicationName, 21 | std::uint32_t applicationVersion, 22 | std::string engineName, 23 | std::uint32_t engineVersion, 24 | const std::vector& extensions, 25 | const std::vector& layers); 26 | void destroy(); 27 | 28 | vk::Instance& getVkInstance(); 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /include/queue.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include"device.h" 6 | 7 | namespace simpleVulkan 8 | { 9 | class Queue 10 | { 11 | private: 12 | vk::Device m_device; 13 | vk::Queue m_queue; 14 | public: 15 | Queue(); 16 | ~Queue(); 17 | 18 | void init(vk::Device deivce); 19 | Result submit(vk::CommandBuffer cmdBuffer); 20 | Result submit(vk::CommandBuffer cmdBuffer,vk::Semaphore semaphore); 21 | Result wait(); 22 | Result present(vk::SwapchainKHR swapchain,uint32_t index); 23 | 24 | vk::Queue& getVkQueue(); 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /include/render_pass.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include"device.h" 4 | 5 | namespace simpleVulkan 6 | { 7 | class RenderPass 8 | { 9 | vk::Device m_device; 10 | vk::RenderPass m_renderPass; 11 | public: 12 | RenderPass(); 13 | ~RenderPass(); 14 | 15 | Result create(vk::Device device,vk::Format colorFormat,vk::Format depthFormat); 16 | void destroy(); 17 | 18 | vk::RenderPass& getVkRenderPass(); 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /include/shader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include"device.h" 4 | 5 | namespace simpleVulkan 6 | { 7 | class Shader 8 | { 9 | vk::Device m_device; 10 | vk::ShaderModule m_shaderModule; 11 | public: 12 | Shader(); 13 | ~Shader(); 14 | 15 | Result create(vk::Device device,size_t size,void* code); 16 | void destroy(); 17 | 18 | vk::ShaderModule& getVkShaderModule(); 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /include/simple_vulkan.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include"application.h" 3 | #include"instance.h" 4 | #include"device.h" 5 | #include"queue.h" 6 | #include"command_buffers.h" 7 | #include"swapchain.h" 8 | #include"image.h" 9 | #include"render_pass.h" 10 | #include"frame_buffer.h" 11 | #include"buffer.h" 12 | #include"descriptor_sets.h" 13 | #include"shader.h" 14 | #include"graphics_pipeline.h" 15 | #include"utility.h" 16 | -------------------------------------------------------------------------------- /include/swapchain.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include"device.h" 9 | 10 | namespace simpleVulkan 11 | { 12 | class Swapchain 13 | { 14 | vk::Device m_device; 15 | vk::ImageUsageFlags m_usage; 16 | vk::Format m_format; 17 | uint32_t m_width; 18 | uint32_t m_height; 19 | vk::SwapchainKHR m_swapchain; 20 | std::vector m_images; 21 | std::vector m_imageViews; 22 | public: 23 | Swapchain(); 24 | ~Swapchain(); 25 | 26 | Result create( 27 | vk::PhysicalDevice physicalDevice, 28 | vk::Device device, 29 | vk::SurfaceKHR& surface, 30 | vk::ImageUsageFlags usage, 31 | uint32_t width, 32 | uint32_t height); 33 | void destroy(); 34 | 35 | vk::ImageUsageFlags getUsage(); 36 | vk::Format getFormat(); 37 | uint32_t getWidth(); 38 | uint32_t getHeight(); 39 | size_t count(); 40 | 41 | vk::SwapchainKHR& getVkSwapchainKHR(); 42 | vk::Image& getVkImage(size_t index); 43 | vk::ImageView& getVkImageView(size_t index); 44 | }; 45 | } 46 | -------------------------------------------------------------------------------- /include/utility.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | bool readBinaryFile(const std::string& fileName,std::vector& result) 7 | { 8 | long int size; 9 | size_t retval; 10 | 11 | std::FILE *fp = std::fopen(fileName.c_str(), "rb"); 12 | if (!fp) return false; 13 | 14 | fseek(fp, 0L, SEEK_END); 15 | size = ftell(fp); 16 | 17 | fseek(fp, 0L, SEEK_SET); 18 | 19 | result.resize(size); 20 | retval = std::fread(result.data(), size, 1,fp); 21 | 22 | return true; 23 | } 24 | -------------------------------------------------------------------------------- /premake4.lua: -------------------------------------------------------------------------------- 1 | sources = { 2 | "src/*.cpp" 3 | , "src/application.cpp" 4 | , "src/buffer.cpp" 5 | , "src/command_buffers.cpp" 6 | , "src/descriptor_sets.cpp" 7 | , "src/device.cpp" 8 | , "src/frame_buffer.cpp" 9 | , "src/graphics_pipeline.cpp" 10 | , "src/image.cpp" 11 | , "src/instance.cpp" 12 | , "src/main.cpp" 13 | , "src/queue.cpp" 14 | , "src/render_pass.cpp" 15 | , "src/shader.cpp" 16 | , "src/swapchain.cpp" 17 | } 18 | 19 | solution "SimpleVulkanSolution" 20 | configurations { "Release", "Debug" } 21 | 22 | platforms { "x64", "x32" } 23 | 24 | -- A project defines one build target 25 | project "SimpleVulkan" 26 | kind "ConsoleApp" 27 | language "C++" 28 | 29 | files { sources } 30 | 31 | includedirs { 32 | "include/" 33 | } 34 | 35 | -- Windows general 36 | configuration { "windows" } 37 | defines { 'NOMINMAX', '_LARGEFILE_SOURCE', '_FILE_OFFSET_BITS=64' } 38 | defines { 'VKCPP_ENHANCED_MODE' } 39 | includedirs { "%VULKAN_SDK%/Include" } 40 | includedirs { "./deps/windows/glfw3/include" } 41 | includedirs { "./deps/vkcpp" } 42 | configuration { "x64" } 43 | libdirs { "%VULKAN_SDK%/Bin" } 44 | libdirs { "./deps/windows/glfw3/lib" } 45 | links { "glfw3", "vulkan-1" } 46 | 47 | 48 | -- Linux specific 49 | configuration {"linux", "gmake"} 50 | defines { '__STDC_CONSTANT_MACROS', '__STDC_LIMIT_MACROS' } -- c99 51 | links{"glfw3","vulkan","rt","m","dl","pthread","X11","Xrandr","Xinerama","Xxf86vm","Xcursor"} 52 | buildoptions {"-std=c++11"} 53 | linkoptions {"-std=c++11"} 54 | 55 | 56 | configuration "Debug" 57 | defines { "DEBUG" } -- -DDEBUG 58 | flags { "Symbols" } 59 | targetdir "bin/Debug" 60 | targetname "vulkan_test" 61 | 62 | configuration "Release" 63 | defines { "NDEBUG" } 64 | flags { "Symbols", "Optimize" } 65 | targetdir "bin/Release" 66 | targetname "vulkan_test" 67 | -------------------------------------------------------------------------------- /shader/triangle.frag: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | 5 | layout (location = 0) in vec4 inColor; 6 | 7 | layout (location = 0) out vec4 outColor; 8 | 9 | void main() 10 | { 11 | outColor = inColor;//vec4(1.0f,1.0f,0.0f,1.0f); 12 | } 13 | -------------------------------------------------------------------------------- /shader/triangle.vert: -------------------------------------------------------------------------------- 1 | #version 450 2 | #extension GL_ARB_separate_shader_objects : enable 3 | #extension GL_ARB_shading_language_420pack : enable 4 | 5 | layout (location = 0) in vec2 inPos; 6 | 7 | layout (location = 0) out vec4 outColor; 8 | 9 | out gl_PerVertex 10 | { 11 | vec4 gl_Position; 12 | }; 13 | 14 | layout (binding = 0) uniform Transfrom 15 | { 16 | mat2 matrix; 17 | } transform; 18 | 19 | void main() 20 | { 21 | gl_Position = vec4(transform.matrix * inPos,0.0f,1.0f); 22 | outColor = vec4(0.0f,1.0f,1.0f,1.0f); 23 | } 24 | -------------------------------------------------------------------------------- /src/application.cpp: -------------------------------------------------------------------------------- 1 | #include"application.h" 2 | #include 3 | #include 4 | #include 5 | 6 | namespace simpleVulkan 7 | { 8 | Application::Application() : m_validate(false) {} 9 | Application::~Application(){} 10 | bool Application::create(std::string windowName,uint32_t width,uint32_t height, bool validate) 11 | { 12 | m_width = width; 13 | m_height = height; 14 | m_validate = validate; 15 | 16 | glfwInit(); 17 | if(!glfwVulkanSupported()) 18 | { 19 | return false; 20 | } 21 | glfwWindowHint(GLFW_CLIENT_API,GLFW_NO_API); 22 | m_window = glfwCreateWindow(m_width,m_height,"test_vulkan",nullptr,nullptr); 23 | unsigned int glfwExtensionsCount; 24 | const char** glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionsCount); 25 | std::vector extensions(glfwExtensionsCount); 26 | for(size_t i=0;i> i) & 1) 49 | { 50 | std::cout << (uint32_t)memoryProperties.memoryTypes()[i].propertyFlags() << std::endl; 51 | if(memoryProperties.memoryTypes()[i].propertyFlags() & vk::MemoryPropertyFlagBits::eHostVisible) 52 | { 53 | memoryTypeIndex = i; 54 | break; 55 | } 56 | } 57 | } 58 | 59 | //init MemoryAllocateInfo 60 | vk::MemoryAllocateInfo memoryInfo; 61 | memoryInfo.memoryTypeIndex(memoryTypeIndex); 62 | memoryInfo.allocationSize(req.size()); 63 | 64 | //allocate VertexMemory 65 | result = m_device.allocateMemory(&memoryInfo,nullptr,&m_memory); 66 | if(result != vk::Result::eSuccess) 67 | { 68 | return result; 69 | } 70 | 71 | //bind VertexMemory to VertexBuffer 72 | #ifdef VKCPP_ENHANCED_MODE 73 | m_device.bindBufferMemory(m_buffer,m_memory,0); 74 | #else 75 | result = m_device.bindBufferMemory(m_buffer,m_memory,0); 76 | #endif 77 | return result; 78 | } 79 | 80 | void Buffer::destroy() 81 | { 82 | m_device.freeMemory(m_memory,nullptr); 83 | m_device.destroyBuffer(m_buffer,nullptr); 84 | } 85 | 86 | void Buffer::write(const void* pData) 87 | { 88 | vk::Result result; 89 | 90 | void* mappedMemory = nullptr; 91 | 92 | #ifdef VKCPP_ENHANCED_MODE 93 | mappedMemory = m_device.mapMemory(m_memory,0,m_size,vk::MemoryMapFlagBits()); 94 | #else 95 | result = m_device.mapMemory(m_memory,0,m_size,vk::MemoryMapFlagBits(),&mappedMemory); 96 | #endif 97 | //copy Vertexes 98 | memcpy(mappedMemory,pData,m_size); 99 | 100 | //unmap VertexMemory 101 | m_device.unmapMemory(m_memory); 102 | 103 | } 104 | 105 | size_t Buffer::getSize() 106 | { 107 | return m_size; 108 | } 109 | 110 | vk::Buffer& Buffer::getVkBuffer() 111 | { 112 | return m_buffer; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/command_buffers.cpp: -------------------------------------------------------------------------------- 1 | #include"command_buffers.h" 2 | 3 | #include 4 | 5 | namespace simpleVulkan 6 | { 7 | CommandBuffers::CommandBuffers() 8 | { 9 | } 10 | 11 | CommandBuffers::~CommandBuffers(){} 12 | 13 | Result CommandBuffers::create(vk::Device device,size_t count) 14 | { 15 | vk::Result result; 16 | m_device = device; 17 | //init CommandPoolCreateInfo 18 | vk::CommandPoolCreateInfo cmdPoolInfo; 19 | cmdPoolInfo.queueFamilyIndex(0); 20 | cmdPoolInfo.flags(vk::CommandPoolCreateFlagBits::eResetCommandBuffer); 21 | 22 | //create CommandPool 23 | result = m_device.createCommandPool(&cmdPoolInfo,nullptr,&m_cmdPool); 24 | if(result != vk::Result::eSuccess) 25 | { 26 | return result; 27 | } 28 | 29 | //init CommandBufferAllocateInfo 30 | vk::CommandBufferAllocateInfo cmdBufAllocateInfo; 31 | cmdBufAllocateInfo.commandPool(m_cmdPool); 32 | cmdBufAllocateInfo.level(vk::CommandBufferLevel::ePrimary); 33 | cmdBufAllocateInfo.commandBufferCount(count); 34 | 35 | m_cmdBuffers.resize(count); 36 | //allocate CommandBuffer 37 | result = m_device.allocateCommandBuffers(&cmdBufAllocateInfo,m_cmdBuffers.data()); 38 | return result; 39 | } 40 | 41 | void CommandBuffers::destroy() 42 | { 43 | m_device.destroyCommandPool(m_cmdPool,nullptr);; 44 | } 45 | 46 | vk::CommandPool& CommandBuffers::getVkCommandPool() 47 | { 48 | return m_cmdPool; 49 | } 50 | vk::CommandBuffer& CommandBuffers::getVkCommandBuffer(size_t index) 51 | { 52 | return m_cmdBuffers[index]; 53 | } 54 | const std::vector& CommandBuffers::getVkCommandBuffers() 55 | { 56 | return m_cmdBuffers; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/descriptor_sets.cpp: -------------------------------------------------------------------------------- 1 | #include"descriptor_sets.h" 2 | 3 | namespace simpleVulkan 4 | { 5 | DescriptorSets::DescriptorSets() 6 | { 7 | } 8 | DescriptorSets::~DescriptorSets() 9 | { 10 | } 11 | 12 | Result DescriptorSets::create( 13 | vk::Device device, 14 | const std::vector& descriptorBindings, 15 | uint32_t setsCount) 16 | { 17 | vk::Result result; 18 | 19 | m_device = device; 20 | 21 | //init DescriptorSetLayoutCreateInfo 22 | vk::DescriptorSetLayoutCreateInfo layoutInfo; 23 | layoutInfo.bindingCount(descriptorBindings.size()); 24 | layoutInfo.pBindings(descriptorBindings.data()); 25 | 26 | //create DescriptorSetLayout 27 | result = m_device.createDescriptorSetLayout(&layoutInfo,nullptr,&m_descriptorSetLayout); 28 | if(result != vk::Result::eSuccess) 29 | { 30 | return result; 31 | } 32 | 33 | //init DescriptroPoolSizes 34 | std::vector poolSizes(descriptorBindings.size()); 35 | for(size_t i=0;i 4 | 5 | namespace simpleVulkan 6 | { 7 | Device::Device(){} 8 | Device::~Device(){} 9 | 10 | Result Device::create(vk::Instance instance, bool validate) 11 | { 12 | vk::Result result; 13 | //get PhysicalDevices 14 | uint32_t physDevicesNum = 0; 15 | result = instance.enumeratePhysicalDevices(&physDevicesNum,nullptr); 16 | if(result != vk::Result::eSuccess) 17 | { 18 | return result; 19 | } 20 | m_physicalDevices.resize(physDevicesNum); 21 | result = instance.enumeratePhysicalDevices( 22 | &physDevicesNum, 23 | m_physicalDevices.data()); 24 | 25 | if(result != vk::Result::eSuccess) 26 | { 27 | return result; 28 | } 29 | 30 | //create Devices 31 | m_devices.resize(m_physicalDevices.size()); 32 | for(size_t deviceIndex=0;deviceIndex queueFamilyProperties(queueFamilyPropertiesCount); 39 | m_physicalDevices[deviceIndex].getQueueFamilyProperties(&queueFamilyPropertiesCount, queueFamilyProperties.data()); 40 | 41 | uint32_t familyIndex; 42 | for (int i =0; i < queueFamilyProperties.size(); ++i) 43 | { 44 | if (queueFamilyProperties[i].queueFlags() & vk::QueueFlagBits::eGraphics) 45 | { 46 | familyIndex = i; 47 | break; 48 | } 49 | } 50 | //init DeviceQueueInfo 51 | vk::DeviceQueueCreateInfo queueInfo; 52 | float queueProperties {0.0f}; 53 | queueInfo.queueFamilyIndex(familyIndex); 54 | queueInfo.queueCount(1); 55 | queueInfo.pQueuePriorities(&queueProperties); 56 | 57 | //init DeviceCreateInfo 58 | vk::DeviceCreateInfo deviceInfo; 59 | deviceInfo.queueCreateInfoCount(1); 60 | deviceInfo.pQueueCreateInfos(&queueInfo); 61 | 62 | std::vector layers; 63 | std::vector extensions; 64 | 65 | extensions.push_back("VK_KHR_swapchain"); 66 | deviceInfo.enabledExtensionCount(extensions.size()); 67 | deviceInfo.ppEnabledExtensionNames(extensions.data()); 68 | 69 | 70 | if (validate) 71 | { 72 | layers.push_back("VK_LAYER_LUNARG_standard_validation"); 73 | } 74 | 75 | deviceInfo.enabledLayerCount(layers.size()); 76 | deviceInfo.ppEnabledLayerNames(layers.data()); 77 | 78 | //create Device 79 | result = m_physicalDevices[deviceIndex].createDevice(&deviceInfo,nullptr,&m_devices[deviceIndex]); 80 | } 81 | return result; 82 | } 83 | 84 | void Device::destroy() 85 | { 86 | for(vk::Device& device:m_devices) 87 | { 88 | device.destroy(nullptr); 89 | } 90 | } 91 | 92 | vk::PhysicalDevice& Device::getVkPhysicalDevice(size_t index) 93 | { 94 | return m_physicalDevices[index]; 95 | } 96 | vk::Device& Device::getVkDevice(size_t index) 97 | { 98 | return m_devices[index]; 99 | } 100 | 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/frame_buffer.cpp: -------------------------------------------------------------------------------- 1 | #include"frame_buffer.h" 2 | #include"image.h" 3 | #include"render_pass.h" 4 | 5 | namespace simpleVulkan 6 | { 7 | Framebuffer::Framebuffer() 8 | { 9 | } 10 | 11 | Framebuffer::~Framebuffer() 12 | { 13 | } 14 | 15 | Result Framebuffer::create( 16 | vk::Device device, 17 | uint32_t width, 18 | uint32_t height, 19 | vk::ImageView colorImageView, 20 | vk::ImageView depthImageView, 21 | vk::RenderPass renderPass) 22 | { 23 | m_device = device; 24 | vk::Result result; 25 | vk::ImageView attachments[2]; 26 | attachments[0] = colorImageView; 27 | attachments[1] = depthImageView; 28 | 29 | //init FramebufferCreateInfo 30 | vk::FramebufferCreateInfo framebufferInfo; 31 | framebufferInfo.flags(vk::FramebufferCreateFlagBits()); 32 | framebufferInfo.renderPass(renderPass); 33 | framebufferInfo.attachmentCount(2); 34 | framebufferInfo.pAttachments(attachments); 35 | framebufferInfo.width(width); 36 | framebufferInfo.height(height); 37 | framebufferInfo.layers(1); 38 | 39 | //create Framebuffer 40 | result = m_device.createFramebuffer(&framebufferInfo,nullptr,&m_framebuffer); 41 | return result; 42 | } 43 | 44 | void Framebuffer::destroy() 45 | { 46 | m_device.destroyFramebuffer(m_framebuffer,nullptr); 47 | } 48 | 49 | vk::Framebuffer& Framebuffer::getVkFrameBuffer() 50 | { 51 | return m_framebuffer; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/graphics_pipeline.cpp: -------------------------------------------------------------------------------- 1 | #include"graphics_pipeline.h" 2 | 3 | namespace simpleVulkan 4 | { 5 | GraphicsPipeline::GraphicsPipeline() 6 | { 7 | } 8 | 9 | GraphicsPipeline::~GraphicsPipeline() 10 | { 11 | } 12 | 13 | Result GraphicsPipeline::create( 14 | vk::Device device, 15 | vk::ShaderModule vertexShader, 16 | vk::ShaderModule fragmentShader, 17 | vk::DescriptorSetLayout setLayout, 18 | const std::vector& vertexBindings, 19 | const std::vector& vertexAttributes, 20 | vk::Viewport viewport, 21 | vk::Rect2D scissor, 22 | vk::RenderPass renderPass) 23 | { 24 | vk::Result result; 25 | 26 | m_device = device; 27 | 28 | 29 | //init PipelineCacheCreateInfo 30 | vk::PipelineCacheCreateInfo cacheInfo; 31 | cacheInfo.flags(vk::PipelineCacheCreateFlagBits()); 32 | cacheInfo.initialDataSize(0); 33 | cacheInfo.pInitialData(nullptr); 34 | 35 | //create PipelineCache 36 | result = m_device.createPipelineCache( 37 | &cacheInfo, 38 | nullptr, 39 | &m_pipelineCache); 40 | if(result != vk::Result::eSuccess) 41 | { 42 | return result; 43 | } 44 | 45 | //init PipelineShaderStageCreateInfo 46 | vk::PipelineShaderStageCreateInfo stageInfos[2]; 47 | stageInfos[0].flags(vk::PipelineShaderStageCreateFlagBits()); 48 | stageInfos[0].stage(vk::ShaderStageFlagBits::eVertex); 49 | stageInfos[0].module(vertexShader); 50 | stageInfos[0].pName("main"); 51 | stageInfos[0].pSpecializationInfo(nullptr); 52 | stageInfos[1].flags(vk::PipelineShaderStageCreateFlagBits()); 53 | stageInfos[1].stage(vk::ShaderStageFlagBits::eFragment); 54 | stageInfos[1].module(fragmentShader); 55 | stageInfos[1].pName("main"); 56 | stageInfos[1].pSpecializationInfo(nullptr); 57 | 58 | //init PipelineLayoutCreateInfo 59 | vk::PipelineLayoutCreateInfo layoutInfo; 60 | layoutInfo.pushConstantRangeCount(0); 61 | layoutInfo.pPushConstantRanges(nullptr); 62 | layoutInfo.setLayoutCount(1); 63 | layoutInfo.pSetLayouts(&setLayout); 64 | 65 | result = m_device.createPipelineLayout( 66 | &layoutInfo, 67 | nullptr, 68 | &m_pipelineLayout); 69 | if(result != vk::Result::eSuccess) 70 | { 71 | return result; 72 | } 73 | 74 | //init VertexInputStateCreateInfo 75 | vk::PipelineVertexInputStateCreateInfo vertexInputInfo; 76 | vertexInputInfo.flags(vk::PipelineVertexInputStateCreateFlagBits()); 77 | vertexInputInfo.vertexBindingDescriptionCount(vertexBindings.size()); 78 | vertexInputInfo.pVertexBindingDescriptions(vertexBindings.data()); 79 | vertexInputInfo.vertexAttributeDescriptionCount(vertexAttributes.size()); 80 | vertexInputInfo.pVertexAttributeDescriptions(vertexAttributes.data()); 81 | 82 | //init PipelineInputAssemblyStateCreateInfo 83 | vk::PipelineInputAssemblyStateCreateInfo inputAssemblyInfo; 84 | inputAssemblyInfo.flags(vk::PipelineInputAssemblyStateCreateFlagBits()); 85 | inputAssemblyInfo.topology(vk::PrimitiveTopology::eTriangleList); 86 | inputAssemblyInfo.primitiveRestartEnable(false); 87 | 88 | //init PipelineViewportStateCreateInfo 89 | vk::PipelineViewportStateCreateInfo viewportInfo; 90 | viewportInfo.flags(vk::PipelineViewportStateCreateFlagBits()); 91 | viewportInfo.viewportCount(1); 92 | viewportInfo.pViewports(&viewport); 93 | viewportInfo.scissorCount(1); 94 | viewportInfo.pScissors(&scissor); 95 | 96 | //init PipelineRasterizationStateCreateInfo 97 | vk::PipelineRasterizationStateCreateInfo rasterizationInfo; 98 | rasterizationInfo.flags(vk::PipelineRasterizationStateCreateFlagBits()); 99 | rasterizationInfo.depthClampEnable(false); 100 | rasterizationInfo.rasterizerDiscardEnable(false); 101 | rasterizationInfo.polygonMode(vk::PolygonMode::eFill); 102 | rasterizationInfo.cullMode(vk::CullModeFlagBits::eNone); 103 | rasterizationInfo.frontFace(vk::FrontFace::eCounterClockwise); 104 | rasterizationInfo.depthBiasEnable(false); 105 | rasterizationInfo.depthBiasConstantFactor(0.0f); 106 | rasterizationInfo.depthBiasClamp(0.0f); 107 | rasterizationInfo.depthBiasSlopeFactor(0.0f); 108 | rasterizationInfo.lineWidth(1.0f); 109 | 110 | //init PipelineMultisampleStateCreateInfo 111 | vk::PipelineMultisampleStateCreateInfo multisampleInfo; 112 | multisampleInfo.flags(vk::PipelineMultisampleStateCreateFlagBits()); 113 | multisampleInfo.rasterizationSamples(vk::SampleCountFlagBits::e1); 114 | multisampleInfo.sampleShadingEnable(false); 115 | multisampleInfo.minSampleShading(0.0f); 116 | multisampleInfo.pSampleMask(nullptr); 117 | multisampleInfo.alphaToCoverageEnable(false); 118 | multisampleInfo.alphaToOneEnable(false); 119 | 120 | //init StencilOpState 121 | vk::StencilOpState stencilState; 122 | stencilState.failOp(vk::StencilOp::eKeep); 123 | stencilState.passOp(vk::StencilOp::eKeep); 124 | stencilState.depthFailOp(vk::StencilOp::eKeep); 125 | stencilState.compareOp(vk::CompareOp::eNever); 126 | stencilState.compareMask(0); 127 | stencilState.writeMask(0); 128 | stencilState.reference(0); 129 | 130 | //init PipelineDepthStencilStateCreateInfo 131 | vk::PipelineDepthStencilStateCreateInfo depthInfo; 132 | depthInfo.flags(vk::PipelineDepthStencilStateCreateFlagBits()); 133 | depthInfo.depthTestEnable(true); //debug 134 | depthInfo.depthWriteEnable(true); 135 | depthInfo.depthCompareOp(vk::CompareOp::eLessOrEqual); 136 | depthInfo.depthBoundsTestEnable(false); 137 | depthInfo.stencilTestEnable(false); 138 | depthInfo.front(stencilState); 139 | depthInfo.back(stencilState); 140 | depthInfo.minDepthBounds(0.0f); 141 | depthInfo.maxDepthBounds(0.0f); 142 | 143 | //init PipelineColorBlendAttachmentState 144 | vk::PipelineColorBlendAttachmentState blendState; 145 | blendState.blendEnable(false); 146 | blendState.srcColorBlendFactor(vk::BlendFactor::eZero); 147 | blendState.dstColorBlendFactor(vk::BlendFactor::eZero); 148 | blendState.colorBlendOp(vk::BlendOp::eAdd); 149 | blendState.srcAlphaBlendFactor(vk::BlendFactor::eZero); 150 | blendState.dstAlphaBlendFactor(vk::BlendFactor::eZero); 151 | blendState.alphaBlendOp(vk::BlendOp::eAdd); 152 | blendState.colorWriteMask( 153 | vk::ColorComponentFlagBits::eR | 154 | vk::ColorComponentFlagBits::eG | 155 | vk::ColorComponentFlagBits::eB | 156 | vk::ColorComponentFlagBits::eA ); 157 | 158 | //init PipelineColorBlendStateCreateInfo 159 | vk::PipelineColorBlendStateCreateInfo blendInfo; 160 | blendInfo.flags(vk::PipelineColorBlendStateCreateFlagBits()); 161 | blendInfo.logicOpEnable(false); 162 | blendInfo.logicOp(vk::LogicOp::eClear); 163 | blendInfo.attachmentCount(1); 164 | blendInfo.pAttachments(&blendState); 165 | blendInfo.blendConstants(std::array{0.0f,0.0f,0.0f,0.0f}); 166 | 167 | //init GraphicPipelineCreateInfo 168 | vk::GraphicsPipelineCreateInfo pipelineInfo; 169 | pipelineInfo.flags(vk::PipelineCreateFlagBits()); 170 | pipelineInfo.stageCount(2); 171 | pipelineInfo.pStages(stageInfos); 172 | pipelineInfo.pVertexInputState(&vertexInputInfo); 173 | pipelineInfo.pInputAssemblyState(&inputAssemblyInfo); 174 | pipelineInfo.pTessellationState(nullptr); 175 | pipelineInfo.pViewportState(&viewportInfo); 176 | pipelineInfo.pRasterizationState(&rasterizationInfo); 177 | pipelineInfo.pMultisampleState(&multisampleInfo); 178 | pipelineInfo.pDepthStencilState(&depthInfo); 179 | pipelineInfo.pColorBlendState(&blendInfo); 180 | pipelineInfo.pDynamicState(nullptr); 181 | pipelineInfo.layout(m_pipelineLayout); 182 | pipelineInfo.renderPass(renderPass); 183 | pipelineInfo.subpass(0); 184 | pipelineInfo.basePipelineHandle(vk::Pipeline()); 185 | pipelineInfo.basePipelineIndex(0); 186 | 187 | //create GraphicPipeline 188 | result = m_device.createGraphicsPipelines( 189 | m_pipelineCache, 190 | 1, 191 | &pipelineInfo, 192 | nullptr, 193 | &m_pipeline); 194 | return result; 195 | } 196 | 197 | void GraphicsPipeline::destroy() 198 | { 199 | m_device.destroyPipeline(m_pipeline,nullptr); 200 | m_device.destroyPipelineLayout(m_pipelineLayout,nullptr); 201 | m_device.destroyPipelineCache(m_pipelineCache,nullptr); 202 | } 203 | 204 | vk::PipelineLayout& GraphicsPipeline::getVkPipelineLayout() 205 | { 206 | return m_pipelineLayout; 207 | } 208 | 209 | vk::Pipeline& GraphicsPipeline::getVkPipeline() 210 | { 211 | return m_pipeline; 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/image.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace simpleVulkan 5 | { 6 | Image::Image() 7 | {} 8 | 9 | Image::~Image(){} 10 | 11 | Result Image::create( 12 | vk::Device device, 13 | vk::Format format, 14 | vk::ImageUsageFlags usage, 15 | uint32_t width, 16 | uint32_t height) 17 | { 18 | m_device = device; 19 | m_format = format; 20 | m_usage = usage; 21 | m_width = width; 22 | m_height = height; 23 | 24 | vk::Result result; 25 | 26 | //init ImageCreateInfo 27 | vk::ImageCreateInfo imageInfo; 28 | imageInfo.imageType(vk::ImageType::e2D); 29 | imageInfo.format(m_format); 30 | imageInfo.extent().width(m_width); 31 | imageInfo.extent().height(m_height); 32 | imageInfo.extent().depth(1); 33 | imageInfo.mipLevels(1); 34 | imageInfo.arrayLayers(1); 35 | imageInfo.samples(vk::SampleCountFlagBits::e1); 36 | imageInfo.tiling(vk::ImageTiling::eLinear); 37 | imageInfo.usage(m_usage); 38 | imageInfo.sharingMode(vk::SharingMode::eExclusive); 39 | imageInfo.queueFamilyIndexCount(0); 40 | imageInfo.pQueueFamilyIndices(nullptr); 41 | imageInfo.initialLayout(vk::ImageLayout::eUndefined); 42 | 43 | //create DepthImage 44 | result = m_device.createImage(&imageInfo,nullptr,&m_image); 45 | 46 | //init MemoryAlloateInfo 47 | vk::MemoryRequirements req; 48 | m_device.getImageMemoryRequirements(m_image,&req); 49 | vk::MemoryAllocateInfo allocInfo; 50 | allocInfo.allocationSize(req.size()); 51 | allocInfo.memoryTypeIndex(1); //maybe 52 | 53 | //alloc DepthMemory 54 | result = m_device.allocateMemory(&allocInfo,nullptr,&m_deviceMemory); 55 | 56 | //bind Image 57 | m_device.bindImageMemory(m_image,m_deviceMemory,0); 58 | 59 | vk::ImageAspectFlags aspect; 60 | if(m_usage & vk::ImageUsageFlagBits::eColorAttachment) 61 | { 62 | aspect |= vk::ImageAspectFlagBits::eColor; 63 | } 64 | if(m_usage & vk::ImageUsageFlagBits::eDepthStencilAttachment) 65 | { 66 | aspect |= vk::ImageAspectFlagBits::eDepth; 67 | } 68 | 69 | //init ImageViewCreateInfo 70 | vk::ImageViewCreateInfo imageViewInfo; 71 | imageViewInfo.flags(vk::ImageViewCreateFlagBits()); 72 | imageViewInfo.image(m_image); 73 | imageViewInfo.format(m_format); 74 | imageViewInfo.components().r(vk::ComponentSwizzle::eR); 75 | imageViewInfo.components().g(vk::ComponentSwizzle::eG); 76 | imageViewInfo.components().b(vk::ComponentSwizzle::eB); 77 | imageViewInfo.components().a(vk::ComponentSwizzle::eA); 78 | imageViewInfo.subresourceRange().aspectMask(aspect); 79 | imageViewInfo.subresourceRange().baseMipLevel(0); 80 | imageViewInfo.subresourceRange().levelCount(1); 81 | imageViewInfo.subresourceRange().baseArrayLayer(0); 82 | imageViewInfo.subresourceRange().layerCount(1); 83 | imageViewInfo.viewType(vk::ImageViewType::e2D); 84 | 85 | //create ImageView 86 | result = m_device.createImageView(&imageViewInfo,nullptr,&m_imageView); 87 | return result; 88 | } 89 | 90 | void Image::destroy() 91 | { 92 | m_device.destroyImageView(m_imageView,nullptr); 93 | m_device.freeMemory(m_deviceMemory,nullptr); 94 | m_device.destroyImage(m_image,nullptr); 95 | } 96 | 97 | vk::Image& Image::getVkImage() 98 | { 99 | return m_image; 100 | } 101 | vk::ImageView& Image::getVkImageView() 102 | { 103 | return m_imageView; 104 | } 105 | int32_t Image::getWidth() 106 | { 107 | return m_width; 108 | } 109 | int32_t Image::getHeight() 110 | { 111 | return m_height; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/instance.cpp: -------------------------------------------------------------------------------- 1 | #include"instance.h" 2 | 3 | #ifndef VK_API_VERSION 4 | #define VK_API_VERSION VK_API_VERSION_1_0 5 | #endif 6 | 7 | namespace simpleVulkan 8 | { 9 | Instance::Instance(){} 10 | Instance::~Instance(){} 11 | 12 | Result Instance::create( 13 | std::string applicationName, 14 | std::uint32_t applicationVersion, 15 | std::string engineName, 16 | std::uint32_t engineVersion, 17 | const std::vector& extensions, 18 | const std::vector& layers) 19 | { 20 | vk::Result result; 21 | 22 | //init ApplicationInfo 23 | vk::ApplicationInfo appInfo; 24 | appInfo.pApplicationName(applicationName.c_str()); 25 | appInfo.applicationVersion(applicationVersion); 26 | appInfo.pEngineName(engineName.c_str()); 27 | appInfo.engineVersion(engineVersion); 28 | appInfo.apiVersion(VK_API_VERSION); 29 | 30 | //std::vector layers; 31 | //layers.push_back("VK_LAYER_LUNARG_param_checker"); 32 | //layers.push_back("VK_LAYER_LUNARG_swapchain"); 33 | //layers.push_back("VK_LAYER_LUNARG_mem_tracker"); 34 | //layers.push_back("VK_LAYER_GOOGLE_unique_objects"); 35 | //deviceInfo.enabledLayerCount(layers.size()); 36 | //deviceInfo.ppEnabledLayerNames(layers.data()); 37 | 38 | //init InstanceCreateInfo 39 | vk::InstanceCreateInfo instInfo; 40 | instInfo.pApplicationInfo(&appInfo); 41 | instInfo.enabledExtensionCount(extensions.size()); 42 | instInfo.ppEnabledExtensionNames(extensions.data()); 43 | instInfo.enabledLayerCount(layers.size()); 44 | instInfo.ppEnabledLayerNames(layers.data()); 45 | 46 | //create Instance 47 | result = vk::createInstance(&instInfo,nullptr,&m_instance); 48 | 49 | return result; 50 | } 51 | 52 | void Instance::destroy() 53 | { 54 | m_instance.destroy(nullptr); 55 | } 56 | 57 | vk::Instance& Instance::getVkInstance() 58 | { 59 | return m_instance; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include"simple_vulkan.h" 10 | 11 | #define ENABLE_VALIDATION (1) 12 | 13 | #if ENABLE_VALIDATION 14 | VKAPI_ATTR VkBool32 VKAPI_CALL MyDebugReportCallback( 15 | VkDebugReportFlagsEXT flags, 16 | VkDebugReportObjectTypeEXT objectType, 17 | uint64_t object, 18 | size_t location, 19 | int32_t messageCode, 20 | const char* pLayerPrefix, 21 | const char* pMessage, 22 | void* pUserData) 23 | { 24 | std::cerr << pMessage << std::endl; 25 | return VK_FALSE; 26 | } 27 | #endif 28 | 29 | class TestApplication : public simpleVulkan::Application 30 | { 31 | vk::Format m_colorFormat; 32 | vk::Format m_depthFormat = vk::Format::eD24UnormS8Uint; 33 | 34 | float m_vertexes[3][2]; 35 | float m_matrix[2][4]; 36 | 37 | //= { 38 | // {1.0f,0.0f,0.0f,0.0f}, 39 | // {0.0f,1.0f,0.0f,0.0f} 40 | //}; 41 | 42 | const std::string m_vertexShaderName = "./vert.spv"; 43 | const std::string m_fragShaderName = "./frag.spv"; 44 | 45 | simpleVulkan::Instance* m_instance; 46 | simpleVulkan::Device* m_device; 47 | simpleVulkan::Queue* m_queue; 48 | simpleVulkan::CommandBuffers* m_cmdBuf; 49 | simpleVulkan::Swapchain* m_swapchain; 50 | simpleVulkan::Image* m_depthImage; 51 | simpleVulkan::RenderPass* m_renderPass; 52 | std::vector m_FrameBuffers; 53 | simpleVulkan::Buffer* m_vertexBuffer; 54 | simpleVulkan::Buffer* m_matrixBuffer; 55 | simpleVulkan::DescriptorSets* m_descriptorSets; 56 | simpleVulkan::Shader* m_vertexShader; 57 | simpleVulkan::Shader* m_fragmentShader; 58 | simpleVulkan::GraphicsPipeline* m_pipeline; 59 | 60 | VkSemaphore a; 61 | vk::SurfaceKHR m_windowSurface; 62 | vk::Semaphore m_semaphore; 63 | vk::Viewport m_viewport; 64 | vk::Rect2D m_scissor; 65 | 66 | 67 | uint32_t m_bufferIndex; 68 | uint32_t m_count; 69 | 70 | public: 71 | using simpleVulkan::Application::Application; 72 | private: 73 | 74 | virtual bool initialize( 75 | const std::vector& glfwExtensions, 76 | GLFWwindow* window) override 77 | { 78 | 79 | m_vertexes[0][0] = 0.0f; 80 | m_vertexes[0][1] = 1.0f; 81 | m_vertexes[1][0] = 0.86f; 82 | m_vertexes[1][1] = -0.5f; 83 | m_vertexes[2][0] = -0.86f; 84 | m_vertexes[2][1] = -0.5f; 85 | 86 | 87 | setInterval(std::chrono::milliseconds(10)); 88 | vk::Result result; 89 | 90 | std::vector layers; 91 | 92 | if (getValidateFlag()) 93 | { 94 | layers.push_back("VK_LAYER_LUNARG_standard_validation"); 95 | } 96 | 97 | m_instance = new simpleVulkan::Instance(); 98 | vk::Result ret = m_instance->create("testApp", 1, "testEngine", 1, glfwExtensions, layers); 99 | if (ret != vk::Result::eSuccess) { 100 | std::cerr << "failed to create instance!" << std::endl; 101 | exit(-1); 102 | } 103 | 104 | if (getValidateFlag()) 105 | { 106 | vk::DebugReportCallbackCreateInfoEXT callbackInfo( 107 | vk::DebugReportFlagBitsEXT::eWarning | vk::DebugReportFlagBitsEXT::eError | vk::DebugReportFlagBitsEXT::eDebug, 108 | MyDebugReportCallback, nullptr); 109 | 110 | // @todo { acquire proc address somewhewre, not here. } 111 | { 112 | VkInstance instance = (m_instance->getVkInstance()); 113 | /* Load VK_EXT_debug_report entry points in debug builds */ 114 | PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = 115 | reinterpret_cast 116 | (vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT")); 117 | PFN_vkDebugReportMessageEXT vkDebugReportMessageEXT = 118 | reinterpret_cast 119 | (vkGetInstanceProcAddr(instance, "vkDebugReportMessageEXT")); 120 | PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = 121 | reinterpret_cast 122 | (vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT")); 123 | 124 | /* Setup callback creation information */ 125 | VkDebugReportCallbackCreateInfoEXT callbackCreateInfo; 126 | callbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; 127 | callbackCreateInfo.pNext = nullptr; 128 | callbackCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | 129 | VK_DEBUG_REPORT_WARNING_BIT_EXT | 130 | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; 131 | callbackCreateInfo.pfnCallback = &MyDebugReportCallback; 132 | callbackCreateInfo.pUserData = nullptr; 133 | 134 | /* Register the callback */ 135 | VkDebugReportCallbackEXT callback; 136 | VkResult result = vkCreateDebugReportCallbackEXT(instance, &callbackCreateInfo, nullptr, &callback); 137 | if (result != VK_SUCCESS) { 138 | std::cerr << "failed to create debug report callback!" << std::endl; 139 | exit(-1); 140 | } 141 | } 142 | } 143 | 144 | m_device = new simpleVulkan::Device(); 145 | m_device->create(m_instance->getVkInstance(), getValidateFlag()); 146 | 147 | m_queue = new simpleVulkan::Queue(); 148 | m_queue->init(m_device->getVkDevice(0)); 149 | 150 | m_cmdBuf = new simpleVulkan::CommandBuffers(); 151 | m_cmdBuf->create(m_device->getVkDevice(0), 2); 152 | { 153 | //init CommandBufferInheritanceInfo 154 | vk::CommandBufferInheritanceInfo cmdBufInheritanceInfo; 155 | 156 | //init CommandBufferBeginInfo 157 | vk::CommandBufferBeginInfo cmdBufBeginInfo; 158 | cmdBufBeginInfo.pInheritanceInfo(&cmdBufInheritanceInfo); 159 | 160 | //begin CommandBuffer 161 | result = m_cmdBuf->getVkCommandBuffer(0).begin(&cmdBufBeginInfo); 162 | } 163 | 164 | //get WindowSurface 165 | glfwCreateWindowSurface(static_cast(m_instance->getVkInstance()), window, nullptr, reinterpret_cast(&m_windowSurface)); 166 | 167 | m_swapchain = new simpleVulkan::Swapchain(); 168 | m_swapchain->create(m_device->getVkPhysicalDevice(0), m_device->getVkDevice(0), m_windowSurface, vk::ImageUsageFlagBits::eColorAttachment, getWidth(), getHeight()); 169 | m_colorFormat = m_swapchain->getFormat(); 170 | 171 | for (int i = 0; i < m_swapchain->count(); ++i) 172 | { 173 | //init ImageMemoryBarrier 174 | vk::ImageMemoryBarrier barrier; 175 | barrier.srcAccessMask(vk::AccessFlagBits()); 176 | barrier.dstAccessMask(vk::AccessFlagBits::eMemoryRead); 177 | barrier.oldLayout(vk::ImageLayout::eUndefined); 178 | barrier.newLayout(vk::ImageLayout::ePresentSrcKHR); 179 | barrier.image(m_swapchain->getVkImage(i)); 180 | barrier.subresourceRange().aspectMask(vk::ImageAspectFlagBits::eColor); 181 | barrier.subresourceRange().baseMipLevel(0); 182 | barrier.subresourceRange().levelCount(1); 183 | barrier.subresourceRange().baseArrayLayer(0); 184 | barrier.subresourceRange().layerCount(1); 185 | 186 | //layout SwapchainImage 187 | m_cmdBuf->getVkCommandBuffer(0).pipelineBarrier( 188 | vk::PipelineStageFlagBits::eTopOfPipe, 189 | vk::PipelineStageFlagBits::eTopOfPipe, 190 | vk::DependencyFlagBits(), 191 | 0, 192 | nullptr, 193 | 0, 194 | nullptr, 195 | 1, 196 | &barrier); 197 | } 198 | 199 | m_depthImage = new simpleVulkan::Image(); 200 | m_depthImage->create( 201 | m_device->getVkDevice(0), 202 | m_depthFormat, 203 | vk::ImageUsageFlagBits::eDepthStencilAttachment, 204 | getWidth(), 205 | getHeight()); 206 | 207 | //init ImageMemoryBarrier 208 | vk::ImageMemoryBarrier barrier; 209 | barrier.srcAccessMask(vk::AccessFlagBits()); 210 | barrier.dstAccessMask(vk::AccessFlagBits::eDepthStencilAttachmentRead); 211 | barrier.oldLayout(vk::ImageLayout::eUndefined); 212 | barrier.newLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal); 213 | barrier.image(m_depthImage->getVkImage()); 214 | barrier.subresourceRange().aspectMask(vk::ImageAspectFlagBits::eDepth); 215 | barrier.subresourceRange().baseMipLevel(0); 216 | barrier.subresourceRange().levelCount(1); 217 | barrier.subresourceRange().baseArrayLayer(0); 218 | barrier.subresourceRange().layerCount(1); 219 | 220 | //layout DepthImage 221 | //m_cmdBuf->getVkCommandBuffer(0).pipelineBarrier( 222 | // vk::PipelineStageFlagBits::eTopOfPipe, 223 | // vk::PipelineStageFlagBits::eTopOfPipe, 224 | // vk::DependencyFlagBits(), 225 | // 0, 226 | // nullptr, 227 | // 0, 228 | // nullptr, 229 | // 1, 230 | // &barrier); 231 | 232 | m_renderPass = new simpleVulkan::RenderPass(); 233 | m_renderPass->create(m_device->getVkDevice(0), m_colorFormat, m_depthFormat); 234 | 235 | { 236 | m_FrameBuffers.resize(m_swapchain->count()); 237 | for (size_t i = 0; i < m_FrameBuffers.size(); ++i) 238 | { 239 | m_FrameBuffers[i] = new simpleVulkan::Framebuffer(); 240 | m_FrameBuffers[i]->create( 241 | m_device->getVkDevice(0), 242 | getWidth(), 243 | getHeight(), 244 | m_swapchain->getVkImageView(i), 245 | m_depthImage->getVkImageView(), 246 | m_renderPass->getVkRenderPass()); 247 | } 248 | } 249 | 250 | //end CommandBuffer 251 | #ifdef VKCPP_ENHANCED_MODE 252 | m_cmdBuf->getVkCommandBuffer(0).end(); 253 | #else 254 | result = m_cmdBuf->getVkCommandBuffer(0).end(); 255 | #endif 256 | //init SubmitInfo 257 | m_queue->submit(m_cmdBuf->getVkCommandBuffer(0)); 258 | 259 | //wait queue 260 | m_queue->wait(); 261 | 262 | //read VertexShader 263 | std::vector code(0); 264 | if (!readBinaryFile(m_vertexShaderName, code)) 265 | { 266 | std::cout << "could not read vertex shader!!" << std::endl; 267 | } 268 | 269 | m_vertexShader = new simpleVulkan::Shader(); 270 | m_vertexShader->create(m_device->getVkDevice(0), code.size(), code.data()); 271 | 272 | //read FragShader 273 | code.clear(); 274 | if (!readBinaryFile(m_fragShaderName, code)) 275 | { 276 | std::cout << "could not read fragment shader!!" << std::endl; 277 | } 278 | 279 | m_fragmentShader = new simpleVulkan::Shader(); 280 | m_fragmentShader->create(m_device->getVkDevice(0), code.size(), code.data()); 281 | 282 | std::vector vertexBindings(1); 283 | std::vector vertexAttributes(1); 284 | 285 | //init VertexBinding 286 | vertexBindings[0].binding(0); 287 | vertexBindings[0].inputRate(vk::VertexInputRate::eVertex); 288 | vertexBindings[0].stride(sizeof(float) * 2); 289 | 290 | //init VertexAttributes 291 | vertexAttributes[0].binding(0); 292 | vertexAttributes[0].location(0); 293 | vertexAttributes[0].format(vk::Format::eR32G32Sfloat); 294 | vertexAttributes[0].offset(0); 295 | 296 | //create VertexBuffer 297 | m_vertexBuffer = new simpleVulkan::Buffer(); 298 | m_vertexBuffer->create(m_device->getVkPhysicalDevice(0), m_device->getVkDevice(0), vk::BufferUsageFlagBits::eVertexBuffer, sizeof(m_vertexes)); 299 | 300 | //write VertexBuffer 301 | m_vertexBuffer->write(reinterpret_cast(m_vertexes)); 302 | 303 | //create FragmentBuffer 304 | m_matrixBuffer = new simpleVulkan::Buffer(); 305 | m_matrixBuffer->create(m_device->getVkPhysicalDevice(0), m_device->getVkDevice(0), vk::BufferUsageFlagBits::eUniformBuffer, sizeof(m_matrix)); 306 | 307 | //write FragmentBuffer 308 | m_matrixBuffer->write(reinterpret_cast(m_matrix)); 309 | 310 | //init DescriptorSetLayoutBinding 311 | std::vector layoutBinding(1); 312 | layoutBinding[0].binding(0); 313 | layoutBinding[0].descriptorType(vk::DescriptorType::eUniformBuffer); 314 | layoutBinding[0].stageFlags(vk::ShaderStageFlagBits::eVertex); 315 | layoutBinding[0].pImmutableSamplers(nullptr); 316 | layoutBinding[0].descriptorCount(1); 317 | 318 | m_descriptorSets = new simpleVulkan::DescriptorSets(); 319 | m_descriptorSets->create(m_device->getVkDevice(0), layoutBinding, 1); 320 | 321 | //write DescriptorSet 322 | { 323 | 324 | //init DescriptorBufferInfo 325 | vk::DescriptorBufferInfo bufferInfo; 326 | bufferInfo.buffer(m_matrixBuffer->getVkBuffer()); 327 | bufferInfo.offset(0); 328 | bufferInfo.range(sizeof(m_matrix)); 329 | 330 | //init WriteDescriptorSet 331 | vk::WriteDescriptorSet writeSet; 332 | writeSet.dstSet(m_descriptorSets->getVkDescriptorSet(0)); 333 | writeSet.dstBinding(0); 334 | writeSet.dstArrayElement(0); 335 | writeSet.descriptorCount(1); 336 | writeSet.descriptorType(vk::DescriptorType::eUniformBuffer); 337 | writeSet.pBufferInfo(&bufferInfo); 338 | 339 | //update DescriptorSet 340 | m_device->getVkDevice(0).updateDescriptorSets(1, &writeSet, 0, nullptr); 341 | } 342 | 343 | //init Viewport 344 | m_viewport.x(0.0f); 345 | m_viewport.y(0.0f); 346 | m_viewport.width(getWidth()); 347 | m_viewport.height(getHeight()); 348 | m_viewport.minDepth(0.0f); 349 | m_viewport.maxDepth(1.0f); 350 | 351 | //init Scissor 352 | m_scissor.offset().x(0); 353 | m_scissor.offset().y(0); 354 | m_scissor.extent().width(getWidth()); 355 | m_scissor.extent().height(getHeight()); 356 | 357 | m_pipeline = new simpleVulkan::GraphicsPipeline(); 358 | m_pipeline->create( 359 | m_device->getVkDevice(0), 360 | m_vertexShader->getVkShaderModule(), 361 | m_fragmentShader->getVkShaderModule(), 362 | m_descriptorSets->getVkDescriptorSetLayout(), 363 | vertexBindings, 364 | vertexAttributes, 365 | m_viewport, 366 | m_scissor, 367 | m_renderPass->getVkRenderPass()); 368 | { 369 | //init SemaphoreCreateInfo 370 | vk::SemaphoreCreateInfo semaphoreInfo; 371 | semaphoreInfo.flags(vk::SemaphoreCreateFlagBits()); 372 | 373 | //create Semaphore 374 | result = m_device->getVkDevice(0).createSemaphore( 375 | &semaphoreInfo, 376 | nullptr, 377 | &m_semaphore); 378 | } 379 | 380 | return true; 381 | 382 | } 383 | virtual void finalize() override 384 | { 385 | } 386 | 387 | virtual bool render() override 388 | { 389 | vk::Result result; 390 | float rate = 100 / (3.14f * 2.0f); 391 | m_matrix[0][0] = std::cos(m_count / rate); 392 | m_matrix[0][1] = std::sin(m_count / rate); 393 | m_matrix[1][0] = -std::sin(m_count / rate); 394 | m_matrix[1][1] = std::cos(m_count / rate); 395 | m_matrixBuffer->write(reinterpret_cast(&m_matrix)); 396 | 397 | //acquire next Image 398 | result = m_device->getVkDevice(0).acquireNextImageKHR( 399 | m_swapchain->getVkSwapchainKHR(), 400 | 400000000, 401 | m_semaphore, 402 | nullptr, 403 | &m_bufferIndex); 404 | 405 | { 406 | //init CommandBufferInheritanceInfo 407 | vk::CommandBufferInheritanceInfo inheritanceInfo; 408 | inheritanceInfo.renderPass(m_renderPass->getVkRenderPass()); //debug 409 | inheritanceInfo.subpass(0); //debug 410 | inheritanceInfo.framebuffer(m_FrameBuffers[m_bufferIndex]->getVkFrameBuffer()); //debug 411 | inheritanceInfo.occlusionQueryEnable(false); 412 | inheritanceInfo.queryFlags(vk::QueryControlFlagBits()); 413 | inheritanceInfo.pipelineStatistics(vk::QueryPipelineStatisticFlagBits()); 414 | 415 | //init CommandBufferBeginInfo 416 | vk::CommandBufferBeginInfo beginInfo; 417 | beginInfo.pInheritanceInfo(&inheritanceInfo); 418 | 419 | //begin CommandBuffer 420 | m_cmdBuf->getVkCommandBuffer(1).begin(&beginInfo); 421 | 422 | { 423 | //pipelineBarrier 424 | vk::ImageMemoryBarrier barrier; 425 | barrier.srcAccessMask(vk::AccessFlagBits::eMemoryRead); 426 | barrier.dstAccessMask(vk::AccessFlagBits::eColorAttachmentWrite); 427 | barrier.oldLayout(vk::ImageLayout::ePresentSrcKHR); 428 | barrier.newLayout(vk::ImageLayout::eColorAttachmentOptimal); 429 | barrier.srcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); 430 | barrier.dstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); 431 | barrier.subresourceRange().aspectMask(vk::ImageAspectFlagBits::eColor); 432 | barrier.subresourceRange().baseMipLevel(0); 433 | barrier.subresourceRange().layerCount(1); 434 | barrier.subresourceRange().baseArrayLayer(0); 435 | barrier.subresourceRange().levelCount(1); 436 | barrier.image(m_swapchain->getVkImage(m_bufferIndex)); 437 | m_cmdBuf->getVkCommandBuffer(1).pipelineBarrier( 438 | vk::PipelineStageFlagBits::eAllCommands, 439 | vk::PipelineStageFlagBits::eTopOfPipe, 440 | vk::DependencyFlagBits(), 441 | 0, 442 | nullptr, 443 | 0, 444 | nullptr, 445 | 1, 446 | &barrier); 447 | } 448 | 449 | } 450 | 451 | { 452 | //clear color 453 | vk::ClearColorValue clearColor(std::array{0.0f, 1.0f, 0.0f, 1.0f}); 454 | vk::ImageSubresourceRange range(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1); 455 | m_cmdBuf->getVkCommandBuffer(1).clearColorImage(m_swapchain->getVkImage(m_bufferIndex), vk::ImageLayout::eGeneral, &clearColor, 1, &range); 456 | } 457 | 458 | { 459 | //clear depth 460 | vk::ClearDepthStencilValue clearDepth(1.0f, 0); 461 | vk::ImageSubresourceRange range(vk::ImageAspectFlagBits::eDepth, 0, 1, 0, 1); 462 | m_cmdBuf->getVkCommandBuffer(1).clearDepthStencilImage(m_depthImage->getVkImage(), vk::ImageLayout::eGeneral, &clearDepth, 1, &range); 463 | } 464 | 465 | { 466 | //clear image 467 | vk::ClearColorValue clearColor(std::array{1.0f, 0.0f, 0.0f, 1.0f}); 468 | vk::ClearDepthStencilValue clearDepth(1.0f, 0.0f); 469 | vk::ClearValue clearValues[2]; 470 | clearValues[0].color(clearColor); 471 | clearValues[1].depthStencil(clearDepth); 472 | 473 | //init RenderPassBeginInfo 474 | vk::RenderPassBeginInfo passInfo; 475 | passInfo.renderPass(m_renderPass->getVkRenderPass()); 476 | passInfo.framebuffer(m_FrameBuffers[m_bufferIndex]->getVkFrameBuffer()); 477 | passInfo.renderArea().offset().x(0); 478 | passInfo.renderArea().offset().y(0); 479 | passInfo.renderArea().extent().width(getWidth()); 480 | passInfo.renderArea().extent().height(getHeight()); 481 | passInfo.clearValueCount(2); 482 | passInfo.pClearValues(clearValues); 483 | 484 | //begin RenderPass 485 | m_cmdBuf->getVkCommandBuffer(1).beginRenderPass(&passInfo, vk::SubpassContents::eInline); 486 | } 487 | 488 | //bind Pipeline 489 | m_cmdBuf->getVkCommandBuffer(1).bindPipeline(vk::PipelineBindPoint::eGraphics, m_pipeline->getVkPipeline()); 490 | 491 | //bind DescriptorSet 492 | m_cmdBuf->getVkCommandBuffer(1).bindDescriptorSets(vk::PipelineBindPoint::eGraphics, m_pipeline->getVkPipelineLayout(), 0, 1, &m_descriptorSets->getVkDescriptorSet(0), 0, nullptr); 493 | 494 | //set Viewport 495 | m_cmdBuf->getVkCommandBuffer(1).setViewport(0, 1, &m_viewport); 496 | 497 | //set Scissor 498 | m_cmdBuf->getVkCommandBuffer(1).setScissor(0, 1, &m_scissor); 499 | 500 | //bind VertexBuffer 501 | vk::DeviceSize offset(0); 502 | m_cmdBuf->getVkCommandBuffer(1).bindVertexBuffers(0, 1, &m_vertexBuffer->getVkBuffer(), &offset); 503 | 504 | //draw 505 | m_cmdBuf->getVkCommandBuffer(1).draw(3, 1, 0, 0); 506 | 507 | //end RenderPass 508 | m_cmdBuf->getVkCommandBuffer(1).endRenderPass(); 509 | 510 | { 511 | //pipelineBarrier 512 | vk::ImageMemoryBarrier barrier; 513 | barrier.srcAccessMask(vk::AccessFlagBits::eColorAttachmentWrite); 514 | barrier.dstAccessMask(vk::AccessFlagBits::eMemoryRead); 515 | barrier.oldLayout(vk::ImageLayout::eColorAttachmentOptimal); 516 | barrier.newLayout(vk::ImageLayout::ePresentSrcKHR); 517 | barrier.srcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); 518 | barrier.dstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED); 519 | barrier.subresourceRange().aspectMask(vk::ImageAspectFlagBits::eColor); 520 | barrier.subresourceRange().baseMipLevel(0); 521 | barrier.subresourceRange().layerCount(1); 522 | barrier.subresourceRange().baseArrayLayer(0); 523 | barrier.subresourceRange().levelCount(1); 524 | barrier.image(m_swapchain->getVkImage(m_bufferIndex)); 525 | m_cmdBuf->getVkCommandBuffer(1).pipelineBarrier( 526 | vk::PipelineStageFlagBits::eColorAttachmentOutput, 527 | vk::PipelineStageFlagBits::eBottomOfPipe, 528 | vk::DependencyFlagBits(), 529 | 0, nullptr, 530 | 0, nullptr, 531 | 1, &barrier); 532 | } 533 | 534 | //end CommandBuffer 535 | m_cmdBuf->getVkCommandBuffer(1).end(); 536 | 537 | m_queue->submit(m_cmdBuf->getVkCommandBuffer(1),m_semaphore); 538 | 539 | //wait Queue 540 | m_queue->wait(); 541 | 542 | m_queue->present(m_swapchain->getVkSwapchainKHR(), m_bufferIndex); 543 | 544 | //wait Device 545 | m_device->getVkDevice(0).waitIdle(); 546 | 547 | std::cout << "BufferIndex:" << m_bufferIndex << std::endl; 548 | std::cout << "Time:" << glfwGetTime() << std::endl; 549 | ++m_count; 550 | return true; 551 | } 552 | }; 553 | 554 | 555 | int main( 556 | int argc, 557 | char **argv) 558 | { 559 | bool validate = true; // Use vulkan validation layer + debug report? 560 | if (argc > 1) 561 | { 562 | if (strcmp("-novalidate", argv[1]) == 0) { 563 | validate = false; 564 | } 565 | } 566 | simpleVulkan::Application* app = new TestApplication(); 567 | if (app->create("test", 400, 400, validate)) 568 | { 569 | app->run(); 570 | app->destroy(); 571 | } 572 | } 573 | -------------------------------------------------------------------------------- /src/queue.cpp: -------------------------------------------------------------------------------- 1 | #include"queue.h" 2 | 3 | #include"device.h" 4 | 5 | namespace simpleVulkan 6 | { 7 | Queue::Queue(){} 8 | Queue::~Queue(){} 9 | 10 | void Queue::init(vk::Device device) 11 | { 12 | m_device = device; 13 | m_device.getQueue(0,0,&m_queue); 14 | } 15 | 16 | Result Queue::submit(vk::CommandBuffer cmdBuffer) 17 | { 18 | vk::PipelineStageFlags stage = vk::PipelineStageFlagBits::eBottomOfPipe; 19 | vk::Result result; 20 | //init SubmitInfo 21 | vk::SubmitInfo submitInfo; 22 | submitInfo.waitSemaphoreCount(0); 23 | submitInfo.pWaitSemaphores(nullptr); 24 | submitInfo.signalSemaphoreCount(0); 25 | submitInfo.pSignalSemaphores(nullptr); 26 | submitInfo.pWaitDstStageMask(&stage); 27 | submitInfo.commandBufferCount(1); 28 | submitInfo.pCommandBuffers(&cmdBuffer); 29 | 30 | //submit queue 31 | result = m_queue.submit(1,&submitInfo,vk::Fence()); 32 | return result; 33 | } 34 | 35 | Result Queue::submit(vk::CommandBuffer cmdBuffer,vk::Semaphore semaphore) 36 | { 37 | vk::PipelineStageFlags stage = vk::PipelineStageFlagBits::eBottomOfPipe; 38 | vk::Result result; 39 | //init SubmitInfo 40 | vk::SubmitInfo submitInfo; 41 | submitInfo.waitSemaphoreCount(1); 42 | submitInfo.pWaitSemaphores(&semaphore); 43 | submitInfo.signalSemaphoreCount(0); 44 | submitInfo.pSignalSemaphores(nullptr); 45 | submitInfo.pWaitDstStageMask(&stage); 46 | submitInfo.commandBufferCount(1); 47 | submitInfo.pCommandBuffers(&cmdBuffer); 48 | 49 | //submit queue 50 | result = m_queue.submit(1,&submitInfo,vk::Fence()); 51 | return result; 52 | } 53 | Result Queue::wait() 54 | { 55 | #ifdef VKCPP_ENHANCED_MODE 56 | m_queue.waitIdle(); 57 | return Result::eSuccess; 58 | #else 59 | vk::Result result; 60 | result = m_queue.waitIdle(); 61 | return result; 62 | #endif 63 | } 64 | Result Queue::present(vk::SwapchainKHR swapchain,uint32_t index) 65 | { 66 | vk::Result result; 67 | //init PresentInfoKHR 68 | vk::PresentInfoKHR presentInfo; 69 | presentInfo.swapchainCount(1); 70 | presentInfo.pSwapchains(&swapchain); 71 | presentInfo.pImageIndices(&index); 72 | presentInfo.waitSemaphoreCount(0); 73 | presentInfo.pWaitSemaphores(nullptr); 74 | presentInfo.pResults(nullptr); 75 | 76 | //present 77 | result = m_queue.presentKHR(&presentInfo); 78 | return result; 79 | } 80 | 81 | vk::Queue& Queue::getVkQueue() 82 | { 83 | return m_queue; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/render_pass.cpp: -------------------------------------------------------------------------------- 1 | #include"render_pass.h" 2 | 3 | namespace simpleVulkan 4 | { 5 | RenderPass::RenderPass() 6 | { 7 | } 8 | RenderPass::~RenderPass() 9 | { 10 | } 11 | 12 | Result RenderPass::create(vk::Device device,vk::Format colorFormat,vk::Format depthFormat) 13 | { 14 | m_device = device; 15 | 16 | vk::Result result; 17 | //init AttachmentDescription 18 | vk::AttachmentDescription attachments[2]; 19 | attachments[0].format(colorFormat); 20 | attachments[0].samples(vk::SampleCountFlagBits::e1); 21 | attachments[0].loadOp(vk::AttachmentLoadOp::eClear); 22 | attachments[0].storeOp(vk::AttachmentStoreOp::eStore); 23 | attachments[0].stencilLoadOp(vk::AttachmentLoadOp::eDontCare); 24 | attachments[0].stencilStoreOp(vk::AttachmentStoreOp::eDontCare); 25 | attachments[0].initialLayout(vk::ImageLayout::eColorAttachmentOptimal); 26 | attachments[0].finalLayout(vk::ImageLayout::eColorAttachmentOptimal); 27 | attachments[0].flags(vk::AttachmentDescriptionFlagBits()); 28 | attachments[1].format(depthFormat); 29 | attachments[1].samples(vk::SampleCountFlagBits::e1); 30 | attachments[1].loadOp(vk::AttachmentLoadOp::eClear); 31 | attachments[1].storeOp(vk::AttachmentStoreOp::eDontCare); 32 | attachments[1].stencilLoadOp(vk::AttachmentLoadOp::eDontCare); 33 | attachments[1].stencilStoreOp(vk::AttachmentStoreOp::eDontCare); 34 | attachments[1].initialLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal); 35 | attachments[1].finalLayout(vk::ImageLayout::eDepthStencilAttachmentOptimal); 36 | attachments[1].flags(vk::AttachmentDescriptionFlagBits()); 37 | 38 | //init AttachmentReference 39 | vk::AttachmentReference colorRef; 40 | colorRef.attachment(0); 41 | colorRef.layout(vk::ImageLayout::eColorAttachmentOptimal); 42 | vk::AttachmentReference depthRef; 43 | depthRef.attachment(1); 44 | depthRef.layout(vk::ImageLayout::eDepthStencilAttachmentOptimal); 45 | 46 | //init SubpassDescription 47 | vk::SubpassDescription subpassDesc; 48 | subpassDesc.flags(vk::SubpassDescriptionFlagBits()); 49 | subpassDesc.inputAttachmentCount(0); 50 | subpassDesc.pInputAttachments(nullptr); 51 | subpassDesc.colorAttachmentCount(1); 52 | subpassDesc.pColorAttachments(&colorRef); 53 | subpassDesc.pResolveAttachments(nullptr); 54 | subpassDesc.pDepthStencilAttachment(&depthRef); 55 | subpassDesc.pDepthStencilAttachment(nullptr); 56 | subpassDesc.preserveAttachmentCount(0); 57 | subpassDesc.pPreserveAttachments(nullptr); 58 | 59 | //init RenderPassCreateInfo 60 | vk::RenderPassCreateInfo renderPassInfo; 61 | renderPassInfo.flags(vk::RenderPassCreateFlagBits()); 62 | renderPassInfo.attachmentCount(2); 63 | renderPassInfo.pAttachments(attachments); 64 | renderPassInfo.subpassCount(1); 65 | renderPassInfo.pSubpasses(&subpassDesc); 66 | renderPassInfo.dependencyCount(0); 67 | renderPassInfo.pDependencies(nullptr); 68 | 69 | //create RenderPass 70 | result = m_device.createRenderPass(&renderPassInfo,nullptr,&m_renderPass); 71 | return result; 72 | } 73 | 74 | void RenderPass::destroy() 75 | { 76 | m_device.destroyRenderPass(m_renderPass,nullptr); 77 | } 78 | 79 | vk::RenderPass& RenderPass::getVkRenderPass() 80 | { 81 | return m_renderPass; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/shader.cpp: -------------------------------------------------------------------------------- 1 | #include"shader.h" 2 | namespace simpleVulkan 3 | { 4 | Shader::Shader() 5 | { 6 | } 7 | 8 | Shader::~Shader() 9 | { 10 | } 11 | 12 | Result Shader::create(vk::Device device,size_t size,void* code) 13 | { 14 | m_device = device; 15 | vk::Result result; 16 | 17 | //init VertexShaderModuleCreateInfo 18 | vk::ShaderModuleCreateInfo shaderInfo; 19 | shaderInfo.flags(vk::ShaderModuleCreateFlagBits()); 20 | shaderInfo.codeSize(size); 21 | shaderInfo.pCode(reinterpret_cast(code)); 22 | 23 | //create VertexShader 24 | result = m_device.createShaderModule(&shaderInfo,nullptr,&m_shaderModule); 25 | return result; 26 | } 27 | 28 | void Shader::destroy() 29 | { 30 | m_device.destroyShaderModule(m_shaderModule,nullptr); 31 | } 32 | 33 | vk::ShaderModule& Shader::getVkShaderModule() 34 | { 35 | return m_shaderModule; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/swapchain.cpp: -------------------------------------------------------------------------------- 1 | #include"swapchain.h" 2 | 3 | namespace simpleVulkan 4 | { 5 | Swapchain::Swapchain() 6 | { 7 | } 8 | Swapchain::~Swapchain() 9 | { 10 | } 11 | Result Swapchain::create( 12 | vk::PhysicalDevice physicalDevice, 13 | vk::Device device, 14 | vk::SurfaceKHR& surface, 15 | vk::ImageUsageFlags usage, 16 | uint32_t width, 17 | uint32_t height) 18 | { 19 | m_device = device; 20 | m_usage = usage; 21 | m_width = width; 22 | m_height = height; 23 | 24 | vk::SurfaceTransformFlagBitsKHR transform = vk::SurfaceTransformFlagBitsKHR::eIdentity; 25 | vk::CompositeAlphaFlagBitsKHR compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque; 26 | 27 | vk::Result result; 28 | 29 | //get SurfaceFormats 30 | uint32_t surfaceFormatsCount; 31 | result = physicalDevice.getSurfaceFormatsKHR(surface, &surfaceFormatsCount, nullptr); 32 | if(result != vk::Result::eSuccess) 33 | { 34 | return result; 35 | } 36 | std::vector surfaceFormats(surfaceFormatsCount); 37 | result = physicalDevice.getSurfaceFormatsKHR(surface, &surfaceFormatsCount, surfaceFormats.data()); 38 | if(result != vk::Result::eSuccess) 39 | { 40 | return result; 41 | } 42 | 43 | m_format = surfaceFormats[0].format(); 44 | 45 | //get SurfacePresentModes 46 | uint32_t surfacePresentModesCount; 47 | result = physicalDevice.getSurfacePresentModesKHR(surface, &surfacePresentModesCount, nullptr); 48 | if(result != vk::Result::eSuccess) 49 | { 50 | return result; 51 | } 52 | std::vector surfacePresentModes(surfacePresentModesCount); 53 | result = physicalDevice.getSurfacePresentModesKHR(surface, &surfacePresentModesCount, surfacePresentModes.data()); 54 | if(result != vk::Result::eSuccess) 55 | { 56 | return result; 57 | } 58 | 59 | //get SurfaceCapablilies 60 | vk::SurfaceCapabilitiesKHR surfaceCapabilities; 61 | result = physicalDevice.getSurfaceCapabilitiesKHR(surface, &surfaceCapabilities); 62 | if(result != vk::Result::eSuccess) 63 | { 64 | return result; 65 | } 66 | 67 | if (!(surfaceCapabilities.supportedUsageFlags() & usage)) 68 | { 69 | return vk::Result::eErrorInitializationFailed; 70 | } 71 | if (!(surfaceCapabilities.supportedTransforms() & transform)) 72 | { 73 | return vk::Result::eErrorInitializationFailed; 74 | } 75 | if (!(surfaceCapabilities.supportedCompositeAlpha() & compositeAlpha)) 76 | { 77 | return vk::Result::eErrorInitializationFailed; 78 | } 79 | 80 | 81 | //init SwapchainCreateInfo 82 | vk::SwapchainCreateInfoKHR swapchainInfo; 83 | swapchainInfo.flags(vk::SwapchainCreateFlagBitsKHR{}); 84 | swapchainInfo.surface(surface); 85 | swapchainInfo.minImageCount(surfaceCapabilities.minImageCount()); 86 | swapchainInfo.imageFormat(surfaceFormats[0].format()); 87 | swapchainInfo.imageColorSpace(surfaceFormats[0].colorSpace()); 88 | swapchainInfo.imageExtent(vk::Extent2D(width,height)); 89 | swapchainInfo.imageArrayLayers(1); 90 | swapchainInfo.imageUsage(m_usage); 91 | swapchainInfo.imageSharingMode(vk::SharingMode::eExclusive); 92 | swapchainInfo.queueFamilyIndexCount(0); 93 | swapchainInfo.pQueueFamilyIndices(nullptr); 94 | swapchainInfo.preTransform(transform); 95 | swapchainInfo.compositeAlpha(compositeAlpha); 96 | swapchainInfo.presentMode(surfacePresentModes[0]); 97 | swapchainInfo.clipped(true); 98 | swapchainInfo.oldSwapchain(vk::SwapchainKHR()); 99 | 100 | //create Swapchain 101 | result = m_device.createSwapchainKHR(&swapchainInfo,nullptr,&m_swapchain); 102 | if(result != vk::Result::eSuccess) 103 | { 104 | return result; 105 | } 106 | 107 | //get SwapchainImages 108 | uint32_t swapchainCount; 109 | result = m_device.getSwapchainImagesKHR(m_swapchain,&swapchainCount,nullptr); 110 | if(result != vk::Result::eSuccess) 111 | { 112 | return result; 113 | } 114 | m_images.resize(swapchainCount); 115 | result = m_device.getSwapchainImagesKHR(m_swapchain,&swapchainCount,m_images.data()); 116 | if(result != vk::Result::eSuccess) 117 | { 118 | return result; 119 | } 120 | 121 | //create SwapchainImageViews 122 | m_imageViews.resize(swapchainCount); 123 | vk::ImageAspectFlags aspect; 124 | if(m_usage & vk::ImageUsageFlagBits::eColorAttachment) 125 | { 126 | aspect |= vk::ImageAspectFlagBits::eColor; 127 | } 128 | if(m_usage & vk::ImageUsageFlagBits::eDepthStencilAttachment) 129 | { 130 | aspect |= vk::ImageAspectFlagBits::eDepth; 131 | } 132 | for(uint32_t i=0;i