Attempt to add depth buffer

This commit is contained in:
Bailey Harrison 2023-03-13 20:27:47 +00:00
parent 3df5cfbc02
commit 9e7c6e923d
10 changed files with 206 additions and 59 deletions

View File

@ -31,8 +31,8 @@ namespace engine {
const gfx::DescriptorSetLayout* setZeroLayout; const gfx::DescriptorSetLayout* setZeroLayout;
const gfx::DescriptorSet* setZero; const gfx::DescriptorSet* setZero;
struct SetZeroBuffer { struct SetZeroBuffer {
glm::mat4 view;
glm::mat4 proj; glm::mat4 proj;
glm::vec2 myValue;
}; };
gfx::DescriptorBuffer* setZeroBuffer; gfx::DescriptorBuffer* setZeroBuffer;
}; };

View File

@ -2,12 +2,11 @@
layout( push_constant ) uniform Constants { layout( push_constant ) uniform Constants {
mat4 model; mat4 model;
mat4 view;
} constants; } constants;
layout(set = 0, binding = 0) uniform SetZeroBuffer { layout(set = 0, binding = 0) uniform SetZeroBuffer {
mat4 view;
mat4 proj; mat4 proj;
vec2 myValue;
} setZeroBuffer; } setZeroBuffer;
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 inPosition;
@ -16,7 +15,7 @@ layout(location = 2) in vec2 inUV;
layout(location = 0) out vec2 fragUV; layout(location = 0) out vec2 fragUV;
void main() { void main() {
mat4 myView = constants.view; mat4 myView = setZeroBuffer.view;
myView[3] = vec4(0.0, 0.0, 0.0, 1.0); myView[3] = vec4(0.0, 0.0, 0.0, 1.0);
vec4 pos = setZeroBuffer.proj * myView * constants.model * vec4(inPosition, 1.0); vec4 pos = setZeroBuffer.proj * myView * constants.model * vec4(inPosition, 1.0);
gl_Position = pos; gl_Position = pos;

View File

@ -2,12 +2,11 @@
layout( push_constant ) uniform Constants { layout( push_constant ) uniform Constants {
mat4 model; mat4 model;
mat4 view;
} constants; } constants;
layout(set = 0, binding = 0) uniform SetZeroBuffer { layout(set = 0, binding = 0) uniform SetZeroBuffer {
mat4 view;
mat4 proj; mat4 proj;
vec2 myValue;
} setZeroBuffer; } setZeroBuffer;
layout(location = 0) in vec3 inPosition; layout(location = 0) in vec3 inPosition;
@ -20,12 +19,12 @@ layout(location = 2) out vec2 fragUV;
layout(location = 3) out vec3 fragLightPos; layout(location = 3) out vec3 fragLightPos;
void main() { void main() {
gl_Position = setZeroBuffer.proj * constants.view * constants.model * vec4(inPosition, 1.0); gl_Position = setZeroBuffer.proj * setZeroBuffer.view * constants.model * vec4(inPosition, 1.0);
fragPos = vec3(constants.view * constants.model * vec4(inPosition, 1.0)); fragPos = vec3(setZeroBuffer.view * constants.model * vec4(inPosition, 1.0));
fragNorm = mat3(transpose(inverse(constants.view * constants.model))) * inNorm; fragNorm = mat3(transpose(inverse(setZeroBuffer.view * constants.model))) * inNorm;
fragUV = inUV; fragUV = inUV;
vec3 lightPos = vec3(2000.0, 2000.0, -2000.0); vec3 lightPos = vec3(2000.0, 2000.0, -2000.0);
fragLightPos = vec3(constants.view * vec4(lightPos, 1.0)); fragLightPos = vec3(setZeroBuffer.view * vec4(lightPos, 1.0));
} }

View File

@ -78,8 +78,8 @@ namespace engine {
renderData.setZeroLayout = gfx()->createDescriptorSetLayout(); renderData.setZeroLayout = gfx()->createDescriptorSetLayout();
renderData.setZero = gfx()->allocateDescriptorSet(renderData.setZeroLayout); renderData.setZero = gfx()->allocateDescriptorSet(renderData.setZeroLayout);
RenderData::SetZeroBuffer initialData{ RenderData::SetZeroBuffer initialData{
.view = glm::mat4{1.0f},
.proj = glm::perspectiveZO(glm::radians(70.0f), 1024.0f / 768.0f, 0.1f, 1000.0f), .proj = glm::perspectiveZO(glm::radians(70.0f), 1024.0f / 768.0f, 0.1f, 1000.0f),
.myValue = { 0.0f, 1.0f }
}; };
renderData.setZeroBuffer = gfx()->createDescriptorBuffer(sizeof(RenderData::SetZeroBuffer), &initialData); renderData.setZeroBuffer = gfx()->createDescriptorBuffer(sizeof(RenderData::SetZeroBuffer), &initialData);
gfx()->updateDescriptor(renderData.setZero, 0, renderData.setZeroBuffer, 0, sizeof(RenderData::SetZeroBuffer)); gfx()->updateDescriptor(renderData.setZero, 0, renderData.setZeroBuffer, 0, sizeof(RenderData::SetZeroBuffer));

View File

@ -613,6 +613,7 @@ namespace engine {
pimpl->allocator = createAllocator(pimpl->instance.instance, pimpl->device.device, pimpl->device.physicalDevice); pimpl->allocator = createAllocator(pimpl->instance.instance, pimpl->device.device, pimpl->device.physicalDevice);
pimpl->swapchainInfo.device = pimpl->device.device; pimpl->swapchainInfo.device = pimpl->device.device;
pimpl->swapchainInfo.allocator = pimpl->allocator;
pimpl->swapchainInfo.physicalDevice = pimpl->device.physicalDevice; pimpl->swapchainInfo.physicalDevice = pimpl->device.physicalDevice;
pimpl->swapchainInfo.surface = pimpl->surface; pimpl->swapchainInfo.surface = pimpl->surface;
pimpl->swapchainInfo.window = pimpl->window; pimpl->swapchainInfo.window = pimpl->window;

View File

@ -47,11 +47,10 @@ namespace engine {
const glm::mat4 projMatrix = glm::perspectiveZO(verticalFovRadians, m_viewportAspectRatio, m_camera.clipNear, m_camera.clipFar); const glm::mat4 projMatrix = glm::perspectiveZO(verticalFovRadians, m_viewportAspectRatio, m_camera.clipNear, m_camera.clipFar);
/* update SET 0 */ /* update SET 0 */
RenderData::SetZeroBuffer uniform{}; RenderData::SetZeroBuffer uniform{
uniform.proj = projMatrix; .view = viewMatrix,
uniform.myValue.x = 1.0f; .proj = projMatrix
m_value = glm::mod(m_value + ts, 1.0f); };
uniform.myValue.y = m_value;
m_gfx->writeDescriptorBuffer(renderData.setZeroBuffer, 0, sizeof(RenderData::SetZeroBuffer), &uniform); m_gfx->writeDescriptorBuffer(renderData.setZeroBuffer, 0, sizeof(RenderData::SetZeroBuffer), &uniform);
/* render all renderable entities */ /* render all renderable entities */
@ -69,11 +68,9 @@ namespace engine {
struct { struct {
glm::mat4 model; glm::mat4 model;
glm::mat4 view;
} pushConsts{}; } pushConsts{};
pushConsts.model = t->worldMatrix; pushConsts.model = t->worldMatrix;
pushConsts.view = viewMatrix;
m_gfx->cmdBindPipeline(renderData.drawBuffer, r->material->getShader()->getPipeline()); m_gfx->cmdBindPipeline(renderData.drawBuffer, r->material->getShader()->getPipeline());
m_gfx->cmdBindDescriptorSet(renderData.drawBuffer, r->material->getShader()->getPipeline(), renderData.setZero, 0); m_gfx->cmdBindDescriptorSet(renderData.drawBuffer, r->material->getShader()->getPipeline(), renderData.setZero, 0);

View File

@ -5,10 +5,21 @@
#include <cstring> #include <cstring>
#include <assert.h> #include <assert.h>
#include "log.hpp"
#include "device.h" #include "device.h"
namespace engine { namespace engine {
static bool checkQueueFamilySupportsPresent(VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t familyIndex)
{
VkBool32 supportsPresent;
VkResult res;
res = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, static_cast<uint32_t>(familyIndex), surface, &supportsPresent);
if (res != VK_SUCCESS) throw std::runtime_error("Failed to check for queue family present support!");
return supportsPresent;
}
/* chooses a device, creates it, gets its function pointers, and creates command pools */ /* chooses a device, creates it, gets its function pointers, and creates command pools */
Device createDevice(VkInstance instance, DeviceRequirements requirements, VkSurfaceKHR surface) Device createDevice(VkInstance instance, DeviceRequirements requirements, VkSurfaceKHR surface)
{ {
@ -209,22 +220,33 @@ namespace engine {
for (size_t i = 0; i < queueFamilies.size(); i++) { for (size_t i = 0; i < queueFamilies.size(); i++) {
VkQueueFamilyProperties p = queueFamilies[i]; VkQueueFamilyProperties p = queueFamilies[i];
if (p.queueCount < 2) continue; // need one queue for presenting and one-or-more for rendering if (p.queueCount < 2) continue; // ideally have one queue for presenting and at least one other for rendering
if (p.queueFlags & VK_QUEUE_GRAPHICS_BIT) { if (p.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
VkBool32 supportsPresent; if (checkQueueFamilySupportsPresent(d.physicalDevice, surface, i)) {
res = vkGetPhysicalDeviceSurfaceSupportKHR(d.physicalDevice, static_cast<uint32_t>(i), surface, &supportsPresent);
if (res != VK_SUCCESS) throw std::runtime_error("Failed to check for queue family present support!");
if (supportsPresent) {
graphicsFamily = static_cast<uint32_t>(i); graphicsFamily = static_cast<uint32_t>(i);
break; break;
} }
} }
} }
if (graphicsFamily == UINT32_MAX) throw std::runtime_error("Unable to find a graphics/present queue family!"); if (graphicsFamily == UINT32_MAX) {
for (size_t i = 0; i < queueFamilies.size(); i++) {
VkQueueFamilyProperties p = queueFamilies[i];
if (p.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
if (checkQueueFamilySupportsPresent(d.physicalDevice, surface, i)) {
graphicsFamily = static_cast<uint32_t>(i);
}
}
}
if (graphicsFamily == UINT32_MAX) {
throw std::runtime_error("Failed to find a graphics/present family!");
}
LOG_WARN("Failed to find ideal graphics/present queue family! Falling back to family #{}.", graphicsFamily);
}
// find a transfer queue family (image layout transitions, buffer upload) // find a transfer queue family (image layout transitions, buffer upload)
uint32_t transferFamily = UINT32_MAX; uint32_t transferFamily = UINT32_MAX;
// prefer a dedicated transfer queue family
for (size_t i = 0; i < queueFamilies.size(); i++) { for (size_t i = 0; i < queueFamilies.size(); i++) {
VkQueueFamilyProperties p = queueFamilies[i]; VkQueueFamilyProperties p = queueFamilies[i];
if (((p.queueFlags & VK_QUEUE_TRANSFER_BIT) != 0) && if (((p.queueFlags & VK_QUEUE_TRANSFER_BIT) != 0) &&
@ -234,7 +256,10 @@ namespace engine {
break; break;
} }
} }
if (transferFamily == UINT32_MAX) throw std::runtime_error("Unable to find a transfer queue family!"); if (transferFamily == UINT32_MAX) {
transferFamily = graphicsFamily;
LOG_WARN("Failed to find a dedicated transfer queue family! Falling back to graphics family.");
}
// queue priorities // queue priorities
std::vector<float> graphicsQueuePriorities(queueFamilies[graphicsFamily].queueCount); std::vector<float> graphicsQueuePriorities(queueFamilies[graphicsFamily].queueCount);
@ -242,24 +267,26 @@ namespace engine {
std::vector<float> transferQueuePriorities(queueFamilies[transferFamily].queueCount); std::vector<float> transferQueuePriorities(queueFamilies[transferFamily].queueCount);
std::fill(transferQueuePriorities.begin(), transferQueuePriorities.end(), 1.0f); std::fill(transferQueuePriorities.begin(), transferQueuePriorities.end(), 1.0f);
std::array<VkDeviceQueueCreateInfo, 2> queueCreateInfos{ std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
VkDeviceQueueCreateInfo{ queueCreateInfos.push_back(VkDeviceQueueCreateInfo{
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.queueFamilyIndex = graphicsFamily, .queueFamilyIndex = graphicsFamily,
.queueCount = queueFamilies[graphicsFamily].queueCount, .queueCount = queueFamilies[graphicsFamily].queueCount,
.pQueuePriorities = graphicsQueuePriorities.data(), .pQueuePriorities = graphicsQueuePriorities.data()
}, });
VkDeviceQueueCreateInfo{
if (transferFamily != graphicsFamily) {
queueCreateInfos.push_back(VkDeviceQueueCreateInfo{
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.queueFamilyIndex = transferFamily, .queueFamilyIndex = transferFamily,
.queueCount = queueFamilies[transferFamily].queueCount, .queueCount = queueFamilies[transferFamily].queueCount,
.pQueuePriorities = transferQueuePriorities.data(), .pQueuePriorities = transferQueuePriorities.data()
} });
}; }
/* create device now */ /* create device now */
VkDeviceCreateInfo deviceCreateInfo{ VkDeviceCreateInfo deviceCreateInfo{
@ -282,14 +309,49 @@ namespace engine {
volkLoadDevice(d.device); volkLoadDevice(d.device);
vkGetDeviceQueue(d.device, graphicsFamily, 0, &d.queues.presentQueue);
d.queues.drawQueues.resize(queueFamilies[graphicsFamily].queueCount - 1); if (transferFamily != graphicsFamily) {
for (uint32_t i = 0; i < d.queues.drawQueues.size(); i++) { vkGetDeviceQueue(d.device, graphicsFamily, 0, &d.queues.presentQueue);
vkGetDeviceQueue(d.device, graphicsFamily, i + 1, &d.queues.drawQueues[i]); if (queueFamilies[graphicsFamily].queueCount >= 2) {
} d.queues.drawQueues.resize(queueFamilies[graphicsFamily].queueCount - 1);
d.queues.transferQueues.resize(queueFamilies[transferFamily].queueCount); for (uint32_t i = 0; i < d.queues.drawQueues.size(); i++) {
for (uint32_t i = 0; i < d.queues.transferQueues.size(); i++) { vkGetDeviceQueue(d.device, graphicsFamily, i + 1, &d.queues.drawQueues[i]);
vkGetDeviceQueue(d.device, transferFamily, i, &d.queues.transferQueues[i]); }
} else {
d.queues.drawQueues.resize(1);
d.queues.drawQueues[0] = d.queues.presentQueue;
}
d.queues.transferQueues.resize(queueFamilies[transferFamily].queueCount);
for (uint32_t i = 0; i < d.queues.transferQueues.size(); i++) {
vkGetDeviceQueue(d.device, transferFamily, i, &d.queues.transferQueues[i]);
}
} else {
// same graphics family for graphics/present and transfer
uint32_t queueCount = queueFamilies[graphicsFamily].queueCount;
vkGetDeviceQueue(d.device, graphicsFamily, 0, &d.queues.presentQueue);
if (queueCount >= 2) {
d.queues.transferQueues.resize(1);
vkGetDeviceQueue(d.device, graphicsFamily, 1, &d.queues.transferQueues[0]);
// use the remaining queues for drawing
if (queueCount >= 3) {
d.queues.drawQueues.resize(queueCount - 2);
for (uint32_t i = 0; i < queueCount - 2; i++) {
vkGetDeviceQueue(d.device, graphicsFamily, i + 2, &d.queues.drawQueues[i]);
}
} else {
// 2 queues available
// present and drawing share a queue
// transfer gets its own queue
d.queues.drawQueues.resize(1);
d.queues.drawQueues[0] = d.queues.presentQueue;
}
} else {
// only 1 queue available :(
d.queues.transferQueues.resize(1);
d.queues.transferQueues[0] = d.queues.presentQueue;
d.queues.drawQueues.resize(1);
d.queues.drawQueues[0] = d.queues.presentQueue;
}
} }
d.queues.presentAndDrawQueueFamily = graphicsFamily; d.queues.presentAndDrawQueueFamily = graphicsFamily;

View File

@ -14,6 +14,7 @@ namespace engine {
void createSwapchain(Swapchain* sc, const SwapchainInfo& info) void createSwapchain(Swapchain* sc, const SwapchainInfo& info)
{ {
sc->device = info.device; sc->device = info.device;
sc->allocator = info.allocator;
LOG_INFO("Recreating swapchain!\n"); LOG_INFO("Recreating swapchain!\n");
@ -129,6 +130,61 @@ namespace engine {
vkDestroySwapchainKHR(info.device, scInfo.oldSwapchain, nullptr); vkDestroySwapchainKHR(info.device, scInfo.oldSwapchain, nullptr);
} }
{ /* create the depth buffer */
sc->depthStencil.format = VK_FORMAT_D32_SFLOAT;
if (sc->depthStencil.image != VK_NULL_HANDLE) {
vkDestroyImageView(info.device, sc->depthStencil.view, nullptr);
vmaDestroyImage(sc->allocator, sc->depthStencil.image, sc->depthStencil.allocation);
}
VkImageCreateInfo imageInfo{};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
imageInfo.pNext = nullptr;
imageInfo.flags = 0;
imageInfo.imageType = VK_IMAGE_TYPE_2D;
imageInfo.format = sc->depthStencil.format;
imageInfo.extent.width = sc->extent.width;
imageInfo.extent.height = sc->extent.height;
imageInfo.mipLevels = 1;
imageInfo.arrayLayers = 1;
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.queueFamilyIndexCount = 0; // ignored
imageInfo.pQueueFamilyIndices = nullptr; // ignored
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VmaAllocationCreateInfo allocInfo{};
allocInfo.usage = VMA_MEMORY_USAGE_AUTO_PREFER_DEVICE;
allocInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
allocInfo.priority = 1.0f;
res = vmaCreateImage(sc->allocator, &imageInfo, &allocInfo, &sc->depthStencil.image, &sc->depthStencil.allocation, nullptr);
if (res != VK_SUCCESS) throw std::runtime_error("Failed to create depth buffer image! Code: " + std::to_string(res));
VkImageViewCreateInfo viewInfo{};
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
viewInfo.pNext = nullptr;
viewInfo.flags = 0;
viewInfo.image = sc->depthStencil.image;
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
viewInfo.format = sc->depthStencil.format;
viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
viewInfo.subresourceRange.baseMipLevel = 0;
viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1;
res = vkCreateImageView(info.device, &viewInfo, nullptr, &sc->depthStencil.view);
assert(res == VK_SUCCESS);
}
/* create the render pass */ /* create the render pass */
if (sc->renderpass != VK_NULL_HANDLE) { if (sc->renderpass != VK_NULL_HANDLE) {
vkDestroyRenderPass(sc->device, sc->renderpass, nullptr); vkDestroyRenderPass(sc->device, sc->renderpass, nullptr);
@ -144,10 +200,26 @@ namespace engine {
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
}; };
VkAttachmentDescription depthStencilAttachment{
.flags = 0,
.format = sc->depthStencil.format,
.samples = VK_SAMPLE_COUNT_1_BIT,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // the depth buffer is not used after the fragment shader
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE, // ignored
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE, // ignored
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
};
std::array<VkAttachmentDescription, 2> attachments { colorAttachment, depthStencilAttachment };
VkAttachmentReference colorAttachmentRef{ VkAttachmentReference colorAttachmentRef{
.attachment = 0, .attachment = 0,
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
}; };
VkAttachmentReference depthStencilAttachmentRef{
.attachment = 1,
.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
};
VkSubpassDescription subpass{ VkSubpassDescription subpass{
.flags = 0, .flags = 0,
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
@ -156,25 +228,25 @@ namespace engine {
.colorAttachmentCount = 1, .colorAttachmentCount = 1,
.pColorAttachments = &colorAttachmentRef, .pColorAttachments = &colorAttachmentRef,
.pResolveAttachments = nullptr, .pResolveAttachments = nullptr,
.pDepthStencilAttachment = nullptr, .pDepthStencilAttachment = &depthStencilAttachmentRef,
.preserveAttachmentCount = 0, .preserveAttachmentCount = 0,
.pPreserveAttachments = nullptr, .pPreserveAttachments = nullptr,
}; };
VkSubpassDependency dependency{ VkSubpassDependency dependency{
.srcSubpass = VK_SUBPASS_EXTERNAL, .srcSubpass = VK_SUBPASS_EXTERNAL,
.dstSubpass = 0, .dstSubpass = 0,
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, .dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
.srcAccessMask = 0, .srcAccessMask = 0,
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
.dependencyFlags = 0 .dependencyFlags = 0
}; };
VkRenderPassCreateInfo renderPassInfo{ VkRenderPassCreateInfo renderPassInfo{
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.flags = 0, .flags = 0,
.attachmentCount = 1, .attachmentCount = attachments.size(),
.pAttachments = &colorAttachment, .pAttachments = attachments.data(),
.subpassCount = 1, .subpassCount = 1,
.pSubpasses = &subpass, .pSubpasses = &subpass,
.dependencyCount = 1, .dependencyCount = 1,
@ -194,9 +266,9 @@ namespace engine {
/* create image view and framebuffer for each image */ /* create image view and framebuffer for each image */
sc->images.resize(swapchainImageCount); sc->images.resize(swapchainImageCount);
for (uint32_t i = 0; i < swapchainImageCount; i++) { for (uint32_t i = 0; i < swapchainImageCount; i++) {
auto& [image, view, framebuffer] = sc->images.at(i); auto& [image, imageView, framebuffer] = sc->images.at(i);
if (view != VK_NULL_HANDLE) vkDestroyImageView(sc->device, view, nullptr); if (imageView != VK_NULL_HANDLE) vkDestroyImageView(sc->device, imageView, nullptr);
if (framebuffer != VK_NULL_HANDLE) vkDestroyFramebuffer(sc->device, framebuffer, nullptr); if (framebuffer != VK_NULL_HANDLE) vkDestroyFramebuffer(sc->device, framebuffer, nullptr);
image = swapchainImages[i]; image = swapchainImages[i];
@ -218,16 +290,20 @@ namespace engine {
viewInfo.subresourceRange.levelCount = 1; viewInfo.subresourceRange.levelCount = 1;
viewInfo.subresourceRange.baseArrayLayer = 0; viewInfo.subresourceRange.baseArrayLayer = 0;
viewInfo.subresourceRange.layerCount = 1; viewInfo.subresourceRange.layerCount = 1;
VkResult res = vkCreateImageView(sc->device, &viewInfo, nullptr, &view); VkResult res = vkCreateImageView(sc->device, &viewInfo, nullptr, &imageView);
if (res != VK_SUCCESS) throw std::runtime_error("Failed to create image view from swapchain image!"); if (res != VK_SUCCESS) throw std::runtime_error("Failed to create image view from swapchain image!");
std::array<VkImageView, 2> attachments {
imageView, sc->depthStencil.view
};
VkFramebufferCreateInfo fbInfo{}; VkFramebufferCreateInfo fbInfo{};
fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
fbInfo.pNext = nullptr; fbInfo.pNext = nullptr;
fbInfo.flags = 0; fbInfo.flags = 0;
fbInfo.renderPass = sc->renderpass; fbInfo.renderPass = sc->renderpass;
fbInfo.attachmentCount = 1; fbInfo.attachmentCount = attachments.size();
fbInfo.pAttachments = &view; fbInfo.pAttachments = attachments.data();
fbInfo.width = sc->extent.width; fbInfo.width = sc->extent.width;
fbInfo.height = sc->extent.height; fbInfo.height = sc->extent.height;
fbInfo.layers = 1; fbInfo.layers = 1;
@ -246,6 +322,8 @@ namespace engine {
vkDestroyImageView(sc.device, view, nullptr); vkDestroyImageView(sc.device, view, nullptr);
} }
vkDestroyRenderPass(sc.device, sc.renderpass, nullptr); vkDestroyRenderPass(sc.device, sc.renderpass, nullptr);
vkDestroyImageView(sc.device, sc.depthStencil.view, nullptr);
vmaDestroyImage(sc.allocator, sc.depthStencil.image, sc.depthStencil.allocation);
vkDestroySwapchainKHR(sc.device, sc.swapchain, nullptr); vkDestroySwapchainKHR(sc.device, sc.swapchain, nullptr);
} }

View File

@ -1,22 +1,32 @@
#pragma once #pragma once
#include <tuple> #include <tuple>
#include <vector>
#include <SDL2/SDL_vulkan.h> #include <SDL2/SDL_vulkan.h>
#include <volk.h> #include <volk.h>
#include <vk_mem_alloc.h>
namespace engine { namespace engine {
struct Swapchain { struct Swapchain {
VkSwapchainKHR swapchain = VK_NULL_HANDLE; VkSwapchainKHR swapchain = VK_NULL_HANDLE;
VkDevice device = VK_NULL_HANDLE; // the associated device VkDevice device = VK_NULL_HANDLE; // the associated device
VmaAllocator allocator = VK_NULL_HANDLE; // the associated allocator
VkSurfaceFormatKHR surfaceFormat{}; VkSurfaceFormatKHR surfaceFormat{};
VkSurfaceCapabilitiesKHR surfaceCapabilities{}; VkSurfaceCapabilitiesKHR surfaceCapabilities{};
VkPresentModeKHR presentMode{}; VkPresentModeKHR presentMode{};
VkExtent2D extent{}; VkExtent2D extent{};
VkRenderPass renderpass = VK_NULL_HANDLE; VkRenderPass renderpass = VK_NULL_HANDLE;
std::vector<std::tuple<VkImage, VkImageView, VkFramebuffer>> images{}; std::vector<std::tuple<VkImage, VkImageView, VkFramebuffer>> images{};
struct DepthStencil {
VkImage image = VK_NULL_HANDLE;
VmaAllocation allocation = VK_NULL_HANDLE;
VkImageView view = VK_NULL_HANDLE;
VkFormat format{};
} depthStencil{};
}; };
struct SwapchainInfo { struct SwapchainInfo {
@ -24,6 +34,7 @@ namespace engine {
VkPhysicalDevice physicalDevice; VkPhysicalDevice physicalDevice;
VkSurfaceKHR surface; VkSurfaceKHR surface;
SDL_Window* window; SDL_Window* window;
VmaAllocator allocator;
bool vsync; bool vsync;
bool waitForPresent; bool waitForPresent;
}; };

View File

@ -107,7 +107,7 @@ void playGame(bool enableFrameLimiter)
/* cube */ /* cube */
{ {
uint32_t cube = myScene->createEntity("cube"); uint32_t cube = myScene->createEntity("cube");
myScene->getComponent<engine::TransformComponent>(cube)->position = glm::vec3{ -0.5f, -0.5f, -0.5f }; myScene->getComponent<engine::TransformComponent>(cube)->position = glm::vec3{ -0.5f, -0.5f + 5.0f, -0.5f };
auto cubeRenderable = myScene->addComponent<engine::RenderableComponent>(cube); auto cubeRenderable = myScene->addComponent<engine::RenderableComponent>(cube);
cubeRenderable->material = std::make_shared<engine::resources::Material>(app.getResource<engine::resources::Shader>("builtin.standard")); cubeRenderable->material = std::make_shared<engine::resources::Material>(app.getResource<engine::resources::Shader>("builtin.standard"));
cubeRenderable->mesh = genCuboidMesh(app.gfx(), 1.0f, 1.0f, 1.0f, 1); cubeRenderable->mesh = genCuboidMesh(app.gfx(), 1.0f, 1.0f, 1.0f, 1);