add persistent model api and use it for brushes
this needed for better rtx blas management
This commit is contained in:
parent
7fe55e6d90
commit
af5e20269d
|
@ -1,5 +1,10 @@
|
|||
## 2021-03-28
|
||||
- [x] bake s/d-lights visibility data into bsp leaves
|
||||
## 2021-04-06..07
|
||||
- [ ] persistent models
|
||||
- [x] load brushes into render model
|
||||
- [x] destroy brushes when time comes (when?)
|
||||
- [x] rasterize models in renderer
|
||||
- [ ] rtx: build AS for model
|
||||
- [ ] rtx: include pre-built models in TLAS
|
||||
|
||||
# Next
|
||||
- [ ] rtx: use light visibility data
|
||||
|
@ -151,3 +156,6 @@
|
|||
|
||||
## 2021-03-22
|
||||
- [x] rtx: traverse bsp for science!
|
||||
|
||||
## 2021-03-28
|
||||
- [x] bake s/d-lights visibility data into bsp leaves
|
||||
|
|
|
@ -301,7 +301,7 @@ void main() {
|
|||
|
||||
//if (gl_GlobalInvocationID.x > imageSize(image).x / 2)
|
||||
{
|
||||
const float wet = .9;
|
||||
const float wet = .5;
|
||||
C = mix(C, imageLoad(previous_frame, ivec2(gl_GlobalInvocationID.xy)).rgb, wet);
|
||||
}
|
||||
imageStore(image, ivec2(gl_GlobalInvocationID.xy), vec4(C, 1.));
|
||||
|
|
|
@ -17,20 +17,12 @@
|
|||
#include <math.h>
|
||||
#include <memory.h>
|
||||
|
||||
typedef struct vk_brush_model_surface_s {
|
||||
int texture_num;
|
||||
msurface_t *surf;
|
||||
|
||||
uint32_t index_offset;
|
||||
uint16_t index_count;
|
||||
} vk_brush_model_surface_t;
|
||||
|
||||
typedef struct vk_brush_model_s {
|
||||
vk_buffer_handle_t vertex_buffer;
|
||||
vk_buffer_handle_t index_buffer;
|
||||
vk_render_model_t render_model;
|
||||
|
||||
int num_surfaces;
|
||||
vk_brush_model_surface_t surfaces[];
|
||||
// Surfaces for getting animated textures.
|
||||
// Each surface corresponds to a single geometry within render_model with the same index.
|
||||
msurface_t *surf[];
|
||||
} vk_brush_model_t;
|
||||
|
||||
static struct {
|
||||
|
@ -123,14 +115,11 @@ texture_t *R_TextureAnimation( const cl_entity_t *ent, msurface_t *s )
|
|||
return base;
|
||||
}
|
||||
|
||||
void VK_BrushDrawModel( const cl_entity_t *ent, int render_mode )
|
||||
void VK_BrushModelDraw( const cl_entity_t *ent, int render_mode )
|
||||
{
|
||||
// Expect all buffers to be bound
|
||||
const model_t *mod = ent->model;
|
||||
const vk_brush_model_t *bmodel = mod->cache.data;
|
||||
int current_texture = -1;
|
||||
int index_count = 0;
|
||||
int index_offset = -1;
|
||||
vk_brush_model_t *bmodel = mod->cache.data;
|
||||
|
||||
if (!bmodel) {
|
||||
gEngine.Con_Printf( S_ERROR "Model %s wasn't loaded\n", mod->name);
|
||||
|
@ -143,63 +132,58 @@ void VK_BrushDrawModel( const cl_entity_t *ent, int render_mode )
|
|||
return;
|
||||
}
|
||||
|
||||
VK_RenderDebugLabelBegin( mod->name );
|
||||
|
||||
for (int i = 0; i < bmodel->num_surfaces; ++i) {
|
||||
const vk_brush_model_surface_t *bsurf = bmodel->surfaces + i;
|
||||
texture_t *t = R_TextureAnimation(ent, bsurf->surf);
|
||||
|
||||
for (int i = 0; i < bmodel->render_model.num_geometries; ++i) {
|
||||
texture_t *t = R_TextureAnimation(ent, bmodel->surf[i]);
|
||||
if (t->gl_texturenum < 0)
|
||||
continue;
|
||||
|
||||
if (current_texture != t->gl_texturenum)
|
||||
{
|
||||
if (index_count) {
|
||||
const render_draw_t draw = {
|
||||
.lightmap = tglob.lightmapTextures[0],
|
||||
.texture = current_texture,
|
||||
.render_mode = render_mode,
|
||||
.element_count = index_count,
|
||||
.vertex_buffer = bmodel->vertex_buffer,
|
||||
.index_buffer = bmodel->index_buffer,
|
||||
.vertex_offset = 0,
|
||||
.index_offset = index_offset,
|
||||
};
|
||||
|
||||
VK_RenderScheduleDraw( &draw );
|
||||
}
|
||||
|
||||
current_texture = t->gl_texturenum;
|
||||
index_count = 0;
|
||||
index_offset = -1;
|
||||
}
|
||||
|
||||
if (index_offset < 0)
|
||||
index_offset = bsurf->index_offset;
|
||||
// Make sure that all surfaces are concatenated in buffers
|
||||
ASSERT(index_offset + index_count == bsurf->index_offset);
|
||||
index_count += bsurf->index_count;
|
||||
bmodel->render_model.geometries[i].texture = t->gl_texturenum;
|
||||
}
|
||||
|
||||
if (index_count) {
|
||||
const render_draw_t draw = {
|
||||
.lightmap = tglob.lightmapTextures[0],
|
||||
.texture = current_texture,
|
||||
.render_mode = render_mode,
|
||||
.element_count = index_count,
|
||||
.vertex_buffer = bmodel->vertex_buffer,
|
||||
.index_buffer = bmodel->index_buffer,
|
||||
.vertex_offset = 0,
|
||||
.index_offset = index_offset,
|
||||
};
|
||||
|
||||
VK_RenderScheduleDraw( &draw );
|
||||
}
|
||||
|
||||
VK_RenderDebugLabelEnd();
|
||||
bmodel->render_model.render_mode = render_mode;
|
||||
VK_RenderModelDraw(&bmodel->render_model);
|
||||
}
|
||||
|
||||
static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_surfaces) {
|
||||
static qboolean renderableSurface( const msurface_t *surf, int i ) {
|
||||
if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) {
|
||||
gEngine.Con_Reportf("Skipping surface %d because of flags %08x\n", i, surf->flags);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWTILED )) {
|
||||
gEngine.Con_Reportf("Skipping surface %d because of tiled flag\n", i);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int num_surfaces, num_vertices, num_indices;
|
||||
int max_texture_id;
|
||||
} model_sizes_t;
|
||||
|
||||
static model_sizes_t computeSizes( const model_t *mod ) {
|
||||
model_sizes_t sizes = {0};
|
||||
|
||||
for( int i = 0; i < mod->nummodelsurfaces; ++i)
|
||||
{
|
||||
const msurface_t *surf = mod->surfaces + mod->firstmodelsurface + i;
|
||||
|
||||
if (!renderableSurface(surf, i))
|
||||
continue;
|
||||
|
||||
++sizes.num_surfaces;
|
||||
sizes.num_vertices += surf->numedges;
|
||||
sizes.num_indices += 3 * (surf->numedges - 1);
|
||||
if (surf->texinfo->texture->gl_texturenum > sizes.max_texture_id)
|
||||
sizes.max_texture_id = surf->texinfo->texture->gl_texturenum;
|
||||
}
|
||||
|
||||
return sizes;
|
||||
}
|
||||
|
||||
static qboolean loadBrushSurfaces( model_sizes_t sizes, const model_t *mod ) {
|
||||
vk_brush_model_t *bmodel = mod->cache.data;
|
||||
uint32_t vertex_offset = 0;
|
||||
int num_surfaces = 0;
|
||||
|
@ -209,35 +193,13 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
|
|||
uint16_t *bind = NULL;
|
||||
uint32_t index_offset = 0;
|
||||
|
||||
int num_indices = 0, num_vertices = 0, max_texture_id = 0;
|
||||
for( int i = 0; i < mod->nummodelsurfaces; ++i)
|
||||
{
|
||||
const msurface_t *surf = mod->surfaces + mod->firstmodelsurface + i;
|
||||
vk_brush_model_surface_t *bsurf = out_surfaces + num_surfaces;
|
||||
|
||||
if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) ) {
|
||||
gEngine.Con_Reportf("Skipping surface %d because of flags %08x\n", i, surf->flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWTILED )) {
|
||||
gEngine.Con_Reportf("Skipping surface %d because of tiled flag\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
num_vertices += surf->numedges;
|
||||
num_indices += 3 * (surf->numedges - 1);
|
||||
if (surf->texinfo->texture->gl_texturenum > max_texture_id)
|
||||
max_texture_id = surf->texinfo->texture->gl_texturenum;
|
||||
}
|
||||
|
||||
vertex_buffer = VK_RenderBufferAlloc( sizeof(vk_vertex_t), num_vertices, LifetimeMap );
|
||||
index_buffer = VK_RenderBufferAlloc( sizeof(uint16_t), num_indices, LifetimeMap );
|
||||
vertex_buffer = VK_RenderBufferAlloc( sizeof(vk_vertex_t), sizes.num_vertices, LifetimeMap );
|
||||
index_buffer = VK_RenderBufferAlloc( sizeof(uint16_t), sizes.num_indices, LifetimeMap );
|
||||
if (vertex_buffer == InvalidHandle || index_buffer == InvalidHandle)
|
||||
{
|
||||
// TODO should we free one of the above if it still succeeded?
|
||||
gEngine.Con_Printf(S_ERROR "Ran out of buffer space\n");
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
vertex_lock = VK_RenderBufferLock( vertex_buffer );
|
||||
|
@ -245,34 +207,25 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
|
|||
bvert = vertex_lock.ptr;
|
||||
bind = index_lock.ptr;
|
||||
|
||||
if (!bind)
|
||||
{
|
||||
gEngine.Con_Printf(S_ERROR "Ran out of buffer index space\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_brush.stat.num_indices += num_indices;
|
||||
g_brush.stat.num_vertices += num_vertices;
|
||||
|
||||
// Load sorted by gl_texturenum
|
||||
for (int t = 0; t <= max_texture_id; ++t)
|
||||
for (int t = 0; t <= sizes.max_texture_id; ++t)
|
||||
{
|
||||
for( int i = 0; i < mod->nummodelsurfaces; ++i)
|
||||
{
|
||||
msurface_t *surf = mod->surfaces + mod->firstmodelsurface + i;
|
||||
vk_brush_model_surface_t *bsurf = out_surfaces + num_surfaces;
|
||||
mextrasurf_t *info = surf->info;
|
||||
vk_render_geometry_t *model_geometry = bmodel->render_model.geometries + num_surfaces;
|
||||
const float sample_size = gEngine.Mod_SampleSizeForFace( surf );
|
||||
int index_count = 0;
|
||||
|
||||
if( surf->flags & ( SURF_DRAWSKY | SURF_DRAWTURB | SURF_CONVEYOR | SURF_DRAWTURB_QUADS ) )
|
||||
continue;
|
||||
|
||||
if( FBitSet( surf->flags, SURF_DRAWTILED ))
|
||||
if (!renderableSurface(surf, i))
|
||||
continue;
|
||||
|
||||
if (t != surf->texinfo->texture->gl_texturenum)
|
||||
continue;
|
||||
|
||||
bmodel->surf[num_surfaces] = surf;
|
||||
|
||||
++num_surfaces;
|
||||
|
||||
//gEngine.Con_Reportf( "surface %d: numverts=%d numedges=%d\n", i, surf->polys ? surf->polys->numverts : -1, surf->numedges );
|
||||
|
@ -280,13 +233,13 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
|
|||
if (vertex_offset + surf->numedges >= UINT16_MAX)
|
||||
{
|
||||
gEngine.Con_Printf(S_ERROR "Model %s indices don't fit into 16 bits\n", mod->name);
|
||||
return -1;
|
||||
// FIXME unlock and free buffers
|
||||
return false;
|
||||
}
|
||||
|
||||
bsurf->surf = surf;
|
||||
bsurf->texture_num = surf->texinfo->texture->gl_texturenum;
|
||||
bsurf->index_offset = index_offset;
|
||||
bsurf->index_count = 0;
|
||||
model_geometry->index_offset = index_offset;
|
||||
model_geometry->vertex_offset = 0;
|
||||
model_geometry->texture = t;
|
||||
|
||||
VK_CreateSurfaceLightmap( surf, mod );
|
||||
|
||||
|
@ -335,11 +288,12 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
|
|||
*(bind++) = (uint16_t)(vertex_offset + 0);
|
||||
*(bind++) = (uint16_t)(vertex_offset + k - 1);
|
||||
*(bind++) = (uint16_t)(vertex_offset + k);
|
||||
bsurf->index_count += 3;
|
||||
index_count += 3;
|
||||
index_offset += 3;
|
||||
}
|
||||
}
|
||||
|
||||
model_geometry->element_count = index_count;
|
||||
vertex_offset += surf->numedges;
|
||||
}
|
||||
}
|
||||
|
@ -347,16 +301,16 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
|
|||
VK_RenderBufferUnlock( index_buffer );
|
||||
VK_RenderBufferUnlock( vertex_buffer );
|
||||
|
||||
bmodel->vertex_buffer = vertex_buffer;
|
||||
bmodel->index_buffer = index_buffer;
|
||||
ASSERT(sizes.num_surfaces == num_surfaces);
|
||||
bmodel->render_model.num_geometries = num_surfaces;
|
||||
bmodel->render_model.index_buffer = index_buffer;
|
||||
bmodel->render_model.vertex_buffer = vertex_buffer;
|
||||
|
||||
return num_surfaces;
|
||||
}
|
||||
|
||||
qboolean VK_LoadBrushModel( model_t *mod, const byte *buffer )
|
||||
qboolean VK_BrushModelLoad( model_t *mod )
|
||||
{
|
||||
vk_brush_model_t *bmodel;
|
||||
|
||||
if (mod->cache.data)
|
||||
{
|
||||
gEngine.Con_Reportf( S_WARN "Model %s was already loaded\n", mod->name );
|
||||
|
@ -365,20 +319,40 @@ qboolean VK_LoadBrushModel( model_t *mod, const byte *buffer )
|
|||
|
||||
gEngine.Con_Reportf("%s: %s flags=%08x\n", __FUNCTION__, mod->name, mod->flags);
|
||||
|
||||
bmodel = Mem_Malloc(vk_core.pool, sizeof(vk_brush_model_t) + sizeof(vk_brush_model_surface_t) * mod->nummodelsurfaces);
|
||||
mod->cache.data = bmodel;
|
||||
{
|
||||
const model_sizes_t sizes = computeSizes( mod );
|
||||
vk_brush_model_t *bmodel = Mem_Malloc(vk_core.pool, sizeof(vk_brush_model_t) + (sizeof(msurface_t*) + sizeof(vk_render_geometry_t)) * sizes.num_surfaces);
|
||||
mod->cache.data = bmodel;
|
||||
bmodel->render_model.debug_name = mod->name;
|
||||
bmodel->render_model.render_mode = kRenderNormal;
|
||||
bmodel->render_model.geometries = (vk_render_geometry_t*)((char*)(bmodel + 1) + sizeof(msurface_t*) * sizes.num_surfaces);
|
||||
|
||||
bmodel->num_surfaces = loadBrushSurfaces( mod, bmodel->surfaces );
|
||||
if (bmodel->num_surfaces < 0) {
|
||||
gEngine.Con_Reportf( S_ERROR "Model %s was not loaded\n", mod->name );
|
||||
return false;
|
||||
if (!loadBrushSurfaces(sizes, mod) || !VK_RenderModelInit(&bmodel->render_model)) {
|
||||
gEngine.Con_Printf(S_ERROR "Could not load model %s\n", mod->name);
|
||||
Mem_Free(bmodel);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_brush.stat.num_indices += sizes.num_indices;
|
||||
g_brush.stat.num_vertices += sizes.num_vertices;
|
||||
|
||||
gEngine.Con_Reportf("Model %s loaded surfaces: %d (of %d); total vertices: %u, total indices: %u\n", mod->name, bmodel->render_model.num_geometries, mod->nummodelsurfaces, g_brush.stat.num_vertices, g_brush.stat.num_indices);
|
||||
}
|
||||
|
||||
gEngine.Con_Reportf("Model %s loaded surfaces: %d (of %d); total vertices: %u, total indices: %u\n", mod->name, bmodel->num_surfaces, mod->nummodelsurfaces, g_brush.stat.num_vertices, g_brush.stat.num_indices);
|
||||
return true;
|
||||
}
|
||||
|
||||
void VK_BrushClear( void )
|
||||
void VK_BrushModelDestroy( model_t *mod ) {
|
||||
vk_brush_model_t *bmodel = mod->cache.data;
|
||||
if (!bmodel)
|
||||
return;
|
||||
|
||||
VK_RenderModelDestroy(&bmodel->render_model);
|
||||
Mem_Free(bmodel);
|
||||
mod->cache.data = NULL;
|
||||
}
|
||||
|
||||
void VK_BrushStatsClear( void )
|
||||
{
|
||||
// Free previous map data
|
||||
g_brush.stat.num_vertices = 0;
|
||||
|
|
|
@ -9,7 +9,9 @@ struct cl_entity_s;
|
|||
|
||||
qboolean VK_BrushInit( void );
|
||||
void VK_BrushShutdown( void );
|
||||
qboolean VK_LoadBrushModel( struct model_s *mod, const byte *buffer );
|
||||
qboolean VK_BrushRenderBegin( void );
|
||||
void VK_BrushDrawModel( const struct cl_entity_s *ent, int render_mode );
|
||||
void VK_BrushClear( void );
|
||||
|
||||
qboolean VK_BrushModelLoad( struct model_s *mod );
|
||||
void VK_BrushModelDestroy( struct model_s *mod );
|
||||
|
||||
void VK_BrushModelDraw( const struct cl_entity_s *ent, int render_mode );
|
||||
void VK_BrushStatsClear( void );
|
||||
|
|
|
@ -183,7 +183,7 @@ static void loadDeviceFunctions(dllfunc_t *funcs, int count)
|
|||
|
||||
static qboolean createInstance( void )
|
||||
{
|
||||
const char **instance_extensions = NULL;
|
||||
char ** instance_extensions = NULL;
|
||||
unsigned int num_instance_extensions = vk_core.debug ? 1 : 0;
|
||||
VkApplicationInfo app_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||
|
|
|
@ -507,6 +507,7 @@ void VK_LightsBakePVL( int frame_number ) {
|
|||
for (int i = 0; i < map->numleafs; ++i) {
|
||||
const mleaf_t *leaf = map->leafs + i;
|
||||
vk_light_leaf_t *lights = g_lights.leaves + i;
|
||||
// TODO we should not decompress PVS, as it might be faster to interate through compressed directly
|
||||
const byte *visdata = Mod_DecompressPVS(leaf->compressed_vis, world->visbytes);
|
||||
int num_emissive_lights = 0;
|
||||
|
||||
|
@ -551,6 +552,11 @@ void VK_LightsBakePVL( int frame_number ) {
|
|||
if (lights->num_slights == MAX_VISIBLE_SURFACE_LIGHTS)
|
||||
continue;
|
||||
|
||||
// TODO cull by:
|
||||
// - front/back facing?
|
||||
// - distance and intensity
|
||||
// - ...
|
||||
|
||||
lights->slights[lights->num_slights++] = candidate_light;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ typedef struct {
|
|||
typedef struct {
|
||||
int frame_number;
|
||||
|
||||
// TODO make this opaque light clusters
|
||||
int num_leaves; // same as worldmodel->numleaves
|
||||
vk_light_leaf_t *leaves;
|
||||
|
||||
|
|
|
@ -620,6 +620,8 @@ static uint32_t writeDlightsToUBO( void )
|
|||
}
|
||||
ubo_lights = (vk_ubo_lights_t*)((byte*)(g_render.uniform_buffer.mapped) + ubo_lights_offset);
|
||||
|
||||
// TODO rtx and query light styles
|
||||
#if 0
|
||||
for (int i = 0; i < g_render.num_static_lights && num_lights < ARRAYSIZE(ubo_lights->light); ++i) {
|
||||
Vector4Set(
|
||||
ubo_lights->light[num_lights].color,
|
||||
|
@ -636,6 +638,7 @@ static uint32_t writeDlightsToUBO( void )
|
|||
|
||||
num_lights++;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO this should not be here (where? vk_scene?)
|
||||
for (int i = 0; i < MAX_DLIGHTS && num_lights < ARRAYSIZE(ubo_lights->light); ++i) {
|
||||
|
@ -750,6 +753,7 @@ void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage
|
|||
|
||||
ASSERT(vk_core.rtx);
|
||||
VK_RaySceneBegin();
|
||||
|
||||
for (int i = 0; i < g_render_state.num_draw_commands; ++i) {
|
||||
const draw_command_t *const draw = g_render_state.draw_commands + i;
|
||||
const vk_buffer_alloc_t *vertex_buffer = getBufferFromHandle( draw->draw.vertex_buffer );
|
||||
|
@ -761,7 +765,7 @@ void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage
|
|||
// but here we've completely lost this info, as models are now just a stream
|
||||
// of independent draws
|
||||
|
||||
const vk_ray_model_create_t ray_model_args = {
|
||||
const vk_ray_model_dynamic_t dynamic_model = {
|
||||
.element_count = draw->draw.element_count,
|
||||
.max_vertex = vertex_buffer->count, // TODO this is an upper bound for brushes at least, it can be lowered
|
||||
.index_offset = index_buffer ? (draw->draw.index_offset + index_buffer->buffer_offset_in_units) : UINT32_MAX,
|
||||
|
@ -772,7 +776,7 @@ void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage
|
|||
.texture_id = draw->draw.texture,
|
||||
};
|
||||
|
||||
VK_RayScenePushModel(cmdbuf, &ray_model_args);
|
||||
VK_RaySceneAddModelDynamic(cmdbuf, &dynamic_model);
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -823,3 +827,76 @@ void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage
|
|||
VK_RaySceneEnd(&args);
|
||||
}
|
||||
}
|
||||
|
||||
qboolean VK_RenderModelInit( vk_render_model_t *model) {
|
||||
if (vk_core.rtx) {
|
||||
PRINT_NOT_IMPLEMENTED();
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO pre-bake optimal draws
|
||||
return true;
|
||||
}
|
||||
|
||||
void VK_RenderModelDestroy( vk_render_model_t* model ) {
|
||||
(void)model;
|
||||
|
||||
if (vk_core.rtx) {
|
||||
PRINT_NOT_IMPLEMENTED();
|
||||
}
|
||||
}
|
||||
|
||||
void VK_RenderModelDraw( vk_render_model_t* model ) {
|
||||
int current_texture = -1;
|
||||
int index_count = 0;
|
||||
int index_offset = -1;
|
||||
|
||||
for (int i = 0; i < model->num_geometries; ++i) {
|
||||
const vk_render_geometry_t *geom = model->geometries + i;
|
||||
if (geom->texture < 0)
|
||||
continue;
|
||||
|
||||
if (current_texture != geom->texture)
|
||||
{
|
||||
if (index_count) {
|
||||
const render_draw_t draw = {
|
||||
.lightmap = tglob.lightmapTextures[0],
|
||||
.texture = current_texture,
|
||||
.render_mode = model->render_mode,
|
||||
.element_count = index_count,
|
||||
.vertex_buffer = model->vertex_buffer,
|
||||
.index_buffer = model->index_buffer,
|
||||
.vertex_offset = 0,
|
||||
.index_offset = index_offset,
|
||||
};
|
||||
|
||||
VK_RenderScheduleDraw( &draw );
|
||||
}
|
||||
|
||||
current_texture = geom->texture;
|
||||
index_count = 0;
|
||||
index_offset = -1;
|
||||
}
|
||||
|
||||
if (index_offset < 0)
|
||||
index_offset = geom->index_offset;
|
||||
// Make sure that all surfaces are concatenated in buffers
|
||||
ASSERT(index_offset + index_count == geom->index_offset);
|
||||
index_count += geom->element_count;
|
||||
}
|
||||
|
||||
if (index_count) {
|
||||
const render_draw_t draw = {
|
||||
.lightmap = tglob.lightmapTextures[0],
|
||||
.texture = current_texture,
|
||||
.render_mode = model->render_mode,
|
||||
.element_count = index_count,
|
||||
.vertex_buffer = model->vertex_buffer,
|
||||
.index_buffer = model->index_buffer,
|
||||
.vertex_offset = 0,
|
||||
.index_offset = index_offset,
|
||||
};
|
||||
|
||||
VK_RenderScheduleDraw( &draw );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,13 +66,44 @@ typedef struct render_draw_s {
|
|||
uint32_t element_count;
|
||||
uint32_t index_offset, vertex_offset;
|
||||
vk_buffer_handle_t index_buffer, vertex_buffer;
|
||||
struct { float r, g, b; } emissive;
|
||||
/* TODO this should be a separate thing? */ struct { float r, g, b; } emissive;
|
||||
} render_draw_t;
|
||||
|
||||
void VK_RenderBegin( void );
|
||||
typedef struct {
|
||||
int texture;
|
||||
uint32_t element_count;
|
||||
uint32_t index_offset, vertex_offset;
|
||||
} vk_render_geometry_t;
|
||||
|
||||
typedef struct {
|
||||
const char *debug_name;
|
||||
int render_mode;
|
||||
int num_geometries;
|
||||
vk_render_geometry_t *geometries;
|
||||
|
||||
// Common for the entire model
|
||||
vk_buffer_handle_t index_buffer, vertex_buffer;
|
||||
|
||||
// TODO potentially dynamic data: textures
|
||||
//qboolean dynamic; // whether this model will require data reupload
|
||||
|
||||
struct {
|
||||
void *blas; // FIXME
|
||||
} rtx;
|
||||
} vk_render_model_t;
|
||||
|
||||
qboolean VK_RenderModelInit( vk_render_model_t* model );
|
||||
void VK_RenderModelDestroy( vk_render_model_t* model );
|
||||
void VK_RenderModelDraw( vk_render_model_t* model );
|
||||
|
||||
void VK_RenderFrameBegin( void );
|
||||
|
||||
// void VK_RenderObjectBegin( void *tag, const char *name /* expect transient ... */ );
|
||||
// void VK_RenderObjectEnd();
|
||||
|
||||
void VK_RenderScheduleDraw( const render_draw_t *draw );
|
||||
void VK_RenderEnd( VkCommandBuffer cmdbuf );
|
||||
void VK_RenderEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage img_dst, uint32_t w, uint32_t h );
|
||||
void VK_RenderFrameEnd( VkCommandBuffer cmdbuf );
|
||||
void VK_RenderFrameEndRTX( VkCommandBuffer cmdbuf, VkImageView img_dst_view, VkImage img_dst, uint32_t w, uint32_t h );
|
||||
|
||||
void VK_RenderDebugLabelBegin( const char *label );
|
||||
void VK_RenderDebugLabelEnd( void );
|
||||
|
|
|
@ -138,11 +138,6 @@ static void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *load
|
|||
PRINT_NOT_IMPLEMENTED_ARGS("(%p, %s), %p, %d", mod, mod->name, buffer, *loaded);
|
||||
}
|
||||
|
||||
static void Mod_UnloadTextures( model_t *mod )
|
||||
{
|
||||
PRINT_NOT_IMPLEMENTED_ARGS("(%p, %s)", mod, mod->name);
|
||||
}
|
||||
|
||||
static qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buffer )
|
||||
{
|
||||
qboolean loaded = true;
|
||||
|
@ -175,8 +170,16 @@ static qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte
|
|||
if( loaded && gEngine.drawFuncs->Mod_ProcessUserData )
|
||||
gEngine.drawFuncs->Mod_ProcessUserData( mod, create, buffer );
|
||||
|
||||
if( !create )
|
||||
Mod_UnloadTextures( mod );
|
||||
if( !create ) {
|
||||
switch( mod->type )
|
||||
{
|
||||
case mod_brush:
|
||||
VK_BrushModelDestroy( mod );
|
||||
break;
|
||||
default:
|
||||
PRINT_NOT_IMPLEMENTED_ARGS("destroy (%p, %d, %s)", mod, mod->type, mod->name);
|
||||
}
|
||||
}
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
|
|
@ -208,7 +208,7 @@ static vk_ray_model_t *getModelByHandle(vk_ray_model_handle_t handle)
|
|||
}
|
||||
*/
|
||||
|
||||
void VK_RayScenePushModel( VkCommandBuffer cmdbuf, const vk_ray_model_create_t *create_info) // _handle_t model_handle )
|
||||
void VK_RaySceneAddModelDynamic( VkCommandBuffer cmdbuf, const vk_ray_model_dynamic_t *dynamic)
|
||||
{
|
||||
vk_ray_model_t* model = g_rtx.models + g_rtx_scene.num_models;
|
||||
ASSERT(g_rtx_scene.num_models <= ARRAYSIZE(g_rtx.models));
|
||||
|
@ -221,8 +221,8 @@ void VK_RayScenePushModel( VkCommandBuffer cmdbuf, const vk_ray_model_create_t *
|
|||
ASSERT(vk_core.rtx);
|
||||
|
||||
{
|
||||
const VkDeviceAddress buffer_addr = getBufferDeviceAddress(create_info->buffer);
|
||||
const uint32_t prim_count = create_info->element_count / 3;
|
||||
const VkDeviceAddress buffer_addr = getBufferDeviceAddress(dynamic->buffer);
|
||||
const uint32_t prim_count = dynamic->element_count / 3;
|
||||
const VkAccelerationStructureGeometryKHR geom[] = {
|
||||
{
|
||||
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR,
|
||||
|
@ -231,12 +231,12 @@ void VK_RayScenePushModel( VkCommandBuffer cmdbuf, const vk_ray_model_create_t *
|
|||
.geometry.triangles =
|
||||
(VkAccelerationStructureGeometryTrianglesDataKHR){
|
||||
.sType = VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR,
|
||||
.indexType = create_info->index_offset == UINT32_MAX ? VK_INDEX_TYPE_NONE_KHR : VK_INDEX_TYPE_UINT16,
|
||||
.maxVertex = create_info->max_vertex,
|
||||
.indexType = dynamic->index_offset == UINT32_MAX ? VK_INDEX_TYPE_NONE_KHR : VK_INDEX_TYPE_UINT16,
|
||||
.maxVertex = dynamic->max_vertex,
|
||||
.vertexFormat = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.vertexStride = sizeof(vk_vertex_t),
|
||||
.vertexData.deviceAddress = buffer_addr + create_info->vertex_offset * sizeof(vk_vertex_t),
|
||||
.indexData.deviceAddress = buffer_addr + create_info->index_offset * sizeof(uint16_t),
|
||||
.vertexData.deviceAddress = buffer_addr + dynamic->vertex_offset * sizeof(vk_vertex_t),
|
||||
.indexData.deviceAddress = buffer_addr + dynamic->index_offset * sizeof(uint16_t),
|
||||
},
|
||||
} };
|
||||
|
||||
|
@ -257,18 +257,18 @@ void VK_RayScenePushModel( VkCommandBuffer cmdbuf, const vk_ray_model_create_t *
|
|||
// Store geometry references in kusochki
|
||||
{
|
||||
vk_kusok_data_t *kusok = (vk_kusok_data_t*)(g_rtx.kusochki_buffer.mapped) + g_rtx_scene.num_models;
|
||||
kusok->vertex_offset = create_info->vertex_offset;
|
||||
kusok->index_offset = create_info->index_offset;
|
||||
ASSERT(create_info->element_count % 3 == 0);
|
||||
kusok->triangles = create_info->element_count / 3;
|
||||
kusok->vertex_offset = dynamic->vertex_offset;
|
||||
kusok->index_offset = dynamic->index_offset;
|
||||
ASSERT(dynamic->element_count % 3 == 0);
|
||||
kusok->triangles = dynamic->element_count / 3;
|
||||
|
||||
ASSERT(create_info->texture_id < MAX_TEXTURES);
|
||||
if (create_info->texture_id >= 0 && g_emissive_texture_table[create_info->texture_id].set) {
|
||||
VectorCopy(g_emissive_texture_table[create_info->texture_id].emissive, kusok->emissive);
|
||||
ASSERT(dynamic->texture_id < MAX_TEXTURES);
|
||||
if (dynamic->texture_id >= 0 && g_emissive_texture_table[dynamic->texture_id].set) {
|
||||
VectorCopy(g_emissive_texture_table[dynamic->texture_id].emissive, kusok->emissive);
|
||||
} else {
|
||||
kusok->emissive[0] = create_info->emissive.r;
|
||||
kusok->emissive[1] = create_info->emissive.g;
|
||||
kusok->emissive[2] = create_info->emissive.b;
|
||||
kusok->emissive[0] = dynamic->emissive.r;
|
||||
kusok->emissive[1] = dynamic->emissive.g;
|
||||
kusok->emissive[2] = dynamic->emissive.b;
|
||||
}
|
||||
|
||||
if (kusok->emissive[0] > 0 || kusok->emissive[1] > 0 || kusok->emissive[2] > 0) {
|
||||
|
@ -283,7 +283,7 @@ void VK_RayScenePushModel( VkCommandBuffer cmdbuf, const vk_ray_model_create_t *
|
|||
}
|
||||
}
|
||||
|
||||
memcpy(model->transform_row, *create_info->transform_row, sizeof(model->transform_row));
|
||||
memcpy(model->transform_row, *dynamic->transform_row, sizeof(model->transform_row));
|
||||
|
||||
g_rtx_scene.num_models++;
|
||||
}
|
||||
|
|
|
@ -12,15 +12,10 @@ typedef struct {
|
|||
VkBuffer buffer;
|
||||
const matrix3x4 *transform_row;
|
||||
struct { float r,g,b; } emissive;
|
||||
} vk_ray_model_create_t;
|
||||
|
||||
typedef int vk_ray_model_handle_t;
|
||||
enum { InvalidRayModel = -1 };
|
||||
|
||||
vk_ray_model_handle_t VK_RayModelCreate( const vk_ray_model_create_t *args );
|
||||
} vk_ray_model_dynamic_t;
|
||||
|
||||
void VK_RaySceneBegin( void );
|
||||
void VK_RayScenePushModel(VkCommandBuffer cmdbuf, const vk_ray_model_create_t* model); // vk_ray_model_handle_t model );
|
||||
void VK_RaySceneAddModelDynamic(VkCommandBuffer cmdbuf, const vk_ray_model_dynamic_t* model);
|
||||
|
||||
typedef struct {
|
||||
VkCommandBuffer cmdbuf;
|
||||
|
|
|
@ -93,7 +93,7 @@ void R_NewMap( void )
|
|||
VK_RunLightStyles();
|
||||
|
||||
// TODO should we do something like VK_BrushBeginLoad?
|
||||
VK_BrushClear();
|
||||
VK_BrushStatsClear();
|
||||
|
||||
// FIXME this is totally incorrect btw.
|
||||
// When loading a save game from the same map this is called, but brush models
|
||||
|
@ -116,7 +116,7 @@ void R_NewMap( void )
|
|||
if( m->type != mod_brush )
|
||||
continue;
|
||||
|
||||
if (!VK_LoadBrushModel( m, NULL ))
|
||||
if (!VK_BrushModelLoad( m ))
|
||||
{
|
||||
gEngine.Con_Printf( S_ERROR "Couldn't load model %s\n", m->name );
|
||||
}
|
||||
|
@ -591,7 +591,7 @@ static void drawEntity( cl_entity_t *ent, int render_mode )
|
|||
case mod_brush:
|
||||
R_RotateForEntity( model, ent );
|
||||
VK_RenderStateSetMatrixModel( model );
|
||||
VK_BrushDrawModel( ent, render_mode );
|
||||
VK_BrushModelDraw( ent, render_mode );
|
||||
break;
|
||||
|
||||
case mod_studio:
|
||||
|
@ -643,7 +643,7 @@ void VK_SceneRender( const ref_viewpass_t *rvp )
|
|||
VK_LightsBakePVL( 0 /* FIXME frame number */);
|
||||
|
||||
VK_RenderStateSetColor( 1.f, 1.f, 1.f, 1.f);
|
||||
VK_BrushDrawModel( world, kRenderNormal );
|
||||
VK_BrushModelDraw( world, kRenderNormal );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ void VK_SceneInit( void );
|
|||
|
||||
void VK_SceneRender( const struct ref_viewpass_s *rvp );
|
||||
|
||||
qboolean VK_LoadBrushModel( model_t *mod, const byte *buffer );
|
||||
qboolean R_AddEntity( struct cl_entity_s *clent, int type );
|
||||
void R_ProcessEntData( qboolean allocate );
|
||||
void R_ClearScreen( void );
|
||||
|
|
Loading…
Reference in New Issue