mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-19 15:30:50 +00:00
[vulkan] Get the output step working for draw
It leaks command buffers (due to a misunderstanding of vkResetCommandPool), but it seems 2d draw (sliced quads) is working nicely.
This commit is contained in:
parent
3de39f5408
commit
6deeed1829
9 changed files with 236 additions and 443 deletions
|
@ -87,8 +87,6 @@ int Vulkan_Draw_AddFont (struct font_s *font, struct vulkan_ctx_s *ctx);
|
|||
void Vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c,
|
||||
struct vulkan_ctx_s *ctx);
|
||||
|
||||
void Vulkan_FlushText (struct qfv_renderframe_s *rFrame);
|
||||
|
||||
void Vulkan_LineGraph (int x, int y, int *h_vals, int count, int height,
|
||||
struct vulkan_ctx_s *ctx);
|
||||
|
||||
|
|
|
@ -84,8 +84,6 @@ void Vulkan_SetSkyMatrix (struct vulkan_ctx_s *ctx, mat4f_t sky);
|
|||
|
||||
void Vulkan_Matrix_Init (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Matrix_Shutdown (struct vulkan_ctx_s *ctx);
|
||||
// "Draw" :)
|
||||
void Vulkan_Matrix_Draw (struct qfv_renderframe_s *rFrame);
|
||||
VkDescriptorSet Vulkan_Matrix_Descriptors (struct vulkan_ctx_s *ctx, int frame)
|
||||
__attribute__((pure));
|
||||
|
||||
|
|
|
@ -307,34 +307,6 @@ vulkan_Draw_Glyph (int x, int y, int fontid, int glyphid, int c)
|
|||
{
|
||||
Vulkan_Draw_Glyph (x, y, fontid, glyphid, c, vulkan_ctx);
|
||||
}
|
||||
//#define TEST_RENDER
|
||||
#ifndef TEST_RENDER
|
||||
static void
|
||||
vulkan_begin_frame (void)
|
||||
{
|
||||
qfv_device_t *device = vulkan_ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
VkDevice dev = device->dev;
|
||||
|
||||
__auto_type frame = &vulkan_ctx->frames.a[vulkan_ctx->curFrame];
|
||||
|
||||
dfunc->vkWaitForFences (dev, 1, &frame->fence, VK_TRUE, 2000000000);
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_render_view (void)
|
||||
{
|
||||
for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) {
|
||||
__auto_type rp = vulkan_ctx->renderPasses.a[i];
|
||||
__auto_type rpFrame = &rp->frames.a[vulkan_ctx->curFrame];
|
||||
// swapImageIndex may be updated by a render pass
|
||||
uint32_t imageIndex = vulkan_ctx->swapImageIndex;
|
||||
if (rp->framebuffers) {
|
||||
rpFrame->framebuffer = rp->framebuffers->a[imageIndex];
|
||||
}
|
||||
rp->draw (rpFrame);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_set_2d (int scaled)
|
||||
|
@ -353,153 +325,15 @@ vulkan_set_2d (int scaled)
|
|||
mctx->dirty = mctx->frames.size;
|
||||
}
|
||||
|
||||
static void
|
||||
vulkan_end_frame (void)
|
||||
{
|
||||
qfv_device_t *device = vulkan_ctx->device;
|
||||
VkDevice dev = device->dev;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
qfv_queue_t *queue = &device->queue;
|
||||
uint32_t curFrame = vulkan_ctx->curFrame;
|
||||
__auto_type frame = &vulkan_ctx->frames.a[curFrame];
|
||||
uint32_t imageIndex = vulkan_ctx->swapImageIndex;
|
||||
|
||||
VkCommandBufferBeginInfo beginInfo
|
||||
= { VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
|
||||
|
||||
__auto_type cmdBufs = (qfv_cmdbufferset_t) DARRAY_STATIC_INIT (4);
|
||||
DARRAY_APPEND (&cmdBufs, frame->cmdBuffer);
|
||||
|
||||
dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo);
|
||||
for (size_t i = 0; i < vulkan_ctx->renderPasses.size; i++) {
|
||||
__auto_type rp = vulkan_ctx->renderPasses.a[i];
|
||||
__auto_type rpFrame = &rp->frames.a[curFrame];
|
||||
|
||||
if (rp->primary_commands) {
|
||||
for (int j = 0; j < rpFrame->subpassCount; j++) {
|
||||
__auto_type cmdSet = &rpFrame->subpassCmdSets[j];
|
||||
size_t base = cmdBufs.size;
|
||||
DARRAY_RESIZE (&cmdBufs, base + cmdSet->size);
|
||||
memcpy (&cmdBufs.a[base], cmdSet->a,
|
||||
cmdSet->size * sizeof (VkCommandBuffer));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
QFV_CmdBeginLabel (device, frame->cmdBuffer, rp->name, rp->color);
|
||||
if (rpFrame->renderpass && rp->renderpass) {
|
||||
VkRenderPassBeginInfo renderPassInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||
.renderPass = rp->renderpass,
|
||||
.framebuffer = rp->framebuffers->a[imageIndex],
|
||||
.renderArea = rp->renderArea,
|
||||
.clearValueCount = rp->clearValues->size,
|
||||
.pClearValues = rp->clearValues->a,
|
||||
};
|
||||
|
||||
dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo,
|
||||
rpFrame->subpassContents);
|
||||
|
||||
for (int j = 0; j < rpFrame->subpassCount; j++) {
|
||||
__auto_type cmdSet = &rpFrame->subpassCmdSets[j];
|
||||
if (cmdSet->size) {
|
||||
QFV_CmdBeginLabel (device, frame->cmdBuffer,
|
||||
rpFrame->subpassInfo[j].name,
|
||||
rpFrame->subpassInfo[j].color);
|
||||
dfunc->vkCmdExecuteCommands (frame->cmdBuffer,
|
||||
cmdSet->size, cmdSet->a);
|
||||
QFV_CmdEndLabel (device, frame->cmdBuffer);
|
||||
}
|
||||
// reset for next time around
|
||||
cmdSet->size = 0;
|
||||
|
||||
//Regardless of whether any commands were submitted for this
|
||||
//subpass, must step through each and every subpass, otherwise
|
||||
//the attachments won't be transitioned correctly.
|
||||
if (j < rpFrame->subpassCount - 1) {
|
||||
dfunc->vkCmdNextSubpass (frame->cmdBuffer,
|
||||
rpFrame->subpassContents);
|
||||
}
|
||||
}
|
||||
dfunc->vkCmdEndRenderPass (frame->cmdBuffer);
|
||||
} else {
|
||||
for (int j = 0; j < rpFrame->subpassCount; j++) {
|
||||
__auto_type cmdSet = &rpFrame->subpassCmdSets[j];
|
||||
if (cmdSet->size) {
|
||||
dfunc->vkCmdExecuteCommands (frame->cmdBuffer,
|
||||
cmdSet->size, cmdSet->a);
|
||||
}
|
||||
// reset for next time around
|
||||
cmdSet->size = 0;
|
||||
}
|
||||
}
|
||||
QFV_CmdEndLabel (device, frame->cmdBuffer);
|
||||
}
|
||||
|
||||
if (vulkan_ctx->capture_callback) {
|
||||
VkImage srcImage = vulkan_ctx->swapchain->images->a[imageIndex];
|
||||
VkCommandBuffer cmd = QFV_CaptureImage (vulkan_ctx->capture, srcImage,
|
||||
curFrame);
|
||||
dfunc->vkCmdExecuteCommands (frame->cmdBuffer, 1, &cmd);
|
||||
}
|
||||
dfunc->vkEndCommandBuffer (frame->cmdBuffer);
|
||||
|
||||
VkPipelineStageFlags waitStage
|
||||
= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
VkSubmitInfo submitInfo = {
|
||||
VK_STRUCTURE_TYPE_SUBMIT_INFO, 0,
|
||||
1, &frame->imageAvailableSemaphore, &waitStage,
|
||||
cmdBufs.size, cmdBufs.a,
|
||||
1, &frame->renderDoneSemaphore,
|
||||
};
|
||||
dfunc->vkResetFences (dev, 1, &frame->fence);
|
||||
dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence);
|
||||
|
||||
DARRAY_CLEAR (&cmdBufs);
|
||||
|
||||
if (vulkan_ctx->capture_callback) {
|
||||
//FIXME look into "threading" this rather than waiting here
|
||||
dfunc->vkWaitForFences (device->dev, 1, &frame->fence, VK_TRUE,
|
||||
1000000000ull);
|
||||
vulkan_ctx->capture_callback (QFV_CaptureData (vulkan_ctx->capture,
|
||||
curFrame),
|
||||
vulkan_ctx->capture->extent.width,
|
||||
vulkan_ctx->capture->extent.height);
|
||||
vulkan_ctx->capture_callback = 0;
|
||||
}
|
||||
|
||||
VkPresentInfoKHR presentInfo = {
|
||||
VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, 0,
|
||||
1, &frame->renderDoneSemaphore,
|
||||
1, &vulkan_ctx->swapchain->swapchain, &imageIndex,
|
||||
0
|
||||
};
|
||||
dfunc->vkQueuePresentKHR (queue->queue, &presentInfo);
|
||||
|
||||
vulkan_ctx->curFrame++;
|
||||
vulkan_ctx->curFrame %= vulkan_ctx->frames.size;
|
||||
}
|
||||
#endif
|
||||
static void
|
||||
vulkan_UpdateScreen (transform_t camera, double realtime, SCR_Func *scr_funcs)
|
||||
{
|
||||
#ifdef TEST_RENDER
|
||||
vulkan_set_2d (1);//FIXME
|
||||
while (*scr_funcs) {
|
||||
(*scr_funcs) ();
|
||||
scr_funcs++;
|
||||
}
|
||||
QFV_RunRenderJob (vulkan_ctx);
|
||||
#else
|
||||
EntQueue_Clear (r_ent_queue);
|
||||
vulkan_begin_frame ();
|
||||
vulkan_set_2d (1);
|
||||
while (*scr_funcs) {
|
||||
(*scr_funcs) ();
|
||||
scr_funcs++;
|
||||
}
|
||||
vulkan_render_view ();
|
||||
vulkan_end_frame ();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -137,7 +137,7 @@ run_subpass (qfv_subpass_t *sp, VkCommandBuffer cmd, vulkan_ctx_t *ctx)
|
|||
static void
|
||||
run_renderpass (qfv_renderpass_t *rp, vulkan_ctx_t *ctx)
|
||||
{
|
||||
printf ("%10.2f run_renderpass: %s\n", Sys_DoubleTime (), rp->label.name);
|
||||
//printf ("%10.2f run_renderpass: %s\n", Sys_DoubleTime (), rp->label.name);
|
||||
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
@ -177,7 +177,7 @@ static void
|
|||
run_compute_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd,
|
||||
vulkan_ctx_t *ctx)
|
||||
{
|
||||
printf ("run_compute_pipeline: %s\n", pipeline->label.name);
|
||||
//printf ("run_compute_pipeline: %s\n", pipeline->label.name);
|
||||
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
@ -242,7 +242,7 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx)
|
|||
|
||||
for (uint32_t i = 0; i < job->num_steps; i++) {
|
||||
__auto_type step = &job->steps[i];
|
||||
printf ("%10.2f run_step: %s\n", Sys_DoubleTime (), step->label.name);
|
||||
//printf ("%10.2f run_step: %s\n", Sys_DoubleTime (), step->label.name);
|
||||
if (step->render) {
|
||||
run_renderpass (step->render->active, ctx);
|
||||
}
|
||||
|
@ -266,8 +266,8 @@ QFV_RunRenderJob (vulkan_ctx_t *ctx)
|
|||
job->commands.size, job->commands.a,
|
||||
1, &frame->renderDoneSemaphore,
|
||||
};
|
||||
printf ("%10.2f submit for frame %d: %zd %p\n", Sys_DoubleTime (),
|
||||
ctx->curFrame, job->commands.size, frame->imageAvailableSemaphore);
|
||||
//printf ("%10.2f submit for frame %d: %zd %p\n", Sys_DoubleTime (),
|
||||
// ctx->curFrame, job->commands.size, frame->imageAvailableSemaphore);
|
||||
dfunc->vkResetFences (device->dev, 1, &frame->fence);
|
||||
dfunc->vkQueueSubmit (queue->queue, 1, &submitInfo, frame->fence);
|
||||
|
||||
|
@ -361,7 +361,7 @@ wait_on_fence (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
|||
auto job = ctx->render_context->job;
|
||||
job->command_pool = frame->command_pool;
|
||||
dfunc->vkResetCommandPool (device->dev, job->command_pool, 0);
|
||||
DARRAY_CLEAR (&job->commands);
|
||||
DARRAY_RESIZE (&job->commands, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -11,6 +11,7 @@ properties = {
|
|||
output = "[0.0, 0.7, 0.7, 1]";
|
||||
waterwarp = "[0.0, 0.7, 0.7, 1]";
|
||||
fisheye = "[0.0, 0.7, 0.7, 1]";
|
||||
slice = "[0.8, 0.7, 0.2, 1]";
|
||||
};
|
||||
color_dependency = {
|
||||
src = {
|
||||
|
@ -549,6 +550,42 @@ properties = {
|
|||
};
|
||||
};
|
||||
};
|
||||
slice = {
|
||||
shader = {
|
||||
vertex = {
|
||||
stage = vertex;
|
||||
name = main;
|
||||
module = $builtin/slice.vert;
|
||||
};
|
||||
fragment = {
|
||||
stage = fragment;
|
||||
name = main;
|
||||
module = $builtin/twod.frag;
|
||||
};
|
||||
};
|
||||
vertexInput = {
|
||||
bindings = (
|
||||
{ binding = 0; stride = "4 + 4 + 4*4"; inputRate = instance; },
|
||||
);
|
||||
attributes = (
|
||||
// 9-slice index
|
||||
{ location = 0; binding = 0; format = r32_uint; offset = 0; },
|
||||
// 9-slice color
|
||||
{ location = 1; binding = 0; format = r8g8b8a8_unorm; offset = 4; },
|
||||
// 9-slice position (2d)
|
||||
{ location = 2; binding = 0; format = r32g32_sfloat; offset = 8; },
|
||||
// 9-slice size delta (2d)
|
||||
{ location = 3; binding = 0; format = r32g32_sfloat; offset = 16; },
|
||||
);
|
||||
};
|
||||
inputAssembly = {
|
||||
topology = triangle_strip;
|
||||
primitiveRestartEnable = true;
|
||||
};
|
||||
layout = {
|
||||
descriptorSets = (matrix_set, quad_data_set);
|
||||
};
|
||||
};
|
||||
};
|
||||
descriptorSetLayouts = {
|
||||
matrix_set = {
|
||||
|
@ -1271,6 +1308,22 @@ renderpasses = {
|
|||
);
|
||||
layout = $output.layout;
|
||||
};
|
||||
slice = {
|
||||
@inherit = $compose_base;
|
||||
|
||||
color = $color.slice;
|
||||
tasks = (
|
||||
{ func = slice_draw; },
|
||||
);
|
||||
|
||||
stages = (
|
||||
$slice.shader.vertex,
|
||||
$slice.shader.fragment,
|
||||
);
|
||||
vertexInput = $slice.vertexInput;
|
||||
inputAssembly = $slice.inputAssembly;
|
||||
layout = $slice.layout;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -1281,9 +1334,11 @@ steps = {
|
|||
process = {
|
||||
tasks = (
|
||||
{ func = wait_on_fence; },
|
||||
{ func = update_matrices; },
|
||||
);
|
||||
};
|
||||
};
|
||||
/*
|
||||
particles = {
|
||||
dependencies = (wait_on_fence);
|
||||
compute = {
|
||||
|
@ -1342,6 +1397,7 @@ steps = {
|
|||
};
|
||||
};
|
||||
};
|
||||
*/
|
||||
preoutput = {
|
||||
dependencies = (wait_on_fence);
|
||||
process = {
|
||||
|
@ -1349,6 +1405,7 @@ steps = {
|
|||
{ func = acquire_output;
|
||||
params = ("\"output\""); },
|
||||
{ func = update_input; },
|
||||
{ func = flush_draw; },
|
||||
);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -72,14 +72,6 @@
|
|||
#include "r_internal.h"
|
||||
#include "vid_vulkan.h"
|
||||
|
||||
static const char * __attribute__((used)) draw_pass_names[] = {
|
||||
"2d",
|
||||
};
|
||||
|
||||
static QFV_Subpass subpass_map[] = {
|
||||
[QFV_draw2d] = 0,
|
||||
};
|
||||
|
||||
typedef struct pic_data_s {
|
||||
uint32_t vert_index;
|
||||
uint32_t slice_index;
|
||||
|
@ -875,9 +867,161 @@ load_white_pic (vulkan_ctx_t *ctx)
|
|||
dctx->white_pic, ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_quads (vulkan_ctx_t *ctx, VkCommandBuffer cmd)
|
||||
{
|
||||
auto device = ctx->device;
|
||||
auto dfunc = device->funcs;
|
||||
auto dctx = ctx->draw_context;
|
||||
auto dframe = &dctx->frames.a[ctx->curFrame];
|
||||
|
||||
VkBuffer instance_buffer = dframe->instance_buffer;
|
||||
VkDeviceSize offsets[] = {0};
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &instance_buffer, offsets);
|
||||
|
||||
VkBuffer ind_buffer = dctx->index_object[0].buffer.buffer;
|
||||
dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
uint32_t inst_start = 0;
|
||||
for (size_t i = 0; i < dframe->quad_batch.size; i++) {
|
||||
int fontid = dframe->quad_batch.a[i].descid;
|
||||
uint32_t inst_count = dframe->quad_batch.a[i].count;
|
||||
uint32_t ind_count = inst_count >> 24;
|
||||
inst_count &= 0xffffff;
|
||||
VkDescriptorSet set[2] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
fontid < 0 ? dframe->dyn_descs.sets[~fontid]
|
||||
: dctx->fonts.a[fontid].set,
|
||||
};
|
||||
VkPipelineLayout layout = dctx->quad_layout;
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
layout, 0, 2, set, 0, 0);
|
||||
|
||||
dfunc->vkCmdDrawIndexed (cmd, ind_count, inst_count, 0, 0, inst_start);
|
||||
inst_start += inst_count;
|
||||
}
|
||||
DARRAY_RESIZE (&dframe->quad_batch, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_lines (vulkan_ctx_t *ctx, VkCommandBuffer cmd)
|
||||
{
|
||||
auto device = ctx->device;
|
||||
auto dfunc = device->funcs;
|
||||
auto dctx = ctx->draw_context;
|
||||
auto dframe = &dctx->frames.a[ctx->curFrame];
|
||||
|
||||
VkBuffer line_buffer = dframe->line_buffer;
|
||||
VkDeviceSize offsets[] = {0};
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &line_buffer, offsets);
|
||||
VkDescriptorSet set[1] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
};
|
||||
VkPipelineLayout layout = dctx->lines_layout;
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
layout, 0, 1, set, 0, 0);
|
||||
dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE,
|
||||
1, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
flush_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||
{
|
||||
auto taskctx = (qfv_taskctx_t *) ectx;
|
||||
auto ctx = taskctx->ctx;
|
||||
flush_draw_scrap (ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
slice_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||
{
|
||||
auto taskctx = (qfv_taskctx_t *) ectx;
|
||||
auto ctx = taskctx->ctx;
|
||||
auto device = ctx->device;
|
||||
auto dfunc = device->funcs;
|
||||
auto dctx = ctx->draw_context;
|
||||
auto dframe = &dctx->frames.a[ctx->curFrame];
|
||||
if (!dframe->quad_insts.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
VkDeviceMemory memory = dctx->draw_resource[1].memory;
|
||||
size_t atom = device->physDev->properties->limits.nonCoherentAtomSize;
|
||||
size_t atom_mask = atom - 1;
|
||||
#define a(x) (((x) + atom_mask) & ~atom_mask)
|
||||
VkMappedMemoryRange ranges[] = {
|
||||
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
memory, dframe->instance_offset,
|
||||
a(dframe->quad_insts.count * BYTES_PER_QUAD) },
|
||||
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
memory, dframe->dvert_offset,
|
||||
a(dframe->dvertex_index * sizeof (quadvert_t)) },
|
||||
};
|
||||
#undef a
|
||||
dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges);
|
||||
|
||||
draw_quads (ctx, taskctx->cmd);
|
||||
|
||||
dframe->quad_insts.count = 0;
|
||||
dframe->dvertex_index = 0;
|
||||
dframe->dyn_descs.in_use = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
line_draw (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||
{
|
||||
auto taskctx = (qfv_taskctx_t *) ectx;
|
||||
auto ctx = taskctx->ctx;
|
||||
auto device = ctx->device;
|
||||
auto dfunc = device->funcs;
|
||||
auto dctx = ctx->draw_context;
|
||||
auto dframe = &dctx->frames.a[ctx->curFrame];
|
||||
|
||||
if (!dframe->line_verts.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
VkDeviceMemory memory = dctx->draw_resource[1].memory;
|
||||
size_t atom = device->physDev->properties->limits.nonCoherentAtomSize;
|
||||
size_t atom_mask = atom - 1;
|
||||
#define a(x) (((x) + atom_mask) & ~atom_mask)
|
||||
VkMappedMemoryRange ranges[] = {
|
||||
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
memory, dframe->line_offset,
|
||||
a(dframe->line_verts.count * BYTES_PER_LINE) },
|
||||
};
|
||||
#undef a
|
||||
dfunc->vkFlushMappedMemoryRanges (device->dev, 1, ranges);
|
||||
|
||||
draw_lines (ctx, taskctx->cmd);
|
||||
|
||||
dframe->line_verts.count = 0;
|
||||
}
|
||||
|
||||
static exprfunc_t flush_draw_func[] = {
|
||||
{ .func = flush_draw },
|
||||
{}
|
||||
};
|
||||
static exprfunc_t slice_draw_func[] = {
|
||||
{ .func = slice_draw },
|
||||
{}
|
||||
};
|
||||
static exprfunc_t line_draw_func[] = {
|
||||
{ .func = line_draw },
|
||||
{}
|
||||
};
|
||||
static exprsym_t draw_task_syms[] = {
|
||||
{ "flush_draw", &cexpr_function, flush_draw_func },
|
||||
{ "slice_draw", &cexpr_function, slice_draw_func },
|
||||
{ "line_draw", &cexpr_function, line_draw_func },
|
||||
{}
|
||||
};
|
||||
|
||||
void
|
||||
Vulkan_Draw_Init (vulkan_ctx_t *ctx)
|
||||
{
|
||||
QFV_Render_AddTasks (ctx, draw_task_syms);
|
||||
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
|
@ -973,15 +1117,6 @@ Vulkan_Draw_Init (vulkan_ctx_t *ctx)
|
|||
DARRAY_INIT (&dframe->cmdSet, QFV_drawNumPasses);
|
||||
DARRAY_RESIZE (&dframe->cmdSet, QFV_drawNumPasses);
|
||||
dframe->cmdSet.grow = 0;
|
||||
|
||||
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &dframe->cmdSet);
|
||||
|
||||
for (int j = 0; j < QFV_drawNumPasses; j++) {
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
|
||||
dframe->cmdSet.a[j],
|
||||
va (ctx->va_ctx, "cmd:draw:%zd:%s", i,
|
||||
draw_pass_names[j]));
|
||||
}
|
||||
}
|
||||
qfvPopDebug (ctx);
|
||||
}
|
||||
|
@ -1412,173 +1547,6 @@ Vulkan_Draw_FadeScreen (vulkan_ctx_t *ctx)
|
|||
draw_blendscreen (color, ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_begin_subpass (QFV_DrawSubpass subpass, qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
||||
VkCommandBuffer cmd = dframe->cmdSet.a[subpass];
|
||||
|
||||
dfunc->vkResetCommandBuffer (cmd, 0);
|
||||
VkCommandBufferInheritanceInfo inherit = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
|
||||
rFrame->renderpass->renderpass, subpass_map[subpass],
|
||||
rFrame->framebuffer,
|
||||
0, 0, 0,
|
||||
};
|
||||
VkCommandBufferBeginInfo beginInfo = {
|
||||
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 0,
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
|
||||
| VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, &inherit,
|
||||
};
|
||||
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
|
||||
|
||||
QFV_duCmdBeginLabel (device, cmd, va (ctx->va_ctx, "draw:%s",
|
||||
draw_pass_names[subpass]),
|
||||
{0.5, 0.8, 0.1, 1});
|
||||
}
|
||||
|
||||
static void
|
||||
draw_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx)
|
||||
{
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
QFV_duCmdEndLabel (device, cmd);
|
||||
dfunc->vkEndCommandBuffer (cmd);
|
||||
}
|
||||
|
||||
static void
|
||||
bind_pipeline (qfv_renderframe_t *rFrame, VkPipeline pipeline,
|
||||
VkCommandBuffer cmd)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
dfunc->vkCmdSetViewport (cmd, 0, 1, &rFrame->renderpass->viewport);
|
||||
dfunc->vkCmdSetScissor (cmd, 0, 1, &rFrame->renderpass->scissor);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_quads (qfv_renderframe_t *rFrame, VkCommandBuffer cmd)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
||||
|
||||
VkBuffer instance_buffer = dframe->instance_buffer;
|
||||
VkDeviceSize offsets[] = {0};
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &instance_buffer, offsets);
|
||||
|
||||
VkBuffer ind_buffer = dctx->index_object[0].buffer.buffer;
|
||||
dfunc->vkCmdBindIndexBuffer (cmd, ind_buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
uint32_t inst_start = 0;
|
||||
for (size_t i = 0; i < dframe->quad_batch.size; i++) {
|
||||
int fontid = dframe->quad_batch.a[i].descid;
|
||||
uint32_t inst_count = dframe->quad_batch.a[i].count;
|
||||
uint32_t ind_count = inst_count >> 24;
|
||||
inst_count &= 0xffffff;
|
||||
VkDescriptorSet set[2] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
fontid < 0 ? dframe->dyn_descs.sets[~fontid]
|
||||
: dctx->fonts.a[fontid].set,
|
||||
};
|
||||
VkPipelineLayout layout = dctx->quad_layout;
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
layout, 0, 2, set, 0, 0);
|
||||
|
||||
dfunc->vkCmdDrawIndexed (cmd, ind_count, inst_count, 0, 0, inst_start);
|
||||
inst_start += inst_count;
|
||||
}
|
||||
DARRAY_RESIZE (&dframe->quad_batch, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_lines (qfv_renderframe_t *rFrame, VkCommandBuffer cmd)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
||||
|
||||
VkBuffer line_buffer = dframe->line_buffer;
|
||||
VkDeviceSize offsets[] = {0};
|
||||
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &line_buffer, offsets);
|
||||
VkDescriptorSet set[1] = {
|
||||
Vulkan_Matrix_Descriptors (ctx, ctx->curFrame),
|
||||
};
|
||||
VkPipelineLayout layout = dctx->lines_layout;
|
||||
dfunc->vkCmdBindDescriptorSets (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
layout, 0, 1, set, 0, 0);
|
||||
dfunc->vkCmdDraw (cmd, dframe->line_verts.count * VERTS_PER_LINE,
|
||||
1, 0, 0);
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_FlushText (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
flush_draw_scrap (ctx);
|
||||
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
drawctx_t *dctx = ctx->draw_context;
|
||||
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
|
||||
|
||||
if (!dframe->quad_insts.count && !dframe->line_verts.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
VkDeviceMemory memory = dctx->draw_resource[1].memory;
|
||||
size_t atom = device->physDev->properties->limits.nonCoherentAtomSize;
|
||||
size_t atom_mask = atom - 1;
|
||||
#define a(x) (((x) + atom_mask) & ~atom_mask)
|
||||
VkMappedMemoryRange ranges[] = {
|
||||
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
memory, dframe->instance_offset,
|
||||
a(dframe->quad_insts.count * BYTES_PER_QUAD) },
|
||||
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
memory, dframe->dvert_offset,
|
||||
a(dframe->dvertex_index * sizeof (quadvert_t)) },
|
||||
{ VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
|
||||
memory, dframe->line_offset,
|
||||
a(dframe->line_verts.count * BYTES_PER_LINE) },
|
||||
};
|
||||
#undef a
|
||||
dfunc->vkFlushMappedMemoryRanges (device->dev, 2, ranges);
|
||||
|
||||
DARRAY_APPEND (&rFrame->subpassCmdSets[subpass_map[QFV_draw2d]],
|
||||
dframe->cmdSet.a[QFV_draw2d]);
|
||||
|
||||
draw_begin_subpass (QFV_draw2d, rFrame);
|
||||
|
||||
if (dframe->quad_insts.count) {
|
||||
bind_pipeline (rFrame, dctx->quad_pipeline,
|
||||
dframe->cmdSet.a[QFV_draw2d]);
|
||||
draw_quads (rFrame, dframe->cmdSet.a[QFV_draw2d]);
|
||||
}
|
||||
if (dframe->line_verts.count) {
|
||||
bind_pipeline (rFrame, dctx->line_pipeline,
|
||||
dframe->cmdSet.a[QFV_draw2d]);
|
||||
draw_lines (rFrame, dframe->cmdSet.a[QFV_draw2d]);
|
||||
}
|
||||
|
||||
draw_end_subpass (dframe->cmdSet.a[QFV_draw2d], ctx);
|
||||
|
||||
dframe->quad_insts.count = 0;
|
||||
dframe->line_verts.count = 0;
|
||||
dframe->dvertex_index = 0;
|
||||
dframe->dyn_descs.in_use = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Draw_BlendScreen (quat_t color, vulkan_ctx_t *ctx)
|
||||
{
|
||||
|
|
|
@ -167,7 +167,6 @@ Vulkan_NewScene (scene_t *scene, vulkan_ctx_t *ctx)
|
|||
static void
|
||||
main_draw (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
Vulkan_Matrix_Draw (rFrame);
|
||||
Vulkan_RenderView (rFrame);
|
||||
Vulkan_Lighting_Draw (rFrame);
|
||||
Vulkan_Compose_Draw (rFrame);
|
||||
|
|
|
@ -174,15 +174,15 @@ Vulkan_SetSkyMatrix (vulkan_ctx_t *ctx, mat4f_t sky)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Vulkan_Matrix_Draw (qfv_renderframe_t *rFrame)
|
||||
static void
|
||||
update_matrices (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
__auto_type mctx = ctx->matrix_context;
|
||||
__auto_type mframe = &mctx->frames.a[ctx->curFrame];
|
||||
auto taskctx = (qfv_taskctx_t *) ectx;
|
||||
auto ctx = taskctx->ctx;
|
||||
auto device = ctx->device;
|
||||
auto dfunc = device->funcs;
|
||||
auto mctx = ctx->matrix_context;
|
||||
auto mframe = &mctx->frames.a[ctx->curFrame];
|
||||
|
||||
setup_view (ctx);
|
||||
setup_sky (ctx);
|
||||
|
@ -218,9 +218,19 @@ Vulkan_Matrix_Draw (qfv_renderframe_t *rFrame)
|
|||
QFV_PacketSubmit (packet);
|
||||
}
|
||||
|
||||
static exprfunc_t update_matrices_func[] = {
|
||||
{ .func = update_matrices },
|
||||
{}
|
||||
};
|
||||
static exprsym_t matrix_task_syms[] = {
|
||||
{ "update_matrices", &cexpr_function, update_matrices_func },
|
||||
{}
|
||||
};
|
||||
|
||||
void
|
||||
Vulkan_Matrix_Init (vulkan_ctx_t *ctx)
|
||||
{
|
||||
QFV_Render_AddTasks (ctx, matrix_task_syms);
|
||||
qfvPushDebug (ctx, "matrix init");
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
|
|
@ -62,85 +62,15 @@
|
|||
#include "vid_vulkan.h"
|
||||
#include "vkparse.h"//FIXME
|
||||
|
||||
static void
|
||||
acquire_image (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
auto ctx = rFrame->vulkan_ctx;
|
||||
auto device = ctx->device;
|
||||
auto dfunc = device->funcs;
|
||||
auto frame = &ctx->frames.a[ctx->curFrame];
|
||||
|
||||
uint32_t imageIndex = 0;
|
||||
while (!QFV_AcquireNextImage (ctx->swapchain,
|
||||
frame->imageAvailableSemaphore,
|
||||
0, &imageIndex)) {
|
||||
QFV_DeviceWaitIdle (device);
|
||||
if (ctx->capture) {
|
||||
QFV_DestroyCapture (ctx->capture);
|
||||
}
|
||||
Vulkan_CreateSwapchain (ctx);
|
||||
Vulkan_CreateCapture (ctx);
|
||||
|
||||
__auto_type out = ctx->output_renderpass;
|
||||
out->output = (qfv_output_t) {
|
||||
.extent = ctx->swapchain->extent,
|
||||
.format = ctx->swapchain->format,
|
||||
.frames = ctx->swapchain->numImages,
|
||||
.view_list = ctx->swapchain->imageViews->a,
|
||||
};
|
||||
out->viewport.width = out->output.extent.width;
|
||||
out->viewport.height = out->output.extent.height;
|
||||
out->scissor.extent = out->output.extent;
|
||||
QFV_RenderPass_CreateFramebuffer (out);
|
||||
|
||||
dfunc->vkDestroySemaphore (device->dev, frame->imageAvailableSemaphore,
|
||||
0);
|
||||
frame->imageAvailableSemaphore = QFV_CreateSemaphore (device);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_SEMAPHORE,
|
||||
frame->imageAvailableSemaphore,
|
||||
va (ctx->va_ctx, "sc image:%d", ctx->curFrame));
|
||||
}
|
||||
ctx->swapImageIndex = imageIndex;
|
||||
}
|
||||
|
||||
static void
|
||||
output_update_input (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
outputctx_t *octx = ctx->output_context;
|
||||
uint32_t curFrame = ctx->curFrame;
|
||||
outputframe_t *oframe = &octx->frames.a[curFrame];
|
||||
|
||||
if (oframe->input == octx->input) {
|
||||
return;
|
||||
}
|
||||
oframe->input = octx->input;
|
||||
|
||||
VkDescriptorImageInfo imageInfo = {
|
||||
octx->sampler, oframe->input,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
};
|
||||
VkWriteDescriptorSet write[] = {
|
||||
{ VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 0,
|
||||
oframe->set, 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
&imageInfo, 0, 0 }
|
||||
};
|
||||
dfunc->vkUpdateDescriptorSets (device->dev, 1, write, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
preoutput_draw (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
acquire_image (rFrame);
|
||||
output_update_input (rFrame);
|
||||
}
|
||||
|
||||
static void
|
||||
process_input (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
return;
|
||||
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||
qfv_device_t *device = ctx->device;
|
||||
qfv_devfuncs_t *dfunc = device->funcs;
|
||||
|
@ -216,7 +146,6 @@ static void
|
|||
draw_output (qfv_renderframe_t *rFrame)
|
||||
{
|
||||
process_input (rFrame);
|
||||
Vulkan_FlushText (rFrame);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -256,7 +185,6 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
|||
auto octx = ctx->output_context;
|
||||
auto sc = ctx->swapchain;
|
||||
|
||||
printf ("acquire_output: %d\n", ctx->curFrame);
|
||||
uint32_t imageIndex = 0;
|
||||
while (!QFV_AcquireNextImage (sc, frame->imageAvailableSemaphore,
|
||||
0, &imageIndex)) {
|
||||
|
@ -309,6 +237,7 @@ acquire_output (const exprval_t **params, exprval_t *result, exprctx_t *ectx)
|
|||
octx->framebuffers[i],
|
||||
va (ctx->va_ctx, "sc fb:%d", i));
|
||||
}
|
||||
rp->beginInfo.renderArea.extent = sc->extent;
|
||||
for (uint32_t i = 0; i < rp->subpass_count; i++) {
|
||||
auto sp = &rp->subpasses[i];
|
||||
for (uint32_t j = 0; j < sp->pipeline_count; j++) {
|
||||
|
|
Loading…
Reference in a new issue