engage scene rendering in VK_RenderFrame and not in EndFrame

Rework a bit how matrices are computed. More global state dependencies
;_;

Buffer-up draw commands, and only schedule them for drawing at EndFrame.
This commit is contained in:
Ivan Avdeev 2021-02-20 14:54:57 -08:00
parent a5e279f580
commit 3f70b76208
10 changed files with 229 additions and 184 deletions

View File

@ -3,15 +3,15 @@
- [x] move uniform_data_t to global render state ~inside render_draw_t, remove any mentions of uniform/slots from api; alt: global render state?~
- [x] rename RenderDraw to SubmitDraw
- [x] ~add debug label to render_draw_t?;~ alt: VK_RenderDebugNameBegin/End
- [x] perform 3d rendering on corresponding refapi calls, not endframe
- [ ] restore debug labels
- [x] fix sprite blending
# Next
- [ ] refactor vk_render interface:
- [ ] make 2nd commad buffer for resource upload
- [ ] start building command buffers in beginframe
- [ ] perform 3d rendering on corresponding refapi calls, not endframe
# Planned
- [ ] make 2nd commad buffer for resource upload
- [ ] fix sprite blending; there are commented out functions that we really need (see tunnel before the helicopter in the very beginning)
- [ ] RTX: make projection matrix independent render global/current/static state
- [ ] fix projection matrix differences w/ gl render
- [ ] bad condition for temp vs map-permanent buffer error message
@ -40,6 +40,8 @@
- [ ] RTX: studio models should not pre-transform vertices with modelView matrix
# Someday
- [ ] start building command buffers in beginframe
- [ ] multiple frames in flight (#nd cmdbuf, ...)
- [ ] cleanup unused stuff in vk_studio.c
- [ ] (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, ..
- [ ] waf shader build step -- get from upstream

View File

@ -137,14 +137,14 @@ void vk2dBegin( void )
g2d.batch[0].vertex_count = 0;
}
void vk2dEnd( void )
void vk2dEnd( VkCommandBuffer cmdbuf )
{
const VkDeviceSize offset = 0;
if (!g2d.num_pics)
return;
vkCmdBindVertexBuffers(vk_core.cb, 0, 1, &g2d.pics_buffer.buffer, &offset);
vkCmdBindVertexBuffers(cmdbuf, 0, 1, &g2d.pics_buffer.buffer, &offset);
for (int i = 0; i <= g2d.current_batch; ++i)
{
@ -152,9 +152,9 @@ void vk2dEnd( void )
const VkPipeline pipeline = g2d.pipelines[g2d.batch[i].blending_mode];
if (texture->vk.descriptor)
{
vkCmdBindPipeline(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g2d.pipeline_layout, 0, 1, &texture->vk.descriptor, 0, NULL);
vkCmdDraw(vk_core.cb, g2d.batch[i].vertex_count, 1, g2d.batch[i].vertex_offset, 0);
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, g2d.pipeline_layout, 0, 1, &texture->vk.descriptor, 0, NULL);
vkCmdDraw(cmdbuf, g2d.batch[i].vertex_count, 1, g2d.batch[i].vertex_offset, 0);
} // FIXME else what?
}
}

View File

@ -1,5 +1,6 @@
#pragma once
#include "vk_core.h"
#include "xash3d_types.h"
void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty );
@ -11,4 +12,4 @@ void CL_FillRGBABlend( float x, float y, float w, float h, int r, int g, int b,
qboolean initVk2d( void );
void deinitVk2d( void );
void vk2dBegin( void );
void vk2dEnd( void );
void vk2dEnd( VkCommandBuffer cmdbuf );

View File

@ -2,6 +2,7 @@
#include "vk_2d.h"
#include "vk_scene.h"
#include "vk_render.h"
#include "eiface.h"
@ -12,6 +13,8 @@ static struct
VkSemaphore image_available;
VkSemaphore done;
VkFence fence;
uint32_t swapchain_image_index;
} g_frame;
static VkFormat findSupportedImageFormat(const VkFormat *candidates, VkImageTiling tiling, VkFormatFeatureFlags features) {
@ -251,7 +254,8 @@ static qboolean createSwapchain( void )
void R_BeginFrame( qboolean clearScene )
{
// gEngine.Con_Reportf("%s(clearScene=%d)\n", __FUNCTION__, clearScene);
// TODO should we handle multiple R_BeginFrame w/o R_EndFrame gracefully?
ASSERT(g_frame.swapchain_image_index == -1);
// Check that swapchain has the same size
{
@ -265,6 +269,29 @@ void R_BeginFrame( qboolean clearScene )
}
}
for (int i = 0;; ++i)
{
const VkResult acquire_result = vkAcquireNextImageKHR(vk_core.device, vk_frame.swapchain, UINT64_MAX, g_frame.image_available,
VK_NULL_HANDLE, &g_frame.swapchain_image_index);
switch (acquire_result)
{
// TODO re-ask for swapchain size if it changed
case VK_ERROR_OUT_OF_DATE_KHR:
case VK_ERROR_SURFACE_LOST_KHR:
if (i == 0) {
createSwapchain();
continue;
}
gEngine.Con_Printf(S_WARN "vkAcquireNextImageKHR returned %s, frame will be lost\n", resultName(acquire_result));
return;
default:
XVK_CHECK(acquire_result);
}
break;
}
// FIXME when
{
cvar_t* vid_gamma = gEngine.pfnGetCvarPointer( "gamma", 0 );
@ -286,17 +313,16 @@ void R_BeginFrame( qboolean clearScene )
}
vk2dBegin();
VK_RenderBegin();
}
void GL_RenderFrame( const struct ref_viewpass_s *rvp )
void VK_RenderFrame( const struct ref_viewpass_s *rvp )
{
// gEngine.Con_Printf(S_WARN "VK FIXME: %s\n", __FUNCTION__);
FIXME_VK_SceneSetViewPass(rvp);
VK_SceneRender( rvp );
}
void R_EndFrame( void )
{
uint32_t swapchain_image_index;
VkClearValue clear_value[] = {
{.color = {{1., 0., 0., 0.}}},
{.depthStencil = {1., 0.}} // TODO reverse-z
@ -316,36 +342,12 @@ void R_EndFrame( void )
VkPresentInfoKHR presinfo = {
.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
.pSwapchains = &vk_frame.swapchain,
.pImageIndices = &swapchain_image_index,
.pImageIndices = &g_frame.swapchain_image_index,
.swapchainCount = 1,
.pWaitSemaphores = &g_frame.done,
.waitSemaphoreCount = 1,
};
// gEngine.Con_Reportf("%s\n", __FUNCTION__);
for (int i = 0;; ++i)
{
const VkResult acquire_result = vkAcquireNextImageKHR(vk_core.device, vk_frame.swapchain, UINT64_MAX, g_frame.image_available,
VK_NULL_HANDLE, &swapchain_image_index);
switch (acquire_result)
{
case VK_ERROR_OUT_OF_DATE_KHR:
case VK_ERROR_SURFACE_LOST_KHR:
if (i == 0) {
createSwapchain();
continue;
}
gEngine.Con_Printf(S_WARN "vkAcquireNextImageKHR returned %s, frame will be lost\n", resultName(acquire_result));
return;
default:
XVK_CHECK(acquire_result);
}
break;
}
{
VkCommandBufferBeginInfo beginfo = {
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
@ -362,7 +364,7 @@ void R_EndFrame( void )
.renderArea.extent.height = vk_frame.create_info.imageExtent.height,
.clearValueCount = ARRAYSIZE(clear_value),
.pClearValues = clear_value,
.framebuffer = vk_frame.framebuffers[swapchain_image_index],
.framebuffer = vk_frame.framebuffers[g_frame.swapchain_image_index],
};
vkCmdBeginRenderPass(vk_core.cb, &rpbi, VK_SUBPASS_CONTENTS_INLINE);
}
@ -380,9 +382,8 @@ void R_EndFrame( void )
vkCmdSetScissor(vk_core.cb, 0, ARRAYSIZE(scissor), scissor);
}
VK_SceneRender();
vk2dEnd();
VK_RenderEnd( vk_core.cb );
vk2dEnd( vk_core.cb );
vkCmdEndRenderPass(vk_core.cb);
XVK_CHECK(vkEndCommandBuffer(vk_core.cb));
@ -405,6 +406,8 @@ void R_EndFrame( void )
// TODO bad sync
XVK_CHECK(vkWaitForFences(vk_core.device, 1, &g_frame.fence, VK_TRUE, INT64_MAX));
XVK_CHECK(vkResetFences(vk_core.device, 1, &g_frame.fence));
g_frame.swapchain_image_index = -1;
}
qboolean VK_FrameCtlInit( void )
@ -418,6 +421,7 @@ qboolean VK_FrameCtlInit( void )
g_frame.image_available = createSemaphore();
g_frame.done = createSemaphore();
g_frame.fence = createFence();
g_frame.swapchain_image_index = -1;
return true;
}

View File

@ -27,5 +27,5 @@ qboolean VK_FrameCtlInit( void );
void VK_FrameCtlShutdown( void );
void R_BeginFrame( qboolean clearScene );
void GL_RenderFrame( const struct ref_viewpass_s *rvp );
void VK_RenderFrame( const struct ref_viewpass_s *rvp );
void R_EndFrame( void );

View File

@ -320,15 +320,23 @@ void VK_RenderTempBufferEnd( void )
g_render.buffer_free_offset = g_render.temp_buffer_offset;
}
static struct {
int pipeline;
int lightmap; // TODO rename to 2nd texture
int texture;
#define MAX_DRAW_COMMANDS 8192 // TODO estimate
#define MAX_DEBUG_NAME_LENGTH 32
typedef struct {
render_draw_t draw;
uint32_t ubo_offset;
//char debug_name[MAX_DEBUG_NAME_LENGTH];
} draw_command_t;
static struct {
int uniform_data_set_mask;
int next_free_uniform_slot;
uniform_data_t current_uniform_data;
uniform_data_t dirty_uniform_data;
draw_command_t draw_commands[MAX_DRAW_COMMANDS];
int num_draw_commands;
} g_render_state;
enum {
@ -341,20 +349,12 @@ enum {
void VK_RenderBegin( void ) {
g_render_state.next_free_uniform_slot = 0;
g_render_state.pipeline = -1;
g_render_state.lightmap = -1;
g_render_state.texture = -1;
g_render_state.uniform_data_set_mask = UNIFORM_UNSET;
memset(&g_render_state.current_uniform_data, 0, sizeof(g_render_state.current_uniform_data));
memset(&g_render_state.dirty_uniform_data, 0, sizeof(g_render_state.dirty_uniform_data));
{
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);
}
g_render_state.num_draw_commands = 0;
}
void VK_RenderStateSetColor( float r, float g, float b, float a )
@ -388,6 +388,9 @@ static int allocUniformSlot( void ) {
void VK_RenderScheduleDraw( const render_draw_t *draw )
{
int ubo_index = g_render_state.next_free_uniform_slot - 1;
draw_command_t *draw_command;
ASSERT(draw->render_mode >= 0);
ASSERT(draw->render_mode < ARRAYSIZE(g_render.pipelines));
ASSERT(draw->lightmap >= 0);
@ -398,11 +401,16 @@ void VK_RenderScheduleDraw( const render_draw_t *draw )
return;
}
if (g_render_state.num_draw_commands >= ARRAYSIZE(g_render_state.draw_commands)) {
gEngine.Con_Printf( S_ERROR "Maximum number of draw commands reached\n" );
return;
}
// Figure out whether we need to update UBO data, and upload new data if we do
// TODO generally it's not safe to do memcmp for structure
// TODO generally it's not safe to do memcmp for structures comparison
if (((g_render_state.uniform_data_set_mask & UNIFORM_UPLOADED) == 0) || memcmp(&g_render_state.current_uniform_data, &g_render_state.dirty_uniform_data, sizeof(g_render_state.current_uniform_data)) != 0) {
const int ubo_index = allocUniformSlot();
uniform_data_t *ubo;
ubo_index = allocUniformSlot();
if (ubo_index < 0) {
gEngine.Con_Printf( S_ERROR "Ran out of uniform slots\n" );
return;
@ -412,56 +420,78 @@ void VK_RenderScheduleDraw( const render_draw_t *draw )
memcpy(&g_render_state.current_uniform_data, &g_render_state.dirty_uniform_data, sizeof(g_render_state.dirty_uniform_data));
memcpy(ubo, &g_render_state.current_uniform_data, sizeof(*ubo));
g_render_state.uniform_data_set_mask |= UNIFORM_UPLOADED;
{
const uint32_t dynamic_offset[] = { g_render.uniform_unit_size * ubo_index};
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 0, 1, vk_core.descriptor_pool.ubo_sets, ARRAYSIZE(dynamic_offset), dynamic_offset);
}
}
if (g_render_state.pipeline != draw->render_mode) {
g_render_state.pipeline = draw->render_mode;
vkCmdBindPipeline(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipelines[g_render_state.pipeline]);
}
if (g_render_state.lightmap != draw->lightmap) {
g_render_state.lightmap = draw->lightmap;
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 2, 1, &findTexture(g_render_state.lightmap)->vk.descriptor, 0, NULL);
}
if (g_render_state.texture != draw->texture)
{
g_render_state.texture = draw->texture;
// TODO names/enums for binding points
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 1, 1, &findTexture(g_render_state.texture)->vk.descriptor, 0, NULL);
}
if (draw->index_offset == UINT32_MAX) {
/*gEngine.Con_Reportf( "Draw("
"ubo_index=%d, "
"lightmap=%d, "
"texture=%d, "
"render_mode=%d, "
"element_count=%u, "
"index_offset=%u, "
"vertex_offset=%u)\n",
draw->ubo_index,
draw->lightmap,
draw->texture,
draw->render_mode,
draw->element_count,
draw->index_offset,
draw->vertex_offset );
*/
vkCmdDraw(vk_core.cb, draw->element_count, 1, draw->vertex_offset, 0);
} else {
vkCmdDrawIndexed(vk_core.cb, draw->element_count, 1, draw->index_offset, draw->vertex_offset, 0);
}
draw_command = g_render_state.draw_commands + (g_render_state.num_draw_commands++);
draw_command->draw = *draw;
draw_command->ubo_offset = g_render.uniform_unit_size * ubo_index;
}
void VK_RenderEnd( void )
void VK_RenderEnd( VkCommandBuffer cmdbuf )
{
// TODO we can sort collected draw commands for more efficient and correct rendering
// that requires adding info about distance to camera for correct order-dependent blending
int pipeline = -1;
int texture = -1;
int lightmap = -1;
uint32_t ubo_offset = -1;
{
const VkDeviceSize offset = 0;
vkCmdBindVertexBuffers(cmdbuf, 0, 1, &g_render.buffer.buffer, &offset);
vkCmdBindIndexBuffer(cmdbuf, g_render.buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
}
for (int i = 0; i < g_render_state.num_draw_commands; ++i) {
const draw_command_t *const draw = g_render_state.draw_commands + i;
if (ubo_offset != draw->ubo_offset)
{
ubo_offset = draw->ubo_offset;
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 0, 1, vk_core.descriptor_pool.ubo_sets, 1., &ubo_offset);
}
if (pipeline != draw->draw.render_mode) {
pipeline = draw->draw.render_mode;
vkCmdBindPipeline(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipelines[pipeline]);
}
if (lightmap != draw->draw.lightmap) {
lightmap = draw->draw.lightmap;
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 2, 1, &findTexture(lightmap)->vk.descriptor, 0, NULL);
}
if (texture != draw->draw.texture)
{
texture = draw->draw.texture;
// TODO names/enums for binding points
vkCmdBindDescriptorSets(vk_core.cb, VK_PIPELINE_BIND_POINT_GRAPHICS, g_render.pipeline_layout, 1, 1, &findTexture(texture)->vk.descriptor, 0, NULL);
}
if (draw->draw.index_offset == UINT32_MAX) {
/*gEngine.Con_Reportf( "Draw("
"ubo_index=%d, "
"lightmap=%d, "
"texture=%d, "
"render_mode=%d, "
"element_count=%u, "
"index_offset=%u, "
"vertex_offset=%u)\n",
draw->ubo_index,
draw->lightmap,
draw->texture,
draw->render_mode,
draw->element_count,
draw->index_offset,
draw->vertex_offset );
*/
vkCmdDraw(vk_core.cb, draw->draw.element_count, 1, draw->draw.vertex_offset, 0);
} else {
vkCmdDrawIndexed(vk_core.cb, draw->draw.element_count, 1, draw->draw.index_offset, draw->draw.vertex_offset, 0);
}
}
}
void VK_RenderDebugLabelBegin( const char *name )

View File

@ -46,7 +46,7 @@ typedef struct render_draw_s {
void VK_RenderBegin( void );
void VK_RenderScheduleDraw( const render_draw_t *draw );
void VK_RenderEnd( void );
void VK_RenderEnd( VkCommandBuffer cmdbuf );
void VK_RenderDebugLabelBegin( const char *label );
void VK_RenderDebugLabelEnd( void );

View File

@ -611,7 +611,7 @@ ref_interface_t gReffuncs =
R_LightVec,
R_StudioGetTexture,
GL_RenderFrame,
VK_RenderFrame,
GL_OrthoBounds,
R_SpeedsMessage,
Mod_GetCurrentVis,

View File

@ -14,6 +14,7 @@
#include "com_strings.h"
#include "ref_params.h"
#include "eiface.h"
#include "pm_movevars.h"
#include <stdlib.h> // qsort
#include <memory.h>
@ -222,16 +223,16 @@ void R_RenderScene( void )
PRINT_NOT_IMPLEMENTED();
}
#define WORLDMODEL (gEngine.pfnGetModelByIndex( 1 ))
#define MOVEVARS (gEngine.pfnGetMoveVars())
static float R_GetFarClip( void )
{
/* FIXME
if( WORLDMODEL && RI.drawWorld )
if( WORLDMODEL /* FIXME VK && RI.drawWorld */ )
return MOVEVARS->zmax * 1.73f;
*/
return 2048.0f;
}
static void R_SetupProjectionMatrix( const ref_viewpass_t *rvp, matrix4x4 m )
static void R_SetupProjectionMatrix( matrix4x4 m )
{
float xMin, xMax, yMin, yMax, zNear, zFar;
@ -249,62 +250,22 @@ static void R_SetupProjectionMatrix( const ref_viewpass_t *rvp, matrix4x4 m )
zNear = 4.0f;
zFar = Q_max( 256.0f, farClip );
yMax = zNear * tan( rvp->fov_y * M_PI_F / 360.0f );
yMax = zNear * tan( g_camera.fov_y * M_PI_F / 360.0f );
yMin = -yMax;
xMax = zNear * tan( rvp->fov_x * M_PI_F / 360.0f );
xMax = zNear * tan( g_camera.fov_x * M_PI_F / 360.0f );
xMin = -xMax;
Matrix4x4_CreateProjection( m, xMax, xMin, yMax, yMin, zNear, zFar );
}
static void R_SetupModelviewMatrix( const ref_viewpass_t* rvp, matrix4x4 m )
static void R_SetupModelviewMatrix( matrix4x4 m )
{
Matrix4x4_CreateModelview( m );
Matrix4x4_ConcatRotate( m, -rvp->viewangles[2], 1, 0, 0 );
Matrix4x4_ConcatRotate( m, -rvp->viewangles[0], 0, 1, 0 );
Matrix4x4_ConcatRotate( m, -rvp->viewangles[1], 0, 0, 1 );
Matrix4x4_ConcatTranslate( m, -rvp->vieworigin[0], -rvp->vieworigin[1], -rvp->vieworigin[2] );
}
// FIXME this is a total garbage. pls avoid adding even more weird local static state
static ref_viewpass_t fixme_rvp;
void FIXME_VK_SceneSetViewPass( const struct ref_viewpass_s *rvp )
{
fixme_rvp = *rvp;
R_SetupModelviewMatrix( rvp, g_camera.worldviewMatrix );
R_SetupProjectionMatrix( rvp, g_camera.projectionMatrix );
Matrix4x4_Concat( g_camera.worldviewProjectionMatrix, g_camera.projectionMatrix, g_camera.worldviewMatrix );
/*
RI.params = RP_NONE;
RI.drawWorld = FBitSet( rvp->flags, RF_DRAW_WORLD );
RI.onlyClientDraw = FBitSet( rvp->flags, RF_ONLY_CLIENTDRAW );
RI.farClip = 0;
if( !FBitSet( rvp->flags, RF_DRAW_CUBEMAP ))
RI.drawOrtho = FBitSet( rvp->flags, RF_DRAW_OVERVIEW );
else RI.drawOrtho = false;
*/
// setup viewport
g_camera.viewport[0] = rvp->viewport[0];
g_camera.viewport[1] = rvp->viewport[1];
g_camera.viewport[2] = rvp->viewport[2];
g_camera.viewport[3] = rvp->viewport[3];
// calc FOV
g_camera.fov_x = rvp->fov_x;
g_camera.fov_y = rvp->fov_y;
VectorCopy( rvp->vieworigin, g_camera.vieworg );
VectorCopy( rvp->viewangles, g_camera.viewangles );
//VectorCopy( rvp->vieworigin, g_camera.pvsorigin );
AngleVectors( g_camera.viewangles, g_camera.vforward, g_camera.vright, g_camera.vup );
Matrix4x4_ConcatRotate( m, -g_camera.viewangles[2], 1, 0, 0 );
Matrix4x4_ConcatRotate( m, -g_camera.viewangles[0], 0, 1, 0 );
Matrix4x4_ConcatRotate( m, -g_camera.viewangles[1], 0, 0, 1 );
Matrix4x4_ConcatTranslate( m, -g_camera.vieworg[0], -g_camera.vieworg[1], -g_camera.vieworg[2] );
}
static void R_RotateForEntity( matrix4x4 out, const cl_entity_t *e )
@ -347,7 +308,6 @@ Sorting translucent entities by rendermode then by distance
FIXME find a better place for this function
===============
*/
static vec3_t R_TransEntityCompare_vieworg; // F
static int R_TransEntityCompare( const void *a, const void *b)
{
vk_trans_entity_t *tent1, *tent2;
@ -371,7 +331,7 @@ static int R_TransEntityCompare( const void *a, const void *b)
{
VectorAverage( ent1->model->mins, ent1->model->maxs, org );
VectorAdd( ent1->origin, org, org );
VectorSubtract( R_TransEntityCompare_vieworg, org, vecLen );
VectorSubtract( g_camera.vieworg, org, vecLen );
dist1 = DotProduct( vecLen, vecLen );
}
else dist1 = 1000000000;
@ -380,7 +340,7 @@ static int R_TransEntityCompare( const void *a, const void *b)
{
VectorAverage( ent2->model->mins, ent2->model->maxs, org );
VectorAdd( ent2->origin, org, org );
VectorSubtract( R_TransEntityCompare_vieworg, org, vecLen );
VectorSubtract( g_camera.vieworg, org, vecLen );
dist2 = DotProduct( vecLen, vecLen );
}
else dist2 = 1000000000;
@ -516,22 +476,74 @@ int CL_FxBlend( cl_entity_t *e ) // FIXME do R_SetupFrustum: , vec3_t vforward )
return blend;
}
static void prepareMatrix( const ref_viewpass_t *rvp, matrix4x4 worldview, matrix4x4 projection, matrix4x4 mvp )
// Analagous to R_SetupRefParams, R_SetupFrustum in GL/Soft renderers
static void setupCamera( const ref_viewpass_t *rvp, matrix4x4 mvp )
{
matrix4x4 tmp;
/* FIXME VK unused?
RI.params = RP_NONE;
RI.drawWorld = FBitSet( rvp->flags, RF_DRAW_WORLD );
RI.onlyClientDraw = FBitSet( rvp->flags, RF_ONLY_CLIENTDRAW );
RI.farClip = 0;
// Vulkan has Y pointing down, and z should end up in (0, 1)
const matrix4x4 vk_proj_fixup = {
{1, 0, 0, 0},
{0, -1, 0, 0},
{0, 0, .5, 0},
{0, 0, .5, 1}
};
R_SetupProjectionMatrix( rvp, tmp );
Matrix4x4_Concat( projection, vk_proj_fixup, tmp );
if( !FBitSet( rvp->flags, RF_DRAW_CUBEMAP ))
RI.drawOrtho = FBitSet( rvp->flags, RF_DRAW_OVERVIEW );
else RI.drawOrtho = false;
*/
R_SetupModelviewMatrix( rvp, worldview );
Matrix4x4_Concat( mvp, projection, worldview);
// setup viewport
g_camera.viewport[0] = rvp->viewport[0];
g_camera.viewport[1] = rvp->viewport[1];
g_camera.viewport[2] = rvp->viewport[2];
g_camera.viewport[3] = rvp->viewport[3];
// calc FOV
g_camera.fov_x = rvp->fov_x;
g_camera.fov_y = rvp->fov_y;
VectorCopy( rvp->vieworigin, g_camera.vieworg );
VectorCopy( rvp->viewangles, g_camera.viewangles );
// FIXME VK unused? VectorCopy( rvp->vieworigin, g_camera.pvsorigin );
if( RP_NORMALPASS() && ( gEngine.EngineGetParm( PARM_WATER_LEVEL, 0 ) >= 3 ))
{
g_camera.fov_x = atan( tan( DEG2RAD( g_camera.fov_x ) / 2 ) * ( 0.97f + sin( gpGlobals->time * 1.5f ) * 0.03f )) * 2 / (M_PI_F / 180.0f);
g_camera.fov_y = atan( tan( DEG2RAD( g_camera.fov_y ) / 2 ) * ( 1.03f - sin( gpGlobals->time * 1.5f ) * 0.03f )) * 2 / (M_PI_F / 180.0f);
}
// build the transformation matrix for the given view angles
AngleVectors( g_camera.viewangles, g_camera.vforward, g_camera.vright, g_camera.vup );
/* FIXME VK unused?
if( !r_lockfrustum->value )
{
VectorCopy( RI.vieworg, RI.cullorigin );
VectorCopy( RI.vforward, RI.cull_vforward );
VectorCopy( RI.vright, RI.cull_vright );
VectorCopy( RI.vup, RI.cull_vup );
}
*/
/* FIXME VK unused?
if( RI.drawOrtho )
GL_FrustumInitOrtho( &RI.frustum, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar );
else GL_FrustumInitProj( &g_camera.frustum, 0.0f, R_GetFarClip(), g_camera.fov_x, g_camera.fov_y ); // NOTE: we ignore nearplane here (mirrors only)
*/
R_SetupProjectionMatrix( g_camera.projectionMatrix );
R_SetupModelviewMatrix( g_camera.modelviewMatrix );
Matrix4x4_Concat( g_camera.worldviewProjectionMatrix, g_camera.projectionMatrix, g_camera.modelviewMatrix );
{
// Vulkan has Y pointing down, and z should end up in (0, 1)
const matrix4x4 vk_proj_fixup = {
{1, 0, 0, 0},
{0, -1, 0, 0},
{0, 0, .5, 0},
{0, 0, .5, 1}
};
Matrix4x4_Concat( mvp, vk_proj_fixup, g_camera.worldviewProjectionMatrix);
}
}
static void drawEntity( cl_entity_t *ent, int render_mode, const matrix4x4 mvp )
@ -604,19 +616,18 @@ static void drawEntity( cl_entity_t *ent, int render_mode, const matrix4x4 mvp )
}
static float g_frametime = 0;
void VK_SceneRender( void )
void VK_SceneRender( const ref_viewpass_t *rvp )
{
matrix4x4 worldview, projection, mvp;
matrix4x4 mvp;
int current_pipeline_index = kRenderNormal;
g_frametime = /*FIXME VK RP_NORMALPASS( )) ? */
gpGlobals->time - gpGlobals->oldtime
/* FIXME VK : 0.f */;
// FIXME this is a bad place for this call -- theoretically we can get multiple calls to VK_SceneRender so we should not erase previous tmp buffer contents
VK_RenderTempBufferBegin();
VK_RenderBegin();
prepareMatrix( &fixme_rvp, worldview, projection, mvp );
setupCamera( rvp, mvp );
VK_RenderDebugLabelBegin( "opaque" );
@ -655,7 +666,6 @@ void VK_SceneRender( void )
{
// sort translucents entities by rendermode and distance
VectorCopy( fixme_rvp.vieworigin, R_TransEntityCompare_vieworg );
qsort( g_lists.draw_list->trans_entities, g_lists.draw_list->num_trans_entities, sizeof( vk_trans_entity_t ), R_TransEntityCompare );
// Draw transparent ents
@ -672,8 +682,6 @@ void VK_SceneRender( void )
VK_RenderDebugLabelEnd();
VK_RenderEnd();
VK_RenderTempBufferEnd();
}

View File

@ -15,8 +15,8 @@ typedef struct vk_trans_entity_s {
} vk_trans_entity_t;
void VK_SceneInit( void );
void FIXME_VK_SceneSetViewPass( const struct ref_viewpass_s *rvp );
void VK_SceneRender( 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 );