mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 14:20:59 +00:00
[vulkan] Hook up the shadow map render pass
There are some issues with the light renderers getting mangled, and only the first light is even touched (just begin and end of render pass), but this gets a lot of the framework into place.
This commit is contained in:
parent
c58a2e5f54
commit
8e7474f614
5 changed files with 233 additions and 124 deletions
|
@ -35,6 +35,7 @@
|
||||||
#include "QF/modelgen.h"
|
#include "QF/modelgen.h"
|
||||||
#include "QF/scene/light.h"
|
#include "QF/scene/light.h"
|
||||||
#include "QF/Vulkan/qf_vid.h"
|
#include "QF/Vulkan/qf_vid.h"
|
||||||
|
#include "QF/Vulkan/qf_renderpass.h"
|
||||||
#include "QF/Vulkan/command.h"
|
#include "QF/Vulkan/command.h"
|
||||||
#include "QF/Vulkan/image.h"
|
#include "QF/Vulkan/image.h"
|
||||||
#include "QF/simd/types.h"
|
#include "QF/simd/types.h"
|
||||||
|
@ -79,6 +80,20 @@ typedef struct lightingframe_s {
|
||||||
typedef struct lightingframeset_s
|
typedef struct lightingframeset_s
|
||||||
DARRAY_TYPE (lightingframe_t) lightingframeset_t;
|
DARRAY_TYPE (lightingframe_t) lightingframeset_t;
|
||||||
|
|
||||||
|
typedef struct light_renderer_s {
|
||||||
|
VkRenderPass renderPass; // shared
|
||||||
|
VkFramebuffer framebuffer;
|
||||||
|
VkImage image; // shared
|
||||||
|
VkImageView view;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t layer;
|
||||||
|
uint32_t numLayers;
|
||||||
|
int mode;
|
||||||
|
} light_renderer_t;
|
||||||
|
|
||||||
|
typedef struct light_renderer_set_s
|
||||||
|
DARRAY_TYPE (light_renderer_t) light_renderer_set_t;
|
||||||
|
|
||||||
typedef struct lightingctx_s {
|
typedef struct lightingctx_s {
|
||||||
lightingframeset_t frames;
|
lightingframeset_t frames;
|
||||||
VkPipeline pipeline;
|
VkPipeline pipeline;
|
||||||
|
@ -86,10 +101,16 @@ typedef struct lightingctx_s {
|
||||||
VkSampler sampler;
|
VkSampler sampler;
|
||||||
VkDeviceMemory light_memory;
|
VkDeviceMemory light_memory;
|
||||||
VkDeviceMemory shadow_memory;
|
VkDeviceMemory shadow_memory;
|
||||||
qfv_lightmatset_t lightmats;
|
qfv_lightmatset_t light_mats;
|
||||||
qfv_imageset_t lightimages;
|
qfv_imageset_t light_images;
|
||||||
lightintset_t lightlayers;
|
light_renderer_set_t light_renderers;
|
||||||
qfv_imageviewset_t lightviews;
|
|
||||||
|
qfv_renderpass_t *qfv_renderpass;
|
||||||
|
VkRenderPass renderpass_6;
|
||||||
|
VkRenderPass renderpass_4;
|
||||||
|
VkRenderPass renderpass_1;
|
||||||
|
|
||||||
|
VkCommandPool cmdpool;
|
||||||
|
|
||||||
struct lightingdata_s *ldata;
|
struct lightingdata_s *ldata;
|
||||||
struct scene_s *scene;
|
struct scene_s *scene;
|
||||||
|
@ -98,6 +119,7 @@ typedef struct lightingctx_s {
|
||||||
struct vulkan_ctx_s;
|
struct vulkan_ctx_s;
|
||||||
struct qfv_renderframe_s;
|
struct qfv_renderframe_s;
|
||||||
|
|
||||||
|
void Vulkan_Lighting_CreateRenderPasses (struct vulkan_ctx_s *ctx);
|
||||||
void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx);
|
void Vulkan_Lighting_Init (struct vulkan_ctx_s *ctx);
|
||||||
void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx);
|
void Vulkan_Lighting_Shutdown (struct vulkan_ctx_s *ctx);
|
||||||
void Vulkan_Lighting_Draw (struct qfv_renderframe_s *rFrame);
|
void Vulkan_Lighting_Draw (struct qfv_renderframe_s *rFrame);
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <vulkan/vulkan.h>
|
#include <vulkan/vulkan.h>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
QFV_rp_shadowmap,
|
||||||
QFV_rp_main,
|
QFV_rp_main,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,54 +1,17 @@
|
||||||
{
|
{
|
||||||
images = {
|
|
||||||
shadow = {
|
|
||||||
flags = cube_compatible;
|
|
||||||
imageType = `2d;
|
|
||||||
format = x8_d24_unorm_pack32;
|
|
||||||
samples = 1;
|
|
||||||
extent = {
|
|
||||||
width = 256; // FIXME config
|
|
||||||
height = 256; // FIXME config
|
|
||||||
depth = 1;
|
|
||||||
};
|
|
||||||
mipLevels = 1;
|
|
||||||
arrayLayers = 2048; // FIXME config
|
|
||||||
tiling = optimal;
|
|
||||||
usage = depth_stencil_attachment|sampled;
|
|
||||||
initialLayout = undefined;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
imageViews = {
|
|
||||||
shadow = {
|
|
||||||
image = depth;
|
|
||||||
viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
|
||||||
format = $properties.images.shadow.format;
|
|
||||||
components = {
|
|
||||||
r = identity; g = identity; b = identity; a = identity;
|
|
||||||
};
|
|
||||||
subresourceRange = {
|
|
||||||
aspectMask = depth;
|
|
||||||
levelCount = 1;
|
|
||||||
layerCount = $properties.images.shadow.arrayLayers;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
framebuffer = {
|
|
||||||
renderPass = $properties.renderpass;
|
|
||||||
attachments = (shadow);
|
|
||||||
width = $properties.images.shadow.extent.width;
|
|
||||||
height = $properties.images.shadow.extent.height;
|
|
||||||
layers = $properties.images.shadow.arrayLayers;
|
|
||||||
};
|
|
||||||
clearValues = (
|
clearValues = (
|
||||||
{ depthStencil = { depth = 1; stencil = 0; }; },
|
{ depthStencil = { depth = 1; stencil = 0; }; },
|
||||||
);
|
);
|
||||||
renderpass = {
|
info = {
|
||||||
@next = (VkRenderPassMultiviewCreateInfo, {
|
color = "[0.2, 0.2, 0.2, 1]";
|
||||||
viewMasks = (0xffffffff);
|
subpass_info = (
|
||||||
});
|
{ name = depth; color = "[ 0.5, 0.5, 0.5, 1]" },
|
||||||
|
);
|
||||||
|
};
|
||||||
|
renderpass_base = {
|
||||||
attachments = (
|
attachments = (
|
||||||
{
|
{
|
||||||
format = $properties.images.shadow.format;
|
format = $output.format;
|
||||||
samples = 1;
|
samples = 1;
|
||||||
loadOp = dont_care;
|
loadOp = dont_care;
|
||||||
storeOp = store;
|
storeOp = store;
|
||||||
|
@ -68,4 +31,22 @@
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
renderpass_6 = {
|
||||||
|
@inherit = $properties.renderpass_base;
|
||||||
|
@next = (VkRenderPassMultiviewCreateInfo, {
|
||||||
|
viewMasks = (0x0000003fu);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
renderpass_4 = {
|
||||||
|
@inherit = $properties.renderpass_base;
|
||||||
|
@next = (VkRenderPassMultiviewCreateInfo, {
|
||||||
|
viewMasks = (0x0000000fu);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
renderpass_1 = {
|
||||||
|
@inherit = $properties.renderpass_base;
|
||||||
|
@next = (VkRenderPassMultiviewCreateInfo, {
|
||||||
|
viewMasks = (0x00000001u);
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@
|
||||||
|
|
||||||
#include "r_internal.h"
|
#include "r_internal.h"
|
||||||
#include "vid_vulkan.h"
|
#include "vid_vulkan.h"
|
||||||
|
#include "vkparse.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_lights (vulkan_ctx_t *ctx)
|
update_lights (vulkan_ctx_t *ctx)
|
||||||
|
@ -217,6 +218,75 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame)
|
||||||
dfunc->vkEndCommandBuffer (cmd);
|
dfunc->vkEndCommandBuffer (cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lighting_draw_maps (qfv_renderframe_t *rFrame)
|
||||||
|
{
|
||||||
|
vulkan_ctx_t *ctx = rFrame->vulkan_ctx;
|
||||||
|
qfv_device_t *device = ctx->device;
|
||||||
|
qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
|
lightingctx_t *lctx = ctx->lighting_context;
|
||||||
|
|
||||||
|
if (rFrame->subpassCmdSets[0].size) {
|
||||||
|
__auto_type sets = &rFrame->subpassCmdSets[0];
|
||||||
|
dfunc->vkFreeCommandBuffers (device->dev, lctx->cmdpool,
|
||||||
|
sets->size, sets->a);
|
||||||
|
sets->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lctx->ldata) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
__auto_type bufferset = QFV_AllocCommandBufferSet (1, alloca);
|
||||||
|
QFV_AllocateCommandBuffers (device, lctx->cmdpool, 0, bufferset);
|
||||||
|
VkCommandBuffer cmd = bufferset->a[0];
|
||||||
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_COMMAND_BUFFER,
|
||||||
|
cmd, va (ctx->va_ctx, "lighting:%zd", ctx->curFrame));
|
||||||
|
|
||||||
|
VkCommandBufferBeginInfo beginInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||||
|
};
|
||||||
|
dfunc->vkBeginCommandBuffer (cmd, &beginInfo);
|
||||||
|
|
||||||
|
__auto_type rp = rFrame->renderpass;
|
||||||
|
QFV_CmdBeginLabel (device, cmd, rp->name, rp->color);
|
||||||
|
|
||||||
|
__auto_type lr = &lctx->light_renderers.a[0];
|
||||||
|
VkRenderPassBeginInfo renderPassInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
||||||
|
.renderArea = { {0, 0}, {lr->size, lr->size} },
|
||||||
|
.framebuffer = lr->framebuffer,
|
||||||
|
.renderPass = lr->renderPass,
|
||||||
|
.pClearValues = lctx->qfv_renderpass->clearValues->a,
|
||||||
|
};
|
||||||
|
__auto_type subpassContents = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
|
||||||
|
dfunc->vkCmdBeginRenderPass (cmd, &renderPassInfo, subpassContents);
|
||||||
|
//...
|
||||||
|
dfunc->vkCmdEndRenderPass (cmd);
|
||||||
|
QFV_CmdEndLabel (device, cmd);
|
||||||
|
dfunc->vkEndCommandBuffer (cmd);
|
||||||
|
|
||||||
|
DARRAY_APPEND (&rFrame->subpassCmdSets[0], cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Vulkan_Lighting_CreateRenderPasses (vulkan_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t));
|
||||||
|
ctx->lighting_context = lctx;
|
||||||
|
|
||||||
|
// extents are dynamic and filled in for each light
|
||||||
|
// frame buffers are highly dynamic
|
||||||
|
qfv_output_t output = {};
|
||||||
|
__auto_type rp = Vulkan_CreateRenderPass (ctx, "shadow",
|
||||||
|
&output, lighting_draw_maps);
|
||||||
|
rp->primary_commands = 1;
|
||||||
|
rp->order = QFV_rp_shadowmap;
|
||||||
|
DARRAY_APPEND (&ctx->renderPasses, rp);
|
||||||
|
|
||||||
|
lctx->qfv_renderpass = rp;
|
||||||
|
}
|
||||||
|
|
||||||
static VkDescriptorBufferInfo base_buffer_info = {
|
static VkDescriptorBufferInfo base_buffer_info = {
|
||||||
0, 0, VK_WHOLE_SIZE
|
0, 0, VK_WHOLE_SIZE
|
||||||
};
|
};
|
||||||
|
@ -250,13 +320,24 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
|
||||||
|
|
||||||
qfvPushDebug (ctx, "lighting init");
|
qfvPushDebug (ctx, "lighting init");
|
||||||
|
|
||||||
lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t));
|
// lighting_context initialized in Vulkan_Lighting_CreateRenderPasses
|
||||||
ctx->lighting_context = lctx;
|
|
||||||
|
|
||||||
DARRAY_INIT (&lctx->lightmats, 16);
|
ctx->output = (qfv_output_t) {.format = VK_FORMAT_X8_D24_UNORM_PACK32 };
|
||||||
DARRAY_INIT (&lctx->lightlayers, 16);
|
lightingctx_t *lctx = ctx->lighting_context;
|
||||||
DARRAY_INIT (&lctx->lightimages, 16);
|
plitem_t *rp_def = lctx->qfv_renderpass->renderpassDef;
|
||||||
DARRAY_INIT (&lctx->lightviews, 16);
|
plitem_t *rp_cfg = PL_ObjectForKey (rp_def, "renderpass_6");
|
||||||
|
lctx->renderpass_6 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def);
|
||||||
|
rp_cfg = PL_ObjectForKey (rp_def, "renderpass_4");
|
||||||
|
lctx->renderpass_4 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def);
|
||||||
|
rp_cfg = PL_ObjectForKey (rp_def, "renderpass_1");
|
||||||
|
lctx->renderpass_1 = QFV_ParseRenderPass (ctx, rp_cfg, rp_def);
|
||||||
|
|
||||||
|
lctx->cmdpool = QFV_CreateCommandPool (device, device->queue.queueFamily,
|
||||||
|
1, 1);
|
||||||
|
|
||||||
|
DARRAY_INIT (&lctx->light_mats, 16);
|
||||||
|
DARRAY_INIT (&lctx->light_images, 16);
|
||||||
|
DARRAY_INIT (&lctx->light_renderers, 16);
|
||||||
|
|
||||||
size_t frames = ctx->frames.size;
|
size_t frames = ctx->frames.size;
|
||||||
DARRAY_INIT (&lctx->frames, frames);
|
DARRAY_INIT (&lctx->frames, frames);
|
||||||
|
@ -382,14 +463,16 @@ clear_shadows (vulkan_ctx_t *ctx)
|
||||||
dfunc->vkFreeMemory (device->dev, lctx->shadow_memory, 0);
|
dfunc->vkFreeMemory (device->dev, lctx->shadow_memory, 0);
|
||||||
lctx->shadow_memory = 0;
|
lctx->shadow_memory = 0;
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < lctx->lightviews.size; i++) {
|
for (size_t i = 0; i < lctx->light_renderers.size; i++) {
|
||||||
dfunc->vkDestroyImageView (device->dev, lctx->lightviews.a[i], 0);
|
__auto_type lr = &lctx->light_renderers.a[i];
|
||||||
|
dfunc->vkDestroyFramebuffer (device->dev, lr->framebuffer, 0);
|
||||||
|
dfunc->vkDestroyImageView (device->dev, lr->view, 0);
|
||||||
}
|
}
|
||||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
for (size_t i = 0; i < lctx->light_images.size; i++) {
|
||||||
dfunc->vkDestroyImage (device->dev, lctx->lightimages.a[i], 0);
|
dfunc->vkDestroyImage (device->dev, lctx->light_images.a[i], 0);
|
||||||
}
|
}
|
||||||
lctx->lightimages.size = 0;
|
lctx->light_images.size = 0;
|
||||||
lctx->lightviews.size = 0;
|
lctx->light_renderers.size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -401,16 +484,20 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *ctx)
|
||||||
|
|
||||||
clear_shadows (ctx);
|
clear_shadows (ctx);
|
||||||
|
|
||||||
|
dfunc->vkDestroyCommandPool (device->dev, lctx->cmdpool, 0);
|
||||||
|
dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_6, 0);
|
||||||
|
dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_4, 0);
|
||||||
|
dfunc->vkDestroyRenderPass (device->dev, lctx->renderpass_1, 0);
|
||||||
|
|
||||||
for (size_t i = 0; i < lctx->frames.size; i++) {
|
for (size_t i = 0; i < lctx->frames.size; i++) {
|
||||||
lightingframe_t *lframe = &lctx->frames.a[i];
|
lightingframe_t *lframe = &lctx->frames.a[i];
|
||||||
dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0);
|
dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0);
|
||||||
}
|
}
|
||||||
dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0);
|
dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0);
|
||||||
dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0);
|
dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0);
|
||||||
DARRAY_CLEAR (&lctx->lightmats);
|
DARRAY_CLEAR (&lctx->light_mats);
|
||||||
DARRAY_CLEAR (&lctx->lightimages);
|
DARRAY_CLEAR (&lctx->light_images);
|
||||||
DARRAY_CLEAR (&lctx->lightlayers);
|
DARRAY_CLEAR (&lctx->light_renderers);
|
||||||
DARRAY_CLEAR (&lctx->lightviews);
|
|
||||||
free (lctx->frames.a);
|
free (lctx->frames.a);
|
||||||
free (lctx);
|
free (lctx);
|
||||||
}
|
}
|
||||||
|
@ -421,7 +508,7 @@ static void
|
||||||
create_light_matrices (lightingctx_t *lctx)
|
create_light_matrices (lightingctx_t *lctx)
|
||||||
{
|
{
|
||||||
lightingdata_t *ldata = lctx->ldata;
|
lightingdata_t *ldata = lctx->ldata;
|
||||||
DARRAY_RESIZE (&lctx->lightmats, ldata->lights.size);
|
DARRAY_RESIZE (&lctx->light_mats, ldata->lights.size);
|
||||||
for (size_t i = 0; i < ldata->lights.size; i++) {
|
for (size_t i = 0; i < ldata->lights.size; i++) {
|
||||||
light_t *light = &ldata->lights.a[i];
|
light_t *light = &ldata->lights.a[i];
|
||||||
mat4f_t view;
|
mat4f_t view;
|
||||||
|
@ -469,7 +556,7 @@ create_light_matrices (lightingctx_t *lctx)
|
||||||
QFV_PerspectiveCos (proj, -light->direction[3]);
|
QFV_PerspectiveCos (proj, -light->direction[3]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mmulf (lctx->lightmats.a[i], proj, view);
|
mmulf (lctx->light_mats.a[i], proj, view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,30 +608,26 @@ create_map (int size, int layers, int cube, vulkan_ctx_t *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
static VkImageView
|
static VkImageView
|
||||||
create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx)
|
create_view (const light_renderer_t *lr, int id, 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;
|
||||||
|
|
||||||
int layers = 0;
|
|
||||||
VkImageViewType type = 0;
|
VkImageViewType type = 0;
|
||||||
const char *viewtype = 0;
|
const char *viewtype = 0;
|
||||||
|
|
||||||
switch (mode) {
|
switch (lr->mode) {
|
||||||
case ST_NONE:
|
case ST_NONE:
|
||||||
return 0;
|
return 0;
|
||||||
case ST_PLANE:
|
case ST_PLANE:
|
||||||
layers = 1;
|
|
||||||
type = VK_IMAGE_VIEW_TYPE_2D;
|
type = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
viewtype = "plane";
|
viewtype = "plane";
|
||||||
break;
|
break;
|
||||||
case ST_CASCADE:
|
case ST_CASCADE:
|
||||||
layers = 4;
|
|
||||||
type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||||
viewtype = "cascade";
|
viewtype = "cascade";
|
||||||
break;
|
break;
|
||||||
case ST_CUBE:
|
case ST_CUBE:
|
||||||
layers = 6;
|
|
||||||
type = VK_IMAGE_VIEW_TYPE_CUBE;
|
type = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||||
viewtype = "cube";
|
viewtype = "cube";
|
||||||
break;
|
break;
|
||||||
|
@ -553,14 +636,14 @@ create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx)
|
||||||
VkImageViewCreateInfo createInfo = {
|
VkImageViewCreateInfo createInfo = {
|
||||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0,
|
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 0,
|
||||||
0,
|
0,
|
||||||
image, type, VK_FORMAT_X8_D24_UNORM_PACK32,
|
lr->image, type, VK_FORMAT_X8_D24_UNORM_PACK32,
|
||||||
{
|
{
|
||||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||||
},
|
},
|
||||||
{ VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, baseLayer, layers }
|
{ VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, lr->layer, lr->numLayers }
|
||||||
};
|
};
|
||||||
|
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
|
@ -572,6 +655,26 @@ create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx)
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VkFramebuffer
|
||||||
|
create_framebuffer (const light_renderer_t *lr, vulkan_ctx_t *ctx)
|
||||||
|
{
|
||||||
|
qfv_device_t *device = ctx->device;
|
||||||
|
qfv_devfuncs_t *dfunc = device->funcs;
|
||||||
|
|
||||||
|
VkFramebuffer framebuffer;
|
||||||
|
VkFramebufferCreateInfo cInfo = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
||||||
|
.renderPass = lr->renderPass,
|
||||||
|
.attachmentCount = 1,
|
||||||
|
.pAttachments = &lr->view,
|
||||||
|
.width = lr->size,
|
||||||
|
.height = lr->size,
|
||||||
|
.layers = 1,
|
||||||
|
};
|
||||||
|
dfunc->vkCreateFramebuffer (device->dev, &cInfo, 0, &framebuffer);
|
||||||
|
return framebuffer;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx)
|
build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
|
@ -592,126 +695,127 @@ build_shadow_maps (lightingctx_t *lctx, vulkan_ctx_t *ctx)
|
||||||
for (int i = 0; i < numLights; i++) {
|
for (int i = 0; i < numLights; i++) {
|
||||||
lightMap[i] = i;
|
lightMap[i] = i;
|
||||||
}
|
}
|
||||||
DARRAY_RESIZE (&lctx->lightlayers, numLights);
|
|
||||||
heapsort_r (lightMap, numLights, sizeof (int), light_compare, ldata);
|
heapsort_r (lightMap, numLights, sizeof (int), light_compare, ldata);
|
||||||
|
|
||||||
|
DARRAY_RESIZE (&lctx->light_renderers, numLights);
|
||||||
for (int i = 0; i < numLights; i++) {
|
for (int i = 0; i < numLights; i++) {
|
||||||
int layers = 1;
|
int layers = 1;
|
||||||
int shadow = ST_NONE;
|
|
||||||
int li = lightMap[i];
|
int li = lightMap[i];
|
||||||
|
__auto_type lr = &lctx->light_renderers.a[li];
|
||||||
|
|
||||||
|
lr->mode = ST_NONE;
|
||||||
if (!lights[li].position[3]) {
|
if (!lights[li].position[3]) {
|
||||||
shadow = ST_CASCADE;
|
lr->mode = ST_CASCADE;
|
||||||
} else {
|
} else {
|
||||||
if (lights[li].direction[3] > -0.5) {
|
if (lights[li].direction[3] > -0.5) {
|
||||||
shadow = ST_CUBE;
|
lr->mode = ST_CUBE;
|
||||||
} else {
|
} else {
|
||||||
shadow = ST_PLANE;
|
lr->mode = ST_PLANE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shadow == ST_CASCADE || shadow == ST_NONE) {
|
if (lr->mode == ST_CASCADE || lr->mode == ST_NONE) {
|
||||||
// cascade shadows will be handled separately, and "none" has no
|
// cascade shadows will be handled separately, and "none" has no
|
||||||
// shadow map at all
|
// shadow map at all
|
||||||
imageMap[li] = -1;
|
imageMap[li] = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (shadow == ST_CUBE) {
|
if (lr->mode == ST_CUBE) {
|
||||||
layers = 6;
|
layers = 6;
|
||||||
}
|
}
|
||||||
if (size != abs ((int) lights[li].color[3])
|
if (size != abs ((int) lights[li].color[3])
|
||||||
|| numLayers + layers > maxLayers) {
|
|| numLayers + layers > maxLayers) {
|
||||||
if (numLayers) {
|
if (numLayers) {
|
||||||
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
||||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||||
numLayers = 0;
|
numLayers = 0;
|
||||||
}
|
}
|
||||||
size = abs ((int) lights[li].color[3]);
|
size = abs ((int) lights[li].color[3]);
|
||||||
}
|
}
|
||||||
imageMap[li] = lctx->lightimages.size;
|
imageMap[li] = lctx->light_images.size;
|
||||||
lctx->lightlayers.a[li] = numLayers;
|
lr->size = size;
|
||||||
|
lr->layer = numLayers;
|
||||||
|
lr->numLayers = layers;
|
||||||
numLayers += layers;
|
numLayers += layers;
|
||||||
totalLayers += layers;
|
totalLayers += layers;
|
||||||
}
|
}
|
||||||
if (numLayers) {
|
if (numLayers) {
|
||||||
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
||||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
numLayers = 0;
|
numLayers = 0;
|
||||||
size = 1024;
|
size = 1024;
|
||||||
for (int i = 0; i < numLights; i++) {
|
for (int i = 0; i < numLights; i++) {
|
||||||
int layers = 4;
|
int layers = 4;
|
||||||
int shadow = ST_NONE;
|
|
||||||
int li = lightMap[i];
|
int li = lightMap[i];
|
||||||
|
__auto_type lr = &lctx->light_renderers.a[li];
|
||||||
|
|
||||||
if (!lights[li].position[3]) {
|
if (lr->mode != ST_CASCADE) {
|
||||||
shadow = ST_CASCADE;
|
|
||||||
} else {
|
|
||||||
if (lights[li].direction[3] > -0.5) {
|
|
||||||
shadow = ST_CUBE;
|
|
||||||
} else {
|
|
||||||
shadow = ST_PLANE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shadow != ST_CASCADE) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (numLayers + layers > maxLayers) {
|
if (numLayers + layers > maxLayers) {
|
||||||
VkImage shadow_map = create_map (size, numLayers, 0, ctx);
|
VkImage shadow_map = create_map (size, numLayers, 0, ctx);
|
||||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||||
numLayers = 0;
|
numLayers = 0;
|
||||||
}
|
}
|
||||||
imageMap[li] = lctx->lightimages.size;
|
imageMap[li] = lctx->light_images.size;
|
||||||
lctx->lightlayers.a[li] = numLayers;
|
lr->size = size;
|
||||||
|
lr->layer = numLayers;
|
||||||
|
lr->numLayers = layers;
|
||||||
numLayers += layers;
|
numLayers += layers;
|
||||||
totalLayers += layers;
|
totalLayers += layers;
|
||||||
}
|
}
|
||||||
if (numLayers) {
|
if (numLayers) {
|
||||||
VkImage shadow_map = create_map (size, numLayers, 0, ctx);
|
VkImage shadow_map = create_map (size, numLayers, 0, ctx);
|
||||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
for (size_t i = 0; i < lctx->light_images.size; i++) {
|
||||||
memsize += QFV_GetImageSize (device, lctx->lightimages.a[i]);
|
memsize += QFV_GetImageSize (device, lctx->light_images.a[i]);
|
||||||
}
|
}
|
||||||
lctx->shadow_memory = QFV_AllocImageMemory (device, lctx->lightimages.a[0],
|
lctx->shadow_memory = QFV_AllocImageMemory (device, lctx->light_images.a[0],
|
||||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||||
memsize, 0);
|
memsize, 0);
|
||||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
||||||
lctx->shadow_memory, "memory:shadowmap");
|
lctx->shadow_memory, "memory:shadowmap");
|
||||||
|
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
for (size_t i = 0; i < lctx->light_images.size; i++) {
|
||||||
dfunc->vkBindImageMemory (device->dev, lctx->lightimages.a[i],
|
dfunc->vkBindImageMemory (device->dev, lctx->light_images.a[i],
|
||||||
lctx->shadow_memory, offset);
|
lctx->shadow_memory, offset);
|
||||||
offset += QFV_GetImageSize (device, lctx->lightimages.a[i]);
|
offset += QFV_GetImageSize (device, lctx->light_images.a[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
DARRAY_RESIZE (&lctx->lightviews, numLights);
|
|
||||||
for (int i = 0; i < numLights; i++) {
|
for (int i = 0; i < numLights; i++) {
|
||||||
int li = lightMap[i];
|
int li = lightMap[i];
|
||||||
|
__auto_type lr = &lctx->light_renderers.a[li];
|
||||||
|
|
||||||
if (imageMap[li] == -1) {
|
if (imageMap[li] == -1) {
|
||||||
lctx->lightviews.a[li] = 0;
|
*lr = (light_renderer_t) {};
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int mode = ST_NONE;
|
|
||||||
|
|
||||||
if (!ldata->lights.a[li].position[3]) {
|
switch (lr->numLayers) {
|
||||||
mode = ST_CASCADE;
|
case 6:
|
||||||
} else {
|
lr->renderPass = lctx->renderpass_6;
|
||||||
if (ldata->lights.a[li].direction[3] > -0.5) {
|
break;
|
||||||
mode = ST_CUBE;
|
case 4:
|
||||||
} else {
|
lr->renderPass = lctx->renderpass_4;
|
||||||
mode = ST_PLANE;
|
break;
|
||||||
}
|
case 1:
|
||||||
|
lr->renderPass = lctx->renderpass_1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Sys_Error ("build_shadow_maps: invalid light layer count: %u",
|
||||||
|
lr->numLayers);
|
||||||
}
|
}
|
||||||
lctx->lightviews.a[li] = create_view (lctx->lightimages.a[imageMap[li]],
|
lr->image = lctx->light_images.a[imageMap[li]];
|
||||||
lctx->lightlayers.a[li],
|
lr->view = create_view (lr, li, ctx);
|
||||||
mode, li, ctx);
|
lr->framebuffer = create_framebuffer(lr, ctx);
|
||||||
}
|
}
|
||||||
Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n",
|
Sys_MaskPrintf (SYS_vulkan,
|
||||||
totalLayers, lctx->lightimages.size, memsize);
|
"shadow maps: %d layers in %zd images: %zd\n",
|
||||||
|
totalLayers, lctx->light_images.size, memsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -374,6 +374,7 @@ void
|
||||||
Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx)
|
Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx)
|
||||||
{
|
{
|
||||||
Vulkan_Main_CreateRenderPasses (ctx);
|
Vulkan_Main_CreateRenderPasses (ctx);
|
||||||
|
Vulkan_Lighting_CreateRenderPasses (ctx);
|
||||||
|
|
||||||
heapsort (ctx->renderPasses.a, ctx->renderPasses.size,
|
heapsort (ctx->renderPasses.a, ctx->renderPasses.size,
|
||||||
sizeof (qfv_renderpass_t *), renderpass_cmp);
|
sizeof (qfv_renderpass_t *), renderpass_cmp);
|
||||||
|
|
Loading…
Reference in a new issue