[virglrenderer-devel] [PATCH 3/6] vrend: Use destination swizzle when creating blit shaders

Alexandros Frantzis alexandros.frantzis at collabora.com
Wed Apr 11 13:39:12 UTC 2018


Update the blit shader creation code to take the destination format
swizzle into account. This involves inverting the swizzle information
and using the inverted swizzle to reorder the texel components in the
shader. The new swizzle code also removes the need for having a special
case if the destination format uses emulated alpha.

At the moment we always recreate the shader in case we have a swizzle,
but a more efficient shader caching scheme could be devised to improve
this.

Signed-off-by: Alexandros Frantzis <alexandros.frantzis at collabora.com>
---
 src/vrend_blitter.c  | 115 +++++++++++++++++++--------------------------------
 src/vrend_blitter.h  |  16 +------
 src/vrend_renderer.c |   9 +++-
 3 files changed, 51 insertions(+), 89 deletions(-)

diff --git a/src/vrend_blitter.c b/src/vrend_blitter.c
index 8e4c121..93357c8 100644
--- a/src/vrend_blitter.c
+++ b/src/vrend_blitter.c
@@ -59,9 +59,9 @@ struct vrend_blitter_ctx {
    GLuint vs;
    GLuint vs_pos_only;
    GLuint fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES];
-   GLuint fs_texfetch_col_emu_alpha[PIPE_MAX_TEXTURE_TYPES];
    GLuint fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES];
    GLuint fs_texfetch_depth_msaa[PIPE_MAX_TEXTURE_TYPES];
+   GLuint fs_texfetch_col_swizzle;
    GLuint fb_id;
 
    unsigned dst_width;
@@ -104,67 +104,39 @@ static bool blit_build_vs_passthrough(struct vrend_blitter_ctx *blit_ctx)
    return true;
 }
 
-static GLuint blit_build_frag_tex_col(struct vrend_blitter_ctx *blit_ctx, int tgsi_tex_target)
+static void create_dest_swizzle_snippet(const uint8_t swizzle[4], char snippet[64])
 {
-   GLuint fs_id;
-   char shader_buf[4096];
-   int is_shad;
-   const char *twm;
-   const char *ext_str = "";
-   switch (tgsi_tex_target) {
-   case TGSI_TEXTURE_1D:
-   case TGSI_TEXTURE_BUFFER:
-      twm = ".x";
-      break;
-   case TGSI_TEXTURE_1D_ARRAY:
-   case TGSI_TEXTURE_2D:
-   case TGSI_TEXTURE_RECT:
-   case TGSI_TEXTURE_2D_MSAA:
-   default:
-      twm = ".xy";
-      break;
-   case TGSI_TEXTURE_SHADOW1D:
-   case TGSI_TEXTURE_SHADOW2D:
-   case TGSI_TEXTURE_SHADOW1D_ARRAY:
-   case TGSI_TEXTURE_SHADOWRECT:
-   case TGSI_TEXTURE_3D:
-   case TGSI_TEXTURE_CUBE:
-   case TGSI_TEXTURE_2D_ARRAY:
-   case TGSI_TEXTURE_2D_ARRAY_MSAA:
-      twm = ".xyz";
-      break;
-   case TGSI_TEXTURE_SHADOWCUBE:
-   case TGSI_TEXTURE_SHADOW2D_ARRAY:
-   case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
-   case TGSI_TEXTURE_CUBE_ARRAY:
-      twm = "";
-      break;
-   }
-
-   if (tgsi_tex_target == TGSI_TEXTURE_CUBE_ARRAY ||
-       tgsi_tex_target == TGSI_TEXTURE_SHADOWCUBE_ARRAY)
-      ext_str = "#extension GL_ARB_texture_cube_map_array : require\n";
-
-   snprintf(shader_buf, 4096, blit_ctx->use_gles ? FS_TEXFETCH_COL_GLES : FS_TEXFETCH_COL_GL,
-      ext_str, vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm, "");
-
-   fs_id = glCreateShader(GL_FRAGMENT_SHADER);
+   ssize_t si = 0;
+   uint8_t inverse[4] = {0xff, 0xff, 0xff, 0xff};
 
-   if (!build_and_check(fs_id, shader_buf)) {
-      glDeleteShader(fs_id);
-      return 0;
+   for (int i = 0; i < 4; ++i) {
+      if (swizzle[i] > 3) continue;
+      if (inverse[swizzle[i]] == 0xff)
+         inverse[swizzle[i]] = i;
    }
 
-   return fs_id;
+   for (int i = 0; i < 4; ++i) {
+      int res = -1;
+      if (inverse[i] > 3) {
+         res = snprintf(&snippet[si], 64 - si, "0.0f%s", i < 3 ? ", " : "");
+      } else {
+         res = snprintf(&snippet[si], 64 - si, "texel.%c%s", "rgba"[inverse[i]],
+                        i < 3 ? ", " : "");
+      }
+      si += res > 0 ? res : 0;
+   }
 }
 
-static GLuint blit_build_frag_tex_col_emu_alpha(struct vrend_blitter_ctx *blit_ctx, int tgsi_tex_target)
+static GLuint blit_build_frag_tex_col(struct vrend_blitter_ctx *blit_ctx,
+                                      int tgsi_tex_target,
+                                      const uint8_t swizzle[4])
 {
    GLuint fs_id;
    char shader_buf[4096];
    int is_shad;
    const char *twm;
    const char *ext_str = "";
+   char dest_swizzle_snippet[64] = "texel";
    switch (tgsi_tex_target) {
    case TGSI_TEXTURE_1D:
    case TGSI_TEXTURE_BUFFER:
@@ -199,8 +171,12 @@ static GLuint blit_build_frag_tex_col_emu_alpha(struct vrend_blitter_ctx *blit_c
        tgsi_tex_target == TGSI_TEXTURE_SHADOWCUBE_ARRAY)
       ext_str = "#extension GL_ARB_texture_cube_map_array : require\n";
 
-   snprintf(shader_buf, 4096, blit_ctx->use_gles ? FS_TEXFETCH_COL_ALPHA_DEST_GLES : FS_TEXFETCH_COL_ALPHA_DEST_GL,
-      ext_str, vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm, "");
+   if (swizzle)
+      create_dest_swizzle_snippet(swizzle, dest_swizzle_snippet);
+
+   snprintf(shader_buf, 4096, blit_ctx->use_gles ? FS_TEXFETCH_COL_GLES : FS_TEXFETCH_COL_GL,
+            ext_str, vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm,
+            dest_swizzle_snippet);
 
    fs_id = glCreateShader(GL_FRAGMENT_SHADER);
 
@@ -322,37 +298,30 @@ static GLuint blit_get_frag_tex_writedepth(struct vrend_blitter_ctx *blit_ctx, i
    }
 }
 
-static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx, int pipe_tex_target, unsigned nr_samples)
+static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx, int pipe_tex_target, unsigned nr_samples, const struct vrend_format_table *entry)
 {
    assert(pipe_tex_target < PIPE_MAX_TEXTURE_TYPES);
 
    if (nr_samples > 1) {
       return 0;
-   } else {
-      GLuint *shader = &blit_ctx->fs_texfetch_col[pipe_tex_target];
-
-      if (!*shader) {
-         unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, 0);
-
-         *shader = blit_build_frag_tex_col(blit_ctx, tgsi_tex);
+   } else if (entry->flags & VREND_BIND_NEED_SWIZZLE) {
+      GLuint *shader = &blit_ctx->fs_texfetch_col_swizzle;
+      if (shader) {
+          glDeleteShader(*shader);
       }
-      return *shader;
-   }
-}
 
-static GLuint blit_get_frag_tex_col_emu_alpha(struct vrend_blitter_ctx *blit_ctx, int pipe_tex_target, unsigned nr_samples)
-{
-   assert(pipe_tex_target < PIPE_MAX_TEXTURE_TYPES);
+     unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, 0);
 
-   if (nr_samples > 1) {
-      return 0;
+     *shader = blit_build_frag_tex_col(blit_ctx, tgsi_tex, entry->swizzle);
+
+      return *shader;
    } else {
-      GLuint *shader = &blit_ctx->fs_texfetch_col_emu_alpha[pipe_tex_target];
+      GLuint *shader = &blit_ctx->fs_texfetch_col[pipe_tex_target];
 
       if (!*shader) {
          unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, 0);
 
-         *shader = blit_build_frag_tex_col_emu_alpha(blit_ctx, tgsi_tex);
+         *shader = blit_build_frag_tex_col(blit_ctx, tgsi_tex, NULL);
       }
       return *shader;
    }
@@ -578,6 +547,8 @@ void vrend_renderer_blit_gl(struct vrend_context *ctx,
       util_format_description(dst_res->base.format);
    const struct vrend_format_table *src_entry =
       vrend_get_format_table_entry(info->src.format);
+   const struct vrend_format_table *dst_entry =
+      vrend_get_format_table_entry(info->dst.format);
 
    has_depth = util_format_has_depth(src_desc) &&
       util_format_has_depth(dst_desc);
@@ -604,10 +575,8 @@ void vrend_renderer_blit_gl(struct vrend_context *ctx,
 
    if (blit_depth || blit_stencil)
       fs_id = blit_get_frag_tex_writedepth(blit_ctx, src_res->base.target, src_res->base.nr_samples);
-   else if (vrend_format_is_emulated_alpha(info->dst.format))
-      fs_id = blit_get_frag_tex_col_emu_alpha(blit_ctx, src_res->base.target, src_res->base.nr_samples);
    else
-      fs_id = blit_get_frag_tex_col(blit_ctx, src_res->base.target, src_res->base.nr_samples);
+      fs_id = blit_get_frag_tex_col(blit_ctx, src_res->base.target, src_res->base.nr_samples, dst_entry);
    glAttachShader(prog_id, fs_id);
 
    glLinkProgram(prog_id);
diff --git a/src/vrend_blitter.h b/src/vrend_blitter.h
index 07573a7..bdaeeb1 100644
--- a/src/vrend_blitter.h
+++ b/src/vrend_blitter.h
@@ -58,26 +58,14 @@
    "uniform sampler%s samp;\n"                  \
    "in vec4 tc;\n"                              \
    "void main() {\n"                            \
-   "   gl_FragColor = texture(samp, tc%s)%s;\n" \
+   "   vec4 texel = texture(samp, tc%s);\n"     \
+   "   gl_FragColor = vec4(%s);\n" \
    "}\n"
 
 #define FS_TEXFETCH_COL_GL HEADER_GL FS_TEXFETCH_COL_BODY
 #define FS_TEXFETCH_COL_GLES HEADER_GLES OUTFRAG_GLES FS_TEXFETCH_COL_BODY
 
 
-#define FS_TEXFETCH_COL_ALPHA_DEST_BODY         \
-   "%s"                                         \
-   "uniform sampler%s samp;\n"                  \
-   "in vec4 tc;\n"                              \
-   "void main() {\n"                            \
-   "   vec4 temp = texture(samp, tc%s)%s;\n"    \
-   "   gl_FragColor = temp.aaaa;\n"             \
-   "}\n"
-
-#define FS_TEXFETCH_COL_ALPHA_DEST_GL HEADER_GL FS_TEXFETCH_COL_ALPHA_DEST_BODY
-#define FS_TEXFETCH_COL_ALPHA_DEST_GLES HEADER_GLES OUTFRAG_GLES FS_TEXFETCH_COL_ALPHA_DEST_BODY
-
-
 #define FS_TEXFETCH_DS_BODY                             \
    "uniform sampler%s samp;\n"                          \
    "in vec4 tc;\n"                                      \
diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 1ab64d5..2ab9bb9 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -452,6 +452,11 @@ bool vrend_format_is_emulated_alpha(enum virgl_formats format)
            format == VIRGL_FORMAT_A16_UNORM);
 }
 
+bool vrend_format_needs_swizzle(enum virgl_formats format)
+{
+   return tex_conv_table[format].flags & VREND_BIND_NEED_SWIZZLE;
+}
+
 static inline const char *pipe_shader_to_prefix(int shader_type)
 {
    switch (shader_type) {
@@ -5947,8 +5952,8 @@ static void vrend_renderer_blit_int(struct vrend_context *ctx,
    if (info->src.box.depth != info->dst.box.depth)
       use_gl = true;
 
-   if (vrend_format_is_emulated_alpha(info->dst.format) ||
-       vrend_format_is_emulated_alpha(info->src.format))
+   if (vrend_format_needs_swizzle(info->dst.format) ||
+       vrend_format_needs_swizzle(info->src.format))
       use_gl = true;
 
    if (use_gl) {
-- 
2.15.1



More information about the virglrenderer-devel mailing list