libobs: Full-screen triangle format conversions
The cache coherency of rasterization for full-screen passes is better using an oversized triangle that is clipped rather than two triangles. Traversal order of rasterization is GPU-specific, but will almost certainly be better using an undivided primitive. A smaller benefit is that quads along the diagonal are not evaluated multiple times, but that's minor in comparison. Redo format shaders to bypass vertex buffer, and input layout. Add global shader bool "obs_glsl_compile" to make API-specific decisions, i.e. handle upside-down UVs. gl_ortho is not needed for format conversion because the vertex shader does not use ViewProj anymore. This can be applied to more situations, but start small first. Testbed full screen passes, Intel HD Graphics 530: RGBA -> UYVX: 467 -> 439 us, ~6% savings UYVX -> uv: 295 -> 239 us, ~19% savings
This commit is contained in:
@@ -163,7 +163,7 @@ static void gl_write_storage_var(struct gl_shader_parser *glsp,
|
||||
|
||||
if (st) {
|
||||
gl_unwrap_storage_struct(glsp, st, var->name, input, prefix);
|
||||
} else {
|
||||
} else if (!input || strcmp(var->mapping, "VERTEXID")) {
|
||||
struct gl_parser_attrib attrib;
|
||||
gl_parser_attrib_init(&attrib);
|
||||
|
||||
@@ -536,9 +536,13 @@ static void gl_write_main_storage_assign(struct gl_shader_parser *glsp,
|
||||
if (!dstr_is_empty(&dst_copy))
|
||||
dstr_cat_dstr(&glsp->gl_string, &dst_copy);
|
||||
dstr_cat(&glsp->gl_string, " = ");
|
||||
if (src)
|
||||
dstr_cat(&glsp->gl_string, src);
|
||||
dstr_cat(&glsp->gl_string, var->name);
|
||||
if (input && (strcmp(var->mapping, "VERTEXID") == 0))
|
||||
dstr_cat(&glsp->gl_string, "uint(gl_VertexID)");
|
||||
else {
|
||||
if (src)
|
||||
dstr_cat(&glsp->gl_string, src);
|
||||
dstr_cat(&glsp->gl_string, var->name);
|
||||
}
|
||||
dstr_cat(&glsp->gl_string, ";\n");
|
||||
|
||||
if (!input)
|
||||
@@ -628,6 +632,12 @@ static void gl_rename_attributes(struct gl_shader_parser *glsp)
|
||||
size_t val;
|
||||
|
||||
if (attrib->input) {
|
||||
if (strcmp(attrib->mapping, "VERTEXID") == 0) {
|
||||
dstr_replace(&glsp->gl_string, attrib->name.array,
|
||||
"gl_VertexID");
|
||||
continue;
|
||||
}
|
||||
|
||||
prefix = glsp->input_prefix;
|
||||
val = input_idx++;
|
||||
} else {
|
||||
@@ -653,6 +663,7 @@ static bool gl_shader_buildstring(struct gl_shader_parser *glsp)
|
||||
}
|
||||
|
||||
dstr_copy(&glsp->gl_string, "#version 150\n\n");
|
||||
dstr_cat(&glsp->gl_string, "const bool obs_glsl_compile = true;\n\n");
|
||||
gl_write_params(glsp);
|
||||
gl_write_inputs(glsp, main_func);
|
||||
gl_write_outputs(glsp, main_func);
|
||||
|
@@ -891,7 +891,7 @@ void device_begin_scene(gs_device_t *device)
|
||||
clear_textures(device);
|
||||
}
|
||||
|
||||
static inline bool can_render(const gs_device_t *device)
|
||||
static inline bool can_render(const gs_device_t *device, uint32_t num_verts)
|
||||
{
|
||||
if (!device->cur_vertex_shader) {
|
||||
blog(LOG_ERROR, "No vertex shader specified");
|
||||
@@ -903,7 +903,7 @@ static inline bool can_render(const gs_device_t *device)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!device->cur_vertex_buffer) {
|
||||
if (!device->cur_vertex_buffer && (num_verts == 0)) {
|
||||
blog(LOG_ERROR, "No vertex buffer specified");
|
||||
return false;
|
||||
}
|
||||
@@ -977,7 +977,7 @@ void device_draw(gs_device_t *device, enum gs_draw_mode draw_mode,
|
||||
gs_effect_t *effect = gs_get_effect();
|
||||
struct gs_program *program;
|
||||
|
||||
if (!can_render(device))
|
||||
if (!can_render(device, num_verts))
|
||||
goto fail;
|
||||
|
||||
if (effect)
|
||||
|
@@ -257,7 +257,7 @@ bool load_vb_buffers(struct gs_program *program, struct gs_vertex_buffer *vb,
|
||||
struct gs_shader *shader = program->vertex_shader;
|
||||
size_t i;
|
||||
|
||||
if (!gl_bind_vertex_array(vb->vao))
|
||||
if (vb && !gl_bind_vertex_array(vb->vao))
|
||||
return false;
|
||||
|
||||
for (i = 0; i < shader->attribs.num; i++) {
|
||||
|
Reference in New Issue
Block a user