화면크기변경 로직 추가

This commit is contained in:
2025-05-17 20:13:34 +09:00
parent bba916f29e
commit 45ee4f0056
12 changed files with 308 additions and 127 deletions

View File

@@ -38,6 +38,14 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(GSL)
FetchContent_Declare(
ASSIMP
GIT_REPOSITORY "https://github.com/assimp/assimp.git"
GIT_TAG "v5.4.3"
GIT_SHALLOW ON
)
FetchContent_MakeAvailable(ASSIMP)
file(GLOB_RECURSE VulkanEngineSources CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/glfw/*.cpp"
@@ -50,6 +58,7 @@ target_link_libraries(VulkanEngine PRIVATE glm)
target_link_libraries(VulkanEngine PRIVATE glfw)
target_link_libraries(VulkanEngine PRIVATE Microsoft.GSL::GSL)
target_link_libraries(VulkanEngine PRIVATE spdlog)
target_link_libraries(VulkanEngine PRIVATE assimp::assimp)
target_include_directories(VulkanEngine PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
target_compile_features(VulkanEngine PRIVATE cxx_std_20)
@@ -64,4 +73,5 @@ file(GLOB_RECURSE ShaderSources CONFIGURE_DEPENDS
add_shaders(VulkanEngineShaders ${ShaderSources})
add_dependencies(VulkanEngine VulkanEngineShaders)
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/paving-stones.jpg" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets")
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/paving-stones.jpg" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets")
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/assets/player.fbx" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/assets")

BIN
assets/player.fbx Normal file

Binary file not shown.

View File

@@ -12,3 +12,5 @@
#include "spdlog/spdlog.h"
#include "utilities.h"
#define MAX_BUFFERED_FRAMES (2)

View File

@@ -8,6 +8,19 @@
#include "vertex.h"
namespace veng {
struct Frame {
VkSemaphore image_available_signal = VK_NULL_HANDLE;
VkSemaphore render_finished_signal = VK_NULL_HANDLE;
VkFence still_rendering_fence = VK_NULL_HANDLE;
VkCommandBuffer command_buffer = VK_NULL_HANDLE;
VkDescriptorSet uniform_set = VK_NULL_HANDLE;
BufferHandle uniform_buffer;
void* uniform_buffer_location;
};
class Graphics final {
public:
Graphics(gsl::not_null<Window*> window);
@@ -66,6 +79,7 @@ class Graphics final {
void CreateDescriptorPools();
void CreateDescriptorSets();
void CreateTextureSampler();
void CreateDepthResources();
void RecreateSwapChain();
void CleanupSwapChain();
@@ -111,11 +125,14 @@ class Graphics final {
void EndTransientCommandBuffer(VkCommandBuffer command_buffer);
void CreateUniformBuffers();
TextureHandle CreateImage(glm::ivec2 size, VkBufferUsageFlags usage,
TextureHandle CreateImage(glm::ivec2 size, VkFormat image_format,
VkBufferUsageFlags usage,
VkMemoryPropertyFlags properties);
void TransitionImageLayout(VkImage image, VkImageLayout old_layout, VkImageLayout new_layout);
void TransitionImageLayout(VkImage image, VkImageLayout old_layout,
VkImageLayout new_layout);
void CopyBufferToImage(VkBuffer buffer, VkImage image, glm::ivec2 image_size);
VkImageView CreateImageView(VkImage image, VkFormat format);
VkImageView CreateImageView(VkImage image, VkFormat format,
VkImageAspectFlags aspect_flag);
VkViewport GetViewport();
VkRect2D GetScissor();
@@ -147,23 +164,20 @@ class Graphics final {
VkDescriptorSetLayout descriptor_set_layout_ = VK_NULL_HANDLE;
VkCommandPool command_pool_ = VK_NULL_HANDLE;
VkCommandBuffer command_buffer_ = VK_NULL_HANDLE;
VkSemaphore image_available_signal_ = VK_NULL_HANDLE;
VkSemaphore render_finished_signal_ = VK_NULL_HANDLE;
VkFence still_rendering_fence_ = VK_NULL_HANDLE;
std::uint32_t current_image_index_ = 0;
VkDescriptorSetLayout uniform_set_layout_ = VK_NULL_HANDLE;
VkDescriptorPool uniform_pool_ = VK_NULL_HANDLE;
VkDescriptorSet uniform_set_ = VK_NULL_HANDLE;
BufferHandle uniform_buffer_;
void* uniform_buffer_location_;
VkDescriptorSetLayout texture_set_layout_ = VK_NULL_HANDLE;
VkDescriptorPool texture_pool_ = VK_NULL_HANDLE;
VkSampler texture_sampler_ = VK_NULL_HANDLE;
TextureHandle depth_texture_;
std::array<Frame, MAX_BUFFERED_FRAMES> frames_;
std::int32_t current_frame_ = 0;
gsl::not_null<Window*> window_;
bool validation_enabled_ = false;

View File

@@ -1,15 +1,16 @@
#include <GLFW/glfw3.h>
#include <glm/gtc/matrix_transform.hpp>
#include <iostream>
#include "assimp/Importer.hpp"
#include "assimp/postprocess.h"
#include "glfw/glfw_initialization.h"
#include "glfw/glfw_monitor.h"
#include "glfw/glfw_window.h"
#include "precomp.h"
#include "vulkan/graphics.h"
#include <iostream>
std::int32_t main(std::int32_t argc, gsl::zstring* argv) {
const veng::GlfwInitialization _glfw;
@@ -18,6 +19,17 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) {
veng::Graphics graphics(&window);
Assimp::Importer assetImporter;
const struct aiScene* scene = assetImporter.ReadFile(
"assets/player.fbx", aiProcess_CalcTangentSpace | aiProcess_Triangulate |
aiProcess_JoinIdenticalVertices | aiProcess_SortByPType);
if (nullptr == scene) {
spdlog::error(assetImporter.GetErrorString());
return false;
}
std::array<veng::Vertex, 4> vertices = {
veng::Vertex{{-.5f, -.5f, 0.f}, {0.f, 1.f}},
veng::Vertex{{.5f, -.5f, 0.f}, {1.f, 1.f}},
@@ -30,28 +42,45 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) {
glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), glm::radians(45.f),
glm::vec3(0.f, 1.f, 0.f));
glm::mat4 rotation2 =
glm::rotate(glm::mat4(1.0f), glm::radians(0.f), glm::vec3(0.f, 0.f, 1.f));
glm::mat4 view = glm::translate(glm::mat4(1.f), glm::vec3(0.f, 0.f, -2.f));
glm::mat4 projection =
glm::perspective(glm::radians(60.f), 800.f / 600.f, 0.1f, 100.f);
glm::perspective(glm::radians(150.f), 800.f / 600.f, 0.1f, 100.f);
graphics.SetViewProjection(view, projection);
veng::TextureHandle texture = graphics.CreateTexture("assets/paving-stones.jpg");
veng::TextureHandle texture =
graphics.CreateTexture("assets/paving-stones.jpg");
double last_time = glfwGetTime();
glm::ivec2 window_size;
while (!window.ShouldClose()) {
glfwPollEvents();
glm::ivec2 current_window_size = window.GetFramebufferSize();
if (current_window_size != window_size && current_window_size.x != 0 && current_window_size.y != 0) {
window_size = current_window_size;
projection = glm::perspective(
glm::radians(90.f),
(float)current_window_size.x / (float)current_window_size.y, 0.1f,
100.f);
graphics.SetViewProjection(view, projection);
}
if (graphics.BeginFrame()) {
double current_time = glfwGetTime();
float delta_time = static_cast<float>(current_time - last_time);
last_time = current_time;
std::cout << 1.f / delta_time << std::endl;
graphics.SetTexture(texture);
rotation2 = glm::rotate(rotation2, delta_time * glm::radians(-360.f),
glm::vec3(0.f, 0.f, 1.f));
graphics.SetModelMatrix(rotation2);
graphics.RenderIndexedBuffer(buffer, index_buffer, indices.size());
rotation = glm::rotate(rotation, delta_time * glm::radians(3600.f),
rotation = glm::rotate(rotation, delta_time * glm::radians(360.f),
glm::vec3(0.f, 0.f, 1.f));
graphics.SetModelMatrix(rotation);
graphics.RenderIndexedBuffer(buffer, index_buffer, indices.size());

View File

@@ -134,34 +134,40 @@ void Graphics::DestroyBuffer(BufferHandle handle) {
}
void Graphics::SetModelMatrix(glm::mat4 model) {
vkCmdPushConstants(command_buffer_, pipeline_layout_,
// for (Frame& frame : frames_)
vkCmdPushConstants(frames_[current_frame_].command_buffer, pipeline_layout_,
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &model);
}
void Graphics::SetViewProjection(glm::mat4 view, glm::mat4 projection) {
UniformTransformations transformations{view, projection};
std::memcpy(uniform_buffer_location_, &transformations,
sizeof(UniformTransformations));
for (Frame& frame : frames_)
std::memcpy(frame.uniform_buffer_location,
&transformations, sizeof(UniformTransformations));
}
void Graphics::RenderBuffer(BufferHandle handle, std::uint32_t vertex_count) {
VkDeviceSize offset = 0;
vkCmdBindDescriptorSets(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline_layout_, 0, 1, &uniform_set_, 0, nullptr);
vkCmdBindVertexBuffers(command_buffer_, 0, 1, &handle.buffer, &offset);
vkCmdDraw(command_buffer_, vertex_count, 1, 0, 0);
vkCmdBindDescriptorSets(frames_[current_frame_].command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, 0,
1, &frames_[current_frame_].uniform_set, 0, nullptr);
vkCmdBindVertexBuffers(frames_[current_frame_].command_buffer, 0, 1,
&handle.buffer, &offset);
vkCmdDraw(frames_[current_frame_].command_buffer, vertex_count, 1, 0, 0);
}
void Graphics::RenderIndexedBuffer(BufferHandle vertex_buffer,
BufferHandle index_buffer,
std::uint32_t count) {
VkDeviceSize offset = 0;
vkCmdBindDescriptorSets(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline_layout_, 0, 1, &uniform_set_, 0, nullptr);
vkCmdBindVertexBuffers(command_buffer_, 0, 1, &vertex_buffer.buffer, &offset);
vkCmdBindIndexBuffer(command_buffer_, index_buffer.buffer, 0,
VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(command_buffer_, count, 1, 0, 0, 0);
vkCmdBindDescriptorSets(frames_[current_frame_].command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, 0,
1, &frames_[current_frame_].uniform_set, 0, nullptr);
vkCmdBindVertexBuffers(frames_[current_frame_].command_buffer, 0, 1,
&vertex_buffer.buffer, &offset);
vkCmdBindIndexBuffer(frames_[current_frame_].command_buffer,
index_buffer.buffer, 0, VK_INDEX_TYPE_UINT32);
vkCmdDrawIndexed(frames_[current_frame_].command_buffer, count, 1, 0, 0, 0);
SetModelMatrix(glm::mat4(1.f));
}
@@ -198,13 +204,15 @@ void Graphics::EndTransientCommandBuffer(VkCommandBuffer command_buffer) {
void Graphics::CreateUniformBuffers() {
VkDeviceSize buffer_size = sizeof(UniformTransformations);
uniform_buffer_ =
CreateBuffer(buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
for (Frame& frame : frames_) {
frame.uniform_buffer =
CreateBuffer(buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
vkMapMemory(logical_device_, uniform_buffer_.memory, 0, buffer_size, 0,
&uniform_buffer_location_);
vkMapMemory(logical_device_, frame.uniform_buffer.memory, 0, buffer_size, 0,
&frame.uniform_buffer_location);
}
}
void Graphics::CreateDescriptorSetLayouts() {
@@ -249,13 +257,13 @@ void Graphics::CreateDescriptorSetLayouts() {
void Graphics::CreateDescriptorPools() {
VkDescriptorPoolSize uniform_pool_size = {};
uniform_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
uniform_pool_size.descriptorCount = 1;
uniform_pool_size.descriptorCount = MAX_BUFFERED_FRAMES;
VkDescriptorPoolCreateInfo uniform_create_info = {};
uniform_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
uniform_create_info.poolSizeCount = 1;
uniform_create_info.pPoolSizes = &uniform_pool_size;
uniform_create_info.maxSets = 1;
uniform_create_info.maxSets = MAX_BUFFERED_FRAMES;
if (vkCreateDescriptorPool(logical_device_, &uniform_create_info, nullptr,
&uniform_pool_) != VK_SUCCESS) {
@@ -284,31 +292,33 @@ void Graphics::CreateDescriptorPools() {
}
void Graphics::CreateDescriptorSets() {
VkDescriptorSetAllocateInfo set_info = {};
set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
set_info.descriptorPool = uniform_pool_;
set_info.descriptorSetCount = 1;
set_info.pSetLayouts = &uniform_set_layout_;
for (Frame& frame : frames_) {
VkDescriptorSetAllocateInfo set_info = {};
set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
set_info.descriptorPool = uniform_pool_;
set_info.descriptorSetCount = 1;
set_info.pSetLayouts = &uniform_set_layout_;
VkResult result =
vkAllocateDescriptorSets(logical_device_, &set_info, &uniform_set_);
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
VkResult result = vkAllocateDescriptorSets(logical_device_, &set_info,
&frame.uniform_set);
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
VkDescriptorBufferInfo buffer_info = {};
buffer_info.buffer = uniform_buffer_.buffer;
buffer_info.offset = 0;
buffer_info.range = sizeof(UniformTransformations);
VkDescriptorBufferInfo buffer_info = {};
buffer_info.buffer = frame.uniform_buffer.buffer;
buffer_info.offset = 0;
buffer_info.range = sizeof(UniformTransformations);
VkWriteDescriptorSet descriptor_write = {};
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptor_write.dstSet = uniform_set_;
descriptor_write.dstBinding = 0;
descriptor_write.dstArrayElement = 0;
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptor_write.descriptorCount = 1;
descriptor_write.pBufferInfo = &buffer_info;
VkWriteDescriptorSet descriptor_write = {};
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptor_write.dstSet = frame.uniform_set;
descriptor_write.dstBinding = 0;
descriptor_write.dstArrayElement = 0;
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptor_write.descriptorCount = 1;
descriptor_write.pBufferInfo = &buffer_info;
vkUpdateDescriptorSets(logical_device_, 1, &descriptor_write, 0, nullptr);
vkUpdateDescriptorSets(logical_device_, 1, &descriptor_write, 0, nullptr);
}
}
} // namespace veng

View File

@@ -16,6 +16,7 @@ Graphics::~Graphics() {
if (logical_device_ != VK_NULL_HANDLE) {
vkDeviceWaitIdle(logical_device_);
CleanupSwapChain();
DestroyTexture(depth_texture_);
if (texture_pool_ != VK_NULL_HANDLE)
vkDestroyDescriptorPool(logical_device_, texture_pool_, nullptr);
@@ -30,21 +31,25 @@ Graphics::~Graphics() {
if (uniform_pool_ != VK_NULL_HANDLE)
vkDestroyDescriptorPool(logical_device_, uniform_pool_, nullptr);
DestroyBuffer(uniform_buffer_);
for (Frame& frame : frames_) {
DestroyBuffer(frame.uniform_buffer);
if (frame.image_available_signal != VK_NULL_HANDLE)
vkDestroySemaphore(logical_device_, frame.image_available_signal,
nullptr);
if (frame.render_finished_signal != VK_NULL_HANDLE)
vkDestroySemaphore(logical_device_, frame.render_finished_signal,
nullptr);
if (frame.still_rendering_fence != VK_NULL_HANDLE)
vkDestroyFence(logical_device_, frame.still_rendering_fence, nullptr);
}
if (uniform_set_layout_ != VK_NULL_HANDLE)
vkDestroyDescriptorSetLayout(logical_device_, uniform_set_layout_,
nullptr);
if (image_available_signal_ != VK_NULL_HANDLE)
vkDestroySemaphore(logical_device_, image_available_signal_, nullptr);
if (render_finished_signal_ != VK_NULL_HANDLE)
vkDestroySemaphore(logical_device_, render_finished_signal_, nullptr);
if (still_rendering_fence_ != VK_NULL_HANDLE)
vkDestroyFence(logical_device_, still_rendering_fence_, nullptr);
if (command_pool_ != VK_NULL_HANDLE)
vkDestroyCommandPool(logical_device_, command_pool_, nullptr);
@@ -81,6 +86,7 @@ void Graphics::InitializeVulkan() {
CreateRenderPass();
CreateDescriptorSetLayouts();
CreateGraphicsPipeline();
CreateDepthResources();
CreateFramebuffers();
CreateCommandPool();
CreateCommandBuffer();
@@ -89,6 +95,8 @@ void Graphics::InitializeVulkan() {
CreateDescriptorPools();
CreateDescriptorSets();
CreateTextureSampler();
TransitionImageLayout(depth_texture_.image, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
}
} // namespace veng

View File

@@ -140,6 +140,8 @@ void Graphics::CreateLogicalDeviceAndQueues() {
}
VkPhysicalDeviceFeatures required_features = {};
required_features.depthBounds = true;
required_features.depthClamp = true;
VkDeviceCreateInfo device_info = {};
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;

View File

@@ -9,11 +9,14 @@ void Graphics::CreateFramebuffers() {
swap_chain_framebuffers_.resize(swap_chain_image_views_.size());
for (std::uint32_t i = 0; i < swap_chain_image_views_.size(); i++) {
std::array<VkImageView, 2> attachments = {swap_chain_image_views_[i],
depth_texture_.image_view};
VkFramebufferCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
info.renderPass = render_pass_;
info.attachmentCount = 1;
info.pAttachments = &swap_chain_image_views_[i];
info.attachmentCount = attachments.size();
info.pAttachments = attachments.data();
info.width = extent_.width;
info.height = extent_.height;
info.layers = 1;
@@ -43,21 +46,28 @@ void Graphics::CreateCommandBuffer() {
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
info.commandBufferCount = 1;
VkResult result =
vkAllocateCommandBuffers(logical_device_, &info, &command_buffer_);
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
for (Frame& frame : frames_) {
VkResult result =
vkAllocateCommandBuffers(logical_device_, &info, &frame.command_buffer);
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
}
}
void Graphics::BeginCommands() {
vkResetCommandBuffer(command_buffer_, 0);
vkResetCommandBuffer(frames_[current_frame_].command_buffer, 0);
VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
VkResult result = vkBeginCommandBuffer(command_buffer_, &begin_info);
VkResult result = vkBeginCommandBuffer(
frames_[current_frame_].command_buffer, &begin_info);
if (result != VK_SUCCESS)
throw std::runtime_error("Failed to begin command buffer!");
std::array<VkClearValue, 2> clear_values;
clear_values[0].color = {{0.f, 0.f, 0.f, 1.f}};
clear_values[1].depthStencil = {1.f, 0};
VkRenderPassBeginInfo render_pass_begin_info = {};
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
render_pass_begin_info.renderPass = render_pass_;
@@ -65,54 +75,60 @@ void Graphics::BeginCommands() {
swap_chain_framebuffers_[current_image_index_];
render_pass_begin_info.renderArea.offset = {0, 0};
render_pass_begin_info.renderArea.extent = extent_;
render_pass_begin_info.clearValueCount = clear_values.size();
render_pass_begin_info.pClearValues = clear_values.data();
VkClearValue clear_color = {{{0.f, 0.f, 0.f, 1.f}}};
render_pass_begin_info.clearValueCount = 1;
render_pass_begin_info.pClearValues = &clear_color;
vkCmdBeginRenderPass(command_buffer_, &render_pass_begin_info,
vkCmdBeginRenderPass(frames_[current_frame_].command_buffer,
&render_pass_begin_info,
VK_SUBPASS_CONTENTS_INLINE);
vkCmdBindPipeline(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkCmdBindPipeline(frames_[current_frame_].command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline_);
VkViewport viewport = GetViewport();
VkRect2D scissor = GetScissor();
vkCmdSetViewport(command_buffer_, 0, 1, &viewport);
vkCmdSetScissor(command_buffer_, 0, 1, &scissor);
vkCmdSetViewport(frames_[current_frame_].command_buffer, 0, 1, &viewport);
vkCmdSetScissor(frames_[current_frame_].command_buffer, 0, 1, &scissor);
}
void Graphics::EndCommands() {
vkCmdEndRenderPass(command_buffer_);
VkResult result = vkEndCommandBuffer(command_buffer_);
vkCmdEndRenderPass(frames_[current_frame_].command_buffer);
VkResult result = vkEndCommandBuffer(frames_[current_frame_].command_buffer);
if (result != VK_SUCCESS)
throw std::runtime_error("Failed to record command buffer!");
}
void Graphics::CreateSignals() {
VkSemaphoreCreateInfo semafore_info = {};
semafore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (Frame& frame : frames_) {
VkSemaphoreCreateInfo semafore_info = {};
semafore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
&image_available_signal_) != VK_SUCCESS)
std::exit(EXIT_FAILURE);
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
&render_finished_signal_) != VK_SUCCESS)
std::exit(EXIT_FAILURE);
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
&frame.image_available_signal) !=
VK_SUCCESS)
std::exit(EXIT_FAILURE);
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
&frame.render_finished_signal) !=
VK_SUCCESS)
std::exit(EXIT_FAILURE);
VkFenceCreateInfo fence_info = {};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VkFenceCreateInfo fence_info = {};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
if (vkCreateFence(logical_device_, &fence_info, nullptr,
&still_rendering_fence_) != VK_SUCCESS)
std::exit(EXIT_FAILURE);
if (vkCreateFence(logical_device_, &fence_info, nullptr,
&frame.still_rendering_fence) !=
VK_SUCCESS)
std::exit(EXIT_FAILURE);
}
}
bool Graphics::BeginFrame() {
vkWaitForFences(logical_device_, 1, &still_rendering_fence_, VK_TRUE,
vkWaitForFences(logical_device_, 1,
&frames_[current_frame_].still_rendering_fence, VK_TRUE,
UINT64_MAX);
VkResult image_acquire_result = vkAcquireNextImageKHR(
logical_device_, swap_chain_, UINT64_MAX, image_available_signal_,
VkResult image_acquire_result = vkAcquireNextImageKHR(logical_device_, swap_chain_, UINT64_MAX,
frames_[current_frame_].image_available_signal,
VK_NULL_HANDLE, &current_image_index_);
if (image_acquire_result == VK_ERROR_OUT_OF_DATE_KHR) {
@@ -124,7 +140,8 @@ bool Graphics::BeginFrame() {
image_acquire_result != VK_SUBOPTIMAL_KHR)
throw std::runtime_error("Couldn't acquire render image!");
vkResetFences(logical_device_, 1, &still_rendering_fence_);
vkResetFences(logical_device_, 1,
&frames_[current_frame_].still_rendering_fence);
BeginCommands();
SetModelMatrix(glm::mat4(1.f));
@@ -139,22 +156,25 @@ void veng::Graphics::EndFrame() {
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &image_available_signal_;
submit_info.pWaitSemaphores = &frames_[current_frame_].image_available_signal;
submit_info.pWaitDstStageMask = &wait_stage;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer_;
submit_info.pCommandBuffers = &frames_[current_frame_].command_buffer;
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &render_finished_signal_;
submit_info.pSignalSemaphores =
&frames_[current_frame_].render_finished_signal;
VkResult submit_result =
vkQueueSubmit(graphics_queue_, 1, &submit_info, still_rendering_fence_);
vkQueueSubmit(graphics_queue_, 1, &submit_info,
frames_[current_frame_].still_rendering_fence);
if (submit_result != VK_SUCCESS)
throw std::runtime_error("failed to submit draw commands!");
VkPresentInfoKHR present_info = {};
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present_info.waitSemaphoreCount = 1;
present_info.pWaitSemaphores = &render_finished_signal_;
present_info.pWaitSemaphores =
&frames_[current_frame_].render_finished_signal;
present_info.swapchainCount = 1;
present_info.pSwapchains = &swap_chain_;
present_info.pImageIndices = &current_image_index_;
@@ -164,6 +184,8 @@ void veng::Graphics::EndFrame() {
RecreateSwapChain();
else if (result != VK_SUCCESS)
throw std::runtime_error("Failed to present swap chain image!");
current_frame_ = (current_frame_++) % MAX_BUFFERED_FRAMES;
}
} // namespace veng

View File

@@ -149,6 +149,17 @@ void Graphics::CreateGraphicsPipeline() {
color_blending_info.attachmentCount = 1;
color_blending_info.pAttachments = &color_blend_attachment;
VkPipelineDepthStencilStateCreateInfo depth_stencil_info = {};
depth_stencil_info.sType =
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
depth_stencil_info.depthTestEnable = VK_TRUE;
depth_stencil_info.depthWriteEnable = VK_TRUE;
depth_stencil_info.depthCompareOp = VK_COMPARE_OP_LESS;
depth_stencil_info.depthBoundsTestEnable = VK_TRUE;
depth_stencil_info.minDepthBounds = 0.f;
depth_stencil_info.maxDepthBounds = 1.f;
depth_stencil_info.stencilTestEnable = VK_FALSE;
VkPushConstantRange model_matrix_range = {};
model_matrix_range.offset = 0;
model_matrix_range.size = sizeof(glm::mat4);
@@ -177,7 +188,7 @@ void Graphics::CreateGraphicsPipeline() {
pipeline_info.pViewportState = &viewport_info;
pipeline_info.pRasterizationState = &rasterization_state_info;
pipeline_info.pMultisampleState = &multisampling_info;
pipeline_info.pDepthStencilState = nullptr;
pipeline_info.pDepthStencilState = &depth_stencil_info;
pipeline_info.pColorBlendState = &color_blending_info;
pipeline_info.pDynamicState = &dynamic_state_info;
pipeline_info.layout = pipeline_layout_;
@@ -204,17 +215,50 @@ void Graphics::CreateRenderPass() {
color_attachment_ref.attachment = 0;
color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
VkAttachmentDescription depth_attachment = {};
depth_attachment.format = VK_FORMAT_D32_SFLOAT;
depth_attachment.samples = VK_SAMPLE_COUNT_1_BIT;
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depth_attachment.finalLayout =
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkAttachmentReference depth_attachment_ref = {};
depth_attachment_ref.attachment = 1;
depth_attachment_ref.layout =
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
VkSubpassDescription main_subpass = {};
main_subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
main_subpass.colorAttachmentCount = 1;
main_subpass.pColorAttachments = &color_attachment_ref;
main_subpass.pDepthStencilAttachment = &depth_attachment_ref;
VkSubpassDependency dependency = {};
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.srcAccessMask = 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<VkAttachmentDescription, 2> attachments = {color_attachment,
depth_attachment};
VkRenderPassCreateInfo render_pass_info = {};
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
render_pass_info.attachmentCount = 1;
render_pass_info.pAttachments = &color_attachment;
render_pass_info.attachmentCount = attachments.size();
render_pass_info.pAttachments = attachments.data();
render_pass_info.subpassCount = 1;
render_pass_info.pSubpasses = &main_subpass;
render_pass_info.dependencyCount = 1;
render_pass_info.pDependencies = &dependency;
VkResult result = vkCreateRenderPass(logical_device_, &render_pass_info,
nullptr, &render_pass_);
@@ -234,6 +278,7 @@ void veng::Graphics::RecreateSwapChain() {
CreateSwapChain();
CreateImageViews();
CreateDepthResources();
CreateFramebuffers();
}
@@ -248,6 +293,14 @@ void veng::Graphics::CleanupSwapChain() {
if (swap_chain_ != VK_NULL_HANDLE)
vkDestroySwapchainKHR(logical_device_, swap_chain_, nullptr);
vkDeviceWaitIdle(logical_device_);
vkDestroyImageView(logical_device_, depth_texture_.image_view, nullptr);
depth_texture_.image_view = VK_NULL_HANDLE;
vkDestroyImage(logical_device_, depth_texture_.image, nullptr);
depth_texture_.image = VK_NULL_HANDLE;
vkFreeMemory(logical_device_, depth_texture_.memory, nullptr);
depth_texture_.memory = VK_NULL_HANDLE;
}
} // namespace veng

View File

@@ -140,7 +140,7 @@ void Graphics::CreateSwapChain() {
swap_chain_images_.data());
}
VkImageView Graphics::CreateImageView(VkImage image, VkFormat format) {
VkImageView Graphics::CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect_flag) {
VkImageViewCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
info.image = image;
@@ -150,7 +150,7 @@ VkImageView Graphics::CreateImageView(VkImage image, VkFormat format) {
info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
info.subresourceRange.aspectMask = aspect_flag;
info.subresourceRange.baseMipLevel = 0;
info.subresourceRange.levelCount = 1;
info.subresourceRange.baseArrayLayer = 0;
@@ -167,7 +167,7 @@ void Graphics::CreateImageViews() {
auto image_view_it = swap_chain_image_views_.begin();
for (VkImage image : swap_chain_images_) {
*image_view_it = CreateImageView(image, surface_format_.format);
*image_view_it = CreateImageView(image, surface_format_.format, VK_IMAGE_ASPECT_COLOR_BIT);
std::advance(image_view_it, 1);
}

View File

@@ -52,7 +52,7 @@ TextureHandle Graphics::CreateTexture(gsl::czstring path) {
stbi_image_free(pixel_data);
TextureHandle handle =
CreateImage(image_extents,
CreateImage(image_extents, VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
@@ -62,7 +62,8 @@ TextureHandle Graphics::CreateTexture(gsl::czstring path) {
TransitionImageLayout(handle.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
handle.image_view = CreateImageView(handle.image, VK_FORMAT_R8G8B8A8_SRGB);
handle.image_view = CreateImageView(handle.image, VK_FORMAT_R8G8B8A8_SRGB,
VK_IMAGE_ASPECT_COLOR_BIT);
VkDescriptorSetAllocateInfo set_info = {};
set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
@@ -96,14 +97,23 @@ TextureHandle Graphics::CreateTexture(gsl::czstring path) {
void Graphics::DestroyTexture(TextureHandle handle) {
vkDeviceWaitIdle(logical_device_);
vkFreeDescriptorSets(logical_device_, texture_pool_, 1, &handle.set);
vkDestroyImageView(logical_device_, handle.image_view, nullptr);
vkDestroyImage(logical_device_, handle.image, nullptr);
vkFreeMemory(logical_device_, handle.memory, nullptr);
if (handle.set != VK_NULL_HANDLE)
vkFreeDescriptorSets(logical_device_, texture_pool_, 1, &handle.set);
if (handle.image_view != VK_NULL_HANDLE)
vkDestroyImageView(logical_device_, handle.image_view, nullptr);
if (handle.image != VK_NULL_HANDLE)
vkDestroyImage(logical_device_, handle.image, nullptr);
if (handle.memory != VK_NULL_HANDLE)
vkFreeMemory(logical_device_, handle.memory, nullptr);
}
void Graphics::SetTexture(TextureHandle handle) {
vkCmdBindDescriptorSets(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS,
vkCmdBindDescriptorSets(frames_[current_frame_].command_buffer,
VK_PIPELINE_BIND_POINT_GRAPHICS,
pipeline_layout_, 1, 1, &handle.set, 0, nullptr);
}
@@ -118,7 +128,6 @@ void Graphics::TransitionImageLayout(VkImage image, VkImageLayout old_layout,
barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
barrier.image = image;
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
barrier.subresourceRange.baseArrayLayer = 0;
barrier.subresourceRange.baseMipLevel = 0;
barrier.subresourceRange.levelCount = 1;
@@ -139,8 +148,20 @@ void Graphics::TransitionImageLayout(VkImage image, VkImageLayout old_layout,
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
destination_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
} else if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED &&
new_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
barrier.srcAccessMask = 0;
barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
source_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
destination_stage = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
}
if (new_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
else
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
vkCmdPipelineBarrier(local_command_buffer, source_stage, destination_stage, 0,
0, nullptr, 0, nullptr, 1, &barrier);
@@ -169,7 +190,8 @@ void Graphics::CopyBufferToImage(VkBuffer buffer, VkImage image,
EndTransientCommandBuffer(local_command_buffer);
}
TextureHandle Graphics::CreateImage(glm::ivec2 size, VkBufferUsageFlags usage,
TextureHandle Graphics::CreateImage(glm::ivec2 size, VkFormat image_format,
VkBufferUsageFlags usage,
VkMemoryPropertyFlags properties) {
TextureHandle handle = {};
@@ -183,7 +205,7 @@ TextureHandle Graphics::CreateImage(glm::ivec2 size, VkBufferUsageFlags usage,
image_info.extent.depth = 1;
image_info.mipLevels = 1;
image_info.arrayLayers = 1;
image_info.format = VK_FORMAT_R8G8B8A8_SRGB;
image_info.format = image_format;
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
@@ -216,4 +238,13 @@ TextureHandle Graphics::CreateImage(glm::ivec2 size, VkBufferUsageFlags usage,
return handle;
}
void Graphics::CreateDepthResources() {
VkFormat kDepthFormat = VK_FORMAT_D32_SFLOAT;
depth_texture_ = CreateImage({extent_.width, extent_.height}, kDepthFormat,
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
depth_texture_.image_view = CreateImageView(
depth_texture_.image, kDepthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
}
} // namespace veng