Jelajahi Sumber

libobs-opengl: SRGB-safe GLSL path for raw loads

texelFetch ignores SKIP_DECODE_EXT. Replace implementation with
textureSize and textureLod.
jpark37 4 tahun lalu
induk
melakukan
7427272062
3 mengubah file dengan 42 tambahan dan 12 penghapusan
  1. 29 10
      libobs-opengl/gl-shaderparser.c
  2. 12 2
      libobs-opengl/gl-subsystem.c
  3. 1 0
      libobs-opengl/gl-subsystem.h

+ 29 - 10
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);

+ 12 - 2
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;

+ 1 - 0
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;