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:
parent
a5e279f580
commit
3f70b76208
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -611,7 +611,7 @@ ref_interface_t gReffuncs =
|
|||
R_LightVec,
|
||||
R_StudioGetTexture,
|
||||
|
||||
GL_RenderFrame,
|
||||
VK_RenderFrame,
|
||||
GL_OrthoBounds,
|
||||
R_SpeedsMessage,
|
||||
Mod_GetCurrentVis,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue