renderer,gl33: expose new magic uniforms; see render_context.glslh

Also optimize access to all magic uniforms slightly.
This commit is contained in:
Andrei Alexeyev 2021-02-04 01:50:10 +02:00
parent bc6f41244d
commit a5d0deec0f
No known key found for this signature in database
GPG key ID: 363707CD4C7FE8A4
5 changed files with 144 additions and 20 deletions

View file

@ -9,4 +9,19 @@ UNIFORM(513) mat4 r_projectionMatrix;
UNIFORM(514) mat4 r_textureMatrix;
UNIFORM(515) vec4 r_color;
// Active viewport, i.e. the region we're rendering into.
// xy = offset, zw = width and height.
// Units are real pixels.
UNIFORM(516) vec4 r_viewport;
// Size(s) of output buffer(s) we're rendering into, in real pixels.
// A size of 0,0 means the buffer is not attached.
//
// Note that r_colorOutputSizes is not a direct mapping to framebuffer attachments;
// it is affected by the output -> attachment mapping (see r_framebuffer_set_output_attachments).
// This means that r_colorOutputSizes[N] always corresponds to fragment shader output #N, which
// is probably what you'd expect.
UNIFORM(517) vec2 r_colorOutputSizes[4]; // NOTE: should match FRAMEBUFFER_MAX_OUTPUTS in renderer/api.h
UNIFORM(521) vec2 r_depthOutputSize;
#endif

View file

@ -547,7 +547,7 @@ void _r_uniform_ptr_float_array(Uniform *uniform, uint offset, uint count, float
void _r_uniform_float_array(const char *uniform, uint offset, uint count, float elements[count]) attr_nonnull(1, 4);
#define r_uniform_float_array(uniform, ...) _R_UNIFORM_GENERIC(float_array, uniform, __VA_ARGS__)
void _r_uniform_ptr_vec2(Uniform *uniform, float x, float y) attr_nonnull(1);
void _r_uniform_ptr_vec2(Uniform *uniform, float x, float y);
void _r_uniform_vec2(const char *uniform, float x, float y) attr_nonnull(1);
#define r_uniform_vec2(uniform, ...) _R_UNIFORM_GENERIC(vec2, uniform, __VA_ARGS__)

View file

@ -383,17 +383,93 @@ static void gl33_sync_viewport(void) {
}
}
static IntExtent gl33_get_default_framebuffer_size(void) {
IntExtent s;
// TODO: cache this at window creation time and refresh on resize events?
SDL_GL_GetDrawableSize(R.window, &s.w, &s.h);
return s;
}
static void gl33_get_output_size(Framebuffer *fb, FramebufferAttachment a, vec2_noalign out) {
if(a == FRAMEBUFFER_ATTACH_NONE) {
out[0] = 0;
out[1] = 0;
return;
}
FramebufferAttachmentQueryResult q = gl33_framebuffer_query_attachment(fb, a);
if(q.texture == NULL) {
out[0] = 0;
out[1] = 0;
return;
}
uint w, h;
gl33_texture_get_size(q.texture, q.miplevel, &w, &h);
out[0] = w;
out[1] = h;
}
static void gl33_sync_magic_uniforms(void) {
ShaderProgram *shader = NOT_NULL(R.progs.active);
Framebuffer *fb = R.framebuffer.active;
Uniform **u = shader->magic_uniforms;
r_uniform_mat4(u[UMAGIC_MATRIX_MV], *_r_matrices.modelview.head);
r_uniform_mat4(u[UMAGIC_MATRIX_PROJ], *_r_matrices.projection.head);
r_uniform_mat4(u[UMAGIC_MATRIX_TEX], *_r_matrices.texture.head);
r_uniform_vec4_rgba(u[UMAGIC_COLOR], &R.color);
r_uniform_vec4_vec(u[UMAGIC_VIEWPORT], &R.viewport.active.x);
int num_color_out;
if(u[UMAGIC_COLOR_OUT_SIZES]) {
num_color_out = iclamp(u[UMAGIC_COLOR_OUT_SIZES]->array_size, 0, FRAMEBUFFER_MAX_OUTPUTS);
} else {
num_color_out = 0;
}
if(fb) {
if(num_color_out > 0) {
vec2_noalign out[num_color_out];
for(int i = 0; i < num_color_out; ++i) {
gl33_get_output_size(fb, fb->output_mapping[i], out[i]);
}
r_uniform_vec2_array(u[UMAGIC_COLOR_OUT_SIZES], 0, num_color_out, out);
}
if(u[UMAGIC_DEPTH_OUT_SIZE]) {
vec2_noalign out;
gl33_get_output_size(fb, FRAMEBUFFER_ATTACH_DEPTH, out);
r_uniform_vec2_vec(u[UMAGIC_DEPTH_OUT_SIZE], out);
}
} else { // default framebuffer
// TODO: Maybe figure out whether we have the depth buffer?
// We don't request one for the default framebuffer, so pretend it's not there.
r_uniform_vec2(u[UMAGIC_DEPTH_OUT_SIZE], 0, 0);
if(num_color_out > 0) {
IntExtent fb_size = gl33_get_default_framebuffer_size();
vec2 out[num_color_out];
out[0][0] = fb_size.w;
out[0][1] = fb_size.h;
memset(out + 1, 0, sizeof(out) - sizeof(out[0]));
r_uniform_vec2_array(u[UMAGIC_COLOR_OUT_SIZES], 0, num_color_out, out);
}
}
}
static void gl33_sync_state(void) {
gl33_sync_capabilities();
gl33_sync_framebuffer();
gl33_sync_shader();
r_uniform_mat4("r_modelViewMatrix", *_r_matrices.modelview.head);
r_uniform_mat4("r_projectionMatrix", *_r_matrices.projection.head);
r_uniform_mat4("r_textureMatrix", *_r_matrices.texture.head);
r_uniform_vec4_rgba("r_color", &R.color);
gl33_sync_viewport();
gl33_sync_magic_uniforms();
gl33_sync_uniforms(R.progs.active);
gl33_sync_texunits(true);
gl33_sync_framebuffer();
gl33_sync_viewport();
gl33_sync_vao();
gl33_sync_blend_mode();
@ -1057,8 +1133,7 @@ static IntExtent gl33_framebuffer_get_size(Framebuffer *fb) {
IntExtent fb_size;
if(fb == NULL) {
// TODO: cache this at window creation time and refresh on resize events?
SDL_GL_GetDrawableSize(R.window, &fb_size.w, &fb_size.h);
fb_size = gl33_get_default_framebuffer_size();
} else {
fb_size = gl33_framebuffer_get_effective_size(fb);
}

View file

@ -151,18 +151,22 @@ static struct {
[UNIFORM_MAT4] = { uset_mat4, uget_mat4 },
};
typedef struct MagicalUniform {
typedef struct MagicUniformSpec {
const char *name;
const char *typename;
UniformType type;
} MagicalUniform;
} MagicUniformSpec;
static MagicalUniform magical_unfiroms[] = {
{ "r_modelViewMatrix", "mat4", UNIFORM_MAT4 },
{ "r_projectionMatrix", "mat4", UNIFORM_MAT4 },
{ "r_textureMatrix", "mat4", UNIFORM_MAT4 },
{ "r_color", "vec4", UNIFORM_VEC4 },
static MagicUniformSpec magic_unfiroms[] = {
[UMAGIC_MATRIX_MV] = { "r_modelViewMatrix", "mat4", UNIFORM_MAT4 },
[UMAGIC_MATRIX_PROJ] = { "r_projectionMatrix", "mat4", UNIFORM_MAT4 },
[UMAGIC_MATRIX_TEX] = { "r_textureMatrix", "mat4", UNIFORM_MAT4 },
[UMAGIC_COLOR] = { "r_color", "vec4", UNIFORM_VEC4 },
[UMAGIC_VIEWPORT] = { "r_viewport", "vec4", UNIFORM_VEC4 },
[UMAGIC_COLOR_OUT_SIZES] = { "r_colorOutputSizes[0]", "vec2", UNIFORM_VEC2 },
[UMAGIC_DEPTH_OUT_SIZE] = { "r_depthOutputSize", "vec2", UNIFORM_VEC2 },
};
static_assert_nomsg(ARRAY_SIZE(magic_unfiroms) == NUM_MAGIC_UNIFORMS);
static void gl33_update_uniform(Uniform *uniform, uint offset, uint count, const void *data) {
// these are validated properly in gl33_uniform
@ -325,13 +329,22 @@ static bool cache_uniforms(ShaderProgram *prog) {
continue;
}
for(int j = 0; j < sizeof(magical_unfiroms)/sizeof(MagicalUniform); ++j) {
MagicalUniform *m = magical_unfiroms + j;
MagicUniformIndex magic_index = UMAGIC_INVALID;
if(!strcmp(name, m->name) && uni.type != m->type) {
log_error("Magical uniform '%s' must be of type '%s'", name, m->typename);
for(int j = 0; j < ARRAY_SIZE(magic_unfiroms); ++j) {
MagicUniformSpec *m = magic_unfiroms + j;
if(strcmp(name, m->name)) {
continue;
}
if(uni.type != m->type) {
log_error("Magic uniform '%s' must be of type '%s'", name, m->typename);
return false;
}
magic_index = j;
break;
}
const UniformTypeInfo *typeinfo = r_uniform_type_info(uni.type);
@ -385,6 +398,12 @@ static bool cache_uniforms(ShaderProgram *prog) {
}
}
if(magic_index != UMAGIC_INVALID) {
assume((uint)magic_index < ARRAY_SIZE(prog->magic_uniforms));
assert(prog->magic_uniforms[magic_index] == NULL);
prog->magic_uniforms[magic_index] = new_uni;
}
ht_set(&prog->uniforms, name, new_uni);
log_debug("%s = %i [array elements: %i; size: %zi bytes]", name, loc, uni.array_size, uni.array_size * uni.elem_size);
}

View file

@ -17,9 +17,24 @@
#include "opengl.h"
#include "resource/shader_program.h"
typedef enum MagicUniformIndex {
UMAGIC_INVALID = -1,
UMAGIC_MATRIX_MV,
UMAGIC_MATRIX_PROJ,
UMAGIC_MATRIX_TEX,
UMAGIC_COLOR,
UMAGIC_VIEWPORT,
UMAGIC_COLOR_OUT_SIZES,
UMAGIC_DEPTH_OUT_SIZE,
NUM_MAGIC_UNIFORMS,
} MagicUniformIndex;
struct ShaderProgram {
GLuint gl_handle;
ht_str2ptr_t uniforms;
Uniform *magic_uniforms[NUM_MAGIC_UNIFORMS];
char debug_label[R_DEBUG_LABEL_SIZE];
};