mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 23:11:38 +00:00
Create and destroy color/depth resources
This commit is contained in:
parent
89d48b5650
commit
1f4c019abc
6 changed files with 235 additions and 4 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue