From 729c6b9177541f189ebed5158a432b21d0d82211 Mon Sep 17 00:00:00 2001 From: mwezdeck Date: Wed, 22 Sep 2021 08:30:52 +0200 Subject: [PATCH] vrend: apply format swizzling during GLSL generation If the guest is creating texture and the memory comes from buffer object by creating GL_TEXTURE_BUFFER, then host creates GL_TEXTURE_BUFFER too. No texture parameters can be set for GL_TEXTURE_BUFFER. If there is mismatch between the guest texture format and the host texture format, for example GL_ALPHA8(guest) and GL_R8(host), then we can't apply swizzling for such textures. In such case, add manually swizzling in GLSL shader generation step. The logic of this patch: 1. Add additional fields in shader key struct 2. During draw_vbo call check if "manual swizzling" is needed 3. If yes, the add fields in key struct and generate shader again 4. During generation of for example texelFetch instruction in GLSL put additional instruction for swizzling Reviewed-by: Gert Wollny --- src/vrend_renderer.c | 27 +++++++++++++++++++++++++++ src/vrend_shader.c | 26 ++++++++++++++++++++++++++ src/vrend_shader.h | 3 +++ 3 files changed, 56 insertions(+) diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 5606c7f..d9f4b7b 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -2144,6 +2144,21 @@ static inline GLenum to_gl_swizzle(int swizzle) } } +static inline int to_pipe_swizzle(GLenum swizzle) +{ + switch (swizzle) { + case GL_RED: return PIPE_SWIZZLE_RED; + case GL_GREEN: return PIPE_SWIZZLE_GREEN; + case GL_BLUE: return PIPE_SWIZZLE_BLUE; + case GL_ALPHA: return PIPE_SWIZZLE_ALPHA; + case GL_ZERO: return PIPE_SWIZZLE_ZERO; + case GL_ONE: return PIPE_SWIZZLE_ONE; + default: + assert(0); + return 0; + } +} + int vrend_create_sampler_view(struct vrend_context *ctx, uint32_t handle, uint32_t res_handle, uint32_t format, @@ -3533,6 +3548,18 @@ static inline void vrend_fill_shader_key(struct vrend_sub_context *sub_ctx, if (type != PIPE_SHADER_COMPUTE) vrend_sync_shader_io(sub_ctx, sel, key); + + for (int i = 0; i < sub_ctx->views->num_views; i++) { + struct vrend_sampler_view *view = sub_ctx->views[type].views[i]; + if (view && view->texture->target == GL_TEXTURE_BUFFER && + view->format != tex_conv_table[view->format].internalformat) { + key->sampler_views_lower_swizzle_mask |= 1 << i; + key->tex_swizzle[i] = to_pipe_swizzle(view->gl_swizzle[0]) | + to_pipe_swizzle(view->gl_swizzle[1]) << 3 | + to_pipe_swizzle(view->gl_swizzle[2]) << 6 | + to_pipe_swizzle(view->gl_swizzle[3]) << 9 ; + } + } } static int vrend_shader_create(struct vrend_context *ctx, diff --git a/src/vrend_shader.c b/src/vrend_shader.c index 2a6a41d..c9c0228 100644 --- a/src/vrend_shader.c +++ b/src/vrend_shader.c @@ -441,6 +441,21 @@ static inline const char *get_wm_string(unsigned wm) } } +static inline const char *get_swizzle_string(uint8_t swizzle) +{ + switch (swizzle) { + case PIPE_SWIZZLE_RED: return ".x"; + case PIPE_SWIZZLE_GREEN: return ".y"; + case PIPE_SWIZZLE_BLUE: return ".z"; + case PIPE_SWIZZLE_ALPHA: return ".w"; + case PIPE_SWIZZLE_ZERO: + case PIPE_SWIZZLE_ONE: return ".0"; + default: + assert(0); + return ""; + } +} + const char *get_internalformat_string(int virgl_format, enum tgsi_return_type *stype); static inline const char *tgsi_proc_to_prefix(int shader_type) @@ -2903,6 +2918,17 @@ static void translate_tex(struct dump_ctx *ctx, tex_ext, srcs[sampler_index], get_string(txfi), srcs[0], get_wm_string(twm), bias, offset, dinfo->dst_override_no_wm[0] ? "" : writemask); + if (ctx->key->sampler_views_lower_swizzle_mask & (1 << sinfo->sreg_index)) { + uint8_t swizzle_r = ctx->key->tex_swizzle[sinfo->sreg_index] & 7; + uint8_t swizzle_g = (ctx->key->tex_swizzle[sinfo->sreg_index] & (7 << 3)) >> 3; + uint8_t swizzle_b = (ctx->key->tex_swizzle[sinfo->sreg_index] & (7 << 6)) >> 6; + uint8_t swizzle_a = (ctx->key->tex_swizzle[sinfo->sreg_index] & (7 << 9)) >> 9; + emit_buff(&ctx->glsl_strbufs, "%s = vec4(%s%s, %s%s, %s%s, %s%s);\n", dst, + swizzle_r == PIPE_SWIZZLE_ZERO ? "0" : (swizzle_r == PIPE_SWIZZLE_ONE ? "1" : dst), get_swizzle_string(swizzle_r), + swizzle_g == PIPE_SWIZZLE_ZERO ? "0" : (swizzle_g == PIPE_SWIZZLE_ONE ? "1" : dst), get_swizzle_string(swizzle_g), + swizzle_b == PIPE_SWIZZLE_ZERO ? "0" : (swizzle_b == PIPE_SWIZZLE_ONE ? "1" : dst), get_swizzle_string(swizzle_b), + swizzle_a == PIPE_SWIZZLE_ZERO ? "0" : (swizzle_a == PIPE_SWIZZLE_ONE ? "1" : dst), get_swizzle_string(swizzle_a)); + } } } else if (ctx->cfg->glsl_version < 140 && (ctx->shader_req_bits & SHADER_REQ_SAMPLER_RECT)) { /* rect is special in GLSL 1.30 */ diff --git a/src/vrend_shader.h b/src/vrend_shader.h index de84ca4..1e56282 100644 --- a/src/vrend_shader.h +++ b/src/vrend_shader.h @@ -168,6 +168,9 @@ struct vrend_shader_key { uint32_t compiled_fs_uid; + uint32_t sampler_views_lower_swizzle_mask; + uint16_t tex_swizzle[PIPE_MAX_SHADER_SAMPLER_VIEWS]; + uint8_t alpha_test; uint8_t clip_plane_enable; uint8_t num_cull : 4;