[vulkan] Start moving towards a deferred renderer

After getting lights even vaguely working for alias models, I realized
that it just wasn't going to be feasible to do nice lighting with
forward rendering. This gets the bulk of the work done for deferred
rendering, but still need to sort out the shaders before any real
testing can be done.
This commit is contained in:
Bill Currie 2021-02-14 11:35:06 +09:00
parent 121425a75b
commit a94949c009
17 changed files with 1347 additions and 551 deletions

View file

@ -3,8 +3,17 @@
#include "QF/darray.h" #include "QF/darray.h"
typedef struct qfv_imageset_s DARRAY_TYPE (VkImage) qfv_imageset_t; typedef struct qfv_imageset_s
typedef struct qfv_imageviewset_s DARRAY_TYPE (VkImageView) qfv_imageviewset_t; DARRAY_TYPE (VkImage) qfv_imageset_t;
#define QFV_AllocImages(num, allocator) \
DARRAY_ALLOCFIXED (qfv_imageset_t, num, allocator)
typedef struct qfv_imageviewset_s
DARRAY_TYPE (VkImageView) qfv_imageviewset_t;
#define QFV_AllocImageViews(num, allocator) \
DARRAY_ALLOCFIXED (qfv_imageviewset_t, num, allocator)
typedef struct qfv_imageresource_s { typedef struct qfv_imageresource_s {
struct qfv_device_s *device; struct qfv_device_s *device;

View file

@ -36,6 +36,7 @@
#include "QF/model.h" #include "QF/model.h"
#include "QF/modelgen.h" #include "QF/modelgen.h"
#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
typedef struct aliasvrt_s { typedef struct aliasvrt_s {
float vertex[4]; float vertex[4];
@ -61,32 +62,22 @@ typedef struct qfv_alias_skin_s {
byte colorb[4]; byte colorb[4];
} qfv_alias_skin_t; } qfv_alias_skin_t;
typedef struct qfv_light_s { #define ALIAS_BUFFER_INFOS 1
vec3_t color;
float dist;
vec3_t position;
int type;
vec3_t direction;
float cone;
} qfv_light_t;
#define ALIAS_LIGHTS 8
typedef struct qfv_light_buffer_s {
int light_count;
qfv_light_t lights[ALIAS_LIGHTS] __attribute__((aligned(16)));
} qfv_light_buffer_t;
#define ALIAS_BUFFER_INFOS 2
#define ALIAS_IMAGE_INFOS 1 #define ALIAS_IMAGE_INFOS 1
enum {
QFV_aliasDepth,
QFV_aliasGBuffer,
//QFV_aliasTranslucent,
QFV_aliasNumPasses
};
typedef struct aliasframe_s { typedef struct aliasframe_s {
VkCommandBuffer cmd; qfv_cmdbufferset_t cmdSet;
VkDescriptorBufferInfo bufferInfo[ALIAS_BUFFER_INFOS]; VkDescriptorBufferInfo bufferInfo[ALIAS_BUFFER_INFOS];
VkDescriptorImageInfo imageInfo[ALIAS_IMAGE_INFOS]; VkDescriptorImageInfo imageInfo[ALIAS_IMAGE_INFOS];
VkWriteDescriptorSet descriptors[ALIAS_BUFFER_INFOS + ALIAS_IMAGE_INFOS]; VkWriteDescriptorSet descriptors[ALIAS_BUFFER_INFOS + ALIAS_IMAGE_INFOS];
qfv_light_buffer_t *lights;
VkBuffer light_buffer;
} aliasframe_t; } aliasframe_t;
typedef struct aliasframeset_s typedef struct aliasframeset_s
@ -94,11 +85,10 @@ typedef struct aliasframeset_s
typedef struct aliasctx_s { typedef struct aliasctx_s {
aliasframeset_t frames; aliasframeset_t frames;
VkPipeline pipeline; VkPipeline depth;
VkPipeline gbuf;
VkPipelineLayout layout; VkPipelineLayout layout;
VkSampler sampler; VkSampler sampler;
VkDeviceMemory light_memory;
} aliasctx_t; } aliasctx_t;
struct vulkan_ctx_s; struct vulkan_ctx_s;

View file

@ -35,6 +35,7 @@
#include "QF/darray.h" #include "QF/darray.h"
#include "QF/model.h" #include "QF/model.h"
#include "QF/Vulkan/qf_vid.h" #include "QF/Vulkan/qf_vid.h"
#include "QF/Vulkan/command.h"
typedef struct bspvert_s { typedef struct bspvert_s {
quat_t vertex; quat_t vertex;
@ -69,13 +70,19 @@ typedef enum {
// Texture, GlowMap, LightMap, SkySheet, SkyCube // Texture, GlowMap, LightMap, SkySheet, SkyCube
#define BSP_IMAGE_INFOS 5 #define BSP_IMAGE_INFOS 5
enum {
QFV_bspDepth,
QFV_bspGBuffer,
QFV_bspTranslucent,
QFV_bspNumPasses
};
typedef struct bspframe_s { typedef struct bspframe_s {
uint32_t *index_data; // pointer into mega-buffer for this frame (c) uint32_t *index_data; // pointer into mega-buffer for this frame (c)
uint32_t index_offset; // offset of index_data within mega-buffer (c) uint32_t index_offset; // offset of index_data within mega-buffer (c)
uint32_t index_count; // number if indices queued (d) uint32_t index_count; // number if indices queued (d)
VkCommandBuffer bsp_cmd; qfv_cmdbufferset_t cmdSet;
VkCommandBuffer turb_cmd;
VkCommandBuffer sky_cmd;
VkDescriptorBufferInfo bufferInfo[BSP_BUFFER_INFOS]; VkDescriptorBufferInfo bufferInfo[BSP_BUFFER_INFOS];
VkDescriptorImageInfo imageInfo[BSP_IMAGE_INFOS]; VkDescriptorImageInfo imageInfo[BSP_IMAGE_INFOS];
VkWriteDescriptorSet descriptors[BSP_BUFFER_INFOS + BSP_IMAGE_INFOS]; VkWriteDescriptorSet descriptors[BSP_BUFFER_INFOS + BSP_IMAGE_INFOS];

View file

@ -35,9 +35,22 @@
#endif #endif
#include <vulkan/vulkan.h> #include <vulkan/vulkan.h>
//FIXME location
enum {
QFV_passDepth, // geometry
QFV_passGBuffer, // geometry
QFV_passTranslucent, // geometry
QFV_passLighting, // single quad
QFV_passCompose, // single quad
QFV_NumPasses
};
struct vulkan_ctx_s; struct vulkan_ctx_s;
void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_DestroyFrames (struct vulkan_ctx_s *ctx);
void Vulkan_CreateFrames (struct vulkan_ctx_s *ctx);
void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx); void Vulkan_CreateFramebuffers (struct vulkan_ctx_s *ctx);
void Vulkan_DestroyFramebuffers (struct vulkan_ctx_s *ctx);
void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_CreateRenderPass (struct vulkan_ctx_s *ctx);
void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx); void Vulkan_DestroyRenderPass (struct vulkan_ctx_s *ctx);
void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx); void Vulkan_CreateMatrices (struct vulkan_ctx_s *ctx);

View file

@ -27,6 +27,12 @@ typedef struct qfv_subpassdependency_s
#define QFV_AllocSubpassDependencies(num, allocator) \ #define QFV_AllocSubpassDependencies(num, allocator) \
DARRAY_ALLOCFIXED (qfv_subpassdependency_t, num, allocator) DARRAY_ALLOCFIXED (qfv_subpassdependency_t, num, allocator)
typedef struct qfv_framebufferset_s
DARRAY_TYPE (VkFramebuffer) qfv_framebufferset_t;
#define QFV_AllocFrameBuffers(num, allocator) \
DARRAY_ALLOCFIXED (qfv_framebufferset_t, num, allocator)
struct qfv_device_s; struct qfv_device_s;
struct qfv_imageviewset_s; struct qfv_imageviewset_s;
VkRenderPass VkRenderPass

View file

@ -8,20 +8,15 @@
#include "QF/darray.h" #include "QF/darray.h"
typedef struct vulkan_renderpass_s { typedef struct vulkan_frame_s {
VkRenderPass renderpass;
struct qfv_imageresource_s *colorImage;
struct qfv_imageresource_s *depthImage;
} vulkan_renderpass_t;
typedef struct vulkan_framebuffer_s {
VkFramebuffer framebuffer; VkFramebuffer framebuffer;
VkFence fence; VkFence fence;
VkSemaphore imageAvailableSemaphore; VkSemaphore imageAvailableSemaphore;
VkSemaphore renderDoneSemaphore; VkSemaphore renderDoneSemaphore;
VkCommandBuffer cmdBuffer; VkCommandBuffer cmdBuffer;
struct qfv_cmdbufferset_s *subCommand; int cmdSetCount;
struct qfv_cmdbufferset_s *cmdSets;
} vulkan_frame_t; } vulkan_frame_t;
typedef struct vulkan_matrices_s { typedef struct vulkan_matrices_s {
@ -59,11 +54,22 @@ typedef struct vulkan_ctx_s {
VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain VkSurfaceKHR surface; //FIXME surface = window, so "contains" swapchain
struct plitem_s *pipelineDef; struct plitem_s *pipelineDef;
struct plitem_s *renderpassDef;
VkRenderPass renderpass;
struct qfv_imageset_s *attachment_images;
struct qfv_imageviewset_s *attachment_views;
VkDeviceMemory attachmentMemory;
uint32_t swapImageIndex;
struct qfv_framebufferset_s *framebuffers;
struct hashtab_s *shaderModules; struct hashtab_s *shaderModules;
struct hashtab_s *setLayouts; struct hashtab_s *setLayouts;
struct hashtab_s *pipelineLayouts; struct hashtab_s *pipelineLayouts;
struct hashtab_s *descriptorPools; struct hashtab_s *descriptorPools;
struct hashtab_s *samplers; struct hashtab_s *samplers;
struct hashtab_s *images;
struct hashtab_s *imageViews;
struct aliasctx_s *alias_context; struct aliasctx_s *alias_context;
struct bspctx_s *bsp_context; struct bspctx_s *bsp_context;
@ -72,7 +78,6 @@ typedef struct vulkan_ctx_s {
VkCommandPool cmdpool; VkCommandPool cmdpool;
VkCommandBuffer cmdbuffer; VkCommandBuffer cmdbuffer;
VkFence fence; // for ctx->cmdbuffer only VkFence fence; // for ctx->cmdbuffer only
vulkan_renderpass_t renderpass;
struct qfv_stagebuf_s *staging; struct qfv_stagebuf_s *staging;
VkPipeline pipeline; VkPipeline pipeline;
size_t curFrame; size_t curFrame;

View file

@ -209,6 +209,8 @@ libs_video_renderer_vid_render_sw32_la_SOURCES=\
pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist pipeline_src = libs/video/renderer/vulkan/qfpipeline.plist
pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc pipeline_gen = libs/video/renderer/vulkan/qfpipeline.plc
renderpass_src = libs/video/renderer/vulkan/deferred.plist
renderpass_gen = libs/video/renderer/vulkan/deferred.plc
video_renderer_vulkan_libs = \ video_renderer_vulkan_libs = \
libs/models/libmodels_vulkan.la libs/models/libmodels_vulkan.la
@ -250,7 +252,7 @@ libs/video/renderer/vulkan/vkparse.lo: libs/video/renderer/vulkan/vkparse.c $(vk
libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c) libs/video/renderer/vulkan/shader.lo: libs/video/renderer/vulkan/shader.c $(vkshader_c)
libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) libs/video/renderer/vulkan/vulkan_vid_common.lo: libs/video/renderer/vulkan/vulkan_vid_common.c $(vkparse_src) $(pipeline_gen) ${renderpass_gen}
qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT) qwaq_curses = ruamoko/qwaq/qwaq-curses$(EXEEXT)

View file

@ -87,8 +87,9 @@ vulkan_R_Init (void)
Vulkan_CreateStagingBuffers (vulkan_ctx); Vulkan_CreateStagingBuffers (vulkan_ctx);
Vulkan_CreateMatrices (vulkan_ctx); Vulkan_CreateMatrices (vulkan_ctx);
Vulkan_CreateSwapchain (vulkan_ctx); Vulkan_CreateSwapchain (vulkan_ctx);
Vulkan_CreateFramebuffers (vulkan_ctx); Vulkan_CreateFrames (vulkan_ctx);
Vulkan_CreateRenderPass (vulkan_ctx); Vulkan_CreateRenderPass (vulkan_ctx);
Vulkan_CreateFramebuffers (vulkan_ctx);
// FIXME this should be staged so screen updates can begin while pipelines // FIXME this should be staged so screen updates can begin while pipelines
// are being built // are being built
vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline"); vulkan_ctx->pipeline = Vulkan_CreatePipeline (vulkan_ctx, "pipeline");
@ -111,6 +112,8 @@ vulkan_R_Init (void)
static void static void
vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs) vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs)
{ {
const VkSubpassContents subpassContents
= VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
static int count = 0; static int count = 0;
static double startTime; static double startTime;
uint32_t imageIndex = 0; uint32_t imageIndex = 0;
@ -128,20 +131,9 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs)
QFV_AcquireNextImage (vulkan_ctx->swapchain, QFV_AcquireNextImage (vulkan_ctx->swapchain,
frame->imageAvailableSemaphore, frame->imageAvailableSemaphore,
0, &imageIndex); 0, &imageIndex);
vulkan_ctx->swapImageIndex = imageIndex;
int attachCount = vulkan_ctx->msaaSamples > 1 ? 3 : 2; frame->framebuffer = vulkan_ctx->framebuffers->a[imageIndex];
__auto_type attachments = DARRAY_ALLOCFIXED (qfv_imageviewset_t,
attachCount, alloca);
qfv_swapchain_t *sc = vulkan_ctx->swapchain;
attachments->a[0] = sc->imageViews->a[imageIndex];
attachments->a[1] = vulkan_ctx->renderpass.depthImage->view;
if (attachCount > 2) {
attachments->a[2] = vulkan_ctx->renderpass.colorImage->view;
}
VkRenderPass renderpass = vulkan_ctx->renderpass.renderpass;
frame->framebuffer = QFV_CreateFramebuffer (device, renderpass,
attachments, sc->extent, 1);
scr_3dfunc (); scr_3dfunc ();
while (*scr_funcs) { while (*scr_funcs) {
@ -160,20 +152,26 @@ vulkan_R_RenderFrame (SCR_Func scr_3dfunc, SCR_Func *scr_funcs)
}; };
VkRenderPassBeginInfo renderPassInfo = { VkRenderPassBeginInfo renderPassInfo = {
VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0, VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, 0,
vulkan_ctx->renderpass.renderpass, 0, vulkan_ctx->renderpass, 0,
{ {0, 0}, sc->extent }, { {0, 0}, vulkan_ctx->swapchain->extent },
3, clearValues 3, clearValues
}; };
dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo); dfunc->vkBeginCommandBuffer (frame->cmdBuffer, &beginInfo);
renderPassInfo.framebuffer = frame->framebuffer; renderPassInfo.framebuffer = frame->framebuffer;
dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo, dfunc->vkCmdBeginRenderPass (frame->cmdBuffer, &renderPassInfo,
VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS); subpassContents);
dfunc->vkCmdExecuteCommands (frame->cmdBuffer, frame->subCommand->size, for (int i = 0; i < frame->cmdSetCount; i++) {
frame->subCommand->a); dfunc->vkCmdExecuteCommands (frame->cmdBuffer, frame->cmdSets[i].size,
// reset for next time around frame->cmdSets[i].a);
frame->subCommand->size = 0; // reset for next time around
frame->cmdSets[i].size = 0;
if (i < frame->cmdSetCount) {
dfunc->vkCmdNextSubpass (frame->cmdBuffer, subpassContents);
}
}
dfunc->vkCmdEndRenderPass (frame->cmdBuffer); dfunc->vkCmdEndRenderPass (frame->cmdBuffer);
dfunc->vkEndCommandBuffer (frame->cmdBuffer); dfunc->vkEndCommandBuffer (frame->cmdBuffer);

View file

@ -0,0 +1,342 @@
{
images = {
depth = {
imageType = VK_IMAGE_TYPE_2D; //FIXME short form is 2d...
format = x8_d24_unorm_pack32;
samples = 1;
extent = {
width = $swapchain.extent.width;
height = $swapchain.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = depth_stencil_attachment|input_attachment;
};
color = {
imageType = VK_IMAGE_TYPE_2D;
format = r8g8b8a8_unorm;
samples = 1;
extent = {
width = $swapchain.extent.width;
height = $swapchain.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment;
};
normals = {
imageType = VK_IMAGE_TYPE_2D;
format = r16g16b16a16_sfloat;
samples = 1;
extent = {
width = $swapchain.extent.width;
height = $swapchain.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment;
};
opaque = {
imageType = VK_IMAGE_TYPE_2D;
format = r8g8b8a8_unorm;
samples = 1;
extent = {
width = $swapchain.extent.width;
height = $swapchain.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment;
};
translucent = {
imageType = VK_IMAGE_TYPE_2D;
format = r8g8b8a8_unorm;
samples = 1;
extent = {
width = $swapchain.extent.width;
height = $swapchain.extent.height;
depth = 1;
};
mipLevels = 1;
arrayLayers = 1;
tiling = optimal;
usage = color_attachment|input_attachment;
};
};
imageViews = {
depth = {
image = depth;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.depth.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = depth;
levelCount = 1;
layerCount = 1;
};
};
color = {
image = color;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.color.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
normals = {
image = normals;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.normals.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
opaque = {
image = opaque;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.opaque.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
translucent = {
image = translucent;
viewType = VK_IMAGE_VIEW_TYPE_2D;
format = $properties.images.translucent.format;
components = {
r = identity;
g = identity;
b = identity;
a = identity;
};
subresourceRange = {
aspectMask = color;
levelCount = 1;
layerCount = 1;
};
};
};
framebuffer = {
renderPass = renderpass;
attachments = (depth, color, normals, opaque, translucent,
"$swapchain.views[$swapImageIndex]");
width = $swapchain.extent.width;
height = $swapchain.extent.height;
};
renderpass = {
attachments = (
{
format = $properties.images.depth.format;
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = depth_stencil_attachment_optimal;
},
{
format = $properties.images.color.format;
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
format = $properties.images.normals.format;
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
format = $properties.images.opaque.format;
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
format = $properties.images.translucent.format;
samples = 1;
loadOp = dont_care;
storeOp = dont_care;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = color_attachment_optimal;
},
{
format = $swapchain.format;
samples = 1;
loadOp = clear;
storeOp = store;
stencilLoadOp = dont_care;
stencilStoreOp = dont_care;
initialLayout = undefined;
finalLayout = present_src_khr;
},
);
subpasses = (
{ // depth
pipelineBindPoint = graphics;
depthStencilAttachment = {
attachment = 0;
layout = depth_stencil_attachment_optimal;
};
},
{ // g-buffer generation
pipelineBindPoint = graphics;
colorAttachments = (
{ // color
attachment = 1;
layout = color_attachment_optimal;
},
{ // normals
attachment = 2;
layout = color_attachment_optimal;
},
);
depthStencilAttachment = {
attachment = 0;
layout = depth_stencil_attachment_optimal;
};
},
{ // lighting
pipelineBindPoint = graphics;
inputAttachments = (
{ // depth
attachment = 0;
layout = shader_read_only_optimal;
},
{ // color
attachment = 1;
layout = shader_read_only_optimal;
},
{ // normals
attachment = 2;
layout = shader_read_only_optimal;
},
);
colorAttachments = (
{ // opaque
attachment = 3;
layout = color_attachment_optimal;
},
);
},
{ // translucent
pipelineBindPoint = graphics;
colorAttachments = (
{ // translucent
attachment = 4;
layout = color_attachment_optimal;
},
);
},
{ // compose
pipelineBindPoint = graphics;
inputAttachments = (
{ // opaque
attachment = 3;
layout = shader_read_only_optimal;
},
{ // translucent
attachment = 4;
layout = shader_read_only_optimal;
},
);
colorAttachments = (
{ // swapchain
attachment = 5;
layout = color_attachment_optimal;
},
);
},
);
dependencies = (
{
srcSubpass = 0;
dstSubpass = 1;
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
dstAccessMask = shader_read;
dependencyFlags = by_region;
},
{
srcSubpass = 1;
dstSubpass = 2;
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
dstAccessMask = shader_read;
dependencyFlags = by_region;
},
{
srcSubpass = 2;
dstSubpass = 4;
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
dstAccessMask = shader_read;
dependencyFlags = by_region;
},
{
srcSubpass = 3;
dstSubpass = 4;
srcStageMask = color_attachment_output;
dstStageMask = fragment_shader;
srcAccessMask = color_attachment_write;
dstAccessMask = shader_read;
dependencyFlags = by_region;
},
);
};
}

View file

@ -273,7 +273,45 @@
}; };
}; };
pipelines = { pipelines = {
alias = { alias_depth = {
stages = (
{
stage = vertex;
name = main;
module = $builtin/alias.vert;
},
);
vertexInput = {
bindings = (
"$properties.pipelines.alias_gbuf.vertexInput.bindings[0]",
"$properties.pipelines.alias_gbuf.vertexInput.bindings[1]",
);
attributes = (
"$properties.pipelines.alias_gbuf.vertexInput.attributes[0]",
"$properties.pipelines.alias_gbuf.vertexInput.attributes[1]",
"$properties.pipelines.alias_gbuf.vertexInput.attributes[2]",
"$properties.pipelines.alias_gbuf.vertexInput.attributes[3]",
);
};
inputAssembly = $properties.pipelines.alias_gbuf.inputAssembly;
viewport = $properties.pipelines.alias_gbuf.viewport;
rasterization = $properties.pipelines.alias_gbuf.rasterization;
multisample = $properties.pipelines.alias_gbuf.multisample;
depthStencil = {
depthTestEnable = true;
depthWriteEnable = true;
depthCompareOp = less_or_equal;
depthBoundsTestEnable = false;
stencilTestEnable = false;
};
colorBlend = $properties.pipelines.alias_gbuf.colorBlend;
dynamic = {
dynamicState = ( viewport, scissor );
};
layout = alias_layout;
//renderPass = renderpass;
};
alias_gbuf = {
stages = ( stages = (
{ {
stage = vertex; stage = vertex;
@ -404,7 +442,41 @@
layout = alias_layout; layout = alias_layout;
//renderPass = renderpass; //renderPass = renderpass;
}; };
quakebsp_main = { bsp_depth = {
stages = (
{
stage = vertex;
name = main;
module = $builtin/quakebsp.vert;
},
);
vertexInput = {
bindings = (
"$properties.pipelines.bsp_gbuf.vertexInput.bindings[0]",
);
attributes = (
"$properties.pipelines.bsp_gbuf.vertexInput.attributes[0]",
);
};
inputAssembly = $properties.pipelines.bsp_main.inputAssembly;
viewport = $properties.pipelines.bsp_main.viewport;
rasterization = $properties.pipelines.bsp_main.rasterization;
multisample = $properties.pipelines.bsp_main.multisample;
depthStencil = {
depthTestEnable = true;
depthWriteEnable = true;
depthCompareOp = less_or_equal;
depthBoundsTestEnable = false;
stencilTestEnable = false;
};
colorBlend = $properties.pipelines.bsp_gbuf.colorBlend;
dynamic = {
dynamicState = ( viewport, scissor );
};
layout = quakebsp_layout;
//renderPass = renderpass;
};
bsp_gbuf = {
stages = ( stages = (
{ {
stage = vertex; stage = vertex;
@ -523,86 +595,15 @@
}; };
}, },
); );
vertexInput = { vertexInput = $properties.pipelines.bsp_gbuf.vertexInput;
bindings = ( inputAssembly = $properties.pipelines.bsp_gbuf.inputAssembly;
{ viewport = $properties.pipelines.bsp_gbuf.viewport;
binding = 0; rasterization = $properties.pipelines.bsp_gbuf.rasterization;
stride = "2 * 4 * 4"; multisample = $properties.pipelines.bsp_gbuf.multisample;
inputRate = vertex; depthStencil = $properties.pipelines.bsp_gbuf.depthStencil;
}, colorBlend = $properties.pipelines.bsp_gbuf.colorBlend;
);
attributes = (
{
location = 0;
binding = 0;
format = r32g32b32a32_sfloat;
offset = 0;
},
{
location = 1;
binding = 0;
format = r32g32b32a32_sfloat;
offset = 16;
},
);
};
inputAssembly = {
topology = triangle_fan;
primitiveRestartEnable = true;
};
viewport = {
viewports = (
{
x = 0; y = 0;
width = 640; height = 480;
minDepth = 0; maxDepth = 1;
}
);
scissors = (
{
offset = { x = 0; y = 0 };
extent = { width = 640; height = 480; };
},
);
};
rasterization = {
depthClampEnable = false;
rasterizerDiscardEnable = false;
polygonMode = fill;
cullMode = back;
frontFace = clockwise;
depthBiasEnable = false;
lineWidth = 1;
};
multisample = {
rasterizationSamples = $msaaSamples;
sampleShadingEnable = false;
minSampleShading = 0.5f;
alphaToCoverageEnable = false;
alphaToOneEnable = false;
};
depthStencil = {
depthTestEnable = true;
depthWriteEnable = true;
depthCompareOp = less_or_equal;
depthBoundsTestEnable = false;
stencilTestEnable = false;
};
colorBlend = {
logicOpEnable = false;
attachments = ({
blendEnable = true;
srcColorBlendFactor = src_alpha;
dstColorBlendFactor = one_minus_src_alpha;
colorBlendOp = add;
srcAlphaBlendFactor = src_alpha;
dstAlphaBlendFactor = one_minus_src_alpha;
alphaBlendOp = add;
colorWriteMask = r|g|b|a;
});
};
dynamic = { dynamic = {
dynamicState = ( viewport, scissor, blend_constants ); dynamicState = ( viewport, scissor );
}; };
layout = quakebsp_layout; layout = quakebsp_layout;
//renderPass = renderpass; //renderPass = renderpass;

View file

@ -460,7 +460,8 @@ parse_VkDescriptorSetLayout (const plfield_t *field, const plitem_t *item,
ret = !cexpr_eval_string (name, &ectx); ret = !cexpr_eval_string (name, &ectx);
if (ret) { if (ret) {
VkDescriptorSetLayout setLayout; VkDescriptorSetLayout setLayout;
setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem); setLayout = QFV_ParseDescriptorSetLayout (ctx, setItem,
pctx->properties);
*handle = (VkDescriptorSetLayout) setLayout; *handle = (VkDescriptorSetLayout) setLayout;
QFV_AddHandle (ctx->setLayouts, name, (uint64_t) setLayout); QFV_AddHandle (ctx->setLayouts, name, (uint64_t) setLayout);
@ -495,7 +496,7 @@ parse_VkPipelineLayout (const plitem_t *item, void **data,
ret = !cexpr_eval_string (name, &ectx); ret = !cexpr_eval_string (name, &ectx);
if (ret) { if (ret) {
VkPipelineLayout layout; VkPipelineLayout layout;
layout = QFV_ParsePipelineLayout (ctx, setItem); layout = QFV_ParsePipelineLayout (ctx, setItem, context->properties);
*handle = (VkPipelineLayout) layout; *handle = (VkPipelineLayout) layout;
QFV_AddHandle (ctx->pipelineLayouts, name, (uint64_t) layout); QFV_AddHandle (ctx->pipelineLayouts, name, (uint64_t) layout);
@ -503,6 +504,92 @@ parse_VkPipelineLayout (const plitem_t *item, void **data,
return ret; return ret;
} }
static int
parse_VkImage (const plitem_t *item, void **data, plitem_t *messages,
parsectx_t *context)
{
__auto_type handle = (VkImage *) data[0];
int ret = 1;
exprctx_t ectx = *context->ectx;
vulkan_ctx_t *ctx = context->vctx;
const char *name = PL_String (item);
Sys_Printf ("parse_VkImage: %s\n", name);
if (name[0] != '$') {
name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name);
}
*handle = (VkImage) QFV_GetHandle (ctx->images, name);
if (*handle) {
return 1;
}
plitem_t *imageItem = 0;
exprval_t result = { &cexpr_plitem, &imageItem };
ectx.symtab = 0;
ectx.result = &result;
ret = !cexpr_eval_string (name, &ectx);
if (ret) {
VkImage image;
image = QFV_ParseImage (ctx, imageItem, context->properties);
*handle = (VkImage) image;
QFV_AddHandle (ctx->images, name, (uint64_t) image);
}
return ret;
}
static exprtype_t imageview_type = {
"VkImageView",
sizeof (VkImageView),
0, 0, 0
};
static int
parse_VkImageView (const plfield_t *field, const plitem_t *item, void *data,
plitem_t *messages, void *_context)
{
parsectx_t *context = _context;
__auto_type handle = (VkImageView *) data;
int ret = 1;
exprctx_t ectx = *context->ectx;
vulkan_ctx_t *ctx = context->vctx;
const char *name = PL_String (item);
Sys_Printf ("parse_VkImageView: %s\n", name);
if (name[0] != '$') {
name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name);
}
*handle = (VkImageView) QFV_GetHandle (ctx->imageViews, name);
if (*handle) {
return 1;
}
exprval_t *value = 0;
exprval_t result = { &cexpr_exprval, &value };
ectx.symtab = 0;
ectx.result = &result;
ret = !cexpr_eval_string (name, &ectx);
plitem_t *imageViewItem = 0;
if (ret) {
VkImageView imageView;
if (value->type == &imageview_type) {
imageView = *(VkImageView *) value->value;
} else if (value->type == &cexpr_plitem) {
imageView = QFV_ParseImageView (ctx, imageViewItem,
context->properties);
QFV_AddHandle (ctx->imageViews, name, (uint64_t) imageView);
} else {
PL_Message (messages, item, "not a VkImageView");
return 0;
}
*handle = (VkImageView) imageView;
}
return ret;
}
static const char * static const char *
handleref_getkey (const void *hr, void *unused) handleref_getkey (const void *hr, void *unused)
{ {
@ -592,6 +679,36 @@ sampler_free (void *hr, void *_ctx)
handleref_free (handleref, ctx); handleref_free (handleref, ctx);
} }
static void
image_free (void *hr, void *_ctx)
{
__auto_type handleref = (handleref_t *) hr;
__auto_type image = (VkImage) handleref->handle;
__auto_type ctx = (vulkan_ctx_t *) _ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
if (image) {
dfunc->vkDestroyImage (device->dev, image, 0);
};
handleref_free (handleref, ctx);
}
static void
imageView_free (void *hr, void *_ctx)
{
__auto_type handleref = (handleref_t *) hr;
__auto_type imageView = (VkImageView) handleref->handle;
__auto_type ctx = (vulkan_ctx_t *) _ctx;
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
if (imageView) {
dfunc->vkDestroyImageView (device->dev, imageView, 0);
};
handleref_free (handleref, ctx);
}
static hashtab_t *enum_symtab; static hashtab_t *enum_symtab;
static int static int
@ -605,23 +722,71 @@ parse_BasePipeline (const plitem_t *item, void **data,
#include "libs/video/renderer/vulkan/vkparse.cinc" #include "libs/video/renderer/vulkan/vkparse.cinc"
static exprsym_t imageset_symbols[] = { static void
{"size", &cexpr_size_t, (void *)field_offset (qfv_imageset_t, size)}, imageviewset_index (const exprval_t *a, size_t index, exprval_t *c,
exprctx_t *ctx)
{
__auto_type set = *(qfv_imageviewset_t **) a->value;
exprval_t *val = 0;
if (index >= set->size) {
cexpr_error (ctx, "invalid index: %zd", index);
} else {
val = cexpr_value (&imageview_type, ctx);
*(VkImageView *) val->value = set->a[index];
}
*(exprval_t **) c->value = val;
}
static void
imageviewset_int (const exprval_t *a, const exprval_t *b, exprval_t *c,
exprctx_t *ctx)
{
size_t index = *(int *) b->value;
imageviewset_index (a, index, c, ctx);
}
static void
imageviewset_uint (const exprval_t *a, const exprval_t *b, exprval_t *c,
exprctx_t *ctx)
{
size_t index = *(unsigned *) b->value;
imageviewset_index (a, index, c, ctx);
}
static void
imageviewset_size_t (const exprval_t *a, const exprval_t *b, exprval_t *c,
exprctx_t *ctx)
{
size_t index = *(size_t *) b->value;
imageviewset_index (a, index, c, ctx);
}
binop_t imageviewset_binops[] = {
{ '.', &cexpr_field, &cexpr_exprval, cexpr_struct_pointer_getfield },
{ '[', &cexpr_int, &imageview_type, imageviewset_int },
{ '[', &cexpr_uint, &imageview_type, imageviewset_uint },
{ '[', &cexpr_size_t, &imageview_type, imageviewset_size_t },
{}
};
static exprsym_t imageviewset_symbols[] = {
{"size", &cexpr_size_t, (void *)field_offset (qfv_imageviewset_t, size)},
{ } { }
}; };
static exprtab_t imageset_symtab = { static exprtab_t imageviewset_symtab = {
imageset_symbols, imageviewset_symbols,
}; };
exprtype_t imageset_type = { exprtype_t imageviewset_type = {
"imageset", "imageviewset",
sizeof (qfv_imageset_t *), sizeof (qfv_imageviewset_t *),
cexpr_struct_pointer_binops, imageviewset_binops,
0, 0,
&imageset_symtab, &imageviewset_symtab,
}; };
static exprsym_t qfv_swapchain_t_symbols[] = { static exprsym_t qfv_swapchain_t_symbols[] = {
{"format", &VkFormat_type, (void *)field_offset (qfv_swapchain_t, format)}, {"format", &VkFormat_type, (void *)field_offset (qfv_swapchain_t, format)},
{"images", &imageset_type, (void *)field_offset (qfv_swapchain_t, images)}, {"extent", &VkExtent2D_type, (void *)field_offset (qfv_swapchain_t, extent)},
{"views", &imageviewset_type, (void *)field_offset (qfv_swapchain_t, imageViews)},
{ } { }
}; };
static exprtab_t qfv_swapchain_t_symtab = { static exprtab_t qfv_swapchain_t_symtab = {
@ -714,7 +879,7 @@ QFV_InitParse (vulkan_ctx_t *ctx)
vkgen_init_symtabs (&context); vkgen_init_symtabs (&context);
cexpr_init_symtab (&qfv_swapchain_t_symtab, &context); cexpr_init_symtab (&qfv_swapchain_t_symtab, &context);
cexpr_init_symtab (&vulkan_frameset_t_symtab, &context); cexpr_init_symtab (&vulkan_frameset_t_symtab, &context);
cexpr_init_symtab (&imageset_symtab, &context); cexpr_init_symtab (&imageviewset_symtab, &context);
if (!ctx->setLayouts) { if (!ctx->setLayouts) {
ctx->shaderModules = handlref_symtab (shaderModule_free, ctx); ctx->shaderModules = handlref_symtab (shaderModule_free, ctx);
@ -722,6 +887,8 @@ QFV_InitParse (vulkan_ctx_t *ctx)
ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx); ctx->pipelineLayouts = handlref_symtab (pipelineLayout_free, ctx);
ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx); ctx->descriptorPools = handlref_symtab (descriptorPool_free, ctx);
ctx->samplers = handlref_symtab (sampler_free, ctx); ctx->samplers = handlref_symtab (sampler_free, ctx);
ctx->images = handlref_symtab (image_free, ctx);
ctx->imageViews = handlref_symtab (imageView_free, ctx);
} }
} }
@ -733,16 +900,17 @@ QFV_GetEnum (const char *name)
static int static int
parse_object (vulkan_ctx_t *ctx, plitem_t *plist, parse_object (vulkan_ctx_t *ctx, plitem_t *plist,
plparser_t parser, void *object) plparser_t parser, void *object, plitem_t *properties)
{ {
plitem_t *messages = PL_NewArray (); plitem_t *messages = PL_NewArray ();
exprctx_t exprctx = {}; exprctx_t exprctx = {};
parsectx_t parsectx = { &exprctx, ctx }; parsectx_t parsectx = { &exprctx, ctx, properties };
exprsym_t var_syms[] = { exprsym_t var_syms[] = {
{"swapchain", &qfv_swapchain_t_type, ctx->swapchain}, {"swapchain", &qfv_swapchain_t_type, ctx->swapchain},
{"frames", &vulkan_frameset_t_type, &ctx->frames}, {"frames", &vulkan_frameset_t_type, &ctx->frames},
{"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples}, {"msaaSamples", &VkSampleCountFlagBits_type, &ctx->msaaSamples},
{QFV_PROPERTIES, &cexpr_plitem, &ctx->pipelineDef}, {"swapImageIndex", &cexpr_uint, &ctx->swapImageIndex},
{QFV_PROPERTIES, &cexpr_plitem, &parsectx.properties},
{} {}
}; };
exprtab_t vars_tab = { var_syms, 0 }; exprtab_t vars_tab = { var_syms, 0 };
@ -775,13 +943,14 @@ parse_qfv_renderpass (const plfield_t *field, const plitem_t *item, void *data,
} }
VkRenderPass VkRenderPass
QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist) QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_renderpass_t renderpass_data = {}; qfv_renderpass_t renderpass_data = {};
if (!parse_object (ctx, plist, parse_qfv_renderpass, &renderpass_data)) { if (!parse_object (ctx, plist, parse_qfv_renderpass, &renderpass_data,
properties)) {
return 0; return 0;
} }
@ -805,7 +974,7 @@ QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist)
} }
VkPipeline VkPipeline
QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist) QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
@ -813,11 +982,11 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist)
memset (&cInfo->a[0], 0, sizeof (cInfo->a[0])); memset (&cInfo->a[0], 0, sizeof (cInfo->a[0]));
if (!parse_object (ctx, plist, parse_VkGraphicsPipelineCreateInfo, if (!parse_object (ctx, plist, parse_VkGraphicsPipelineCreateInfo,
&cInfo->a[0])) { &cInfo->a[0], properties)) {
return 0; return 0;
} }
cInfo->a[0].renderPass = ctx->renderpass.renderpass; cInfo->a[0].renderPass = ctx->renderpass;
__auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo); __auto_type plSet = QFV_CreateGraphicsPipelines (device, 0, cInfo);
VkPipeline pipeline = plSet->a[0]; VkPipeline pipeline = plSet->a[0];
free (plSet); free (plSet);
@ -825,14 +994,16 @@ QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist)
} }
VkDescriptorPool VkDescriptorPool
QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist) QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
VkDescriptorPoolCreateInfo cInfo = {}; VkDescriptorPoolCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkDescriptorPoolCreateInfo, &cInfo)) { if (!parse_object (ctx, plist, parse_VkDescriptorPoolCreateInfo, &cInfo,
properties)) {
return 0; return 0;
} }
@ -843,7 +1014,8 @@ QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist)
} }
VkDescriptorSetLayout VkDescriptorSetLayout
QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist) QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
@ -851,7 +1023,7 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist)
VkDescriptorSetLayoutCreateInfo cInfo = {}; VkDescriptorSetLayoutCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkDescriptorSetLayoutCreateInfo, if (!parse_object (ctx, plist, parse_VkDescriptorSetLayoutCreateInfo,
&cInfo)) { &cInfo, properties)) {
return 0; return 0;
} }
@ -862,7 +1034,8 @@ QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, plitem_t *plist)
} }
VkPipelineLayout VkPipelineLayout
QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist) QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
@ -870,7 +1043,7 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist)
VkPipelineLayoutCreateInfo cInfo = {}; VkPipelineLayoutCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkPipelineLayoutCreateInfo, if (!parse_object (ctx, plist, parse_VkPipelineLayoutCreateInfo,
&cInfo)) { &cInfo, properties)) {
return 0; return 0;
} }
@ -881,14 +1054,15 @@ QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist)
} }
VkSampler VkSampler
QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist) QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
VkSamplerCreateInfo cInfo = {}; VkSamplerCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkSamplerCreateInfo, &cInfo)) { if (!parse_object (ctx, plist, parse_VkSamplerCreateInfo, &cInfo,
properties)) {
return 0; return 0;
} }
@ -897,3 +1071,195 @@ QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist)
return sampler; return sampler;
} }
VkImage
QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
VkImageCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkImageCreateInfo, &cInfo,
properties)) {
return 0;
}
VkImage image;
dfunc->vkCreateImage (device->dev, &cInfo, 0, &image);
return image;
}
VkImageView
QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
VkImageViewCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkImageViewCreateInfo, &cInfo,
properties)) {
return 0;
}
VkImageView imageView;
dfunc->vkCreateImageView (device->dev, &cInfo, 0, &imageView);
return imageView;
}
typedef struct {
uint32_t count;
VkImageCreateInfo *info;
} imagecreate_t;
typedef struct {
uint32_t count;
VkImageViewCreateInfo *info;
} imageviewcreate_t;
static plelement_t qfv_imagecreate_dict = {
QFDictionary,
sizeof (VkImageCreateInfo),
array_alloc,
parse_VkImageCreateInfo,
};
static plelement_t qfv_imageviewcreate_dict = {
QFDictionary,
sizeof (VkImageViewCreateInfo),
array_alloc,
parse_VkImageViewCreateInfo,
};
static int
parse_imagecreate_dict (const plfield_t *field, const plitem_t *item,
void *data, plitem_t *messages, void *context)
{
plfield_t f = { "images", 0, QFArray, parse_array,
&qfv_imagecreate_dict };
typedef struct arr_s DARRAY_TYPE(byte) arr_t;
arr_t *arr = 0;
int ret;
if ((ret = PL_ParseLabeledArray (&f, item, &arr, messages, context))) {
imagecreate_t *imagecreate = data;
imagecreate->count = arr->size;
imagecreate->info = (VkImageCreateInfo *) arr->a;
} else {
//FIXME leaky boat when succeeds
if (arr) {
free (arr);
}
}
return ret;
}
static int
parse_imageviewcreate_dict (const plfield_t *field, const plitem_t *item,
void *data, plitem_t *messages, void *context)
{
plfield_t f = { "images", 0, QFArray, parse_array,
&qfv_imageviewcreate_dict };
typedef struct arr_s DARRAY_TYPE(byte) arr_t;
arr_t *arr = 0;
int ret;
if ((ret = PL_ParseLabeledArray (&f, item, &arr, messages, context))) {
imageviewcreate_t *imageviewcreate = data;
imageviewcreate->count = arr->size;
imageviewcreate->info = (VkImageViewCreateInfo *) arr->a;
} else {
//FIXME leaky boat when succeeds
if (arr) {
free (arr);
}
}
return ret;
}
qfv_imageset_t *
QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *item, plitem_t *properties)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
imagecreate_t create = {};
pltype_t type = PL_Type (item);
if (type == QFDictionary) {
if (!parse_object (ctx, item, parse_imagecreate_dict, &create,
properties)) {
return 0;
}
} else {
Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item));
return 0;
}
__auto_type set = QFV_AllocImages (create.count, malloc);
for (uint32_t i = 0; i < create.count; i++) {
dfunc->vkCreateImage (device->dev, &create.info[i], 0, &set->a[i]);
const char *name = PL_KeyAtIndex (item, i);
name = va (ctx->va_ctx, "$"QFV_PROPERTIES".images.%s", name);
QFV_AddHandle (ctx->images, name, (uint64_t) set->a[i]);
}
return set;
}
qfv_imageviewset_t *
QFV_ParseImageViewSet (vulkan_ctx_t *ctx, plitem_t *item,
plitem_t *properties)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
imageviewcreate_t create = {};
pltype_t type = PL_Type (item);
if (type == QFDictionary) {
if (!parse_object (ctx, item, parse_imageviewcreate_dict, &create,
properties)) {
return 0;
}
} else {
Sys_Printf ("Neither array nor dictionary: %d\n", PL_Line (item));
return 0;
}
__auto_type set = QFV_AllocImageViews (create.count, malloc);
for (uint32_t i = 0; i < create.count; i++) {
dfunc->vkCreateImageView (device->dev, &create.info[i], 0, &set->a[i]);
const char *name = PL_KeyAtIndex (item, i);
name = va (ctx->va_ctx, "$"QFV_PROPERTIES".imageViews.%s", name);
QFV_AddHandle (ctx->imageViews, name, (uint64_t) set->a[i]);
}
return set;
}
VkFramebuffer
QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist, plitem_t *properties)
{
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
VkFramebufferCreateInfo cInfo = {};
if (!parse_object (ctx, plist, parse_VkFramebufferCreateInfo, &cInfo,
properties)) {
return 0;
}
VkFramebuffer framebuffer;
dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer);
return framebuffer;
}

View file

@ -4,6 +4,8 @@
typedef struct parsectx_s { typedef struct parsectx_s {
struct exprctx_s *ectx; struct exprctx_s *ectx;
struct vulkan_ctx_s *vctx; struct vulkan_ctx_s *vctx;
struct plitem_s *properties;
void *data;
} parsectx_t; } parsectx_t;
#include "QF/cexpr.h" #include "QF/cexpr.h"
@ -32,12 +34,29 @@ exprenum_t *QFV_GetEnum (const char *name);
uint64_t QFV_GetHandle (struct hashtab_s *tab, const char *name); uint64_t QFV_GetHandle (struct hashtab_s *tab, const char *name);
void QFV_AddHandle (struct hashtab_s *tab, const char *name, uint64_t handle); void QFV_AddHandle (struct hashtab_s *tab, const char *name, uint64_t handle);
VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist); VkRenderPass QFV_ParseRenderPass (vulkan_ctx_t *ctx, plitem_t *plist,
VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist); plitem_t *properties);
VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist); VkPipeline QFV_ParsePipeline (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties);
VkDescriptorPool QFV_ParseDescriptorPool (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties);
VkDescriptorSetLayout QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx, VkDescriptorSetLayout QFV_ParseDescriptorSetLayout (vulkan_ctx_t *ctx,
plitem_t *plist); plitem_t *plist,
VkPipelineLayout QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist); plitem_t *properties);
VkSampler QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist); VkPipelineLayout QFV_ParsePipelineLayout (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties);
VkSampler QFV_ParseSampler (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties);
VkImage QFV_ParseImage (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties);
VkImageView QFV_ParseImageView (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties);
struct qfv_imageset_s *QFV_ParseImageSet (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties);
struct qfv_imageviewset_s *QFV_ParseImageViewSet (vulkan_ctx_t *ctx,
plitem_t *plist,
plitem_t *properties);
VkFramebuffer QFV_ParseFramebuffer (vulkan_ctx_t *ctx, plitem_t *plist,
plitem_t *properties);
#endif//__vkparse_h #endif//__vkparse_h

View file

@ -20,6 +20,9 @@
VkGraphicsPipelineCreateInfo, VkGraphicsPipelineCreateInfo,
VkDescriptorPoolCreateInfo, VkDescriptorPoolCreateInfo,
VkSamplerCreateInfo, VkSamplerCreateInfo,
VkImageCreateInfo,
VkImageViewCreateInfo,
VkFramebufferCreateInfo,
); );
parse = { parse = {
VkSubpassDescription = { VkSubpassDescription = {
@ -282,6 +285,48 @@
fields = (basePipelineHandle); fields = (basePipelineHandle);
}; };
basePipelineIndex = auto; basePipelineIndex = auto;
};
VkImageCreateInfo = {
flags = auto;
imageType = auto;
format = auto;
extent = auto;
mipLevels = auto;
arrayLayers = auto;
samples = auto;
tiling = auto;
usage = auto;
sharingMode = skip; // FIXME for now
queueFamilyIndexCount = skip; // FIXME for now
pQueueFamilyIndices = skip; // FIXME for now
initialLayout = auto;
};
VkImageViewCreateInfo = {
flags = auto;
image = {
type = (custom, (QFDictionary, QFString),
parse_VkImage);
fields = (image);
};
viewType = auto;
format = auto;
components = auto;
subresourceRange = auto;
};
VkFramebufferCreateInfo = {
//flags = auto; reserved for future use (Bits enum does not exist)
renderPass = {
type = (custom, QFString, parse_VkShaderModule);
fields = (renderPass);
};
attachments = {
type = (array, VkImageView);
size = attachmentCount;
values = pAttachments;
};
width = auto;
height = auto;
layers = auto;
} }
} }
} }

View file

@ -64,16 +64,65 @@
#include "r_internal.h" #include "r_internal.h"
#include "vid_vulkan.h" #include "vid_vulkan.h"
void static const char *alias_pass_names[] = {
Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx) "depth",
"g-buffer",
"translucent",
};
static void
emit_commands (VkCommandBuffer cmd, int pose1, int pose2,
qfv_alias_skin_t *skin,
void *vert_constants, int vert_size,
void *frag_constants, int frag_size,
aliashdr_t *hdr, vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context; aliasctx_t *actx = ctx->alias_context;
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
__auto_type mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands);
VkDeviceSize offsets[] = {
pose1 * hdr->poseverts * sizeof (aliasvrt_t),
pose2 * hdr->poseverts * sizeof (aliasvrt_t),
0,
};
VkBuffer buffers[] = {
mesh->vertex_buffer,
mesh->vertex_buffer,
mesh->uv_buffer,
};
int bindingCount = skin ? 3 : 2;
dfunc->vkCmdBindVertexBuffers (cmd, 0, bindingCount, buffers, offsets);
dfunc->vkCmdBindIndexBuffer (cmd, mesh->index_buffer, 0,
VK_INDEX_TYPE_UINT32);
dfunc->vkCmdPushConstants (cmd, actx->layout, VK_SHADER_STAGE_VERTEX_BIT,
0, vert_size, vert_constants);
if (skin) {
dfunc->vkCmdPushConstants (cmd, actx->layout,
VK_SHADER_STAGE_FRAGMENT_BIT,
68, frag_size, frag_constants);
aframe->imageInfo[0].imageView = skin->view;
dfunc->vkCmdPushDescriptorSetKHR (cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->layout,
0, ALIAS_IMAGE_INFOS,
aframe->descriptors
+ ALIAS_BUFFER_INFOS);
}
dfunc->vkCmdDrawIndexed (cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0);
}
void
Vulkan_DrawAlias (entity_t *ent, vulkan_ctx_t *ctx)
{
aliasctx_t *actx = ctx->alias_context;
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
model_t *model = ent->model; model_t *model = ent->model;
aliashdr_t *hdr; aliashdr_t *hdr;
qfv_alias_mesh_t *mesh;
qfv_alias_skin_t *skin; qfv_alias_skin_t *skin;
float vertex_constants[17]; float vertex_constants[17];
byte fragment_constants[3][4]; byte fragment_constants[3][4];
@ -81,7 +130,6 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx)
if (!(hdr = model->aliashdr)) { if (!(hdr = model->aliashdr)) {
hdr = Cache_Get (&model->cache); hdr = Cache_Get (&model->cache);
} }
mesh = (qfv_alias_mesh_t *) ((byte *) hdr + hdr->commands);
memcpy (vertex_constants, ent->transform, sizeof (ent->transform)); memcpy (vertex_constants, ent->transform, sizeof (ent->transform));
vertex_constants[16] = R_AliasGetLerpedFrames (ent, hdr); vertex_constants[16] = R_AliasGetLerpedFrames (ent, hdr);
@ -97,90 +145,26 @@ Vulkan_DrawAlias (entity_t *ent, struct vulkan_ctx_s *ctx)
QuatCopy (skin->colora, fragment_constants[1]); QuatCopy (skin->colora, fragment_constants[1]);
QuatCopy (skin->colorb, fragment_constants[2]); QuatCopy (skin->colorb, fragment_constants[2]);
VkDeviceSize offsets[] = { emit_commands (aframe->cmdSet.a[QFV_aliasDepth], ent->pose1, ent->pose2,
ent->pose1 * hdr->poseverts * sizeof (aliasvrt_t), 0, vertex_constants, sizeof (vertex_constants),
ent->pose2 * hdr->poseverts * sizeof (aliasvrt_t), fragment_constants, sizeof (fragment_constants),
0, hdr, ctx);
};
VkBuffer buffers[] = {
mesh->vertex_buffer,
mesh->vertex_buffer,
mesh->uv_buffer,
};
dfunc->vkCmdBindVertexBuffers (aframe->cmd, 0, 3, buffers, offsets);
dfunc->vkCmdBindIndexBuffer (aframe->cmd, mesh->index_buffer, 0,
VK_INDEX_TYPE_UINT32);
dfunc->vkCmdPushConstants (aframe->cmd, actx->layout,
VK_SHADER_STAGE_VERTEX_BIT,
0, sizeof (vertex_constants), vertex_constants);
dfunc->vkCmdPushConstants (aframe->cmd, actx->layout,
VK_SHADER_STAGE_FRAGMENT_BIT,
68, sizeof (fragment_constants),
fragment_constants);
aframe->imageInfo[0].imageView = skin->view;
dfunc->vkCmdPushDescriptorSetKHR (aframe->cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->layout,
0, ALIAS_IMAGE_INFOS,
aframe->descriptors
+ ALIAS_BUFFER_INFOS);
dfunc->vkCmdDrawIndexed (aframe->cmd, 3 * hdr->mdl.numtris, 1, 0, 0, 0);
} }
static void static void
calc_lighting (qfv_light_t *light, entity_t *ent) alias_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline,
{ vulkan_ctx_t *ctx)
vec3_t ambient_color;
//FIXME should be ent->position
float l = R_LightPoint (&r_worldentity.model->brush, r_origin) / 128.0;
//XXX l = max (light, max (ent->model->min_light, ent->min_light));
light->type = 2;
VectorSet (1, 1, 1, ambient_color); //FIXME
// position doubles as ambient light
VectorScale (ambient_color, l, light->position);
VectorSet (-1, 0, 0, light->direction); //FIXME
VectorCopy (light->position, light->color);
}
void
Vulkan_AliasBegin (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context; aliasctx_t *actx = ctx->alias_context;
dlight_t *lights[ALIAS_LIGHTS];
//XXX quat_t fog;
__auto_type cframe = &ctx->frames.a[ctx->curFrame]; __auto_type cframe = &ctx->frames.a[ctx->curFrame];
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = aframe->cmd;
DARRAY_APPEND (cframe->subCommand, cmd);
//FIXME ambient needs to be per entity
aframe->lights->light_count = 1;
calc_lighting (&aframe->lights->lights[0], 0);
R_FindNearLights (r_origin, ALIAS_LIGHTS - 1, lights);
for (int i = 0; i < ALIAS_LIGHTS - 1; i++) {
if (!lights[i]) {
break;
}
aframe->lights->light_count++;
VectorCopy (lights[i]->color, aframe->lights->lights[i + 1].color);
VectorCopy (lights[i]->origin, aframe->lights->lights[i + 1].position);
aframe->lights->lights[i + 1].dist = lights[i]->radius;
aframe->lights->lights[i + 1].type = 0;
}
//FIXME need per frame matrices
aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
aframe->bufferInfo[1].buffer = aframe->light_buffer;
dfunc->vkResetCommandBuffer (cmd, 0); dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = { VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass.renderpass, 0, ctx->renderpass, 0,
cframe->framebuffer, cframe->framebuffer,
0, 0, 0, 0, 0, 0,
}; };
@ -192,7 +176,7 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx)
dfunc->vkBeginCommandBuffer (cmd, &beginInfo); dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
actx->pipeline); pipeline);
//VkDescriptorSet sets[] = { //VkDescriptorSet sets[] = {
// aframe->descriptors[0].dstSet, // aframe->descriptors[0].dstSet,
// aframe->descriptors[1].dstSet, // aframe->descriptors[1].dstSet,
@ -213,15 +197,43 @@ Vulkan_AliasBegin (vulkan_ctx_t *ctx)
//XXX fog[3] = glsl_Fog_GetDensity () / 64.0; //XXX fog[3] = glsl_Fog_GetDensity () / 64.0;
} }
void static void
Vulkan_AliasEnd (vulkan_ctx_t *ctx) alias_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = ctx->alias_context;
dfunc->vkEndCommandBuffer (cmd);
}
void
Vulkan_AliasBegin (vulkan_ctx_t *ctx)
{
aliasctx_t *actx = ctx->alias_context;
__auto_type cframe = &ctx->frames.a[ctx->curFrame];
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame]; aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
dfunc->vkEndCommandBuffer (aframe->cmd);
//XXX quat_t fog;
DARRAY_APPEND (&cframe->cmdSets[QFV_passDepth],
aframe->cmdSet.a[QFV_aliasDepth]);
DARRAY_APPEND (&cframe->cmdSets[QFV_passGBuffer],
aframe->cmdSet.a[QFV_aliasGBuffer]);
//FIXME need per frame matrices
aframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
alias_begin_subpass (aframe->cmdSet.a[QFV_aliasDepth], actx->depth, ctx);
alias_begin_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], actx->gbuf, ctx);
}
void
Vulkan_AliasEnd (vulkan_ctx_t *ctx)
{
aliasctx_t *actx = ctx->alias_context;
aliasframe_t *aframe = &actx->frames.a[ctx->curFrame];
alias_end_subpass (aframe->cmdSet.a[QFV_aliasDepth], ctx);
alias_end_subpass (aframe->cmdSet.a[QFV_aliasGBuffer], ctx);
} }
static VkDescriptorBufferInfo base_buffer_info = { static VkDescriptorBufferInfo base_buffer_info = {
@ -247,7 +259,6 @@ void
Vulkan_Alias_Init (vulkan_ctx_t *ctx) Vulkan_Alias_Init (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
aliasctx_t *actx = calloc (1, sizeof (aliasctx_t)); aliasctx_t *actx = calloc (1, sizeof (aliasctx_t));
ctx->alias_context = actx; ctx->alias_context = actx;
@ -257,7 +268,8 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx)
DARRAY_RESIZE (&actx->frames, frames); DARRAY_RESIZE (&actx->frames, frames);
actx->frames.grow = 0; actx->frames.grow = 0;
actx->pipeline = Vulkan_CreatePipeline (ctx, "alias"); actx->depth = Vulkan_CreatePipeline (ctx, "alias_depth");
actx->gbuf = Vulkan_CreatePipeline (ctx, "alias_gbuf");
actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout"); actx->layout = Vulkan_CreatePipelineLayout (ctx, "alias_layout");
actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler"); actx->sampler = Vulkan_CreateSampler (ctx, "alias_sampler");
@ -276,43 +288,22 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx)
}*/ }*/
//__auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool"); //__auto_type pool = QFV_GetDescriptorPool (ctx, "alias.pool");
__auto_type cmdBuffers = QFV_AllocCommandBufferSet (frames, alloca);
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers);
__auto_type lbuffers = QFV_AllocBufferSet (frames, alloca);
for (size_t i = 0; i < frames; i++) {
lbuffers->a[i] = QFV_CreateBuffer (device, sizeof (qfv_light_buffer_t),
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_BUFFER,
lbuffers->a[i],
va (ctx->va_ctx, "buffer:alias:%s:%zd",
"lights", i));
}
VkMemoryRequirements requirements;
dfunc->vkGetBufferMemoryRequirements (device->dev, lbuffers->a[0],
&requirements);
actx->light_memory = QFV_AllocBufferMemory (device, lbuffers->a[0],
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
frames * requirements.size, 0);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
actx->light_memory, va (ctx->va_ctx,
"memory:alias:%s", "lights"));
byte *light_data;
dfunc->vkMapMemory (device->dev, actx->light_memory, 0,
frames * requirements.size, 0, (void **) &light_data);
//__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts); //__auto_type sets = QFV_AllocateDescriptorSet (device, pool, layouts);
for (size_t i = 0; i < frames; i++) { for (size_t i = 0; i < frames; i++) {
__auto_type aframe = &actx->frames.a[i]; __auto_type aframe = &actx->frames.a[i];
aframe->cmd = cmdBuffers->a[i];
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
aframe->cmd,
va (ctx->va_ctx, "cmd:alias:%zd", i));
aframe->light_buffer = lbuffers->a[i];
aframe->lights = (qfv_light_buffer_t *) (light_data + i * requirements.size);
QFV_BindBufferMemory (device, lbuffers->a[i], actx->light_memory,
i * requirements.size);
DARRAY_INIT (&aframe->cmdSet, QFV_aliasNumPasses);
DARRAY_RESIZE (&aframe->cmdSet, QFV_aliasNumPasses);
aframe->cmdSet.grow = 0;
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &aframe->cmdSet);
for (int j = 0; j < QFV_aliasNumPasses; j++) {
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
aframe->cmdSet.a[j],
va (ctx->va_ctx, "cmd:alias:%zd:%s", i,
alias_pass_names[j]));
}
for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) { for (int j = 0; j < ALIAS_BUFFER_INFOS; j++) {
aframe->bufferInfo[j] = base_buffer_info; aframe->bufferInfo[j] = base_buffer_info;
aframe->descriptors[j] = base_buffer_write; aframe->descriptors[j] = base_buffer_write;
@ -333,7 +324,7 @@ Vulkan_Alias_Init (vulkan_ctx_t *ctx)
} }
void void
Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx) Vulkan_Alias_Shutdown (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
@ -341,11 +332,11 @@ Vulkan_Alias_Shutdown (struct vulkan_ctx_s *ctx)
for (size_t i = 0; i < actx->frames.size; i++) { for (size_t i = 0; i < actx->frames.size; i++) {
__auto_type aframe = &actx->frames.a[i]; __auto_type aframe = &actx->frames.a[i];
dfunc->vkDestroyBuffer (device->dev, aframe->light_buffer, 0); free (aframe->cmdSet.a);
} }
dfunc->vkFreeMemory (device->dev, actx->light_memory, 0);
dfunc->vkDestroyPipeline (device->dev, actx->pipeline, 0); dfunc->vkDestroyPipeline (device->dev, actx->depth, 0);
DARRAY_CLEAR (&actx->frames); dfunc->vkDestroyPipeline (device->dev, actx->gbuf, 0);
free (actx->frames.a);
free (actx); free (actx);
} }

View file

@ -69,6 +69,12 @@
#include "r_internal.h" #include "r_internal.h"
#include "vid_vulkan.h" #include "vid_vulkan.h"
static const char *bsp_pass_names[] = {
"depth",
"g-buffer",
"translucent",
};
static float identity[] = { static float identity[] = {
1, 0, 0, 0, 1, 0, 0, 0,
0, 1, 0, 0, 0, 1, 0, 0,
@ -779,33 +785,44 @@ bind_view (qfv_bsp_tex tex, VkImageView view, bspframe_t *bframe,
+ BSP_BUFFER_INFOS); + BSP_BUFFER_INFOS);
} }
static void
push_transform (vec_t *transform, VkPipelineLayout layout,
qfv_devfuncs_t *dfunc, VkCommandBuffer cmd)
{
dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT,
0, 16 * sizeof (float), transform);
}
static void
push_fragconst (fragconst_t *fragconst, VkPipelineLayout layout,
qfv_devfuncs_t *dfunc, VkCommandBuffer cmd)
{
dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_FRAGMENT_BIT,
0, sizeof (fragconst_t), fragconst);
}
static void
push_descriptors (int count, VkWriteDescriptorSet *descriptors,
VkPipelineLayout layout, qfv_devfuncs_t *dfunc,
VkCommandBuffer cmd)
{
dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
layout, 0, count, descriptors);
}
static void static void
draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc, draw_elechain (elechain_t *ec, VkPipelineLayout layout, qfv_devfuncs_t *dfunc,
VkCommandBuffer cmd) VkCommandBuffer cmd)
{ {
elements_t *el; elements_t *el;
/*if (colloc >= 0) {
float *color;
color = ec->color;
if (!color)
color = bctx->default_color;
if (!QuatCompare (color, bctx->last_color)) {
QuatCopy (color, bctx->last_color);
qfeglVertexAttrib4fv (quake_bsp.color.location, color);
}
}*/
if (ec->transform) { if (ec->transform) {
dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, push_transform (ec->transform, layout, dfunc, cmd);
0, 16 * sizeof (float), ec->transform);
} else { } else {
//FIXME should cache current transform //FIXME should cache current transform
dfunc->vkCmdPushConstants (cmd, layout, VK_SHADER_STAGE_VERTEX_BIT, push_transform (identity, layout, dfunc, cmd);
0, 16 * sizeof (float), identity);
} }
for (el = ec->elements; el; el = el->next) { for (el = ec->elements; el; el = el->next) {
//FIXME check if these are contiguous and if so merge into one
//command
if (!el->index_count) if (!el->index_count)
continue; continue;
dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index, dfunc->vkCmdDrawIndexed (cmd, el->index_count, 1, el->first_index,
@ -828,35 +845,18 @@ get_view (qfv_tex_t *tex, qfv_tex_t *default_tex)
} }
static void static void
bsp_begin (vulkan_ctx_t *ctx) bsp_begin_subpass (VkCommandBuffer cmd, VkPipeline pipeline, vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
bspctx_t *bctx = ctx->bsp_context; bspctx_t *bctx = ctx->bsp_context;
//XXX quat_t fog;
bctx->default_color[3] = 1;
QuatCopy (bctx->default_color, bctx->last_color);
__auto_type cframe = &ctx->frames.a[ctx->curFrame]; __auto_type cframe = &ctx->frames.a[ctx->curFrame];
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = bframe->bsp_cmd;
DARRAY_APPEND (cframe->subCommand, cmd);
//FIXME need per frame matrices
bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
bframe->imageInfo[0].imageView = 0; // set by tex chain loop
bframe->imageInfo[1].imageView = 0; // set by tex chain loop
bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap);
bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex,
bctx->default_skysheet);
bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex,
bctx->default_skybox);
dfunc->vkResetCommandBuffer (cmd, 0); dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = { VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass.renderpass, 0, ctx->renderpass, 0,
cframe->framebuffer, cframe->framebuffer,
0, 0, 0, 0, 0, 0,
}; };
@ -868,7 +868,7 @@ bsp_begin (vulkan_ctx_t *ctx)
dfunc->vkBeginCommandBuffer (cmd, &beginInfo); dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
bctx->main); pipeline);
VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1}; VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1};
VkRect2D scissor = { {0, 0}, {vid.width, vid.height} }; VkRect2D scissor = { {0, 0}, {vid.width, vid.height} };
dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport); dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport);
@ -893,14 +893,54 @@ bsp_begin (vulkan_ctx_t *ctx)
} }
static void static void
bsp_end (vulkan_ctx_t *ctx) bsp_end_subpass (VkCommandBuffer cmd, vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
bspctx_t *bctx = ctx->bsp_context;
dfunc->vkEndCommandBuffer (cmd);
}
static void
bsp_begin (vulkan_ctx_t *ctx)
{
bspctx_t *bctx = ctx->bsp_context;
//XXX quat_t fog;
bctx->default_color[3] = 1;
QuatCopy (bctx->default_color, bctx->last_color);
__auto_type cframe = &ctx->frames.a[ctx->curFrame];
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
dfunc->vkEndCommandBuffer (bframe->bsp_cmd);
DARRAY_APPEND (&cframe->cmdSets[QFV_passDepth],
bframe->cmdSet.a[QFV_bspDepth]);
DARRAY_APPEND (&cframe->cmdSets[QFV_passGBuffer],
bframe->cmdSet.a[QFV_bspGBuffer]);
//FIXME need per frame matrices
bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
bframe->imageInfo[0].imageView = 0; // set by tex chain loop
bframe->imageInfo[1].imageView = 0; // set by tex chain loop
bframe->imageInfo[2].imageView = QFV_ScrapImageView (bctx->light_scrap);
bframe->imageInfo[3].imageView = get_view (bctx->skysheet_tex,
bctx->default_skysheet);
bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex,
bctx->default_skybox);
//FIXME pipeline
bsp_begin_subpass (bframe->cmdSet.a[QFV_bspDepth], bctx->main, ctx);
bsp_begin_subpass (bframe->cmdSet.a[QFV_bspGBuffer], bctx->main, ctx);
}
static void
bsp_end (vulkan_ctx_t *ctx)
{
bspctx_t *bctx = ctx->bsp_context;
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
bsp_end_subpass (bframe->cmdSet.a[QFV_bspDepth], ctx);
bsp_end_subpass (bframe->cmdSet.a[QFV_bspGBuffer], ctx);
} }
/*static void /*static void
@ -982,8 +1022,6 @@ spin (mat4_t mat, bspctx_t *bctx)
static void static void
sky_begin (vulkan_ctx_t *ctx) sky_begin (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
bspctx_t *bctx = ctx->bsp_context; bspctx_t *bctx = ctx->bsp_context;
bctx->default_color[3] = 1; bctx->default_color[3] = 1;
@ -993,8 +1031,10 @@ sky_begin (vulkan_ctx_t *ctx)
__auto_type cframe = &ctx->frames.a[ctx->curFrame]; __auto_type cframe = &ctx->frames.a[ctx->curFrame];
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = bframe->sky_cmd;
DARRAY_APPEND (cframe->subCommand, cmd); //FIXME where should skys go? g-buffer is overkill. Translucent pre-pass?
DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent],
bframe->cmdSet.a[QFV_bspTranslucent]);
//FIXME need per frame matrices //FIXME need per frame matrices
bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d; bframe->bufferInfo[0].buffer = ctx->matrices.buffer_3d;
@ -1006,54 +1046,18 @@ sky_begin (vulkan_ctx_t *ctx)
bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex, bframe->imageInfo[4].imageView = get_view (bctx->skybox_tex,
bctx->default_skybox); bctx->default_skybox);
dfunc->vkResetCommandBuffer (cmd, 0); //FIXME sky pass
VkCommandBufferInheritanceInfo inherit = { bsp_begin_subpass (bframe->cmdSet.a[QFV_bspTranslucent], bctx->sky, ctx);
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass.renderpass, 0,
cframe->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);
dfunc->vkCmdBindPipeline (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
bctx->sky);
VkViewport viewport = {0, 0, vid.width, vid.height, 0, 1};
VkRect2D scissor = { {0, 0}, {vid.width, vid.height} };
dfunc->vkCmdSetViewport (cmd, 0, 1, &viewport);
dfunc->vkCmdSetScissor (cmd, 0, 1, &scissor);
VkDeviceSize offsets[] = { 0 };
dfunc->vkCmdBindVertexBuffers (cmd, 0, 1, &bctx->vertex_buffer, offsets);
dfunc->vkCmdBindIndexBuffer (cmd, bctx->index_buffer, bframe->index_offset,
VK_INDEX_TYPE_UINT32);
// push VP matrices
dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
bctx->layout,
0, 1, bframe->descriptors + 0);
// push static images
dfunc->vkCmdPushDescriptorSetKHR (cmd, VK_PIPELINE_BIND_POINT_GRAPHICS,
bctx->layout,
0, 5, bframe->descriptors + 1);
//XXX glsl_Fog_GetColor (fog);
//XXX fog[3] = glsl_Fog_GetDensity () / 64.0;
} }
static void static void
sky_end (vulkan_ctx_t *ctx) sky_end (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device;
qfv_devfuncs_t *dfunc = device->funcs;
bspctx_t *bctx = ctx->bsp_context; bspctx_t *bctx = ctx->bsp_context;
bspframe_t *bframe = &bctx->frames.a[ctx->curFrame]; bspframe_t *bframe = &bctx->frames.a[ctx->curFrame];
dfunc->vkEndCommandBuffer (bframe->sky_cmd);
//FIXME sky pass
bsp_end_subpass (bframe->cmdSet.a[QFV_bspTranslucent], ctx);
} }
static inline void static inline void
@ -1133,13 +1137,13 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx)
Vulkan_FlushLightmaps (ctx); Vulkan_FlushLightmaps (ctx);
bsp_begin (ctx); bsp_begin (ctx);
dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, push_transform (identity, bctx->layout, dfunc,
VK_SHADER_STAGE_VERTEX_BIT, bframe->cmdSet.a[QFV_bspDepth]);
0, 16 * sizeof (float), identity); push_transform (identity, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspGBuffer]);
fragconst_t frag_constants = { time: vr_data.realtime }; fragconst_t frag_constants = { time: vr_data.realtime };
dfunc->vkCmdPushConstants (bframe->bsp_cmd, bctx->layout, push_fragconst (&frag_constants, bctx->layout, dfunc,
VK_SHADER_STAGE_FRAGMENT_BIT, bframe->cmdSet.a[QFV_bspGBuffer]);
64, sizeof (fragconst_t), &frag_constants);
//XXX qfeglActiveTexture (GL_TEXTURE0 + 0); //XXX qfeglActiveTexture (GL_TEXTURE0 + 0);
for (size_t i = 0; i < bctx->texture_chains.size; i++) { for (size_t i = 0; i < bctx->texture_chains.size; i++) {
vulktex_t *tex; vulktex_t *tex;
@ -1153,13 +1157,15 @@ Vulkan_DrawWorld (vulkan_ctx_t *ctx)
ctx->default_white); ctx->default_white);
bframe->imageInfo[1].imageView = get_view (tex->glow, bframe->imageInfo[1].imageView = get_view (tex->glow,
ctx->default_black); ctx->default_black);
dfunc->vkCmdPushDescriptorSetKHR (bframe->bsp_cmd,
VK_PIPELINE_BIND_POINT_GRAPHICS, push_descriptors (2, bframe->descriptors + 1, bctx->layout, dfunc,
bctx->layout, bframe->cmdSet.a[QFV_bspGBuffer]);
0, 2, bframe->descriptors + 1);
for (ec = tex->elechain; ec; ec = ec->next) { for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc, bframe->bsp_cmd); draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspDepth]);
draw_elechain (ec, bctx->layout, dfunc,
bframe->cmdSet.a[QFV_bspGBuffer]);
} }
tex->elechain = 0; tex->elechain = 0;
tex->elechain_tail = &tex->elechain; tex->elechain_tail = &tex->elechain;
@ -1246,22 +1252,24 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx)
return; return;
sky_begin (ctx); sky_begin (ctx);
dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, //FIXME sky pass
VK_SHADER_STAGE_VERTEX_BIT, push_transform (identity, bctx->layout, dfunc,
0, 16 * sizeof (float), identity); bframe->cmdSet.a[QFV_bspTranslucent]);
fragconst_t frag_constants = { time: vr_data.realtime }; fragconst_t frag_constants = { time: vr_data.realtime };
dfunc->vkCmdPushConstants (bframe->sky_cmd, bctx->layout, push_fragconst (&frag_constants, bctx->layout, dfunc,
VK_SHADER_STAGE_FRAGMENT_BIT, bframe->cmdSet.a[QFV_bspTranslucent]);
64, sizeof (fragconst_t), &frag_constants);
for (is = bctx->sky_chain; is; is = is->tex_chain) { for (is = bctx->sky_chain; is; is = is->tex_chain) {
surf = is->surface; surf = is->surface;
if (tex != surf->texinfo->texture->render) { if (tex != surf->texinfo->texture->render) {
if (tex) { if (tex) {
bind_view (qfv_bsp_skysheet, bind_view (qfv_bsp_skysheet,
get_view (tex->tex, ctx->default_black), get_view (tex->tex, ctx->default_black),
bframe, bframe->sky_cmd, bctx->layout, dfunc); bframe,
bframe->cmdSet.a[QFV_bspTranslucent],//FIXME
bctx->layout, dfunc);
for (ec = tex->elechain; ec; ec = ec->next) { for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc, bframe->sky_cmd); draw_elechain (ec, bctx->layout, dfunc,//FIXME
bframe->cmdSet.a[QFV_bspTranslucent]);
} }
tex->elechain = 0; tex->elechain = 0;
tex->elechain_tail = &tex->elechain; tex->elechain_tail = &tex->elechain;
@ -1271,11 +1279,12 @@ Vulkan_DrawSky (vulkan_ctx_t *ctx)
add_surf_elements (tex, is, &ec, &el, bctx, bframe); add_surf_elements (tex, is, &ec, &el, bctx, bframe);
} }
if (tex) { if (tex) {
bind_view (qfv_bsp_skysheet, bind_view (qfv_bsp_skysheet, get_view (tex->tex, ctx->default_black),
get_view (tex->tex, ctx->default_black), bframe, bframe->cmdSet.a[QFV_bspTranslucent],//FIXME
bframe, bframe->sky_cmd, bctx->layout, dfunc); bctx->layout, dfunc);
for (ec = tex->elechain; ec; ec = ec->next) { for (ec = tex->elechain; ec; ec = ec->next) {
draw_elechain (ec, bctx->layout, dfunc, bframe->sky_cmd); draw_elechain (ec, bctx->layout, dfunc,//FIXME
bframe->cmdSet.a[QFV_bspTranslucent]);
} }
tex->elechain = 0; tex->elechain = 0;
tex->elechain_tail = &tex->elechain; tex->elechain_tail = &tex->elechain;
@ -1453,23 +1462,21 @@ Vulkan_Bsp_Init (vulkan_ctx_t *ctx)
bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout"); bctx->layout = Vulkan_CreatePipelineLayout (ctx, "quakebsp_layout");
bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler"); bctx->sampler = Vulkan_CreateSampler (ctx, "quakebsp_sampler");
__auto_type cmdBuffers = QFV_AllocCommandBufferSet (3 * frames, alloca);
QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, cmdBuffers);
for (size_t i = 0; i < frames; i++) { for (size_t i = 0; i < frames; i++) {
__auto_type bframe = &bctx->frames.a[i]; __auto_type bframe = &bctx->frames.a[i];
bframe->bsp_cmd = cmdBuffers->a[i * 3 + 0];
bframe->turb_cmd = cmdBuffers->a[i * 3 + 1]; DARRAY_INIT (&bframe->cmdSet, QFV_bspNumPasses);
bframe->sky_cmd = cmdBuffers->a[i * 3 + 2]; DARRAY_RESIZE (&bframe->cmdSet, QFV_bspNumPasses);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, bframe->cmdSet.grow = 0;
bframe->bsp_cmd,
va (ctx->va_ctx, "cmd:bsp:%zd", i)); QFV_AllocateCommandBuffers (device, ctx->cmdpool, 1, &bframe->cmdSet);
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
bframe->turb_cmd, for (int j = 0; j < QFV_bspNumPasses; j++) {
va (ctx->va_ctx, "cmd:turb:%zd", i)); QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER, bframe->cmdSet.a[i],
bframe->sky_cmd, va (ctx->va_ctx, "cmd:bsp:%zd:%s", i,
va (ctx->va_ctx, "cmd:sky:%zd", i)); bsp_pass_names[j]));
}
for (int j = 0; j < BSP_BUFFER_INFOS; j++) { for (int j = 0; j < BSP_BUFFER_INFOS; j++) {
bframe->bufferInfo[j] = base_buffer_info; bframe->bufferInfo[j] = base_buffer_info;
@ -1495,6 +1502,11 @@ Vulkan_Bsp_Shutdown (struct vulkan_ctx_s *ctx)
qfv_devfuncs_t *dfunc = device->funcs; qfv_devfuncs_t *dfunc = device->funcs;
bspctx_t *bctx = ctx->bsp_context; bspctx_t *bctx = ctx->bsp_context;
for (size_t i = 0; i < bctx->frames.size; i++) {
__auto_type bframe = &bctx->frames.a[i];
free (bframe->cmdSet.a);
}
dfunc->vkDestroyPipeline (device->dev, bctx->main, 0); dfunc->vkDestroyPipeline (device->dev, bctx->main, 0);
dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0); dfunc->vkDestroyPipeline (device->dev, bctx->sky, 0);
DARRAY_CLEAR (&bctx->texture_chains); DARRAY_CLEAR (&bctx->texture_chains);

View file

@ -696,7 +696,8 @@ Vulkan_FlushText (vulkan_ctx_t *ctx)
drawframe_t *dframe = &dctx->frames.a[ctx->curFrame]; drawframe_t *dframe = &dctx->frames.a[ctx->curFrame];
VkCommandBuffer cmd = dframe->cmd; VkCommandBuffer cmd = dframe->cmd;
DARRAY_APPEND (cframe->subCommand, cmd); //FIXME which pass?
DARRAY_APPEND (&cframe->cmdSets[QFV_passTranslucent], cmd);
VkMappedMemoryRange range = { VkMappedMemoryRange range = {
VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0, VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, 0,
@ -708,7 +709,7 @@ Vulkan_FlushText (vulkan_ctx_t *ctx)
dfunc->vkResetCommandBuffer (cmd, 0); dfunc->vkResetCommandBuffer (cmd, 0);
VkCommandBufferInheritanceInfo inherit = { VkCommandBufferInheritanceInfo inherit = {
VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0, VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, 0,
ctx->renderpass.renderpass, 0, ctx->renderpass, 0,
cframe->framebuffer, cframe->framebuffer,
0, 0, 0 0, 0, 0
}; };

View file

@ -78,6 +78,10 @@ static const char quakeforge_pipeline[] =
#include "libs/video/renderer/vulkan/qfpipeline.plc" #include "libs/video/renderer/vulkan/qfpipeline.plc"
; ;
static const char quakeforge_renderpass[] =
#include "libs/video/renderer/vulkan/deferred.plc"
;
cvar_t *vulkan_frame_count; cvar_t *vulkan_frame_count;
cvar_t *vulkan_presentation_mode; cvar_t *vulkan_presentation_mode;
cvar_t *msaaSamples; cvar_t *msaaSamples;
@ -163,6 +167,7 @@ void
Vulkan_Init_Common (vulkan_ctx_t *ctx) Vulkan_Init_Common (vulkan_ctx_t *ctx)
{ {
Sys_Printf ("Vulkan_Init_Common\n"); Sys_Printf ("Vulkan_Init_Common\n");
QFV_InitParse (ctx); QFV_InitParse (ctx);
Vulkan_Init_Cvars (); Vulkan_Init_Cvars ();
ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version ctx->instance = QFV_CreateInstance (ctx, PACKAGE_STRING, 0x000702ff, 0, instance_extensions);//FIXME version
@ -185,9 +190,9 @@ Vulkan_Shutdown_Common (vulkan_ctx_t *ctx)
QFV_DestroyPipeline (ctx->device, ctx->pipeline); QFV_DestroyPipeline (ctx->device, ctx->pipeline);
} }
if (ctx->frames.size) { if (ctx->frames.size) {
Vulkan_DestroyFramebuffers (ctx); Vulkan_DestroyFrames (ctx);
} }
if (ctx->renderpass.colorImage) { if (ctx->renderpass) {
Vulkan_DestroyRenderPass (ctx); Vulkan_DestroyRenderPass (ctx);
} }
if (ctx->swapchain) { if (ctx->swapchain) {
@ -216,6 +221,15 @@ void
Vulkan_CreateDevice (vulkan_ctx_t *ctx) Vulkan_CreateDevice (vulkan_ctx_t *ctx)
{ {
ctx->device = QFV_CreateDevice (ctx, device_extensions); ctx->device = QFV_CreateDevice (ctx, device_extensions);
//FIXME msaa and deferred rendering...
//also, location
ctx->msaaSamples = 1;
/*ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val,
QFV_GetMaxSampleCount (device->physDev));
if (ctx->msaaSamples > 1) {
name = "renderpass_msaa";
}*/
} }
void void
@ -257,138 +271,54 @@ qfv_load_pipeline (vulkan_ctx_t *ctx, const char *name)
return item; return item;
} }
static plitem_t *
qfv_load_renderpass (vulkan_ctx_t *ctx, const char *name)
{
if (!ctx->renderpassDef) {
ctx->renderpassDef = PL_GetPropertyList (quakeforge_renderpass,
&ctx->hashlinks);
}
plitem_t *item = ctx->renderpassDef;
if (!item || !(item = PL_ObjectForKey (item, name))) {
Sys_Printf ("error loading %s\n", name);
} else {
Sys_Printf ("Found %s def\n", name);
}
return item;
}
static size_t
get_image_size (VkImage image, qfv_device_t *device)
{
qfv_devfuncs_t *dfunc = device->funcs;
size_t size;
size_t align;
VkMemoryRequirements requirements;
dfunc->vkGetImageMemoryRequirements (device->dev, image, &requirements);
size = requirements.size;
align = requirements.alignment - 1;
size = (size + align) & ~(align);
return size;
}
void void
Vulkan_CreateRenderPass (vulkan_ctx_t *ctx) Vulkan_CreateRenderPass (vulkan_ctx_t *ctx)
{ {
const char *name = "renderpass";//FIXME const char *name = "renderpass";//FIXME
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;
ctx->msaaSamples = min ((VkSampleCountFlagBits) msaaSamples->int_val, plitem_t *item = qfv_load_renderpass (ctx, name);
QFV_GetMaxSampleCount (device->physDev));
if (ctx->msaaSamples > 1) {
name = "renderpass_msaa";
}
//FIXME a tad inconsistent ctx->renderpass = QFV_ParseRenderPass (ctx, item, ctx->renderpassDef);
plitem_t *item = qfv_load_pipeline (ctx, name);
if (!item) {
return;
}
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, ctx->msaaSamples,
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, ctx->msaaSamples,
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, ~0ull);
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;
ctx->renderpass.renderpass = QFV_ParseRenderPass (ctx, item);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS, QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_RENDER_PASS,
ctx->renderpass.renderpass, ctx->renderpass, va (ctx->va_ctx, "renderpass:%s",
va (ctx->va_ctx, "pipeline:%s", name)); name));
} }
void void
Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx) Vulkan_DestroyRenderPass (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device;
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);
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;
} }
VkPipeline VkPipeline
@ -401,7 +331,7 @@ Vulkan_CreatePipeline (vulkan_ctx_t *ctx, const char *name)
} else { } else {
Sys_Printf ("Found pipeline def %s\n", name); Sys_Printf ("Found pipeline def %s\n", name);
} }
VkPipeline pipeline = QFV_ParsePipeline (ctx, item); VkPipeline pipeline = QFV_ParsePipeline (ctx, item, ctx->pipelineDef);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline, QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE, pipeline,
va (ctx->va_ctx, "pipeline:%s", name)); va (ctx->va_ctx, "pipeline:%s", name));
return pipeline; return pipeline;
@ -425,7 +355,7 @@ Vulkan_CreateDescriptorPool (vulkan_ctx_t *ctx, const char *name)
} else { } else {
Sys_Printf ("Found descriptor pool def %s\n", name); Sys_Printf ("Found descriptor pool def %s\n", name);
} }
pool = QFV_ParseDescriptorPool (ctx, item); pool = QFV_ParseDescriptorPool (ctx, item, ctx->pipelineDef);
QFV_AddHandle (tab, path, (uint64_t) pool); QFV_AddHandle (tab, path, (uint64_t) pool);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool, QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_POOL, pool,
va (ctx->va_ctx, "descriptor_pool:%s", name)); va (ctx->va_ctx, "descriptor_pool:%s", name));
@ -450,7 +380,7 @@ Vulkan_CreatePipelineLayout (vulkan_ctx_t *ctx, const char *name)
} else { } else {
Sys_Printf ("Found pipeline layout def %s\n", name); Sys_Printf ("Found pipeline layout def %s\n", name);
} }
layout = QFV_ParsePipelineLayout (ctx, item); layout = QFV_ParsePipelineLayout (ctx, item, ctx->pipelineDef);
QFV_AddHandle (tab, path, (uint64_t) layout); QFV_AddHandle (tab, path, (uint64_t) layout);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout, QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_PIPELINE_LAYOUT, layout,
va (ctx->va_ctx, "pipeline_layout:%s", name)); va (ctx->va_ctx, "pipeline_layout:%s", name));
@ -475,7 +405,7 @@ Vulkan_CreateSampler (vulkan_ctx_t *ctx, const char *name)
} else { } else {
Sys_Printf ("Found sampler def %s\n", name); Sys_Printf ("Found sampler def %s\n", name);
} }
sampler = QFV_ParseSampler (ctx, item); sampler = QFV_ParseSampler (ctx, item, ctx->pipelineDef);
QFV_AddHandle (tab, path, (uint64_t) sampler); QFV_AddHandle (tab, path, (uint64_t) sampler);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler, QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_SAMPLER, sampler,
va (ctx->va_ctx, "sampler:%s", name)); va (ctx->va_ctx, "sampler:%s", name));
@ -500,7 +430,7 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name)
} else { } else {
Sys_Printf ("Found descriptor set def %s\n", name); Sys_Printf ("Found descriptor set def %s\n", name);
} }
set = QFV_ParseDescriptorSetLayout (ctx, item); set = QFV_ParseDescriptorSetLayout (ctx, item, ctx->pipelineDef);
QFV_AddHandle (tab, path, (uint64_t) set); QFV_AddHandle (tab, path, (uint64_t) set);
QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, QFV_duSetObjectName (ctx->device, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT,
set, va (ctx->va_ctx, "descriptor_set:%s", name)); set, va (ctx->va_ctx, "descriptor_set:%s", name));
@ -508,7 +438,7 @@ Vulkan_CreateDescriptorSetLayout(vulkan_ctx_t *ctx, const char *name)
} }
void void
Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx) Vulkan_CreateFrames (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
VkCommandPool cmdpool = ctx->cmdpool; VkCommandPool cmdpool = ctx->cmdpool;
@ -531,13 +461,16 @@ Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx)
frame->renderDoneSemaphore = QFV_CreateSemaphore (device); frame->renderDoneSemaphore = QFV_CreateSemaphore (device);
frame->cmdBuffer = cmdBuffers->a[i]; frame->cmdBuffer = cmdBuffers->a[i];
frame->subCommand = malloc (sizeof (qfv_cmdbufferset_t)); frame->cmdSetCount = QFV_NumPasses;
DARRAY_INIT (frame->subCommand, 4); frame->cmdSets = malloc (QFV_NumPasses * sizeof (qfv_cmdbufferset_t));
for (int j = 0; j < QFV_NumPasses; j++) {
DARRAY_INIT (&frame->cmdSets[j], 4);
}
} }
} }
void void
Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx) Vulkan_DestroyFrames (vulkan_ctx_t *ctx)
{ {
qfv_device_t *device = ctx->device; qfv_device_t *device = ctx->device;
qfv_devfuncs_t *df = device->funcs; qfv_devfuncs_t *df = device->funcs;
@ -553,3 +486,59 @@ Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx)
DARRAY_CLEAR (&ctx->frames); DARRAY_CLEAR (&ctx->frames);
} }
void
Vulkan_CreateFramebuffers (vulkan_ctx_t *ctx)
{
qfv_device_t *device = ctx->device;
plitem_t *item = qfv_load_renderpass (ctx, "images");
if (!item) {
return;
}
__auto_type images = QFV_ParseImageSet (ctx, item, ctx->renderpassDef);
ctx->attachment_images = images;
size_t memSize = 0;
for (size_t i = 0; i < images->size; i++) {
memSize += get_image_size (images->a[i], device);
}
VkDeviceMemory mem;
mem = QFV_AllocImageMemory (device, images->a[0],
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
memSize, 0);
ctx->attachmentMemory = mem;
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
mem, "memory:framebuffers");
size_t offset = 0;
for (size_t i = 0; i < images->size; i++) {
QFV_BindImageMemory (device, images->a[i], mem, offset);
offset += get_image_size (images->a[i], device);
}
item = qfv_load_renderpass (ctx, "imageViews");
if (!item) {
return;
}
__auto_type views = QFV_ParseImageViewSet (ctx, item, ctx->renderpassDef);
ctx->attachment_views = views;
item = qfv_load_renderpass (ctx, "framebuffer");
if (!item) {
return;
}
ctx->framebuffers = QFV_AllocFrameBuffers (ctx->swapchain->numImages,
malloc);
for (size_t i = 0; i < ctx->framebuffers->size; i++) {
ctx->swapImageIndex = i;
ctx->framebuffers->a[i] = QFV_ParseFramebuffer (ctx, item,
ctx->renderpassDef);
}
}
void
Vulkan_DestroyFramebuffers (vulkan_ctx_t *ctx)
{
}