From d37688e4c2c0d6cd0b082ccfbd663905359f6ea5 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 30 Mar 2025 16:06:01 +0200 Subject: Compute shader cleanup --- src/color_conversion.c | 132 +++++++++++++++++++++++++++---------------------- 1 file changed, 73 insertions(+), 59 deletions(-) diff --git a/src/color_conversion.c b/src/color_conversion.c index 591bde8..9cbfc17 100644 --- a/src/color_conversion.c +++ b/src/color_conversion.c @@ -5,6 +5,13 @@ #include #include +#define SHADER_INDEX_Y 0 +#define SHADER_INDEX_UV 1 +#define SHADER_INDEX_Y_EXTERNAL 2 +#define SHADER_INDEX_UV_EXTERNAL 3 +#define SHADER_INDEX_RGB 4 +#define SHADER_INDEX_RGB_EXTERNAL 5 + // TODO: Scissor doesn't work with compute shader. In the compute shader this can be implemented with two step calls, and using the result // with a call to mix to choose source/output color. @@ -257,23 +264,23 @@ int gsr_color_conversion_init(gsr_color_conversion *self, const gsr_color_conver return -1; } - if(load_compute_shader_y(&self->shaders[0], self->params.egl, &self->uniforms[0], self->max_local_size_dim, params->destination_color, params->color_range, false) != 0) { + if(load_compute_shader_y(&self->shaders[SHADER_INDEX_Y], self->params.egl, &self->uniforms[SHADER_INDEX_Y], self->max_local_size_dim, params->destination_color, params->color_range, false) != 0) { fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load Y compute shader\n"); goto err; } - if(load_compute_shader_uv(&self->shaders[1], self->params.egl, &self->uniforms[1], self->max_local_size_dim, params->destination_color, params->color_range, false) != 0) { + if(load_compute_shader_uv(&self->shaders[SHADER_INDEX_UV], self->params.egl, &self->uniforms[SHADER_INDEX_UV], self->max_local_size_dim, params->destination_color, params->color_range, false) != 0) { fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load UV compute shader\n"); goto err; } if(self->params.load_external_image_shader) { - if(load_compute_shader_y(&self->shaders[2], self->params.egl, &self->uniforms[2], self->max_local_size_dim, params->destination_color, params->color_range, true) != 0) { + if(load_compute_shader_y(&self->shaders[SHADER_INDEX_Y_EXTERNAL], self->params.egl, &self->uniforms[SHADER_INDEX_Y_EXTERNAL], self->max_local_size_dim, params->destination_color, params->color_range, true) != 0) { fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load Y compute shader\n"); goto err; } - if(load_compute_shader_uv(&self->shaders[3], self->params.egl, &self->uniforms[3], self->max_local_size_dim, params->destination_color, params->color_range, true) != 0) { + if(load_compute_shader_uv(&self->shaders[SHADER_INDEX_UV_EXTERNAL], self->params.egl, &self->uniforms[SHADER_INDEX_UV_EXTERNAL], self->max_local_size_dim, params->destination_color, params->color_range, true) != 0) { fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load UV compute shader\n"); goto err; } @@ -286,13 +293,13 @@ int gsr_color_conversion_init(gsr_color_conversion *self, const gsr_color_conver return -1; } - if(load_compute_shader_rgb(&self->shaders[4], self->params.egl, &self->uniforms[4], self->max_local_size_dim, false) != 0) { + if(load_compute_shader_rgb(&self->shaders[SHADER_INDEX_RGB], self->params.egl, &self->uniforms[SHADER_INDEX_RGB], self->max_local_size_dim, false) != 0) { fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load Y compute shader\n"); goto err; } if(self->params.load_external_image_shader) { - if(load_compute_shader_rgb(&self->shaders[5], self->params.egl, &self->uniforms[5], self->max_local_size_dim, true) != 0) { + if(load_compute_shader_rgb(&self->shaders[SHADER_INDEX_RGB_EXTERNAL], self->params.egl, &self->uniforms[SHADER_INDEX_RGB_EXTERNAL], self->max_local_size_dim, true) != 0) { fprintf(stderr, "gsr error: gsr_color_conversion_init: failed to load Y compute shader\n"); goto err; } @@ -395,6 +402,63 @@ static void gsr_color_conversion_swizzle_reset(gsr_color_conversion *self, gsr_s } } +typedef enum { + GSR_COLOR_COMP_Y, + GSR_COLOR_COMP_UV, + GSR_COLOR_COMP_RGB +} gsr_color_component; + +static int color_component_get_texture_index(gsr_color_component color_component) { + switch(color_component) { + case GSR_COLOR_COMP_Y: return 0; + case GSR_COLOR_COMP_UV: return 1; + case GSR_COLOR_COMP_RGB: return 0; + } + assert(false); + return 0; +} + +static unsigned int color_component_get_color_format(gsr_color_component color_component, bool use_16bit_colors) { + switch(color_component) { + case GSR_COLOR_COMP_Y: return use_16bit_colors ? GL_R16 : GL_R8; + case GSR_COLOR_COMP_UV: return use_16bit_colors ? GL_RG16 : GL_RG8; + case GSR_COLOR_COMP_RGB: return GL_RGBA8; // TODO: 16-bit color support + } + assert(false); + return GL_RGBA8; +} + +static int color_component_get_shader_index(gsr_color_component color_component, bool external_texture) { + switch(color_component) { + case GSR_COLOR_COMP_Y: return external_texture ? SHADER_INDEX_Y_EXTERNAL : SHADER_INDEX_Y; + case GSR_COLOR_COMP_UV: return external_texture ? SHADER_INDEX_UV_EXTERNAL : SHADER_INDEX_UV; + case GSR_COLOR_COMP_RGB: return external_texture ? SHADER_INDEX_RGB_EXTERNAL : SHADER_INDEX_RGB; + } + assert(false); + return SHADER_INDEX_RGB; +} + +static void gsr_color_conversion_dispatch_compute_shader(gsr_color_conversion *self, bool external_texture, float rotation_matrix[2][2], vec2i source_position, vec2i destination_pos, vec2i destination_size, vec2f scale, bool use_16bit_colors, gsr_color_component color_component) { + const int shader_index = color_component_get_shader_index(color_component, external_texture); + const int texture_index = color_component_get_texture_index(color_component); + const unsigned int color_format = color_component_get_color_format(color_component, use_16bit_colors); + + self->params.egl->glActiveTexture(GL_TEXTURE1); + self->params.egl->glBindTexture(GL_TEXTURE_2D, self->params.destination_textures[texture_index]); + self->params.egl->glActiveTexture(GL_TEXTURE0); + + gsr_color_uniforms *uniform = &self->uniforms[shader_index]; + gsr_shader_use(&self->shaders[shader_index]); + self->params.egl->glUniformMatrix2fv(uniform->rotation_matrix, 1, GL_TRUE, (const float*)rotation_matrix); + self->params.egl->glUniform2i(uniform->source_position, source_position.x, source_position.y); + self->params.egl->glUniform2i(uniform->target_position, destination_pos.x, destination_pos.y); + self->params.egl->glUniform2f(uniform->scale, scale.x, scale.y); + self->params.egl->glBindImageTexture(0, self->params.destination_textures[texture_index], 0, GL_FALSE, 0, GL_WRITE_ONLY, color_format); + const double num_groups_x = ceil((double)destination_size.x/(double)self->max_local_size_dim); + const double num_groups_y = ceil((double)destination_size.y/(double)self->max_local_size_dim); + self->params.egl->glDispatchCompute(max_int(1, num_groups_x), max_int(1, num_groups_y), 1); +} + void gsr_color_conversion_draw(gsr_color_conversion *self, unsigned int texture_id, vec2i destination_pos, vec2i destination_size, vec2i texture_pos, vec2i texture_size, gsr_rotation rotation, bool external_texture, gsr_source_color source_color) { vec2f scale = {0.0f, 0.0f}; if(texture_size.x > 0 && texture_size.y > 0) @@ -415,62 +479,12 @@ void gsr_color_conversion_draw(gsr_color_conversion *self, unsigned int texture_ case GSR_DESTINATION_COLOR_NV12: case GSR_DESTINATION_COLOR_P010: { const bool use_16bit_colors = self->params.destination_color == GSR_DESTINATION_COLOR_P010; - const int shader_index_offset = external_texture ? 2 : 0; - - self->params.egl->glActiveTexture(GL_TEXTURE1); - self->params.egl->glBindTexture(GL_TEXTURE_2D, self->params.destination_textures[0]); - self->params.egl->glActiveTexture(GL_TEXTURE0); - - // Y - { - gsr_color_uniforms *uniform = &self->uniforms[shader_index_offset + 0]; - gsr_shader_use(&self->shaders[shader_index_offset + 0]); - self->params.egl->glUniformMatrix2fv(uniform->rotation_matrix, 1, GL_TRUE, (const float*)rotation_matrix); - self->params.egl->glUniform2i(uniform->source_position, source_position.x, source_position.y); - self->params.egl->glUniform2i(uniform->target_position, destination_pos.x, destination_pos.y); - self->params.egl->glUniform2f(uniform->scale, scale.x, scale.y); - self->params.egl->glBindImageTexture(0, self->params.destination_textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, use_16bit_colors ? GL_R16 : GL_R8); - const double num_groups_x = ceil((double)destination_size.x/(double)self->max_local_size_dim); - const double num_groups_y = ceil((double)destination_size.y/(double)self->max_local_size_dim); - self->params.egl->glDispatchCompute(max_int(1, num_groups_x), max_int(1, num_groups_y), 1); - } - - self->params.egl->glActiveTexture(GL_TEXTURE1); - self->params.egl->glBindTexture(GL_TEXTURE_2D, self->params.destination_textures[1]); - self->params.egl->glActiveTexture(GL_TEXTURE0); - - // UV - { - gsr_color_uniforms *uniform = &self->uniforms[shader_index_offset + 1]; - gsr_shader_use(&self->shaders[shader_index_offset + 1]); - self->params.egl->glUniformMatrix2fv(uniform->rotation_matrix, 1, GL_TRUE, (const float*)rotation_matrix); - self->params.egl->glUniform2i(uniform->source_position, source_position.x, source_position.y); - self->params.egl->glUniform2i(uniform->target_position, destination_pos.x, destination_pos.y); - self->params.egl->glUniform2f(uniform->scale, scale.x, scale.y); - self->params.egl->glBindImageTexture(0, self->params.destination_textures[1], 0, GL_FALSE, 0, GL_WRITE_ONLY, use_16bit_colors ? GL_RG16 : GL_RG8); - const double num_groups_x = ceil((double)destination_size.x*0.5/(double)self->max_local_size_dim); - const double num_groups_y = ceil((double)destination_size.y*0.5/(double)self->max_local_size_dim); - self->params.egl->glDispatchCompute(max_int(1, num_groups_x), max_int(1, num_groups_y), 1); - } + gsr_color_conversion_dispatch_compute_shader(self, external_texture, rotation_matrix, source_position, destination_pos, destination_size, scale, use_16bit_colors, GSR_COLOR_COMP_Y); + gsr_color_conversion_dispatch_compute_shader(self, external_texture, rotation_matrix, source_position, destination_pos, (vec2i){destination_size.x/2, destination_size.y/2}, scale, use_16bit_colors, GSR_COLOR_COMP_UV); break; } case GSR_DESTINATION_COLOR_RGB8: { - const int shader_index_offset = external_texture ? 1 : 0; - - self->params.egl->glActiveTexture(GL_TEXTURE1); - self->params.egl->glBindTexture(GL_TEXTURE_2D, self->params.destination_textures[0]); - self->params.egl->glActiveTexture(GL_TEXTURE0); - - gsr_color_uniforms *uniform = &self->uniforms[shader_index_offset + 4]; - gsr_shader_use(&self->shaders[shader_index_offset + 4]); - self->params.egl->glUniformMatrix2fv(uniform->rotation_matrix, 1, GL_TRUE, (const float*)rotation_matrix); - self->params.egl->glUniform2i(uniform->source_position, source_position.x, source_position.y); - self->params.egl->glUniform2i(uniform->target_position, destination_pos.x, destination_pos.y); - self->params.egl->glUniform2f(uniform->scale, scale.x, scale.y); - self->params.egl->glBindImageTexture(0, self->params.destination_textures[0], 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8); - const double num_groups_x = ceil((double)destination_size.x/(double)self->max_local_size_dim); - const double num_groups_y = ceil((double)destination_size.y/(double)self->max_local_size_dim); - self->params.egl->glDispatchCompute(max_int(1, num_groups_x), max_int(1, num_groups_y), 1); + gsr_color_conversion_dispatch_compute_shader(self, external_texture, rotation_matrix, source_position, destination_pos, destination_size, scale, false, GSR_COLOR_COMP_RGB); break; } } -- cgit v1.2.3-70-g09d2