refactor
This commit is contained in:
parent
f5bd6f85a8
commit
dc88120f58
29 changed files with 321 additions and 278 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +1,6 @@
|
||||||
[submodule "extern/Modules"]
|
[submodule "extern/Modules"]
|
||||||
path = extern/Modules
|
path = extern/Modules
|
||||||
url = https://github.com/elushaX/Modules.git
|
url = https://github.com/elushaX/Modules.git
|
||||||
|
[submodule "extern/imgui"]
|
||||||
|
path = extern/imgui
|
||||||
|
url = https://github.com/ocornut/imgui.git
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@ project(App)
|
||||||
set(CMAKE_CXX_STANDARD 26)
|
set(CMAKE_CXX_STANDARD 26)
|
||||||
|
|
||||||
add_subdirectory(extern/Modules)
|
add_subdirectory(extern/Modules)
|
||||||
|
add_subdirectory(extern/Utils)
|
||||||
|
|
||||||
add_subdirectory(src/Common)
|
add_subdirectory(src/VulkanGraphics)
|
||||||
add_subdirectory(src/GPU)
|
|
||||||
add_subdirectory(src/PlatformWindow)
|
|
||||||
add_subdirectory(src/App)
|
add_subdirectory(src/App)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
cmake_minimum_required(VERSION 3.30)
|
cmake_minimum_required(VERSION 3.30)
|
||||||
|
|
||||||
project(Common)
|
project(Utils)
|
||||||
|
|
||||||
file(GLOB SOURCES "./private/*.cpp")
|
file(GLOB SOURCES "./private/*.cpp")
|
||||||
add_library(${PROJECT_NAME} ${SOURCES})
|
add_library(${PROJECT_NAME} ${SOURCES})
|
||||||
1
extern/imgui
vendored
Submodule
1
extern/imgui
vendored
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 5b7feebfd8f3e58392d955b4c8ae01f77eae25ed
|
||||||
|
|
@ -5,6 +5,6 @@ project(App)
|
||||||
file(GLOB SOURCES "./private/*.cpp")
|
file(GLOB SOURCES "./private/*.cpp")
|
||||||
add_executable(${PROJECT_NAME} ${SOURCES})
|
add_executable(${PROJECT_NAME} ${SOURCES})
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC public)
|
target_include_directories(${PROJECT_NAME} PUBLIC public)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC Common GPU PlatformWindow)
|
target_link_libraries(${PROJECT_NAME} PUBLIC VulkanGraphics)
|
||||||
|
|
||||||
file(COPY shaders DESTINATION ${PROJECT_BINARY_DIR}/)
|
file(COPY shaders DESTINATION ${PROJECT_BINARY_DIR}/)
|
||||||
|
|
@ -1,12 +1,29 @@
|
||||||
#include "app_interactive.hpp"
|
#include "VulkanWindow.hpp"
|
||||||
#include "app_offscreen.hpp"
|
#include "VulkanOffscreen.hpp"
|
||||||
|
|
||||||
|
#include "renderer.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int runOffscreen() {
|
int runOffscreen() {
|
||||||
try {
|
try {
|
||||||
AppOffscreen app;
|
VulkanOffscreen app;
|
||||||
app.run();
|
Renderer renderer;
|
||||||
|
|
||||||
|
renderer.create(app.getRenderInfo());
|
||||||
|
app.setRenderPass(renderer.getRenderPass());
|
||||||
|
|
||||||
|
auto frameData = app.beginDrawFrame();
|
||||||
|
|
||||||
|
renderer.fillRenderCommands(frameData.commandBuffer, frameData.framebuffer, frameData.extent2D);
|
||||||
|
renderer.updateUniformBuffer({frameData.extent2D.width, frameData.extent2D.height});
|
||||||
|
|
||||||
|
app.endDrawFrame(frameData);
|
||||||
|
|
||||||
|
app.saveFrame();
|
||||||
|
|
||||||
|
renderer.destroy(app.getDevice());
|
||||||
|
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
@ -16,10 +33,28 @@ int runOffscreen() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int runInteractive() {
|
int runInteractive() {
|
||||||
AppInteractive app;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
app.run();
|
Renderer renderer;
|
||||||
|
VulkanWindow app;
|
||||||
|
|
||||||
|
renderer.create(app.getRenderInfo());
|
||||||
|
app.setRenderPass(renderer.getRenderPass());
|
||||||
|
|
||||||
|
while (!glfwWindowShouldClose(app.getWindow())) {
|
||||||
|
app.pollEvents();
|
||||||
|
|
||||||
|
auto drawData = app.startDrawFrame();
|
||||||
|
|
||||||
|
renderer.fillRenderCommands(drawData.commandBuffer, drawData.frameBuffer, drawData.extent2D);
|
||||||
|
renderer.updateUniformBuffer({drawData.extent2D.width, drawData.extent2D.height});
|
||||||
|
|
||||||
|
app.endDrawFrame(drawData);
|
||||||
|
}
|
||||||
|
|
||||||
|
app.waitDevice();
|
||||||
|
renderer.destroy(app.getDevice());
|
||||||
|
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
std::cerr << e.what() << std::endl;
|
std::cerr << e.what() << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
#include "renderer.hpp"
|
#include "renderer.hpp"
|
||||||
#include "vulkan_utils.hpp"
|
#include "VulkanUtils.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
void Renderer::create(const CreateInfo &info) {
|
void Renderer::create(const RenderCreateInfo &info) {
|
||||||
mShader.create(info.device);
|
mShader.create(info.device);
|
||||||
|
|
||||||
createRenderPass(info.device, info.format, info.finalImageLayout);
|
createRenderPass(info.device, info.format, info.finalImageLayout);
|
||||||
|
|
@ -371,7 +371,7 @@ void Renderer::destroyBuffer(VkDevice device, VkBuffer buffer, VkDeviceMemory me
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Renderer::populateGraphicsCommandBuffer(VkCommandBuffer commandBuffer, VkFramebuffer framebuffer, VkExtent2D extend) {
|
Renderer::fillRenderCommands(VkCommandBuffer commandBuffer, VkFramebuffer framebuffer, VkExtent2D extend) {
|
||||||
VkCommandBufferBeginInfo commandBufferBeginInfo{
|
VkCommandBufferBeginInfo commandBufferBeginInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
};
|
};
|
||||||
|
|
@ -471,4 +471,25 @@ void Renderer::copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue qu
|
||||||
vkQueueWaitIdle(queue);
|
vkQueueWaitIdle(queue);
|
||||||
|
|
||||||
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
|
vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::updateUniformBuffer(const std::pair<uint32_t, uint32_t>& frameBufferSize) const {
|
||||||
|
static float time = 0;
|
||||||
|
time += 0.001;
|
||||||
|
|
||||||
|
glm::mat4 model = glm::rotate(glm::mat4(1.0f), (time * glm::radians(90.f)), glm::vec3(0.f, 0.f, 1.f));
|
||||||
|
glm::mat4 view = glm::lookAt(glm::vec3{2.0f, 2.0f, 2.0f}, glm::vec3{0.0f, 0.0f, 0.0f}, -glm::vec3{0.0f, 0.0f, 1.0f});
|
||||||
|
glm::mat4 perspective = glm::perspective(glm::radians(45.f),
|
||||||
|
(float) frameBufferSize.first /
|
||||||
|
(float) frameBufferSize.second, 0.1f, 10.f);
|
||||||
|
|
||||||
|
auto transforms = perspective * view * model;
|
||||||
|
|
||||||
|
CustomShader::UniformBuffer ubo{
|
||||||
|
.transforms = transforms,
|
||||||
|
.origin = glm::vec4(0, 0, 0, 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(mUniformBufferMemoryMapped, &ubo, sizeof(ubo));
|
||||||
|
// ubo.transforms =
|
||||||
}
|
}
|
||||||
|
|
@ -3,39 +3,11 @@
|
||||||
#include "shader.hpp"
|
#include "shader.hpp"
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
struct Renderer {
|
class Renderer {
|
||||||
CustomShader mShader;
|
public:
|
||||||
VkPipeline mGraphicsPipeline = VK_NULL_HANDLE;
|
Renderer() = default;
|
||||||
VkRenderPass mGraphicsRenderPass = VK_NULL_HANDLE;
|
|
||||||
VkPipelineLayout mGraphicsPipelineLayout{}; // no uniforms used in the shader
|
|
||||||
|
|
||||||
// Buffers
|
void create(const RenderCreateInfo& info);
|
||||||
VkBuffer mVertexBuffer = VK_NULL_HANDLE;
|
|
||||||
VkDeviceMemory mVertexBufferMemory = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
VkBuffer mIndexBuffer = VK_NULL_HANDLE;
|
|
||||||
VkDeviceMemory mIndexBufferMemory = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
VkDescriptorPool mDescriptorPool = VK_NULL_HANDLE;
|
|
||||||
VkDescriptorSet mDescriptorSet = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
VkBuffer mUniformBuffer = VK_NULL_HANDLE;
|
|
||||||
VkDeviceMemory mUniformBufferMemory = VK_NULL_HANDLE;
|
|
||||||
void* mUniformBufferMemoryMapped = nullptr;
|
|
||||||
|
|
||||||
struct CreateInfo {
|
|
||||||
VkDevice device;
|
|
||||||
VkPhysicalDevice physicalDevice;
|
|
||||||
VkExtent2D extent2D;
|
|
||||||
VkFormat format;
|
|
||||||
|
|
||||||
VkCommandPool commandPool;
|
|
||||||
VkQueue queue;
|
|
||||||
|
|
||||||
VkImageLayout finalImageLayout;
|
|
||||||
};
|
|
||||||
|
|
||||||
void create(const CreateInfo& info);
|
|
||||||
|
|
||||||
void destroy(VkDevice device) const;
|
void destroy(VkDevice device) const;
|
||||||
|
|
||||||
|
|
@ -56,7 +28,7 @@ struct Renderer {
|
||||||
void createUniformBuffer(VkPhysicalDevice physicalDevice, VkDevice device);
|
void createUniformBuffer(VkPhysicalDevice physicalDevice, VkDevice device);
|
||||||
|
|
||||||
|
|
||||||
void populateGraphicsCommandBuffer(VkCommandBuffer commandBuffer, VkFramebuffer framebuffer, VkExtent2D extend);
|
void fillRenderCommands(VkCommandBuffer commandBuffer, VkFramebuffer framebuffer, VkExtent2D extend);
|
||||||
|
|
||||||
struct BufferCreateInfo {
|
struct BufferCreateInfo {
|
||||||
VkBuffer *buffer;
|
VkBuffer *buffer;
|
||||||
|
|
@ -74,4 +46,28 @@ struct Renderer {
|
||||||
static void destroyBuffer(VkDevice device, VkBuffer buffer, VkDeviceMemory memory);
|
static void destroyBuffer(VkDevice device, VkBuffer buffer, VkDeviceMemory memory);
|
||||||
|
|
||||||
void destroyGraphicsPipeline(VkDevice device) const;
|
void destroyGraphicsPipeline(VkDevice device) const;
|
||||||
|
|
||||||
|
void updateUniformBuffer(const std::pair<uint32_t, uint32_t>& frameBufferSize) const;
|
||||||
|
|
||||||
|
VkRenderPass getRenderPass() { return mGraphicsRenderPass; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
CustomShader mShader;
|
||||||
|
VkPipeline mGraphicsPipeline = VK_NULL_HANDLE;
|
||||||
|
VkRenderPass mGraphicsRenderPass = VK_NULL_HANDLE;
|
||||||
|
VkPipelineLayout mGraphicsPipelineLayout{}; // no uniforms used in the shader
|
||||||
|
|
||||||
|
// Buffers
|
||||||
|
VkBuffer mVertexBuffer = VK_NULL_HANDLE;
|
||||||
|
VkDeviceMemory mVertexBufferMemory = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkBuffer mIndexBuffer = VK_NULL_HANDLE;
|
||||||
|
VkDeviceMemory mIndexBufferMemory = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkDescriptorPool mDescriptorPool = VK_NULL_HANDLE;
|
||||||
|
VkDescriptorSet mDescriptorSet = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkBuffer mUniformBuffer = VK_NULL_HANDLE;
|
||||||
|
VkDeviceMemory mUniformBufferMemory = VK_NULL_HANDLE;
|
||||||
|
void* mUniformBufferMemoryMapped = nullptr;
|
||||||
};
|
};
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common.hpp"
|
#include "VulkanInterface.hpp"
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include "common.hpp"
|
||||||
|
|
||||||
struct CustomShader {
|
struct CustomShader {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.30)
|
|
||||||
|
|
||||||
project(PlatformWindow)
|
|
||||||
|
|
||||||
file(GLOB SOURCES "./private/*.cpp")
|
|
||||||
add_library(${PROJECT_NAME} ${SOURCES})
|
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC public)
|
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC glfw GPU)
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
cmake_minimum_required(VERSION 3.30)
|
cmake_minimum_required(VERSION 3.30)
|
||||||
|
|
||||||
project(GPU)
|
project(VulkanGraphics)
|
||||||
|
|
||||||
file(GLOB SOURCES "./private/*.cpp")
|
file(GLOB SOURCES "./private/*.cpp")
|
||||||
add_library(${PROJECT_NAME} ${SOURCES})
|
add_library(${PROJECT_NAME} ${SOURCES})
|
||||||
target_include_directories(${PROJECT_NAME} PUBLIC public)
|
target_include_directories(${PROJECT_NAME} PUBLIC public)
|
||||||
target_link_libraries(${PROJECT_NAME} PUBLIC vulkan Common)
|
target_link_libraries(${PROJECT_NAME} PUBLIC vulkan glfw Containers Math Utils)
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "swapchain.hpp"
|
#include "SwapChain.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@ -1,23 +1,15 @@
|
||||||
#include "app_offscreen.hpp"
|
#include "VulkanOffscreen.hpp"
|
||||||
|
|
||||||
|
#include "Buffer2D.hpp"
|
||||||
|
#include "Color.hpp"
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
AppOffscreen::AppOffscreen() {
|
VulkanOffscreen::VulkanOffscreen() {
|
||||||
initDevice();
|
initDevice();
|
||||||
initPipeline();
|
initPipeline();
|
||||||
initFramebuffer();
|
|
||||||
initStagingBuffer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::run() {
|
VulkanOffscreen::~VulkanOffscreen() {
|
||||||
updateUniformBuffer();
|
|
||||||
draw();
|
|
||||||
transitionImageLayout();
|
|
||||||
transferToHost();
|
|
||||||
readMemory();
|
|
||||||
}
|
|
||||||
|
|
||||||
AppOffscreen::~AppOffscreen() {
|
|
||||||
vkDeviceWaitIdle(mDevice);
|
vkDeviceWaitIdle(mDevice);
|
||||||
|
|
||||||
finalizeStagingBuffer();
|
finalizeStagingBuffer();
|
||||||
|
|
@ -26,7 +18,55 @@ AppOffscreen::~AppOffscreen() {
|
||||||
finalizeDevice();
|
finalizeDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::initDevice() {
|
RenderCreateInfo VulkanOffscreen::getRenderInfo() {
|
||||||
|
return {
|
||||||
|
.device = mDevice,
|
||||||
|
.physicalDevice = mPhysicalDevice,
|
||||||
|
.extent2D = mExtent,
|
||||||
|
.format = mFormat,
|
||||||
|
.commandPool = mCommandPool,
|
||||||
|
.queue = mGraphicsQueue,
|
||||||
|
.finalImageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||||
|
// .finalImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanOffscreen::setRenderPass(VkRenderPass renderPass) {
|
||||||
|
initFramebuffer(renderPass);
|
||||||
|
initStagingBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanOffscreen::FrameData VulkanOffscreen::beginDrawFrame() {
|
||||||
|
return {
|
||||||
|
mCommandBuffer, mFramebuffer, mExtent,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanOffscreen::endDrawFrame(const FrameData&) {
|
||||||
|
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||||
|
|
||||||
|
VkSubmitInfo submitInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||||
|
.waitSemaphoreCount = 0,
|
||||||
|
.pWaitSemaphores = nullptr,
|
||||||
|
.pWaitDstStageMask = waitStages,
|
||||||
|
.commandBufferCount = 1,
|
||||||
|
.pCommandBuffers = &mCommandBuffer,
|
||||||
|
.signalSemaphoreCount = 0,
|
||||||
|
.pSignalSemaphores = nullptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (vkQueueSubmit(mGraphicsQueue, 1, &submitInfo, nullptr) != VK_SUCCESS) {
|
||||||
|
throw std::runtime_error("failed to submit to graphics queue");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanOffscreen::saveFrame() {
|
||||||
|
transferToHost();
|
||||||
|
readMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanOffscreen::initDevice() {
|
||||||
std::vector<const char*> extensions = {};
|
std::vector<const char*> extensions = {};
|
||||||
std::vector<const char*> validationLayers = {};
|
std::vector<const char*> validationLayers = {};
|
||||||
std::vector<const char*> deviceExtensions = {};
|
std::vector<const char*> deviceExtensions = {};
|
||||||
|
|
@ -97,8 +137,7 @@ void AppOffscreen::initDevice() {
|
||||||
vkGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
|
vkGetDeviceQueue(mDevice, mGraphicsQueueIndex, 0, &mGraphicsQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::initPipeline() {
|
void VulkanOffscreen::initPipeline() {
|
||||||
mShader.create(mDevice);
|
|
||||||
|
|
||||||
VkCommandPoolCreateInfo commandPoolCreateInfo {
|
VkCommandPoolCreateInfo commandPoolCreateInfo {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
|
|
@ -117,22 +156,9 @@ void AppOffscreen::initPipeline() {
|
||||||
};
|
};
|
||||||
|
|
||||||
vkAllocateCommandBuffers(mDevice, &allocateInfo, &mCommandBuffer);
|
vkAllocateCommandBuffers(mDevice, &allocateInfo, &mCommandBuffer);
|
||||||
|
|
||||||
Renderer::CreateInfo renderCreateInfo {
|
|
||||||
.device = mDevice,
|
|
||||||
.physicalDevice = mPhysicalDevice,
|
|
||||||
.extent2D = mExtent,
|
|
||||||
.format = mFormat,
|
|
||||||
.commandPool = mCommandPool,
|
|
||||||
.queue = mGraphicsQueue,
|
|
||||||
.finalImageLayout = VK_IMAGE_LAYOUT_GENERAL,
|
|
||||||
// .finalImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
||||||
};
|
|
||||||
|
|
||||||
mRenderer.create(renderCreateInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::initFramebuffer() {
|
void VulkanOffscreen::initFramebuffer(VkRenderPass renderPass) {
|
||||||
// vkGetDeviceImageMemoryRequirements();
|
// vkGetDeviceImageMemoryRequirements();
|
||||||
|
|
||||||
VkImageCreateInfo imageCreateInfo {
|
VkImageCreateInfo imageCreateInfo {
|
||||||
|
|
@ -193,7 +219,7 @@ void AppOffscreen::initFramebuffer() {
|
||||||
|
|
||||||
VkFramebufferCreateInfo createInfo {
|
VkFramebufferCreateInfo createInfo {
|
||||||
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
.renderPass = mRenderer.mGraphicsRenderPass,
|
.renderPass = renderPass,
|
||||||
.attachmentCount = 1,
|
.attachmentCount = 1,
|
||||||
.pAttachments = &mImageView,
|
.pAttachments = &mImageView,
|
||||||
.width = mExtent.width,
|
.width = mExtent.width,
|
||||||
|
|
@ -206,32 +232,7 @@ void AppOffscreen::initFramebuffer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::draw() {
|
void VulkanOffscreen::transferToHost() {
|
||||||
mRenderer.populateGraphicsCommandBuffer(mCommandBuffer, mFramebuffer, mExtent);
|
|
||||||
|
|
||||||
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
|
||||||
|
|
||||||
VkSubmitInfo submitInfo{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
||||||
.waitSemaphoreCount = 0,
|
|
||||||
.pWaitSemaphores = nullptr,
|
|
||||||
.pWaitDstStageMask = waitStages,
|
|
||||||
.commandBufferCount = 1,
|
|
||||||
.pCommandBuffers = &mCommandBuffer,
|
|
||||||
.signalSemaphoreCount = 0,
|
|
||||||
.pSignalSemaphores = nullptr,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (vkQueueSubmit(mGraphicsQueue, 1, &submitInfo, nullptr) != VK_SUCCESS) {
|
|
||||||
throw std::runtime_error("failed to submit to graphics queue");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppOffscreen::transitionImageLayout() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppOffscreen::transferToHost() {
|
|
||||||
vkDeviceWaitIdle(mDevice);
|
vkDeviceWaitIdle(mDevice);
|
||||||
|
|
||||||
VkBufferImageCopy stagingBufferToImageCopy {
|
VkBufferImageCopy stagingBufferToImageCopy {
|
||||||
|
|
@ -289,7 +290,7 @@ void AppOffscreen::transferToHost() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::readMemory() {
|
void VulkanOffscreen::readMemory() {
|
||||||
void* data;
|
void* data;
|
||||||
uint32_t size = mExtent.height * mExtent.width * sizeof(float) * 4;
|
uint32_t size = mExtent.height * mExtent.width * sizeof(float) * 4;
|
||||||
if (vkMapMemory(mDevice, mStagingBufferMemory, 0, size, 0, &data) != VK_SUCCESS) {
|
if (vkMapMemory(mDevice, mStagingBufferMemory, 0, size, 0, &data) != VK_SUCCESS) {
|
||||||
|
|
@ -304,25 +305,7 @@ void AppOffscreen::readMemory() {
|
||||||
vkUnmapMemory(mDevice, mStagingBufferMemory);
|
vkUnmapMemory(mDevice, mStagingBufferMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::updateUniformBuffer() const {
|
void VulkanOffscreen::initStagingBuffer() {
|
||||||
static float time = 0;
|
|
||||||
time += 0.001;
|
|
||||||
|
|
||||||
glm::mat4 model = glm::rotate(glm::mat4(1.0f), (time * glm::radians(90.f)), glm::vec3(0.f, 0.f, 1.f));
|
|
||||||
glm::mat4 view = glm::lookAt(glm::vec3{2.0f, 2.0f, 2.0f}, glm::vec3{0.0f, 0.0f, 0.0f}, -glm::vec3{0.0f, 0.0f, 1.0f});
|
|
||||||
glm::mat4 perspective = glm::perspective(glm::radians(45.f), (float) mExtent.width / (float) mExtent.height, 0.1f, 10.f);
|
|
||||||
|
|
||||||
auto transforms = perspective * view * model;
|
|
||||||
|
|
||||||
CustomShader::UniformBuffer ubo{
|
|
||||||
.transforms = transforms,
|
|
||||||
.origin = glm::vec4(0, 0, 0, 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
memcpy(mRenderer.mUniformBufferMemoryMapped, &ubo, sizeof(ubo));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppOffscreen::initStagingBuffer() {
|
|
||||||
|
|
||||||
VkBufferCreateInfo stagingBufferCreateInfo {
|
VkBufferCreateInfo stagingBufferCreateInfo {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
|
|
@ -346,27 +329,24 @@ void AppOffscreen::initStagingBuffer() {
|
||||||
vkBindBufferMemory(mDevice, mStagingBuffer, mStagingBufferMemory, 0);
|
vkBindBufferMemory(mDevice, mStagingBuffer, mStagingBufferMemory, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::finalizeStagingBuffer() {
|
void VulkanOffscreen::finalizeStagingBuffer() {
|
||||||
vkFreeMemory(mDevice, mStagingBufferMemory, nullptr);
|
vkFreeMemory(mDevice, mStagingBufferMemory, nullptr);
|
||||||
vkDestroyBuffer(mDevice, mStagingBuffer, nullptr);
|
vkDestroyBuffer(mDevice, mStagingBuffer, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::finalizeFramebuffer() {
|
void VulkanOffscreen::finalizeFramebuffer() {
|
||||||
vkFreeMemory(mDevice, mFramebufferMemory, nullptr);
|
vkFreeMemory(mDevice, mFramebufferMemory, nullptr);
|
||||||
vkDestroyFramebuffer(mDevice, mFramebuffer, nullptr);
|
vkDestroyFramebuffer(mDevice, mFramebuffer, nullptr);
|
||||||
vkDestroyImageView(mDevice, mImageView, nullptr);
|
vkDestroyImageView(mDevice, mImageView, nullptr);
|
||||||
vkDestroyImage(mDevice, mImage, nullptr);
|
vkDestroyImage(mDevice, mImage, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::finalizePipeline() {
|
void VulkanOffscreen::finalizePipeline() {
|
||||||
vkFreeCommandBuffers(mDevice, mCommandPool, 1, &mCommandBuffer);
|
vkFreeCommandBuffers(mDevice, mCommandPool, 1, &mCommandBuffer);
|
||||||
vkDestroyCommandPool(mDevice, mCommandPool, nullptr);
|
vkDestroyCommandPool(mDevice, mCommandPool, nullptr);
|
||||||
|
|
||||||
mShader.destroy(mDevice);
|
|
||||||
mRenderer.destroy(mDevice);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppOffscreen::finalizeDevice() {
|
void VulkanOffscreen::finalizeDevice() {
|
||||||
vkDestroyDevice(mDevice, nullptr);
|
vkDestroyDevice(mDevice, nullptr);
|
||||||
vkDestroyInstance(mInstance, nullptr);
|
vkDestroyInstance(mInstance, nullptr);
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#include "vulkan_utils.hpp"
|
#include "VulkanUtils.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
@ -1,32 +1,69 @@
|
||||||
#include "app_interactive.hpp"
|
#include "VulkanWindow.hpp"
|
||||||
|
#include "SwapChain.hpp"
|
||||||
#include <vulkan/vulkan.h>
|
|
||||||
|
|
||||||
#include "renderer.hpp"
|
|
||||||
#include "swapchain.hpp"
|
|
||||||
#include "vulkan_utils.hpp"
|
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
VulkanWindow::VulkanWindow() {
|
||||||
|
mSwapChain = new SwapChain();
|
||||||
|
|
||||||
void AppInteractive::run() {
|
|
||||||
initWindow();
|
initWindow();
|
||||||
initVulkan();
|
initVulkan();
|
||||||
mainLoop();
|
|
||||||
cleanup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::scheduleWindowResize(int sizeX, int sizeY) {
|
VulkanWindow::~VulkanWindow() {
|
||||||
|
cleanup();
|
||||||
|
delete mSwapChain;
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderCreateInfo VulkanWindow::getRenderInfo() {
|
||||||
|
return {
|
||||||
|
mDevice, mPhysicalDevice,
|
||||||
|
mSwapChain->mSwapChainExtent, mSwapChain->mSwapChainFormat,
|
||||||
|
mCommandPool, mGraphicsQueue, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWwindow* VulkanWindow::getWindow() {
|
||||||
|
return mWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDevice VulkanWindow::getDevice() {
|
||||||
|
return mDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanWindow::setRenderPass(VkRenderPass renderPass) {
|
||||||
|
mRenderPass = renderPass;
|
||||||
|
mSwapChain->createSwapChainFramebuffers(mDevice, mRenderPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanWindow::pollEvents() {
|
||||||
|
glfwPollEvents();
|
||||||
|
|
||||||
|
if (mWindowSizeDirtyFlag) {
|
||||||
|
if (timeDeltaMs(mWindowSizeDirtyFlagTime) > mWindowSizeApplyMinDelay) {
|
||||||
|
recreateSwapChain(mWindowFramebufferSize.first, mWindowFramebufferSize.second);
|
||||||
|
mWindowSizeDirtyFlag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanWindow::waitDevice() {
|
||||||
|
vkDeviceWaitIdle(mDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanWindow::scheduleWindowResize(int sizeX, int sizeY) {
|
||||||
mWindowSizeDirtyFlagTime = std::chrono::system_clock::now();
|
mWindowSizeDirtyFlagTime = std::chrono::system_clock::now();
|
||||||
mWindowSizeDirtyFlag = true;
|
mWindowSizeDirtyFlag = true;
|
||||||
mWindowFramebufferSize = std::make_pair(sizeX, sizeY);
|
mWindowFramebufferSize = std::make_pair(sizeX, sizeY);
|
||||||
assert(!(sizeX <= 0 || sizeY <= 0));
|
assert(!(sizeX <= 0 || sizeY <= 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::initWindow() {
|
void VulkanWindow::initWindow() {
|
||||||
// glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
// glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
||||||
glfwInit();
|
glfwInit();
|
||||||
|
|
||||||
|
|
@ -37,11 +74,11 @@ void AppInteractive::initWindow() {
|
||||||
|
|
||||||
glfwSetWindowUserPointer(mWindow, this);
|
glfwSetWindowUserPointer(mWindow, this);
|
||||||
glfwSetFramebufferSizeCallback(mWindow, [](GLFWwindow *window, int sizeX, int sizeY) {
|
glfwSetFramebufferSizeCallback(mWindow, [](GLFWwindow *window, int sizeX, int sizeY) {
|
||||||
((AppInteractive *) glfwGetWindowUserPointer(window))->scheduleWindowResize(sizeX, sizeY);
|
((VulkanWindow *) glfwGetWindowUserPointer(window))->scheduleWindowResize(sizeX, sizeY);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::initVulkan() {
|
void VulkanWindow::initVulkan() {
|
||||||
const std::vector<const char *> deviceExtensions = {
|
const std::vector<const char *> deviceExtensions = {
|
||||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||||
};
|
};
|
||||||
|
|
@ -105,44 +142,16 @@ void AppInteractive::initVulkan() {
|
||||||
.presentationQueueFamilyIndex = (uint32_t) mPresentationQueueFamilyIndex,
|
.presentationQueueFamilyIndex = (uint32_t) mPresentationQueueFamilyIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
mSwapChain.createSwapChain(swapChainCreateInfo);
|
mSwapChain->createSwapChain(swapChainCreateInfo);
|
||||||
mSwapChain.createSwapChainImageViews(mDevice);
|
mSwapChain->createSwapChainImageViews(mDevice);
|
||||||
|
|
||||||
createCommandPool();
|
createCommandPool();
|
||||||
createCommandBuffer();
|
createCommandBuffer();
|
||||||
|
|
||||||
Renderer::CreateInfo rendererCreateInfo{
|
|
||||||
mDevice, mPhysicalDevice,
|
|
||||||
mSwapChain.mSwapChainExtent, mSwapChain.mSwapChainFormat,
|
|
||||||
mCommandPool, mGraphicsQueue, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
|
|
||||||
};
|
|
||||||
|
|
||||||
mRenderer.create(rendererCreateInfo);
|
|
||||||
|
|
||||||
mSwapChain.createSwapChainFramebuffers(mDevice, mRenderer.mGraphicsRenderPass);
|
|
||||||
|
|
||||||
createSynchronizationObjects();
|
createSynchronizationObjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::mainLoop() {
|
void VulkanWindow::createLogicalDevice(const std::vector<const char *> &deviceExtensions) {
|
||||||
while (!glfwWindowShouldClose(mWindow)) {
|
|
||||||
glfwPollEvents();
|
|
||||||
|
|
||||||
if (mWindowSizeDirtyFlag) {
|
|
||||||
auto timeDelayMs = timeDeltaMs(mWindowSizeDirtyFlagTime);
|
|
||||||
if (timeDelayMs > mWindowSizeApplyMinDelay) {
|
|
||||||
recreateSwapChain(mWindowFramebufferSize.first, mWindowFramebufferSize.second);
|
|
||||||
mWindowSizeDirtyFlag = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
drawFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
vkDeviceWaitIdle(mDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppInteractive::createLogicalDevice(const std::vector<const char *> &deviceExtensions) {
|
|
||||||
float queuePriority = 1.f;
|
float queuePriority = 1.f;
|
||||||
|
|
||||||
VkDeviceQueueCreateInfo graphicsQueueCreateInfos{
|
VkDeviceQueueCreateInfo graphicsQueueCreateInfos{
|
||||||
|
|
@ -181,21 +190,21 @@ void AppInteractive::createLogicalDevice(const std::vector<const char *> &device
|
||||||
if (mDevice == VK_NULL_HANDLE) throw std::runtime_error("failed to create vulkan logical device");
|
if (mDevice == VK_NULL_HANDLE) throw std::runtime_error("failed to create vulkan logical device");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::getQueues() {
|
void VulkanWindow::getQueues() {
|
||||||
vkGetDeviceQueue(mDevice, mGraphicsQueueFamilyIndex, 0, &mGraphicsQueue);
|
vkGetDeviceQueue(mDevice, mGraphicsQueueFamilyIndex, 0, &mGraphicsQueue);
|
||||||
vkGetDeviceQueue(mDevice, mPresentationQueueFamilyIndex, 0, &mPresentQueue);
|
vkGetDeviceQueue(mDevice, mPresentationQueueFamilyIndex, 0, &mPresentQueue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::createWindowSurface() {
|
void VulkanWindow::createWindowSurface() {
|
||||||
if (glfwCreateWindowSurface(mInstance, mWindow, nullptr, &mSurface) != VK_SUCCESS) {
|
if (glfwCreateWindowSurface(mInstance, mWindow, nullptr, &mSurface) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("failed to create vulkan window surface");
|
throw std::runtime_error("failed to create vulkan window surface");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::recreateSwapChain(int sizeX, int sizeY) {
|
void VulkanWindow::recreateSwapChain(int sizeX, int sizeY) {
|
||||||
vkDeviceWaitIdle(mDevice);
|
vkDeviceWaitIdle(mDevice);
|
||||||
|
|
||||||
mSwapChain.destroySwapChain(mDevice);
|
mSwapChain->destroySwapChain(mDevice);
|
||||||
|
|
||||||
SwapChain::CreateInfo createInfo{
|
SwapChain::CreateInfo createInfo{
|
||||||
.device = mDevice,
|
.device = mDevice,
|
||||||
|
|
@ -207,13 +216,12 @@ void AppInteractive::recreateSwapChain(int sizeX, int sizeY) {
|
||||||
.presentationQueueFamilyIndex = (uint32_t) mPresentationQueueFamilyIndex,
|
.presentationQueueFamilyIndex = (uint32_t) mPresentationQueueFamilyIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
mSwapChain.createSwapChain(createInfo);
|
mSwapChain->createSwapChain(createInfo);
|
||||||
mSwapChain.createSwapChainImageViews(mDevice);
|
mSwapChain->createSwapChainImageViews(mDevice);
|
||||||
mSwapChain.createSwapChainFramebuffers(mDevice, mRenderer.mGraphicsRenderPass);
|
mSwapChain->createSwapChainFramebuffers(mDevice, mRenderPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanWindow::createSynchronizationObjects() {
|
||||||
void AppInteractive::createSynchronizationObjects() {
|
|
||||||
VkSemaphoreCreateInfo semaphoreCreateInfo{
|
VkSemaphoreCreateInfo semaphoreCreateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||||
};
|
};
|
||||||
|
|
@ -232,18 +240,27 @@ void AppInteractive::createSynchronizationObjects() {
|
||||||
if (failure) throw std::runtime_error("failed to create synchronization objects");
|
if (failure) throw std::runtime_error("failed to create synchronization objects");
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::drawFrame() {
|
VulkanWindow::DrawFrame VulkanWindow::startDrawFrame() {
|
||||||
vkWaitForFences(mDevice, 1, &mFenceCanStartNewFrame, VK_TRUE, UINT64_MAX);
|
vkWaitForFences(mDevice, 1, &mFenceCanStartNewFrame, VK_TRUE, UINT64_MAX);
|
||||||
vkResetFences(mDevice, 1, &mFenceCanStartNewFrame);
|
vkResetFences(mDevice, 1, &mFenceCanStartNewFrame);
|
||||||
|
|
||||||
uint32_t imageIndex = 0;
|
uint32_t imageIndex = 0;
|
||||||
vkAcquireNextImageKHR(mDevice, mSwapChain.mSwapChain, UINT64_MAX, mSemaphoreImageAcquired, VK_NULL_HANDLE,
|
vkAcquireNextImageKHR(mDevice, mSwapChain->mSwapChain, UINT64_MAX, mSemaphoreImageAcquired, VK_NULL_HANDLE,
|
||||||
&imageIndex);
|
&imageIndex);
|
||||||
|
|
||||||
vkResetCommandBuffer(mCommandBuffer, 0);
|
vkResetCommandBuffer(mCommandBuffer, 0);
|
||||||
mRenderer.populateGraphicsCommandBuffer(mCommandBuffer, mSwapChain.mSwapChainFrameBuffers[imageIndex],
|
|
||||||
mSwapChain.mSwapChainExtent);
|
|
||||||
|
|
||||||
|
VkFramebuffer framebuffer = mSwapChain->mSwapChainFrameBuffers[imageIndex];
|
||||||
|
|
||||||
|
return {
|
||||||
|
.commandBuffer = mCommandBuffer,
|
||||||
|
.frameBuffer = framebuffer,
|
||||||
|
.extent2D = mSwapChain->mSwapChainExtent,
|
||||||
|
.swapChainImageIndex = imageIndex,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanWindow::endDrawFrame(const DrawFrame& frame) {
|
||||||
VkSemaphore waitSemaphores[] = {mSemaphoreImageAcquired};
|
VkSemaphore waitSemaphores[] = {mSemaphoreImageAcquired};
|
||||||
VkSemaphore signalSemaphores[] = {mSemaphoreFramebufferDrawn};
|
VkSemaphore signalSemaphores[] = {mSemaphoreFramebufferDrawn};
|
||||||
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
||||||
|
|
@ -259,13 +276,11 @@ void AppInteractive::drawFrame() {
|
||||||
.pSignalSemaphores = signalSemaphores,
|
.pSignalSemaphores = signalSemaphores,
|
||||||
};
|
};
|
||||||
|
|
||||||
updateUniformBuffer();
|
|
||||||
|
|
||||||
if (vkQueueSubmit(mGraphicsQueue, 1, &submitInfo, mFenceCanStartNewFrame) != VK_SUCCESS) {
|
if (vkQueueSubmit(mGraphicsQueue, 1, &submitInfo, mFenceCanStartNewFrame) != VK_SUCCESS) {
|
||||||
throw std::runtime_error("failed to submit to graphics queue");
|
throw std::runtime_error("failed to submit to graphics queue");
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSwapchainKHR swapchains[] = {mSwapChain.mSwapChain};
|
VkSwapchainKHR swapchains[] = {mSwapChain->mSwapChain};
|
||||||
|
|
||||||
VkPresentInfoKHR presentInfo{
|
VkPresentInfoKHR presentInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
|
||||||
|
|
@ -273,53 +288,23 @@ void AppInteractive::drawFrame() {
|
||||||
.pWaitSemaphores = signalSemaphores,
|
.pWaitSemaphores = signalSemaphores,
|
||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
.pSwapchains = swapchains,
|
.pSwapchains = swapchains,
|
||||||
.pImageIndices = &imageIndex,
|
.pImageIndices = &frame.swapChainImageIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkQueuePresentKHR(mPresentQueue, &presentInfo);
|
vkQueuePresentKHR(mPresentQueue, &presentInfo);
|
||||||
/* Somehow res is always VK_SUCCESS
|
|
||||||
if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) {
|
|
||||||
recreateSwapChain();
|
|
||||||
} else if (res != VK_SUCCESS) {
|
|
||||||
throw std::runtime_error("cannot acquire new khr image");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::updateUniformBuffer() const {
|
void VulkanWindow::destroySynchronizationObjects() {
|
||||||
static float time = 0;
|
|
||||||
time += 0.001;
|
|
||||||
|
|
||||||
glm::mat4 model = glm::rotate(glm::mat4(1.0f), (time * glm::radians(90.f)), glm::vec3(0.f, 0.f, 1.f));
|
|
||||||
glm::mat4 view = glm::lookAt(glm::vec3{2.0f, 2.0f, 2.0f}, glm::vec3{0.0f, 0.0f, 0.0f}, -glm::vec3{0.0f, 0.0f, 1.0f});
|
|
||||||
glm::mat4 perspective = glm::perspective(glm::radians(45.f),
|
|
||||||
(float) mWindowFramebufferSize.first /
|
|
||||||
(float) mWindowFramebufferSize.second, 0.1f, 10.f);
|
|
||||||
|
|
||||||
auto transforms = perspective * view * model;
|
|
||||||
|
|
||||||
CustomShader::UniformBuffer ubo{
|
|
||||||
.transforms = transforms,
|
|
||||||
.origin = glm::vec4(0, 0, 0, 0),
|
|
||||||
};
|
|
||||||
|
|
||||||
memcpy(mRenderer.mUniformBufferMemoryMapped, &ubo, sizeof(ubo));
|
|
||||||
// ubo.transforms =
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppInteractive::destroySynchronizationObjects() {
|
|
||||||
vkDestroySemaphore(mDevice, mSemaphoreImageAcquired, nullptr);
|
vkDestroySemaphore(mDevice, mSemaphoreImageAcquired, nullptr);
|
||||||
vkDestroySemaphore(mDevice, mSemaphoreFramebufferDrawn, nullptr);
|
vkDestroySemaphore(mDevice, mSemaphoreFramebufferDrawn, nullptr);
|
||||||
vkDestroyFence(mDevice, mFenceCanStartNewFrame, nullptr);
|
vkDestroyFence(mDevice, mFenceCanStartNewFrame, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::cleanup() {
|
void VulkanWindow::cleanup() {
|
||||||
mRenderer.destroy(mDevice);
|
|
||||||
|
|
||||||
destroyCommandPool();
|
destroyCommandPool();
|
||||||
destroySynchronizationObjects();
|
destroySynchronizationObjects();
|
||||||
|
|
||||||
mSwapChain.destroySwapChain(mDevice);
|
mSwapChain->destroySwapChain(mDevice);
|
||||||
|
|
||||||
vkDestroyDevice(mDevice, nullptr);
|
vkDestroyDevice(mDevice, nullptr);
|
||||||
vkDestroySurfaceKHR(mInstance, mSurface, nullptr);
|
vkDestroySurfaceKHR(mInstance, mSurface, nullptr);
|
||||||
|
|
@ -328,7 +313,7 @@ void AppInteractive::cleanup() {
|
||||||
glfwTerminate();
|
glfwTerminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::createCommandPool() {
|
void VulkanWindow::createCommandPool() {
|
||||||
VkCommandPoolCreateInfo createInfo{
|
VkCommandPoolCreateInfo createInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
|
||||||
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
|
||||||
|
|
@ -340,7 +325,7 @@ void AppInteractive::createCommandPool() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::createCommandBuffer() {
|
void VulkanWindow::createCommandBuffer() {
|
||||||
VkCommandBufferAllocateInfo allocateInfo{
|
VkCommandBufferAllocateInfo allocateInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
.commandPool = mCommandPool,
|
.commandPool = mCommandPool,
|
||||||
|
|
@ -353,6 +338,6 @@ void AppInteractive::createCommandBuffer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppInteractive::destroyCommandPool() {
|
void VulkanWindow::destroyCommandPool() {
|
||||||
vkDestroyCommandPool(mDevice, mCommandPool, nullptr);
|
vkDestroyCommandPool(mDevice, mCommandPool, nullptr);
|
||||||
}
|
}
|
||||||
15
src/VulkanGraphics/public/VulkanInterface.hpp
Normal file
15
src/VulkanGraphics/public/VulkanInterface.hpp
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
|
struct RenderCreateInfo {
|
||||||
|
VkDevice device;
|
||||||
|
VkPhysicalDevice physicalDevice;
|
||||||
|
VkExtent2D extent2D;
|
||||||
|
VkFormat format;
|
||||||
|
|
||||||
|
VkCommandPool commandPool;
|
||||||
|
VkQueue queue;
|
||||||
|
|
||||||
|
VkImageLayout finalImageLayout;
|
||||||
|
};
|
||||||
|
|
@ -1,39 +1,44 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "vulkan_utils.hpp"
|
#include "VulkanUtils.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "renderer.hpp"
|
class VulkanOffscreen {
|
||||||
#include "shader.hpp"
|
|
||||||
|
|
||||||
class AppOffscreen {
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AppOffscreen();
|
VulkanOffscreen();
|
||||||
|
~VulkanOffscreen();
|
||||||
|
|
||||||
void run();
|
RenderCreateInfo getRenderInfo();
|
||||||
|
void setRenderPass(VkRenderPass renderPass);
|
||||||
|
|
||||||
~AppOffscreen();
|
struct FrameData {
|
||||||
|
VkCommandBuffer commandBuffer;
|
||||||
|
VkFramebuffer framebuffer;
|
||||||
|
VkExtent2D extent2D;
|
||||||
|
};
|
||||||
|
|
||||||
|
FrameData beginDrawFrame();
|
||||||
|
void endDrawFrame(const FrameData& frame);
|
||||||
|
|
||||||
|
void saveFrame();
|
||||||
|
|
||||||
|
VkDevice getDevice() { return mDevice; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initDevice();
|
void initDevice();
|
||||||
|
|
||||||
void initPipeline();
|
void initPipeline();
|
||||||
|
|
||||||
void initFramebuffer();
|
void initFramebuffer(VkRenderPass renderPass);
|
||||||
|
|
||||||
void initStagingBuffer();
|
void initStagingBuffer();
|
||||||
|
|
||||||
void draw();
|
|
||||||
|
|
||||||
void transitionImageLayout();
|
|
||||||
|
|
||||||
void readMemory();
|
void readMemory();
|
||||||
|
|
||||||
void updateUniformBuffer() const;
|
|
||||||
|
|
||||||
void transferToHost();
|
void transferToHost();
|
||||||
|
|
||||||
void finalizeStagingBuffer();
|
void finalizeStagingBuffer();
|
||||||
|
|
@ -70,7 +75,4 @@ private:
|
||||||
|
|
||||||
VkBuffer mStagingBuffer = VK_NULL_HANDLE;
|
VkBuffer mStagingBuffer = VK_NULL_HANDLE;
|
||||||
VkDeviceMemory mStagingBufferMemory = VK_NULL_HANDLE;
|
VkDeviceMemory mStagingBufferMemory = VK_NULL_HANDLE;
|
||||||
|
|
||||||
Renderer mRenderer;
|
|
||||||
CustomShader mShader;
|
|
||||||
};
|
};
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vulkan/vulkan.h>
|
#include "VulkanInterface.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
@ -15,4 +16,4 @@ int findQueueFamilyIndex(VkPhysicalDevice physicalDevice, const QueuePickPolicy&
|
||||||
uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags flags);
|
uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags flags);
|
||||||
|
|
||||||
VkInstance createInstance(const char ** instanceExtensions, uint32_t extensionsCount);
|
VkInstance createInstance(const char ** instanceExtensions, uint32_t extensionsCount);
|
||||||
VkPhysicalDevice pickPhysicalDevice(VkInstance instance, const PhysicalDevicePickPolicy& pickPolicy);
|
VkPhysicalDevice pickPhysicalDevice(VkInstance instance, const PhysicalDevicePickPolicy& pickPolicy);
|
||||||
|
|
@ -1,16 +1,35 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "vulkan_utils.hpp"
|
#include "VulkanUtils.hpp"
|
||||||
|
|
||||||
#include "renderer.hpp"
|
|
||||||
#include "swapchain.hpp"
|
|
||||||
#include "utils.hpp"
|
#include "utils.hpp"
|
||||||
|
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
class AppInteractive {
|
class SwapChain;
|
||||||
|
|
||||||
|
class VulkanWindow {
|
||||||
public:
|
public:
|
||||||
void run();
|
VulkanWindow();
|
||||||
|
~VulkanWindow();
|
||||||
|
|
||||||
|
GLFWwindow* getWindow();
|
||||||
|
VkDevice getDevice();
|
||||||
|
RenderCreateInfo getRenderInfo();
|
||||||
|
void setRenderPass(VkRenderPass renderPass);
|
||||||
|
|
||||||
|
struct DrawFrame{
|
||||||
|
VkCommandBuffer commandBuffer;
|
||||||
|
VkFramebuffer frameBuffer;
|
||||||
|
VkExtent2D extent2D;
|
||||||
|
uint32_t swapChainImageIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
void pollEvents();
|
||||||
|
void waitDevice();
|
||||||
|
|
||||||
|
DrawFrame startDrawFrame();
|
||||||
|
void endDrawFrame(const DrawFrame& frame);
|
||||||
|
|
||||||
void scheduleWindowResize(int sizeX, int sizeY);
|
void scheduleWindowResize(int sizeX, int sizeY);
|
||||||
|
|
||||||
|
|
@ -19,8 +38,6 @@ private:
|
||||||
|
|
||||||
void initVulkan();
|
void initVulkan();
|
||||||
|
|
||||||
void mainLoop();
|
|
||||||
|
|
||||||
void createLogicalDevice(const std::vector<const char *> &deviceExtensions);
|
void createLogicalDevice(const std::vector<const char *> &deviceExtensions);
|
||||||
|
|
||||||
void getQueues();
|
void getQueues();
|
||||||
|
|
@ -31,10 +48,6 @@ private:
|
||||||
|
|
||||||
void createSynchronizationObjects();
|
void createSynchronizationObjects();
|
||||||
|
|
||||||
void drawFrame();
|
|
||||||
|
|
||||||
void updateUniformBuffer() const;
|
|
||||||
|
|
||||||
void destroySynchronizationObjects();
|
void destroySynchronizationObjects();
|
||||||
|
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
|
@ -67,9 +80,10 @@ private:
|
||||||
VkQueue mPresentQueue = VK_NULL_HANDLE;
|
VkQueue mPresentQueue = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkSurfaceKHR mSurface = VK_NULL_HANDLE;
|
VkSurfaceKHR mSurface = VK_NULL_HANDLE;
|
||||||
SwapChain mSwapChain;
|
SwapChain* mSwapChain = nullptr;
|
||||||
|
|
||||||
Renderer mRenderer;
|
VkRenderPass mRenderPass = VK_NULL_HANDLE;
|
||||||
|
// Renderer* mRenderer = nullptr;
|
||||||
|
|
||||||
VkSemaphore mSemaphoreImageAcquired = VK_NULL_HANDLE;
|
VkSemaphore mSemaphoreImageAcquired = VK_NULL_HANDLE;
|
||||||
VkSemaphore mSemaphoreFramebufferDrawn = VK_NULL_HANDLE;
|
VkSemaphore mSemaphoreFramebufferDrawn = VK_NULL_HANDLE;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue