[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:
Bill Currie 2023-06-21 23:31:08 +09:00
parent 3de39f5408
commit 6deeed1829
9 changed files with 236 additions and 443 deletions

View file

@ -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);

View file

@ -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));

View file

@ -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

View file

@ -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

View file

@ -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; },
);
};
};

View file

@ -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)
{

View file

@ -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);

View file

@ -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;

View file

@ -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++) {