mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-22 12:31:10 +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/scene/light.h"
|
||||
#include "QF/Vulkan/qf_vid.h"
|
||||
#include "QF/Vulkan/qf_renderpass.h"
|
||||
#include "QF/Vulkan/command.h"
|
||||
#include "QF/Vulkan/image.h"
|
||||
#include "QF/simd/types.h"
|
||||
|
@ -79,6 +80,20 @@ typedef struct lightingframe_s {
|
|||
typedef struct lightingframeset_s
|
||||
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 {
|
||||
lightingframeset_t frames;
|
||||
VkPipeline pipeline;
|
||||
|
@ -86,10 +101,16 @@ typedef struct lightingctx_s {
|
|||
VkSampler sampler;
|
||||
VkDeviceMemory light_memory;
|
||||
VkDeviceMemory shadow_memory;
|
||||
qfv_lightmatset_t lightmats;
|
||||
qfv_imageset_t lightimages;
|
||||
lightintset_t lightlayers;
|
||||
qfv_imageviewset_t lightviews;
|
||||
qfv_lightmatset_t light_mats;
|
||||
qfv_imageset_t light_images;
|
||||
light_renderer_set_t light_renderers;
|
||||
|
||||
qfv_renderpass_t *qfv_renderpass;
|
||||
VkRenderPass renderpass_6;
|
||||
VkRenderPass renderpass_4;
|
||||
VkRenderPass renderpass_1;
|
||||
|
||||
VkCommandPool cmdpool;
|
||||
|
||||
struct lightingdata_s *ldata;
|
||||
struct scene_s *scene;
|
||||
|
@ -98,6 +119,7 @@ typedef struct lightingctx_s {
|
|||
struct vulkan_ctx_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_Shutdown (struct vulkan_ctx_s *ctx);
|
||||
void Vulkan_Lighting_Draw (struct qfv_renderframe_s *rFrame);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <vulkan/vulkan.h>
|
||||
|
||||
enum {
|
||||
QFV_rp_shadowmap,
|
||||
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 = (
|
||||
{ depthStencil = { depth = 1; stencil = 0; }; },
|
||||
);
|
||||
renderpass = {
|
||||
@next = (VkRenderPassMultiviewCreateInfo, {
|
||||
viewMasks = (0xffffffff);
|
||||
});
|
||||
info = {
|
||||
color = "[0.2, 0.2, 0.2, 1]";
|
||||
subpass_info = (
|
||||
{ name = depth; color = "[ 0.5, 0.5, 0.5, 1]" },
|
||||
);
|
||||
};
|
||||
renderpass_base = {
|
||||
attachments = (
|
||||
{
|
||||
format = $properties.images.shadow.format;
|
||||
format = $output.format;
|
||||
samples = 1;
|
||||
loadOp = dont_care;
|
||||
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 "vid_vulkan.h"
|
||||
#include "vkparse.h"
|
||||
|
||||
static void
|
||||
update_lights (vulkan_ctx_t *ctx)
|
||||
|
@ -217,6 +218,75 @@ Vulkan_Lighting_Draw (qfv_renderframe_t *rFrame)
|
|||
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 = {
|
||||
0, 0, VK_WHOLE_SIZE
|
||||
};
|
||||
|
@ -250,13 +320,24 @@ Vulkan_Lighting_Init (vulkan_ctx_t *ctx)
|
|||
|
||||
qfvPushDebug (ctx, "lighting init");
|
||||
|
||||
lightingctx_t *lctx = calloc (1, sizeof (lightingctx_t));
|
||||
ctx->lighting_context = lctx;
|
||||
// lighting_context initialized in Vulkan_Lighting_CreateRenderPasses
|
||||
|
||||
DARRAY_INIT (&lctx->lightmats, 16);
|
||||
DARRAY_INIT (&lctx->lightlayers, 16);
|
||||
DARRAY_INIT (&lctx->lightimages, 16);
|
||||
DARRAY_INIT (&lctx->lightviews, 16);
|
||||
ctx->output = (qfv_output_t) {.format = VK_FORMAT_X8_D24_UNORM_PACK32 };
|
||||
lightingctx_t *lctx = ctx->lighting_context;
|
||||
plitem_t *rp_def = lctx->qfv_renderpass->renderpassDef;
|
||||
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;
|
||||
DARRAY_INIT (&lctx->frames, frames);
|
||||
|
@ -382,14 +463,16 @@ clear_shadows (vulkan_ctx_t *ctx)
|
|||
dfunc->vkFreeMemory (device->dev, lctx->shadow_memory, 0);
|
||||
lctx->shadow_memory = 0;
|
||||
}
|
||||
for (size_t i = 0; i < lctx->lightviews.size; i++) {
|
||||
dfunc->vkDestroyImageView (device->dev, lctx->lightviews.a[i], 0);
|
||||
for (size_t i = 0; i < lctx->light_renderers.size; i++) {
|
||||
__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++) {
|
||||
dfunc->vkDestroyImage (device->dev, lctx->lightimages.a[i], 0);
|
||||
for (size_t i = 0; i < lctx->light_images.size; i++) {
|
||||
dfunc->vkDestroyImage (device->dev, lctx->light_images.a[i], 0);
|
||||
}
|
||||
lctx->lightimages.size = 0;
|
||||
lctx->lightviews.size = 0;
|
||||
lctx->light_images.size = 0;
|
||||
lctx->light_renderers.size = 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -401,16 +484,20 @@ Vulkan_Lighting_Shutdown (vulkan_ctx_t *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++) {
|
||||
lightingframe_t *lframe = &lctx->frames.a[i];
|
||||
dfunc->vkDestroyBuffer (device->dev, lframe->light_buffer, 0);
|
||||
}
|
||||
dfunc->vkFreeMemory (device->dev, lctx->light_memory, 0);
|
||||
dfunc->vkDestroyPipeline (device->dev, lctx->pipeline, 0);
|
||||
DARRAY_CLEAR (&lctx->lightmats);
|
||||
DARRAY_CLEAR (&lctx->lightimages);
|
||||
DARRAY_CLEAR (&lctx->lightlayers);
|
||||
DARRAY_CLEAR (&lctx->lightviews);
|
||||
DARRAY_CLEAR (&lctx->light_mats);
|
||||
DARRAY_CLEAR (&lctx->light_images);
|
||||
DARRAY_CLEAR (&lctx->light_renderers);
|
||||
free (lctx->frames.a);
|
||||
free (lctx);
|
||||
}
|
||||
|
@ -421,7 +508,7 @@ static void
|
|||
create_light_matrices (lightingctx_t *lctx)
|
||||
{
|
||||
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++) {
|
||||
light_t *light = &ldata->lights.a[i];
|
||||
mat4f_t view;
|
||||
|
@ -469,7 +556,7 @@ create_light_matrices (lightingctx_t *lctx)
|
|||
QFV_PerspectiveCos (proj, -light->direction[3]);
|
||||
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
|
||||
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_devfuncs_t *dfunc = device->funcs;
|
||||
|
||||
int layers = 0;
|
||||
VkImageViewType type = 0;
|
||||
const char *viewtype = 0;
|
||||
|
||||
switch (mode) {
|
||||
switch (lr->mode) {
|
||||
case ST_NONE:
|
||||
return 0;
|
||||
case ST_PLANE:
|
||||
layers = 1;
|
||||
type = VK_IMAGE_VIEW_TYPE_2D;
|
||||
viewtype = "plane";
|
||||
break;
|
||||
case ST_CASCADE:
|
||||
layers = 4;
|
||||
type = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
viewtype = "cascade";
|
||||
break;
|
||||
case ST_CUBE:
|
||||
layers = 6;
|
||||
type = VK_IMAGE_VIEW_TYPE_CUBE;
|
||||
viewtype = "cube";
|
||||
break;
|
||||
|
@ -553,14 +636,14 @@ create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx)
|
|||
VkImageViewCreateInfo createInfo = {
|
||||
VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 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_IMAGE_ASPECT_DEPTH_BIT, 0, 1, baseLayer, layers }
|
||||
{ VK_IMAGE_ASPECT_DEPTH_BIT, 0, 1, lr->layer, lr->numLayers }
|
||||
};
|
||||
|
||||
VkImageView view;
|
||||
|
@ -572,6 +655,26 @@ create_view (VkImage image, int baseLayer, int mode, int id, vulkan_ctx_t *ctx)
|
|||
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
|
||||
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++) {
|
||||
lightMap[i] = i;
|
||||
}
|
||||
DARRAY_RESIZE (&lctx->lightlayers, numLights);
|
||||
heapsort_r (lightMap, numLights, sizeof (int), light_compare, ldata);
|
||||
|
||||
DARRAY_RESIZE (&lctx->light_renderers, numLights);
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
int layers = 1;
|
||||
int shadow = ST_NONE;
|
||||
int li = lightMap[i];
|
||||
__auto_type lr = &lctx->light_renderers.a[li];
|
||||
|
||||
lr->mode = ST_NONE;
|
||||
if (!lights[li].position[3]) {
|
||||
shadow = ST_CASCADE;
|
||||
lr->mode = ST_CASCADE;
|
||||
} else {
|
||||
if (lights[li].direction[3] > -0.5) {
|
||||
shadow = ST_CUBE;
|
||||
lr->mode = ST_CUBE;
|
||||
} 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
|
||||
// shadow map at all
|
||||
imageMap[li] = -1;
|
||||
continue;
|
||||
}
|
||||
if (shadow == ST_CUBE) {
|
||||
if (lr->mode == ST_CUBE) {
|
||||
layers = 6;
|
||||
}
|
||||
if (size != abs ((int) lights[li].color[3])
|
||||
|| numLayers + layers > maxLayers) {
|
||||
if (numLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||
numLayers = 0;
|
||||
}
|
||||
size = abs ((int) lights[li].color[3]);
|
||||
}
|
||||
imageMap[li] = lctx->lightimages.size;
|
||||
lctx->lightlayers.a[li] = numLayers;
|
||||
imageMap[li] = lctx->light_images.size;
|
||||
lr->size = size;
|
||||
lr->layer = numLayers;
|
||||
lr->numLayers = layers;
|
||||
numLayers += layers;
|
||||
totalLayers += layers;
|
||||
}
|
||||
if (numLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 1, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||
}
|
||||
|
||||
numLayers = 0;
|
||||
size = 1024;
|
||||
for (int i = 0; i < numLights; i++) {
|
||||
int layers = 4;
|
||||
int shadow = ST_NONE;
|
||||
int li = lightMap[i];
|
||||
__auto_type lr = &lctx->light_renderers.a[li];
|
||||
|
||||
if (!lights[li].position[3]) {
|
||||
shadow = ST_CASCADE;
|
||||
} else {
|
||||
if (lights[li].direction[3] > -0.5) {
|
||||
shadow = ST_CUBE;
|
||||
} else {
|
||||
shadow = ST_PLANE;
|
||||
}
|
||||
}
|
||||
|
||||
if (shadow != ST_CASCADE) {
|
||||
if (lr->mode != ST_CASCADE) {
|
||||
continue;
|
||||
}
|
||||
if (numLayers + layers > maxLayers) {
|
||||
VkImage shadow_map = create_map (size, numLayers, 0, ctx);
|
||||
DARRAY_APPEND (&lctx->lightimages, shadow_map);
|
||||
DARRAY_APPEND (&lctx->light_images, shadow_map);
|
||||
numLayers = 0;
|
||||
}
|
||||
imageMap[li] = lctx->lightimages.size;
|
||||
lctx->lightlayers.a[li] = numLayers;
|
||||
imageMap[li] = lctx->light_images.size;
|
||||
lr->size = size;
|
||||
lr->layer = numLayers;
|
||||
lr->numLayers = layers;
|
||||
numLayers += layers;
|
||||
totalLayers += layers;
|
||||
}
|
||||
if (numLayers) {
|
||||
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++) {
|
||||
memsize += QFV_GetImageSize (device, lctx->lightimages.a[i]);
|
||||
for (size_t i = 0; i < lctx->light_images.size; 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,
|
||||
memsize, 0);
|
||||
QFV_duSetObjectName (device, VK_OBJECT_TYPE_DEVICE_MEMORY,
|
||||
lctx->shadow_memory, "memory:shadowmap");
|
||||
|
||||
size_t offset = 0;
|
||||
for (size_t i = 0; i < lctx->lightimages.size; i++) {
|
||||
dfunc->vkBindImageMemory (device->dev, lctx->lightimages.a[i],
|
||||
for (size_t i = 0; i < lctx->light_images.size; i++) {
|
||||
dfunc->vkBindImageMemory (device->dev, lctx->light_images.a[i],
|
||||
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++) {
|
||||
int li = lightMap[i];
|
||||
__auto_type lr = &lctx->light_renderers.a[li];
|
||||
|
||||
if (imageMap[li] == -1) {
|
||||
lctx->lightviews.a[li] = 0;
|
||||
*lr = (light_renderer_t) {};
|
||||
continue;
|
||||
}
|
||||
int mode = ST_NONE;
|
||||
|
||||
if (!ldata->lights.a[li].position[3]) {
|
||||
mode = ST_CASCADE;
|
||||
} else {
|
||||
if (ldata->lights.a[li].direction[3] > -0.5) {
|
||||
mode = ST_CUBE;
|
||||
} else {
|
||||
mode = ST_PLANE;
|
||||
}
|
||||
switch (lr->numLayers) {
|
||||
case 6:
|
||||
lr->renderPass = lctx->renderpass_6;
|
||||
break;
|
||||
case 4:
|
||||
lr->renderPass = lctx->renderpass_4;
|
||||
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]],
|
||||
lctx->lightlayers.a[li],
|
||||
mode, li, ctx);
|
||||
lr->image = lctx->light_images.a[imageMap[li]];
|
||||
lr->view = create_view (lr, li, ctx);
|
||||
lr->framebuffer = create_framebuffer(lr, ctx);
|
||||
}
|
||||
Sys_MaskPrintf (SYS_vulkan, "shadow maps: %d layers in %zd images: %zd\n",
|
||||
totalLayers, lctx->lightimages.size, memsize);
|
||||
Sys_MaskPrintf (SYS_vulkan,
|
||||
"shadow maps: %d layers in %zd images: %zd\n",
|
||||
totalLayers, lctx->light_images.size, memsize);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -374,6 +374,7 @@ void
|
|||
Vulkan_CreateRenderPasses (vulkan_ctx_t *ctx)
|
||||
{
|
||||
Vulkan_Main_CreateRenderPasses (ctx);
|
||||
Vulkan_Lighting_CreateRenderPasses (ctx);
|
||||
|
||||
heapsort (ctx->renderPasses.a, ctx->renderPasses.size,
|
||||
sizeof (qfv_renderpass_t *), renderpass_cmp);
|
||||
|
|
Loading…
Reference in a new issue