Create and destroy color/depth resources

This commit is contained in:
Bill Currie 2020-02-18 14:28:28 +09:00
parent 89d48b5650
commit 1f4c019abc
6 changed files with 235 additions and 4 deletions

View file

@ -6,6 +6,13 @@
typedef struct qfv_imageset_s DARRAY_TYPE (VkImage) qfv_imageset_t;
typedef struct qfv_imageviewset_s DARRAY_TYPE (VkImageView) qfv_imageviewset_t;
typedef struct qfv_imageresource_s {
struct qfv_device_s *device;
VkImage image;
VkDeviceMemory object;
VkImageView view;
} qfv_imageresource_t;
typedef struct qfv_imagetransition_s {
VkImage image;
VkAccessFlags srcAccess;
@ -37,6 +44,9 @@ VkDeviceMemory QFV_AllocImageMemory (struct qfv_device_s *device,
VkMemoryPropertyFlags properties,
VkDeviceSize size, VkDeviceSize offset);
int QFV_BindImageMemory (struct qfv_device_s *device, VkImage image,
VkDeviceMemory object, VkDeviceSize offset);
qfv_imagebarrierset_t *
QFV_CreateImageTransitionSet (qfv_imagetransition_t *transitions,
int numTransitions);

View file

@ -36,6 +36,8 @@
#include <vulkan/vulkan.h>
struct vulkan_ctx_s;
void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx);
void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx);
void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx);
void Vulkan_CreateDevice (struct vulkan_ctx_s *ctx);
void Vulkan_Init_Common (struct vulkan_ctx_s *ctx);

View file

@ -14,6 +14,11 @@ typedef struct vulkan_frameset_s {
struct qfv_semaphoreset_s *renderDoneSemaphores;
} vulkan_frameset_t;
typedef struct vulkan_renderpass_s {
struct qfv_imageresource_s *colorImage;
struct qfv_imageresource_s *depthImage;
} vulkan_renderpass_t;
typedef struct vulkan_ctx_s {
void (*load_vulkan) (struct vulkan_ctx_s *ctx);
void (*unload_vulkan) (struct vulkan_ctx_s *ctx);
@ -33,7 +38,10 @@ typedef struct vulkan_ctx_s {
VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain
VkCommandPool cmdpool;
VkCommandBuffer cmdbuffer;
VkFence fence; // for ctx->cmdbuffer only
vulkan_frameset_t frameset;
vulkan_renderpass_t renderpass;
#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname;
#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname;

View file

@ -63,6 +63,7 @@ vulkan_R_Init (void)
qfv_cmdbufferset_t *cmdBuffers;
Vulkan_CreateSwapchain (vulkan_ctx);
Vulkan_CreateRenderPass (vulkan_ctx);
cmdBuffers = QFV_AllocateCommandBuffers (device, vulkan_ctx->cmdpool, 0,
vulkan_ctx->swapchain->numImages);
vulkan_ctx->frameset.cmdBuffers = cmdBuffers;
@ -139,7 +140,7 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void))
qfv_queue_t *queue = &vulkan_ctx->device->queue;
vulkan_frameset_t *frameset = &vulkan_ctx->frameset;
dfunc->vkWaitForFences (dev, 1, & frameset->fences->a[frameset->curFrame],
dfunc->vkWaitForFences (dev, 1, &frameset->fences->a[frameset->curFrame],
VK_TRUE, 2000000000);
QFV_AcquireNextImage (vulkan_ctx->swapchain,
frameset->imageSemaphores->a[frameset->curFrame],
@ -174,7 +175,8 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void))
double currenTime = Sys_DoubleTime ();
double time = currenTime - startTime;
startTime = currenTime;
printf ("%d frames in %g s: %g fps \r", count, time, count / time);
printf ("%d frames in %g s: %g fps \r",
count, time, count / time);
fflush (stdout);
count = 0;
}
@ -291,7 +293,13 @@ vulkan_vid_render_choose_visual (void)
vulkan_ctx->choose_visual (vulkan_ctx);
vulkan_ctx->cmdpool = QFV_CreateCommandPool (vulkan_ctx->device,
vulkan_ctx->device->queue.queueFamily,
0, 0);
0, 1);
__auto_type cmdset = QFV_AllocateCommandBuffers (vulkan_ctx->device,
vulkan_ctx->cmdpool,
0, 1);
vulkan_ctx->cmdbuffer = cmdset->a[0];
free (cmdset);
vulkan_ctx->fence = QFV_CreateFence (vulkan_ctx->device, 1);
Sys_Printf ("vk choose visual %p %p %d %p\n", vulkan_ctx->device->dev,
vulkan_ctx->device->queue.queue,
vulkan_ctx->device->queue.queueFamily,
@ -309,7 +317,7 @@ vulkan_vid_render_create_context (void)
qfv_semaphoreset_t *renderDoneSems = DARRAY_ALLOCFIXED (*renderDoneSems, 2,
malloc);
for (int i = 0; i < 2; i++) {
fences->a[i]= QFV_CreateFence (vulkan_ctx->device, 1);
fences->a[i] = QFV_CreateFence (vulkan_ctx->device, 1);
imageSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device);
renderDoneSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device);
}
@ -348,6 +356,7 @@ vulkan_vid_render_shutdown (void)
df->vkDestroySemaphore (dev, frameset->imageSemaphores->a[i], 0);
df->vkDestroySemaphore (dev, frameset->renderDoneSemaphores->a[i], 0);
}
df->vkDestroyFence (dev, vulkan_ctx->fence, 0);
df->vkDestroyCommandPool (dev, vulkan_ctx->cmdpool, 0);
Vulkan_Shutdown_Common (vulkan_ctx);
}

View file

@ -126,6 +126,16 @@ QFV_AllocImageMemory (qfv_device_t *device,
return object;
}
int
QFV_BindImageMemory (qfv_device_t *device,
VkImage image, VkDeviceMemory object, VkDeviceSize offset)
{
VkDevice dev = device->dev;
qfv_devfuncs_t *dfunc = device->funcs;
VkResult res = dfunc->vkBindImageMemory (dev, image, object, offset);
return res == VK_SUCCESS;
}
qfv_imagebarrierset_t *
QFV_CreateImageTransitionSet (qfv_imagetransition_t *transitions,
int numTransitions)

View file

@ -51,6 +51,7 @@
#include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/device.h"
#include "QF/Vulkan/instance.h"
#include "QF/Vulkan/image.h"
#include "QF/Vulkan/swapchain.h"
#include "compat.h"
@ -116,6 +117,9 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx)
void
Vulkan_Shutdown_Common (vulkan_ctx_t *ctx)
{
if (ctx->renderpass.colorImage) {
Vulkan_DestroyRenderPass (ctx);
}
if (ctx->swapchain) {
QFV_DestroySwapchain (ctx->swapchain);
}
@ -151,3 +155,191 @@ Vulkan_CreateSwapchain (vulkan_ctx_t *ctx)
old_swapchain, 0);
}
}
typedef struct {
VkPipelineStageFlags src;
VkPipelineStageFlags dst;
} qfv_pipelinestagepair_t;
//XXX Note: imageLayoutTransitionBarriers, imageLayoutTransitionStages and
// the enum be kept in sync
enum {
qfv_LT_Undefined_to_TransferDst,
qfv_LT_TransferDst_to_ShaderReadOnly,
qfv_LT_Undefined_to_DepthStencil,
qfv_LT_Undefined_to_Color,
};
static VkImageMemoryBarrier imageLayoutTransitionBarriers[] = {
// undefined -> transfer dst optimal
{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
0,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0,
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
},
// transfer dst optimal -> shader read only optimal
{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0,
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
},
// undefined -> depth stencil attachment optimal
{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
0,
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT
| VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0,
{ VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, 0, 1 }
},
// undefined -> color attachment optimal
{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, 0,
0,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
| VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, 0,
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }
},
{ /* end of transition barriers */ }
};
static qfv_pipelinestagepair_t imageLayoutTransitionStages[] = {
// undefined -> transfer dst optimal
{ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT },
// transfer dst optimal -> shader read only optimal
{ VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT },
// undefined -> depth stencil attachment optimal
{ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT },
// undefined -> color attachment optimal
{ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT },
};
void
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
VkDevice dev = device->dev;
qfv_devfuncs_t *df = device->funcs;
VkCommandBuffer cmd = ctx->cmdbuffer;
qfv_swapchain_t *sc = ctx->swapchain;
qfv_imageresource_t *colorImage = malloc (sizeof (*colorImage));
qfv_imageresource_t *depthImage = malloc (sizeof (*depthImage));
VkExtent3D extent = {sc->extent.width, sc->extent.height, 1};
Sys_MaskPrintf (SYS_VULKAN, "color resource\n");
colorImage->image
= QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D,
sc->format, extent, 1, 1,
VK_SAMPLE_COUNT_1_BIT, // FIXME
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
colorImage->object
= QFV_AllocImageMemory (device, colorImage->image,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0);
QFV_BindImageMemory (device, colorImage->image, colorImage->object, 0);
colorImage->view
= QFV_CreateImageView (device, colorImage->image,
VK_IMAGE_VIEW_TYPE_2D,
sc->format, VK_IMAGE_ASPECT_COLOR_BIT);
Sys_MaskPrintf (SYS_VULKAN, " image: %p object: %p view:%p\n",
colorImage->image, colorImage->object, colorImage->view);
Sys_MaskPrintf (SYS_VULKAN, "depth resource\n");
VkFormat depthFormat = VK_FORMAT_D32_SFLOAT;
depthImage->image
= QFV_CreateImage (device, 0, VK_IMAGE_TYPE_2D,
depthFormat, extent, 1, 1,
VK_SAMPLE_COUNT_1_BIT, // FIXME (for depth?!?)
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
depthImage->object
= QFV_AllocImageMemory (device, depthImage->image,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 0, 0);
QFV_BindImageMemory (device, depthImage->image, depthImage->object, 0);
depthImage->view
= QFV_CreateImageView (device, depthImage->image,
VK_IMAGE_VIEW_TYPE_2D,
depthFormat, VK_IMAGE_ASPECT_DEPTH_BIT);
Sys_MaskPrintf (SYS_VULKAN, " image: %p object: %p view:%p\n",
depthImage->image, depthImage->object, depthImage->view);
VkImageMemoryBarrier barrier;
qfv_pipelinestagepair_t stages;
df->vkWaitForFences (dev, 1, &ctx->fence, VK_TRUE, ~0ul);
df->vkResetCommandBuffer (cmd, 0);
VkCommandBufferBeginInfo beginInfo = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0,
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, 0,
};
df->vkBeginCommandBuffer (cmd, &beginInfo);
stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_Color];
barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_Color];
barrier.image = colorImage->image;
df->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0,
0, 0,
0, 0,
1, &barrier);
stages = imageLayoutTransitionStages[qfv_LT_Undefined_to_DepthStencil];
barrier = imageLayoutTransitionBarriers[qfv_LT_Undefined_to_DepthStencil];
barrier.image = depthImage->image;
if (depthFormat == VK_FORMAT_D32_SFLOAT_S8_UINT
|| depthFormat == VK_FORMAT_D24_UNORM_S8_UINT) {
barrier.subresourceRange.aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
df->vkCmdPipelineBarrier (cmd, stages.src, stages.dst, 0,
0, 0,
0, 0,
1, &barrier);
df->vkEndCommandBuffer (cmd);
VkSubmitInfo submitInfo = {
VK_STRUCTURE_TYPE_SUBMIT_INFO, 0,
0, 0, 0,
1, &cmd,
0, 0
};
df->vkResetFences (dev, 1, &ctx->fence);
df->vkQueueSubmit (device->queue.queue, 1, &submitInfo, ctx->fence);
ctx->renderpass.colorImage = colorImage;
ctx->renderpass.depthImage = depthImage;
}
void
Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
VkDevice dev = device->dev;
qfv_devfuncs_t *df = device->funcs;
df->vkDestroyImageView (dev, ctx->renderpass.colorImage->view, 0);
df->vkDestroyImage (dev, ctx->renderpass.colorImage->image, 0);
df->vkFreeMemory (dev, ctx->renderpass.colorImage->object, 0);
free (ctx->renderpass.colorImage);
ctx->renderpass.colorImage = 0;
df->vkDestroyImageView (dev, ctx->renderpass.depthImage->view, 0);
df->vkDestroyImage (dev, ctx->renderpass.depthImage->image, 0);
df->vkFreeMemory (dev, ctx->renderpass.depthImage->object, 0);
free (ctx->renderpass.depthImage);
ctx->renderpass.depthImage = 0;
}