mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-17 01:11:45 +00:00
Create and destroy render pass and frame buffers
This commit is contained in:
parent
1f4c019abc
commit
ba654b09f7
9 changed files with 212 additions and 89 deletions
|
@ -62,4 +62,6 @@ qfv_instance_t *QFV_CreateInstance (struct vulkan_ctx_s *ctx,
|
|||
const char **extensions);
|
||||
void QFV_DestroyInstance (qfv_instance_t *instance);
|
||||
|
||||
VkSampleCountFlagBits QFV_GetMaxSampleCount (qfv_physdev_t *physdev);
|
||||
|
||||
#endif // __QF_Vulkan_instance_h
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include <vulkan/vulkan.h>
|
||||
|
||||
struct vulkan_ctx_s;
|
||||
void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_CreateSwapchain (struct vulkan_ctx_s *ctx);
|
||||
|
|
|
@ -15,18 +15,8 @@ typedef struct qfv_attachmentreference_s
|
|||
#define QFV_AllocAttachmentReference(num, allocator) \
|
||||
DARRAY_ALLOCFIXED (qfv_attachmentreference_t, num, allocator)
|
||||
|
||||
typedef struct qfv_subpassparameters_s {
|
||||
VkPipelineBindPoint pipelineBindPoint;
|
||||
qfv_attachmentreference_t *inputAttachments;
|
||||
qfv_attachmentreference_t *colorAttachments;
|
||||
qfv_attachmentreference_t *resolveAttachments;
|
||||
VkAttachmentReference *depthStencilAttachment;
|
||||
uint32_t numPreserve;
|
||||
uint32_t *preserveAttachments;
|
||||
} qfv_subpassparameters_t;
|
||||
|
||||
typedef struct qfv_subpassparametersset_s
|
||||
DARRAY_TYPE (qfv_subpassparameters_t) qfv_subpassparametersset_t;
|
||||
DARRAY_TYPE (VkSubpassDescription) qfv_subpassparametersset_t;
|
||||
|
||||
#define QFV_AllocSubpassParametersSet(num, allocator) \
|
||||
DARRAY_ALLOCFIXED (qfv_subpassparametersset_t, num, allocator)
|
||||
|
@ -49,6 +39,6 @@ QFV_CreateFramebuffer (struct qfv_device_s *device,
|
|||
VkRenderPass renderPass,
|
||||
uint32_t numAttachments,
|
||||
VkImageView *attachments,
|
||||
uint32_t width, uint32_t height, uint32_t layers);
|
||||
VkExtent2D, uint32_t layers);
|
||||
|
||||
#endif//__QF_Vulkan_renderpass_h
|
||||
|
|
|
@ -88,6 +88,25 @@
|
|||
ar; \
|
||||
})
|
||||
|
||||
/** Initialized the array.
|
||||
|
||||
The array will be initialized to be empty but with grow set to the
|
||||
specifed value.
|
||||
|
||||
\param array *Address* of the array to be modified (ie, pointer to the
|
||||
array struct instance, not the instance itself: use & for
|
||||
static instances of the array struct).
|
||||
\param growSize Number of elements by which the array is to grow when
|
||||
required.
|
||||
\hideinitializer
|
||||
*/
|
||||
#define DARRAY_INIT(array, growSize) \
|
||||
do { \
|
||||
__auto_type ar = (array); \
|
||||
ar->size = ar->maxSize = 0; \
|
||||
ar->grow = (growSize); \
|
||||
} while (0)
|
||||
|
||||
/** Clear the array.
|
||||
|
||||
If the array can grow, its backing will be freed and maxSize and a reset,
|
||||
|
|
|
@ -6,19 +6,25 @@
|
|||
#endif
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
typedef struct vulkan_frameset_s {
|
||||
int curFrame; // index into fences
|
||||
struct qfv_fenceset_s *fences;
|
||||
struct qfv_cmdbufferset_s *cmdBuffers;
|
||||
struct qfv_semaphoreset_s *imageSemaphores;
|
||||
struct qfv_semaphoreset_s *renderDoneSemaphores;
|
||||
} vulkan_frameset_t;
|
||||
#include "QF/darray.h"
|
||||
|
||||
typedef struct vulkan_renderpass_s {
|
||||
VkRenderPass renderpass;
|
||||
struct qfv_imageresource_s *colorImage;
|
||||
struct qfv_imageresource_s *depthImage;
|
||||
} vulkan_renderpass_t;
|
||||
|
||||
typedef struct vulkan_framebuffer_s {
|
||||
VkFramebuffer framebuffer;
|
||||
VkFence fence;
|
||||
VkSemaphore imageAvailableSemaphore;
|
||||
VkSemaphore renderDoneSemaphore;
|
||||
VkCommandBuffer cmdBuffer;
|
||||
} vulkan_framebuffer_t;
|
||||
|
||||
typedef struct vulkan_framebufferset_s
|
||||
DARRAY_TYPE (vulkan_framebuffer_t) vulkan_framebufferset_t;
|
||||
|
||||
typedef struct vulkan_ctx_s {
|
||||
void (*load_vulkan) (struct vulkan_ctx_s *ctx);
|
||||
void (*unload_vulkan) (struct vulkan_ctx_s *ctx);
|
||||
|
@ -40,8 +46,9 @@ typedef struct vulkan_ctx_s {
|
|||
VkCommandPool cmdpool;
|
||||
VkCommandBuffer cmdbuffer;
|
||||
VkFence fence; // for ctx->cmdbuffer only
|
||||
vulkan_frameset_t frameset;
|
||||
vulkan_renderpass_t renderpass;
|
||||
size_t curFrame;
|
||||
vulkan_framebufferset_t framebuffers;
|
||||
|
||||
#define EXPORTED_VULKAN_FUNCTION(fname) PFN_##fname fname;
|
||||
#define GLOBAL_LEVEL_VULKAN_FUNCTION(fname) PFN_##fname fname;
|
||||
|
|
|
@ -60,13 +60,11 @@ vulkan_R_Init (void)
|
|||
{
|
||||
qfv_device_t *device = vulkan_ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
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;
|
||||
Vulkan_CreateFramebuffers (vulkan_ctx);
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo
|
||||
= { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
VkClearColorValue clearColor = { {0.7294, 0.8549, 0.3333, 1.0} };
|
||||
|
@ -96,29 +94,30 @@ vulkan_R_Init (void)
|
|||
0, // filled in later
|
||||
image_subresource_range
|
||||
};
|
||||
for (size_t i = 0; i < cmdBuffers->size; i++) {
|
||||
for (size_t i = 0; i < vulkan_ctx->framebuffers.size; i++) {
|
||||
__auto_type framebuffer = &vulkan_ctx->framebuffers.a[i];
|
||||
pc_barrier.image = vulkan_ctx->swapchain->images->a[i];
|
||||
cp_barrier.image = vulkan_ctx->swapchain->images->a[i];
|
||||
dfunc->vkBeginCommandBuffer (cmdBuffers->a[i], &beginInfo);
|
||||
dfunc->vkCmdPipelineBarrier (cmdBuffers->a[i],
|
||||
dfunc->vkBeginCommandBuffer (framebuffer->cmdBuffer, &beginInfo);
|
||||
dfunc->vkCmdPipelineBarrier (framebuffer->cmdBuffer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
0,
|
||||
0, 0, // memory barriers
|
||||
0, 0, // buffer barriers
|
||||
1, &pc_barrier);
|
||||
dfunc->vkCmdClearColorImage (cmdBuffers->a[i], pc_barrier.image,
|
||||
dfunc->vkCmdClearColorImage (framebuffer->cmdBuffer, pc_barrier.image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
&clearColor, 1,
|
||||
&image_subresource_range);
|
||||
dfunc->vkCmdPipelineBarrier (cmdBuffers->a[i],
|
||||
dfunc->vkCmdPipelineBarrier (framebuffer->cmdBuffer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
1, &cp_barrier);
|
||||
dfunc->vkEndCommandBuffer (cmdBuffers->a[i]);
|
||||
dfunc->vkEndCommandBuffer (framebuffer->cmdBuffer);
|
||||
}
|
||||
Sys_Printf ("R_Init %p %d", vulkan_ctx->swapchain->swapchain,
|
||||
vulkan_ctx->swapchain->numImages);
|
||||
|
@ -138,38 +137,38 @@ vulkan_SCR_UpdateScreen (double time, void (*f)(void), void (**g)(void))
|
|||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
VkDevice dev = device->dev;
|
||||
qfv_queue_t *queue = &vulkan_ctx->device->queue;
|
||||
vulkan_frameset_t *frameset = &vulkan_ctx->frameset;
|
||||
|
||||
dfunc->vkWaitForFences (dev, 1, &frameset->fences->a[frameset->curFrame],
|
||||
VK_TRUE, 2000000000);
|
||||
__auto_type framebuffer
|
||||
= &vulkan_ctx->framebuffers.a[vulkan_ctx->curFrame];
|
||||
|
||||
dfunc->vkWaitForFences (dev, 1, &framebuffer->fence, VK_TRUE, 2000000000);
|
||||
QFV_AcquireNextImage (vulkan_ctx->swapchain,
|
||||
frameset->imageSemaphores->a[frameset->curFrame],
|
||||
0, &imageIndex);
|
||||
framebuffer->imageAvailableSemaphore,
|
||||
0, &imageIndex);
|
||||
|
||||
VkPipelineStageFlags waitStage
|
||||
= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo submitInfo = {
|
||||
VK_STRUCTURE_TYPE_SUBMIT_INFO, 0,
|
||||
1,
|
||||
&frameset->imageSemaphores->a[frameset->curFrame],
|
||||
&framebuffer->imageAvailableSemaphore,
|
||||
&waitStage,
|
||||
1, &frameset->cmdBuffers->a[imageIndex],
|
||||
1, &frameset->renderDoneSemaphores->a[frameset->curFrame],
|
||||
1, &framebuffer->cmdBuffer,
|
||||
1, &framebuffer->renderDoneSemaphore,
|
||||
};
|
||||
dfunc->vkResetFences (dev, 1, &frameset->fences->a[frameset->curFrame]);
|
||||
dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo,
|
||||
frameset->fences->a[frameset->curFrame]);
|
||||
dfunc->vkResetFences (dev, 1, &framebuffer->fence);
|
||||
dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, framebuffer->fence);
|
||||
|
||||
VkPresentInfoKHR presentInfo = {
|
||||
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0,
|
||||
1, &frameset->renderDoneSemaphores->a[frameset->curFrame],
|
||||
1, &framebuffer->renderDoneSemaphore,
|
||||
1, &vulkan_ctx->swapchain->swapchain, &imageIndex,
|
||||
0
|
||||
};
|
||||
dfunc->vkQueuePresentKHR (queue->queue, &presentInfo);
|
||||
|
||||
frameset->curFrame++;
|
||||
frameset->curFrame %= frameset->fences->size;
|
||||
vulkan_ctx->curFrame++;
|
||||
vulkan_ctx->curFrame %= vulkan_ctx->framebuffers.size;
|
||||
|
||||
if (++count >= 100) {
|
||||
double currenTime = Sys_DoubleTime ();
|
||||
|
@ -311,19 +310,6 @@ vulkan_vid_render_create_context (void)
|
|||
{
|
||||
vulkan_ctx->create_window (vulkan_ctx);
|
||||
vulkan_ctx->surface = vulkan_ctx->create_surface (vulkan_ctx);
|
||||
vulkan_ctx->frameset.curFrame = 0;
|
||||
qfv_fenceset_t *fences = DARRAY_ALLOCFIXED (*fences, 2, malloc);
|
||||
qfv_semaphoreset_t *imageSems = DARRAY_ALLOCFIXED (*imageSems, 2, malloc);
|
||||
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);
|
||||
imageSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device);
|
||||
renderDoneSems->a[i] = QFV_CreateSemaphore (vulkan_ctx->device);
|
||||
}
|
||||
vulkan_ctx->frameset.fences = fences;
|
||||
vulkan_ctx->frameset.imageSemaphores = imageSems;
|
||||
vulkan_ctx->frameset.renderDoneSemaphores = renderDoneSems;
|
||||
Sys_Printf ("vk create context %p\n", vulkan_ctx->surface);
|
||||
}
|
||||
|
||||
|
@ -350,12 +336,6 @@ vulkan_vid_render_shutdown (void)
|
|||
qfv_devfuncs_t *df = device->funcs;
|
||||
VkDevice dev = device->dev;
|
||||
QFV_DeviceWaitIdle (device);
|
||||
vulkan_frameset_t *frameset = &vulkan_ctx->frameset;
|
||||
for (size_t i = 0; i < frameset->fences->size; i++) {
|
||||
df->vkDestroyFence (dev, frameset->fences->a[i], 0);
|
||||
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);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "QF/cvar.h"
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/input.h"
|
||||
#include "QF/mathlib.h"
|
||||
#include "QF/qargs.h"
|
||||
#include "QF/quakefs.h"
|
||||
#include "QF/sys.h"
|
||||
|
@ -284,3 +285,17 @@ QFV_DestroyInstance (qfv_instance_t *instance)
|
|||
instance->funcs->vkDestroyInstance (instance->instance, 0);
|
||||
free (instance);
|
||||
}
|
||||
|
||||
VkSampleCountFlagBits
|
||||
QFV_GetMaxSampleCount (qfv_physdev_t *physdev)
|
||||
{
|
||||
VkSampleCountFlagBits maxSamples = VK_SAMPLE_COUNT_64_BIT;
|
||||
VkSampleCountFlagBits counts;
|
||||
counts = min (physdev->properties.limits.framebufferColorSampleCounts,
|
||||
physdev->properties.limits.framebufferDepthSampleCounts);
|
||||
while (maxSamples && maxSamples > counts) {
|
||||
maxSamples >>= 1;
|
||||
}
|
||||
Sys_MaskPrintf (SYS_VULKAN, "Max samples: %x\n", maxSamples);
|
||||
return maxSamples;
|
||||
}
|
||||
|
|
|
@ -71,29 +71,10 @@ QFV_CreateRenderPass (qfv_device_t *device,
|
|||
VkDevice dev = device->dev;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
VkSubpassDescription *subpasses = alloca (subpassparams->size
|
||||
* sizeof (*subpasses));
|
||||
|
||||
for (uint32_t i = 0; i < subpassparams->size; i++) {
|
||||
qfv_subpassparameters_t *params = &subpassparams->a[i];
|
||||
subpasses[i].flags = 0;
|
||||
subpasses[i].pipelineBindPoint = params->pipelineBindPoint;
|
||||
subpasses[i].inputAttachmentCount = params->inputAttachments->size;
|
||||
subpasses[i].pInputAttachments = params->inputAttachments->a;
|
||||
subpasses[i].colorAttachmentCount = params->colorAttachments->size;
|
||||
subpasses[i].pColorAttachments = params->colorAttachments->a;
|
||||
if (params->resolveAttachments) {
|
||||
subpasses[i].pResolveAttachments = params->resolveAttachments->a;
|
||||
}
|
||||
subpasses[i].pDepthStencilAttachment = params->depthStencilAttachment;
|
||||
subpasses[i].preserveAttachmentCount = params->numPreserve;
|
||||
subpasses[i].pPreserveAttachments = params->preserveAttachments;
|
||||
}
|
||||
|
||||
VkRenderPassCreateInfo createInfo = {
|
||||
VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, 0, 0,
|
||||
attachments->size, attachments->a,
|
||||
subpassparams->size, subpasses,
|
||||
subpassparams->size, subpassparams->a,
|
||||
dependencies->size, dependencies->a,
|
||||
};
|
||||
|
||||
|
@ -105,7 +86,7 @@ QFV_CreateRenderPass (qfv_device_t *device,
|
|||
VkFramebuffer
|
||||
QFV_CreateFramebuffer (qfv_device_t *device, VkRenderPass renderPass,
|
||||
uint32_t numAttachments, VkImageView *attachments,
|
||||
uint32_t width, uint32_t height, uint32_t layers)
|
||||
VkExtent2D extent, uint32_t layers)
|
||||
{
|
||||
VkDevice dev = device->dev;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
@ -113,7 +94,7 @@ QFV_CreateFramebuffer (qfv_device_t *device, VkRenderPass renderPass,
|
|||
VkFramebufferCreateInfo createInfo = {
|
||||
VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, 0, 0,
|
||||
renderPass, numAttachments, attachments,
|
||||
width, height, layers,
|
||||
extent.width, extent.height, layers,
|
||||
};
|
||||
|
||||
VkFramebuffer framebuffer;
|
||||
|
|
|
@ -50,8 +50,10 @@
|
|||
#include "QF/vid.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/device.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
#include "QF/Vulkan/instance.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/Vulkan/renderpass.h"
|
||||
#include "QF/Vulkan/swapchain.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
@ -117,6 +119,9 @@ Vulkan_Init_Common (vulkan_ctx_t *ctx)
|
|||
void
|
||||
Vulkan_Shutdown_Common (vulkan_ctx_t *ctx)
|
||||
{
|
||||
if (ctx->framebuffers.size) {
|
||||
Vulkan_DestroyFramebuffers (ctx);
|
||||
}
|
||||
if (ctx->renderpass.colorImage) {
|
||||
Vulkan_DestroyRenderPass (ctx);
|
||||
}
|
||||
|
@ -241,11 +246,13 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
|
|||
|
||||
VkExtent3D extent = {sc->extent.width, sc->extent.height, 1};
|
||||
|
||||
VkSampleCountFlagBits msaaSamples
|
||||
= QFV_GetMaxSampleCount (device->physDev);
|
||||
|
||||
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
|
||||
sc->format, extent, 1, 1, msaaSamples,
|
||||
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT
|
||||
| VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
|
||||
colorImage->object
|
||||
|
@ -263,8 +270,7 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
|
|||
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?!?)
|
||||
depthFormat, extent, 1, 1, msaaSamples,
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
|
||||
depthImage->object
|
||||
= QFV_AllocImageMemory (device, depthImage->image,
|
||||
|
@ -322,6 +328,72 @@ Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
|
|||
|
||||
ctx->renderpass.colorImage = colorImage;
|
||||
ctx->renderpass.depthImage = depthImage;
|
||||
|
||||
__auto_type attachments = QFV_AllocAttachmentDescription (3, alloca);
|
||||
__auto_type attachmentRefs = QFV_AllocAttachmentReference (3, alloca);
|
||||
|
||||
// color attachment
|
||||
attachments->a[0].flags = 0;
|
||||
attachments->a[0].format = sc->format;
|
||||
attachments->a[0].samples = msaaSamples;
|
||||
attachments->a[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments->a[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments->a[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments->a[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments->a[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments->a[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
attachmentRefs->a[0].attachment = 0;
|
||||
attachmentRefs->a[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
// depth attachment
|
||||
attachments->a[1].flags = 0;
|
||||
attachments->a[1].format = depthFormat;
|
||||
attachments->a[1].samples = msaaSamples;
|
||||
attachments->a[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments->a[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments->a[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments->a[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments->a[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments->a[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
attachmentRefs->a[1].attachment = 1;
|
||||
attachmentRefs->a[1].layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
|
||||
// resolve attachment
|
||||
attachments->a[2].flags = 0;
|
||||
attachments->a[2].format = sc->format;
|
||||
attachments->a[2].samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
attachments->a[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
attachments->a[2].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
attachments->a[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
attachments->a[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
|
||||
attachments->a[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
attachments->a[2].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
||||
attachmentRefs->a[2].attachment = 2;
|
||||
attachmentRefs->a[2].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
|
||||
__auto_type subpasses = QFV_AllocSubpassParametersSet (1, alloca);
|
||||
subpasses->a[0].flags = 0;
|
||||
subpasses->a[0].pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
|
||||
subpasses->a[0].inputAttachmentCount = 0;
|
||||
subpasses->a[0].pInputAttachments = 0;
|
||||
subpasses->a[0].colorAttachmentCount = 1;
|
||||
subpasses->a[0].pColorAttachments = &attachmentRefs->a[0];
|
||||
subpasses->a[0].pResolveAttachments = &attachmentRefs->a[2];
|
||||
subpasses->a[0].pDepthStencilAttachment = &attachmentRefs->a[1];
|
||||
subpasses->a[0].preserveAttachmentCount = 0;
|
||||
subpasses->a[0].pPreserveAttachments = 0;
|
||||
|
||||
__auto_type depenencies = QFV_AllocSubpassDependencies (1, alloca);
|
||||
depenencies->a[0].srcSubpass = VK_SUBPASS_EXTERNAL;
|
||||
depenencies->a[0].dstSubpass = 0;
|
||||
depenencies->a[0].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
depenencies->a[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
depenencies->a[0].srcAccessMask = 0;
|
||||
depenencies->a[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
|
||||
depenencies->a[0].dependencyFlags = 0;
|
||||
|
||||
ctx->renderpass.renderpass = QFV_CreateRenderPass (device, attachments,
|
||||
subpasses, depenencies);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -331,6 +403,8 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx)
|
|||
VkDevice dev = device->dev;
|
||||
qfv_devfuncs_t *df = device->funcs;
|
||||
|
||||
df->vkDestroyRenderPass (dev, ctx->renderpass.renderpass, 0);
|
||||
|
||||
df->vkDestroyImageView (dev, ctx->renderpass.colorImage->view, 0);
|
||||
df->vkDestroyImage (dev, ctx->renderpass.colorImage->image, 0);
|
||||
df->vkFreeMemory (dev, ctx->renderpass.colorImage->object, 0);
|
||||
|
@ -343,3 +417,56 @@ Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx)
|
|||
free (ctx->renderpass.depthImage);
|
||||
ctx->renderpass.depthImage = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
VkCommandPool cmdpool = ctx->cmdpool;
|
||||
qfv_swapchain_t *sc = ctx->swapchain;
|
||||
VkRenderPass renderpass = ctx->renderpass.renderpass;
|
||||
|
||||
if (!ctx->framebuffers.grow) {
|
||||
DARRAY_INIT (&ctx->framebuffers, 4);
|
||||
}
|
||||
|
||||
DARRAY_RESIZE (&ctx->framebuffers, sc->numImages);
|
||||
|
||||
__auto_type attachments = DARRAY_ALLOCFIXED (qfv_imageviewset_t, 3,
|
||||
alloca);
|
||||
attachments->a[0] = ctx->renderpass.colorImage->view;
|
||||
attachments->a[1] = ctx->renderpass.depthImage->view;
|
||||
|
||||
__auto_type cmdBuffers
|
||||
= QFV_AllocateCommandBuffers (device, cmdpool, 0,
|
||||
ctx->framebuffers.size);
|
||||
|
||||
for (size_t i = 0; i < ctx->framebuffers.size; i++) {
|
||||
attachments->a[2] = sc->imageViews->a[i];
|
||||
__auto_type frame = &ctx->framebuffers.a[i];
|
||||
frame->framebuffer = QFV_CreateFramebuffer (device, renderpass,
|
||||
attachments->size,
|
||||
attachments->a,
|
||||
sc->extent, 1);
|
||||
frame->fence = QFV_CreateFence (device, 1);
|
||||
frame->imageAvailableSemaphore = QFV_CreateSemaphore (device);
|
||||
frame->renderDoneSemaphore = QFV_CreateSemaphore (device);
|
||||
frame->cmdBuffer = cmdBuffers->a[i];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *df = device->funcs;
|
||||
VkDevice dev = device->dev;
|
||||
|
||||
for (size_t i = 0; i < ctx->framebuffers.size; i++) {
|
||||
__auto_type frame = &ctx->framebuffers.a[i];
|
||||
df->vkDestroyFence (dev, frame->fence, 0);
|
||||
df->vkDestroySemaphore (dev, frame->imageAvailableSemaphore, 0);
|
||||
df->vkDestroySemaphore (dev, frame->renderDoneSemaphore, 0);
|
||||
df->vkDestroyFramebuffer (dev, frame->framebuffer, 0);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue