[wip] begin creating gbuffer resources based on meatpipe description
This commit is contained in:
parent
fbf2d7096d
commit
1ef9526aff
|
@ -1,4 +1,5 @@
|
|||
#include "ray_pass.h"
|
||||
#include "shaders/ray_interop.h" // for SPEC_SBT_RECORD_SIZE_INDEX
|
||||
#include "ray_resources.h"
|
||||
#include "vk_pipeline.h"
|
||||
#include "vk_descriptor.h"
|
||||
|
|
|
@ -6,74 +6,8 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#define MAX_BARRIERS 16
|
||||
#define MAX_RESOURCES 32
|
||||
#define MAX_NAME 32
|
||||
|
||||
#if 0
|
||||
typedef struct vk_named_resource_t {
|
||||
char name[MAX_NAME];
|
||||
int count;
|
||||
ray_resource_desc_t desc_fixme;
|
||||
} vk_named_resource_t;
|
||||
|
||||
static struct {
|
||||
vk_named_resource_t named[MAX_RESOURCES];
|
||||
ray_resource_t resources[RayResource__COUNT];
|
||||
} g_resources;
|
||||
|
||||
static int findSlot(const char* name) {
|
||||
// Find the exact match if exists
|
||||
// There might be gaps, so we need to check everything
|
||||
for (int i = 0; i < MAX_RESOURCES; ++i) {
|
||||
if (strcmp(g_resources.named[i].name, name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
// Find first free slot
|
||||
for (int i = 0; i < MAX_RESOURCES; ++i) {
|
||||
if (!g_resources.named[i].name[0])
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
qboolean R_VkResourceSetExternal(const char* name, VkDescriptorType type, vk_descriptor_value_t value, int count, ray_resource_desc_t desc, const xvk_image_t *image) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (strlen(name) >= MAX_NAME)
|
||||
return false;
|
||||
|
||||
const int index = findSlot(name);
|
||||
if (index < 0)
|
||||
return false;
|
||||
|
||||
vk_named_resource_t *const r = g_resources.named + index;
|
||||
ray_resource_t *const rr = g_resources.resources + index;
|
||||
|
||||
if (!r->name[0]) {
|
||||
strncpy(r->name, name, sizeof(r->name));
|
||||
rr->type = type;
|
||||
r->count = count;
|
||||
r->desc_fixme = desc;
|
||||
} else {
|
||||
ASSERT(rr->type == type);
|
||||
ASSERT(r->count == count);
|
||||
ASSERT(r->desc_fixme.type == desc.type);
|
||||
ASSERT(r->desc_fixme.image_format == desc.image_format);
|
||||
}
|
||||
|
||||
rr->value = value;
|
||||
rr->image = image;
|
||||
memset(&rr->read, 0, sizeof(rr->read));
|
||||
memset(&rr->write, 0, sizeof(rr->write));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RayResourcesFill(VkCommandBuffer cmdbuf, ray_resources_fill_t fill) {
|
||||
VkImageMemoryBarrier image_barriers[MAX_BARRIERS];
|
||||
int image_barriers_count = 0;
|
||||
|
|
|
@ -1,75 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "vk_const.h"
|
||||
#include "vk_image.h"
|
||||
#include "vk_core.h"
|
||||
#include "vk_descriptor.h"
|
||||
|
||||
#include "shaders/ray_interop.h"
|
||||
|
||||
//qboolean R_VkResourceInit(void);
|
||||
//void R_VkResourceShutdown();
|
||||
|
||||
typedef enum {
|
||||
ResourceUnknown,
|
||||
ResourceBuffer,
|
||||
ResourceImage,
|
||||
} ray_resource_type_e;
|
||||
|
||||
typedef struct {
|
||||
ray_resource_type_e type;
|
||||
int image_format; // if type == ResourceImage
|
||||
} ray_resource_desc_t;
|
||||
|
||||
qboolean R_VkResourceSetExternal(const char* name, VkDescriptorType type, vk_descriptor_value_t value, int count, ray_resource_desc_t desc, const xvk_image_t *image);
|
||||
|
||||
/*
|
||||
typedef struct {
|
||||
int semantic;
|
||||
int count;
|
||||
} ray_resource_binding_desc_fixme_t;
|
||||
|
||||
ray_resource_binding_desc_fixme_t RayResouceGetBindingForName_FIXME(const char *name, ray_resource_desc_t desc);
|
||||
*/
|
||||
|
||||
#define RAY_SCENE_RESOURCES(X) \
|
||||
X(TLAS, tlas) \
|
||||
X(Buffer, ubo) \
|
||||
X(Buffer, kusochki) \
|
||||
X(Buffer, indices) \
|
||||
X(Buffer, vertices) \
|
||||
X(Buffer, lights) \
|
||||
X(Buffer, light_clusters) \
|
||||
X(Texture, all_textures) \
|
||||
X(Texture, skybox) \
|
||||
|
||||
enum {
|
||||
#define X(type, name, ...) RayResource_##name,
|
||||
RAY_SCENE_RESOURCES(X)
|
||||
RAY_PRIMARY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_POLY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_POINT_OUTPUTS(X)
|
||||
X(-1, denoised)
|
||||
#undef X
|
||||
RayResource__COUNT
|
||||
};
|
||||
|
||||
typedef struct vk_ray_resources_s {
|
||||
uint32_t width, height;
|
||||
} vk_ray_resources_t;
|
||||
|
||||
typedef struct {
|
||||
VkAccessFlags access_mask;
|
||||
VkImageLayout image_layout;
|
||||
VkPipelineStageFlagBits pipelines;
|
||||
} ray_resource_state_t;
|
||||
|
||||
struct xvk_image_s;
|
||||
typedef struct vk_resource_s {
|
||||
VkDescriptorType type;
|
||||
ray_resource_state_t write, read;
|
||||
union {
|
||||
vk_descriptor_value_t value;
|
||||
const xvk_image_t *image;
|
||||
};
|
||||
vk_descriptor_value_t value;
|
||||
} vk_resource_t;
|
||||
|
||||
typedef struct vk_resource_s *vk_resource_p;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
#ifndef GLSL
|
||||
#include "xash3d_types.h"
|
||||
#include "vk_const.h"
|
||||
#define MAX_EMISSIVE_KUSOCHKI 256
|
||||
#define uint uint32_t
|
||||
#define vec2 vec2_t
|
||||
|
|
197
ref_vk/vk_rtx.c
197
ref_vk/vk_rtx.c
|
@ -38,34 +38,7 @@
|
|||
#define FRAME_HEIGHT 1080
|
||||
#endif
|
||||
|
||||
#define rgba8 VK_FORMAT_R8G8B8A8_UNORM
|
||||
#define rgba32f VK_FORMAT_R32G32B32A32_SFLOAT
|
||||
#define rgba16f VK_FORMAT_R16G16B16A16_SFLOAT
|
||||
|
||||
// TODO sync with shaders
|
||||
// TODO optimal values
|
||||
#define WG_W 16
|
||||
#define WG_H 8
|
||||
|
||||
typedef struct {
|
||||
vec3_t pos;
|
||||
float radius;
|
||||
vec3_t color;
|
||||
float padding_;
|
||||
} vk_light_t;
|
||||
|
||||
typedef struct PushConstants vk_rtx_push_constants_t;
|
||||
|
||||
typedef struct {
|
||||
xvk_image_t denoised;
|
||||
|
||||
#define X(index, name, ...) xvk_image_t name;
|
||||
RAY_PRIMARY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_POLY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_POINT_OUTPUTS(X)
|
||||
#undef X
|
||||
|
||||
} xvk_ray_frame_images_t;
|
||||
#define MAX_RESOURCES 32
|
||||
|
||||
static struct {
|
||||
// Holds UniformBuffer data
|
||||
|
@ -74,13 +47,43 @@ static struct {
|
|||
|
||||
// TODO with proper intra-cmdbuf sync we don't really need 2x images
|
||||
unsigned frame_number;
|
||||
xvk_ray_frame_images_t frames[MAX_FRAMES_IN_FLIGHT];
|
||||
vk_meatpipe_t *mainpipe;
|
||||
vk_resource_p *mainpipe_resources;
|
||||
|
||||
struct {
|
||||
char name[64];
|
||||
vk_resource_t resource;
|
||||
xvk_image_t image;
|
||||
} res[MAX_RESOURCES];
|
||||
|
||||
qboolean reload_pipeline;
|
||||
qboolean reload_lighting;
|
||||
} g_rtx = {0};
|
||||
|
||||
static int findResource(const char *name) {
|
||||
// Find the exact match if exists
|
||||
// There might be gaps, so we need to check everything
|
||||
for (int i = 0; i < MAX_RESOURCES; ++i) {
|
||||
if (strcmp(g_rtx.res[i].name, name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int getResourceSlotForName(const char *name) {
|
||||
const int index = findResource(name);
|
||||
if (index >= 0)
|
||||
return index;
|
||||
|
||||
// Find first free slot
|
||||
for (int i = 0; i < MAX_RESOURCES; ++i) {
|
||||
if (!g_rtx.res[i].name[0])
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void VK_RayNewMap( void ) {
|
||||
RT_VkAccelNewMap();
|
||||
|
@ -127,17 +130,12 @@ static void prepareUniformBuffer( const vk_ray_frame_render_args_t *args, int fr
|
|||
typedef struct {
|
||||
const vk_ray_frame_render_args_t* render_args;
|
||||
int frame_index;
|
||||
const xvk_ray_frame_images_t *current_frame;
|
||||
float fov_angle_y;
|
||||
const vk_lights_bindings_t *light_bindings;
|
||||
} perform_tracing_args_t;
|
||||
|
||||
static void performTracing(VkCommandBuffer cmdbuf, const perform_tracing_args_t* args) {
|
||||
const vk_ray_resources_t res = {
|
||||
.width = FRAME_WIDTH,
|
||||
.height = FRAME_HEIGHT,
|
||||
};
|
||||
|
||||
#if 0
|
||||
R_VkResourceSetExternal("tlas", VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR,
|
||||
(vk_descriptor_value_t){
|
||||
.accel = (VkWriteDescriptorSetAccelerationStructureKHR) {
|
||||
|
@ -171,6 +169,7 @@ static void performTracing(VkCommandBuffer cmdbuf, const perform_tracing_args_t*
|
|||
RES_SET_BUFFER(light_clusters, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, args->light_bindings->buffer, args->light_bindings->grid.offset, args->light_bindings->grid.size);
|
||||
#undef RES_SET_SBUFFER_FULL
|
||||
#undef RES_SET_BUFFER
|
||||
#endif
|
||||
|
||||
// Upload kusochki updates
|
||||
{
|
||||
|
@ -232,7 +231,7 @@ static void performTracing(VkCommandBuffer cmdbuf, const perform_tracing_args_t*
|
|||
const r_vkimage_blit_args blit_args = {
|
||||
.in_stage = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
|
||||
.src = {
|
||||
.image = args->current_frame->denoised.image,
|
||||
// FIXME .image = args->current_frame->denoised.image,
|
||||
.width = FRAME_WIDTH,
|
||||
.height = FRAME_HEIGHT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
|
@ -252,10 +251,76 @@ static void performTracing(VkCommandBuffer cmdbuf, const perform_tracing_args_t*
|
|||
DEBUG_END(cmdbuf);
|
||||
}
|
||||
|
||||
static void reloadMainpipe() {
|
||||
vk_meatpipe_t *const newpipe = R_VkMeatpipeCreateFromFile("rt.meat");
|
||||
if (!newpipe)
|
||||
return;
|
||||
|
||||
const size_t newpipe_resources_size = sizeof(vk_resource_p) * newpipe->resources_count;
|
||||
vk_resource_p *newpipe_resources = Mem_Calloc(vk_core.pool, newpipe_resources_size);
|
||||
|
||||
for (int i = 0; i < newpipe->resources_count; ++i) {
|
||||
const vk_meatpipe_resource_t *mr = newpipe->resources + i;
|
||||
gEngine.Con_Reportf("res %d/%d: %s descriptor=%u count=%d flags=[%c%c] image_format=%u\n",
|
||||
i, newpipe->resources_count, mr->name, mr->descriptor_type, mr->count,
|
||||
(mr->flags & MEATPIPE_RES_WRITE) ? 'W' : ' ',
|
||||
(mr->flags & MEATPIPE_RES_CREATE) ? 'C' : ' ',
|
||||
mr->image_format);
|
||||
|
||||
const qboolean create = !!(mr->flags & MEATPIPE_RES_CREATE);
|
||||
|
||||
const int index = create ? getResourceSlotForName(mr->name) : findResource(mr->name);
|
||||
if (index < 0) {
|
||||
gEngine.Con_Printf(S_ERROR "Couldn't find resource/slot for %s\n", mr->name);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// TODO create if creatable
|
||||
if (create && g_rtx.res[index].image.image == VK_NULL_HANDLE) {
|
||||
Q_strncpy(g_rtx.res[index].name, mr->name, sizeof(g_rtx.res[index].name));
|
||||
const xvk_image_create_t create = {
|
||||
.debug_name = mr->name,
|
||||
.width = FRAME_WIDTH,
|
||||
.height = FRAME_HEIGHT,
|
||||
.mips = 1,
|
||||
.layers = 1,
|
||||
.format = mr->image_format,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = VK_IMAGE_USAGE_STORAGE_BIT,
|
||||
.has_alpha = true,
|
||||
.is_cubemap = false,
|
||||
};
|
||||
g_rtx.res[index].image = XVK_ImageCreate(&create);
|
||||
}
|
||||
|
||||
g_rtx.mainpipe_resources[i] = &g_rtx.res[index].resource;
|
||||
}
|
||||
|
||||
if (g_rtx.mainpipe) {
|
||||
R_VkMeatpipeDestroy(g_rtx.mainpipe);
|
||||
|
||||
// FIXME also destroy all extra created resources/images
|
||||
|
||||
Mem_Free(g_rtx.mainpipe_resources);
|
||||
}
|
||||
|
||||
g_rtx.mainpipe = newpipe;
|
||||
|
||||
fail:
|
||||
if (newpipe_resources) {
|
||||
for (int i = 0; i < newpipe->resources_count; ++i) {
|
||||
// FIXME on error we'll leak images
|
||||
}
|
||||
Mem_Free(newpipe_resources);
|
||||
}
|
||||
|
||||
R_VkMeatpipeDestroy(newpipe);
|
||||
}
|
||||
|
||||
void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
|
||||
{
|
||||
const VkCommandBuffer cmdbuf = args->cmdbuf;
|
||||
const xvk_ray_frame_images_t* current_frame = g_rtx.frames + (g_rtx.frame_number % 2);
|
||||
// const xvk_ray_frame_images_t* current_frame = g_rtx.frames + (g_rtx.frame_number % 2);
|
||||
|
||||
ASSERT(vk_core.rtx);
|
||||
// ubo should contain two matrices
|
||||
|
@ -273,11 +338,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
|
|||
gEngine.Con_Printf(S_WARN "Reloading RTX shaders/pipelines\n");
|
||||
XVK_CHECK(vkDeviceWaitIdle(vk_core.device));
|
||||
|
||||
vk_meatpipe_t *const newpipe = R_VkMeatpipeCreateFromFile("rt.meat");
|
||||
if (newpipe) {
|
||||
R_VkMeatpipeDestroy(g_rtx.mainpipe);
|
||||
g_rtx.mainpipe = newpipe;
|
||||
}
|
||||
reloadMainpipe();
|
||||
|
||||
g_rtx.reload_pipeline = false;
|
||||
}
|
||||
|
@ -286,7 +347,7 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
|
|||
const r_vkimage_blit_args blit_args = {
|
||||
.in_stage = VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
.src = {
|
||||
.image = current_frame->denoised.image,
|
||||
// FIXME .image = current_frame->denoised.image,
|
||||
.width = FRAME_WIDTH,
|
||||
.height = FRAME_HEIGHT,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_GENERAL,
|
||||
|
@ -301,13 +362,12 @@ void VK_RayFrameEnd(const vk_ray_frame_render_args_t* args)
|
|||
},
|
||||
};
|
||||
|
||||
R_VkImageClear( cmdbuf, current_frame->denoised.image );
|
||||
// FIMXE R_VkImageClear( cmdbuf, current_frame->denoised.image );
|
||||
R_VkImageBlit( cmdbuf, &blit_args );
|
||||
} else {
|
||||
const perform_tracing_args_t trace_args = {
|
||||
.render_args = args,
|
||||
.frame_index = (g_rtx.frame_number % 2),
|
||||
.current_frame = current_frame,
|
||||
.fov_angle_y = args->fov_angle_y,
|
||||
.light_bindings = &light_bindings,
|
||||
};
|
||||
|
@ -335,8 +395,9 @@ qboolean VK_RayInit( void )
|
|||
if (!RT_VkAccelInit())
|
||||
return false;
|
||||
|
||||
g_rtx.mainpipe = R_VkMeatpipeCreateFromFile("rt.meat");
|
||||
ASSERT(g_rtx.mainpipe);
|
||||
reloadMainpipe();
|
||||
if (!g_rtx.mainpipe)
|
||||
return false;
|
||||
|
||||
g_rtx.uniform_unit_size = ALIGN_UP(sizeof(struct UniformBuffer), vk_core.physical_device.properties.limits.minUniformBufferOffsetAlignment);
|
||||
|
||||
|
@ -355,36 +416,9 @@ qboolean VK_RayInit( void )
|
|||
}
|
||||
RT_RayModel_Clear();
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(g_rtx.frames); ++i) {
|
||||
#define CREATE_GBUFFER_IMAGE(name, format_, add_usage_bits) \
|
||||
do { \
|
||||
char debug_name[64]; \
|
||||
const xvk_image_create_t create = { \
|
||||
.debug_name = debug_name, \
|
||||
.width = FRAME_WIDTH, \
|
||||
.height = FRAME_HEIGHT, \
|
||||
.mips = 1, \
|
||||
.layers = 1, \
|
||||
.format = format_, \
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL, \
|
||||
.usage = VK_IMAGE_USAGE_STORAGE_BIT | add_usage_bits, \
|
||||
.has_alpha = true, \
|
||||
.is_cubemap = false, \
|
||||
}; \
|
||||
Q_snprintf(debug_name, sizeof(debug_name), "rtx frames[%d] " # name, i); \
|
||||
g_rtx.frames[i].name = XVK_ImageCreate(&create); \
|
||||
} while(0)
|
||||
|
||||
CREATE_GBUFFER_IMAGE(denoised, VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
|
||||
#define X(index, name, format) CREATE_GBUFFER_IMAGE(name, format, 0);
|
||||
// TODO better format for normals VK_FORMAT_R16G16B16A16_SNORM
|
||||
// TODO make sure this format and usage is suppported
|
||||
RAY_PRIMARY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_POLY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_POINT_OUTPUTS(X)
|
||||
#undef X
|
||||
|
||||
/*
|
||||
R_VkResourceSetExternal("all_textures", VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
(vk_descriptor_value_t){
|
||||
|
@ -412,14 +446,9 @@ qboolean VK_RayInit( void )
|
|||
RAY_LIGHT_DIRECT_POLY_OUTPUTS(RES_SET_IMAGE);
|
||||
RAY_LIGHT_DIRECT_POINT_OUTPUTS(RES_SET_IMAGE);
|
||||
RES_SET_IMAGE(-1, denoised, rgba16f);
|
||||
*/
|
||||
|
||||
#undef RES_SET_IMAGE
|
||||
#undef rgba8
|
||||
#undef rgba32f
|
||||
#undef rgba16f
|
||||
*/
|
||||
#undef CREATE_GBUFFER_IMAGE
|
||||
}
|
||||
|
||||
gEngine.Cmd_AddCommand("vk_rtx_reload", reloadPipeline, "Reload RTX shader");
|
||||
gEngine.Cmd_AddCommand("vk_rtx_reload_rad", reloadLighting, "Reload RAD files for static lights");
|
||||
|
@ -433,14 +462,12 @@ void VK_RayShutdown( void ) {
|
|||
|
||||
R_VkMeatpipeDestroy(g_rtx.mainpipe);
|
||||
|
||||
// FIXME destroy mainpipe resources
|
||||
/*
|
||||
for (int i = 0; i < ARRAYSIZE(g_rtx.frames); ++i) {
|
||||
XVK_ImageDestroy(&g_rtx.frames[i].denoised);
|
||||
#define X(index, name, ...) XVK_ImageDestroy(&g_rtx.frames[i].name);
|
||||
RAY_PRIMARY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_POLY_OUTPUTS(X)
|
||||
RAY_LIGHT_DIRECT_POINT_OUTPUTS(X)
|
||||
#undef X
|
||||
}
|
||||
*/
|
||||
|
||||
VK_BufferDestroy(&g_ray_model_state.kusochki_buffer);
|
||||
VK_BufferDestroy(&g_rtx.uniform_buffer);
|
||||
|
|
Loading…
Reference in New Issue