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

Alexandros Frantzis alexandros.frantzis at collabora.com
Mon Apr 23 15:45:58 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.

This commit temporarily removes the VIRGL_FORMAT_R8G8B8X8_UNORM special
case. Improved support for it, and other similar "ignore alpha" cases,
is added back in an upcoming commit using appropriate swizzles.

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  | 192 +++++++++++--------------------------------
 src/vrend_blitter.h  |  28 +------
 src/vrend_renderer.c |  12 +--
 3 files changed, 55 insertions(+), 177 deletions(-)

diff --git a/src/vrend_blitter.c b/src/vrend_blitter.c
index a70da14..c273f0f 100644
--- a/src/vrend_blitter.c
+++ b/src/vrend_blitter.c
@@ -49,6 +49,8 @@
 
 #include "vrend_blitter.h"
 
+#define DEST_SWIZZLE_SNIPPET_SIZE 64
+
 struct vrend_blitter_ctx {
    virgl_gl_context gl_context;
    bool initialised;
@@ -59,10 +61,9 @@ struct vrend_blitter_ctx {
    GLuint vs;
    GLuint vs_pos_only;
    GLuint fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES];
-   GLuint fs_texfetch_col_ignore_alpha[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;
@@ -105,68 +106,44 @@ 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[DEST_SWIZZLE_SNIPPET_SIZE])
 {
-   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;
+   static const uint8_t invalid_swizzle = 0xff;
+   ssize_t si = 0;
+   uint8_t inverse[4] = {invalid_swizzle, invalid_swizzle, invalid_swizzle,
+                         invalid_swizzle};
+
+   for (int i = 0; i < 4; ++i) {
+      if (swizzle[i] > 3) continue;
+      if (inverse[swizzle[i]] == invalid_swizzle)
+         inverse[swizzle[i]] = i;
    }
 
-   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);
-
-   if (!build_and_check(fs_id, shader_buf)) {
-      glDeleteShader(fs_id);
-      return 0;
+   for (int i = 0; i < 4; ++i) {
+      int res = -1;
+      if (inverse[i] > 3) {
+          /* Use 0.0f for unused color values, 1.0f for an unused alpha value */
+         res = snprintf(&snippet[si], DEST_SWIZZLE_SNIPPET_SIZE - si,
+                        i < 3 ? "0.0f, " : "1.0f");
+      } else {
+         res = snprintf(&snippet[si], DEST_SWIZZLE_SNIPPET_SIZE - si,
+                        "texel.%c%s", "rgba"[inverse[i]], i < 3 ? ", " : "");
+      }
+      si += res > 0 ? res : 0;
    }
-
-
-   return fs_id;
 }
 
-static GLuint blit_build_frag_tex_col_ignore_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[DEST_SWIZZLE_SNIPPET_SIZE] = "texel";
    switch (tgsi_tex_target) {
    case TGSI_TEXTURE_1D:
    case TGSI_TEXTURE_BUFFER:
@@ -201,62 +178,12 @@ static GLuint blit_build_frag_tex_col_ignore_alpha(struct vrend_blitter_ctx *bli
        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_IGNORE_ALPHA_GLES : FS_TEXFETCH_COL_IGNORE_ALPHA_GL,
-      ext_str, vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm, "");
-
-   fs_id = glCreateShader(GL_FRAGMENT_SHADER);
-
-   if (!build_and_check(fs_id, shader_buf)) {
-      glDeleteShader(fs_id);
-      return 0;
-   }
-
-   return fs_id;
-}
+   if (swizzle)
+      create_dest_swizzle_snippet(swizzle, dest_swizzle_snippet);
 
-static GLuint blit_build_frag_tex_col_emu_alpha(struct vrend_blitter_ctx *blit_ctx, int tgsi_tex_target)
-{
-   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_ALPHA_DEST_GLES : FS_TEXFETCH_COL_ALPHA_DEST_GL,
-      ext_str, vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm, "");
+   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);
 
@@ -378,55 +305,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_ignore_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;
-   } else {
-      GLuint *shader = &blit_ctx->fs_texfetch_col_ignore_alpha[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, entry->swizzle);
 
-         *shader = blit_build_frag_tex_col_ignore_alpha(blit_ctx, tgsi_tex);
-      }
       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);
-
-   if (nr_samples > 1) {
-      return 0;
    } 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;
    }
@@ -652,6 +554,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);
@@ -678,12 +582,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 if (src_res->base.format == VIRGL_FORMAT_R8G8B8X8_UNORM)
-      fs_id = blit_get_frag_tex_col_ignore_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 8c0aac6..ce05bbc 100644
--- a/src/vrend_blitter.h
+++ b/src/vrend_blitter.h
@@ -58,37 +58,13 @@
    "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_IGNORE_ALPHA_BODY       \
-   "%s"                                         \
-   "uniform sampler%s samp;\n"                  \
-   "in vec4 tc;\n"                              \
-   "void main() {\n"                            \
-   "   vec4 temp = texture(samp, tc%s)%s;\n"    \
-   "   gl_FragColor = vec4(temp.rgb, 1.0f);\n"  \
-   "}\n"
-
-#define FS_TEXFETCH_COL_IGNORE_ALPHA_GL HEADER_GL FS_TEXFETCH_COL_IGNORE_ALPHA_BODY
-#define FS_TEXFETCH_COL_IGNORE_ALPHA_GLES HEADER_GLES OUTFRAG_GLES FS_TEXFETCH_COL_IGNORE_ALPHA_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 5c16afe..8e55f63 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,11 +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))
-      use_gl = true;
-
-   if (info->src.format == VIRGL_FORMAT_R8G8B8X8_UNORM)
+   if (vrend_format_needs_swizzle(info->dst.format) ||
+       vrend_format_needs_swizzle(info->src.format))
       use_gl = true;
 
    if (use_gl) {
-- 
2.17.0



More information about the virglrenderer-devel mailing list