commit 11a7af72bf36a3fde504a61f7f3fe4810e590581
parent 63f14949f9a472c0c412d2187a91151dd2c674ba
Author: Michael Savage <mikejsavage@gmail.com>
Date: Sat, 3 Aug 2019 21:35:54 +0300
Out of order drawcall submission/named render passes
Diffstat:
13 files changed, 149 insertions(+), 134 deletions(-)
diff --git a/array.h b/array.h
@@ -298,9 +298,10 @@ public:
free( elems );
}
- void add( const T & x ) {
+ size_t add( const T & x ) {
size_t idx = extend( 1 );
elems[ idx ] = x;
+ return idx;
}
void clear() {
diff --git a/bsp.cc b/bsp.cc
@@ -447,6 +447,22 @@ GAME_FRAME( game_frame ) {
renderer_begin_frame();
+ u8 write_gbuffer_pass = renderer_add_pass( "World outlines gbuffer", world_depth_and_normals, RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
+
+ u8 write_teammate_depth_pass;
+ {
+ RenderPass pass;
+ pass.name = "Write teammate depth";
+ pass.target = model_depth;
+ pass.clear_depth = true;
+ pass.depth = 0.0f;
+ write_teammate_depth_pass = renderer_add_pass( pass );
+ }
+
+ u8 teammate_edge_detection_pass = renderer_add_pass( "Teammate edge detection", model_depth_outline );
+ u8 compose_pass = renderer_add_pass( "Compose", RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
+ u8 ui_pass = renderer_add_pass( "UI" );
+
m4 P = m4_perspective( 90, get_aspect_ratio(), NEAR_PLANE_DEPTH, FAR_PLANE_DEPTH );
m4 V = m4_view( forward, right, up, game->pos );
@@ -456,9 +472,8 @@ GAME_FRAME( game_frame ) {
// depth/normals pre pass
{
- renderer_begin_pass( world_depth_and_normals, RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
-
RenderState render_state;
+ render_state.pass = write_gbuffer_pass;
render_state.shader = get_shader( SHADER_FLAT_VERTEX_COLOURS_TO_GBUFFER );
render_state.set_uniform( "view", view_uniforms );
render_state.set_uniform( "model", world_model_uniforms );
@@ -489,48 +504,35 @@ GAME_FRAME( game_frame ) {
//
render_state.set_uniform( "model", tree_model_uniforms );
renderer_draw_mesh( tree_mesh, render_state );
-
- renderer_end_pass();
}
// model depth
{
- RenderPassConfig pass;
- pass.target = model_depth;
- pass.clear_depth = true;
- pass.depth = 0.0f;
- renderer_begin_pass( pass );
-
RenderState render_state;
+ render_state.pass = write_teammate_depth_pass;
render_state.shader = get_shader( SHADER_FLAT_VERTEX_COLOURS_TO_GBUFFER );
render_state.depth_func = DEPTHFUNC_ALWAYS;
render_state.set_uniform( "view", view_uniforms );
render_state.set_uniform( "model", tree_model_uniforms );
renderer_draw_mesh( tree_mesh, render_state );
-
- renderer_end_pass();
}
// model depth edge detection
{
- renderer_begin_pass( model_depth_outline, RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DONT );
-
RenderState render_state;
+ render_state.pass = teammate_edge_detection_pass;
render_state.shader = get_shader( SHADER_DEPTH_EDGE );
render_state.depth_func = DEPTHFUNC_ALWAYS;
render_state.set_texture( "model_depth", model_depth.textures[ OUTPUT_DEPTH ] );
renderer_draw_fullscreen_triangle( render_state );
-
- renderer_end_pass();
}
// compose
{
- renderer_begin_pass( RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
-
RenderState render_state;
+ render_state.pass = compose_pass;
render_state.shader = get_shader( SHADER_GBUFFER );
render_state.set_uniform( "view", view_uniforms );
render_state.set_uniform( "model", world_model_uniforms );
@@ -566,13 +568,8 @@ GAME_FRAME( game_frame ) {
render_state.set_uniform( "model", tree_model_uniforms );
renderer_draw_mesh( tree_mesh, render_state );
-
- renderer_end_pass();
}
- // UI pass
- renderer_begin_pass( RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DONT );
-
// draw crosshair
{
const float aspect = get_aspect_ratio();
@@ -605,6 +602,7 @@ GAME_FRAME( game_frame ) {
red
);
RenderState render_state;
+ render_state.pass = ui_pass;
render_state.shader = get_shader( SHADER_UI );
render_state.depth_func = DEPTHFUNC_ALWAYS;
immediate_render( render_state );
@@ -641,6 +639,7 @@ GAME_FRAME( game_frame ) {
red
);
RenderState render_state;
+ render_state.pass = ui_pass;
render_state.shader = get_shader( SHADER_UI );
render_state.depth_func = DEPTHFUNC_ALWAYS;
immediate_render( render_state );
@@ -649,7 +648,7 @@ GAME_FRAME( game_frame ) {
v2 p = ( a + 1.0f ) / 2.0f;
p.y = 1.0f - p.y;
p *= v2( window_size.x, window_size.y );
- draw_centered_text( "DEFEND", p.x, p.y - 16 - pxsize / 2, 12 );
+ draw_centered_text( ui_pass, "DEFEND", p.x, p.y - 16 - pxsize / 2, 12 );
}
}
@@ -660,10 +659,9 @@ GAME_FRAME( game_frame ) {
right.x, right.y, right.z,
up.x, up.y, up.z
);
- draw_text( buf, 2, 2, 16 );
- draw_text( str< 128 >( "drawcalls = {}, tris = {}", renderer_num_draw_calls(), renderer_num_vertices() / 3 ).c_str(), 2, 20, 16 );
+ draw_text( ui_pass, buf, 2, 2, 16 );
+ draw_text( ui_pass, str< 128 >( "drawcalls = {}, tris = {}", renderer_num_draw_calls(), renderer_num_vertices() / 3 ).c_str(), 2, 20, 16 );
}
- renderer_end_pass();
renderer_end_frame();
}
diff --git a/clipmap.cc b/clipmap.cc
@@ -755,7 +755,11 @@ GAME_FRAME( game_frame ) {
v3 sun_dir = v3( -cosf( game->sun_angle ), 0, sinf( game->sun_angle ) );
renderer_begin_frame();
- renderer_begin_pass( RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
+
+ u8 world_pass = renderer_add_pass( "Render world", RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
+ u8 ents_pass = renderer_add_pass( "Render entities" );
+ u8 sky_pass = renderer_add_pass( "Render sky" );
+ u8 ui_pass = renderer_add_pass( "Render UI" );
UniformBinding view_uniforms = renderer_uniforms( V, P, game->pos );
UniformBinding inf_view_uniforms = renderer_uniforms( V, Pinf, game->pos );
@@ -774,6 +778,7 @@ GAME_FRAME( game_frame ) {
// draw terrain
{
RenderState render_state;
+ render_state.pass = world_pass;
render_state.shader = get_shader( SHADER_CLIPMAP );
render_state.set_uniform( "view", view_uniforms );
render_state.set_uniform( "sun", sun_uniforms );
@@ -866,6 +871,7 @@ GAME_FRAME( game_frame ) {
float scale = checked_cast< float >( u32( 1 ) << ( NUM_CLIPMAP_LEVELS - 1 ) );
RenderState skirt_render_state;
+ skirt_render_state.pass = world_pass;
skirt_render_state.shader = get_shader( SHADER_CLIPMAP_SKIRT );
skirt_render_state.set_uniform( "view", inf_view_uniforms );
skirt_render_state.set_uniform( "sun", sun_uniforms );
@@ -878,6 +884,7 @@ GAME_FRAME( game_frame ) {
// draw trees
{
RenderState render_state;
+ render_state.pass = ents_pass;
render_state.shader = get_shader( SHADER_TREE );
render_state.set_uniform( "view", view_uniforms );
render_state.set_uniform( "sun", renderer_uniforms( sun_dir ) );
@@ -918,6 +925,7 @@ GAME_FRAME( game_frame ) {
red
);
RenderState render_state;
+ render_state.pass = ui_pass;
render_state.shader = get_shader( SHADER_UI );
render_state.depth_func = DEPTHFUNC_ALWAYS;
immediate_render( render_state );
@@ -960,6 +968,7 @@ GAME_FRAME( game_frame ) {
}
RenderState fireball_render_state;
+ fireball_render_state.pass = ents_pass;
fireball_render_state.shader = get_shader( SHADER_FLAT_VERTEX_COLOURS );
fireball_render_state.set_uniform( "view", view_uniforms );
immediate_render( fireball_render_state );
@@ -977,12 +986,13 @@ GAME_FRAME( game_frame ) {
}
RenderState explosion_render_state;
+ explosion_render_state.pass = ents_pass;
explosion_render_state.shader = get_shader( SHADER_FLAT_VERTEX_COLOURS );
explosion_render_state.set_uniform( "view", view_uniforms );
immediate_render( explosion_render_state );
}
- skybox_render( &game->skybox, Vsky, Pinf, game->sun_angle, sun_dir );
+ skybox_render( &game->skybox, sky_pass, Vsky, Pinf, game->sun_angle, sun_dir );
// networking
{
@@ -1081,6 +1091,7 @@ GAME_FRAME( game_frame ) {
}
RenderState impact_render_state;
+ impact_render_state.pass = world_pass;
impact_render_state.shader = get_shader( SHADER_FLAT_VERTEX_COLOURS );
impact_render_state.set_uniform( "view", view_uniforms );
immediate_render( impact_render_state );
@@ -1092,6 +1103,7 @@ GAME_FRAME( game_frame ) {
draw_qt( MinMaxu32( mins, maxs ), clipmap.quadtree.nodes, 0 );
RenderState render_state;
+ render_state.pass = world_pass;
render_state.shader = get_shader( SHADER_WIREFRAME );
render_state.set_uniform( "view", view_uniforms );
render_state.wireframe = true;
@@ -1102,11 +1114,10 @@ GAME_FRAME( game_frame ) {
{
const str< 128 > status( "Frame time: {.1}ms FPS: {.1} {}", dt * 1000.0f, 1.0f / dt,
connected ? "connected!" : "connecting" );
- draw_text( status.c_str(), 2, 2, 16.0f );
- draw_text( str< 128 >( "pos = {.1} vel = {.1}", game->pos, game->velocity ).c_str(), 2, 20, 16 );
- draw_text( str< 128 >( "drawcalls = {}, tris = {}", renderer_num_draw_calls(), renderer_num_vertices() / 3 ).c_str(), 2, 38, 16 );
+ draw_text( ui_pass, status.c_str(), 2, 2, 16.0f );
+ draw_text( ui_pass, str< 128 >( "pos = {.1} vel = {.1}", game->pos, game->velocity ).c_str(), 2, 20, 16 );
+ draw_text( ui_pass, str< 128 >( "drawcalls = {}, tris = {}", renderer_num_draw_calls(), renderer_num_vertices() / 3 ).c_str(), 2, 38, 16 );
}
- renderer_end_pass();
renderer_end_frame();
}
diff --git a/fullscreen.cc b/fullscreen.cc
@@ -147,6 +147,11 @@ GAME_FRAME( game_frame ) {
renderer_begin_frame();
+ u8 shadowmap_pass = renderer_add_pass( "Write shadowmap", shadow_fb, RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DO );
+ u8 gbuffer_pass = renderer_add_pass( "Write gbuffer", gbuffer, RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
+ u8 compose_pass = renderer_add_pass( "Compose" );
+ u8 ui_pass = renderer_add_pass( "Render UI" );
+
UniformBinding light_view_uniforms;
{
@@ -161,22 +166,18 @@ GAME_FRAME( game_frame ) {
// fill shadow map
{
- renderer_begin_pass( shadow_fb, RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DO );
-
RenderState render_state;
+ render_state.pass = shadowmap_pass;
render_state.shader = get_shader( SHADER_WRITE_SHADOW_MAP );
render_state.set_uniform( "light_view", light_view_uniforms );
draw_scene( render_state );
-
- renderer_end_pass();
}
// fill gbuffers
{
- renderer_begin_pass( gbuffer, RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
-
RenderState render_state;
+ render_state.pass = gbuffer_pass;
render_state.shader = get_shader( SHADER_SHADOWED_VERTEX_COLOURS_TO_GBUFFER );
render_state.set_uniform( "view", renderer_uniforms( V, P, game->pos ) );
render_state.set_uniform( "light_view", light_view_uniforms );
@@ -184,15 +185,12 @@ GAME_FRAME( game_frame ) {
render_state.set_texture( "dither_noise", renderer_blue_noise() );
draw_scene( render_state, true );
-
- renderer_end_pass();
}
// final pass
{
- renderer_begin_pass( RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DONT );
-
RenderState render_state;
+ render_state.pass = compose_pass;
render_state.shader = get_shader( SHADER_GBUFFER );
render_state.depth_func = DEPTHFUNC_DISABLED;
render_state.set_texture( "outline_depth", gbuffer.textures[ OUTPUT_ALBEDO ] );
@@ -201,15 +199,11 @@ GAME_FRAME( game_frame ) {
render_state.set_texture( "blue_noise", renderer_blue_noise() );
renderer_draw_fullscreen_triangle( render_state );
-
- renderer_end_pass();
}
{
- renderer_begin_pass( RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DONT );
const str< 128 > status( "Frame time: {.1}ms FPS: {.1}", dt * 1000.0f, 1.0f / dt );
- draw_text( status.c_str(), 2, 2, 16 );
- renderer_end_pass();
+ draw_text( ui_pass, status.c_str(), 2, 2, 16 );
}
renderer_end_frame();
diff --git a/gltf.cc b/gltf.cc
@@ -542,7 +542,8 @@ GAME_FRAME( game_frame ) {
ComputeMatrixPalette( model.animation, sample_sqt, joint_matrices, skinning_matrices );
renderer_begin_frame();
- renderer_begin_pass( RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
+
+ u8 main_pass = renderer_add_pass( "Render frame", RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
UniformBinding view_uniforms = renderer_uniforms( V, P, game->pos );
UniformBinding model_uniforms = renderer_uniforms( y_up_to_z_up );
@@ -552,6 +553,7 @@ GAME_FRAME( game_frame ) {
// draw skinned model
{
RenderState render_state;
+ render_state.pass = main_pass;
render_state.shader = get_shader( SHADER_SKINNED_FLAT_VERTEX_COLOURS );
render_state.set_uniform( "view", view_uniforms );
render_state.set_uniform( "model", model_uniforms );
@@ -572,6 +574,7 @@ GAME_FRAME( game_frame ) {
immediate_arrow( pos, up, 1, v4( 0, 1, 0, 1 ) );
RenderState render_state;
+ render_state.pass = main_pass;
render_state.shader = get_shader( SHADER_FLAT_VERTEX_COLOURS );
render_state.set_uniform( "view", renderer_uniforms( V, P ) );
immediate_render( render_state );
@@ -591,11 +594,11 @@ GAME_FRAME( game_frame ) {
}
RenderState render_state;
+ render_state.pass = main_pass;
render_state.shader = get_shader( SHADER_FLAT_VERTEX_COLOURS );
render_state.set_uniform( "view", renderer_uniforms( V, P ) );
immediate_render( render_state );
}
- renderer_end_pass();
renderer_end_frame();
}
diff --git a/msdf.cc b/msdf.cc
@@ -35,7 +35,7 @@ static v2 glyph_bounds( u8 glyph, float scale ) {
return v2();
}
-static void msdf_text( const char * str, int x, int y, float scale ) {
+static void msdf_text( u8 pass, const char * str, int x, int y, float scale ) {
const v4 white( 1, 1, 1, 1 );
float height = font_information.max_y - font_information.min_y;
@@ -90,6 +90,7 @@ static void msdf_text( const char * str, int x, int y, float scale ) {
}
RenderState render_state;
+ render_state.pass = pass;
render_state.shader = get_shader( SHADER_MSDF );
render_state.set_texture( "atlas", atlas );
render_state.depth_func = DEPTHFUNC_DISABLED;
@@ -102,7 +103,8 @@ static void msdf_text( const char * str, int x, int y, float scale ) {
float lol = 0.5;
GAME_FRAME( game_frame ) {
- RenderPassConfig pass;
+ RenderPass pass;
+ pass.name = "Render frame";
pass.clear_colour = true;
pass.colour = v4( 0.1, 0.1, 0.1, 0 );
@@ -112,7 +114,8 @@ GAME_FRAME( game_frame ) {
lol += 0.1 * dt;
renderer_begin_frame();
- renderer_begin_pass( pass );
+
+ u8 main_pass = renderer_add_pass( pass );
{
// for( int i = 0; i < 8; i++ ) {
@@ -133,9 +136,8 @@ GAME_FRAME( game_frame ) {
y += 16 << i;
}
- msdf_text( "Thanks again!", 10, 200, 50 );
+ msdf_text( main_pass, "Thanks again!", 10, 200, 50 );
}
- renderer_end_pass();
renderer_end_frame();
}
diff --git a/renderer.cc b/renderer.cc
@@ -1,4 +1,4 @@
-#include "glad.h"
+#include <algorithm>
#include "intrinsics.h"
#include "game.h"
@@ -10,6 +10,8 @@
#include "obj.h"
#include "fnv.h"
+#include "glad.h"
+
STATIC_ASSERT( SAME_TYPE( VB, GLuint ) );
STATIC_ASSERT( SAME_TYPE( IB, GLuint ) );
STATIC_ASSERT( SAME_TYPE( Texture, GLuint ) );
@@ -52,11 +54,6 @@ struct DeleteCommand {
};
};
-struct RenderPass {
- size_t begin, one_past_end;
- RenderPassConfig config;
-};
-
static DynamicArray< DrawCall > draw_calls;
static DynamicArray< RenderPass > render_passes;
static DynamicArray< DeleteCommand > deletes;
@@ -64,9 +61,7 @@ static DynamicArray< DeleteCommand > deletes;
static u32 draw_calls_this_frame;
static u32 vertices_this_frame;
-static RenderPass current_render_pass;
static bool in_frame;
-static bool in_pass;
struct UBO {
GLuint ubo;
@@ -101,7 +96,6 @@ void renderer_init() {
}
in_frame = false;
- in_pass = false;
previous_fbo = 0;
previous_viewport_width = 0;
@@ -135,8 +129,8 @@ void renderer_begin_frame() {
in_frame = true;
draw_calls.clear();
- deletes.clear();
render_passes.clear();
+ deletes.clear();
draw_calls_this_frame = 0;
vertices_this_frame = 0;
@@ -272,7 +266,18 @@ static void set_render_state( const RenderState & state ) {
previous_render_state = state;
}
-static void bind_fb( FB fb ) {
+static bool compare_drawcall( const DrawCall & a, const DrawCall & b ) {
+ if( a.render_state.pass != b.render_state.pass )
+ return a.render_state.pass < b.render_state.pass;
+ return a.render_state.shader < b.render_state.shader;
+}
+
+static void setup_render_pass( const RenderPass & pass ) {
+ if( GLAD_GL_KHR_debug != 0 ) {
+ glPushDebugGroup( GL_DEBUG_SOURCE_APPLICATION, 0, -1, pass.name );
+ }
+
+ const FB & fb = pass.target;
if( fb.fbo != previous_fbo ) {
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, fb.fbo );
previous_fbo = fb.fbo;
@@ -294,6 +299,17 @@ static void bind_fb( FB fb ) {
glViewport( 0, 0, viewport_width, viewport_height );
}
}
+
+ GLbitfield clear_mask = 0;
+ clear_mask |= pass.clear_colour ? GL_COLOR_BUFFER_BIT : 0;
+ clear_mask |= pass.clear_depth ? GL_DEPTH_BUFFER_BIT : 0;
+ if( clear_mask != 0 ) {
+ if( pass.clear_colour )
+ glClearColor( pass.colour.x, pass.colour.y, pass.colour.z, pass.colour.w );
+ if( pass.clear_depth )
+ glClearDepth( pass.depth );
+ glClear( clear_mask );
+ }
}
static void drawcall_single( const Mesh & mesh, const RenderState & state ) {
@@ -335,7 +351,6 @@ static void drawcall_instanced( const Mesh & mesh, const RenderState & state, u3
}
void renderer_end_frame() {
- ASSERT( !in_pass );
ASSERT( in_frame );
in_frame = false;
@@ -344,33 +359,28 @@ void renderer_end_frame() {
glUnmapBuffer( GL_UNIFORM_BUFFER );
}
- for( const RenderPass & pass : render_passes ) {
- bind_fb( pass.config.target );
+ std::sort( draw_calls.begin(), draw_calls.end(), compare_drawcall );
- GLbitfield clear_mask = 0;
- if( pass.config.clear_colour )
- clear_mask |= GL_COLOR_BUFFER_BIT;
- if( pass.config.clear_depth )
- clear_mask |= GL_DEPTH_BUFFER_BIT;
-
- if( clear_mask != 0 ) {
- glClearColor( pass.config.colour.x, pass.config.colour.y, pass.config.colour.z, pass.config.colour.w );
- glClearDepth( pass.config.depth );
- glClear( clear_mask );
+ u8 pass_idx = U8_MAX;
+ for( const DrawCall & dc : draw_calls ) {
+ if( dc.render_state.pass != pass_idx ) {
+ if( GLAD_GL_KHR_debug != 0 && pass_idx != U8_MAX )
+ glPopDebugGroup();
+ setup_render_pass( render_passes[ dc.render_state.pass ] );
+ pass_idx = dc.render_state.pass;
}
- // TODO: sort draw calls
-
- for( const DrawCall & dc : draw_calls.slice( pass.begin, pass.one_past_end ) ) {
- if( dc.num_instances == 0 ) {
- drawcall_single( dc.mesh, dc.render_state );
- }
- else {
- drawcall_instanced( dc.mesh, dc.render_state, dc.num_instances, dc.instance_data );
- }
+ if( dc.num_instances == 0 ) {
+ drawcall_single( dc.mesh, dc.render_state );
+ }
+ else {
+ drawcall_instanced( dc.mesh, dc.render_state, dc.num_instances, dc.instance_data );
}
}
+ if( GLAD_GL_KHR_debug != 0 && pass_idx != U8_MAX )
+ glPopDebugGroup();
+
for( const DeleteCommand & del : deletes ) {
switch( del.type ) {
case DELETE_VB:
@@ -409,33 +419,22 @@ void renderer_end_frame() {
}
}
-void renderer_begin_pass( const RenderPassConfig & pass ) {
- ASSERT( !in_pass );
- in_pass = true;
-
- current_render_pass.begin = draw_calls.size();
- current_render_pass.config = pass;
+u8 renderer_add_pass( const RenderPass & pass ) {
+ return checked_cast< u8 >( render_passes.add( pass ) );
}
-void renderer_begin_pass( FB target, ClearColourBool clear_colour, ClearDepthBool clear_depth ) {
- RenderPassConfig pass;
+u8 renderer_add_pass( const char * name, FB target, ClearColourBool clear_colour, ClearDepthBool clear_depth ) {
+ RenderPass pass;
pass.target = target;
+ pass.name = name;
pass.clear_colour = clear_colour == RENDERER_CLEAR_COLOUR_DO;
pass.clear_depth = clear_depth == RENDERER_CLEAR_DEPTH_DO;
- renderer_begin_pass( pass );
+ return renderer_add_pass( pass );
}
-void renderer_begin_pass( ClearColourBool clear_colour, ClearDepthBool clear_depth ) {
+u8 renderer_add_pass( const char * name, ClearColourBool clear_colour, ClearDepthBool clear_depth ) {
FB target = { };
- renderer_begin_pass( target, clear_colour, clear_depth );
-}
-
-void renderer_end_pass() {
- ASSERT( in_pass );
- in_pass = false;
-
- current_render_pass.one_past_end = draw_calls.size();
- render_passes.add( current_render_pass );
+ return renderer_add_pass( name, target, clear_colour, clear_depth );
}
u32 renderer_num_draw_calls() {
@@ -1163,7 +1162,9 @@ void renderer_delete_mesh( const Mesh & mesh ) {
}
void renderer_draw_mesh( const Mesh & mesh, const RenderState & render_state ) {
- ASSERT( in_frame && in_pass );
+ ASSERT( in_frame );
+ ASSERT( render_state.pass != U8_MAX );
+ ASSERT( render_state.shader != NULL );
DrawCall dc;
dc.mesh = mesh;
@@ -1177,7 +1178,7 @@ void renderer_draw_mesh( const Mesh & mesh, const RenderState & render_state ) {
}
void renderer_draw_instances( const Mesh & mesh, const RenderState & render_state, u32 num_instances, VB instance_data ) {
- ASSERT( in_frame && in_pass );
+ ASSERT( in_frame );
if( num_instances == 0 ) {
return;
diff --git a/renderer.h b/renderer.h
@@ -129,6 +129,7 @@ struct RenderState {
size_t num_uniforms = 0;
size_t num_textures = 0;
+ u8 pass = U8_MAX;
const Shader * shader = NULL;
DepthFunc depth_func = DEPTHFUNC_LESS;
CullFace cull_face = CULLFACE_BACK;
@@ -264,7 +265,9 @@ struct TextureConfig {
v4 border_colour;
};
-struct RenderPassConfig {
+struct RenderPass {
+ const char * name = NULL;
+
FB target = { };
bool clear_colour = false;
@@ -290,12 +293,12 @@ void renderer_init();
void renderer_term();
void renderer_begin_frame();
-void renderer_begin_pass( const RenderPassConfig & pass );
-void renderer_begin_pass( FB target, ClearColourBool clear_colour, ClearDepthBool clear_depth );
-void renderer_begin_pass( ClearColourBool clear_colour, ClearDepthBool clear_depth );
-void renderer_end_pass();
void renderer_end_frame();
+u8 renderer_add_pass( const RenderPass & config );
+u8 renderer_add_pass( const char * name, ClearColourBool clear_colour = RENDERER_CLEAR_COLOUR_DONT, ClearDepthBool clear_depth = RENDERER_CLEAR_DEPTH_DONT );
+u8 renderer_add_pass( const char * name, FB target, ClearColourBool clear_colour = RENDERER_CLEAR_COLOUR_DONT, ClearDepthBool clear_depth = RENDERER_CLEAR_DEPTH_DONT );
+
u32 renderer_num_draw_calls();
u32 renderer_num_vertices();
diff --git a/shadow_map.cc b/shadow_map.cc
@@ -114,6 +114,10 @@ GAME_FRAME( game_frame ) {
renderer_begin_frame();
+ u8 write_shadowmap_pass = renderer_add_pass( "Write shadowmap", shadow_fb, RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DO );
+ u8 world_pass = renderer_add_pass( "Render world", RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
+ u8 ui_pass = renderer_add_pass( "Render UI" );
+
UniformBinding light_view_uniforms;
{
@@ -128,30 +132,27 @@ GAME_FRAME( game_frame ) {
// fill shadow map
{
- renderer_begin_pass( shadow_fb, RENDERER_CLEAR_COLOUR_DONT, RENDERER_CLEAR_DEPTH_DO );
-
RenderState render_state;
+ render_state.pass = write_shadowmap_pass;
render_state.shader = get_shader( SHADER_WRITE_SHADOW_MAP );
render_state.set_uniform( "light_view", light_view_uniforms );
draw_scene( render_state );
-
- renderer_end_pass();
}
- renderer_begin_pass( RENDERER_CLEAR_COLOUR_DO, RENDERER_CLEAR_DEPTH_DO );
-
// render shadow map
{
- RenderState state;
- state.shader = get_shader( SHADER_DEBUG_RENDER_SHADOW_MAP );
- state.set_texture( "tex", shadow_fb.textures[ OUTPUT_DEPTH ] );
- renderer_draw_mesh( square, state );
+ RenderState render_state;
+ render_state.pass = ui_pass;
+ render_state.shader = get_shader( SHADER_DEBUG_RENDER_SHADOW_MAP );
+ render_state.set_texture( "tex", shadow_fb.textures[ OUTPUT_DEPTH ] );
+ renderer_draw_mesh( square, render_state );
}
// draw world
{
RenderState render_state;
+ render_state.pass = world_pass;
render_state.shader = get_shader( SHADER_SHADOWED_VERTEX_COLOURS );
render_state.set_uniform( "view", renderer_uniforms( V, P, game->pos ) );
render_state.set_uniform( "light_view", light_view_uniforms );
@@ -163,9 +164,8 @@ GAME_FRAME( game_frame ) {
{
const str< 128 > status( "Frame time: {.1}ms FPS: {.1}", dt * 1000.0f, 1.0f / dt );
- draw_text( status.c_str(), 2, 2, 16 );
+ draw_text( ui_pass, status.c_str(), 2, 2, 16 );
}
- renderer_end_pass();
renderer_end_frame();
}
diff --git a/skybox.cc b/skybox.cc
@@ -110,7 +110,7 @@ void skybox_init( Skybox * skybox ) {
par_shapes_free_mesh( sphere );
}
-void skybox_render( const Skybox * skybox, const m4 & Vsky, const m4 & P, float sun_angle, v3 sun_dir ) {
+void skybox_render( const Skybox * skybox, u8 pass, const m4 & Vsky, const m4 & P, float sun_angle, v3 sun_dir ) {
const float turbidity = 4.0f;
const float normalized_sun_y = 1.1f;
@@ -120,6 +120,7 @@ void skybox_render( const Skybox * skybox, const m4 & Vsky, const m4 & P, float
Hosek hosek = compute_hosek( hosek_elevation, turbidity, normalized_sun_y );
RenderState render_state;
+ render_state.pass = pass;
render_state.shader = get_shader( SHADER_SKYBOX );
render_state.set_uniform( "view", renderer_uniforms( Vsky, P ) );
render_state.set_uniform( "sky", renderer_uniforms( hosek.A, hosek.B, hosek.C, hosek.D, hosek.E, hosek.F, hosek.G, hosek.H, hosek.I, hosek.Z, sun_dir ) );
diff --git a/skybox.h b/skybox.h
@@ -8,5 +8,5 @@ struct Skybox {
};
void skybox_init( Skybox * skybox );
-void skybox_render( const Skybox * skybox, const m4 & V, const m4 & P, float sun_angle, v3 sun_dir );
+void skybox_render( const Skybox * skybox, u8 pass, const m4 & V, const m4 & P, float sun_angle, v3 sun_dir );
void skybox_destroy( Skybox * skybox );
diff --git a/text_renderer.cc b/text_renderer.cc
@@ -91,7 +91,7 @@ float text_width( const char * str, float pixel_size ) {
return width * scale;
}
-void draw_text( const char * str, int x, int y, float pixel_size ) {
+void draw_text( u8 pass, const char * str, int x, int y, float pixel_size ) {
const v4 white( 1, 1, 1, 1 );
size_t size_idx = 0;
@@ -146,6 +146,7 @@ void draw_text( const char * str, int x, int y, float pixel_size ) {
}
RenderState render_state;
+ render_state.pass = pass;
render_state.shader = get_shader( SHADER_TEXT );
render_state.set_uniform( "window", renderer_uniforms( get_window_size() ) );
render_state.set_texture( "atlas", atlas );
@@ -156,7 +157,7 @@ void draw_text( const char * str, int x, int y, float pixel_size ) {
immediate_render( render_state );
}
-void draw_centered_text( const char * str, int x, int y, float pixel_size ) {
+void draw_centered_text( u8 pass, const char * str, int x, int y, float pixel_size ) {
float w = text_width( str, pixel_size );
- draw_text( str, x - w / 2.0f, y, pixel_size );
+ draw_text( pass, str, x - w / 2.0f, y, pixel_size );
}
diff --git a/text_renderer.h b/text_renderer.h
@@ -7,5 +7,5 @@ void text_renderer_term();
float text_width( const char * str, float pixel_size );
-void draw_text( const char * str, int x, int y, float pixel_size );
-void draw_centered_text( const char * str, int x, int y, float pixel_size );
+void draw_text( u8 pass, const char * str, int x, int y, float pixel_size );
+void draw_centered_text( u8 pass, const char * str, int x, int y, float pixel_size );