[Mesa-dev] [PATCH v6] swr: implement clipPlanes/clipVertex/clipDistance/cullDistance

Cherniak, Bruce bruce.cherniak at intel.com
Wed Jun 8 15:51:31 UTC 2016


Reviewed-by: Bruce Cherniak <bruce.cherniak at intel.com> 

> On Jun 8, 2016, at 9:59 AM, Tim Rowley <timothy.o.rowley at intel.com> wrote:
> 
> v2: only load the clip vertex once
> 
> v3: fix clip enable logic, add cullDistance
> 
> v4: remove duplicate fields in vs jit key, fix test of clip fixup needed
> 
> v5: fix clipdistance linkage for slot!=0,4
> 
> v6: support clip+cull; passes most piglit clip (failures understood)
> ---
> docs/GL3.txt                           |  2 +-
> src/gallium/drivers/swr/swr_context.h  |  2 ++
> src/gallium/drivers/swr/swr_screen.cpp |  3 +-
> src/gallium/drivers/swr/swr_shader.cpp | 65 ++++++++++++++++++++++++++++++++++
> src/gallium/drivers/swr/swr_shader.h   |  1 +
> src/gallium/drivers/swr/swr_state.cpp  | 25 ++++++++++++-
> 6 files changed, 95 insertions(+), 3 deletions(-)
> 
> diff --git a/docs/GL3.txt b/docs/GL3.txt
> index e8d401d..4ba0366 100644
> --- a/docs/GL3.txt
> +++ b/docs/GL3.txt
> @@ -211,7 +211,7 @@ GL 4.5, GLSL 4.50:
>   GL_ARB_ES3_1_compatibility                            DONE (nvc0, radeonsi)
>   GL_ARB_clip_control                                   DONE (i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe, swr)
>   GL_ARB_conditional_render_inverted                    DONE (i965, nv50, nvc0, r600, radeonsi, llvmpipe, softpipe, swr)
> -  GL_ARB_cull_distance                                  DONE (i965, nv50, nvc0, llvmpipe, softpipe)
> +  GL_ARB_cull_distance                                  DONE (i965, nv50, nvc0, llvmpipe, softpipe, swr)
>   GL_ARB_derivative_control                             DONE (i965, nv50, nvc0, r600, radeonsi)
>   GL_ARB_direct_state_access                            DONE (all drivers)
>   GL_ARB_get_texture_sub_image                          DONE (all drivers)
> diff --git a/src/gallium/drivers/swr/swr_context.h b/src/gallium/drivers/swr/swr_context.h
> index a7383bb..75ecae3 100644
> --- a/src/gallium/drivers/swr/swr_context.h
> +++ b/src/gallium/drivers/swr/swr_context.h
> @@ -89,6 +89,8 @@ struct swr_draw_context {
>    swr_jit_texture texturesFS[PIPE_MAX_SHADER_SAMPLER_VIEWS];
>    swr_jit_sampler samplersFS[PIPE_MAX_SAMPLERS];
> 
> +   float userClipPlanes[PIPE_MAX_CLIP_PLANES][4];
> +
>    SWR_SURFACE_STATE renderTargets[SWR_NUM_ATTACHMENTS];
> };
> 
> diff --git a/src/gallium/drivers/swr/swr_screen.cpp b/src/gallium/drivers/swr/swr_screen.cpp
> index ca39202..af82c93 100644
> --- a/src/gallium/drivers/swr/swr_screen.cpp
> +++ b/src/gallium/drivers/swr/swr_screen.cpp
> @@ -333,6 +333,8 @@ swr_get_param(struct pipe_screen *screen, enum pipe_cap param)
>    case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
>    case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
>       return 1;
> +   case PIPE_CAP_CULL_DISTANCE:
> +      return 1;
>    case PIPE_CAP_TGSI_TXQS:
>    case PIPE_CAP_FORCE_PERSAMPLE_INTERP:
>    case PIPE_CAP_SHAREABLE_SHADERS:
> @@ -358,7 +360,6 @@ swr_get_param(struct pipe_screen *screen, enum pipe_cap param)
>    case PIPE_CAP_PCI_DEVICE:
>    case PIPE_CAP_PCI_FUNCTION:
>    case PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT:
> -   case PIPE_CAP_CULL_DISTANCE:
>    case PIPE_CAP_PRIMITIVE_RESTART_FOR_PATCHES:
>    case PIPE_CAP_TGSI_VOTE:
>       return 0;
> diff --git a/src/gallium/drivers/swr/swr_shader.cpp b/src/gallium/drivers/swr/swr_shader.cpp
> index f26467e..8af0700 100644
> --- a/src/gallium/drivers/swr/swr_shader.cpp
> +++ b/src/gallium/drivers/swr/swr_shader.cpp
> @@ -40,6 +40,9 @@
> #include "swr_state.h"
> #include "swr_screen.h"
> 
> +static unsigned
> +locate_linkage(ubyte name, ubyte index, struct tgsi_shader_info *info);
> +
> bool operator==(const swr_jit_fs_key &lhs, const swr_jit_fs_key &rhs)
> {
>    return !memcmp(&lhs, &rhs, sizeof(lhs));
> @@ -119,6 +122,11 @@ swr_generate_vs_key(struct swr_jit_vs_key &key,
> {
>    memset(&key, 0, sizeof(key));
> 
> +   key.clip_plane_mask =
> +      swr_vs->info.base.clipdist_writemask ?
> +      swr_vs->info.base.clipdist_writemask & ctx->rasterizer->clip_plane_enable :
> +      ctx->rasterizer->clip_plane_enable;
> +
>    swr_generate_sampler_key(swr_vs->info, ctx, PIPE_SHADER_VERTEX, key);
> }
> 
> @@ -251,6 +259,63 @@ BuilderSWR::CompileVS(struct swr_context *ctx, swr_jit_vs_key &key)
>       }
>    }
> 
> +   if (ctx->rasterizer->clip_plane_enable ||
> +       swr_vs->info.base.culldist_writemask) {
> +      unsigned clip_mask = ctx->rasterizer->clip_plane_enable;
> +
> +      unsigned cv = 0;
> +      if (swr_vs->info.base.writes_clipvertex) {
> +         cv = 1 + locate_linkage(TGSI_SEMANTIC_CLIPVERTEX, 0,
> +                                 &swr_vs->info.base);
> +      } else {
> +         for (int i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
> +            if (swr_vs->info.base.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
> +                swr_vs->info.base.output_semantic_index[i] == 0) {
> +               cv = i;
> +               break;
> +            }
> +         }
> +      }
> +      LLVMValueRef cx = LLVMBuildLoad(gallivm->builder, outputs[cv][0], "");
> +      LLVMValueRef cy = LLVMBuildLoad(gallivm->builder, outputs[cv][1], "");
> +      LLVMValueRef cz = LLVMBuildLoad(gallivm->builder, outputs[cv][2], "");
> +      LLVMValueRef cw = LLVMBuildLoad(gallivm->builder, outputs[cv][3], "");
> +
> +      for (unsigned val = 0; val < PIPE_MAX_CLIP_PLANES; val++) {
> +         // clip distance overrides user clip planes
> +         if ((swr_vs->info.base.clipdist_writemask & clip_mask & (1 << val)) ||
> +             ((swr_vs->info.base.culldist_writemask << swr_vs->info.base.num_written_clipdistance) & (1 << val))) {
> +            unsigned cv = 1 + locate_linkage(TGSI_SEMANTIC_CLIPDIST, val < 4 ? 0 : 1,
> +                                             &swr_vs->info.base);
> +            if (val < 4) {
> +               LLVMValueRef dist = LLVMBuildLoad(gallivm->builder, outputs[cv][val], "");
> +               STORE(unwrap(dist), vtxOutput, {0, 0, VERTEX_CLIPCULL_DIST_LO_SLOT, val});
> +            } else {
> +               LLVMValueRef dist = LLVMBuildLoad(gallivm->builder, outputs[cv][val - 4], "");
> +               STORE(unwrap(dist), vtxOutput, {0, 0, VERTEX_CLIPCULL_DIST_HI_SLOT, val - 4});
> +            }
> +            continue;
> +         }
> +
> +         if (!(clip_mask & (1 << val)))
> +            continue;
> +
> +         Value *px = LOAD(GEP(hPrivateData, {0, swr_draw_context_userClipPlanes, val, 0}));
> +         Value *py = LOAD(GEP(hPrivateData, {0, swr_draw_context_userClipPlanes, val, 1}));
> +         Value *pz = LOAD(GEP(hPrivateData, {0, swr_draw_context_userClipPlanes, val, 2}));
> +         Value *pw = LOAD(GEP(hPrivateData, {0, swr_draw_context_userClipPlanes, val, 3}));
> +         Value *dist = FADD(FMUL(unwrap(cx), VBROADCAST(px)),
> +                            FADD(FMUL(unwrap(cy), VBROADCAST(py)),
> +                                 FADD(FMUL(unwrap(cz), VBROADCAST(pz)),
> +                                      FMUL(unwrap(cw), VBROADCAST(pw)))));
> +
> +         if (val < 4)
> +            STORE(dist, vtxOutput, {0, 0, VERTEX_CLIPCULL_DIST_LO_SLOT, val});
> +         else
> +            STORE(dist, vtxOutput, {0, 0, VERTEX_CLIPCULL_DIST_HI_SLOT, val - 4});
> +      }
> +   }
> +
>    RET_VOID();
> 
>    gallivm_verify_function(gallivm, wrap(pFunction));
> diff --git a/src/gallium/drivers/swr/swr_shader.h b/src/gallium/drivers/swr/swr_shader.h
> index 1b604b5..ccdda44 100644
> --- a/src/gallium/drivers/swr/swr_shader.h
> +++ b/src/gallium/drivers/swr/swr_shader.h
> @@ -56,6 +56,7 @@ struct swr_jit_fs_key : swr_jit_sampler_key {
> };
> 
> struct swr_jit_vs_key : swr_jit_sampler_key {
> +   unsigned clip_plane_mask; // from rasterizer state & vs_info
> };
> 
> namespace std
> diff --git a/src/gallium/drivers/swr/swr_state.cpp b/src/gallium/drivers/swr/swr_state.cpp
> index f50537f..3eeb98d 100644
> --- a/src/gallium/drivers/swr/swr_state.cpp
> +++ b/src/gallium/drivers/swr/swr_state.cpp
> @@ -849,7 +849,9 @@ swr_update_derived(struct pipe_context *pipe,
>    }
> 
>    /* Raster state */
> -   if (ctx->dirty & (SWR_NEW_RASTERIZER | SWR_NEW_FRAMEBUFFER)) {
> +   if (ctx->dirty & (SWR_NEW_RASTERIZER |
> +                     SWR_NEW_VS | // clipping
> +                     SWR_NEW_FRAMEBUFFER)) {
>       pipe_rasterizer_state *rasterizer = ctx->rasterizer;
>       pipe_framebuffer_state *fb = &ctx->framebuffer;
> 
> @@ -906,6 +908,14 @@ swr_update_derived(struct pipe_context *pipe,
> 
>       rastState->depthClipEnable = rasterizer->depth_clip;
> 
> +      rastState->clipDistanceMask =
> +         ctx->vs->info.base.num_written_clipdistance ?
> +         ctx->vs->info.base.clipdist_writemask & rasterizer->clip_plane_enable :
> +         rasterizer->clip_plane_enable;
> +
> +      rastState->cullDistanceMask =
> +         ctx->vs->info.base.culldist_writemask << ctx->vs->info.base.num_written_clipdistance;
> +
>       SwrSetRastState(ctx->swrContext, rastState);
>    }
> 
> @@ -1067,6 +1077,7 @@ swr_update_derived(struct pipe_context *pipe,
> 
>    /* VertexShader */
>    if (ctx->dirty & (SWR_NEW_VS |
> +                     SWR_NEW_RASTERIZER | // for clip planes
>                      SWR_NEW_SAMPLER |
>                      SWR_NEW_SAMPLER_VIEW |
>                      SWR_NEW_FRAMEBUFFER)) {
> @@ -1341,6 +1352,18 @@ swr_update_derived(struct pipe_context *pipe,
>       }
>    }
> 
> +   if (ctx->dirty & SWR_NEW_CLIP) {
> +      // shader exporting clip distances overrides all user clip planes
> +      if (ctx->rasterizer->clip_plane_enable &&
> +          !ctx->vs->info.base.num_written_clipdistance)
> +      {
> +         swr_draw_context *pDC = &ctx->swrDC;
> +         memcpy(pDC->userClipPlanes,
> +                ctx->clip.ucp,
> +                sizeof(pDC->userClipPlanes));
> +      }
> +   }
> +
>    uint32_t linkage = ctx->vs->linkageMask;
>    if (ctx->rasterizer->sprite_coord_enable)
>       linkage |= (1 << ctx->vs->info.base.num_outputs);
> -- 
> 1.9.1
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev



More information about the mesa-dev mailing list