2023-01-30 04:00:35 +00:00
|
|
|
/*
|
|
|
|
render.c
|
|
|
|
|
|
|
|
Vulkan render manager
|
|
|
|
|
|
|
|
Copyright (C) 2023 Bill Currie <bill@taniwha.org>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public License
|
|
|
|
as published by the Free Software Foundation; either version 2
|
|
|
|
of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to:
|
|
|
|
|
|
|
|
Free Software Foundation, Inc.
|
|
|
|
59 Temple Place - Suite 330
|
|
|
|
Boston, MA 02111-1307, USA
|
|
|
|
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef HAVE_MATH_H
|
|
|
|
# include <math.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRING_H
|
|
|
|
# include <string.h>
|
|
|
|
#endif
|
|
|
|
#ifdef HAVE_STRINGS_H
|
|
|
|
# include <strings.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "QF/Vulkan/command.h"
|
|
|
|
#include "QF/Vulkan/debug.h"
|
|
|
|
#include "QF/Vulkan/device.h"
|
|
|
|
#include "QF/Vulkan/render.h"
|
|
|
|
#include "QF/Vulkan/pipeline.h"
|
|
|
|
#include "vid_vulkan.h"
|
|
|
|
|
2023-02-10 02:04:11 +00:00
|
|
|
#include "QF/Vulkan/qf_renderpass.h"//FIXME
|
|
|
|
#include "vkparse.h"
|
|
|
|
|
2023-01-30 04:00:35 +00:00
|
|
|
static void
|
|
|
|
run_pipeline (qfv_pipeline_t *pipeline, VkCommandBuffer cmd, vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
dfunc->vkCmdBindPipeline (cmd, pipeline->bindPoint, pipeline->pipeline);
|
|
|
|
dfunc->vkCmdSetViewport (cmd, 0, 1, &pipeline->viewport);
|
|
|
|
dfunc->vkCmdSetScissor (cmd, 0, 1, &pipeline->scissor);
|
|
|
|
if (pipeline->num_descriptor_sets) {
|
|
|
|
dfunc->vkCmdBindDescriptorSets (cmd, pipeline->bindPoint,
|
|
|
|
pipeline->layout,
|
|
|
|
pipeline->first_descriptor_set,
|
|
|
|
pipeline->num_descriptor_sets,
|
|
|
|
pipeline->descriptor_sets,
|
|
|
|
0, 0);
|
|
|
|
}
|
|
|
|
if (pipeline->num_push_constants) {
|
|
|
|
QFV_PushConstants (device, cmd, pipeline->layout,
|
|
|
|
pipeline->num_push_constants,
|
|
|
|
pipeline->push_constants);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// https://themaister.net/blog/2019/08/14/yet-another-blog-explaining-vulkan-synchronization/
|
|
|
|
static void
|
2023-02-09 05:52:43 +00:00
|
|
|
run_subpass (qfv_subpass_t_ *sp, vulkan_ctx_t *ctx)
|
2023-01-30 04:00:35 +00:00
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
__auto_type cmd = sp->cmd;
|
|
|
|
dfunc->vkResetCommandBuffer (cmd, 0);
|
|
|
|
dfunc->vkBeginCommandBuffer (cmd, &sp->beginInfo);
|
|
|
|
QFV_duCmdBeginLabel (device, cmd, sp->label.name,
|
|
|
|
{VEC4_EXP (sp->label.color)});
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < sp->pipline_count; i++) {
|
|
|
|
__auto_type pipeline = &sp->pipelines[i];
|
|
|
|
run_pipeline (pipeline, cmd, ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
QFV_duCmdEndLabel (device, cmd);
|
|
|
|
dfunc->vkEndCommandBuffer (cmd);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2023-02-09 05:52:43 +00:00
|
|
|
QFV_RunRenderPass (qfv_renderpass_t_ *rp, vulkan_ctx_t *ctx)
|
2023-01-30 04:00:35 +00:00
|
|
|
{
|
|
|
|
qfv_device_t *device = ctx->device;
|
|
|
|
qfv_devfuncs_t *dfunc = device->funcs;
|
|
|
|
__auto_type cmd = rp->cmd;
|
|
|
|
|
|
|
|
VkCommandBufferBeginInfo beginInfo = {
|
|
|
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
|
|
|
};
|
|
|
|
dfunc->vkResetCommandBuffer (cmd, 0);
|
|
|
|
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
|
|
|
|
QFV_duCmdBeginLabel (device, cmd, rp->label.name,
|
|
|
|
{VEC4_EXP (rp->label.color)});
|
|
|
|
dfunc->vkCmdBeginRenderPass (cmd, &rp->beginInfo, rp->subpassContents);
|
|
|
|
for (uint32_t i = 0; i < rp->subpass_count; i++) {
|
|
|
|
__auto_type sp = &rp->subpasses[i];
|
|
|
|
run_subpass (sp, ctx);
|
|
|
|
dfunc->vkCmdExecuteCommands (cmd, 1, &sp->cmd);
|
|
|
|
//FIXME comment is a bit off as exactly one buffer is always submitted
|
|
|
|
//
|
|
|
|
//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.
|
|
|
|
//However, only if not the last (or only) subpass.
|
|
|
|
if (i < rp->subpass_count - 1) {
|
|
|
|
dfunc->vkCmdNextSubpass (cmd, rp->subpassContents);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QFV_CmdEndLabel (device, cmd);
|
|
|
|
}
|
2023-02-10 02:04:11 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
QFV_LoadRenderPass (vulkan_ctx_t *ctx)
|
|
|
|
{
|
|
|
|
plitem_t *item = Vulkan_GetConfig (ctx, "main_def");
|
|
|
|
__auto_type ri = QFV_ParseRenderInfo (ctx, item);
|
|
|
|
printf ("%p\n", ri);
|
|
|
|
}
|