First attempt for general frame begin/end vulkan functionality.
Test code to draw q3 cinematic. Bugs to fix when things will settle down a bit: cinematic leaks memory, render_view function invalidates command buffer when multiple scenes are rendered in a single frame.
This commit is contained in:
parent
ab66921e14
commit
f944034d17
|
|
@ -21,6 +21,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
#include "tr_local.h"
|
#include "tr_local.h"
|
||||||
|
|
||||||
|
// VULKAN
|
||||||
|
#include "vk_init.h"
|
||||||
|
#include "vk_demo.h"
|
||||||
|
#include "vk_utils.h"
|
||||||
|
|
||||||
backEndData_t *backEndData[SMP_FRAMES];
|
backEndData_t *backEndData[SMP_FRAMES];
|
||||||
backEndState_t backEnd;
|
backEndState_t backEnd;
|
||||||
|
|
||||||
|
|
@ -639,6 +644,9 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
|
||||||
#ifdef __MACOS__
|
#ifdef __MACOS__
|
||||||
Sys_PumpEvents(); // crutch up the mac's limited buffer queue size
|
Sys_PumpEvents(); // crutch up the mac's limited buffer queue size
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// VULKAN
|
||||||
|
vulkan_demo->render_view();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -727,11 +735,23 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
|
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
|
||||||
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
|
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
|
||||||
|
|
||||||
|
// VULKAN
|
||||||
|
vkDestroyImage(get_device(), tr.scratchImage[client]->vk_image, nullptr);
|
||||||
|
vkDestroyImageView(get_device(), tr.scratchImage[client]->vk_image_view, nullptr);
|
||||||
|
tr.scratchImage[client]->vk_image = vulkan_demo->create_texture(data, 4, cols, rows, tr.scratchImage[client]->vk_image_view);
|
||||||
|
vulkan_demo->cinematic_image_view = tr.scratchImage[client]->vk_image_view;
|
||||||
} else {
|
} else {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
|
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
|
||||||
// it and don't try and do a texture compression
|
// it and don't try and do a texture compression
|
||||||
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
|
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
|
||||||
|
|
||||||
|
// VULKAN
|
||||||
|
vkDestroyImage(get_device(), tr.scratchImage[client]->vk_image, nullptr);
|
||||||
|
vkDestroyImageView(get_device(), tr.scratchImage[client]->vk_image_view, nullptr);
|
||||||
|
tr.scratchImage[client]->vk_image = vulkan_demo->create_texture(data, 4, cols, rows, tr.scratchImage[client]->vk_image_view);
|
||||||
|
vulkan_demo->cinematic_image_view = tr.scratchImage[client]->vk_image_view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -754,6 +774,9 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *
|
||||||
qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
|
qglTexCoord2f ( 0.5f / cols, ( rows - 0.5f ) / rows );
|
||||||
qglVertex2f (x, y+h);
|
qglVertex2f (x, y+h);
|
||||||
qglEnd ();
|
qglEnd ();
|
||||||
|
|
||||||
|
// VULKAN
|
||||||
|
vulkan_demo->render_cinematic_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
|
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
|
||||||
|
|
@ -918,6 +941,28 @@ const void *RB_DrawBuffer( const void *data ) {
|
||||||
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
qglClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VULKAN
|
||||||
|
VkResult result = vkAcquireNextImageKHR(get_device(), get_swapchain(), UINT64_MAX, vulkan_demo->image_acquired, VK_NULL_HANDLE, &vulkan_demo->swapchain_image_index);
|
||||||
|
check_vk_result(result, "vkAcquireNextImageKHR");
|
||||||
|
|
||||||
|
result = vkWaitForFences(get_device(), 1, &vulkan_demo->rendering_finished_fence, VK_FALSE, 1e9);
|
||||||
|
check_vk_result(result, "vkWaitForFences");
|
||||||
|
result = vkResetFences(get_device(), 1, &vulkan_demo->rendering_finished_fence);
|
||||||
|
check_vk_result(result, "vkResetFences");
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo begin_info;
|
||||||
|
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
||||||
|
begin_info.pNext = nullptr;
|
||||||
|
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
||||||
|
begin_info.pInheritanceInfo = nullptr;
|
||||||
|
|
||||||
|
extern FILE* logfile;
|
||||||
|
fprintf(logfile, "begin\n");
|
||||||
|
fflush(logfile);
|
||||||
|
|
||||||
|
result = vkBeginCommandBuffer(vulkan_demo->command_buffer, &begin_info);
|
||||||
|
check_vk_result(result, "vkBeginCommandBuffer");
|
||||||
|
|
||||||
return (const void *)(cmd + 1);
|
return (const void *)(cmd + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1032,6 +1077,43 @@ const void *RB_SwapBuffers( const void *data ) {
|
||||||
|
|
||||||
backEnd.projection2D = qfalse;
|
backEnd.projection2D = qfalse;
|
||||||
|
|
||||||
|
// VULKAN
|
||||||
|
extern FILE* logfile;
|
||||||
|
fprintf(logfile, "present\n");
|
||||||
|
fflush(logfile);
|
||||||
|
|
||||||
|
VkResult result = vkEndCommandBuffer(vulkan_demo->command_buffer);
|
||||||
|
check_vk_result(result, "vkEndCommandBuffer");
|
||||||
|
|
||||||
|
VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||||
|
|
||||||
|
VkSubmitInfo submit_info;
|
||||||
|
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
||||||
|
submit_info.pNext = nullptr;
|
||||||
|
submit_info.waitSemaphoreCount = 1;
|
||||||
|
submit_info.pWaitSemaphores = &vulkan_demo->image_acquired;
|
||||||
|
submit_info.pWaitDstStageMask = &wait_dst_stage_mask;
|
||||||
|
submit_info.commandBufferCount = 1;
|
||||||
|
submit_info.pCommandBuffers = &vulkan_demo->command_buffer;
|
||||||
|
submit_info.signalSemaphoreCount = 1;
|
||||||
|
submit_info.pSignalSemaphores = &vulkan_demo->rendering_finished;
|
||||||
|
|
||||||
|
result = vkQueueSubmit(get_queue(), 1, &submit_info, vulkan_demo->rendering_finished_fence);
|
||||||
|
check_vk_result(result, "vkQueueSubmit");
|
||||||
|
|
||||||
|
VkSwapchainKHR swapchain = get_swapchain();
|
||||||
|
VkPresentInfoKHR present_info;
|
||||||
|
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
|
present_info.pNext = nullptr;
|
||||||
|
present_info.waitSemaphoreCount = 1;
|
||||||
|
present_info.pWaitSemaphores = &vulkan_demo->rendering_finished;
|
||||||
|
present_info.swapchainCount = 1;
|
||||||
|
present_info.pSwapchains = &swapchain;
|
||||||
|
present_info.pImageIndices = &vulkan_demo->swapchain_image_index;
|
||||||
|
present_info.pResults = nullptr;
|
||||||
|
result = vkQueuePresentKHR(get_queue(), &present_info);
|
||||||
|
check_vk_result(result, "vkQueuePresentKHR");
|
||||||
|
|
||||||
return (const void *)(cmd + 1);
|
return (const void *)(cmd + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -397,7 +397,4 @@ void RE_RenderScene( const refdef_t *fd ) {
|
||||||
r_firstScenePoly = r_numpolys;
|
r_firstScenePoly = r_numpolys;
|
||||||
|
|
||||||
tr.frontEndMsec += ri.Milliseconds() - startTime;
|
tr.frontEndMsec += ri.Milliseconds() - startTime;
|
||||||
|
|
||||||
// VULKAN
|
|
||||||
vulkan_demo->run_frame();
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,8 @@ static VkFormat find_depth_format(VkPhysicalDevice physical_device) {
|
||||||
VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FILE* logfile;
|
||||||
|
|
||||||
Vulkan_Demo::Vulkan_Demo(int window_width, int window_height, const SDL_SysWMinfo& window_sys_info)
|
Vulkan_Demo::Vulkan_Demo(int window_width, int window_height, const SDL_SysWMinfo& window_sys_info)
|
||||||
: window_width(window_width)
|
: window_width(window_width)
|
||||||
, window_height(window_height)
|
, window_height(window_height)
|
||||||
|
|
@ -110,6 +112,8 @@ Vulkan_Demo::Vulkan_Demo(int window_width, int window_height, const SDL_SysWMinf
|
||||||
get_resource_manager()->initialize(get_device());
|
get_resource_manager()->initialize(get_device());
|
||||||
create_command_pool();
|
create_command_pool();
|
||||||
|
|
||||||
|
logfile = fopen("debuglog.txt", "w");
|
||||||
|
|
||||||
image_acquired = get_resource_manager()->create_semaphore();
|
image_acquired = get_resource_manager()->create_semaphore();
|
||||||
rendering_finished = get_resource_manager()->create_semaphore();
|
rendering_finished = get_resource_manager()->create_semaphore();
|
||||||
|
|
||||||
|
|
@ -135,17 +139,7 @@ Vulkan_Demo::Vulkan_Demo(int window_width, int window_height, const SDL_SysWMinf
|
||||||
create_pipeline();
|
create_pipeline();
|
||||||
|
|
||||||
upload_geometry();
|
upload_geometry();
|
||||||
|
update_ubo_descriptor();
|
||||||
{
|
|
||||||
VkCommandBufferAllocateInfo alloc_info;
|
|
||||||
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
||||||
alloc_info.pNext = nullptr;
|
|
||||||
alloc_info.commandPool = command_pool;
|
|
||||||
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_SECONDARY;
|
|
||||||
alloc_info.commandBufferCount = 1;
|
|
||||||
result = vkAllocateCommandBuffers(get_device(), &alloc_info, &render_scene_command_buffer);
|
|
||||||
check_vk_result(result, "vkAllocateCommandBuffers");
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
VkCommandBufferAllocateInfo alloc_info;
|
VkCommandBufferAllocateInfo alloc_info;
|
||||||
|
|
@ -153,9 +147,8 @@ Vulkan_Demo::Vulkan_Demo(int window_width, int window_height, const SDL_SysWMinf
|
||||||
alloc_info.pNext = nullptr;
|
alloc_info.pNext = nullptr;
|
||||||
alloc_info.commandPool = command_pool;
|
alloc_info.commandPool = command_pool;
|
||||||
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
||||||
alloc_info.commandBufferCount = static_cast<uint32_t>(get_swapchain_image_views().size());
|
alloc_info.commandBufferCount = 1;
|
||||||
render_frame_command_buffers.resize(get_swapchain_image_views().size());
|
result = vkAllocateCommandBuffers(get_device(), &alloc_info, &command_buffer);
|
||||||
result = vkAllocateCommandBuffers(get_device(), &alloc_info, render_frame_command_buffers.data());
|
|
||||||
check_vk_result(result, "vkAllocateCommandBuffers");
|
check_vk_result(result, "vkAllocateCommandBuffers");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -482,7 +475,7 @@ void Vulkan_Demo::create_pipeline() {
|
||||||
rasterization_state.depthClampEnable = VK_FALSE;
|
rasterization_state.depthClampEnable = VK_FALSE;
|
||||||
rasterization_state.rasterizerDiscardEnable = VK_FALSE;
|
rasterization_state.rasterizerDiscardEnable = VK_FALSE;
|
||||||
rasterization_state.polygonMode = VK_POLYGON_MODE_FILL;
|
rasterization_state.polygonMode = VK_POLYGON_MODE_FILL;
|
||||||
rasterization_state.cullMode = VK_CULL_MODE_BACK_BIT;
|
rasterization_state.cullMode = VK_CULL_MODE_NONE/*VK_CULL_MODE_BACK_BIT*/;
|
||||||
rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
rasterization_state.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
|
||||||
rasterization_state.depthBiasEnable = VK_FALSE;
|
rasterization_state.depthBiasEnable = VK_FALSE;
|
||||||
rasterization_state.depthBiasConstantFactor = 0.0f;
|
rasterization_state.depthBiasConstantFactor = 0.0f;
|
||||||
|
|
@ -600,57 +593,12 @@ void Vulkan_Demo::upload_geometry() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan_Demo::record_render_scene() {
|
|
||||||
VkCommandBufferInheritanceInfo inheritance_info;
|
|
||||||
inheritance_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
|
|
||||||
inheritance_info.pNext = nullptr;
|
|
||||||
inheritance_info.renderPass = render_pass;
|
|
||||||
inheritance_info.subpass = 0;
|
|
||||||
inheritance_info.framebuffer = VK_NULL_HANDLE;
|
|
||||||
inheritance_info.occlusionQueryEnable = VK_FALSE;
|
|
||||||
inheritance_info.queryFlags = 0;
|
|
||||||
inheritance_info.pipelineStatistics = 0;
|
|
||||||
|
|
||||||
VkCommandBufferBeginInfo begin_info;
|
|
||||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
||||||
begin_info.pNext = nullptr;
|
|
||||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT | VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
|
||||||
begin_info.pInheritanceInfo = &inheritance_info;
|
|
||||||
|
|
||||||
VkResult result = vkBeginCommandBuffer(render_scene_command_buffer, &begin_info);
|
|
||||||
check_vk_result(result, "vkBeginCommandBuffer");
|
|
||||||
|
|
||||||
const VkDeviceSize offset = 0;
|
|
||||||
vkCmdBindVertexBuffers(render_scene_command_buffer, 0, 1, &vertex_buffer, &offset);
|
|
||||||
vkCmdBindIndexBuffer(render_scene_command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT32);
|
|
||||||
vkCmdBindDescriptorSets(render_scene_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set, 0, nullptr);
|
|
||||||
vkCmdBindPipeline(render_scene_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
|
||||||
vkCmdDrawIndexed(render_scene_command_buffer, model_indices_count, 1, 0, 0, 0);
|
|
||||||
|
|
||||||
result = vkEndCommandBuffer(render_scene_command_buffer);
|
|
||||||
check_vk_result(result, "vkEndCommandBuffer");
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vulkan_Demo::record_render_frame() {
|
void Vulkan_Demo::record_render_frame() {
|
||||||
VkCommandBufferBeginInfo begin_info;
|
VkBufferCopy region;
|
||||||
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
region.srcOffset = 0;
|
||||||
begin_info.pNext = nullptr;
|
region.dstOffset = 0;
|
||||||
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
region.size = sizeof(Uniform_Buffer_Object);
|
||||||
begin_info.pInheritanceInfo = nullptr;
|
vkCmdCopyBuffer(command_buffer, uniform_staging_buffer, uniform_buffer, 1, ®ion);
|
||||||
|
|
||||||
std::array<VkClearValue, 2> clear_values;
|
|
||||||
clear_values[0].color = {0.3f, 0.2f, 0.1f, 0.0f};
|
|
||||||
clear_values[1].depthStencil = {1.0, 0};
|
|
||||||
|
|
||||||
VkRenderPassBeginInfo render_pass_begin_info;
|
|
||||||
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
|
||||||
render_pass_begin_info.pNext = nullptr;
|
|
||||||
render_pass_begin_info.renderPass = render_pass;
|
|
||||||
render_pass_begin_info.framebuffer = VK_NULL_HANDLE; // will be initialized later in the recording loop
|
|
||||||
render_pass_begin_info.renderArea.offset = {0, 0};
|
|
||||||
render_pass_begin_info.renderArea.extent = {(uint32_t)window_width, (uint32_t)window_height};
|
|
||||||
render_pass_begin_info.clearValueCount = static_cast<uint32_t>(clear_values.size());
|
|
||||||
render_pass_begin_info.pClearValues = clear_values.data();
|
|
||||||
|
|
||||||
VkBufferMemoryBarrier barrier;
|
VkBufferMemoryBarrier barrier;
|
||||||
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
|
||||||
|
|
@ -663,51 +611,42 @@ void Vulkan_Demo::record_render_frame() {
|
||||||
barrier.offset = 0;
|
barrier.offset = 0;
|
||||||
barrier.size = sizeof(Uniform_Buffer_Object);
|
barrier.size = sizeof(Uniform_Buffer_Object);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < render_frame_command_buffers.size(); i++) {
|
vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0,
|
||||||
VkResult result = vkBeginCommandBuffer(render_frame_command_buffers[i], &begin_info);
|
0, nullptr, 1, &barrier, 0, nullptr);
|
||||||
check_vk_result(result, "vkBeginCommandBuffer");
|
|
||||||
|
|
||||||
VkBufferCopy region;
|
std::array<VkClearValue, 2> clear_values;
|
||||||
region.srcOffset = 0;
|
clear_values[0].color = {0.3f, 0.2f, 0.1f, 0.0f};
|
||||||
region.dstOffset = 0;
|
clear_values[1].depthStencil = {1.0, 0};
|
||||||
region.size = sizeof(Uniform_Buffer_Object);
|
|
||||||
vkCmdCopyBuffer(render_frame_command_buffers[i], uniform_staging_buffer, uniform_buffer, 1, ®ion);
|
|
||||||
|
|
||||||
vkCmdPipelineBarrier(render_frame_command_buffers[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0,
|
VkRenderPassBeginInfo render_pass_begin_info;
|
||||||
0, nullptr, 1, &barrier, 0, nullptr);
|
render_pass_begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
|
render_pass_begin_info.pNext = nullptr;
|
||||||
|
render_pass_begin_info.renderPass = render_pass;
|
||||||
|
render_pass_begin_info.framebuffer = framebuffers[swapchain_image_index];
|
||||||
|
render_pass_begin_info.renderArea.offset = {0, 0};
|
||||||
|
render_pass_begin_info.renderArea.extent = {(uint32_t)window_width, (uint32_t)window_height};
|
||||||
|
render_pass_begin_info.clearValueCount = static_cast<uint32_t>(clear_values.size());
|
||||||
|
render_pass_begin_info.pClearValues = clear_values.data();
|
||||||
|
|
||||||
render_pass_begin_info.framebuffer = framebuffers[i];
|
vkCmdBeginRenderPass(command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
vkCmdBeginRenderPass(render_frame_command_buffers[i], &render_pass_begin_info, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
|
|
||||||
vkCmdExecuteCommands(render_frame_command_buffers[i], 1, &render_scene_command_buffer);
|
|
||||||
vkCmdEndRenderPass(render_frame_command_buffers[i]);
|
|
||||||
|
|
||||||
result = vkEndCommandBuffer(render_frame_command_buffers[i]);
|
const VkDeviceSize offset = 0;
|
||||||
check_vk_result(result, "vkEndCommandBuffer");
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, &vertex_buffer, &offset);
|
||||||
}
|
vkCmdBindIndexBuffer(command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||||
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, &descriptor_set, 0, nullptr);
|
||||||
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||||
|
vkCmdDrawIndexed(command_buffer, model_indices_count, 1, 0, 0, 0);
|
||||||
|
|
||||||
|
vkCmdEndRenderPass(command_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan_Demo::update_descriptor_set() {
|
void Vulkan_Demo::update_ubo_descriptor() {
|
||||||
static auto start_time = std::chrono::high_resolution_clock::now();
|
|
||||||
auto current_time = std::chrono::high_resolution_clock::now();
|
|
||||||
int time = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();
|
|
||||||
static int image_index = 0;
|
|
||||||
|
|
||||||
if (time > 500) {
|
|
||||||
start_time = current_time;
|
|
||||||
image_index = 37 + (image_index + 1) % (tr.numImages - 37);
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDescriptorBufferInfo buffer_info;
|
VkDescriptorBufferInfo buffer_info;
|
||||||
buffer_info.buffer = uniform_buffer;
|
buffer_info.buffer = uniform_buffer;
|
||||||
buffer_info.offset = 0;
|
buffer_info.offset = 0;
|
||||||
buffer_info.range = sizeof(Uniform_Buffer_Object);
|
buffer_info.range = sizeof(Uniform_Buffer_Object);
|
||||||
|
|
||||||
VkDescriptorImageInfo image_info;
|
std::array<VkWriteDescriptorSet, 1> descriptor_writes;
|
||||||
image_info.sampler = texture_image_sampler;
|
|
||||||
image_info.imageView = tr.images[image_index]->vk_image_view;
|
|
||||||
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
|
||||||
|
|
||||||
std::array<VkWriteDescriptorSet, 2> descriptor_writes;
|
|
||||||
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
descriptor_writes[0].pNext = nullptr;
|
descriptor_writes[0].pNext = nullptr;
|
||||||
descriptor_writes[0].dstSet = descriptor_set;
|
descriptor_writes[0].dstSet = descriptor_set;
|
||||||
|
|
@ -719,26 +658,53 @@ void Vulkan_Demo::update_descriptor_set() {
|
||||||
descriptor_writes[0].pBufferInfo = &buffer_info;
|
descriptor_writes[0].pBufferInfo = &buffer_info;
|
||||||
descriptor_writes[0].pTexelBufferView = nullptr;
|
descriptor_writes[0].pTexelBufferView = nullptr;
|
||||||
|
|
||||||
descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
|
||||||
descriptor_writes[1].dstSet = descriptor_set;
|
}
|
||||||
descriptor_writes[1].dstBinding = 1;
|
|
||||||
descriptor_writes[1].dstArrayElement = 0;
|
void Vulkan_Demo::update_image_descriptor(bool cinematic) {
|
||||||
descriptor_writes[1].descriptorCount = 1;
|
VkImageView image_view;
|
||||||
descriptor_writes[1].pNext = nullptr;
|
|
||||||
descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
if (cinematic) {
|
||||||
descriptor_writes[1].pImageInfo = &image_info;
|
image_view = cinematic_image_view;
|
||||||
descriptor_writes[1].pBufferInfo = nullptr;
|
} else {
|
||||||
descriptor_writes[1].pTexelBufferView = nullptr;
|
static auto start_time = std::chrono::high_resolution_clock::now();
|
||||||
|
auto current_time = std::chrono::high_resolution_clock::now();
|
||||||
|
int time = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count();
|
||||||
|
static int image_index = 0;
|
||||||
|
|
||||||
|
if (time > 200) {
|
||||||
|
start_time = current_time;
|
||||||
|
image_index = (image_index + 1) % tr.numImages;
|
||||||
|
}
|
||||||
|
image_view = tr.images[image_index]->vk_image_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDescriptorImageInfo image_info;
|
||||||
|
image_info.sampler = texture_image_sampler;
|
||||||
|
image_info.imageView = image_view;
|
||||||
|
image_info.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||||
|
|
||||||
|
std::array<VkWriteDescriptorSet, 1> descriptor_writes;
|
||||||
|
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
||||||
|
descriptor_writes[0].dstSet = descriptor_set;
|
||||||
|
descriptor_writes[0].dstBinding = 1;
|
||||||
|
descriptor_writes[0].dstArrayElement = 0;
|
||||||
|
descriptor_writes[0].descriptorCount = 1;
|
||||||
|
descriptor_writes[0].pNext = nullptr;
|
||||||
|
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||||
|
descriptor_writes[0].pImageInfo = &image_info;
|
||||||
|
descriptor_writes[0].pBufferInfo = nullptr;
|
||||||
|
descriptor_writes[0].pTexelBufferView = nullptr;
|
||||||
|
|
||||||
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
|
vkUpdateDescriptorSets(get_device(), (uint32_t)descriptor_writes.size(), descriptor_writes.data(), 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan_Demo::update_uniform_buffer() {
|
void Vulkan_Demo::update_uniform_buffer(bool cinematic) {
|
||||||
static auto start_time = std::chrono::high_resolution_clock::now();
|
static auto start_time = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
auto current_time = std::chrono::high_resolution_clock::now();
|
auto current_time = std::chrono::high_resolution_clock::now();
|
||||||
float time = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count() / 1000.f;
|
float time = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - start_time).count() / 1000.f;
|
||||||
time = 0.0;
|
if (cinematic) time = 0.0;
|
||||||
|
|
||||||
Uniform_Buffer_Object ubo;
|
Uniform_Buffer_Object ubo;
|
||||||
ubo.model = glm::rotate(glm::mat4(), time * glm::radians(30.0f), glm::vec3(0, 1, 0));
|
ubo.model = glm::rotate(glm::mat4(), time * glm::radians(30.0f), glm::vec3(0, 1, 0));
|
||||||
|
|
@ -761,48 +727,20 @@ void Vulkan_Demo::update_uniform_buffer() {
|
||||||
vkUnmapMemory(get_device(), uniform_staging_buffer_memory);
|
vkUnmapMemory(get_device(), uniform_staging_buffer_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vulkan_Demo::run_frame() {
|
void Vulkan_Demo::render_view() {
|
||||||
VkResult result = vkWaitForFences(get_device(), 1, &rendering_finished_fence, VK_FALSE, 1e9);
|
fprintf(logfile, "render_view\n");
|
||||||
check_vk_result(result, "vkWaitForFences");
|
fflush(logfile);
|
||||||
result = vkResetFences(get_device(), 1, &rendering_finished_fence);
|
|
||||||
check_vk_result(result, "vkResetFences");
|
update_image_descriptor(false);
|
||||||
update_descriptor_set();
|
|
||||||
record_render_scene(); // record secondary command buffer before primary ones
|
|
||||||
record_render_frame();
|
record_render_frame();
|
||||||
|
update_uniform_buffer(false);
|
||||||
update_uniform_buffer();
|
}
|
||||||
|
|
||||||
uint32_t swapchain_image_index;
|
void Vulkan_Demo::render_cinematic_frame() {
|
||||||
result = vkAcquireNextImageKHR(get_device(), get_swapchain(), UINT64_MAX, image_acquired, VK_NULL_HANDLE, &swapchain_image_index);
|
fprintf(logfile, "render_cinematic_frame\n");
|
||||||
check_vk_result(result, "vkAcquireNextImageKHR");
|
fflush(logfile);
|
||||||
|
|
||||||
VkPipelineStageFlags wait_dst_stage_mask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
update_image_descriptor(true);
|
||||||
|
record_render_frame();
|
||||||
VkSubmitInfo submit_info;
|
update_uniform_buffer(true);
|
||||||
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
||||||
submit_info.pNext = nullptr;
|
|
||||||
submit_info.waitSemaphoreCount = 1;
|
|
||||||
submit_info.pWaitSemaphores = &image_acquired;
|
|
||||||
submit_info.pWaitDstStageMask = &wait_dst_stage_mask;
|
|
||||||
submit_info.commandBufferCount = 1;
|
|
||||||
submit_info.pCommandBuffers = &render_frame_command_buffers[swapchain_image_index];
|
|
||||||
submit_info.signalSemaphoreCount = 1;
|
|
||||||
submit_info.pSignalSemaphores = &rendering_finished;
|
|
||||||
|
|
||||||
result = vkQueueSubmit(get_queue(), 1, &submit_info, rendering_finished_fence);
|
|
||||||
check_vk_result(result, "vkQueueSubmit");
|
|
||||||
|
|
||||||
VkSwapchainKHR swapchain = get_swapchain();
|
|
||||||
VkPresentInfoKHR present_info;
|
|
||||||
present_info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
|
||||||
present_info.pNext = nullptr;
|
|
||||||
present_info.waitSemaphoreCount = 1;
|
|
||||||
present_info.pWaitSemaphores = &rendering_finished;
|
|
||||||
present_info.swapchainCount = 1;
|
|
||||||
present_info.pSwapchains = &swapchain;
|
|
||||||
present_info.pImageIndices = &swapchain_image_index;
|
|
||||||
present_info.pResults = nullptr;
|
|
||||||
|
|
||||||
result = vkQueuePresentKHR(get_queue(), &present_info);
|
|
||||||
check_vk_result(result, "vkQueuePresentKHR");
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ public:
|
||||||
Vulkan_Demo(int window_width, int window_height, const SDL_SysWMinfo& window_sys_info);
|
Vulkan_Demo(int window_width, int window_height, const SDL_SysWMinfo& window_sys_info);
|
||||||
~Vulkan_Demo();
|
~Vulkan_Demo();
|
||||||
|
|
||||||
void run_frame();
|
void render_view();
|
||||||
|
void render_cinematic_frame();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void create_command_pool();
|
void create_command_pool();
|
||||||
|
|
@ -30,12 +31,12 @@ public:
|
||||||
void create_pipeline();
|
void create_pipeline();
|
||||||
|
|
||||||
void upload_geometry();
|
void upload_geometry();
|
||||||
void record_render_scene();
|
|
||||||
void record_render_frame();
|
void record_render_frame();
|
||||||
void update_descriptor_set();
|
void update_ubo_descriptor();
|
||||||
void update_uniform_buffer();
|
void update_image_descriptor(bool cinematic);
|
||||||
|
void update_uniform_buffer(bool cinematic);
|
||||||
|
|
||||||
private:
|
public:
|
||||||
const int window_width = 0;
|
const int window_width = 0;
|
||||||
const int window_height = 0;
|
const int window_height = 0;
|
||||||
|
|
||||||
|
|
@ -65,6 +66,8 @@ private:
|
||||||
VkBuffer index_buffer = VK_NULL_HANDLE;
|
VkBuffer index_buffer = VK_NULL_HANDLE;
|
||||||
uint32_t model_indices_count = 0;
|
uint32_t model_indices_count = 0;
|
||||||
|
|
||||||
std::vector<VkCommandBuffer> render_frame_command_buffers; // command buffer per swapchain image
|
VkCommandBuffer command_buffer = VK_NULL_HANDLE;
|
||||||
VkCommandBuffer render_scene_command_buffer;
|
|
||||||
|
uint32_t swapchain_image_index = -1;
|
||||||
|
VkImageView cinematic_image_view = VK_NULL_HANDLE;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user