From 7427272062d9faf7655c945a94649aeaa8668cd7 Mon Sep 17 00:00:00 2001 From: jpark37 Date: Tue, 15 Dec 2020 01:24:30 -0800 Subject: [PATCH] libobs-opengl: SRGB-safe GLSL path for raw loads texelFetch ignores SKIP_DECODE_EXT. Replace implementation with textureSize and textureLod. --- libobs-opengl/gl-shaderparser.c | 39 ++++++++++++++++++++++++--------- libobs-opengl/gl-subsystem.c | 14 ++++++++++-- libobs-opengl/gl-subsystem.h | 1 + 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/libobs-opengl/gl-shaderparser.c b/libobs-opengl/gl-shaderparser.c index afb2dff05..bb653d0a8 100644 --- a/libobs-opengl/gl-shaderparser.c +++ b/libobs-opengl/gl-shaderparser.c @@ -416,20 +416,19 @@ static bool gl_write_texture_code(struct gl_shader_parser *glsp, const char *function_end = ")"; - if (cf_token_is(cfp, "Sample")) + if (cf_token_is(cfp, "Sample")) { written = gl_write_texture_call(glsp, var, "texture", true); - else if (cf_token_is(cfp, "SampleBias")) + } else if (cf_token_is(cfp, "SampleBias")) { written = gl_write_texture_call(glsp, var, "texture", true); - else if (cf_token_is(cfp, "SampleGrad")) + } else if (cf_token_is(cfp, "SampleGrad")) { written = gl_write_texture_call(glsp, var, "textureGrad", true); - else if (cf_token_is(cfp, "SampleLevel")) + } else if (cf_token_is(cfp, "SampleLevel")) { written = gl_write_texture_call(glsp, var, "textureLod", true); - else if (cf_token_is(cfp, "Load")) { - written = gl_write_texture_call(glsp, var, "texelFetch", false); - dstr_cat(&glsp->gl_string, "("); - function_end = (strcmp(var->type, "texture3d") == 0) - ? ").xyz, 0)" - : ").xy, 0)"; + } else if (cf_token_is(cfp, "Load")) { + const char *const func = (strcmp(var->type, "texture3d") == 0) + ? "obs_load_3d" + : "obs_load_2d"; + written = gl_write_texture_call(glsp, var, func, false); } if (!written) @@ -744,6 +743,26 @@ static bool gl_shader_buildstring(struct gl_shader_parser *glsp) dstr_copy(&glsp->gl_string, "#version 330\n\n"); dstr_cat(&glsp->gl_string, "const bool obs_glsl_compile = true;\n\n"); + dstr_cat(&glsp->gl_string, + "vec4 obs_load_2d(sampler2D s, ivec3 p_lod)\n"); + dstr_cat(&glsp->gl_string, "{\n"); + dstr_cat(&glsp->gl_string, "\tint lod = p_lod.z;\n"); + dstr_cat(&glsp->gl_string, "\tvec2 size = textureSize(s, lod);\n"); + dstr_cat(&glsp->gl_string, + "\tvec2 p = (vec2(p_lod.xy) + 0.5) / size;\n"); + dstr_cat(&glsp->gl_string, "\tvec4 color = textureLod(s, p, lod);\n"); + dstr_cat(&glsp->gl_string, "\treturn color;\n"); + dstr_cat(&glsp->gl_string, "}\n\n"); + dstr_cat(&glsp->gl_string, + "vec4 obs_load_3d(sampler3D s, ivec4 p_lod)\n"); + dstr_cat(&glsp->gl_string, "{\n"); + dstr_cat(&glsp->gl_string, "\tint lod = p_lod.w;\n"); + dstr_cat(&glsp->gl_string, "\tvec3 size = textureSize(s, lod);\n"); + dstr_cat(&glsp->gl_string, + "\tvec3 p = (vec3(p_lod.xyz) + 0.5) / size;\n"); + dstr_cat(&glsp->gl_string, "\tvec4 color = textureLod(s, p, lod);\n"); + dstr_cat(&glsp->gl_string, "\treturn color;\n"); + dstr_cat(&glsp->gl_string, "}\n\n"); gl_write_params(glsp); gl_write_inputs(glsp, main_func); gl_write_outputs(glsp, main_func); diff --git a/libobs-opengl/gl-subsystem.c b/libobs-opengl/gl-subsystem.c index deede9568..073ac40c8 100644 --- a/libobs-opengl/gl-subsystem.c +++ b/libobs-opengl/gl-subsystem.c @@ -245,6 +245,16 @@ int device_create(gs_device_t **p_device, uint32_t adapter) gl_enable(GL_CULL_FACE); gl_gen_vertex_arrays(1, &device->empty_vao); + struct gs_sampler_info raw_load_info; + raw_load_info.filter = GS_FILTER_POINT; + raw_load_info.address_u = GS_ADDRESS_BORDER; + raw_load_info.address_v = GS_ADDRESS_BORDER; + raw_load_info.address_w = GS_ADDRESS_BORDER; + raw_load_info.max_anisotropy = 1; + raw_load_info.border_color = 0; + device->raw_load_sampler = + device_samplerstate_create(device, &raw_load_info); + gl_clear_context(device); device->cur_swap = NULL; @@ -273,6 +283,7 @@ void device_destroy(gs_device_t *device) while (device->first_program) gs_program_destroy(device->first_program); + samplerstate_release(device->raw_load_sampler); gl_delete_vertex_arrays(1, &device->empty_vao); da_free(device->proj_stack); @@ -512,11 +523,10 @@ void device_load_texture(gs_device_t *device, gs_texture_t *tex, int unit) if (!tex) return; - // texelFetch doesn't need a sampler if (param->sampler_id != (size_t)-1) sampler = device->cur_samplers[param->sampler_id]; else - sampler = NULL; + sampler = device->raw_load_sampler; if (!gl_bind_texture(tex->gl_target, tex->texture)) goto fail; diff --git a/libobs-opengl/gl-subsystem.h b/libobs-opengl/gl-subsystem.h index f471f21ed..fd623c5dd 100644 --- a/libobs-opengl/gl-subsystem.h +++ b/libobs-opengl/gl-subsystem.h @@ -596,6 +596,7 @@ struct gs_device { enum copy_type copy_type; GLuint empty_vao; + gs_samplerstate_t *raw_load_sampler; gs_texture_t *cur_render_target; gs_zstencil_t *cur_zstencil_buffer;