화면크기변경 로직 추가
This commit is contained in:
@@ -38,6 +38,14 @@ FetchContent_Declare(
|
|||||||
)
|
)
|
||||||
FetchContent_MakeAvailable(GSL)
|
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
|
file(GLOB_RECURSE VulkanEngineSources CONFIGURE_DEPENDS
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/glfw/*.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 glfw)
|
||||||
target_link_libraries(VulkanEngine PRIVATE Microsoft.GSL::GSL)
|
target_link_libraries(VulkanEngine PRIVATE Microsoft.GSL::GSL)
|
||||||
target_link_libraries(VulkanEngine PRIVATE spdlog)
|
target_link_libraries(VulkanEngine PRIVATE spdlog)
|
||||||
|
target_link_libraries(VulkanEngine PRIVATE assimp::assimp)
|
||||||
|
|
||||||
target_include_directories(VulkanEngine PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
target_include_directories(VulkanEngine PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||||
target_compile_features(VulkanEngine PRIVATE cxx_std_20)
|
target_compile_features(VulkanEngine PRIVATE cxx_std_20)
|
||||||
@@ -64,4 +73,5 @@ file(GLOB_RECURSE ShaderSources CONFIGURE_DEPENDS
|
|||||||
add_shaders(VulkanEngineShaders ${ShaderSources})
|
add_shaders(VulkanEngineShaders ${ShaderSources})
|
||||||
add_dependencies(VulkanEngine VulkanEngineShaders)
|
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
BIN
assets/player.fbx
Normal file
Binary file not shown.
@@ -12,3 +12,5 @@
|
|||||||
|
|
||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
|
|
||||||
|
#define MAX_BUFFERED_FRAMES (2)
|
||||||
|
|||||||
@@ -8,6 +8,19 @@
|
|||||||
#include "vertex.h"
|
#include "vertex.h"
|
||||||
|
|
||||||
namespace veng {
|
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 {
|
class Graphics final {
|
||||||
public:
|
public:
|
||||||
Graphics(gsl::not_null<Window*> window);
|
Graphics(gsl::not_null<Window*> window);
|
||||||
@@ -66,6 +79,7 @@ class Graphics final {
|
|||||||
void CreateDescriptorPools();
|
void CreateDescriptorPools();
|
||||||
void CreateDescriptorSets();
|
void CreateDescriptorSets();
|
||||||
void CreateTextureSampler();
|
void CreateTextureSampler();
|
||||||
|
void CreateDepthResources();
|
||||||
|
|
||||||
void RecreateSwapChain();
|
void RecreateSwapChain();
|
||||||
void CleanupSwapChain();
|
void CleanupSwapChain();
|
||||||
@@ -111,11 +125,14 @@ class Graphics final {
|
|||||||
void EndTransientCommandBuffer(VkCommandBuffer command_buffer);
|
void EndTransientCommandBuffer(VkCommandBuffer command_buffer);
|
||||||
void CreateUniformBuffers();
|
void CreateUniformBuffers();
|
||||||
|
|
||||||
TextureHandle CreateImage(glm::ivec2 size, VkBufferUsageFlags usage,
|
TextureHandle CreateImage(glm::ivec2 size, VkFormat image_format,
|
||||||
|
VkBufferUsageFlags usage,
|
||||||
VkMemoryPropertyFlags properties);
|
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);
|
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();
|
VkViewport GetViewport();
|
||||||
VkRect2D GetScissor();
|
VkRect2D GetScissor();
|
||||||
@@ -147,23 +164,20 @@ class Graphics final {
|
|||||||
VkDescriptorSetLayout descriptor_set_layout_ = VK_NULL_HANDLE;
|
VkDescriptorSetLayout descriptor_set_layout_ = VK_NULL_HANDLE;
|
||||||
|
|
||||||
VkCommandPool command_pool_ = 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;
|
std::uint32_t current_image_index_ = 0;
|
||||||
|
|
||||||
VkDescriptorSetLayout uniform_set_layout_ = VK_NULL_HANDLE;
|
VkDescriptorSetLayout uniform_set_layout_ = VK_NULL_HANDLE;
|
||||||
VkDescriptorPool uniform_pool_ = 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;
|
VkDescriptorSetLayout texture_set_layout_ = VK_NULL_HANDLE;
|
||||||
VkDescriptorPool texture_pool_ = VK_NULL_HANDLE;
|
VkDescriptorPool texture_pool_ = VK_NULL_HANDLE;
|
||||||
VkSampler texture_sampler_ = 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_;
|
gsl::not_null<Window*> window_;
|
||||||
bool validation_enabled_ = false;
|
bool validation_enabled_ = false;
|
||||||
|
|||||||
43
src/main.cpp
43
src/main.cpp
@@ -1,15 +1,16 @@
|
|||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "assimp/Importer.hpp"
|
||||||
|
#include "assimp/postprocess.h"
|
||||||
#include "glfw/glfw_initialization.h"
|
#include "glfw/glfw_initialization.h"
|
||||||
#include "glfw/glfw_monitor.h"
|
#include "glfw/glfw_monitor.h"
|
||||||
#include "glfw/glfw_window.h"
|
#include "glfw/glfw_window.h"
|
||||||
#include "precomp.h"
|
#include "precomp.h"
|
||||||
#include "vulkan/graphics.h"
|
#include "vulkan/graphics.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
std::int32_t main(std::int32_t argc, gsl::zstring* argv) {
|
std::int32_t main(std::int32_t argc, gsl::zstring* argv) {
|
||||||
const veng::GlfwInitialization _glfw;
|
const veng::GlfwInitialization _glfw;
|
||||||
|
|
||||||
@@ -18,6 +19,17 @@ std::int32_t main(std::int32_t argc, gsl::zstring* argv) {
|
|||||||
|
|
||||||
veng::Graphics graphics(&window);
|
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 = {
|
std::array<veng::Vertex, 4> vertices = {
|
||||||
veng::Vertex{{-.5f, -.5f, 0.f}, {0.f, 1.f}},
|
veng::Vertex{{-.5f, -.5f, 0.f}, {0.f, 1.f}},
|
||||||
veng::Vertex{{.5f, -.5f, 0.f}, {1.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::mat4 rotation = glm::rotate(glm::mat4(1.0f), glm::radians(45.f),
|
||||||
glm::vec3(0.f, 1.f, 0.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 view = glm::translate(glm::mat4(1.f), glm::vec3(0.f, 0.f, -2.f));
|
||||||
glm::mat4 projection =
|
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);
|
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();
|
double last_time = glfwGetTime();
|
||||||
|
|
||||||
|
glm::ivec2 window_size;
|
||||||
while (!window.ShouldClose()) {
|
while (!window.ShouldClose()) {
|
||||||
glfwPollEvents();
|
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()) {
|
if (graphics.BeginFrame()) {
|
||||||
double current_time = glfwGetTime();
|
double current_time = glfwGetTime();
|
||||||
float delta_time = static_cast<float>(current_time - last_time);
|
float delta_time = static_cast<float>(current_time - last_time);
|
||||||
last_time = current_time;
|
last_time = current_time;
|
||||||
|
|
||||||
std::cout << 1.f / delta_time << std::endl;
|
|
||||||
|
|
||||||
graphics.SetTexture(texture);
|
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());
|
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));
|
glm::vec3(0.f, 0.f, 1.f));
|
||||||
graphics.SetModelMatrix(rotation);
|
graphics.SetModelMatrix(rotation);
|
||||||
graphics.RenderIndexedBuffer(buffer, index_buffer, indices.size());
|
graphics.RenderIndexedBuffer(buffer, index_buffer, indices.size());
|
||||||
|
|||||||
@@ -134,34 +134,40 @@ void Graphics::DestroyBuffer(BufferHandle handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::SetModelMatrix(glm::mat4 model) {
|
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);
|
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::mat4), &model);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::SetViewProjection(glm::mat4 view, glm::mat4 projection) {
|
void Graphics::SetViewProjection(glm::mat4 view, glm::mat4 projection) {
|
||||||
UniformTransformations transformations{view, projection};
|
UniformTransformations transformations{view, projection};
|
||||||
std::memcpy(uniform_buffer_location_, &transformations,
|
for (Frame& frame : frames_)
|
||||||
sizeof(UniformTransformations));
|
std::memcpy(frame.uniform_buffer_location,
|
||||||
|
&transformations, sizeof(UniformTransformations));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::RenderBuffer(BufferHandle handle, std::uint32_t vertex_count) {
|
void Graphics::RenderBuffer(BufferHandle handle, std::uint32_t vertex_count) {
|
||||||
VkDeviceSize offset = 0;
|
VkDeviceSize offset = 0;
|
||||||
vkCmdBindDescriptorSets(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
vkCmdBindDescriptorSets(frames_[current_frame_].command_buffer,
|
||||||
pipeline_layout_, 0, 1, &uniform_set_, 0, nullptr);
|
VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, 0,
|
||||||
vkCmdBindVertexBuffers(command_buffer_, 0, 1, &handle.buffer, &offset);
|
1, &frames_[current_frame_].uniform_set, 0, nullptr);
|
||||||
vkCmdDraw(command_buffer_, vertex_count, 1, 0, 0);
|
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,
|
void Graphics::RenderIndexedBuffer(BufferHandle vertex_buffer,
|
||||||
BufferHandle index_buffer,
|
BufferHandle index_buffer,
|
||||||
std::uint32_t count) {
|
std::uint32_t count) {
|
||||||
VkDeviceSize offset = 0;
|
VkDeviceSize offset = 0;
|
||||||
vkCmdBindDescriptorSets(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
vkCmdBindDescriptorSets(frames_[current_frame_].command_buffer,
|
||||||
pipeline_layout_, 0, 1, &uniform_set_, 0, nullptr);
|
VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout_, 0,
|
||||||
vkCmdBindVertexBuffers(command_buffer_, 0, 1, &vertex_buffer.buffer, &offset);
|
1, &frames_[current_frame_].uniform_set, 0, nullptr);
|
||||||
vkCmdBindIndexBuffer(command_buffer_, index_buffer.buffer, 0,
|
vkCmdBindVertexBuffers(frames_[current_frame_].command_buffer, 0, 1,
|
||||||
VK_INDEX_TYPE_UINT32);
|
&vertex_buffer.buffer, &offset);
|
||||||
vkCmdDrawIndexed(command_buffer_, count, 1, 0, 0, 0);
|
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));
|
SetModelMatrix(glm::mat4(1.f));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,13 +204,15 @@ void Graphics::EndTransientCommandBuffer(VkCommandBuffer command_buffer) {
|
|||||||
|
|
||||||
void Graphics::CreateUniformBuffers() {
|
void Graphics::CreateUniformBuffers() {
|
||||||
VkDeviceSize buffer_size = sizeof(UniformTransformations);
|
VkDeviceSize buffer_size = sizeof(UniformTransformations);
|
||||||
uniform_buffer_ =
|
for (Frame& frame : frames_) {
|
||||||
CreateBuffer(buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
frame.uniform_buffer =
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
CreateBuffer(buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
|
||||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||||
|
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
|
|
||||||
vkMapMemory(logical_device_, uniform_buffer_.memory, 0, buffer_size, 0,
|
vkMapMemory(logical_device_, frame.uniform_buffer.memory, 0, buffer_size, 0,
|
||||||
&uniform_buffer_location_);
|
&frame.uniform_buffer_location);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::CreateDescriptorSetLayouts() {
|
void Graphics::CreateDescriptorSetLayouts() {
|
||||||
@@ -249,13 +257,13 @@ void Graphics::CreateDescriptorSetLayouts() {
|
|||||||
void Graphics::CreateDescriptorPools() {
|
void Graphics::CreateDescriptorPools() {
|
||||||
VkDescriptorPoolSize uniform_pool_size = {};
|
VkDescriptorPoolSize uniform_pool_size = {};
|
||||||
uniform_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
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 = {};
|
VkDescriptorPoolCreateInfo uniform_create_info = {};
|
||||||
uniform_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
uniform_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||||
uniform_create_info.poolSizeCount = 1;
|
uniform_create_info.poolSizeCount = 1;
|
||||||
uniform_create_info.pPoolSizes = &uniform_pool_size;
|
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,
|
if (vkCreateDescriptorPool(logical_device_, &uniform_create_info, nullptr,
|
||||||
&uniform_pool_) != VK_SUCCESS) {
|
&uniform_pool_) != VK_SUCCESS) {
|
||||||
@@ -284,31 +292,33 @@ void Graphics::CreateDescriptorPools() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::CreateDescriptorSets() {
|
void Graphics::CreateDescriptorSets() {
|
||||||
VkDescriptorSetAllocateInfo set_info = {};
|
for (Frame& frame : frames_) {
|
||||||
set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
VkDescriptorSetAllocateInfo set_info = {};
|
||||||
set_info.descriptorPool = uniform_pool_;
|
set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||||
set_info.descriptorSetCount = 1;
|
set_info.descriptorPool = uniform_pool_;
|
||||||
set_info.pSetLayouts = &uniform_set_layout_;
|
set_info.descriptorSetCount = 1;
|
||||||
|
set_info.pSetLayouts = &uniform_set_layout_;
|
||||||
|
|
||||||
VkResult result =
|
VkResult result = vkAllocateDescriptorSets(logical_device_, &set_info,
|
||||||
vkAllocateDescriptorSets(logical_device_, &set_info, &uniform_set_);
|
&frame.uniform_set);
|
||||||
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
|
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
|
||||||
|
|
||||||
VkDescriptorBufferInfo buffer_info = {};
|
VkDescriptorBufferInfo buffer_info = {};
|
||||||
buffer_info.buffer = uniform_buffer_.buffer;
|
buffer_info.buffer = frame.uniform_buffer.buffer;
|
||||||
buffer_info.offset = 0;
|
buffer_info.offset = 0;
|
||||||
buffer_info.range = sizeof(UniformTransformations);
|
buffer_info.range = sizeof(UniformTransformations);
|
||||||
|
|
||||||
VkWriteDescriptorSet descriptor_write = {};
|
VkWriteDescriptorSet descriptor_write = {};
|
||||||
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
descriptor_write.dstSet = uniform_set_;
|
descriptor_write.dstSet = frame.uniform_set;
|
||||||
descriptor_write.dstBinding = 0;
|
descriptor_write.dstBinding = 0;
|
||||||
descriptor_write.dstArrayElement = 0;
|
descriptor_write.dstArrayElement = 0;
|
||||||
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||||
descriptor_write.descriptorCount = 1;
|
descriptor_write.descriptorCount = 1;
|
||||||
descriptor_write.pBufferInfo = &buffer_info;
|
descriptor_write.pBufferInfo = &buffer_info;
|
||||||
|
|
||||||
vkUpdateDescriptorSets(logical_device_, 1, &descriptor_write, 0, nullptr);
|
vkUpdateDescriptorSets(logical_device_, 1, &descriptor_write, 0, nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace veng
|
} // namespace veng
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ Graphics::~Graphics() {
|
|||||||
if (logical_device_ != VK_NULL_HANDLE) {
|
if (logical_device_ != VK_NULL_HANDLE) {
|
||||||
vkDeviceWaitIdle(logical_device_);
|
vkDeviceWaitIdle(logical_device_);
|
||||||
CleanupSwapChain();
|
CleanupSwapChain();
|
||||||
|
DestroyTexture(depth_texture_);
|
||||||
|
|
||||||
if (texture_pool_ != VK_NULL_HANDLE)
|
if (texture_pool_ != VK_NULL_HANDLE)
|
||||||
vkDestroyDescriptorPool(logical_device_, texture_pool_, nullptr);
|
vkDestroyDescriptorPool(logical_device_, texture_pool_, nullptr);
|
||||||
@@ -30,21 +31,25 @@ Graphics::~Graphics() {
|
|||||||
if (uniform_pool_ != VK_NULL_HANDLE)
|
if (uniform_pool_ != VK_NULL_HANDLE)
|
||||||
vkDestroyDescriptorPool(logical_device_, uniform_pool_, nullptr);
|
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)
|
if (uniform_set_layout_ != VK_NULL_HANDLE)
|
||||||
vkDestroyDescriptorSetLayout(logical_device_, uniform_set_layout_,
|
vkDestroyDescriptorSetLayout(logical_device_, uniform_set_layout_,
|
||||||
nullptr);
|
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)
|
if (command_pool_ != VK_NULL_HANDLE)
|
||||||
vkDestroyCommandPool(logical_device_, command_pool_, nullptr);
|
vkDestroyCommandPool(logical_device_, command_pool_, nullptr);
|
||||||
|
|
||||||
@@ -81,6 +86,7 @@ void Graphics::InitializeVulkan() {
|
|||||||
CreateRenderPass();
|
CreateRenderPass();
|
||||||
CreateDescriptorSetLayouts();
|
CreateDescriptorSetLayouts();
|
||||||
CreateGraphicsPipeline();
|
CreateGraphicsPipeline();
|
||||||
|
CreateDepthResources();
|
||||||
CreateFramebuffers();
|
CreateFramebuffers();
|
||||||
CreateCommandPool();
|
CreateCommandPool();
|
||||||
CreateCommandBuffer();
|
CreateCommandBuffer();
|
||||||
@@ -89,6 +95,8 @@ void Graphics::InitializeVulkan() {
|
|||||||
CreateDescriptorPools();
|
CreateDescriptorPools();
|
||||||
CreateDescriptorSets();
|
CreateDescriptorSets();
|
||||||
CreateTextureSampler();
|
CreateTextureSampler();
|
||||||
|
TransitionImageLayout(depth_texture_.image, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace veng
|
} // namespace veng
|
||||||
|
|||||||
@@ -140,6 +140,8 @@ void Graphics::CreateLogicalDeviceAndQueues() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures required_features = {};
|
VkPhysicalDeviceFeatures required_features = {};
|
||||||
|
required_features.depthBounds = true;
|
||||||
|
required_features.depthClamp = true;
|
||||||
|
|
||||||
VkDeviceCreateInfo device_info = {};
|
VkDeviceCreateInfo device_info = {};
|
||||||
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||||
|
|||||||
@@ -9,11 +9,14 @@ void Graphics::CreateFramebuffers() {
|
|||||||
swap_chain_framebuffers_.resize(swap_chain_image_views_.size());
|
swap_chain_framebuffers_.resize(swap_chain_image_views_.size());
|
||||||
|
|
||||||
for (std::uint32_t i = 0; i < swap_chain_image_views_.size(); i++) {
|
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 = {};
|
VkFramebufferCreateInfo info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
info.renderPass = render_pass_;
|
info.renderPass = render_pass_;
|
||||||
info.attachmentCount = 1;
|
info.attachmentCount = attachments.size();
|
||||||
info.pAttachments = &swap_chain_image_views_[i];
|
info.pAttachments = attachments.data();
|
||||||
info.width = extent_.width;
|
info.width = extent_.width;
|
||||||
info.height = extent_.height;
|
info.height = extent_.height;
|
||||||
info.layers = 1;
|
info.layers = 1;
|
||||||
@@ -43,21 +46,28 @@ void Graphics::CreateCommandBuffer() {
|
|||||||
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
info.commandBufferCount = 1;
|
info.commandBufferCount = 1;
|
||||||
|
|
||||||
VkResult result =
|
for (Frame& frame : frames_) {
|
||||||
vkAllocateCommandBuffers(logical_device_, &info, &command_buffer_);
|
VkResult result =
|
||||||
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
|
vkAllocateCommandBuffers(logical_device_, &info, &frame.command_buffer);
|
||||||
|
if (result != VK_SUCCESS) std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::BeginCommands() {
|
void Graphics::BeginCommands() {
|
||||||
vkResetCommandBuffer(command_buffer_, 0);
|
vkResetCommandBuffer(frames_[current_frame_].command_buffer, 0);
|
||||||
|
|
||||||
VkCommandBufferBeginInfo begin_info = {};
|
VkCommandBufferBeginInfo begin_info = {};
|
||||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_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)
|
if (result != VK_SUCCESS)
|
||||||
throw std::runtime_error("Failed to begin command buffer!");
|
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 = {};
|
VkRenderPassBeginInfo render_pass_begin_info = {};
|
||||||
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
render_pass_begin_info.renderPass = render_pass_;
|
render_pass_begin_info.renderPass = render_pass_;
|
||||||
@@ -65,54 +75,60 @@ void Graphics::BeginCommands() {
|
|||||||
swap_chain_framebuffers_[current_image_index_];
|
swap_chain_framebuffers_[current_image_index_];
|
||||||
render_pass_begin_info.renderArea.offset = {0, 0};
|
render_pass_begin_info.renderArea.offset = {0, 0};
|
||||||
render_pass_begin_info.renderArea.extent = extent_;
|
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}}};
|
vkCmdBeginRenderPass(frames_[current_frame_].command_buffer,
|
||||||
render_pass_begin_info.clearValueCount = 1;
|
&render_pass_begin_info,
|
||||||
render_pass_begin_info.pClearValues = &clear_color;
|
|
||||||
|
|
||||||
vkCmdBeginRenderPass(command_buffer_, &render_pass_begin_info,
|
|
||||||
VK_SUBPASS_CONTENTS_INLINE);
|
VK_SUBPASS_CONTENTS_INLINE);
|
||||||
vkCmdBindPipeline(command_buffer_, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
vkCmdBindPipeline(frames_[current_frame_].command_buffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
pipeline_);
|
pipeline_);
|
||||||
VkViewport viewport = GetViewport();
|
VkViewport viewport = GetViewport();
|
||||||
VkRect2D scissor = GetScissor();
|
VkRect2D scissor = GetScissor();
|
||||||
|
|
||||||
vkCmdSetViewport(command_buffer_, 0, 1, &viewport);
|
vkCmdSetViewport(frames_[current_frame_].command_buffer, 0, 1, &viewport);
|
||||||
vkCmdSetScissor(command_buffer_, 0, 1, &scissor);
|
vkCmdSetScissor(frames_[current_frame_].command_buffer, 0, 1, &scissor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::EndCommands() {
|
void Graphics::EndCommands() {
|
||||||
vkCmdEndRenderPass(command_buffer_);
|
vkCmdEndRenderPass(frames_[current_frame_].command_buffer);
|
||||||
VkResult result = vkEndCommandBuffer(command_buffer_);
|
VkResult result = vkEndCommandBuffer(frames_[current_frame_].command_buffer);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
throw std::runtime_error("Failed to record command buffer!");
|
throw std::runtime_error("Failed to record command buffer!");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::CreateSignals() {
|
void Graphics::CreateSignals() {
|
||||||
VkSemaphoreCreateInfo semafore_info = {};
|
for (Frame& frame : frames_) {
|
||||||
semafore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
VkSemaphoreCreateInfo semafore_info = {};
|
||||||
|
semafore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
|
|
||||||
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
|
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
|
||||||
&image_available_signal_) != VK_SUCCESS)
|
&frame.image_available_signal) !=
|
||||||
std::exit(EXIT_FAILURE);
|
VK_SUCCESS)
|
||||||
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
|
std::exit(EXIT_FAILURE);
|
||||||
&render_finished_signal_) != VK_SUCCESS)
|
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
|
||||||
std::exit(EXIT_FAILURE);
|
&frame.render_finished_signal) !=
|
||||||
|
VK_SUCCESS)
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
|
||||||
VkFenceCreateInfo fence_info = {};
|
VkFenceCreateInfo fence_info = {};
|
||||||
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||||
|
|
||||||
if (vkCreateFence(logical_device_, &fence_info, nullptr,
|
if (vkCreateFence(logical_device_, &fence_info, nullptr,
|
||||||
&still_rendering_fence_) != VK_SUCCESS)
|
&frame.still_rendering_fence) !=
|
||||||
std::exit(EXIT_FAILURE);
|
VK_SUCCESS)
|
||||||
|
std::exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Graphics::BeginFrame() {
|
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);
|
UINT64_MAX);
|
||||||
VkResult image_acquire_result = vkAcquireNextImageKHR(
|
VkResult image_acquire_result = vkAcquireNextImageKHR(logical_device_, swap_chain_, UINT64_MAX,
|
||||||
logical_device_, swap_chain_, UINT64_MAX, image_available_signal_,
|
frames_[current_frame_].image_available_signal,
|
||||||
VK_NULL_HANDLE, ¤t_image_index_);
|
VK_NULL_HANDLE, ¤t_image_index_);
|
||||||
|
|
||||||
if (image_acquire_result == VK_ERROR_OUT_OF_DATE_KHR) {
|
if (image_acquire_result == VK_ERROR_OUT_OF_DATE_KHR) {
|
||||||
@@ -124,7 +140,8 @@ bool Graphics::BeginFrame() {
|
|||||||
image_acquire_result != VK_SUBOPTIMAL_KHR)
|
image_acquire_result != VK_SUBOPTIMAL_KHR)
|
||||||
throw std::runtime_error("Couldn't acquire render image!");
|
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();
|
BeginCommands();
|
||||||
SetModelMatrix(glm::mat4(1.f));
|
SetModelMatrix(glm::mat4(1.f));
|
||||||
@@ -139,22 +156,25 @@ void veng::Graphics::EndFrame() {
|
|||||||
|
|
||||||
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||||
submit_info.waitSemaphoreCount = 1;
|
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.pWaitDstStageMask = &wait_stage;
|
||||||
submit_info.commandBufferCount = 1;
|
submit_info.commandBufferCount = 1;
|
||||||
submit_info.pCommandBuffers = &command_buffer_;
|
submit_info.pCommandBuffers = &frames_[current_frame_].command_buffer;
|
||||||
submit_info.signalSemaphoreCount = 1;
|
submit_info.signalSemaphoreCount = 1;
|
||||||
submit_info.pSignalSemaphores = &render_finished_signal_;
|
submit_info.pSignalSemaphores =
|
||||||
|
&frames_[current_frame_].render_finished_signal;
|
||||||
|
|
||||||
VkResult submit_result =
|
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)
|
if (submit_result != VK_SUCCESS)
|
||||||
throw std::runtime_error("failed to submit draw commands!");
|
throw std::runtime_error("failed to submit draw commands!");
|
||||||
|
|
||||||
VkPresentInfoKHR present_info = {};
|
VkPresentInfoKHR present_info = {};
|
||||||
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
present_info.waitSemaphoreCount = 1;
|
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.swapchainCount = 1;
|
||||||
present_info.pSwapchains = &swap_chain_;
|
present_info.pSwapchains = &swap_chain_;
|
||||||
present_info.pImageIndices = ¤t_image_index_;
|
present_info.pImageIndices = ¤t_image_index_;
|
||||||
@@ -164,6 +184,8 @@ void veng::Graphics::EndFrame() {
|
|||||||
RecreateSwapChain();
|
RecreateSwapChain();
|
||||||
else if (result != VK_SUCCESS)
|
else if (result != VK_SUCCESS)
|
||||||
throw std::runtime_error("Failed to present swap chain image!");
|
throw std::runtime_error("Failed to present swap chain image!");
|
||||||
|
|
||||||
|
current_frame_ = (current_frame_++) % MAX_BUFFERED_FRAMES;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace veng
|
} // namespace veng
|
||||||
|
|||||||
@@ -149,6 +149,17 @@ void Graphics::CreateGraphicsPipeline() {
|
|||||||
color_blending_info.attachmentCount = 1;
|
color_blending_info.attachmentCount = 1;
|
||||||
color_blending_info.pAttachments = &color_blend_attachment;
|
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 = {};
|
VkPushConstantRange model_matrix_range = {};
|
||||||
model_matrix_range.offset = 0;
|
model_matrix_range.offset = 0;
|
||||||
model_matrix_range.size = sizeof(glm::mat4);
|
model_matrix_range.size = sizeof(glm::mat4);
|
||||||
@@ -177,7 +188,7 @@ void Graphics::CreateGraphicsPipeline() {
|
|||||||
pipeline_info.pViewportState = &viewport_info;
|
pipeline_info.pViewportState = &viewport_info;
|
||||||
pipeline_info.pRasterizationState = &rasterization_state_info;
|
pipeline_info.pRasterizationState = &rasterization_state_info;
|
||||||
pipeline_info.pMultisampleState = &multisampling_info;
|
pipeline_info.pMultisampleState = &multisampling_info;
|
||||||
pipeline_info.pDepthStencilState = nullptr;
|
pipeline_info.pDepthStencilState = &depth_stencil_info;
|
||||||
pipeline_info.pColorBlendState = &color_blending_info;
|
pipeline_info.pColorBlendState = &color_blending_info;
|
||||||
pipeline_info.pDynamicState = &dynamic_state_info;
|
pipeline_info.pDynamicState = &dynamic_state_info;
|
||||||
pipeline_info.layout = pipeline_layout_;
|
pipeline_info.layout = pipeline_layout_;
|
||||||
@@ -204,17 +215,50 @@ void Graphics::CreateRenderPass() {
|
|||||||
color_attachment_ref.attachment = 0;
|
color_attachment_ref.attachment = 0;
|
||||||
color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
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 = {};
|
VkSubpassDescription main_subpass = {};
|
||||||
main_subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
main_subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||||
main_subpass.colorAttachmentCount = 1;
|
main_subpass.colorAttachmentCount = 1;
|
||||||
main_subpass.pColorAttachments = &color_attachment_ref;
|
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 = {};
|
VkRenderPassCreateInfo render_pass_info = {};
|
||||||
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
render_pass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
|
||||||
render_pass_info.attachmentCount = 1;
|
render_pass_info.attachmentCount = attachments.size();
|
||||||
render_pass_info.pAttachments = &color_attachment;
|
render_pass_info.pAttachments = attachments.data();
|
||||||
render_pass_info.subpassCount = 1;
|
render_pass_info.subpassCount = 1;
|
||||||
render_pass_info.pSubpasses = &main_subpass;
|
render_pass_info.pSubpasses = &main_subpass;
|
||||||
|
render_pass_info.dependencyCount = 1;
|
||||||
|
render_pass_info.pDependencies = &dependency;
|
||||||
|
|
||||||
VkResult result = vkCreateRenderPass(logical_device_, &render_pass_info,
|
VkResult result = vkCreateRenderPass(logical_device_, &render_pass_info,
|
||||||
nullptr, &render_pass_);
|
nullptr, &render_pass_);
|
||||||
@@ -234,6 +278,7 @@ void veng::Graphics::RecreateSwapChain() {
|
|||||||
|
|
||||||
CreateSwapChain();
|
CreateSwapChain();
|
||||||
CreateImageViews();
|
CreateImageViews();
|
||||||
|
CreateDepthResources();
|
||||||
CreateFramebuffers();
|
CreateFramebuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,6 +293,14 @@ void veng::Graphics::CleanupSwapChain() {
|
|||||||
|
|
||||||
if (swap_chain_ != VK_NULL_HANDLE)
|
if (swap_chain_ != VK_NULL_HANDLE)
|
||||||
vkDestroySwapchainKHR(logical_device_, swap_chain_, nullptr);
|
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
|
} // namespace veng
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ void Graphics::CreateSwapChain() {
|
|||||||
swap_chain_images_.data());
|
swap_chain_images_.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageView Graphics::CreateImageView(VkImage image, VkFormat format) {
|
VkImageView Graphics::CreateImageView(VkImage image, VkFormat format, VkImageAspectFlags aspect_flag) {
|
||||||
VkImageViewCreateInfo info = {};
|
VkImageViewCreateInfo info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
info.image = image;
|
info.image = image;
|
||||||
@@ -150,7 +150,7 @@ VkImageView Graphics::CreateImageView(VkImage image, VkFormat format) {
|
|||||||
info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
||||||
info.components.a = 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.baseMipLevel = 0;
|
||||||
info.subresourceRange.levelCount = 1;
|
info.subresourceRange.levelCount = 1;
|
||||||
info.subresourceRange.baseArrayLayer = 0;
|
info.subresourceRange.baseArrayLayer = 0;
|
||||||
@@ -167,7 +167,7 @@ void Graphics::CreateImageViews() {
|
|||||||
|
|
||||||
auto image_view_it = swap_chain_image_views_.begin();
|
auto image_view_it = swap_chain_image_views_.begin();
|
||||||
for (VkImage image : swap_chain_images_) {
|
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);
|
std::advance(image_view_it, 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ TextureHandle Graphics::CreateTexture(gsl::czstring path) {
|
|||||||
stbi_image_free(pixel_data);
|
stbi_image_free(pixel_data);
|
||||||
|
|
||||||
TextureHandle handle =
|
TextureHandle handle =
|
||||||
CreateImage(image_extents,
|
CreateImage(image_extents, VK_FORMAT_R8G8B8A8_SRGB,
|
||||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_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,
|
TransitionImageLayout(handle.image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_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 = {};
|
VkDescriptorSetAllocateInfo set_info = {};
|
||||||
set_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_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) {
|
void Graphics::DestroyTexture(TextureHandle handle) {
|
||||||
vkDeviceWaitIdle(logical_device_);
|
vkDeviceWaitIdle(logical_device_);
|
||||||
vkFreeDescriptorSets(logical_device_, texture_pool_, 1, &handle.set);
|
|
||||||
vkDestroyImageView(logical_device_, handle.image_view, nullptr);
|
if (handle.set != VK_NULL_HANDLE)
|
||||||
vkDestroyImage(logical_device_, handle.image, nullptr);
|
vkFreeDescriptorSets(logical_device_, texture_pool_, 1, &handle.set);
|
||||||
vkFreeMemory(logical_device_, handle.memory, nullptr);
|
|
||||||
|
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) {
|
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);
|
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.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
barrier.image = image;
|
barrier.image = image;
|
||||||
barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
||||||
barrier.subresourceRange.baseArrayLayer = 0;
|
barrier.subresourceRange.baseArrayLayer = 0;
|
||||||
barrier.subresourceRange.baseMipLevel = 0;
|
barrier.subresourceRange.baseMipLevel = 0;
|
||||||
barrier.subresourceRange.levelCount = 1;
|
barrier.subresourceRange.levelCount = 1;
|
||||||
@@ -139,8 +148,20 @@ void Graphics::TransitionImageLayout(VkImage image, VkImageLayout old_layout,
|
|||||||
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||||
source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
source_stage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
destination_stage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_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,
|
vkCmdPipelineBarrier(local_command_buffer, source_stage, destination_stage, 0,
|
||||||
0, nullptr, 0, nullptr, 1, &barrier);
|
0, nullptr, 0, nullptr, 1, &barrier);
|
||||||
|
|
||||||
@@ -169,7 +190,8 @@ void Graphics::CopyBufferToImage(VkBuffer buffer, VkImage image,
|
|||||||
EndTransientCommandBuffer(local_command_buffer);
|
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) {
|
VkMemoryPropertyFlags properties) {
|
||||||
TextureHandle handle = {};
|
TextureHandle handle = {};
|
||||||
|
|
||||||
@@ -183,7 +205,7 @@ TextureHandle Graphics::CreateImage(glm::ivec2 size, VkBufferUsageFlags usage,
|
|||||||
image_info.extent.depth = 1;
|
image_info.extent.depth = 1;
|
||||||
image_info.mipLevels = 1;
|
image_info.mipLevels = 1;
|
||||||
image_info.arrayLayers = 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.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
image_info.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
@@ -216,4 +238,13 @@ TextureHandle Graphics::CreateImage(glm::ivec2 size, VkBufferUsageFlags usage,
|
|||||||
return handle;
|
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
|
} // namespace veng
|
||||||
|
|||||||
Reference in New Issue
Block a user