move buffer allocation to vk_render.c from vk_bruh.c
This commit is contained in:
parent
ad5d515200
commit
5ebe36c54c
|
@ -1,10 +1,10 @@
|
||||||
## 2021-02-08
|
## 2021-02-10
|
||||||
- [ ] move entity rendering-enumeration into vk_scene
|
- [x] refactor brush into brushes and separate rendering/buffer management
|
||||||
- [ ] refactor brush into brushes and separate rendering/buffer management
|
|
||||||
|
|
||||||
# Next
|
# Next
|
||||||
- [ ] draw studio models as bounding boxes
|
- [ ] draw studio models as bounding boxes
|
||||||
- [ ] studio models
|
- [ ] studio models
|
||||||
|
- [ ] animated textures (accept PR)
|
||||||
|
|
||||||
# Planned
|
# Planned
|
||||||
- [ ] move all consts to vk_const
|
- [ ] move all consts to vk_const
|
||||||
|
@ -16,11 +16,12 @@
|
||||||
- [ ] issue: transparent brushes are too transparent (train ride)
|
- [ ] issue: transparent brushes are too transparent (train ride)
|
||||||
- [ ] render skybox
|
- [ ] render skybox
|
||||||
- [ ] mipmaps
|
- [ ] mipmaps
|
||||||
- [ ] animated textures
|
|
||||||
- [ ] lightmap dynamic styles
|
- [ ] lightmap dynamic styles
|
||||||
- [ ] flashlight
|
- [ ] flashlight
|
||||||
- [ ] screenshot
|
- [ ] screenshot
|
||||||
|
- [ ] fog
|
||||||
- [ ] RTX
|
- [ ] RTX
|
||||||
|
- [ ] studio models survive NewMap; need to compactify buffers after removing all brushes
|
||||||
|
|
||||||
# Someday
|
# Someday
|
||||||
- [ ] (helps with RTX?) unified rendering (brush/studio models/...), each model is instance, instance data is read from storage buffers, gives info about vertex format, texture bindings, etc; which are read from another set of storage buffers, ..
|
- [ ] (helps with RTX?) unified rendering (brush/studio models/...), each model is instance, instance data is read from storage buffers, gives info about vertex format, texture bindings, etc; which are read from another set of storage buffers, ..
|
||||||
|
@ -42,3 +43,6 @@
|
||||||
- [x] swapchain getting stale
|
- [x] swapchain getting stale
|
||||||
- [x] HUD sprites
|
- [x] HUD sprites
|
||||||
- [x] issue: lightmap sometimes gets corrupted on map load
|
- [x] issue: lightmap sometimes gets corrupted on map load
|
||||||
|
|
||||||
|
## 2021-02-08
|
||||||
|
- [x] move entity rendering-enumeration into vk_scene
|
||||||
|
|
|
@ -17,10 +17,6 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
|
|
||||||
// TODO count these properly
|
|
||||||
#define MAX_BUFFER_VERTICES (1 * 1024 * 1024)
|
|
||||||
#define MAX_BUFFER_INDICES (MAX_BUFFER_VERTICES * 3)
|
|
||||||
|
|
||||||
typedef struct brush_vertex_s
|
typedef struct brush_vertex_s
|
||||||
{
|
{
|
||||||
vec3_t pos;
|
vec3_t pos;
|
||||||
|
@ -47,34 +43,13 @@ typedef struct vk_brush_model_s {
|
||||||
} vk_brush_model_t;
|
} vk_brush_model_t;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
// TODO merge these into a single buffer
|
struct {
|
||||||
vk_buffer_t vertex_buffer;
|
int num_vertices, num_indices;
|
||||||
uint32_t num_vertices;
|
} stat;
|
||||||
|
|
||||||
vk_buffer_t index_buffer;
|
|
||||||
uint32_t num_indices;
|
|
||||||
|
|
||||||
vk_buffer_t uniform_buffer;
|
|
||||||
uint32_t uniform_unit_size;
|
|
||||||
|
|
||||||
VkPipelineLayout pipeline_layout;
|
VkPipelineLayout pipeline_layout;
|
||||||
VkPipeline pipelines[kRenderTransAdd + 1];
|
VkPipeline pipelines[kRenderTransAdd + 1];
|
||||||
} g_brush;
|
} g_brush;
|
||||||
|
|
||||||
/* static brush_vertex_t *allocVertices(int num_vertices) { */
|
|
||||||
/* if (num_vertices + g_brush.num_vertices > MAX_BUFFER_VERTICES) */
|
|
||||||
/* { */
|
|
||||||
/* gEngine.Con_Printf(S_ERROR "Ran out of buffer vertex space\n"); */
|
|
||||||
/* return NULL; */
|
|
||||||
/* } */
|
|
||||||
/* } */
|
|
||||||
|
|
||||||
uniform_data_t *getUniformSlot(int index)
|
|
||||||
{
|
|
||||||
ASSERT(index >= 0);
|
|
||||||
ASSERT(index < MAX_UNIFORM_SLOTS);
|
|
||||||
return (uniform_data_t*)(((uint8_t*)g_brush.uniform_buffer.mapped) + (g_brush.uniform_unit_size * index));
|
|
||||||
}
|
|
||||||
|
|
||||||
static qboolean createPipelines( void )
|
static qboolean createPipelines( void )
|
||||||
{
|
{
|
||||||
|
@ -237,44 +212,9 @@ static qboolean createPipelines( void )
|
||||||
|
|
||||||
qboolean VK_BrushInit( void )
|
qboolean VK_BrushInit( void )
|
||||||
{
|
{
|
||||||
const uint32_t vertex_buffer_size = MAX_BUFFER_VERTICES * sizeof(brush_vertex_t);
|
|
||||||
const uint32_t index_buffer_size = MAX_BUFFER_INDICES * sizeof(uint16_t);
|
|
||||||
const uint32_t ubo_align = Q_max(4, vk_core.physical_device.properties.limits.minUniformBufferOffsetAlignment);
|
|
||||||
|
|
||||||
g_brush.uniform_unit_size = ((sizeof(uniform_data_t) + ubo_align - 1) / ubo_align) * ubo_align;
|
|
||||||
|
|
||||||
// TODO device memory and friends (e.g. handle mobile memory ...)
|
|
||||||
|
|
||||||
if (!createBuffer(&g_brush.vertex_buffer, vertex_buffer_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!createBuffer(&g_brush.index_buffer, index_buffer_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!createBuffer(&g_brush.uniform_buffer, g_brush.uniform_unit_size * MAX_UNIFORM_SLOTS, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!createPipelines())
|
if (!createPipelines())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
{
|
|
||||||
VkDescriptorBufferInfo dbi = {
|
|
||||||
.buffer = g_brush.uniform_buffer.buffer,
|
|
||||||
.offset = 0,
|
|
||||||
.range = sizeof(uniform_data_t),
|
|
||||||
};
|
|
||||||
VkWriteDescriptorSet wds[] = { {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
||||||
.dstBinding = 0,
|
|
||||||
.dstArrayElement = 0,
|
|
||||||
.descriptorCount = 1,
|
|
||||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
|
|
||||||
.pBufferInfo = &dbi,
|
|
||||||
.dstSet = vk_core.descriptor_pool.ubo_sets[0], // FIXME
|
|
||||||
}};
|
|
||||||
vkUpdateDescriptorSets(vk_core.device, ARRAYSIZE(wds), wds, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,17 +225,12 @@ void VK_BrushShutdown( void )
|
||||||
for (int i = 0; i < ARRAYSIZE(g_brush.pipelines); ++i)
|
for (int i = 0; i < ARRAYSIZE(g_brush.pipelines); ++i)
|
||||||
vkDestroyPipeline(vk_core.device, g_brush.pipelines[i], NULL);
|
vkDestroyPipeline(vk_core.device, g_brush.pipelines[i], NULL);
|
||||||
vkDestroyPipelineLayout( vk_core.device, g_brush.pipeline_layout, NULL );
|
vkDestroyPipelineLayout( vk_core.device, g_brush.pipeline_layout, NULL );
|
||||||
|
|
||||||
destroyBuffer( &g_brush.vertex_buffer );
|
|
||||||
destroyBuffer( &g_brush.index_buffer );
|
|
||||||
destroyBuffer( &g_brush.uniform_buffer );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VK_BrushDrawModel( const model_t *mod, int render_mode, int ubo_index )
|
void VK_BrushDrawModel( const model_t *mod, int render_mode, int ubo_index )
|
||||||
{
|
{
|
||||||
// Expect all buffers to be bound
|
// Expect all buffers to be bound
|
||||||
const vk_brush_model_t *bmodel = mod->cache.data;
|
const vk_brush_model_t *bmodel = mod->cache.data;
|
||||||
const uint32_t dynamic_offset[] = { g_brush.uniform_unit_size * ubo_index };
|
|
||||||
int current_texture = -1;
|
int current_texture = -1;
|
||||||
int index_count = 0;
|
int index_count = 0;
|
||||||
int index_offset = -1;
|
int index_offset = -1;
|
||||||
|
@ -322,7 +257,7 @@ void VK_BrushDrawModel( const model_t *mod, int render_mode, int ubo_index )
|
||||||
vkCmdBindPipeline(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_brush.pipelines[fixme_current_pipeline_index]);
|
vkCmdBindPipeline(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_brush.pipelines[fixme_current_pipeline_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_brush.pipeline_layout, 0, 1, vk_core.descriptor_pool.ubo_sets, ARRAYSIZE(dynamic_offset), dynamic_offset);
|
VK_RenderBindUniformBufferWithIndex( g_brush.pipeline_layout, ubo_index);
|
||||||
|
|
||||||
for (int i = 0; i < bmodel->num_surfaces; ++i) {
|
for (int i = 0; i < bmodel->num_surfaces; ++i) {
|
||||||
const vk_brush_model_surface_t *bsurf = bmodel->surfaces + i;
|
const vk_brush_model_surface_t *bsurf = bmodel->surfaces + i;
|
||||||
|
@ -358,10 +293,7 @@ void VK_BrushDrawModel( const model_t *mod, int render_mode, int ubo_index )
|
||||||
|
|
||||||
qboolean VK_BrushRenderBegin( void )
|
qboolean VK_BrushRenderBegin( void )
|
||||||
{
|
{
|
||||||
const VkDeviceSize offset = 0;
|
VK_RenderBindBuffers(); // TODO in scene?
|
||||||
vkCmdBindVertexBuffers(vk_core.cb, 0, 1, &g_brush.vertex_buffer.buffer, &offset);
|
|
||||||
vkCmdBindIndexBuffer(vk_core.cb, g_brush.index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
|
||||||
|
|
||||||
if (!tglob.lightmapTextures[0])
|
if (!tglob.lightmapTextures[0])
|
||||||
{
|
{
|
||||||
gEngine.Con_Printf( S_ERROR "Don't have a lightmap texture\n");
|
gEngine.Con_Printf( S_ERROR "Don't have a lightmap texture\n");
|
||||||
|
@ -376,10 +308,13 @@ qboolean VK_BrushRenderBegin( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_surfaces) {
|
static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_surfaces) {
|
||||||
brush_vertex_t *bvert = g_brush.vertex_buffer.mapped;
|
vk_brush_model_t *bmodel = mod->cache.data;
|
||||||
uint16_t *bind = g_brush.index_buffer.mapped;
|
|
||||||
uint32_t vertex_offset = 0;
|
uint32_t vertex_offset = 0;
|
||||||
int num_surfaces = 0;
|
int num_surfaces = 0;
|
||||||
|
vk_buffer_alloc_t vertex_alloc, index_alloc;
|
||||||
|
brush_vertex_t *bvert = NULL;
|
||||||
|
uint16_t *bind = NULL;
|
||||||
|
uint32_t index_offset = 0;
|
||||||
|
|
||||||
int num_indices = 0, num_vertices = 0, max_texture_id = 0;
|
int num_indices = 0, num_vertices = 0, max_texture_id = 0;
|
||||||
for( int i = 0; i < mod->nummodelsurfaces; ++i)
|
for( int i = 0; i < mod->nummodelsurfaces; ++i)
|
||||||
|
@ -403,6 +338,27 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
|
||||||
max_texture_id = surf->texinfo->texture->gl_texturenum;
|
max_texture_id = surf->texinfo->texture->gl_texturenum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vertex_alloc = VK_RenderBufferAlloc( sizeof(brush_vertex_t), num_vertices );
|
||||||
|
bvert = vertex_alloc.ptr;
|
||||||
|
bmodel->vertex_offset = vertex_alloc.buffer_offset_in_units;
|
||||||
|
if (!bvert)
|
||||||
|
{
|
||||||
|
gEngine.Con_Printf(S_ERROR "Ran out of buffer vertex space\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
index_alloc = VK_RenderBufferAlloc( sizeof(uint16_t), num_indices );
|
||||||
|
bind = index_alloc.ptr;
|
||||||
|
index_offset = index_alloc.buffer_offset_in_units;
|
||||||
|
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
|
// Load sorted by gl_texturenum
|
||||||
for (int t = 0; t <= max_texture_id; ++t)
|
for (int t = 0; t <= max_texture_id; ++t)
|
||||||
{
|
{
|
||||||
|
@ -426,17 +382,6 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
|
||||||
|
|
||||||
//gEngine.Con_Reportf( "surface %d: numverts=%d numedges=%d\n", i, surf->polys ? surf->polys->numverts : -1, surf->numedges );
|
//gEngine.Con_Reportf( "surface %d: numverts=%d numedges=%d\n", i, surf->polys ? surf->polys->numverts : -1, surf->numedges );
|
||||||
|
|
||||||
if (surf->numedges + g_brush.num_vertices > MAX_BUFFER_VERTICES)
|
|
||||||
{
|
|
||||||
gEngine.Con_Printf(S_ERROR "Ran out of buffer vertex space\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((surf->numedges-1) * 3 + g_brush.num_indices > MAX_BUFFER_INDICES)
|
|
||||||
{
|
|
||||||
gEngine.Con_Printf(S_ERROR "Ran out of buffer index space\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vertex_offset + surf->numedges >= UINT16_MAX)
|
if (vertex_offset + surf->numedges >= UINT16_MAX)
|
||||||
{
|
{
|
||||||
|
@ -445,7 +390,7 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
|
||||||
}
|
}
|
||||||
|
|
||||||
bsurf->texture_num = surf->texinfo->texture->gl_texturenum;
|
bsurf->texture_num = surf->texinfo->texture->gl_texturenum;
|
||||||
bsurf->index_offset = g_brush.num_indices;
|
bsurf->index_offset = index_offset;
|
||||||
bsurf->index_count = 0;
|
bsurf->index_count = 0;
|
||||||
|
|
||||||
VK_CreateSurfaceLightmap( surf, mod );
|
VK_CreateSurfaceLightmap( surf, mod );
|
||||||
|
@ -486,14 +431,15 @@ static int loadBrushSurfaces( const model_t *mod, vk_brush_model_surface_t *out_
|
||||||
|
|
||||||
//gEngine.Con_Printf("VERT %u %f %f %f\n", g_brush.num_vertices, in_vertex->position[0], in_vertex->position[1], in_vertex->position[2]);
|
//gEngine.Con_Printf("VERT %u %f %f %f\n", g_brush.num_vertices, in_vertex->position[0], in_vertex->position[1], in_vertex->position[2]);
|
||||||
|
|
||||||
bvert[g_brush.num_vertices++] = vertex;
|
*(bvert++) = vertex;
|
||||||
|
|
||||||
// TODO contemplate triangle_strip (or fan?) + primitive restart
|
// TODO contemplate triangle_strip (or fan?) + primitive restart
|
||||||
if (k > 1) {
|
if (k > 1) {
|
||||||
bind[g_brush.num_indices++] = (uint16_t)(vertex_offset + 0);
|
*(bind++) = (uint16_t)(vertex_offset + 0);
|
||||||
bind[g_brush.num_indices++] = (uint16_t)(vertex_offset + k - 1);
|
*(bind++) = (uint16_t)(vertex_offset + k - 1);
|
||||||
bind[g_brush.num_indices++] = (uint16_t)(vertex_offset + k);
|
*(bind++) = (uint16_t)(vertex_offset + k);
|
||||||
bsurf->index_count += 3;
|
bsurf->index_count += 3;
|
||||||
|
index_offset += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,7 +465,6 @@ qboolean VK_LoadBrushModel( model_t *mod, const byte *buffer )
|
||||||
bmodel = Mem_Malloc(vk_core.pool, sizeof(vk_brush_model_t) + sizeof(vk_brush_model_surface_t) * mod->nummodelsurfaces);
|
bmodel = Mem_Malloc(vk_core.pool, sizeof(vk_brush_model_t) + sizeof(vk_brush_model_surface_t) * mod->nummodelsurfaces);
|
||||||
mod->cache.data = bmodel;
|
mod->cache.data = bmodel;
|
||||||
|
|
||||||
bmodel->vertex_offset = g_brush.num_vertices;
|
|
||||||
bmodel->num_surfaces = loadBrushSurfaces( mod, bmodel->surfaces );
|
bmodel->num_surfaces = loadBrushSurfaces( mod, bmodel->surfaces );
|
||||||
if (bmodel->num_surfaces < 0) {
|
if (bmodel->num_surfaces < 0) {
|
||||||
gEngine.Con_Reportf( S_ERROR "Model %s was not loaded\n", mod->name );
|
gEngine.Con_Reportf( S_ERROR "Model %s was not loaded\n", mod->name );
|
||||||
|
@ -535,13 +480,13 @@ qboolean VK_LoadBrushModel( model_t *mod, const byte *buffer )
|
||||||
/* bmodel->surfaces[i].index_offset, */
|
/* bmodel->surfaces[i].index_offset, */
|
||||||
/* bmodel->surfaces[i].index_count); */
|
/* bmodel->surfaces[i].index_count); */
|
||||||
|
|
||||||
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.num_vertices, g_brush.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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VK_BrushClear( void )
|
void VK_BrushClear( void )
|
||||||
{
|
{
|
||||||
// Free previous map data
|
// Free previous map data
|
||||||
g_brush.num_vertices = 0;
|
g_brush.stat.num_vertices = 0;
|
||||||
g_brush.num_indices = 0;
|
g_brush.stat.num_indices = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ qboolean createBuffer(vk_buffer_t *buf, uint32_t size, VkBufferUsageFlags usage,
|
||||||
// FIXME when there are many allocation per VkDeviceMemory, fix this
|
// FIXME when there are many allocation per VkDeviceMemory, fix this
|
||||||
XVK_CHECK(vkMapMemory(vk_core.device, buf->device_memory.device_memory, 0, bci.size, 0, &buf->mapped));
|
XVK_CHECK(vkMapMemory(vk_core.device, buf->device_memory.device_memory, 0, bci.size, 0, &buf->mapped));
|
||||||
|
|
||||||
|
buf->size = size;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,5 +30,7 @@
|
||||||
++called; \
|
++called; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
#define ALIGN_UP(ptr, align) ((((ptr) + (align) - 1) / (align)) * (align))
|
||||||
|
|
||||||
extern ref_api_t gEngine;
|
extern ref_api_t gEngine;
|
||||||
extern ref_globals_t *gpGlobals;
|
extern ref_globals_t *gpGlobals;
|
||||||
|
|
|
@ -2,3 +2,7 @@
|
||||||
|
|
||||||
#define MAX_SCENE_STACK 2
|
#define MAX_SCENE_STACK 2
|
||||||
#define MAX_SCENE_ENTITIES 2048
|
#define MAX_SCENE_ENTITIES 2048
|
||||||
|
|
||||||
|
// TODO count these properly
|
||||||
|
#define MAX_BUFFER_VERTICES (1 * 1024 * 1024)
|
||||||
|
#define MAX_BUFFER_INDICES (MAX_BUFFER_VERTICES * 3)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "vk_scene.h"
|
#include "vk_scene.h"
|
||||||
#include "vk_cvar.h"
|
#include "vk_cvar.h"
|
||||||
#include "vk_pipeline.h"
|
#include "vk_pipeline.h"
|
||||||
|
#include "vk_render.h"
|
||||||
|
|
||||||
#include "xash3d_types.h"
|
#include "xash3d_types.h"
|
||||||
#include "cvardef.h"
|
#include "cvardef.h"
|
||||||
|
@ -579,6 +580,9 @@ qboolean R_VkInit( void )
|
||||||
|
|
||||||
VK_LoadCvars();
|
VK_LoadCvars();
|
||||||
|
|
||||||
|
if (!VK_RenderInit())
|
||||||
|
return false;
|
||||||
|
|
||||||
VK_SceneInit();
|
VK_SceneInit();
|
||||||
|
|
||||||
initTextures();
|
initTextures();
|
||||||
|
@ -606,6 +610,8 @@ void R_VkShutdown( void )
|
||||||
|
|
||||||
destroyTextures();
|
destroyTextures();
|
||||||
|
|
||||||
|
VK_RenderShutdown();
|
||||||
|
|
||||||
VK_PipelineShutdown();
|
VK_PipelineShutdown();
|
||||||
|
|
||||||
vkDestroyDescriptorPool(vk_core.device, vk_core.descriptor_pool.pool, NULL);
|
vkDestroyDescriptorPool(vk_core.device, vk_core.descriptor_pool.pool, NULL);
|
||||||
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
#include "vk_render.h"
|
||||||
|
|
||||||
|
#include "vk_core.h"
|
||||||
|
#include "vk_buffer.h"
|
||||||
|
#include "vk_const.h"
|
||||||
|
#include "vk_common.h"
|
||||||
|
|
||||||
|
#include "eiface.h"
|
||||||
|
#include "xash3d_mathlib.h"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
vk_buffer_t buffer;
|
||||||
|
uint32_t buffer_free_offset;
|
||||||
|
|
||||||
|
vk_buffer_t uniform_buffer;
|
||||||
|
uint32_t uniform_unit_size;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int align_holes_size;
|
||||||
|
} stat;
|
||||||
|
} g_render;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
VkPipeline current_pipeline;
|
||||||
|
} g_render_state;
|
||||||
|
|
||||||
|
uniform_data_t *VK_RenderGetUniformSlot(int index)
|
||||||
|
{
|
||||||
|
ASSERT(index >= 0);
|
||||||
|
ASSERT(index < MAX_UNIFORM_SLOTS);
|
||||||
|
return (uniform_data_t*)(((uint8_t*)g_render.uniform_buffer.mapped) + (g_render.uniform_unit_size * index));
|
||||||
|
}
|
||||||
|
|
||||||
|
qboolean VK_RenderInit( void )
|
||||||
|
{
|
||||||
|
// TODO Better estimates
|
||||||
|
const uint32_t vertex_buffer_size = MAX_BUFFER_VERTICES * sizeof(float) * (3 + 3 + 2 + 2);
|
||||||
|
const uint32_t index_buffer_size = MAX_BUFFER_INDICES * sizeof(uint16_t);
|
||||||
|
const uint32_t ubo_align = Q_max(4, vk_core.physical_device.properties.limits.minUniformBufferOffsetAlignment);
|
||||||
|
|
||||||
|
g_render.uniform_unit_size = ((sizeof(uniform_data_t) + ubo_align - 1) / ubo_align) * ubo_align;
|
||||||
|
|
||||||
|
// TODO device memory and friends (e.g. handle mobile memory ...)
|
||||||
|
|
||||||
|
if (!createBuffer(&g_render.buffer, vertex_buffer_size + index_buffer_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!createBuffer(&g_render.uniform_buffer, g_render.uniform_unit_size * MAX_UNIFORM_SLOTS, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
{
|
||||||
|
VkDescriptorBufferInfo dbi = {
|
||||||
|
.buffer = g_render.uniform_buffer.buffer,
|
||||||
|
.offset = 0,
|
||||||
|
.range = sizeof(uniform_data_t),
|
||||||
|
};
|
||||||
|
VkWriteDescriptorSet wds[] = { {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||||
|
.dstBinding = 0,
|
||||||
|
.dstArrayElement = 0,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
|
||||||
|
.pBufferInfo = &dbi,
|
||||||
|
.dstSet = vk_core.descriptor_pool.ubo_sets[0], // FIXME
|
||||||
|
}};
|
||||||
|
vkUpdateDescriptorSets(vk_core.device, ARRAYSIZE(wds), wds, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VK_RenderShutdown( void )
|
||||||
|
{
|
||||||
|
destroyBuffer( &g_render.buffer );
|
||||||
|
destroyBuffer( &g_render.uniform_buffer );
|
||||||
|
}
|
||||||
|
|
||||||
|
void VK_RenderBindBuffers( void )
|
||||||
|
{
|
||||||
|
const VkDeviceSize offset = 0;
|
||||||
|
vkCmdBindVertexBuffers(vk_core.cb, 0, 1, &g_render.buffer.buffer, &offset);
|
||||||
|
vkCmdBindIndexBuffer(vk_core.cb, g_render.buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VK_RenderBindUniformBufferWithIndex( VkPipelineLayout pipeline_layout, int index )
|
||||||
|
{
|
||||||
|
const uint32_t dynamic_offset[] = { g_render.uniform_unit_size * index };
|
||||||
|
|
||||||
|
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_layout, 0, 1, vk_core.descriptor_pool.ubo_sets, ARRAYSIZE(dynamic_offset), dynamic_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
vk_buffer_alloc_t VK_RenderBufferAlloc( uint32_t unit_size, uint32_t count )
|
||||||
|
{
|
||||||
|
const uint32_t offset = ALIGN_UP(g_render.buffer_free_offset, unit_size);
|
||||||
|
const uint32_t alloc_size = unit_size * count;
|
||||||
|
vk_buffer_alloc_t ret = {0};
|
||||||
|
if (offset + alloc_size > g_render.buffer.size) {
|
||||||
|
gEngine.Con_Printf(S_ERROR "Cannot allocate %u bytes aligned at %u from buffer; only %u are left",
|
||||||
|
alloc_size, unit_size, g_render.buffer.size - offset);
|
||||||
|
return (vk_buffer_alloc_t){0};
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.buffer_offset_in_units = offset / unit_size;
|
||||||
|
ret.ptr = g_render.buffer.mapped + offset;
|
||||||
|
|
||||||
|
g_render.stat.align_holes_size += offset - g_render.buffer_free_offset;
|
||||||
|
g_render.buffer_free_offset = offset + alloc_size;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VK_RenderBufferClearAll( void )
|
||||||
|
{
|
||||||
|
g_render.buffer_free_offset = 0;
|
||||||
|
g_render.stat.align_holes_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VK_RenderBufferPrintStats( void )
|
||||||
|
{
|
||||||
|
gEngine.Con_Reportf("Buffer usage: %uKiB of (%uKiB); holes: %u bytes\n",
|
||||||
|
g_render.buffer_free_offset / 1024,
|
||||||
|
g_render.buffer.size / 1024,
|
||||||
|
g_render.stat.align_holes_size);
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "vk_common.h"
|
#include "vk_common.h"
|
||||||
#include "vk_const.h"
|
#include "vk_const.h"
|
||||||
|
#include "vk_core.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
matrix4x4 mvp;
|
matrix4x4 mvp;
|
||||||
|
@ -9,4 +10,23 @@ typedef struct {
|
||||||
|
|
||||||
#define MAX_UNIFORM_SLOTS (MAX_SCENE_ENTITIES * 2 /* solid + trans */ + 1)
|
#define MAX_UNIFORM_SLOTS (MAX_SCENE_ENTITIES * 2 /* solid + trans */ + 1)
|
||||||
|
|
||||||
uniform_data_t *getUniformSlot(int index);
|
uniform_data_t *VK_RenderGetUniformSlot(int index);
|
||||||
|
|
||||||
|
typedef struct vk_buffer_alloc_s {
|
||||||
|
uint32_t buffer_offset_in_units;
|
||||||
|
void *ptr;
|
||||||
|
} vk_buffer_alloc_t;
|
||||||
|
|
||||||
|
// TODO uploading to GPU mem interface
|
||||||
|
vk_buffer_alloc_t VK_RenderBufferAlloc( uint32_t unit_size, uint32_t count );
|
||||||
|
|
||||||
|
void VK_RenderBufferClearAll( void );
|
||||||
|
|
||||||
|
qboolean VK_RenderInit( void );
|
||||||
|
void VK_RenderShutdown( void );
|
||||||
|
|
||||||
|
// TODO should this not be global?
|
||||||
|
void VK_RenderBindBuffers( void );
|
||||||
|
void VK_RenderBindUniformBufferWithIndex( VkPipelineLayout pipeline_layout, int index );
|
||||||
|
|
||||||
|
void VK_RenderBufferPrintStats( void );
|
||||||
|
|
|
@ -78,6 +78,7 @@ void R_NewMap( void )
|
||||||
|
|
||||||
// TODO should we do something like VK_BrushBeginLoad?
|
// TODO should we do something like VK_BrushBeginLoad?
|
||||||
VK_BrushClear();
|
VK_BrushClear();
|
||||||
|
VK_RenderBufferClearAll();
|
||||||
|
|
||||||
// Load all models at once
|
// Load all models at once
|
||||||
gEngine.Con_Reportf( "Num models: %d:\n", num_models );
|
gEngine.Con_Reportf( "Num models: %d:\n", num_models );
|
||||||
|
@ -100,6 +101,8 @@ void R_NewMap( void )
|
||||||
|
|
||||||
// TODO should we do something like VK_BrushEndLoad?
|
// TODO should we do something like VK_BrushEndLoad?
|
||||||
VK_UploadLightmap();
|
VK_UploadLightmap();
|
||||||
|
|
||||||
|
VK_RenderBufferPrintStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
qboolean R_AddEntity( struct cl_entity_s *clent, int type )
|
qboolean R_AddEntity( struct cl_entity_s *clent, int type )
|
||||||
|
@ -490,7 +493,7 @@ static int drawEntity( cl_entity_t *ent, int render_mode, int ubo_index, const m
|
||||||
{
|
{
|
||||||
const model_t *mod = ent->model;
|
const model_t *mod = ent->model;
|
||||||
matrix4x4 model, ent_mvp;
|
matrix4x4 model, ent_mvp;
|
||||||
uniform_data_t *ubo = getUniformSlot(ubo_index);
|
uniform_data_t *ubo = VK_RenderGetUniformSlot(ubo_index);
|
||||||
float alpha;
|
float alpha;
|
||||||
|
|
||||||
if (!mod)
|
if (!mod)
|
||||||
|
@ -557,7 +560,7 @@ void VK_SceneRender( void )
|
||||||
const model_t *world = gEngine.pfnGetModelByIndex( 1 );
|
const model_t *world = gEngine.pfnGetModelByIndex( 1 );
|
||||||
if (world)
|
if (world)
|
||||||
{
|
{
|
||||||
uniform_data_t *ubo = getUniformSlot(ubo_index);
|
uniform_data_t *ubo = VK_RenderGetUniformSlot(ubo_index);
|
||||||
Matrix4x4_ToArrayFloatGL( mvp, (float*)ubo->mvp );
|
Matrix4x4_ToArrayFloatGL( mvp, (float*)ubo->mvp );
|
||||||
Vector4Set(ubo->color, 1.f, 1.f, 1.f, 1.f);
|
Vector4Set(ubo->color, 1.f, 1.f, 1.f, 1.f);
|
||||||
VK_BrushDrawModel( world, kRenderNormal, ubo_index );
|
VK_BrushDrawModel( world, kRenderNormal, ubo_index );
|
||||||
|
|
Loading…
Reference in New Issue