|
@@ -4,10 +4,11 @@
|
|
#include <core/UniquePointer.hpp>
|
|
#include <core/UniquePointer.hpp>
|
|
|
|
|
|
#include "GLFW.hpp"
|
|
#include "GLFW.hpp"
|
|
-#include "VulkanUtils.hpp"
|
|
|
|
#include "core/VulkanBase.hpp"
|
|
#include "core/VulkanBase.hpp"
|
|
|
|
|
|
namespace Vulkan = Core::Vulkan;
|
|
namespace Vulkan = Core::Vulkan;
|
|
|
|
+using Vulkan::CommandBuffer;
|
|
|
|
+using Vulkan::SwapchainImages;
|
|
|
|
|
|
#define WRAPPER_DESTRUCT(Type, ...) \
|
|
#define WRAPPER_DESTRUCT(Type, ...) \
|
|
using Core::Vulkan::Type; \
|
|
using Core::Vulkan::Type; \
|
|
@@ -25,6 +26,38 @@ WRAPPER_DESTRUCT(Swapchain, KHR)
|
|
WRAPPER_DESTRUCT(ShaderModule)
|
|
WRAPPER_DESTRUCT(ShaderModule)
|
|
WRAPPER_DESTRUCT(PipelineLayout)
|
|
WRAPPER_DESTRUCT(PipelineLayout)
|
|
|
|
|
|
|
|
+bool ImageView::init(VkDevice d, VkImage image, VkFormat format) {
|
|
|
|
+ VkImageViewCreateInfo info = {
|
|
|
|
+ .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
+ .image = image,
|
|
|
|
+ .viewType = VK_IMAGE_VIEW_TYPE_2D,
|
|
|
|
+ .format = format,
|
|
|
|
+ .subresourceRange = {
|
|
|
|
+ .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
|
|
|
+ .baseMipLevel = 0,
|
|
|
|
+ .levelCount = 1,
|
|
|
|
+ .baseArrayLayer = 0,
|
|
|
|
+ .layerCount = 1}};
|
|
|
|
+ VK_CHECK_TRUE(vkCreateImageView(d, &info, nullptr, &handle));
|
|
|
|
+ device = d;
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool Framebuffer::init(
|
|
|
|
+ const ImageView& iv, VkRenderPass rp, u32 width, u32 height) {
|
|
|
|
+ VkFramebufferCreateInfo info = {
|
|
|
|
+ .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
|
|
|
+ .renderPass = rp,
|
|
|
|
+ .attachmentCount = 1,
|
|
|
|
+ .pAttachments = iv,
|
|
|
|
+ .width = width,
|
|
|
|
+ .height = height,
|
|
|
|
+ .layers = 1};
|
|
|
|
+ VK_CHECK_TRUE(vkCreateFramebuffer(iv.device, &info, nullptr, &handle));
|
|
|
|
+ device = iv.device;
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
bool Semaphore::init(VkDevice d) {
|
|
bool Semaphore::init(VkDevice d) {
|
|
VkSemaphoreCreateInfo info = {
|
|
VkSemaphoreCreateInfo info = {
|
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
|
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO};
|
|
@@ -42,6 +75,43 @@ bool Fence::init(VkDevice d) {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static u32 getSwapImageCount(const VkSurfaceCapabilitiesKHR* caps) {
|
|
|
|
+ u32 c = caps->minImageCount + 1;
|
|
|
|
+ // according to VkSurfaceCapabilitiesKHR doc:
|
|
|
|
+ // maxImageCount is 0 when there is no strict limit
|
|
|
|
+ if(caps->maxImageCount != 0) {
|
|
|
|
+ return Core::min(c, caps->maxImageCount);
|
|
|
|
+ }
|
|
|
|
+ return c;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool Swapchain::init(Data& d) {
|
|
|
|
+ VkSurfaceCapabilitiesKHR caps = {0};
|
|
|
|
+ if(d.base.getSurfaceCapabilities(caps)) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ VkSwapchainCreateInfoKHR ci = {
|
|
|
|
+ .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
|
|
|
+ .surface = d.base,
|
|
|
|
+ .minImageCount = getSwapImageCount(&caps),
|
|
|
|
+ .imageFormat = d.surfaceFormat.format,
|
|
|
|
+ .imageColorSpace = d.surfaceFormat.colorSpace,
|
|
|
|
+ .imageExtent = d.size,
|
|
|
|
+ .imageArrayLayers = 1,
|
|
|
|
+ .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
|
|
|
+ .imageSharingMode = d.sharingMode,
|
|
|
|
+ .queueFamilyIndexCount = static_cast<u32>(d.queueFamilies.getLength()),
|
|
|
|
+ .pQueueFamilyIndices = &d.queueFamilies[0],
|
|
|
|
+ .preTransform = caps.currentTransform,
|
|
|
|
+ .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
|
|
|
+ .presentMode = d.presentMode,
|
|
|
|
+ .clipped = VK_TRUE,
|
|
|
|
+ .oldSwapchain = VK_NULL_HANDLE};
|
|
|
|
+ VK_CHECK_TRUE(vkCreateSwapchainKHR(d.base, &ci, nullptr, &handle));
|
|
|
|
+ device = d.base;
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
bool ShaderModule::init(VkDevice d, const char* path) {
|
|
bool ShaderModule::init(VkDevice d, const char* path) {
|
|
List<char> f;
|
|
List<char> f;
|
|
if(Core::readFile(f, path)) {
|
|
if(Core::readFile(f, path)) {
|
|
@@ -69,6 +139,31 @@ bool PipelineLayout::init(VkDevice d) {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+bool SwapchainImages::init(const Swapchain& s, VkFormat format) {
|
|
|
|
+ u32 c = 0;
|
|
|
|
+ VK_CHECK_TRUE(vkGetSwapchainImagesKHR(s.device, s.handle, &c, nullptr));
|
|
|
|
+ images.resize(c);
|
|
|
|
+ imageViews.resize(c);
|
|
|
|
+ VK_CHECK_TRUE(vkGetSwapchainImagesKHR(s.device, s.handle, &c, &images[0]));
|
|
|
|
+ for(u32 x = 0; x < c; x++) {
|
|
|
|
+ if(imageViews[x].init(s.device, images[x], format)) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool CommandBuffer::init(VkDevice d, VkCommandPool cp) {
|
|
|
|
+ VkCommandBufferAllocateInfo info = {
|
|
|
|
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
|
|
|
+ .commandPool = cp,
|
|
|
|
+ .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
|
|
|
+ .commandBufferCount = 1};
|
|
|
|
+ VK_CHECK_TRUE(vkAllocateCommandBuffers(d, &info, &handle));
|
|
|
|
+ device = d;
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
struct VulkanDummy {
|
|
struct VulkanDummy {
|
|
Core::Vulkan::Base base{};
|
|
Core::Vulkan::Base base{};
|
|
|
|
|
|
@@ -84,7 +179,7 @@ struct VulkanDummy {
|
|
VkQueue presentQueue{};
|
|
VkQueue presentQueue{};
|
|
VkExtent2D swapchainSize{};
|
|
VkExtent2D swapchainSize{};
|
|
Swapchain swapchain{};
|
|
Swapchain swapchain{};
|
|
- VulkanSwapchainImages images{};
|
|
|
|
|
|
+ SwapchainImages images{};
|
|
ShaderModule vertexShaderModule{};
|
|
ShaderModule vertexShaderModule{};
|
|
ShaderModule fragmentShaderModule{};
|
|
ShaderModule fragmentShaderModule{};
|
|
PipelineLayout pipelineLayout{};
|
|
PipelineLayout pipelineLayout{};
|
|
@@ -99,7 +194,7 @@ struct VulkanDummy {
|
|
bool shouldWait = false;
|
|
bool shouldWait = false;
|
|
|
|
|
|
struct Frame {
|
|
struct Frame {
|
|
- VkCommandBuffer commandBuffer{};
|
|
|
|
|
|
+ CommandBuffer commandBuffer{};
|
|
Semaphore imageAvailableSemaphore{};
|
|
Semaphore imageAvailableSemaphore{};
|
|
Semaphore renderFinishedSemaphore{};
|
|
Semaphore renderFinishedSemaphore{};
|
|
Fence inFlightFence{};
|
|
Fence inFlightFence{};
|
|
@@ -154,7 +249,7 @@ struct VulkanDummy {
|
|
}
|
|
}
|
|
|
|
|
|
bool initSwapchain() {
|
|
bool initSwapchain() {
|
|
- VulkanSwapchainData d = {
|
|
|
|
|
|
+ Vulkan::Swapchain::Data d = {
|
|
.base = base,
|
|
.base = base,
|
|
.surfaceFormat = baseData.surfaceFormat,
|
|
.surfaceFormat = baseData.surfaceFormat,
|
|
.presentMode = baseData.presentMode};
|
|
.presentMode = baseData.presentMode};
|
|
@@ -170,7 +265,7 @@ struct VulkanDummy {
|
|
} else {
|
|
} else {
|
|
d.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
d.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
}
|
|
}
|
|
- return initVulkanSwapchain(swapchain, &d);
|
|
|
|
|
|
+ return swapchain.init(d);
|
|
}
|
|
}
|
|
|
|
|
|
bool initDevice() {
|
|
bool initDevice() {
|
|
@@ -257,8 +352,7 @@ struct VulkanDummy {
|
|
}
|
|
}
|
|
|
|
|
|
bool initSwapchainImages() {
|
|
bool initSwapchainImages() {
|
|
- if(initVulkanSwapchainImages(
|
|
|
|
- images, base, swapchain, baseData.surfaceFormat.format)) {
|
|
|
|
|
|
+ if(images.init(swapchain, baseData.surfaceFormat.format)) {
|
|
LOG_ERROR("Could not get swapchain images");
|
|
LOG_ERROR("Could not get swapchain images");
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
@@ -380,6 +474,19 @@ struct VulkanDummy {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ bool initFramebuffers() {
|
|
|
|
+ framebuffers.resize(images.imageViews.getLength());
|
|
|
|
+ size_t i = 0;
|
|
|
|
+ for(Framebuffer& f : framebuffers) {
|
|
|
|
+ if(f.init(
|
|
|
|
+ images.imageViews[i++], renderPass, swapchainSize.width,
|
|
|
|
+ swapchainSize.height)) {
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+
|
|
bool initRenderPass() {
|
|
bool initRenderPass() {
|
|
VkAttachmentDescription c = {
|
|
VkAttachmentDescription c = {
|
|
.format = baseData.surfaceFormat.format,
|
|
.format = baseData.surfaceFormat.format,
|
|
@@ -450,8 +557,7 @@ struct VulkanDummy {
|
|
|
|
|
|
bool initFrames() {
|
|
bool initFrames() {
|
|
for(size_t i = 0; i < MAX_FRAMES; i++) {
|
|
for(size_t i = 0; i < MAX_FRAMES; i++) {
|
|
- if(initCommandVulkanBuffer(
|
|
|
|
- &frames[i].commandBuffer, base, commandPool) ||
|
|
|
|
|
|
+ if(frames[i].commandBuffer.init(base, commandPool) ||
|
|
frames[i].imageAvailableSemaphore.init(base) ||
|
|
frames[i].imageAvailableSemaphore.init(base) ||
|
|
frames[i].renderFinishedSemaphore.init(base) ||
|
|
frames[i].renderFinishedSemaphore.init(base) ||
|
|
frames[i].inFlightFence.init(base)) {
|
|
frames[i].inFlightFence.init(base)) {
|
|
@@ -465,11 +571,8 @@ struct VulkanDummy {
|
|
return base.init() || initPhysicalDevice() || initDevice() ||
|
|
return base.init() || initPhysicalDevice() || initDevice() ||
|
|
initSwapchain() || initSwapchainImages() || initShaders() ||
|
|
initSwapchain() || initSwapchainImages() || initShaders() ||
|
|
pipelineLayout.init(base) || initRenderPass() ||
|
|
pipelineLayout.init(base) || initRenderPass() ||
|
|
- initPipeline() ||
|
|
|
|
- initVulkanFramebuffers(
|
|
|
|
- framebuffers, images.imageViews, renderPass,
|
|
|
|
- swapchainSize.width, swapchainSize.height) ||
|
|
|
|
- initCommandPool() || initFrames();
|
|
|
|
|
|
+ initPipeline() || initFramebuffers() || initCommandPool() ||
|
|
|
|
+ initFrames();
|
|
}
|
|
}
|
|
|
|
|
|
bool render() {
|
|
bool render() {
|
|
@@ -499,7 +602,7 @@ struct VulkanDummy {
|
|
.pWaitSemaphores = waitSemaphores,
|
|
.pWaitSemaphores = waitSemaphores,
|
|
.pWaitDstStageMask = waitStages,
|
|
.pWaitDstStageMask = waitStages,
|
|
.commandBufferCount = 1,
|
|
.commandBufferCount = 1,
|
|
- .pCommandBuffers = &f->commandBuffer,
|
|
|
|
|
|
+ .pCommandBuffers = f->commandBuffer,
|
|
.signalSemaphoreCount = 1,
|
|
.signalSemaphoreCount = 1,
|
|
.pSignalSemaphores = signalSemaphores};
|
|
.pSignalSemaphores = signalSemaphores};
|
|
VK_CHECK_TRUE(vkQueueSubmit(graphicsQueue, 1, &info, f->inFlightFence));
|
|
VK_CHECK_TRUE(vkQueueSubmit(graphicsQueue, 1, &info, f->inFlightFence));
|