화면크기변경 로직 추가
This commit is contained in:
@@ -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)
|
||||
@@ -65,3 +74,4 @@ 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/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 "utilities.h"
|
||||
|
||||
#define MAX_BUFFERED_FRAMES (2)
|
||||
|
||||
@@ -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;
|
||||
|
||||
43
src/main.cpp
43
src/main.cpp
@@ -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());
|
||||
|
||||
@@ -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_ =
|
||||
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,24 +292,25 @@ void Graphics::CreateDescriptorPools() {
|
||||
}
|
||||
|
||||
void Graphics::CreateDescriptorSets() {
|
||||
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_);
|
||||
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.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.dstSet = frame.uniform_set;
|
||||
descriptor_write.dstBinding = 0;
|
||||
descriptor_write.dstArrayElement = 0;
|
||||
descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
@@ -310,5 +319,6 @@ void Graphics::CreateDescriptorSets() {
|
||||
|
||||
vkUpdateDescriptorSets(logical_device_, 1, &descriptor_write, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace veng
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
for (Frame& frame : frames_) {
|
||||
VkResult result =
|
||||
vkAllocateCommandBuffers(logical_device_, &info, &command_buffer_);
|
||||
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,38 +75,41 @@ 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() {
|
||||
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)
|
||||
&frame.image_available_signal) !=
|
||||
VK_SUCCESS)
|
||||
std::exit(EXIT_FAILURE);
|
||||
if (vkCreateSemaphore(logical_device_, &semafore_info, nullptr,
|
||||
&render_finished_signal_) != VK_SUCCESS)
|
||||
&frame.render_finished_signal) !=
|
||||
VK_SUCCESS)
|
||||
std::exit(EXIT_FAILURE);
|
||||
|
||||
VkFenceCreateInfo fence_info = {};
|
||||
@@ -104,15 +117,18 @@ void Graphics::CreateSignals() {
|
||||
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||
|
||||
if (vkCreateFence(logical_device_, &fence_info, nullptr,
|
||||
&still_rendering_fence_) != VK_SUCCESS)
|
||||
&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, ¤t_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 = ¤t_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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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_);
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user