diff --git a/.gitignore b/.gitignore index 567609b..44df08d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build/ +src/shaders/*.spv diff --git a/src/cfx_app.cpp b/src/cfx_app.cpp index 01cc5e7..d8e9564 100644 --- a/src/cfx_app.cpp +++ b/src/cfx_app.cpp @@ -2,10 +2,10 @@ #include "cfx_render_system.hpp" #include "cfx_camera.hpp" #include "keyboard_movement_controller.hpp" -#include -#include -#include -#include +#include +#include +#include +#include #include #define GLM_FORCE_RADIANS @@ -13,152 +13,132 @@ #include #include - -namespace cfx{ - struct SimplePushConstantData{ +namespace cfx +{ + struct SimplePushConstantData + { glm::mat2 transform{1.f}; glm::vec2 offset; alignas(16) glm::vec3 color; - }; - App::App(){ - loadGameObjects(); - - - } - App::~App(){ - - } - void App::run(){ - // std::cout << "CREATE RENDER SYSTEM"<< std::endl; - CFXRenderSystem cfxRenderSystem{cfxDevice,cfxRenderer.getSwapChainRenderPasses()}; - CFXCamera camera{}; - // camera.setViewDirection(glm::vec3(0.f),glm::vec3(0.5f,0.f,1.f)); - // camera.setViewTarget(glm::vec3(-1.f,-2.f,2.f),glm::vec3(0.f,0.f,2.5f)); - - auto viewerObject = CFXGameObject::createGameObject(); - KeyboardMovementController cameraController{}; - - // std::cout << "CREATED RENDER SYSTEM"<< std::endl; - auto currentTime = std::chrono::high_resolution_clock::now(); - while(!window.shouldClose()){ - - glfwPollEvents(); - auto newTime = std::chrono::high_resolution_clock::now(); - float frameTime = std::chrono::duration(newTime-currentTime).count(); - currentTime = newTime; - cameraController.moveInPlaneXZ(window.getGLFWwindow(),frameTime,viewerObject); - camera.setViewYXZ(viewerObject.transformComponent.translation,viewerObject.transformComponent.rotation); - float aspect = cfxRenderer.getAspectRatio(); - // camera.setOrthographicProjection(-aspect,aspect,-1,1,-1,1); - camera.setPerspectiveProjection(glm::radians(50.f),aspect,0.1f,10.f); - - - - auto renderBuffer = cfxRenderer.beginFrame(); - if(renderBuffer.commandBuffer != nullptr){ - cfxRenderer.beginSwapChainRenderPass(renderBuffer.commandBuffer,renderBuffer.deviceMask,renderBuffer.deviceIndex); - cfxRenderSystem.renderGameObjects(renderBuffer.commandBuffer,cfxGameObjects,renderBuffer.deviceIndex,camera); - cfxRenderer.endSwapChainRenderPass(renderBuffer.commandBuffer,renderBuffer.deviceMask,renderBuffer.deviceIndex); - cfxRenderer.endFrame(renderBuffer.deviceIndex); - vkDeviceWaitIdle(cfxDevice.device(renderBuffer.deviceIndex)); - } - - - - } - - // for(int i=0; i < cfxDevice.getDevicesinDeviceGroup(); i++){ - - - // } - - + App::App() + { + loadGameObjects(); + } + App::~App() + { + } + void App::run() + { + // std::cout << "CREATE RENDER SYSTEM"<< std::endl; + CFXRenderSystem cfxRenderSystem{cfxDevice, cfxRenderer.getSwapChainRenderPasses()}; + CFXCamera camera{}; + // camera.setViewDirection(glm::vec3(0.f),glm::vec3(0.5f,0.f,1.f)); + // camera.setViewTarget(glm::vec3(-1.f,-2.f,2.f),glm::vec3(0.f,0.f,2.5f)); + + auto viewerObject = CFXGameObject::createGameObject(); + KeyboardMovementController cameraController{}; + + // std::cout << "CREATED RENDER SYSTEM"<< std::endl; + auto currentTime = std::chrono::high_resolution_clock::now(); + while (!window.shouldClose()) + { + + glfwPollEvents(); + auto newTime = std::chrono::high_resolution_clock::now(); + float frameTime = std::chrono::duration(newTime - currentTime).count(); + currentTime = newTime; + cameraController.moveInPlaneXZ(window.getGLFWwindow(), frameTime, viewerObject); + camera.setViewYXZ(viewerObject.transformComponent.translation, viewerObject.transformComponent.rotation); + float aspect = cfxRenderer.getAspectRatio(); + // camera.setOrthographicProjection(-aspect,aspect,-1,1,-1,1); + camera.setPerspectiveProjection(glm::radians(50.f), aspect, 0.1f, 10.f); + + auto renderBuffer = cfxRenderer.beginFrame(); + if (renderBuffer.commandBuffer != nullptr) + { + cfxRenderer.beginSwapChainRenderPass(renderBuffer.commandBuffer, renderBuffer.deviceMask, renderBuffer.deviceIndex); + cfxRenderSystem.renderGameObjects(renderBuffer.commandBuffer, cfxGameObjects, renderBuffer.deviceIndex, camera); + cfxRenderer.endSwapChainRenderPass(renderBuffer.commandBuffer, renderBuffer.deviceMask, renderBuffer.deviceIndex); + cfxRenderer.endFrame(renderBuffer.deviceIndex); + vkDeviceWaitIdle(cfxDevice.device(renderBuffer.deviceIndex)); + } } - // temporary helper function, creates a 1x1x1 cube centered at offset -// std::unique_ptr createCubeModel(CFXDevice& device, glm::vec3 offset) { -// CFXModel::Builder modelBuilder{}; - -// modelBuilder.vertices = { -// // left face (white) -// {{-.5f, -.5f, -.5f}, {.9f, .9f, .9f}}, -// {{-.5f, .5f, .5f}, {.9f, .9f, .9f}}, -// {{-.5f, -.5f, .5f}, {.9f, .9f, .9f}}, -// {{-.5f, .5f, -.5f}, {.9f, .9f, .9f}}, - -// // right face (yellow) -// {{.5f, -.5f, -.5f}, {.8f, .8f, .1f}}, -// {{.5f, .5f, .5f}, {.8f, .8f, .1f}}, -// {{.5f, -.5f, .5f}, {.8f, .8f, .1f}}, -// {{.5f, .5f, -.5f}, {.8f, .8f, .1f}}, - -// // top face (orange, remember y axis points down) -// {{-.5f, -.5f, -.5f}, {.9f, .6f, .1f}}, -// {{.5f, -.5f, .5f}, {.9f, .6f, .1f}}, -// {{-.5f, -.5f, .5f}, {.9f, .6f, .1f}}, -// {{.5f, -.5f, -.5f}, {.9f, .6f, .1f}}, - -// // bottom face (red) -// {{-.5f, .5f, -.5f}, {.8f, .1f, .1f}}, -// {{.5f, .5f, .5f}, {.8f, .1f, .1f}}, -// {{-.5f, .5f, .5f}, {.8f, .1f, .1f}}, -// {{.5f, .5f, -.5f}, {.8f, .1f, .1f}}, - -// // nose face (blue) -// {{-.5f, -.5f, 0.5f}, {.1f, .1f, .8f}}, -// {{.5f, .5f, 0.5f}, {.1f, .1f, .8f}}, -// {{-.5f, .5f, 0.5f}, {.1f, .1f, .8f}}, -// {{.5f, -.5f, 0.5f}, {.1f, .1f, .8f}}, - -// // tail face (green) -// {{-.5f, -.5f, -0.5f}, {.1f, .8f, .1f}}, -// {{.5f, .5f, -0.5f}, {.1f, .8f, .1f}}, -// {{-.5f, .5f, -0.5f}, {.1f, .8f, .1f}}, -// {{.5f, -.5f, -0.5f}, {.1f, .8f, .1f}}, -// }; -// for (auto& v : modelBuilder.vertices) { -// v.position += offset; -// } - -// modelBuilder.indices = {0, 1, 2, 0, 3, 1, 4, 5, 6, 4, 7, 5, 8, 9, 10, 8, 11, 9, -// 12, 13, 14, 12, 15, 13, 16, 17, 18, 16, 19, 17, 20, 21, 22, 20, 23, 21}; - -// return std::make_unique(device, modelBuilder); -// // return nullptr; -// } - - - - void App::loadGameObjects(){ - // std::cout << "LOAD MODELS" << std::endl; - // std::vector vertices { - // {{0.0f,-0.5f},{1.0f,0.0f,0.0f}}, - // {{0.5f,0.5f},{.0f,1.0f,0.0f}}, - // {{-0.5f,0.5f},{0.0f,0.0f,1.0f}}, - // }; - // sierpinski(vertices, 5, {-0.5f, 0.5f}, {0.5f, 0.5f}, {0.0f, -0.5f}); - // auto cfxModel = std::make_shared(cfxDevice,vertices); - - - std::shared_ptr cfxModel = CFXModel::createModelFromFile(cfxDevice, "models/smooth_vase.obj"); - auto gameObject = CFXGameObject::createGameObject(); - gameObject.transformComponent.translation = {.0f,.0f,2.5f}; - gameObject.transformComponent.scale = glm::vec3{3.f}; - gameObject.model = cfxModel; - - - cfxGameObjects.push_back(std::move(gameObject)); - } - - - - - + // for(int i=0; i < cfxDevice.getDevicesinDeviceGroup(); i++){ + + // } + } + // temporary helper function, creates a 1x1x1 cube centered at offset + // std::unique_ptr createCubeModel(CFXDevice& device, glm::vec3 offset) { + // CFXModel::Builder modelBuilder{}; + + // modelBuilder.vertices = { + // // left face (white) + // {{-.5f, -.5f, -.5f}, {.9f, .9f, .9f}}, + // {{-.5f, .5f, .5f}, {.9f, .9f, .9f}}, + // {{-.5f, -.5f, .5f}, {.9f, .9f, .9f}}, + // {{-.5f, .5f, -.5f}, {.9f, .9f, .9f}}, + + // // right face (yellow) + // {{.5f, -.5f, -.5f}, {.8f, .8f, .1f}}, + // {{.5f, .5f, .5f}, {.8f, .8f, .1f}}, + // {{.5f, -.5f, .5f}, {.8f, .8f, .1f}}, + // {{.5f, .5f, -.5f}, {.8f, .8f, .1f}}, + + // // top face (orange, remember y axis points down) + // {{-.5f, -.5f, -.5f}, {.9f, .6f, .1f}}, + // {{.5f, -.5f, .5f}, {.9f, .6f, .1f}}, + // {{-.5f, -.5f, .5f}, {.9f, .6f, .1f}}, + // {{.5f, -.5f, -.5f}, {.9f, .6f, .1f}}, + + // // bottom face (red) + // {{-.5f, .5f, -.5f}, {.8f, .1f, .1f}}, + // {{.5f, .5f, .5f}, {.8f, .1f, .1f}}, + // {{-.5f, .5f, .5f}, {.8f, .1f, .1f}}, + // {{.5f, .5f, -.5f}, {.8f, .1f, .1f}}, + + // // nose face (blue) + // {{-.5f, -.5f, 0.5f}, {.1f, .1f, .8f}}, + // {{.5f, .5f, 0.5f}, {.1f, .1f, .8f}}, + // {{-.5f, .5f, 0.5f}, {.1f, .1f, .8f}}, + // {{.5f, -.5f, 0.5f}, {.1f, .1f, .8f}}, + + // // tail face (green) + // {{-.5f, -.5f, -0.5f}, {.1f, .8f, .1f}}, + // {{.5f, .5f, -0.5f}, {.1f, .8f, .1f}}, + // {{-.5f, .5f, -0.5f}, {.1f, .8f, .1f}}, + // {{.5f, -.5f, -0.5f}, {.1f, .8f, .1f}}, + // }; + // for (auto& v : modelBuilder.vertices) { + // v.position += offset; + // } + + // modelBuilder.indices = {0, 1, 2, 0, 3, 1, 4, 5, 6, 4, 7, 5, 8, 9, 10, 8, 11, 9, + // 12, 13, 14, 12, 15, 13, 16, 17, 18, 16, 19, 17, 20, 21, 22, 20, 23, 21}; + + // return std::make_unique(device, modelBuilder); + // // return nullptr; + // } + + void App::loadGameObjects() + { + // std::cout << "LOAD MODELS" << std::endl; + // std::vector vertices { + // {{0.0f,-0.5f},{1.0f,0.0f,0.0f}}, + // {{0.5f,0.5f},{.0f,1.0f,0.0f}}, + // {{-0.5f,0.5f},{0.0f,0.0f,1.0f}}, + // }; + // sierpinski(vertices, 5, {-0.5f, 0.5f}, {0.5f, 0.5f}, {0.0f, -0.5f}); + // auto cfxModel = std::make_shared(cfxDevice,vertices); + + std::shared_ptr cfxModel = CFXModel::createModelFromFile(cfxDevice, "models/smooth_vase.obj"); + auto gameObject = CFXGameObject::createGameObject(); + gameObject.transformComponent.translation = {.0f, .0f, 2.5f}; + gameObject.transformComponent.scale = glm::vec3{3.f}; + gameObject.model = cfxModel; + + cfxGameObjects.push_back(std::move(gameObject)); + } - - - - - } \ No newline at end of file diff --git a/src/cfx_app.hpp b/src/cfx_app.hpp index ae979ff..e4899d3 100644 --- a/src/cfx_app.hpp +++ b/src/cfx_app.hpp @@ -5,12 +5,14 @@ #include "cfx_renderer.hpp" #include "cfx_model.hpp" #include "cfx_game_object.hpp" -#include -#include +#include +#include #include -namespace cfx{ - class App{ - public: +namespace cfx +{ + class App + { + public: static constexpr int WIDTH = 800; static constexpr int HEIGHT = 600; App(); @@ -19,23 +21,14 @@ namespace cfx{ App &operator=(const App &) = delete; void run(); - - private: + private: void loadGameObjects(); - - - - - - - - CFXWindow window{WIDTH,HEIGHT,"Hello Vulkan"}; + CFXWindow window{WIDTH, HEIGHT, "Hello Vulkan"}; CFXDevice cfxDevice{window}; // CFXSwapChain cfxSwapChain{cfxDevice,window.getExtent()}; - Renderer cfxRenderer{window,cfxDevice}; + Renderer cfxRenderer{window, cfxDevice}; std::vector commandBuffers; - std::vector cfxGameObjects; - + std::vector cfxGameObjects; }; } \ No newline at end of file diff --git a/src/cfx_camera.cpp b/src/cfx_camera.cpp index 3d73971..97d6e35 100644 --- a/src/cfx_camera.cpp +++ b/src/cfx_camera.cpp @@ -5,75 +5,80 @@ namespace cfx { - void CFXCamera::setOrthographicProjection( - float left, float right, float top, float bottom, float near, float far) { - projectionMatrix = glm::mat4{1.0f}; - projectionMatrix[0][0] = 2.f / (right - left); - projectionMatrix[1][1] = 2.f / (bottom - top); - projectionMatrix[2][2] = 1.f / (far - near); - projectionMatrix[3][0] = -(right + left) / (right - left); - projectionMatrix[3][1] = -(bottom + top) / (bottom - top); - projectionMatrix[3][2] = -near / (far - near); -} - -void CFXCamera::setPerspectiveProjection(float fovy, float aspect, float near, float far) { - assert(glm::abs(aspect - std::numeric_limits::epsilon()) > 0.0f); - const float tanHalfFovy = tan(fovy / 2.f); - projectionMatrix = glm::mat4{0.0f}; - projectionMatrix[0][0] = 1.f / (aspect * tanHalfFovy); - projectionMatrix[1][1] = 1.f / (tanHalfFovy); - projectionMatrix[2][2] = far / (far - near); - projectionMatrix[2][3] = 1.f; - projectionMatrix[3][2] = -(far * near) / (far - near); -} + void CFXCamera::setOrthographicProjection( + float left, float right, float top, float bottom, float near, float far) + { + projectionMatrix = glm::mat4{1.0f}; + projectionMatrix[0][0] = 2.f / (right - left); + projectionMatrix[1][1] = 2.f / (bottom - top); + projectionMatrix[2][2] = 1.f / (far - near); + projectionMatrix[3][0] = -(right + left) / (right - left); + projectionMatrix[3][1] = -(bottom + top) / (bottom - top); + projectionMatrix[3][2] = -near / (far - near); + } -void CFXCamera::setViewDirection(glm::vec3 position, glm::vec3 direction, glm::vec3 up) { - //construct an ortho-normal basis (unit length and mutually perpendicular) - const glm::vec3 w{glm::normalize(direction)}; - const glm::vec3 u{glm::normalize(glm::cross(w, up))}; - const glm::vec3 v{glm::cross(w, u)}; + void CFXCamera::setPerspectiveProjection(float fovy, float aspect, float near, float far) + { + assert(glm::abs(aspect - std::numeric_limits::epsilon()) > 0.0f); + const float tanHalfFovy = tan(fovy / 2.f); + projectionMatrix = glm::mat4{0.0f}; + projectionMatrix[0][0] = 1.f / (aspect * tanHalfFovy); + projectionMatrix[1][1] = 1.f / (tanHalfFovy); + projectionMatrix[2][2] = far / (far - near); + projectionMatrix[2][3] = 1.f; + projectionMatrix[3][2] = -(far * near) / (far - near); + } - viewMatrix = glm::mat4{1.f}; - viewMatrix[0][0] = u.x; - viewMatrix[1][0] = u.y; - viewMatrix[2][0] = u.z; - viewMatrix[0][1] = v.x; - viewMatrix[1][1] = v.y; - viewMatrix[2][1] = v.z; - viewMatrix[0][2] = w.x; - viewMatrix[1][2] = w.y; - viewMatrix[2][2] = w.z; - viewMatrix[3][0] = -glm::dot(u, position); - viewMatrix[3][1] = -glm::dot(v, position); - viewMatrix[3][2] = -glm::dot(w, position); -} + void CFXCamera::setViewDirection(glm::vec3 position, glm::vec3 direction, glm::vec3 up) + { + // construct an ortho-normal basis (unit length and mutually perpendicular) + const glm::vec3 w{glm::normalize(direction)}; + const glm::vec3 u{glm::normalize(glm::cross(w, up))}; + const glm::vec3 v{glm::cross(w, u)}; -void CFXCamera::setViewTarget(glm::vec3 position, glm::vec3 target, glm::vec3 up) { - setViewDirection(position, target - position, up); -} + viewMatrix = glm::mat4{1.f}; + viewMatrix[0][0] = u.x; + viewMatrix[1][0] = u.y; + viewMatrix[2][0] = u.z; + viewMatrix[0][1] = v.x; + viewMatrix[1][1] = v.y; + viewMatrix[2][1] = v.z; + viewMatrix[0][2] = w.x; + viewMatrix[1][2] = w.y; + viewMatrix[2][2] = w.z; + viewMatrix[3][0] = -glm::dot(u, position); + viewMatrix[3][1] = -glm::dot(v, position); + viewMatrix[3][2] = -glm::dot(w, position); + } -void CFXCamera::setViewYXZ(glm::vec3 position, glm::vec3 rotation) { - const float c3 = glm::cos(rotation.z); - const float s3 = glm::sin(rotation.z); - const float c2 = glm::cos(rotation.x); - const float s2 = glm::sin(rotation.x); - const float c1 = glm::cos(rotation.y); - const float s1 = glm::sin(rotation.y); - const glm::vec3 u{(c1 * c3 + s1 * s2 * s3), (c2 * s3), (c1 * s2 * s3 - c3 * s1)}; - const glm::vec3 v{(c3 * s1 * s2 - c1 * s3), (c2 * c3), (c1 * c3 * s2 + s1 * s3)}; - const glm::vec3 w{(c2 * s1), (-s2), (c1 * c2)}; - viewMatrix = glm::mat4{1.f}; - viewMatrix[0][0] = u.x; - viewMatrix[1][0] = u.y; - viewMatrix[2][0] = u.z; - viewMatrix[0][1] = v.x; - viewMatrix[1][1] = v.y; - viewMatrix[2][1] = v.z; - viewMatrix[0][2] = w.x; - viewMatrix[1][2] = w.y; - viewMatrix[2][2] = w.z; - viewMatrix[3][0] = -glm::dot(u, position); - viewMatrix[3][1] = -glm::dot(v, position); - viewMatrix[3][2] = -glm::dot(w, position); -} + void CFXCamera::setViewTarget(glm::vec3 position, glm::vec3 target, glm::vec3 up) + { + setViewDirection(position, target - position, up); + } + + void CFXCamera::setViewYXZ(glm::vec3 position, glm::vec3 rotation) + { + const float c3 = glm::cos(rotation.z); + const float s3 = glm::sin(rotation.z); + const float c2 = glm::cos(rotation.x); + const float s2 = glm::sin(rotation.x); + const float c1 = glm::cos(rotation.y); + const float s1 = glm::sin(rotation.y); + const glm::vec3 u{(c1 * c3 + s1 * s2 * s3), (c2 * s3), (c1 * s2 * s3 - c3 * s1)}; + const glm::vec3 v{(c3 * s1 * s2 - c1 * s3), (c2 * c3), (c1 * c3 * s2 + s1 * s3)}; + const glm::vec3 w{(c2 * s1), (-s2), (c1 * c2)}; + viewMatrix = glm::mat4{1.f}; + viewMatrix[0][0] = u.x; + viewMatrix[1][0] = u.y; + viewMatrix[2][0] = u.z; + viewMatrix[0][1] = v.x; + viewMatrix[1][1] = v.y; + viewMatrix[2][1] = v.z; + viewMatrix[0][2] = w.x; + viewMatrix[1][2] = w.y; + viewMatrix[2][2] = w.z; + viewMatrix[3][0] = -glm::dot(u, position); + viewMatrix[3][1] = -glm::dot(v, position); + viewMatrix[3][2] = -glm::dot(w, position); + } } // namespace cfx diff --git a/src/cfx_camera.hpp b/src/cfx_camera.hpp index 45f4b27..5d194f5 100644 --- a/src/cfx_camera.hpp +++ b/src/cfx_camera.hpp @@ -6,21 +6,20 @@ namespace cfx { - class CFXCamera{ - public: - void setOrthographicProjection(float left,float right, float top, float bottom,float near, float far); - void setPerspectiveProjection(float fovy, float aspect, float near,float far); - void setViewDirection(glm::vec3 position, glm::vec3 direction, glm::vec3 up = glm::vec3{0.f,-1.f,0.f}); - void setViewTarget(glm::vec3 position, glm::vec3 target, glm::vec3 up = glm::vec3{0.f,-1.f,0.f}); + class CFXCamera + { + public: + void setOrthographicProjection(float left, float right, float top, float bottom, float near, float far); + void setPerspectiveProjection(float fovy, float aspect, float near, float far); + void setViewDirection(glm::vec3 position, glm::vec3 direction, glm::vec3 up = glm::vec3{0.f, -1.f, 0.f}); + void setViewTarget(glm::vec3 position, glm::vec3 target, glm::vec3 up = glm::vec3{0.f, -1.f, 0.f}); void setViewYXZ(glm::vec3 position, glm::vec3 rotation); - const glm::mat4& getProjection() const {return projectionMatrix; } - const glm::mat4& getView() const {return viewMatrix; } + const glm::mat4 &getProjection() const { return projectionMatrix; } + const glm::mat4 &getView() const { return viewMatrix; } - private: + private: glm::mat4 projectionMatrix{1.f}; glm::mat4 viewMatrix{1.f}; - - }; - + } // namespace cfx diff --git a/src/cfx_device.cpp b/src/cfx_device.cpp index ad64fee..40ba875 100644 --- a/src/cfx_device.cpp +++ b/src/cfx_device.cpp @@ -6,149 +6,162 @@ #include #include -namespace cfx { - -// local callback functions -static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( - VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, - VkDebugUtilsMessageTypeFlagsEXT messageType, - const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, - void *pUserData) { - std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; - - return VK_FALSE; -} - -VkResult CreateDebugUtilsMessengerEXT( - VkInstance instance, - const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkDebugUtilsMessengerEXT *pDebugMessenger) { - auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr( - instance, - "vkCreateDebugUtilsMessengerEXT"); - if (func != nullptr) { - return func(instance, pCreateInfo, pAllocator, pDebugMessenger); - } else { - return VK_ERROR_EXTENSION_NOT_PRESENT; +namespace cfx +{ + + // local callback functions + static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, + void *pUserData) + { + std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; + + return VK_FALSE; } -} - -void DestroyDebugUtilsMessengerEXT( - VkInstance instance, - VkDebugUtilsMessengerEXT debugMessenger, - const VkAllocationCallbacks *pAllocator) { - auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( - instance, - "vkDestroyDebugUtilsMessengerEXT"); - if (func != nullptr) { - func(instance, debugMessenger, pAllocator); + + VkResult CreateDebugUtilsMessengerEXT( + VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkDebugUtilsMessengerEXT *pDebugMessenger) + { + auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr( + instance, + "vkCreateDebugUtilsMessengerEXT"); + if (func != nullptr) + { + return func(instance, pCreateInfo, pAllocator, pDebugMessenger); + } + else + { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } } -} - -// class member functions -CFXDevice::CFXDevice(CFXWindow &window) : window{window} { - createInstance(); - setupDebugMessenger(); - createDeviceGroups(); - createSurface(); - createLogicalDevice(); - - - - -} - -CFXDevice::~CFXDevice() { - for(VkDevice device: devices_){ - for(VkCommandPool commandPool: commandPools){ - // vkDestroyCommandPool(device, commandPool, nullptr); + + void DestroyDebugUtilsMessengerEXT( + VkInstance instance, + VkDebugUtilsMessengerEXT debugMessenger, + const VkAllocationCallbacks *pAllocator) + { + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr( + instance, + "vkDestroyDebugUtilsMessengerEXT"); + if (func != nullptr) + { + func(instance, debugMessenger, pAllocator); + } } - vkDestroyDevice(device, nullptr); + // class member functions + CFXDevice::CFXDevice(CFXWindow &window) : window{window} + { + createInstance(); + setupDebugMessenger(); + createDeviceGroups(); + createSurface(); + createLogicalDevice(); } - - - + CFXDevice::~CFXDevice() + { + for (VkDevice device : devices_) + { + for (VkCommandPool commandPool : commandPools) + { + // vkDestroyCommandPool(device, commandPool, nullptr); + } + vkDestroyDevice(device, nullptr); + } + + if (enableValidationLayers) + { + DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); + } - if (enableValidationLayers) { - DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); + vkDestroySurfaceKHR(instance, surface_, nullptr); + vkDestroyInstance(instance, nullptr); } - vkDestroySurfaceKHR(instance, surface_, nullptr); - vkDestroyInstance(instance, nullptr); -} + void CFXDevice::createInstance() + { + if (enableValidationLayers && !checkValidationLayerSupport()) + { + throw std::runtime_error("validation layers requested, but not available!"); + } -void CFXDevice::createInstance() { - if (enableValidationLayers && !checkValidationLayerSupport()) { - throw std::runtime_error("validation layers requested, but not available!"); - } + VkApplicationInfo appInfo = {}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "VulkanProject App"; + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.pEngineName = "No Engine"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_2; + + VkInstanceCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + + auto extensions = getRequiredExtensions(); + createInfo.enabledExtensionCount = static_cast(extensions.size()); + createInfo.ppEnabledExtensionNames = extensions.data(); + + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo; + if (enableValidationLayers) + { + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + + populateDebugMessengerCreateInfo(debugCreateInfo); + createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT *)&debugCreateInfo; + } + else + { + createInfo.enabledLayerCount = 0; + createInfo.pNext = nullptr; + } - VkApplicationInfo appInfo = {}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "VulkanProject App"; - appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.pEngineName = "No Engine"; - appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_2; - - VkInstanceCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInfo.pApplicationInfo = &appInfo; - - auto extensions = getRequiredExtensions(); - createInfo.enabledExtensionCount = static_cast(extensions.size()); - createInfo.ppEnabledExtensionNames = extensions.data(); - - VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo; - if (enableValidationLayers) { - createInfo.enabledLayerCount = static_cast(validationLayers.size()); - createInfo.ppEnabledLayerNames = validationLayers.data(); - - populateDebugMessengerCreateInfo(debugCreateInfo); - createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT *)&debugCreateInfo; - } else { - createInfo.enabledLayerCount = 0; - createInfo.pNext = nullptr; - } + if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) + { + throw std::runtime_error("failed to create instance!"); + } - if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { - throw std::runtime_error("failed to create instance!"); + hasGflwRequiredInstanceExtensions(); } - hasGflwRequiredInstanceExtensions(); -} + void CFXDevice::createDeviceGroups() + { -void CFXDevice::createDeviceGroups() { - - vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); - if (deviceCount == 0) { - throw std::runtime_error("failed to find GPUs with Vulkan support!"); - } - std::cout << "Device count: " << deviceCount << std::endl; - physicalDevices.resize(deviceCount); - deviceIds.resize(deviceCount); - deviceNames.resize(deviceCount); - deviceMasks.resize(deviceCount); - deviceIndices.resize(deviceCount); - devices_.resize(deviceCount); - graphicsQueues.resize(deviceCount); - presentQueues.resize(deviceCount); - properties.resize(deviceCount); - commandPools.resize(deviceCount); - - vkEnumeratePhysicalDevices(instance, &deviceCount, physicalDevices.data()); + vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + if (deviceCount == 0) + { + throw std::runtime_error("failed to find GPUs with Vulkan support!"); + } + std::cout << "Device count: " << deviceCount << std::endl; + physicalDevices.resize(deviceCount); + deviceIds.resize(deviceCount); + deviceNames.resize(deviceCount); + deviceMasks.resize(deviceCount); + deviceIndices.resize(deviceCount); + devices_.resize(deviceCount); + graphicsQueues.resize(deviceCount); + presentQueues.resize(deviceCount); + properties.resize(deviceCount); + commandPools.resize(deviceCount); + + vkEnumeratePhysicalDevices(instance, &deviceCount, physicalDevices.data()); std::vector physicalFeatures(deviceCount); std::vector physicalFeatures2(deviceCount); - for(int i=0; i< deviceCount; i++){ - + for (int i = 0; i < deviceCount; i++) + { + physicalFeatures2[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; vkGetPhysicalDeviceProperties(physicalDevices[i], &properties[i]); - vkGetPhysicalDeviceFeatures(physicalDevices[i],&physicalFeatures[i]); - vkGetPhysicalDeviceFeatures2(physicalDevices[i],&physicalFeatures2[i]); + vkGetPhysicalDeviceFeatures(physicalDevices[i], &physicalFeatures[i]); + vkGetPhysicalDeviceFeatures2(physicalDevices[i], &physicalFeatures2[i]); deviceIds[i] = properties[i].deviceID; // deviceMasks[i] = i+1; deviceIndices[i] = i; @@ -156,525 +169,514 @@ void CFXDevice::createDeviceGroups() { std::cout << properties[i].deviceName << std::endl; std::cout << properties[i].deviceType << std::endl; deviceNames[i] = properties[i].deviceName; - - - - + } + // if(vkEnumeratePhysicalDeviceGroups(instance,&deviceGroupCount,VK_NULL_HANDLE) != VK_SUCCESS){ + // throw std::runtime_error("Failed to enumerate device group"); - } + // } + // std::cout<< "DEVICE GROUPS " << deviceGroupCount << std::endl; + // physicalDeviceGroupProperties.resize(deviceGroupCount); + // for (int i = 0; i < deviceGroupCount; i++) { + // // physicalDeviceGroupProperties[i] = pdProperties; + // physicalDeviceGroupProperties[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES; + // std::cout << "DEV GROUP PROPS STYPE 2 "<< physicalDeviceGroupProperties[i].sType << std::endl; + // } - // if(vkEnumeratePhysicalDeviceGroups(instance,&deviceGroupCount,VK_NULL_HANDLE) != VK_SUCCESS){ - // throw std::runtime_error("Failed to enumerate device group"); + // if(vkEnumeratePhysicalDeviceGroups(instance,&deviceGroupCount,physicalDeviceGroupProperties.data()) != VK_SUCCESS){ + // throw std::runtime_error("Failed to enumerate device group"); + // } + // std::cout << "DEV GROUP PROPS SIZE "<< physicalDeviceGroupProperties.size() << std::endl; + // std::cout << "DEV GROUP PROPS SUBSET ALLOCATION "<< physicalDeviceGroupProperties[0].subsetAllocation << std::endl; + // properties.resize(physicalDeviceGroupProperties[0].physicalDeviceCount); + // std::vector physicalFeatures(physicalDeviceGroupProperties[0].physicalDeviceCount); + // std::vector physicalFeatures2(physicalDeviceGroupProperties[0].physicalDeviceCount); + } - // } - // std::cout<< "DEVICE GROUPS " << deviceGroupCount << std::endl; - // physicalDeviceGroupProperties.resize(deviceGroupCount); - // for (int i = 0; i < deviceGroupCount; i++) { - + void CFXDevice::createLogicalDevice() + { + // std::cout<< "CREATING LOGICAL DEVICES " << std::endl; + for (int i = 0; i < deviceCount; i++) + { + // std::cout<< "CREATING LOGICAL DEVICES " << i << std::endl; - // // physicalDeviceGroupProperties[i] = pdProperties; - - // physicalDeviceGroupProperties[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES; - // std::cout << "DEV GROUP PROPS STYPE 2 "<< physicalDeviceGroupProperties[i].sType << std::endl; - // } - - // if(vkEnumeratePhysicalDeviceGroups(instance,&deviceGroupCount,physicalDeviceGroupProperties.data()) != VK_SUCCESS){ - // throw std::runtime_error("Failed to enumerate device group"); + QueueFamilyIndices indices = findQueueFamilies(physicalDevices, i); - // } - // std::cout << "DEV GROUP PROPS SIZE "<< physicalDeviceGroupProperties.size() << std::endl; - // std::cout << "DEV GROUP PROPS SUBSET ALLOCATION "<< physicalDeviceGroupProperties[0].subsetAllocation << std::endl; - // properties.resize(physicalDeviceGroupProperties[0].physicalDeviceCount); - // std::vector physicalFeatures(physicalDeviceGroupProperties[0].physicalDeviceCount); - // std::vector physicalFeatures2(physicalDeviceGroupProperties[0].physicalDeviceCount); - + std::vector queueCreateInfos; + std::set uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily}; -} + float queuePriority = 1.0f; + for (uint32_t queueFamily : uniqueQueueFamilies) + { + VkDeviceQueueCreateInfo queueCreateInfo = {}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = queueFamily; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + queueCreateInfos.push_back(queueCreateInfo); + } -void CFXDevice::createLogicalDevice() { - // std::cout<< "CREATING LOGICAL DEVICES " << std::endl; - for(int i=0; i< deviceCount; i++){ - - // std::cout<< "CREATING LOGICAL DEVICES " << i << std::endl; + VkPhysicalDeviceFeatures deviceFeatures = {}; + deviceFeatures.samplerAnisotropy = VK_TRUE; - QueueFamilyIndices indices = findQueueFamilies(physicalDevices,i); + VkDeviceCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - std::vector queueCreateInfos; - std::set uniqueQueueFamilies = {indices.graphicsFamily, indices.presentFamily}; + createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); + createInfo.pQueueCreateInfos = queueCreateInfos.data(); - float queuePriority = 1.0f; - for (uint32_t queueFamily : uniqueQueueFamilies) { - VkDeviceQueueCreateInfo queueCreateInfo = {}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = queueFamily; - queueCreateInfo.queueCount = 1; - queueCreateInfo.pQueuePriorities = &queuePriority; - queueCreateInfos.push_back(queueCreateInfo); - } + createInfo.pEnabledFeatures = &deviceFeatures; + createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); + createInfo.ppEnabledExtensionNames = deviceExtensions.data(); - VkPhysicalDeviceFeatures deviceFeatures = {}; - deviceFeatures.samplerAnisotropy = VK_TRUE; + // might not really be necessary anymore because device specific validation layers + // have been deprecated + if (enableValidationLayers) + { + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + } + else + { + createInfo.enabledLayerCount = 0; + } + VkDevice device_; + if (vkCreateDevice(physicalDevices[i], &createInfo, nullptr, &device_) != VK_SUCCESS) + { + throw std::runtime_error("failed to create logical device!"); + } - VkDeviceCreateInfo createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + vkGetDeviceQueue(device_, indices.graphicsFamily, 0, &graphicsQueues[i]); + vkGetDeviceQueue(device_, indices.presentFamily, 0, &presentQueues[i]); + devices_[i] = device_; + createCommandPool(i); + // std::cout<< "LOGICAL DEVICE CREATED " << i << std::endl; + } + } - createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); - createInfo.pQueueCreateInfos = queueCreateInfos.data(); + void CFXDevice::createCommandPool(int deviceIndex) + { + // std::cout << "CREATE COMMAND POOL " << deviceIndex << std::endl; + QueueFamilyIndices queueFamilyIndices = findPhysicalQueueFamilies(deviceIndex); + VkCommandPoolCreateInfo poolInfo = {}; + poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily; + poolInfo.flags = + VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + + if (vkCreateCommandPool(devices_[deviceIndex], &poolInfo, nullptr, &commandPools[deviceIndex]) != VK_SUCCESS) + { + throw std::runtime_error("failed to create command pool!"); + } + } + + void CFXDevice::createSurface() + { + // std::cout << "Creating Surface" << std::endl; + // for(VkPhysicalDevice device: physicalDevices){ - createInfo.pEnabledFeatures = &deviceFeatures; - createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); - createInfo.ppEnabledExtensionNames = deviceExtensions.data(); + // window.createWindowSurface(instance, &surface_); + // surfaces.push_back(surface_); - // might not really be necessary anymore because device specific validation layers - // have been deprecated - if (enableValidationLayers) { - createInfo.enabledLayerCount = static_cast(validationLayers.size()); - createInfo.ppEnabledLayerNames = validationLayers.data(); - } else { - createInfo.enabledLayerCount = 0; + // } + window.createWindowSurface(instance, &surface_); } - VkDevice device_; - if (vkCreateDevice(physicalDevices[i], &createInfo, nullptr, &device_) != VK_SUCCESS) { - throw std::runtime_error("failed to create logical device!"); + + void CFXDevice::populateDebugMessengerCreateInfo( + VkDebugUtilsMessengerCreateInfoEXT &createInfo) + { + createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + createInfo.pfnUserCallback = debugCallback; + createInfo.pUserData = nullptr; // Optional } - - vkGetDeviceQueue(device_, indices.graphicsFamily, 0, &graphicsQueues[i]); - vkGetDeviceQueue(device_, indices.presentFamily, 0, &presentQueues[i]); - devices_[i] = device_; - createCommandPool(i); - // std::cout<< "LOGICAL DEVICE CREATED " << i << std::endl; + void CFXDevice::setupDebugMessenger() + { + if (!enableValidationLayers) + return; + VkDebugUtilsMessengerCreateInfoEXT createInfo; + populateDebugMessengerCreateInfo(createInfo); + if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) + { + throw std::runtime_error("failed to set up debug messenger!"); + } } - - - + bool CFXDevice::checkValidationLayerSupport() + { + uint32_t layerCount; + vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + + std::vector availableLayers(layerCount); + vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + + for (const char *layerName : validationLayers) + { + bool layerFound = false; + + for (const auto &layerProperties : availableLayers) + { + if (strcmp(layerName, layerProperties.layerName) == 0) + { + layerFound = true; + break; + } + } + if (!layerFound) + { + return false; + } + } - - + return true; + } - - - + std::vector CFXDevice::getRequiredExtensions() + { + uint32_t glfwExtensionCount = 0; + const char **glfwExtensions; + glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); - -} + std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); -void CFXDevice::createCommandPool(int deviceIndex) { - // std::cout << "CREATE COMMAND POOL " << deviceIndex << std::endl; - QueueFamilyIndices queueFamilyIndices = findPhysicalQueueFamilies(deviceIndex); - VkCommandPoolCreateInfo poolInfo = {}; - poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily; - poolInfo.flags = - VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + if (enableValidationLayers) + { + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } - if (vkCreateCommandPool(devices_[deviceIndex], &poolInfo, nullptr, &commandPools[deviceIndex]) != VK_SUCCESS) { - throw std::runtime_error("failed to create command pool!"); + return extensions; } - - - - -} - -void CFXDevice::createSurface() { - // std::cout << "Creating Surface" << std::endl; - // for(VkPhysicalDevice device: physicalDevices){ - - // window.createWindowSurface(instance, &surface_); - // surfaces.push_back(surface_); - - // } - window.createWindowSurface(instance, &surface_); - - - - - } - - -void CFXDevice::populateDebugMessengerCreateInfo( - VkDebugUtilsMessengerCreateInfoEXT &createInfo) { - createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; - createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | - VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; - createInfo.pfnUserCallback = debugCallback; - createInfo.pUserData = nullptr; // Optional -} - -void CFXDevice::setupDebugMessenger() { - if (!enableValidationLayers) return; - VkDebugUtilsMessengerCreateInfoEXT createInfo; - populateDebugMessengerCreateInfo(createInfo); - if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) { - throw std::runtime_error("failed to set up debug messenger!"); + + void CFXDevice::hasGflwRequiredInstanceExtensions() + { + uint32_t extensionCount = 0; + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); + std::vector extensions(extensionCount); + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); + + std::cout << "available extensions:" << std::endl; + std::unordered_set available; + for (const auto &extension : extensions) + { + std::cout << "\t" << extension.extensionName << std::endl; + available.insert(extension.extensionName); + } + + std::cout << "required extensions:" << std::endl; + auto requiredExtensions = getRequiredExtensions(); + for (const auto &required : requiredExtensions) + { + std::cout << "\t" << required << std::endl; + if (available.find(required) == available.end()) + { + throw std::runtime_error("Missing required glfw extension"); + } + } } -} -bool CFXDevice::checkValidationLayerSupport() { - uint32_t layerCount; - vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + bool CFXDevice::checkDeviceExtensionSupport(VkPhysicalDevice device) + { + uint32_t extensionCount; + vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); - std::vector availableLayers(layerCount); - vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + std::vector availableExtensions(extensionCount); + vkEnumerateDeviceExtensionProperties( + device, + nullptr, + &extensionCount, + availableExtensions.data()); - for (const char *layerName : validationLayers) { - bool layerFound = false; + std::set requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); - for (const auto &layerProperties : availableLayers) { - if (strcmp(layerName, layerProperties.layerName) == 0) { - layerFound = true; - break; - } + for (const auto &extension : availableExtensions) + { + requiredExtensions.erase(extension.extensionName); } - if (!layerFound) { - return false; - } + return requiredExtensions.empty(); } - return true; -} + QueueFamilyIndices CFXDevice::findQueueFamilies(std::vector devices, int deviceIndex) + { + + QueueFamilyIndices indices; + uint32_t queueFamilyCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(devices[deviceIndex], &queueFamilyCount, nullptr); -std::vector CFXDevice::getRequiredExtensions() { - uint32_t glfwExtensionCount = 0; - const char **glfwExtensions; - glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + std::vector queueFamilies(queueFamilyCount); + vkGetPhysicalDeviceQueueFamilyProperties(devices[deviceIndex], &queueFamilyCount, queueFamilies.data()); - std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + int j = 0; + for (const auto &queueFamily : queueFamilies) + { + if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + indices.graphicsFamily = j; + indices.graphicsFamilyHasValue = true; + } + VkBool32 presentSupport = false; + vkGetPhysicalDeviceSurfaceSupportKHR(devices[deviceIndex], j, surface_, &presentSupport); + if (queueFamily.queueCount > 0 && presentSupport) + { + indices.presentFamily = j; + indices.presentFamilyHasValue = true; + } + if (indices.isComplete()) + { + break; + } + + j++; + } - if (enableValidationLayers) { - extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + return indices; } - return extensions; -} + SwapChainSupportDetails CFXDevice::querySwapChainSupport(VkPhysicalDevice device) + { -void CFXDevice::hasGflwRequiredInstanceExtensions() { - uint32_t extensionCount = 0; - vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); - std::vector extensions(extensionCount); - vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); + SwapChainSupportDetails details; + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface_, &details.capabilities); - std::cout << "available extensions:" << std::endl; - std::unordered_set available; - for (const auto &extension : extensions) { - std::cout << "\t" << extension.extensionName << std::endl; - available.insert(extension.extensionName); - } + uint32_t formatCount; + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, nullptr); - std::cout << "required extensions:" << std::endl; - auto requiredExtensions = getRequiredExtensions(); - for (const auto &required : requiredExtensions) { - std::cout << "\t" << required << std::endl; - if (available.find(required) == available.end()) { - throw std::runtime_error("Missing required glfw extension"); + if (formatCount != 0) + { + details.formats.resize(formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, details.formats.data()); } - } -} -bool CFXDevice::checkDeviceExtensionSupport(VkPhysicalDevice device) { - uint32_t extensionCount; - vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); + uint32_t presentModeCount; + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface_, &presentModeCount, nullptr); + + if (presentModeCount != 0) + { + details.presentModes.resize(presentModeCount); + vkGetPhysicalDeviceSurfacePresentModesKHR( + device, + surface_, + &presentModeCount, + details.presentModes.data()); + } + return details; + } - std::vector availableExtensions(extensionCount); - vkEnumerateDeviceExtensionProperties( - device, - nullptr, - &extensionCount, - availableExtensions.data()); + VkFormat CFXDevice::findSupportedFormat( + const std::vector &candidates, VkImageTiling tiling, VkFormatFeatureFlags features) + { + for (VkFormat format : candidates) + { + VkFormatProperties props; + vkGetPhysicalDeviceFormatProperties(physicalDevices[0], format, &props); + + if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) + { + return format; + } + else if ( + tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) + { + return format; + } + } + throw std::runtime_error("failed to find supported format!"); + } - std::set requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); + uint32_t CFXDevice::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties, int deviceIndex) + { + VkPhysicalDeviceMemoryProperties memProperties; + vkGetPhysicalDeviceMemoryProperties(physicalDevices[deviceIndex], &memProperties); + + for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) + { + if ((typeFilter & (1 << i)) && + (memProperties.memoryTypes[i].propertyFlags & properties) == properties) + { + VkPeerMemoryFeatureFlags memoryFlags{}; + vkGetDeviceGroupPeerMemoryFeatures(devices_[deviceIndex], i, deviceIndex != 0 ? deviceIndices[deviceIndex - 1] : deviceIndices[deviceIndex], deviceIndex == 0 ? deviceIndices[deviceIndex + 1] : deviceIndices[deviceIndex], &memoryFlags); + memProperties.memoryHeaps[i].flags = memoryFlags; + + return i; + } + } - for (const auto &extension : availableExtensions) { - requiredExtensions.erase(extension.extensionName); + throw std::runtime_error("failed to find suitable memory type!"); } - return requiredExtensions.empty(); -} + void CFXDevice::createBuffer( + VkDeviceSize size, + VkBufferUsageFlags usage, + VkMemoryPropertyFlags properties, + VkBuffer &buffer, + VkDeviceMemory &bufferMemory, int deviceIndex) + { + + std::vector bufferMemoryInfos{}; + VkBufferCreateInfo bufferInfo{}; + bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + bufferInfo.size = size; + bufferInfo.usage = usage; + bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + if (vkCreateBuffer(devices_[deviceIndex], &bufferInfo, nullptr, &buffer) != VK_SUCCESS) + { + throw std::runtime_error("failed to create vertex buffer!"); + } -QueueFamilyIndices CFXDevice::findQueueFamilies(std::vector devices,int deviceIndex) { - - QueueFamilyIndices indices; - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(devices[deviceIndex], &queueFamilyCount, nullptr); + VkMemoryRequirements memRequirements{}; + vkGetBufferMemoryRequirements(devices_[deviceIndex], buffer, &memRequirements); - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(devices[deviceIndex], &queueFamilyCount, queueFamilies.data()); + VkMemoryAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocInfo.allocationSize = memRequirements.size; + allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties, deviceIndex); - int j = 0; - for (const auto &queueFamily : queueFamilies) { - if (queueFamily.queueCount > 0 && queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphicsFamily = j; - indices.graphicsFamilyHasValue = true; + if (vkAllocateMemory(devices_[deviceIndex], &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) + { + throw std::runtime_error("failed to allocate vertex buffer memory!"); } - VkBool32 presentSupport = false; - vkGetPhysicalDeviceSurfaceSupportKHR(devices[deviceIndex], j, surface_, &presentSupport); - if (queueFamily.queueCount > 0 && presentSupport) { - indices.presentFamily = j; - indices.presentFamilyHasValue = true; + + VkBindBufferMemoryInfo memoryInfo{}; + memoryInfo.sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO; + memoryInfo.buffer = buffer; + memoryInfo.memory = bufferMemory; + memoryInfo.memoryOffset = 0; + + bufferMemoryInfos.push_back(memoryInfo); + if (vkBindBufferMemory2(devices_[deviceIndex], 1, bufferMemoryInfos.data()) != VK_SUCCESS) + { + throw std::runtime_error("failed to bind Buffer memory 2 !"); } - if (indices.isComplete()) { - break; + else + { + // std::cout << "Bind Buffer MEMORY 2 succeeded" < &candidates, VkImageTiling tiling, VkFormatFeatureFlags features) { - for (VkFormat format : candidates) { - VkFormatProperties props; - vkGetPhysicalDeviceFormatProperties(physicalDevices[0], format, &props); + vkQueueSubmit(graphicsQueues[deviceIndex], 1, &submitInfo, VK_NULL_HANDLE); + vkQueueWaitIdle(graphicsQueues[deviceIndex]); - if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) { - return format; - } else if ( - tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) { - return format; - } - } - throw std::runtime_error("failed to find supported format!"); -} - -uint32_t CFXDevice::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties,int deviceIndex) { - VkPhysicalDeviceMemoryProperties memProperties; - vkGetPhysicalDeviceMemoryProperties(physicalDevices[deviceIndex], &memProperties); - - for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) { - if ((typeFilter & (1 << i)) && - (memProperties.memoryTypes[i].propertyFlags & properties) == properties) { - VkPeerMemoryFeatureFlags memoryFlags{}; - vkGetDeviceGroupPeerMemoryFeatures(devices_[deviceIndex],i, deviceIndex !=0 ? deviceIndices[deviceIndex -1]:deviceIndices[deviceIndex],deviceIndex ==0 ? deviceIndices[deviceIndex+1] : deviceIndices[deviceIndex],&memoryFlags); - memProperties.memoryHeaps[i].flags = memoryFlags; - - return i; - } + vkFreeCommandBuffers(devices_[deviceIndex], commandPools[deviceIndex], 1, &commandBuffer); } - throw std::runtime_error("failed to find suitable memory type!"); -} - -void CFXDevice::createBuffer( - VkDeviceSize size, - VkBufferUsageFlags usage, - VkMemoryPropertyFlags properties, - VkBuffer &buffer, - VkDeviceMemory &bufferMemory, int deviceIndex) { - - - std::vector bufferMemoryInfos{}; - VkBufferCreateInfo bufferInfo{}; - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = size; - bufferInfo.usage = usage; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - if (vkCreateBuffer(devices_[deviceIndex], &bufferInfo, nullptr, &buffer) != VK_SUCCESS) { - throw std::runtime_error("failed to create vertex buffer!"); - } + void CFXDevice::copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size, int deviceIndex) + { + VkCommandBuffer commandBuffer = beginSingleTimeCommands(deviceIndex); + // for(VkCommandBuffer commandBuffer: commandBuffers){ - VkMemoryRequirements memRequirements{}; - vkGetBufferMemoryRequirements(devices_[deviceIndex], buffer, &memRequirements); - - VkMemoryAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memRequirements.size; - allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties,deviceIndex); + // } + VkBufferCopy copyRegion{}; + copyRegion.srcOffset = 0; // Optional + copyRegion.dstOffset = 0; // Optional + copyRegion.size = size; + vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region); - if (vkAllocateMemory(devices_[deviceIndex], &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) { - throw std::runtime_error("failed to allocate vertex buffer memory!"); + endSingleTimeCommands(commandBuffer, deviceIndex); } - VkBindBufferMemoryInfo memoryInfo{}; - memoryInfo.sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO; - memoryInfo.buffer = buffer; - memoryInfo.memory = bufferMemory; - memoryInfo.memoryOffset = 0; - - bufferMemoryInfos.push_back(memoryInfo); - if(vkBindBufferMemory2(devices_[deviceIndex],1,bufferMemoryInfos.data())!=VK_SUCCESS){ - throw std::runtime_error("failed to bind Buffer memory 2 !"); - }else{ - // std::cout << "Bind Buffer MEMORY 2 succeeded" < #include -namespace cfx { - -struct SwapChainSupportDetails { - VkSurfaceCapabilitiesKHR capabilities; - std::vector formats; - std::vector presentModes; -}; - -struct QueueFamilyIndices { - uint32_t graphicsFamily; - uint32_t presentFamily; - uint32_t transferFamily; - bool graphicsFamilyHasValue = false; - bool presentFamilyHasValue = false; - bool transferFamilyHasValue = false; - bool isComplete() { return graphicsFamilyHasValue && presentFamilyHasValue && transferFamilyHasValue; } -}; - -class CFXDevice { - public: +namespace cfx +{ + + struct SwapChainSupportDetails + { + VkSurfaceCapabilitiesKHR capabilities; + std::vector formats; + std::vector presentModes; + }; + + struct QueueFamilyIndices + { + uint32_t graphicsFamily; + uint32_t presentFamily; + uint32_t transferFamily; + bool graphicsFamilyHasValue = false; + bool presentFamilyHasValue = false; + bool transferFamilyHasValue = false; + bool isComplete() { return graphicsFamilyHasValue && presentFamilyHasValue && transferFamilyHasValue; } + }; + + class CFXDevice + { + public: #ifdef NDEBUG - const bool enableValidationLayers = false; + const bool enableValidationLayers = false; #else - const bool enableValidationLayers = true; + const bool enableValidationLayers = true; #endif - CFXDevice(CFXWindow &window); - ~CFXDevice(); - - // Not copyable or movable - CFXDevice(const CFXDevice &) = delete; - void operator=(const CFXDevice &) = delete; - CFXDevice(CFXDevice &&) = delete; - CFXDevice &operator=(CFXDevice &&) = delete; - - VkCommandPool getCommandPool(int deviceIndex) { return commandPools[deviceIndex]; } - VkDevice device(int deviceIndex) { return devices_[deviceIndex]; } - std::vector getPhysicalDevices(){return physicalDevices;} - std::vector getDeviceRects(){return deviceRects;} - VkSurfaceKHR surface() { return surface_; } - VkQueue getGraphicsQueues(int deviceIndex) { return graphicsQueues[deviceIndex]; } - VkQueue getPresentQueues(int deviceIndex) { return presentQueues[deviceIndex]; } - int getDevicesinDeviceGroup(){return deviceCount; } - VkInstance getInstance() {return instance;} - std::string getDeviceName(int deviceIndex){ - return deviceNames[deviceIndex]; - } - uint32_t getDeviceId(int deviceIndex){ - return deviceIds[deviceIndex]; - } - std::vector getDeviceIds(){ - return deviceIds; - } - std::vector getDeviceMasks(){ - return deviceMasks; - } - - SwapChainSupportDetails getSwapChainSupport(int deviceIndex) { return querySwapChainSupport(physicalDevices[deviceIndex]); } - uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties,int deviceIndex); - QueueFamilyIndices findPhysicalQueueFamilies(int deviceIndex) { return findQueueFamilies(physicalDevices,deviceIndex); } - VkFormat findSupportedFormat( - const std::vector &candidates, VkImageTiling tiling, VkFormatFeatureFlags features); - - // Buffer Helper Functions - void createBuffer( - VkDeviceSize size, - VkBufferUsageFlags usage, - VkMemoryPropertyFlags properties, - VkBuffer &buffer, - VkDeviceMemory &bufferMemory,int deviceIndex); - VkCommandBuffer beginSingleTimeCommands(int deviceIndex); - void endSingleTimeCommands(VkCommandBuffer commandBuffer,int deviceIndex); - void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size, int deviceIndex); - void copyBufferToImage( - VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t layerCount,int deviceIndex); - - void createImageWithInfo( - const VkImageCreateInfo &imageInfo, - VkMemoryPropertyFlags properties, - VkImage &image, - VkDeviceMemory &imageMemory, int deviceIndex); - - std::vector properties; - - private: - void createInstance(); - void setupDebugMessenger(); - void createSurface(); - void createDeviceGroups(); - void createLogicalDevice(); - void createCommandPool(int deviceIndex); - - - std::vector getRequiredExtensions(); - bool checkValidationLayerSupport(); - QueueFamilyIndices findQueueFamilies(std::vector devices,int deviceIndex); - void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo); - void hasGflwRequiredInstanceExtensions(); - bool checkDeviceExtensionSupport(VkPhysicalDevice device); - SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); - - VkInstance instance; - VkDebugUtilsMessengerEXT debugMessenger; - std::vector physicalDevices; - CFXWindow &window; - std::vector commandPools; - uint32_t deviceGroupCount = 0; - std::vector physicalDeviceGroupProperties; - - std::vector devices_; - VkSurfaceKHR surface_; - uint32_t deviceCount = 0; - - std::vector graphicsQueues; - std::vector presentQueues; - std::vector transferQueues; - // VkQueue graphicsQueue; - // VkQueue presentQueue; - // VkQueue transferQueue; - std::vector deviceRects; - std::vector deviceIds; - std::vector deviceNames; - - const std::vector validationLayers = {"VK_LAYER_KHRONOS_validation"}; - const std::vector deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; - std::vector deviceMasks; - std::vector deviceIndices; - -}; - -} // namespace lve \ No newline at end of file + CFXDevice(CFXWindow &window); + ~CFXDevice(); + + // Not copyable or movable + CFXDevice(const CFXDevice &) = delete; + void operator=(const CFXDevice &) = delete; + CFXDevice(CFXDevice &&) = delete; + CFXDevice &operator=(CFXDevice &&) = delete; + + VkCommandPool getCommandPool(int deviceIndex) { return commandPools[deviceIndex]; } + VkDevice device(int deviceIndex) { return devices_[deviceIndex]; } + std::vector getPhysicalDevices() { return physicalDevices; } + std::vector getDeviceRects() { return deviceRects; } + VkSurfaceKHR surface() { return surface_; } + VkQueue getGraphicsQueues(int deviceIndex) { return graphicsQueues[deviceIndex]; } + VkQueue getPresentQueues(int deviceIndex) { return presentQueues[deviceIndex]; } + int getDevicesinDeviceGroup() { return deviceCount; } + VkInstance getInstance() { return instance; } + std::string getDeviceName(int deviceIndex) + { + return deviceNames[deviceIndex]; + } + uint32_t getDeviceId(int deviceIndex) + { + return deviceIds[deviceIndex]; + } + std::vector getDeviceIds() + { + return deviceIds; + } + std::vector getDeviceMasks() + { + return deviceMasks; + } + + SwapChainSupportDetails getSwapChainSupport(int deviceIndex) { return querySwapChainSupport(physicalDevices[deviceIndex]); } + uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties, int deviceIndex); + QueueFamilyIndices findPhysicalQueueFamilies(int deviceIndex) { return findQueueFamilies(physicalDevices, deviceIndex); } + VkFormat findSupportedFormat( + const std::vector &candidates, VkImageTiling tiling, VkFormatFeatureFlags features); + + // Buffer Helper Functions + void createBuffer( + VkDeviceSize size, + VkBufferUsageFlags usage, + VkMemoryPropertyFlags properties, + VkBuffer &buffer, + VkDeviceMemory &bufferMemory, int deviceIndex); + VkCommandBuffer beginSingleTimeCommands(int deviceIndex); + void endSingleTimeCommands(VkCommandBuffer commandBuffer, int deviceIndex); + void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size, int deviceIndex); + void copyBufferToImage( + VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t layerCount, int deviceIndex); + + void createImageWithInfo( + const VkImageCreateInfo &imageInfo, + VkMemoryPropertyFlags properties, + VkImage &image, + VkDeviceMemory &imageMemory, int deviceIndex); + + std::vector properties; + + private: + void createInstance(); + void setupDebugMessenger(); + void createSurface(); + void createDeviceGroups(); + void createLogicalDevice(); + void createCommandPool(int deviceIndex); + + std::vector getRequiredExtensions(); + bool checkValidationLayerSupport(); + QueueFamilyIndices findQueueFamilies(std::vector devices, int deviceIndex); + void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo); + void hasGflwRequiredInstanceExtensions(); + bool checkDeviceExtensionSupport(VkPhysicalDevice device); + SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); + + VkInstance instance; + VkDebugUtilsMessengerEXT debugMessenger; + std::vector physicalDevices; + CFXWindow &window; + std::vector commandPools; + uint32_t deviceGroupCount = 0; + std::vector physicalDeviceGroupProperties; + + std::vector devices_; + VkSurfaceKHR surface_; + uint32_t deviceCount = 0; + + std::vector graphicsQueues; + std::vector presentQueues; + std::vector transferQueues; + // VkQueue graphicsQueue; + // VkQueue presentQueue; + // VkQueue transferQueue; + std::vector deviceRects; + std::vector deviceIds; + std::vector deviceNames; + + const std::vector validationLayers = {"VK_LAYER_KHRONOS_validation"}; + const std::vector deviceExtensions = {VK_KHR_SWAPCHAIN_EXTENSION_NAME}; + std::vector deviceMasks; + std::vector deviceIndices; + }; + +} // namespace lve \ No newline at end of file diff --git a/src/cfx_game_object.hpp b/src/cfx_game_object.hpp index b64f22e..9929c9e 100644 --- a/src/cfx_game_object.hpp +++ b/src/cfx_game_object.hpp @@ -3,49 +3,48 @@ #include #include -namespace cfx{ +namespace cfx +{ - struct TransformComponent { + struct TransformComponent + { glm::vec3 translation{}; - glm::vec3 scale{1.f,1.f,1.f}; + glm::vec3 scale{1.f, 1.f, 1.f}; glm::vec3 rotation{}; - glm::mat4 mat4(){ - auto transform = glm::translate(glm::mat4{1.f},translation); - transform = glm::rotate(transform,rotation.y,{0.f,1.f,0.f}); - transform = glm::rotate(transform,rotation.x,{1.f,0.f,0.f}); - transform = glm::rotate(transform,rotation.z,{0.f,0.f,1.f}); - transform = glm:: scale(transform,scale); + glm::mat4 mat4() + { + auto transform = glm::translate(glm::mat4{1.f}, translation); + transform = glm::rotate(transform, rotation.y, {0.f, 1.f, 0.f}); + transform = glm::rotate(transform, rotation.x, {1.f, 0.f, 0.f}); + transform = glm::rotate(transform, rotation.z, {0.f, 0.f, 1.f}); + transform = glm::scale(transform, scale); return transform; - - } }; - - class CFXGameObject{ - public: + class CFXGameObject + { + public: using id_t = unsigned int; - static CFXGameObject createGameObject(){ + static CFXGameObject createGameObject() + { static id_t currentId = 0; return CFXGameObject{currentId++}; - } CFXGameObject(const CFXGameObject &) = delete; CFXGameObject &operator=(const CFXGameObject &) = delete; CFXGameObject(CFXGameObject &&) = default; CFXGameObject &operator=(CFXGameObject &&) = default; - id_t getId() { return id;} + id_t getId() { return id; } std::shared_ptr model{}; glm::vec3 color{}; TransformComponent transformComponent{}; - private: + private: id_t id; - CFXGameObject(id_t objId): id{objId} { - + CFXGameObject(id_t objId) : id{objId} + { } - - }; } \ No newline at end of file diff --git a/src/cfx_model.cpp b/src/cfx_model.cpp index d4c48b5..bccab93 100644 --- a/src/cfx_model.cpp +++ b/src/cfx_model.cpp @@ -11,205 +11,212 @@ #include -namespace std{ - template<> - struct hash{ - size_t operator()(cfx::CFXModel::Vertex const &vertex) const{ +namespace std +{ + template <> + struct hash + { + size_t operator()(cfx::CFXModel::Vertex const &vertex) const + { size_t seed = 0; - cfx::hashCombine(seed,vertex.position,vertex.color,vertex.normal,vertex.uv); - + cfx::hashCombine(seed, vertex.position, vertex.color, vertex.normal, vertex.uv); + // cout << "SEED " << seed << endl; return seed; } }; } - - -namespace cfx{ - CFXModel::CFXModel(CFXDevice& device,const CFXModel::Builder &builder): cfxDevice{device} +namespace cfx +{ + CFXModel::CFXModel(CFXDevice &device, const CFXModel::Builder &builder) : cfxDevice{device} { vertexBuffer.resize(cfxDevice.getDevicesinDeviceGroup()); vertexBufferMemory.resize(cfxDevice.getDevicesinDeviceGroup()); indexBuffer.resize(cfxDevice.getDevicesinDeviceGroup()); indexBufferMemory.resize(cfxDevice.getDevicesinDeviceGroup()); - for(int i = 0; i < cfxDevice.getDevicesinDeviceGroup();i++){ - createVertexBuffers(builder.vertices,i); - createIndexBuffers(builder.indices,i); + for (int i = 0; i < cfxDevice.getDevicesinDeviceGroup(); i++) + { + createVertexBuffers(builder.vertices, i); + createIndexBuffers(builder.indices, i); } - } - CFXModel::~CFXModel(){ - for(int i=0; i CFXModel::createModelFromFile(CFXDevice &device,const std::string &filepath){ + std::unique_ptr CFXModel::createModelFromFile(CFXDevice &device, const std::string &filepath) + { Builder builder{}; builder.loadModel(filepath); // std::cout << "Vertex Count "<< builder.vertices.size() << std::endl; - return std::make_unique(device,builder); + return std::make_unique(device, builder); } - void CFXModel::createVertexBuffers(const std::vector &vertices,int deviceIndex){ + void CFXModel::createVertexBuffers(const std::vector &vertices, int deviceIndex) + { vertexCount = static_cast(vertices.size()); assert(vertexCount >= 3 && "Vertex count must be at least 3"); VkDeviceSize bufferSize = sizeof(vertices[0]) * vertexCount; VkBuffer stagingBuffer; VkDeviceMemory stagingBufferMemory; cfxDevice.createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - stagingBuffer, - stagingBufferMemory, deviceIndex); + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + stagingBuffer, + stagingBufferMemory, deviceIndex); void *data; - vkMapMemory(cfxDevice.device(deviceIndex),stagingBufferMemory,0,bufferSize,0,&data); - memcpy(data,vertices.data(),static_cast(bufferSize)); - vkUnmapMemory(cfxDevice.device(deviceIndex),stagingBufferMemory); + vkMapMemory(cfxDevice.device(deviceIndex), stagingBufferMemory, 0, bufferSize, 0, &data); + memcpy(data, vertices.data(), static_cast(bufferSize)); + vkUnmapMemory(cfxDevice.device(deviceIndex), stagingBufferMemory); cfxDevice.createBuffer(bufferSize, - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - vertexBuffer[deviceIndex], - vertexBufferMemory[deviceIndex],deviceIndex); - - cfxDevice.copyBuffer(stagingBuffer,vertexBuffer[deviceIndex],bufferSize,deviceIndex); - vkDestroyBuffer(cfxDevice.device(deviceIndex),stagingBuffer,nullptr); - vkFreeMemory(cfxDevice.device(deviceIndex),stagingBufferMemory,nullptr); - - - + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + vertexBuffer[deviceIndex], + vertexBufferMemory[deviceIndex], deviceIndex); + + cfxDevice.copyBuffer(stagingBuffer, vertexBuffer[deviceIndex], bufferSize, deviceIndex); + vkDestroyBuffer(cfxDevice.device(deviceIndex), stagingBuffer, nullptr); + vkFreeMemory(cfxDevice.device(deviceIndex), stagingBufferMemory, nullptr); } - void CFXModel::createIndexBuffers(const std::vector &indices, int deviceIndex){ - indexCount = static_cast(indices.size()); + void CFXModel::createIndexBuffers(const std::vector &indices, int deviceIndex) + { + indexCount = static_cast(indices.size()); hasIndexBuffer = indexCount > 0; - if(!hasIndexBuffer){ + if (!hasIndexBuffer) + { return; } VkDeviceSize bufferSize = sizeof(indices[0]) * indexCount; VkBuffer stagingBuffer; VkDeviceMemory stagingBufferMemory; cfxDevice.createBuffer(bufferSize, - VK_BUFFER_USAGE_TRANSFER_SRC_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - stagingBuffer, - stagingBufferMemory,deviceIndex); + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + stagingBuffer, + stagingBufferMemory, deviceIndex); void *data; - vkMapMemory(cfxDevice.device(deviceIndex),stagingBufferMemory,0,bufferSize,0,&data); - memcpy(data,indices.data(),static_cast(bufferSize)); - vkUnmapMemory(cfxDevice.device(deviceIndex),stagingBufferMemory); - - cfxDevice.createBuffer(bufferSize, - VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, - VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, - indexBuffer[deviceIndex], - indexBufferMemory[deviceIndex],deviceIndex); - - cfxDevice.copyBuffer(stagingBuffer,indexBuffer[deviceIndex],bufferSize,deviceIndex); - vkDestroyBuffer(cfxDevice.device(deviceIndex),stagingBuffer,nullptr); - vkFreeMemory(cfxDevice.device(deviceIndex),stagingBufferMemory,nullptr); - - + vkMapMemory(cfxDevice.device(deviceIndex), stagingBufferMemory, 0, bufferSize, 0, &data); + memcpy(data, indices.data(), static_cast(bufferSize)); + vkUnmapMemory(cfxDevice.device(deviceIndex), stagingBufferMemory); + cfxDevice.createBuffer(bufferSize, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + indexBuffer[deviceIndex], + indexBufferMemory[deviceIndex], deviceIndex); + + cfxDevice.copyBuffer(stagingBuffer, indexBuffer[deviceIndex], bufferSize, deviceIndex); + vkDestroyBuffer(cfxDevice.device(deviceIndex), stagingBuffer, nullptr); + vkFreeMemory(cfxDevice.device(deviceIndex), stagingBufferMemory, nullptr); } - void CFXModel::draw(VkCommandBuffer commandBuffer){ - if(hasIndexBuffer){ - vkCmdDrawIndexed(commandBuffer,indexCount,1,0,0,0); - }else{ - vkCmdDraw(commandBuffer,vertexCount,1,0,0); + void CFXModel::draw(VkCommandBuffer commandBuffer) + { + if (hasIndexBuffer) + { + vkCmdDrawIndexed(commandBuffer, indexCount, 1, 0, 0, 0); + } + else + { + vkCmdDraw(commandBuffer, vertexCount, 1, 0, 0); } - } - void CFXModel::bind(VkCommandBuffer commandBuffer,int deviceIndex){ + void CFXModel::bind(VkCommandBuffer commandBuffer, int deviceIndex) + { // std::cout << "BIND OBJECT TO COMMAND BUFFER " < CFXModel::Vertex::getBindingDescriptions(){ + std::vector CFXModel::Vertex::getBindingDescriptions() + { std::vector bindingDescriptions(1); bindingDescriptions[0].binding = 0; - bindingDescriptions[0].stride =sizeof(Vertex); + bindingDescriptions[0].stride = sizeof(Vertex); bindingDescriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX; return bindingDescriptions; } - std::vector CFXModel::Vertex::getAttributeDescriptions(){ + std::vector CFXModel::Vertex::getAttributeDescriptions() + { std::vector inputAttributeDescriptions{}; - inputAttributeDescriptions.push_back({0,0,VK_FORMAT_R32G32B32_SFLOAT,offsetof(Vertex,position)}); - inputAttributeDescriptions.push_back({1,0,VK_FORMAT_R32G32B32_SFLOAT,offsetof(Vertex,color)}); - inputAttributeDescriptions.push_back({2,0,VK_FORMAT_R32G32B32_SFLOAT,offsetof(Vertex,normal)}); - inputAttributeDescriptions.push_back({3,0,VK_FORMAT_R32G32_SFLOAT,offsetof(Vertex,uv)}); + inputAttributeDescriptions.push_back({0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, position)}); + inputAttributeDescriptions.push_back({1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, color)}); + inputAttributeDescriptions.push_back({2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(Vertex, normal)}); + inputAttributeDescriptions.push_back({3, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(Vertex, uv)}); return inputAttributeDescriptions; - } - void CFXModel::Builder::loadModel(const std::string &filepath){ + void CFXModel::Builder::loadModel(const std::string &filepath) + { tinyobj::attrib_t attrib; std::vector shapes; std::vector materials; std::string warn; std::string error; - if(!tinyobj::LoadObj(&attrib,&shapes,&materials,&warn,&error,filepath.c_str())){ - throw std::runtime_error(warn+error); + if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &error, filepath.c_str())) + { + throw std::runtime_error(warn + error); } vertices.clear(); indices.clear(); - std::unordered_map uniqueVertices{}; + std::unordered_map uniqueVertices{}; - for(const auto &shape : shapes){ - for(const auto &index : shape.mesh.indices){ + for (const auto &shape : shapes) + { + for (const auto &index : shape.mesh.indices) + { Vertex vertex{}; - if(index.vertex_index >= 0){ + if (index.vertex_index >= 0) + { vertex.position = { - attrib.vertices[3* index.vertex_index + 0], - attrib.vertices[3* index.vertex_index + 1], - attrib.vertices[3* index.vertex_index + 2], + attrib.vertices[3 * index.vertex_index + 0], + attrib.vertices[3 * index.vertex_index + 1], + attrib.vertices[3 * index.vertex_index + 2], }; - vertex.color = { - attrib.colors[3* index.vertex_index + 0], - attrib.colors[3* index.vertex_index + 1], - attrib.colors[3* index.vertex_index + 2], + vertex.color = { + attrib.colors[3 * index.vertex_index + 0], + attrib.colors[3 * index.vertex_index + 1], + attrib.colors[3 * index.vertex_index + 2], }; - - } - if(index.normal_index >= 0){ + if (index.normal_index >= 0) + { vertex.normal = { - attrib.normals[3* index.normal_index + 0], - attrib.normals[3* index.normal_index + 1], - attrib.normals[3* index.normal_index + 2], + attrib.normals[3 * index.normal_index + 0], + attrib.normals[3 * index.normal_index + 1], + attrib.normals[3 * index.normal_index + 2], }; - } - if(index.texcoord_index >= 0){ + if (index.texcoord_index >= 0) + { vertex.uv = { - attrib.texcoords[3* index.texcoord_index + 0], - attrib.texcoords[3* index.normal_index + 1], - - }; - + attrib.texcoords[3 * index.texcoord_index + 0], + attrib.texcoords[3 * index.normal_index + 1], + }; } - if(uniqueVertices.count(vertex)== 0){ - + if (uniqueVertices.count(vertex) == 0) + { + // std::cout << "VERTEX ARRAY SIZE " << static_cast(vertices.size()) << std::endl; uniqueVertices[vertex] = static_cast(vertices.size()); vertices.push_back(vertex); @@ -218,9 +225,7 @@ namespace cfx{ // std::cout << "VERTEX INDEX " << uniqueVertices[vertex] << std::endl; indices.push_back(uniqueVertices[vertex]); } - } - } } \ No newline at end of file diff --git a/src/cfx_model.hpp b/src/cfx_model.hpp index 2e7bb60..0613245 100644 --- a/src/cfx_model.hpp +++ b/src/cfx_model.hpp @@ -8,12 +8,13 @@ #include #include - - -namespace cfx { - class CFXModel{ - public: - struct Vertex{ +namespace cfx +{ + class CFXModel + { + public: + struct Vertex + { glm::vec3 position{}; glm::vec3 color{}; glm::vec3 normal{}; @@ -22,28 +23,31 @@ namespace cfx { static std::vector getBindingDescriptions(); static std::vector getAttributeDescriptions(); - bool operator==(const Vertex &other)const{ + bool operator==(const Vertex &other) const + { return position == other.position && color == other.color && normal == other.normal && uv == other.uv; } }; - struct Builder{ + struct Builder + { std::vector vertices{}; std::vector indices{}; void loadModel(const std::string &filepath); }; - CFXModel(CFXDevice& device,const CFXModel::Builder &builder); + CFXModel(CFXDevice &device, const CFXModel::Builder &builder); ~CFXModel(); CFXModel(const CFXModel &) = delete; CFXModel &operator=(const CFXModel &) = delete; - static std::unique_ptr createModelFromFile(CFXDevice &device,const std::string &filepath); + static std::unique_ptr createModelFromFile(CFXDevice &device, const std::string &filepath); - void bind(VkCommandBuffer commandBuffer,int deviceIndex); + void bind(VkCommandBuffer commandBuffer, int deviceIndex); void draw(VkCommandBuffer commandBuffer); - private: + + private: void createVertexBuffers(const std::vector &vertices, int deviceIndex); - void createIndexBuffers(const std::vector &indices,int deviceIndex); - CFXDevice& cfxDevice; + void createIndexBuffers(const std::vector &indices, int deviceIndex); + CFXDevice &cfxDevice; std::vector vertexBuffer; std::vector vertexBufferMemory; uint32_t vertexCount; @@ -51,7 +55,5 @@ namespace cfx { std::vector indexBuffer; std::vector indexBufferMemory; uint32_t indexCount; - - }; } \ No newline at end of file diff --git a/src/cfx_pipeline.cpp b/src/cfx_pipeline.cpp index 13fd43c..5a46f47 100644 --- a/src/cfx_pipeline.cpp +++ b/src/cfx_pipeline.cpp @@ -1,185 +1,188 @@ #include "cfx_pipeline.hpp" #include "cfx_model.hpp" -#include +#include #include #include -namespace cfx{ - CFXPipeLine::CFXPipeLine(CFXDevice& device, const PipelineConfigInfo& configInfo, const std::string& vertFilePath, const std::string& fragFilePath,int deviceIndex):cfxDevice{device},deviceIndex{deviceIndex}{ - // std::cout << "CREATING PIPELINE OBJECT" < CFXPipeLine::readFile(const std::string& filepath){ + std::vector CFXPipeLine::readFile(const std::string &filepath) + { std::ifstream file{filepath, std::ios::ate | std::ios::binary}; - if(!file.is_open()){ + if (!file.is_open()) + { throw std::runtime_error("failed to open file: " + filepath); } size_t fileSize = static_cast(file.tellg()); std::vector buffer(fileSize); file.seekg(0); - file.read(buffer.data(),fileSize); + file.read(buffer.data(), fileSize); file.close(); return buffer; - - } - void CFXPipeLine::createGraphicsPipeLine(const PipelineConfigInfo& configInfo,const std::string& vertFilePath, const std::string& fragFilePath, int deviceIndex){ + void CFXPipeLine::createGraphicsPipeLine(const PipelineConfigInfo &configInfo, const std::string &vertFilePath, const std::string &fragFilePath, int deviceIndex) + { // std::cout << "CREATING GRAPHICS PIPELINE " << deviceIndex << std::endl; assert(configInfo.pipelineLayout != VK_NULL_HANDLE && "Cannot create pipeline: no pipelineLayout provided in configInfo"); assert(configInfo.renderPass != VK_NULL_HANDLE && "Cannot create pipeline: no renderpass provided in configInfo"); auto vertCode = readFile(vertFilePath); auto fragCode = readFile(fragFilePath); - createShaderModule(vertCode,&vertShaderModule,deviceIndex); - createShaderModule(fragCode,&fragShaderModule,deviceIndex); - VkPipelineShaderStageCreateInfo shaderStages[2]; - shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shaderStages[0].module = vertShaderModule; - shaderStages[0].pName = "main"; - shaderStages[0].flags = 0; - shaderStages[0].pNext = nullptr; - shaderStages[0].pSpecializationInfo = nullptr; - - shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shaderStages[1].module = fragShaderModule; - shaderStages[1].pName = "main"; - shaderStages[1].flags = 0; - shaderStages[1].pNext = nullptr; - shaderStages[1].pSpecializationInfo = nullptr; - - auto bindingDescriptions = CFXModel::Vertex::getBindingDescriptions(); - auto attributeDescriptions = CFXModel::Vertex::getAttributeDescriptions(); - - - VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()); - vertexInputInfo.vertexBindingDescriptionCount = static_cast(bindingDescriptions.size()); - vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); - vertexInputInfo.pVertexBindingDescriptions = bindingDescriptions.data(); - - VkGraphicsPipelineCreateInfo pipelineInfo{}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.stageCount = 2; - pipelineInfo.pStages = shaderStages; - pipelineInfo.pVertexInputState = &vertexInputInfo; - pipelineInfo.pInputAssemblyState = &configInfo.inputAssemblyInfo; - pipelineInfo.pViewportState = &configInfo.viewportInfo; - pipelineInfo.pRasterizationState = &configInfo.rasterizationInfo; - pipelineInfo.pMultisampleState = &configInfo.multisampleInfo; - pipelineInfo.pColorBlendState = &configInfo.colorBlendInfo; - pipelineInfo.pDepthStencilState = &configInfo.depthStencilInfo; - pipelineInfo.pDynamicState = &configInfo.dynamicStateInfo; - - pipelineInfo.layout = configInfo.pipelineLayout; - pipelineInfo.renderPass = configInfo.renderPass; - pipelineInfo.subpass = configInfo.subpass; - - pipelineInfo.basePipelineIndex = -1; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - - if( vkCreateGraphicsPipelines(cfxDevice.device(deviceIndex),VK_NULL_HANDLE,1,&pipelineInfo,nullptr,&graphicsPipeline) != VK_SUCCESS ){ - throw std::runtime_error("Failed to create Graphics Pipeline"); - } - - - + createShaderModule(vertCode, &vertShaderModule, deviceIndex); + createShaderModule(fragCode, &fragShaderModule, deviceIndex); + VkPipelineShaderStageCreateInfo shaderStages[2]; + shaderStages[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + shaderStages[0].module = vertShaderModule; + shaderStages[0].pName = "main"; + shaderStages[0].flags = 0; + shaderStages[0].pNext = nullptr; + shaderStages[0].pSpecializationInfo = nullptr; + + shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + shaderStages[1].module = fragShaderModule; + shaderStages[1].pName = "main"; + shaderStages[1].flags = 0; + shaderStages[1].pNext = nullptr; + shaderStages[1].pSpecializationInfo = nullptr; + + auto bindingDescriptions = CFXModel::Vertex::getBindingDescriptions(); + auto attributeDescriptions = CFXModel::Vertex::getAttributeDescriptions(); + + VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputInfo.vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()); + vertexInputInfo.vertexBindingDescriptionCount = static_cast(bindingDescriptions.size()); + vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); + vertexInputInfo.pVertexBindingDescriptions = bindingDescriptions.data(); + + VkGraphicsPipelineCreateInfo pipelineInfo{}; + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.stageCount = 2; + pipelineInfo.pStages = shaderStages; + pipelineInfo.pVertexInputState = &vertexInputInfo; + pipelineInfo.pInputAssemblyState = &configInfo.inputAssemblyInfo; + pipelineInfo.pViewportState = &configInfo.viewportInfo; + pipelineInfo.pRasterizationState = &configInfo.rasterizationInfo; + pipelineInfo.pMultisampleState = &configInfo.multisampleInfo; + pipelineInfo.pColorBlendState = &configInfo.colorBlendInfo; + pipelineInfo.pDepthStencilState = &configInfo.depthStencilInfo; + pipelineInfo.pDynamicState = &configInfo.dynamicStateInfo; + + pipelineInfo.layout = configInfo.pipelineLayout; + pipelineInfo.renderPass = configInfo.renderPass; + pipelineInfo.subpass = configInfo.subpass; + + pipelineInfo.basePipelineIndex = -1; + pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; + + if (vkCreateGraphicsPipelines(cfxDevice.device(deviceIndex), VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Graphics Pipeline"); + } } - void CFXPipeLine::bind(VkCommandBuffer commandBuffer){ + void CFXPipeLine::bind(VkCommandBuffer commandBuffer) + { // std::cout << "BIND GRAPHICS PIPLELINE TO COMMAND BUFFER" <& code, VkShaderModule * shaderModule,int deviceIndex){ - + void CFXPipeLine::createShaderModule(const std::vector &code, VkShaderModule *shaderModule, int deviceIndex) + { + VkShaderModuleCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; createInfo.codeSize = code.size(); - createInfo.pCode = reinterpret_cast(code.data()); - if(vkCreateShaderModule(cfxDevice.device(deviceIndex),&createInfo,nullptr,shaderModule) != VK_SUCCESS){ + createInfo.pCode = reinterpret_cast(code.data()); + if (vkCreateShaderModule(cfxDevice.device(deviceIndex), &createInfo, nullptr, shaderModule) != VK_SUCCESS) + { throw std::runtime_error("Failed to create shader module"); } - } - void CFXPipeLine::defaultPipelineConfigInfo(PipelineConfigInfo &configInfo){ + void CFXPipeLine::defaultPipelineConfigInfo(PipelineConfigInfo &configInfo) + { // std::cout << "CREATING PIPELINE CONFIG INFO" <(configInfo.dynamicStateEnables.size()); - configInfo.dynamicStateInfo.flags = 0; + configInfo.inputAssemblyInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + configInfo.inputAssemblyInfo.primitiveRestartEnable = VK_FALSE; + + configInfo.viewportInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + configInfo.viewportInfo.viewportCount = 1; + configInfo.viewportInfo.pViewports = nullptr; + configInfo.viewportInfo.scissorCount = 1; + configInfo.viewportInfo.pScissors = nullptr; + + configInfo.rasterizationInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + configInfo.rasterizationInfo.depthClampEnable = VK_FALSE; + configInfo.rasterizationInfo.rasterizerDiscardEnable = VK_FALSE; + configInfo.rasterizationInfo.polygonMode = VK_POLYGON_MODE_FILL; + configInfo.rasterizationInfo.lineWidth = 1.0f; + configInfo.rasterizationInfo.cullMode = VK_CULL_MODE_NONE; + configInfo.rasterizationInfo.frontFace = VK_FRONT_FACE_CLOCKWISE; + configInfo.rasterizationInfo.depthBiasEnable = VK_FALSE; + configInfo.rasterizationInfo.depthBiasConstantFactor = 0.0f; // Optional + configInfo.rasterizationInfo.depthBiasClamp = 0.0f; // Optional + configInfo.rasterizationInfo.depthBiasSlopeFactor = 0.0f; // Optional + + configInfo.multisampleInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + configInfo.multisampleInfo.sampleShadingEnable = VK_FALSE; + configInfo.multisampleInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + configInfo.multisampleInfo.minSampleShading = 1.0f; // Optional + configInfo.multisampleInfo.pSampleMask = nullptr; // Optional + configInfo.multisampleInfo.alphaToCoverageEnable = VK_FALSE; // Optional + configInfo.multisampleInfo.alphaToOneEnable = VK_FALSE; // Optional + + configInfo.colorBlendAttachment.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | + VK_COLOR_COMPONENT_A_BIT; + configInfo.colorBlendAttachment.blendEnable = VK_FALSE; + configInfo.colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; // Optional + configInfo.colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional + configInfo.colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; // Optional + configInfo.colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; // Optional + configInfo.colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; // Optional + configInfo.colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; // Optional + + configInfo.colorBlendInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + configInfo.colorBlendInfo.logicOpEnable = VK_FALSE; + configInfo.colorBlendInfo.logicOp = VK_LOGIC_OP_COPY; // Optional + configInfo.colorBlendInfo.attachmentCount = 1; + configInfo.colorBlendInfo.pAttachments = &configInfo.colorBlendAttachment; + configInfo.colorBlendInfo.blendConstants[0] = 0.0f; // Optional + configInfo.colorBlendInfo.blendConstants[1] = 0.0f; // Optional + configInfo.colorBlendInfo.blendConstants[2] = 0.0f; // Optional + configInfo.colorBlendInfo.blendConstants[3] = 0.0f; // Optional + + configInfo.depthStencilInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + configInfo.depthStencilInfo.depthTestEnable = VK_TRUE; + configInfo.depthStencilInfo.depthWriteEnable = VK_TRUE; + configInfo.depthStencilInfo.depthCompareOp = VK_COMPARE_OP_LESS; + configInfo.depthStencilInfo.depthBoundsTestEnable = VK_FALSE; + configInfo.depthStencilInfo.minDepthBounds = 0.0f; // Optional + configInfo.depthStencilInfo.maxDepthBounds = 1.0f; // Optional + configInfo.depthStencilInfo.stencilTestEnable = VK_FALSE; + configInfo.depthStencilInfo.front = {}; // Optional + configInfo.depthStencilInfo.back = {}; // Optional + + configInfo.dynamicStateEnables = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR}; + configInfo.dynamicStateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + configInfo.dynamicStateInfo.pDynamicStates = configInfo.dynamicStateEnables.data(); + configInfo.dynamicStateInfo.dynamicStateCount = + static_cast(configInfo.dynamicStateEnables.size()); + configInfo.dynamicStateInfo.flags = 0; } } \ No newline at end of file diff --git a/src/cfx_pipeline.hpp b/src/cfx_pipeline.hpp index 4ea359a..f9b83df 100644 --- a/src/cfx_pipeline.hpp +++ b/src/cfx_pipeline.hpp @@ -2,42 +2,45 @@ #include #include #include "cfx_device.hpp" -namespace cfx { - struct PipelineConfigInfo{ - PipelineConfigInfo(const PipelineConfigInfo&) = delete; - PipelineConfigInfo& operator=(const PipelineConfigInfo&) = delete; +namespace cfx +{ + struct PipelineConfigInfo + { + PipelineConfigInfo(const PipelineConfigInfo &) = delete; + PipelineConfigInfo &operator=(const PipelineConfigInfo &) = delete; - VkPipelineViewportStateCreateInfo viewportInfo; - VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo; - VkPipelineRasterizationStateCreateInfo rasterizationInfo; - VkPipelineMultisampleStateCreateInfo multisampleInfo; - VkPipelineColorBlendAttachmentState colorBlendAttachment; - VkPipelineColorBlendStateCreateInfo colorBlendInfo; - VkPipelineDepthStencilStateCreateInfo depthStencilInfo; - std::vector dynamicStateEnables; - VkPipelineDynamicStateCreateInfo dynamicStateInfo; - VkPipelineLayout pipelineLayout = nullptr; - VkRenderPass renderPass = nullptr; - uint32_t subpass = 0; - uint32_t deviceIndex = 0; + VkPipelineViewportStateCreateInfo viewportInfo; + VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo; + VkPipelineRasterizationStateCreateInfo rasterizationInfo; + VkPipelineMultisampleStateCreateInfo multisampleInfo; + VkPipelineColorBlendAttachmentState colorBlendAttachment; + VkPipelineColorBlendStateCreateInfo colorBlendInfo; + VkPipelineDepthStencilStateCreateInfo depthStencilInfo; + std::vector dynamicStateEnables; + VkPipelineDynamicStateCreateInfo dynamicStateInfo; + VkPipelineLayout pipelineLayout = nullptr; + VkRenderPass renderPass = nullptr; + uint32_t subpass = 0; + uint32_t deviceIndex = 0; }; - class CFXPipeLine { - public: - CFXPipeLine(CFXDevice& device, const PipelineConfigInfo& configInfo, const std::string& vertFilePath, const std::string& fragFilePath,int deviceIndex); + class CFXPipeLine + { + public: + CFXPipeLine(CFXDevice &device, const PipelineConfigInfo &configInfo, const std::string &vertFilePath, const std::string &fragFilePath, int deviceIndex); ~CFXPipeLine(); - CFXPipeLine(const CFXPipeLine&) = delete; - void operator=(const CFXPipeLine&) = delete; + CFXPipeLine(const CFXPipeLine &) = delete; + void operator=(const CFXPipeLine &) = delete; - static void defaultPipelineConfigInfo(PipelineConfigInfo& configInfo); + static void defaultPipelineConfigInfo(PipelineConfigInfo &configInfo); void bind(VkCommandBuffer commandBuffer); - private: - static std::vector readFile(const std::string& filepath); + private: + static std::vector readFile(const std::string &filepath); - void createGraphicsPipeLine(const PipelineConfigInfo& configInfo,const std::string& vertFilePath, const std::string& fragFilePath,int deviceIndex); - void createShaderModule(const std::vector& code, VkShaderModule* shaderModule,int deviceIndex); - CFXDevice& cfxDevice; + void createGraphicsPipeLine(const PipelineConfigInfo &configInfo, const std::string &vertFilePath, const std::string &fragFilePath, int deviceIndex); + void createShaderModule(const std::vector &code, VkShaderModule *shaderModule, int deviceIndex); + CFXDevice &cfxDevice; VkPipeline graphicsPipeline{}; VkShaderModule vertShaderModule; VkShaderModule fragShaderModule; diff --git a/src/cfx_render_system.cpp b/src/cfx_render_system.cpp index c158025..1f591f2 100644 --- a/src/cfx_render_system.cpp +++ b/src/cfx_render_system.cpp @@ -1,109 +1,100 @@ #include "cfx_render_system.hpp" -#include -#include -#include -#include +#include +#include +#include +#include #define GLM_FORCE_RADIANS #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include - -namespace cfx{ - struct SimplePushConstantData{ +namespace cfx +{ + struct SimplePushConstantData + { glm::mat4 transform{1.f}; glm::mat4 modelMatrix{1.f}; // alignas(16) glm::vec3 color; - - }; - CFXRenderSystem::CFXRenderSystem(CFXDevice& device,std::vector renderPasses): cfxDevice{device} { - pipelineLayout.resize(cfxDevice.getDevicesinDeviceGroup()); - cfxPipeLines.resize(cfxDevice.getDevicesinDeviceGroup()); - for(int deviceIndex = 0; deviceIndex < cfxDevice.getDevicesinDeviceGroup(); deviceIndex++ ){ - createPipelineLayout(deviceIndex); - createPipeline(renderPasses[deviceIndex],deviceIndex); - } - - - + CFXRenderSystem::CFXRenderSystem(CFXDevice &device, std::vector renderPasses) : cfxDevice{device} + { + pipelineLayout.resize(cfxDevice.getDevicesinDeviceGroup()); + cfxPipeLines.resize(cfxDevice.getDevicesinDeviceGroup()); + for (int deviceIndex = 0; deviceIndex < cfxDevice.getDevicesinDeviceGroup(); deviceIndex++) + { + createPipelineLayout(deviceIndex); + createPipeline(renderPasses[deviceIndex], deviceIndex); } - CFXRenderSystem::~CFXRenderSystem(){ - for(int i = 0; i < cfxDevice.getDevicesinDeviceGroup(); i++){ - vkDestroyPipelineLayout(cfxDevice.device(i),pipelineLayout[i],nullptr); - - } - + } + CFXRenderSystem::~CFXRenderSystem() + { + for (int i = 0; i < cfxDevice.getDevicesinDeviceGroup(); i++) + { + vkDestroyPipelineLayout(cfxDevice.device(i), pipelineLayout[i], nullptr); } - + } - void CFXRenderSystem::renderGameObjects(VkCommandBuffer commandBuffer,std::vector &cfxGameObjects,int deviceIndex, const CFXCamera camera){ - // std::cout << "RENDER GAME OBJECTS ON " << cfxDevice.getDeviceName(deviceIndex) << std::endl; - cfxPipeLines[deviceIndex]->bind(commandBuffer); - auto projectionView = camera.getProjection() * camera.getView(); + void CFXRenderSystem::renderGameObjects(VkCommandBuffer commandBuffer, std::vector &cfxGameObjects, int deviceIndex, const CFXCamera camera) + { + // std::cout << "RENDER GAME OBJECTS ON " << cfxDevice.getDeviceName(deviceIndex) << std::endl; + cfxPipeLines[deviceIndex]->bind(commandBuffer); + auto projectionView = camera.getProjection() * camera.getView(); - for (auto& obj : cfxGameObjects) { - // obj.transformComponent.rotation.y = glm::mod(obj.transformComponent.rotation.y + 0.01f, glm::two_pi()); - // obj.transformComponent.rotation.x = glm::mod(obj.transformComponent.rotation.x + 0.005f, glm::two_pi()); + for (auto &obj : cfxGameObjects) + { + // obj.transformComponent.rotation.y = glm::mod(obj.transformComponent.rotation.y + 0.01f, glm::two_pi()); + // obj.transformComponent.rotation.x = glm::mod(obj.transformComponent.rotation.x + 0.005f, glm::two_pi()); - SimplePushConstantData push{}; - auto modelMatrix = obj.transformComponent.mat4(); + SimplePushConstantData push{}; + auto modelMatrix = obj.transformComponent.mat4(); - push.transform = projectionView * modelMatrix; - push.modelMatrix = modelMatrix; + push.transform = projectionView * modelMatrix; + push.modelMatrix = modelMatrix; - vkCmdPushConstants( - commandBuffer, - pipelineLayout[deviceIndex], - VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, - 0, - sizeof(SimplePushConstantData), - &push); - obj.model->bind(commandBuffer,deviceIndex); - obj.model->draw(commandBuffer); - // std::cout << "RENDER GAME OBJECTS END ON " << std::endl; - } -} - void CFXRenderSystem::createPipelineLayout(int deviceIndex){ - VkPushConstantRange pushConstantRange{}; - pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; - pushConstantRange.offset = 0; - pushConstantRange.size = sizeof(SimplePushConstantData); - // std::cout << "CREATE PIPELINE LAYOUT " << std::endl; - VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.setLayoutCount = 0; - pipelineLayoutInfo.pSetLayouts = nullptr; - pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; - pipelineLayoutInfo.pushConstantRangeCount = 1; - - if(vkCreatePipelineLayout(cfxDevice.device(deviceIndex),&pipelineLayoutInfo,nullptr,&pipelineLayout[deviceIndex]) != VK_SUCCESS){ - throw std::runtime_error("failed to create pipeline layout"); - } - + vkCmdPushConstants( + commandBuffer, + pipelineLayout[deviceIndex], + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + 0, + sizeof(SimplePushConstantData), + &push); + obj.model->bind(commandBuffer, deviceIndex); + obj.model->draw(commandBuffer); + // std::cout << "RENDER GAME OBJECTS END ON " << std::endl; } - void CFXRenderSystem::createPipeline(VkRenderPass renderpass,int deviceIndex){ - - // std::cout << "CREATE PIPELINE " << std::endl; - PipelineConfigInfo pipelineConfig{}; - CFXPipeLine::defaultPipelineConfigInfo(pipelineConfig); - pipelineConfig.renderPass = renderpass; - pipelineConfig.pipelineLayout = pipelineLayout[deviceIndex]; - cfxPipeLines[deviceIndex] = std::make_unique(cfxDevice,pipelineConfig, - "shaders/simple_shader.vert.spv", - "shaders/simple_shader.frag.spv",deviceIndex); - // std::cout << "CREATE PIPELINE END " << std::endl; + } + void CFXRenderSystem::createPipelineLayout(int deviceIndex) + { + VkPushConstantRange pushConstantRange{}; + pushConstantRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; + pushConstantRange.offset = 0; + pushConstantRange.size = sizeof(SimplePushConstantData); + // std::cout << "CREATE PIPELINE LAYOUT " << std::endl; + VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = 0; + pipelineLayoutInfo.pSetLayouts = nullptr; + pipelineLayoutInfo.pPushConstantRanges = &pushConstantRange; + pipelineLayoutInfo.pushConstantRangeCount = 1; + if (vkCreatePipelineLayout(cfxDevice.device(deviceIndex), &pipelineLayoutInfo, nullptr, &pipelineLayout[deviceIndex]) != VK_SUCCESS) + { + throw std::runtime_error("failed to create pipeline layout"); } - - + } + void CFXRenderSystem::createPipeline(VkRenderPass renderpass, int deviceIndex) + { - + // std::cout << "CREATE PIPELINE " << std::endl; + PipelineConfigInfo pipelineConfig{}; + CFXPipeLine::defaultPipelineConfigInfo(pipelineConfig); + pipelineConfig.renderPass = renderpass; + pipelineConfig.pipelineLayout = pipelineLayout[deviceIndex]; + cfxPipeLines[deviceIndex] = std::make_unique(cfxDevice, pipelineConfig, + "shaders/simple_shader.vert.spv", + "shaders/simple_shader.frag.spv", deviceIndex); + // std::cout << "CREATE PIPELINE END " << std::endl; + } - - - - - } \ No newline at end of file diff --git a/src/cfx_render_system.hpp b/src/cfx_render_system.hpp index 1af58c6..70f7dc1 100644 --- a/src/cfx_render_system.hpp +++ b/src/cfx_render_system.hpp @@ -13,33 +13,20 @@ namespace cfx{ class CFXRenderSystem{ public: - CFXRenderSystem(CFXDevice &device, std::vector renderPasses); - ~CFXRenderSystem(); - CFXRenderSystem(const CFXRenderSystem &) = delete; - CFXRenderSystem &operator=(const CFXRenderSystem &) = delete; - void renderGameObjects(VkCommandBuffer commandBuffer, std::vector &gameObjects,int deviceIndex, const CFXCamera camera); - - + CFXRenderSystem(CFXDevice &device, std::vector renderPasses); + ~CFXRenderSystem(); + CFXRenderSystem(const CFXRenderSystem &) = delete; + CFXRenderSystem &operator=(const CFXRenderSystem &) = delete; + void renderGameObjects(VkCommandBuffer commandBuffer, std::vector &gameObjects,int deviceIndex, const CFXCamera camera); private: - - void createPipelineLayout(int deviceIndex); - void createPipeline(VkRenderPass renderpass,int deviceIndex); - - - - - - - - - CFXDevice& cfxDevice; - // CFXSwapChain cfxSwapChain{cfxDevice,window.getExtent()}; - - std::vector> cfxPipeLines; - std::vector pipelineLayout; - - - + void createPipelineLayout(int deviceIndex); + void createPipeline(VkRenderPass renderpass,int deviceIndex); + + CFXDevice& cfxDevice; + // CFXSwapChain cfxSwapChain{cfxDevice,window.getExtent()}; + + std::vector> cfxPipeLines; + std::vector pipelineLayout; }; } \ No newline at end of file diff --git a/src/cfx_renderer.cpp b/src/cfx_renderer.cpp index 89b532f..2fa081c 100644 --- a/src/cfx_renderer.cpp +++ b/src/cfx_renderer.cpp @@ -1,173 +1,170 @@ #include "cfx_renderer.hpp" -#include -#include -#include -#include +#include +#include +#include +#include +namespace cfx +{ -namespace cfx{ - - Renderer::Renderer(CFXWindow &window, CFXDevice &device) : cfxWindow{window}, cfxDevice{device} { + Renderer::Renderer(CFXWindow &window, CFXDevice &device) : cfxWindow{window}, cfxDevice{device} + { deviceCount = cfxDevice.getDevicesinDeviceGroup(); commandBuffers.resize(deviceCount); recreateSwapChain(); - for(int i = 0; i < deviceCount; i++){ + for (int i = 0; i < deviceCount; i++) + { createCommandBuffers(i); } - } - Renderer::~Renderer(){ + Renderer::~Renderer() + { // for(int i = 0; i < deviceCount; i++){ // freeCommandBuffers(i); // } } - - void Renderer::recreateSwapChain(){ + + void Renderer::recreateSwapChain() + { // std::cout << "RECREATE SWAPCHAIN"<< std::endl; auto extent = cfxWindow.getExtent(); - while(extent.width == 0 || extent.height == 0){ + while (extent.width == 0 || extent.height == 0) + { extent = cfxWindow.getExtent(); glfwWaitEvents(); } - for(int i = 0; i < deviceCount; i++){ + for (int i = 0; i < deviceCount; i++) + { vkDeviceWaitIdle(cfxDevice.device(i)); } - if(cfxSwapChain == nullptr){ - cfxSwapChain = std::make_unique(cfxDevice,extent); + if (cfxSwapChain == nullptr) + { + cfxSwapChain = std::make_unique(cfxDevice, extent); } - else{ + else + { // cfxSwapChain->destroySyncObjects() - std::shared_ptr oldSwapchain = std::move(cfxSwapChain); - cfxSwapChain = std::make_unique(cfxDevice,extent,oldSwapchain); - if(!oldSwapchain->compareSwapFormats(*cfxSwapChain.get())){ + std::shared_ptr oldSwapchain = std::move(cfxSwapChain); + cfxSwapChain = std::make_unique(cfxDevice, extent, oldSwapchain); + if (!oldSwapchain->compareSwapFormats(*cfxSwapChain.get())) + { throw std::runtime_error("Swapchain Image or Depth format changed"); } // if(cfxSwapChain->imageCount() != commandBuffers.size()){ // freeCommandBuffers(); // createCommandBuffers(); // } - } } - void Renderer::createCommandBuffers(int deviceIndex){ - - - commandBuffers[deviceIndex].resize(CFXSwapChain::MAX_FRAMES_IN_FLIGHT); - - VkCommandBufferAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandPool = cfxDevice.getCommandPool(deviceIndex); - allocInfo.commandBufferCount = static_cast(commandBuffers[deviceIndex].size()); - if (vkAllocateCommandBuffers(cfxDevice.device(deviceIndex), &allocInfo, commandBuffers[deviceIndex].data()) != - VK_SUCCESS) { - throw std::runtime_error("failed to allocate command buffers!"); - } - - - - - } - void Renderer::freeCommandBuffers(int deviceIndex){ - vkFreeCommandBuffers(cfxDevice.device(deviceIndex), cfxDevice.getCommandPool(deviceIndex), static_cast(commandBuffers[deviceIndex].size()), commandBuffers[deviceIndex].data()); - } - - - - - RenderBuffer Renderer::beginFrame(){ + void Renderer::createCommandBuffers(int deviceIndex) + { + + commandBuffers[deviceIndex].resize(CFXSwapChain::MAX_FRAMES_IN_FLIGHT); + + VkCommandBufferAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandPool = cfxDevice.getCommandPool(deviceIndex); + allocInfo.commandBufferCount = static_cast(commandBuffers[deviceIndex].size()); + if (vkAllocateCommandBuffers(cfxDevice.device(deviceIndex), &allocInfo, commandBuffers[deviceIndex].data()) != + VK_SUCCESS) + { + throw std::runtime_error("failed to allocate command buffers!"); + } + } + + void Renderer::freeCommandBuffers(int deviceIndex) + { + vkFreeCommandBuffers(cfxDevice.device(deviceIndex), cfxDevice.getCommandPool(deviceIndex), static_cast(commandBuffers[deviceIndex].size()), commandBuffers[deviceIndex].data()); + } + + RenderBuffer Renderer::beginFrame() + { // std::cout << "BEGIN FRAME"<< std::endl; RenderBuffer renderBuffer{}; - - assert(!isFrameStarted && "Cant call beginFrame while frame is in progress"); - isFrameStarted = true; - - deviceIndex = currentFrameIndex % cfxDevice.getDevicesinDeviceGroup(); - VkCommandBuffer commandBuffer = getCurrentCommandBuffer(deviceIndex); - renderBuffer.commandBuffer = commandBuffer; - - renderBuffer.deviceIndex = deviceIndex; - std::cout << "BEGIN FRAME FOR DEVICE " << cfxDevice.getDeviceName(deviceIndex) << std::endl; - auto result = cfxSwapChain->acquireNextImage(¤tImageIndex,deviceIndex); - if(result == VK_ERROR_OUT_OF_DATE_KHR){ - recreateSwapChain(); - renderBuffer.commandBuffer = nullptr; - return renderBuffer; - } - if(result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR){ - throw std::runtime_error("failed to aquire swap chain image"); - } + assert(!isFrameStarted && "Cant call beginFrame while frame is in progress"); + isFrameStarted = true; + + deviceIndex = currentFrameIndex % cfxDevice.getDevicesinDeviceGroup(); + VkCommandBuffer commandBuffer = getCurrentCommandBuffer(deviceIndex); + renderBuffer.commandBuffer = commandBuffer; + + renderBuffer.deviceIndex = deviceIndex; + std::cout << "BEGIN FRAME FOR GPU" << deviceIndex << ": " << cfxDevice.getDeviceName(deviceIndex) << std::endl; + auto result = cfxSwapChain->acquireNextImage(¤tImageIndex, deviceIndex); + if (result == VK_ERROR_OUT_OF_DATE_KHR) + { + recreateSwapChain(); + renderBuffer.commandBuffer = nullptr; + return renderBuffer; + } - - + if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) + { + throw std::runtime_error("failed to aquire swap chain image"); + } // std::cout << "BEGIN COMMAND BUFFER" < 1){ // vkCmdSetDeviceMask(commandBuffer,renderBuffer.deviceMask); // } // std::cout << "FRAME BEGAN" <submitCommandBuffers(&commandBuffer,¤tImageIndex,deviceIndex); - if(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || cfxWindow.wasWindowResized()){ - cfxWindow.restWindowResizedFlag(); - recreateSwapChain(); - - } - else if(result != VK_SUCCESS){ - throw std::runtime_error("failed to present swap chain image"); - } - - isFrameStarted = false; - // cfxSwapChain->destroySyncObjects(deviceIndex); - currentFrameIndex = (currentFrameIndex + 1) % CFXSwapChain::MAX_FRAMES_IN_FLIGHT; + if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) + { + throw std::runtime_error("failed to record command buffer!"); + } + // std::cout << "VULKAN DEVICE INDEX END " << cfxDevice.getDeviceName(deviceIndex) << std::endl; + VkResult result = cfxSwapChain->submitCommandBuffers(&commandBuffer, ¤tImageIndex, deviceIndex); + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || cfxWindow.wasWindowResized()) + { + cfxWindow.restWindowResizedFlag(); + recreateSwapChain(); + } + else if (result != VK_SUCCESS) + { + throw std::runtime_error("failed to present swap chain image"); + } + isFrameStarted = false; + // cfxSwapChain->destroySyncObjects(deviceIndex); + currentFrameIndex = (currentFrameIndex + 1) % CFXSwapChain::MAX_FRAMES_IN_FLIGHT; } - void Renderer::beginSwapChainRenderPass(VkCommandBuffer commandBuffer,uint32_t deviceMask,uint32_t deviceIndex){ + void Renderer::beginSwapChainRenderPass(VkCommandBuffer commandBuffer, uint32_t deviceMask, uint32_t deviceIndex) + { // std::cout << "RENDERPASS FOR "<< deviceIndex << std::endl; assert(isFrameStarted && "Cant call beginSwapChainRenderPass if frame is not in progress"); assert(commandBuffer == getCurrentCommandBuffer(deviceIndex) && "cant begin renderpass on a command buffer from a different frame"); - VkRenderPassBeginInfo renderPassInfo{}; renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; // std::cout << "GETTING RENDERPASS FOR "<< deviceIndex << std::endl; renderPassInfo.renderPass = cfxSwapChain->getRenderPass(deviceIndex); // std::cout << "GOT RENDERPASS FOR "<< deviceIndex << std::endl; // std::cout << "GETTING FRAMEBUFFER FOR "<< deviceIndex << std::endl; - renderPassInfo.framebuffer = cfxSwapChain->getFrameBuffer(deviceIndex,currentImageIndex); + renderPassInfo.framebuffer = cfxSwapChain->getFrameBuffer(deviceIndex, currentImageIndex); // std::cout << "GOT FRAMEBUFFER FOR "<< deviceIndex << std::endl; - // renderPassInfo.pNext = &deviceGroupRenderPassInfo; + // renderPassInfo.pNext = &deviceGroupRenderPassInfo; renderPassInfo.renderArea.offset = {0, 0}; renderPassInfo.renderArea.extent = cfxSwapChain->getSwapChainExtent(deviceIndex); @@ -180,30 +177,27 @@ namespace cfx{ // if(cfxDevice.getDevicesinDeviceGroup() > 1){ // vkCmdSetDeviceMask(commandBuffer,deviceMask); // } - - - vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); - // std::cout << "BEGIN RENDER PASS" << std::endl; - - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(cfxSwapChain->getSwapChainExtent(deviceIndex).width); - viewport.height = static_cast(cfxSwapChain->getSwapChainExtent(deviceIndex).height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - VkRect2D scissor{{0, 0}, cfxSwapChain->getSwapChainExtent(deviceIndex)}; - // std::cout << "SET VIEWPORT" << std::endl; - vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - // std::cout << "VIEWPORT SET" << std::endl; - // std::cout << "SET SCISSOR" << std::endl; - vkCmdSetScissor(commandBuffer, 0, 1, &scissor); - // std::cout << "SCISSOR SET" << std::endl; - - + vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + // std::cout << "BEGIN RENDER PASS" << std::endl; + + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = static_cast(cfxSwapChain->getSwapChainExtent(deviceIndex).width); + viewport.height = static_cast(cfxSwapChain->getSwapChainExtent(deviceIndex).height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + VkRect2D scissor{{0, 0}, cfxSwapChain->getSwapChainExtent(deviceIndex)}; + // std::cout << "SET VIEWPORT" << std::endl; + vkCmdSetViewport(commandBuffer, 0, 1, &viewport); + // std::cout << "VIEWPORT SET" << std::endl; + // std::cout << "SET SCISSOR" << std::endl; + vkCmdSetScissor(commandBuffer, 0, 1, &scissor); + // std::cout << "SCISSOR SET" << std::endl; } - void Renderer::endSwapChainRenderPass(VkCommandBuffer commandBuffer,uint32_t deviceMask,int deviceIndex){ + void Renderer::endSwapChainRenderPass(VkCommandBuffer commandBuffer, uint32_t deviceMask, int deviceIndex) + { assert(isFrameStarted && "Cant call endSwapChainRenderPass if frame is not in progress"); assert(commandBuffer == getCurrentCommandBuffer(deviceIndex) && "cant end renderpass on a command buffer from a different frame"); // if(cfxDevice.getDevicesinDeviceGroup() > 1){ @@ -211,9 +205,6 @@ namespace cfx{ // } vkCmdEndRenderPass(commandBuffer); // std::cout << "END RENDER PASS" << std::endl; - } - - - + } \ No newline at end of file diff --git a/src/cfx_renderer.hpp b/src/cfx_renderer.hpp index bd5533a..cab3b10 100644 --- a/src/cfx_renderer.hpp +++ b/src/cfx_renderer.hpp @@ -5,20 +5,22 @@ #include "cfx_swapchain.hpp" #include "cfx_model.hpp" -#include -#include +#include +#include #include #include -namespace cfx{ - struct RenderBuffer{ +namespace cfx +{ + struct RenderBuffer + { VkCommandBuffer commandBuffer; uint32_t deviceMask; uint32_t deviceIndex; }; - class Renderer{ - public: - + class Renderer + { + public: Renderer(CFXWindow &cfxWindow, CFXDevice &cfxDevice); ~Renderer(); Renderer(const Renderer &) = delete; @@ -26,36 +28,31 @@ namespace cfx{ RenderBuffer beginFrame(); void endFrame(int deviceIndex); - bool isFrameInProgress() const {return isFrameStarted;} - VkCommandBuffer getCurrentCommandBuffer(int deviceIndex) const{ - - assert( isFrameStarted && "Cannot get Command Buffer if frame is not in progress"); + bool isFrameInProgress() const { return isFrameStarted; } + VkCommandBuffer getCurrentCommandBuffer(int deviceIndex) const + { + assert(isFrameStarted && "Cannot get Command Buffer if frame is not in progress"); return commandBuffers[deviceIndex][currentFrameIndex]; - } - int getFrameIndex() const { - assert( isFrameStarted && "Cannot get Frame Index if frame is not in progress"); + } + int getFrameIndex() const + { + assert(isFrameStarted && "Cannot get Frame Index if frame is not in progress"); return currentFrameIndex; - } - VkRenderPass getSwapChainRenderPass(int deviceIndex) const {return cfxSwapChain->getRenderPass(deviceIndex);} - std::vector getSwapChainRenderPasses() const {return cfxSwapChain->getRenderPasses();} - void beginSwapChainRenderPass(VkCommandBuffer commandBuffer,uint32_t deviceMask,uint32_t deviceIndex); - void endSwapChainRenderPass(VkCommandBuffer commandBuffer,uint32_t deviceMask,int deviceIndex); - float getAspectRatio() const {return cfxSwapChain->extentAspectRatio(); } - + VkRenderPass getSwapChainRenderPass(int deviceIndex) const { return cfxSwapChain->getRenderPass(deviceIndex); } + std::vector getSwapChainRenderPasses() const { return cfxSwapChain->getRenderPasses(); } + void beginSwapChainRenderPass(VkCommandBuffer commandBuffer, uint32_t deviceMask, uint32_t deviceIndex); + void endSwapChainRenderPass(VkCommandBuffer commandBuffer, uint32_t deviceMask, int deviceIndex); + float getAspectRatio() const { return cfxSwapChain->extentAspectRatio(); } - private: - + private: void createCommandBuffers(int deviceIndex); void freeCommandBuffers(int deviceIndex); void recreateSwapChain(); - - - - CFXWindow& cfxWindow; - CFXDevice& cfxDevice; + CFXWindow &cfxWindow; + CFXDevice &cfxDevice; // CFXSwapChain cfxSwapChain{cfxDevice,window.getExtent()}; std::unique_ptr cfxSwapChain; // CFXPipeLine cfxPipeLine{cfxDevice,CFXPipeLine::defaultPipelineConfigInfo(WIDTH,HEIGHT),"shaders/simple_shader.vert.spv","shaders/simple_shader.frag.spv"}; @@ -65,7 +62,5 @@ namespace cfx{ bool isFrameStarted = false; uint32_t deviceIndex = 0; int deviceCount = 0; - - }; } \ No newline at end of file diff --git a/src/cfx_swapchain.cpp b/src/cfx_swapchain.cpp index 92157cf..5c1dfbd 100644 --- a/src/cfx_swapchain.cpp +++ b/src/cfx_swapchain.cpp @@ -8,545 +8,544 @@ #include #include -namespace cfx{ - CFXSwapChain::CFXSwapChain(CFXDevice &deviceRef, VkExtent2D extent) - : device{deviceRef}, windowExtent{extent} { - init(); - -} -CFXSwapChain::CFXSwapChain(CFXDevice &deviceRef, VkExtent2D extent,std::shared_ptr previous) - : device{deviceRef}, windowExtent{extent}, oldSwapChain{previous} { - - - init(); - oldSwapChain = nullptr; - -} -void CFXSwapChain::init(){ - swapChains.resize(device.getDevicesinDeviceGroup()); - swapChainImages.resize(device.getDevicesinDeviceGroup()); - swapChainImageViews.resize(device.getDevicesinDeviceGroup()); - swapChainFramebuffers.resize(device.getDevicesinDeviceGroup()); - depthImages.resize(device.getDevicesinDeviceGroup()); - depthImageMemorys.resize(device.getDevicesinDeviceGroup()); - depthImageViews.resize(device.getDevicesinDeviceGroup()); - imageAvailableSemaphores.resize(device.getDevicesinDeviceGroup()); - renderFinishedSemaphores.resize(device.getDevicesinDeviceGroup()); - inFlightFences.resize(device.getDevicesinDeviceGroup()); - imagesInFlight.resize(device.getDevicesinDeviceGroup()); - swapChainImageFormat.resize(device.getDevicesinDeviceGroup()); - swapChainDepthFormat.resize(device.getDevicesinDeviceGroup()); - swapChainExtent.resize(device.getDevicesinDeviceGroup()); - renderPasses.resize(device.getDevicesinDeviceGroup()); - - for(int deviceIndex = 0; deviceIndex previous) + : device{deviceRef}, windowExtent{extent}, oldSwapChain{previous} + { -CFXSwapChain::~CFXSwapChain() { - for(int deviceIndex = 0; deviceIndex < device.getDevicesinDeviceGroup(); deviceIndex++){ - - for (int i = 0; i < swapChainImageViews[deviceIndex].size(); i++) { - vkDestroyImageView(device.device(deviceIndex),swapChainImageViews[deviceIndex][i],nullptr); + init(); + oldSwapChain = nullptr; + } + void CFXSwapChain::init() + { + swapChains.resize(device.getDevicesinDeviceGroup()); + swapChainImages.resize(device.getDevicesinDeviceGroup()); + swapChainImageViews.resize(device.getDevicesinDeviceGroup()); + swapChainFramebuffers.resize(device.getDevicesinDeviceGroup()); + depthImages.resize(device.getDevicesinDeviceGroup()); + depthImageMemorys.resize(device.getDevicesinDeviceGroup()); + depthImageViews.resize(device.getDevicesinDeviceGroup()); + imageAvailableSemaphores.resize(device.getDevicesinDeviceGroup()); + renderFinishedSemaphores.resize(device.getDevicesinDeviceGroup()); + inFlightFences.resize(device.getDevicesinDeviceGroup()); + imagesInFlight.resize(device.getDevicesinDeviceGroup()); + swapChainImageFormat.resize(device.getDevicesinDeviceGroup()); + swapChainDepthFormat.resize(device.getDevicesinDeviceGroup()); + swapChainExtent.resize(device.getDevicesinDeviceGroup()); + renderPasses.resize(device.getDevicesinDeviceGroup()); + + for (int deviceIndex = 0; deviceIndex < device.getDevicesinDeviceGroup(); deviceIndex++) + { + createSwapChain(deviceIndex); + createImageViews(deviceIndex); + createDepthResources(deviceIndex); + createRenderPass(deviceIndex); + createFramebuffers(deviceIndex); + createSyncObjects(deviceIndex); + } } - - - for(int i=0; i < swapChainImages[deviceIndex].size();i++){ - - vkDestroyImage(device.device(deviceIndex), swapChainImages[deviceIndex][i], nullptr); + CFXSwapChain::~CFXSwapChain() + { + for (int deviceIndex = 0; deviceIndex < device.getDevicesinDeviceGroup(); deviceIndex++) + { + + for (int i = 0; i < swapChainImageViews[deviceIndex].size(); i++) + { + vkDestroyImageView(device.device(deviceIndex), swapChainImageViews[deviceIndex][i], nullptr); + } + + for (int i = 0; i < swapChainImages[deviceIndex].size(); i++) + { + + vkDestroyImage(device.device(deviceIndex), swapChainImages[deviceIndex][i], nullptr); + } + vkDestroySwapchainKHR(device.device(deviceIndex), swapChains[deviceIndex], nullptr); + + for (int i = 0; i < depthImages[deviceIndex].size(); i++) + { + vkDestroyImageView(device.device(deviceIndex), depthImageViews[deviceIndex][i], nullptr); + vkDestroyImage(device.device(0), depthImages[deviceIndex][i], nullptr); + vkFreeMemory(device.device(0), depthImageMemorys[deviceIndex][i], nullptr); + } + + for (auto frameBufferArray : swapChainFramebuffers[deviceIndex]) + { + vkDestroyFramebuffer(device.device(deviceIndex), frameBufferArray, nullptr); + } + + // cleanup synchronization objects + // vkDestroyRenderPass(device.device(deviceIndex), renderPass, nullptr); + destroySyncObjects(deviceIndex); + } } - vkDestroySwapchainKHR(device.device(deviceIndex), swapChains[deviceIndex], nullptr); - for (int i = 0; i < depthImages[deviceIndex].size(); i++) { - vkDestroyImageView(device.device(deviceIndex), depthImageViews[deviceIndex][i], nullptr); - vkDestroyImage(device.device(0), depthImages[deviceIndex][i], nullptr); - vkFreeMemory(device.device(0), depthImageMemorys[deviceIndex][i], nullptr); - + VkResult CFXSwapChain::acquireNextImage(uint32_t *imageIndex, uint32_t deviceIndex) + { + + // if(deviceIndex != 0){ + // // vkDestroyRenderPass(device.device(0), renderPass, nullptr); + // // vkDestroyRenderPass(device.device(deviceIndex), renderPass, nullptr); + + // // destroySyncObjects(0); + // // destroySyncObjects(deviceIndex); + + // } + + // std::cout << "ACQ NEXT IMG" << std::endl; + // vkResetFences(device.device(deviceIndex), 1, &inFlightFences[deviceIndex][currentFrame]); + vkWaitForFences( + device.device(deviceIndex), + 1, + &inFlightFences[deviceIndex][currentFrame], + VK_TRUE, + std::numeric_limits::max()); + VkAcquireNextImageInfoKHR nextImageInfo{}; + nextImageInfo.sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR; + nextImageInfo.swapchain = swapChains[deviceIndex]; + nextImageInfo.timeout = std::numeric_limits::max(); + nextImageInfo.semaphore = imageAvailableSemaphores[deviceIndex][currentFrame]; + nextImageInfo.fence = VK_NULL_HANDLE; + // nextImageInfo.deviceMask = deviceMasks[deviceIndex]; + // return vkAcquireNextImage2KHR(device.device(deviceIndex),&nextImageInfo,imageIndex); + VkResult result = vkAcquireNextImageKHR( + device.device(deviceIndex), + swapChains[deviceIndex], + std::numeric_limits::max(), + imageAvailableSemaphores[deviceIndex][currentFrame], // must be a not signaled semaphore + VK_NULL_HANDLE, + imageIndex); + // std::cout << " NEXT IMG ACQUIRED " << std::endl; + return result; } - - for (auto frameBufferArray : swapChainFramebuffers[deviceIndex]) { - vkDestroyFramebuffer(device.device(deviceIndex), frameBufferArray, nullptr); - + void CFXSwapChain::destroySyncObjects(int deviceIndex) + { + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { + vkDestroySemaphore(device.device(deviceIndex), renderFinishedSemaphores[deviceIndex][i], nullptr); + vkDestroySemaphore(device.device(deviceIndex), imageAvailableSemaphores[deviceIndex][i], nullptr); + vkDestroyFence(device.device(deviceIndex), inFlightFences[deviceIndex][i], nullptr); + } } - - - + VkResult CFXSwapChain::submitCommandBuffers(const VkCommandBuffer *buffers, uint32_t *imageIndex, uint32_t deviceIndex) + { - // cleanup synchronization objects - // vkDestroyRenderPass(device.device(deviceIndex), renderPass, nullptr); - destroySyncObjects(deviceIndex); - - } - - - - - -} - -VkResult CFXSwapChain::acquireNextImage(uint32_t *imageIndex,uint32_t deviceIndex) { - - - - - // if(deviceIndex != 0){ - // // vkDestroyRenderPass(device.device(0), renderPass, nullptr); - // // vkDestroyRenderPass(device.device(deviceIndex), renderPass, nullptr); - - // // destroySyncObjects(0); - // // destroySyncObjects(deviceIndex); - - // } - - - // std::cout << "ACQ NEXT IMG" << std::endl; - // vkResetFences(device.device(deviceIndex), 1, &inFlightFences[deviceIndex][currentFrame]); - vkWaitForFences( - device.device(deviceIndex), - 1, - &inFlightFences[deviceIndex][currentFrame], - VK_TRUE, - std::numeric_limits::max()); - VkAcquireNextImageInfoKHR nextImageInfo{}; - nextImageInfo.sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR; - nextImageInfo.swapchain = swapChains[deviceIndex]; - nextImageInfo.timeout = std::numeric_limits::max(); - nextImageInfo.semaphore = imageAvailableSemaphores[deviceIndex][currentFrame]; - nextImageInfo.fence = VK_NULL_HANDLE; - // nextImageInfo.deviceMask = deviceMasks[deviceIndex]; - // return vkAcquireNextImage2KHR(device.device(deviceIndex),&nextImageInfo,imageIndex); - VkResult result = vkAcquireNextImageKHR( - device.device(deviceIndex), - swapChains[deviceIndex], - std::numeric_limits::max(), - imageAvailableSemaphores[deviceIndex][currentFrame], // must be a not signaled semaphore - VK_NULL_HANDLE, - imageIndex); - // std::cout << " NEXT IMG ACQUIRED " << std::endl; - return result; - - + // std::cout << "INSIDE SUBMIT_COMMAND_BUFFER FOR DEVICE " << device.getDeviceName(deviceIndex) << std::endl; + // std::cout << device.getDeviceName(deviceIndex) << " CURRENT FRAME " << currentFrame << std::endl; + // std::cout << device.getDeviceName(deviceIndex) << " IMAGE INDEX " << imageIndex << std::endl; + // std::cout << device.getDeviceName(deviceIndex) << " IMAGES IN FLIGHT " << imagesInFlight[deviceIndex].size() << std::endl; + // std::cout << device.getDeviceName(deviceIndex) << " IN FLIGHT FENCES " << inFlightFences[deviceIndex].size() << std::endl; + imagesInFlight[deviceIndex][*imageIndex] = inFlightFences[deviceIndex][currentFrame]; - - + VkSubmitInfo submitInfo = {}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - -} -void CFXSwapChain::destroySyncObjects(int deviceIndex){ - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(device.device(deviceIndex), renderFinishedSemaphores[deviceIndex][i], nullptr); - vkDestroySemaphore(device.device(deviceIndex), imageAvailableSemaphores[deviceIndex][i], nullptr); - vkDestroyFence(device.device(deviceIndex), inFlightFences[deviceIndex][i], nullptr); - } -} + std::vector waitSemaphores = {imageAvailableSemaphores[deviceIndex][currentFrame]}; + std::vector waitSemaphoreIndices = {0}; + VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores.data(); + submitInfo.pWaitDstStageMask = waitStages; -VkResult CFXSwapChain::submitCommandBuffers(const VkCommandBuffer *buffers, uint32_t *imageIndex,uint32_t deviceIndex) { - - - // std::cout << "INSIDE SUBMIT_COMMAND_BUFFER FOR DEVICE " << device.getDeviceName(deviceIndex) << std::endl; - // std::cout << device.getDeviceName(deviceIndex) << " CURRENT FRAME " << currentFrame << std::endl; - // std::cout << device.getDeviceName(deviceIndex) << " IMAGE INDEX " << imageIndex << std::endl; - // std::cout << device.getDeviceName(deviceIndex) << " IMAGES IN FLIGHT " << imagesInFlight[deviceIndex].size() << std::endl; - // std::cout << device.getDeviceName(deviceIndex) << " IN FLIGHT FENCES " << inFlightFences[deviceIndex].size() << std::endl; + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = buffers; - + std::vector signalSemaphores = {renderFinishedSemaphores[deviceIndex][currentFrame]}; + std::vector signalSemaphoreIndices = {0}; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores.data(); - + VkResult result = vkResetFences(device.device(deviceIndex), 1, &inFlightFences[deviceIndex][currentFrame]); + if (result == VK_SUCCESS) + { + if (vkQueueSubmit(device.getGraphicsQueues(deviceIndex), 1, &submitInfo, inFlightFences[deviceIndex][currentFrame]) != + VK_SUCCESS) + { + throw std::runtime_error("failed to submit draw command buffer!"); + } - imagesInFlight[deviceIndex][*imageIndex] = inFlightFences[deviceIndex][currentFrame]; + VkPresentInfoKHR presentInfo = {}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - VkSubmitInfo submitInfo = {}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = signalSemaphores.data(); - std::vector waitSemaphores = {imageAvailableSemaphores[deviceIndex][currentFrame]}; - std::vector waitSemaphoreIndices = {0}; - VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores.data(); - submitInfo.pWaitDstStageMask = waitStages; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = &swapChains[deviceIndex]; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = buffers; + presentInfo.pImageIndices = imageIndex; - std::vector signalSemaphores = {renderFinishedSemaphores[deviceIndex][currentFrame]}; - std::vector signalSemaphoreIndices = {0}; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = signalSemaphores.data(); + VkResult result = vkQueuePresentKHR(device.getPresentQueues(deviceIndex), &presentInfo); + // std::cout<< "CURRENT FRAME >>>>>> "<< currentFrame << std::endl; + currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; - - VkResult result = vkResetFences(device.device(deviceIndex), 1, &inFlightFences[deviceIndex][currentFrame]); - if( result== VK_SUCCESS){ - - if (vkQueueSubmit(device.getGraphicsQueues(deviceIndex), 1, &submitInfo, inFlightFences[deviceIndex][currentFrame]) != - VK_SUCCESS) { - throw std::runtime_error("failed to submit draw command buffer!"); + return result; + } + else + { + throw std::runtime_error("failed to reset Fence!"); + return result; + } } - VkPresentInfoKHR presentInfo = {}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + void CFXSwapChain::createSwapChain(int deviceIndex) + { - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = signalSemaphores.data(); + SwapChainSupportDetails swapChainSupport = device.getSwapChainSupport(deviceIndex); - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &swapChains[deviceIndex]; + VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); + VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes); + VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities); - presentInfo.pImageIndices = imageIndex; - - - VkResult result = vkQueuePresentKHR(device.getPresentQueues(deviceIndex), &presentInfo); - // std::cout<< "CURRENT FRAME >>>>>> "<< currentFrame << std::endl; - currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; - + uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; + if (swapChainSupport.capabilities.maxImageCount > 0 && + imageCount > swapChainSupport.capabilities.maxImageCount) + { + imageCount = swapChainSupport.capabilities.maxImageCount; + } - return result; - }else{ - throw std::runtime_error("failed to reset Fence!"); - return result; - } + VkSwapchainCreateInfoKHR createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = device.surface(); + + createInfo.minImageCount = imageCount; + createInfo.imageFormat = surfaceFormat.format; + createInfo.imageColorSpace = surfaceFormat.colorSpace; + createInfo.imageExtent = extent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + QueueFamilyIndices indices = device.findPhysicalQueueFamilies(deviceIndex); + uint32_t queueFamilyIndices[] = {indices.graphicsFamily, indices.presentFamily}; + + if (indices.graphicsFamily != indices.presentFamily) + { + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.queueFamilyIndexCount = 2; + createInfo.pQueueFamilyIndices = queueFamilyIndices; + } + else + { + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.queueFamilyIndexCount = 0; // Optional + createInfo.pQueueFamilyIndices = nullptr; // Optional + } -} + createInfo.preTransform = swapChainSupport.capabilities.currentTransform; + createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; -void CFXSwapChain::createSwapChain(int deviceIndex) { - - SwapChainSupportDetails swapChainSupport = device.getSwapChainSupport(deviceIndex); + createInfo.presentMode = presentMode; + createInfo.clipped = VK_TRUE; - VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); - VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes); - VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities); + createInfo.oldSwapchain = VK_NULL_HANDLE; - uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; - if (swapChainSupport.capabilities.maxImageCount > 0 && - imageCount > swapChainSupport.capabilities.maxImageCount) { - imageCount = swapChainSupport.capabilities.maxImageCount; + if (vkCreateSwapchainKHR(device.device(deviceIndex), &createInfo, nullptr, &swapChains[deviceIndex]) != VK_SUCCESS) + { + throw std::runtime_error("failed to create swap chain!"); + } + // std::cout<< "CREATE SWAP CHAIN " << std::endl; + + // we only specified a minimum number of images in the swap chain, so the implementation is + // allowed to create a swap chain with more. That's why we'll first query the final number of + // images with vkGetSwapchainImagesKHR, then resize the container and finally call it again to + // retrieve the handles. + if (vkGetSwapchainImagesKHR(device.device(deviceIndex), swapChains[deviceIndex], &imageCount, nullptr) != VK_SUCCESS) + { + throw std::runtime_error("failed to get swap chain images!"); + } + swapChainImages[deviceIndex].resize(imageCount); + // std::cout << "CREATE SWAPCHAIN IMAGE COUNT " << imageCount < attachments = {colorAttachment, depthAttachment}; + + VkRenderPassCreateInfo renderPassInfo{}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.attachmentCount = static_cast(attachments.size()); + renderPassInfo.pAttachments = attachments.data(); + renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpass; + renderPassInfo.dependencyCount = 1; + renderPassInfo.pDependencies = &dependency; + + if (vkCreateRenderPass(device.device(deviceIndex), &renderPassInfo, nullptr, &renderPasses[deviceIndex]) != VK_SUCCESS) + { + throw std::runtime_error("failed to create render pass!"); } - - } - // std::cout<< "CREATE IMAGE VIEWS END " << std::endl; -} - -void CFXSwapChain::createRenderPass(int deviceIndex) { - // std::cout << "CREATE RENDER PASS ON " << device.getDeviceName(deviceIndex) << std::endl; - VkAttachmentDescription depthAttachment{}; - depthAttachment.format = findDepthFormat(); - depthAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - depthAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - depthAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentReference depthAttachmentRef{}; - depthAttachmentRef.attachment = 1; - depthAttachmentRef.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkAttachmentDescription colorAttachment = {}; - colorAttachment.format = getSwapChainImageFormat(deviceIndex); - colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference colorAttachmentRef = {}; - colorAttachmentRef.attachment = 0; - colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - subpass.pDepthStencilAttachment = &depthAttachmentRef; - - VkSubpassDependency dependency = {}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.srcAccessMask = 0; - dependency.srcStageMask = - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.dstSubpass = 0; - dependency.dstStageMask = - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT; - dependency.dstAccessMask = - VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - - std::array attachments = {colorAttachment, depthAttachment}; - - VkRenderPassCreateInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = static_cast(attachments.size()); - renderPassInfo.pAttachments = attachments.data(); - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 1; - renderPassInfo.pDependencies = &dependency; - - if (vkCreateRenderPass(device.device(deviceIndex), &renderPassInfo, nullptr, &renderPasses[deviceIndex]) != VK_SUCCESS) { - throw std::runtime_error("failed to create render pass!"); + // std::cout << "CREATE RENDER PASS END " < attachments = {swapChainImageViews[deviceIndex][i], depthImageViews[deviceIndex][i]}; + + VkExtent2D swapChainExtent = getSwapChainExtent(deviceIndex); + VkFramebufferCreateInfo framebufferInfo = {}; + framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebufferInfo.renderPass = renderPasses[deviceIndex]; + framebufferInfo.attachmentCount = static_cast(attachments.size()); + framebufferInfo.pAttachments = attachments.data(); + framebufferInfo.width = swapChainExtent.width; + framebufferInfo.height = swapChainExtent.height; + framebufferInfo.layers = 1; + // std::cout << "CREATE FRAME BUFFER FUNCTION CALL" < attachments = {swapChainImageViews[deviceIndex][i], depthImageViews[deviceIndex][i]}; + // std::cout << "CREATE FRAME BUFFER END " <(attachments.size()); - framebufferInfo.pAttachments = attachments.data(); - framebufferInfo.width = swapChainExtent.width; - framebufferInfo.height = swapChainExtent.height; - framebufferInfo.layers = 1; - // std::cout << "CREATE FRAME BUFFER FUNCTION CALL" < &availableFormats) + { + for (const auto &availableFormat : availableFormats) + { + if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && + availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + return availableFormat; + } } + + return availableFormats[0]; } - - // std::cout << "CREATE SYNC OBJECTS END " < &availableFormats) { - for (const auto &availableFormat : availableFormats) { - if (availableFormat.format == VK_FORMAT_B8G8R8A8_UNORM && - availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - return availableFormat; + + VkPresentModeKHR CFXSwapChain::chooseSwapPresentMode( + const std::vector &availablePresentModes) + { + + // for (const auto &availablePresentMode : availablePresentModes) { + // if (availablePresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) { + // std::cout << "Present mode: immediate" << std::endl; + // return availablePresentMode; + // } + // } + + std::cout << "Present mode: Immediate" << std::endl; + return VK_PRESENT_MODE_IMMEDIATE_KHR; + } + + VkExtent2D CFXSwapChain::chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities) + { + if (capabilities.currentExtent.width != std::numeric_limits::max()) + { + return capabilities.currentExtent; + } + else + { + VkExtent2D actualExtent = windowExtent; + actualExtent.width = std::max( + capabilities.minImageExtent.width, + std::min(capabilities.maxImageExtent.width, actualExtent.width)); + actualExtent.height = std::max( + capabilities.minImageExtent.height, + std::min(capabilities.maxImageExtent.height, actualExtent.height)); + + return actualExtent; } } - return availableFormats[0]; -} - -VkPresentModeKHR CFXSwapChain::chooseSwapPresentMode( - const std::vector &availablePresentModes) { - - - // for (const auto &availablePresentMode : availablePresentModes) { - // if (availablePresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) { - // std::cout << "Present mode: immediate" << std::endl; - // return availablePresentMode; - // } - // } - - std::cout << "Present mode: Immediate" << std::endl; - return VK_PRESENT_MODE_IMMEDIATE_KHR; -} - -VkExtent2D CFXSwapChain::chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities) { - if (capabilities.currentExtent.width != std::numeric_limits::max()) { - return capabilities.currentExtent; - } else { - VkExtent2D actualExtent = windowExtent; - actualExtent.width = std::max( - capabilities.minImageExtent.width, - std::min(capabilities.maxImageExtent.width, actualExtent.width)); - actualExtent.height = std::max( - capabilities.minImageExtent.height, - std::min(capabilities.maxImageExtent.height, actualExtent.height)); - - return actualExtent; + VkFormat CFXSwapChain::findDepthFormat() + { + return device.findSupportedFormat( + {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}, + VK_IMAGE_TILING_OPTIMAL, + VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); } -} - -VkFormat CFXSwapChain::findDepthFormat() { - return device.findSupportedFormat( - {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}, - VK_IMAGE_TILING_OPTIMAL, - VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT); -} } \ No newline at end of file diff --git a/src/cfx_swapchain.hpp b/src/cfx_swapchain.hpp index ccae939..a39fb43 100644 --- a/src/cfx_swapchain.hpp +++ b/src/cfx_swapchain.hpp @@ -2,86 +2,88 @@ #include "cfx_device.hpp" -#include -#include -#include +#include +#include +#include #include - -namespace cfx{ - class CFXSwapChain{ - public: - static constexpr int MAX_FRAMES_IN_FLIGHT = 4; - - CFXSwapChain(CFXDevice &deviceRef, VkExtent2D windowExtent); - CFXSwapChain(CFXDevice &deviceRef, VkExtent2D windowExtent,std::shared_ptr previous); - ~CFXSwapChain(); - - CFXSwapChain(const CFXSwapChain &) = delete; - void operator=(const CFXSwapChain &) = delete; - - VkFramebuffer getFrameBuffer(int deviceIndex,int index) { return swapChainFramebuffers[deviceIndex][index]; } - VkRenderPass getRenderPass(int deviceIndex) { return renderPasses[deviceIndex]; } - std::vector getRenderPasses() { return renderPasses; } - - VkImageView getImageView(int deviceIndex,int index) { return swapChainImageViews[deviceIndex][index]; } - size_t imageCount(int deviceIndex) { return swapChainImages[deviceIndex].size(); } - VkFormat getSwapChainImageFormat(int deviceIndex) { return swapChainImageFormat[deviceIndex]; } - VkExtent2D getSwapChainExtent(int deviceIndex) { return swapChainExtent[deviceIndex]; } - uint32_t width() { return swapChainExtent[0].width; } - uint32_t height() { return swapChainExtent[0].height; } - - float extentAspectRatio() { - return static_cast(swapChainExtent[0].width) / static_cast(swapChainExtent[0].height); - } - VkFormat findDepthFormat(); - - VkResult acquireNextImage(uint32_t *imageIndex,uint32_t deviceIndex); - VkResult submitCommandBuffers(const VkCommandBuffer *buffers, uint32_t *imageIndex,uint32_t deviceIndex); - bool compareSwapFormats(const CFXSwapChain& cfxSwapChain) const { - return cfxSwapChain.swapChainDepthFormat == swapChainDepthFormat && cfxSwapChain.swapChainImageFormat == swapChainImageFormat; - } - void destroySyncObjects(int deviceIndex); - - private: - void createSwapChain(int deviceIndex); - void init(); - void createImageViews(int deviceIndex); - void createDepthResources(int deviceIndex); - void createRenderPass(int deviceIndex); - void createFramebuffers(int deviceIndex); - void createSyncObjects(int deviceIndex); - - // Helper functions - VkSurfaceFormatKHR chooseSwapSurfaceFormat( - const std::vector &availableFormats); - VkPresentModeKHR chooseSwapPresentMode( - const std::vector &availablePresentModes); - VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities); - - std::vector swapChainImageFormat; - std::vector swapChainDepthFormat; - std::vector swapChainExtent; - - std::vector> swapChainFramebuffers; - std::vector renderPasses; - - std::vector> depthImages; - std::vector> depthImageMemorys; - std::vector> depthImageViews; - std::vector> swapChainImages; - std::vector> swapChainImageViews; - CFXDevice &device; - VkExtent2D windowExtent; - - std::vector swapChains; - std::shared_ptr oldSwapChain; - - - std::vector> imageAvailableSemaphores; - std::vector> renderFinishedSemaphores; - std::vector> inFlightFences; - std::vector> imagesInFlight; - size_t currentFrame = 0; +namespace cfx +{ + class CFXSwapChain + { + public: + static constexpr int MAX_FRAMES_IN_FLIGHT = 4; + + CFXSwapChain(CFXDevice &deviceRef, VkExtent2D windowExtent); + CFXSwapChain(CFXDevice &deviceRef, VkExtent2D windowExtent, std::shared_ptr previous); + ~CFXSwapChain(); + + CFXSwapChain(const CFXSwapChain &) = delete; + void operator=(const CFXSwapChain &) = delete; + + VkFramebuffer getFrameBuffer(int deviceIndex, int index) { return swapChainFramebuffers[deviceIndex][index]; } + VkRenderPass getRenderPass(int deviceIndex) { return renderPasses[deviceIndex]; } + std::vector getRenderPasses() { return renderPasses; } + + VkImageView getImageView(int deviceIndex, int index) { return swapChainImageViews[deviceIndex][index]; } + size_t imageCount(int deviceIndex) { return swapChainImages[deviceIndex].size(); } + VkFormat getSwapChainImageFormat(int deviceIndex) { return swapChainImageFormat[deviceIndex]; } + VkExtent2D getSwapChainExtent(int deviceIndex) { return swapChainExtent[deviceIndex]; } + uint32_t width() { return swapChainExtent[0].width; } + uint32_t height() { return swapChainExtent[0].height; } + + float extentAspectRatio() + { + return static_cast(swapChainExtent[0].width) / static_cast(swapChainExtent[0].height); + } + VkFormat findDepthFormat(); + + VkResult acquireNextImage(uint32_t *imageIndex, uint32_t deviceIndex); + VkResult submitCommandBuffers(const VkCommandBuffer *buffers, uint32_t *imageIndex, uint32_t deviceIndex); + bool compareSwapFormats(const CFXSwapChain &cfxSwapChain) const + { + return cfxSwapChain.swapChainDepthFormat == swapChainDepthFormat && cfxSwapChain.swapChainImageFormat == swapChainImageFormat; + } + void destroySyncObjects(int deviceIndex); + + private: + void createSwapChain(int deviceIndex); + void init(); + void createImageViews(int deviceIndex); + void createDepthResources(int deviceIndex); + void createRenderPass(int deviceIndex); + void createFramebuffers(int deviceIndex); + void createSyncObjects(int deviceIndex); + + // Helper functions + VkSurfaceFormatKHR chooseSwapSurfaceFormat( + const std::vector &availableFormats); + VkPresentModeKHR chooseSwapPresentMode( + const std::vector &availablePresentModes); + VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities); + + std::vector swapChainImageFormat; + std::vector swapChainDepthFormat; + std::vector swapChainExtent; + + std::vector> swapChainFramebuffers; + std::vector renderPasses; + + std::vector> depthImages; + std::vector> depthImageMemorys; + std::vector> depthImageViews; + std::vector> swapChainImages; + std::vector> swapChainImageViews; + CFXDevice &device; + VkExtent2D windowExtent; + + std::vector swapChains; + std::shared_ptr oldSwapChain; + + std::vector> imageAvailableSemaphores; + std::vector> renderFinishedSemaphores; + std::vector> inFlightFences; + std::vector> imagesInFlight; + size_t currentFrame = 0; }; } \ No newline at end of file diff --git a/src/cfx_utils.hpp b/src/cfx_utils.hpp index 75e8234..0587033 100644 --- a/src/cfx_utils.hpp +++ b/src/cfx_utils.hpp @@ -1,14 +1,16 @@ #pragma once - + #include - -namespace cfx { - -// from: https://stackoverflow.com/a/57595105 -template -void hashCombine(size_t& seed, const T& v, const Rest&... rest) { - seed ^= std::hash{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); - (hashCombine(seed, rest), ...); -}; - -} // namespace cfx \ No newline at end of file + +namespace cfx +{ + + // from: https://stackoverflow.com/a/57595105 + template + void hashCombine(size_t &seed, const T &v, const Rest &...rest) + { + seed ^= std::hash{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); + (hashCombine(seed, rest), ...); + }; + +} // namespace cfx \ No newline at end of file diff --git a/src/cfx_window.cpp b/src/cfx_window.cpp index 05845f1..215771d 100644 --- a/src/cfx_window.cpp +++ b/src/cfx_window.cpp @@ -1,33 +1,38 @@ #include "cfx_window.hpp" #include -namespace cfx{ - CFXWindow::CFXWindow(int w,int h, std::string name): width{w},height{h},windowName{name} { +namespace cfx +{ + CFXWindow::CFXWindow(int w, int h, std::string name) : width{w}, height{h}, windowName{name} + { initWindow(); } - CFXWindow::~CFXWindow(){ + CFXWindow::~CFXWindow() + { glfwDestroyWindow(window); glfwTerminate(); } - void CFXWindow::initWindow(){ + void CFXWindow::initWindow() + { glfwInit(); - glfwWindowHint(GLFW_CLIENT_API,GLFW_NO_API); - glfwWindowHint(GLFW_RESIZABLE,GLFW_TRUE); - window = glfwCreateWindow(width,height,windowName.c_str(),nullptr,nullptr); - glfwSetWindowUserPointer(window,this); - glfwSetFramebufferSizeCallback(window,framebufferResizedCallback); + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); + window = glfwCreateWindow(width, height, windowName.c_str(), nullptr, nullptr); + glfwSetWindowUserPointer(window, this); + glfwSetFramebufferSizeCallback(window, framebufferResizedCallback); } - void CFXWindow::createWindowSurface(VkInstance instance,VkSurfaceKHR* surface_){ - if(glfwCreateWindowSurface(instance,window,nullptr,surface_)!=VK_SUCCESS){ + void CFXWindow::createWindowSurface(VkInstance instance, VkSurfaceKHR *surface_) + { + if (glfwCreateWindowSurface(instance, window, nullptr, surface_) != VK_SUCCESS) + { throw std::runtime_error("Failed to create window surface"); - } } - void CFXWindow::framebufferResizedCallback(GLFWwindow *window,int width,int height){ + void CFXWindow::framebufferResizedCallback(GLFWwindow *window, int width, int height) + { auto cfxWindow = reinterpret_cast(glfwGetWindowUserPointer(window)); cfxWindow->framebufferResized = true; cfxWindow->width = width; cfxWindow->height = height; - } } \ No newline at end of file diff --git a/src/cfx_window.hpp b/src/cfx_window.hpp index 95f8256..d882dea 100644 --- a/src/cfx_window.hpp +++ b/src/cfx_window.hpp @@ -3,30 +3,30 @@ #include #include -namespace cfx{ - class CFXWindow { - public: - CFXWindow(int w,int h, std::string name); +namespace cfx +{ + class CFXWindow + { + public: + CFXWindow(int w, int h, std::string name); ~CFXWindow(); CFXWindow(const CFXWindow &) = delete; CFXWindow &operator=(const CFXWindow &) = delete; - bool shouldClose() {return glfwWindowShouldClose(window);} - void createWindowSurface(VkInstance instance,VkSurfaceKHR* surface_); - bool wasWindowResized() {return framebufferResized;} - void restWindowResizedFlag(){framebufferResized = false;} - GLFWwindow *getGLFWwindow() const {return window;} + bool shouldClose() { return glfwWindowShouldClose(window); } + void createWindowSurface(VkInstance instance, VkSurfaceKHR *surface_); + bool wasWindowResized() { return framebufferResized; } + void restWindowResizedFlag() { framebufferResized = false; } + GLFWwindow *getGLFWwindow() const { return window; } + VkExtent2D getExtent() { return {static_cast(width), static_cast(height)}; } - VkExtent2D getExtent(){return {static_cast(width),static_cast(height)};} - - private: + private: void initWindow(); - static void framebufferResizedCallback(GLFWwindow *window,int width,int height); + static void framebufferResizedCallback(GLFWwindow *window, int width, int height); int width; int height; bool framebufferResized = false; std::string windowName; - GLFWwindow *window; - + GLFWwindow *window; }; } \ No newline at end of file diff --git a/src/keyboard_movement_controller.cpp b/src/keyboard_movement_controller.cpp index 62a4f22..caa5b07 100644 --- a/src/keyboard_movement_controller.cpp +++ b/src/keyboard_movement_controller.cpp @@ -1,37 +1,46 @@ #include "keyboard_movement_controller.hpp" #include -namespace cfx{ - void KeyboardMovementController::moveInPlaneXZ(GLFWwindow *window,float dt, CFXGameObject &gameObject){ +namespace cfx +{ + void KeyboardMovementController::moveInPlaneXZ(GLFWwindow *window, float dt, CFXGameObject &gameObject) + { glm::vec3 rotate{0}; - if(glfwGetKey(window,keys.lookRight)==GLFW_PRESS) rotate.y += 1.f; - if(glfwGetKey(window,keys.lookLeft)==GLFW_PRESS) rotate.y -= 1.f; - if(glfwGetKey(window,keys.lookUp)==GLFW_PRESS) rotate.x += 1.f; - if(glfwGetKey(window,keys.lookDown)==GLFW_PRESS) rotate.x -= 1.f; - if(glm::dot(rotate,rotate) > std::numeric_limits::epsilon()){ + if (glfwGetKey(window, keys.lookRight) == GLFW_PRESS) + rotate.y += 1.f; + if (glfwGetKey(window, keys.lookLeft) == GLFW_PRESS) + rotate.y -= 1.f; + if (glfwGetKey(window, keys.lookUp) == GLFW_PRESS) + rotate.x += 1.f; + if (glfwGetKey(window, keys.lookDown) == GLFW_PRESS) + rotate.x -= 1.f; + if (glm::dot(rotate, rotate) > std::numeric_limits::epsilon()) + { gameObject.transformComponent.rotation += lookSpeed * dt * glm::normalize(rotate); - } - gameObject.transformComponent.rotation.x = glm::clamp(gameObject.transformComponent.rotation.x,-1.5f,1.5f); - gameObject.transformComponent.rotation.y = glm::mod(gameObject.transformComponent.rotation.y,glm::two_pi()); + gameObject.transformComponent.rotation.x = glm::clamp(gameObject.transformComponent.rotation.x, -1.5f, 1.5f); + gameObject.transformComponent.rotation.y = glm::mod(gameObject.transformComponent.rotation.y, glm::two_pi()); float yaw = gameObject.transformComponent.rotation.y; - const glm::vec3 forwardDir{sin(yaw),0.f,cos(yaw)}; - const glm::vec3 rightDir{forwardDir.z,0.f,-forwardDir.x}; - const glm::vec3 upDir{0.f,-1.f,0.f}; + const glm::vec3 forwardDir{sin(yaw), 0.f, cos(yaw)}; + const glm::vec3 rightDir{forwardDir.z, 0.f, -forwardDir.x}; + const glm::vec3 upDir{0.f, -1.f, 0.f}; glm::vec3 moveDir{0.f}; - if(glfwGetKey(window,keys.moveForward) == GLFW_PRESS) moveDir += forwardDir; - if(glfwGetKey(window,keys.moveBackward) == GLFW_PRESS) moveDir -= forwardDir; - if(glfwGetKey(window,keys.moveRight) == GLFW_PRESS) moveDir += rightDir; - if(glfwGetKey(window,keys.moveLeft) == GLFW_PRESS) moveDir -= rightDir; - if(glfwGetKey(window,keys.moveUp) == GLFW_PRESS) moveDir += upDir; - if(glfwGetKey(window,keys.moveDown) == GLFW_PRESS) moveDir -= upDir; + if (glfwGetKey(window, keys.moveForward) == GLFW_PRESS) + moveDir += forwardDir; + if (glfwGetKey(window, keys.moveBackward) == GLFW_PRESS) + moveDir -= forwardDir; + if (glfwGetKey(window, keys.moveRight) == GLFW_PRESS) + moveDir += rightDir; + if (glfwGetKey(window, keys.moveLeft) == GLFW_PRESS) + moveDir -= rightDir; + if (glfwGetKey(window, keys.moveUp) == GLFW_PRESS) + moveDir += upDir; + if (glfwGetKey(window, keys.moveDown) == GLFW_PRESS) + moveDir -= upDir; - if(glm::dot(moveDir,moveDir) > std::numeric_limits::epsilon()){ + if (glm::dot(moveDir, moveDir) > std::numeric_limits::epsilon()) + { gameObject.transformComponent.translation += moveSpeed * dt * glm::normalize(moveDir); - } - - - } } \ No newline at end of file diff --git a/src/keyboard_movement_controller.hpp b/src/keyboard_movement_controller.hpp index 42b05af..3137fe0 100644 --- a/src/keyboard_movement_controller.hpp +++ b/src/keyboard_movement_controller.hpp @@ -3,10 +3,13 @@ #include "cfx_game_object.hpp" #include "cfx_window.hpp" -namespace cfx{ - class KeyboardMovementController{ - public: - struct KeyMappings{ +namespace cfx +{ + class KeyboardMovementController + { + public: + struct KeyMappings + { int moveLeft = GLFW_KEY_A; int moveRight = GLFW_KEY_D; int moveForward = GLFW_KEY_W; @@ -19,11 +22,10 @@ namespace cfx{ int lookDown = GLFW_KEY_DOWN; }; - void moveInPlaneXZ(GLFWwindow *window,float dt, CFXGameObject &gameObject); + void moveInPlaneXZ(GLFWwindow *window, float dt, CFXGameObject &gameObject); KeyMappings keys{}; float moveSpeed{0.0003f}; float lookSpeed{0.0005f}; - }; } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5dc2dfb..e485150 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,15 +2,18 @@ #include #include #include -int main(){ +int main() +{ cfx::App app{}; - try{ + try + { app.run(); - }catch (const std::exception &e){ + } + catch (const std::exception &e) + { std::cerr << e.what() << '\n'; return EXIT_FAILURE; } return EXIT_SUCCESS; - } \ No newline at end of file