[Mesa-dev] [PATCH] swr: Add polygon stipple support

Kyriazis, George george.kyriazis at intel.com
Fri Apr 14 18:52:49 UTC 2017


On Apr 14, 2017, at 11:35 AM, Ilia Mirkin <imirkin at alum.mit.edu<mailto:imirkin at alum.mit.edu>> wrote:

On Fri, Apr 14, 2017 at 11:18 AM, Ilia Mirkin <imirkin at alum.mit.edu<mailto:imirkin at alum.mit.edu>> wrote:
On Thu, Apr 13, 2017 at 4:30 PM, George Kyriazis
<george.kyriazis at intel.com<mailto:george.kyriazis at intel.com>> wrote:
Add polygon stipple functionality to the fragment shader.

Explicitly turn off polygon stipple for lines and points, since we
do them using tris.
---
src/gallium/drivers/swr/swr_context.h  |  4 ++-
src/gallium/drivers/swr/swr_shader.cpp | 56 ++++++++++++++++++++++++++++++----
src/gallium/drivers/swr/swr_shader.h   |  1 +
src/gallium/drivers/swr/swr_state.cpp  | 27 ++++++++++++++--
src/gallium/drivers/swr/swr_state.h    |  5 +++
5 files changed, 84 insertions(+), 9 deletions(-)

diff --git a/src/gallium/drivers/swr/swr_context.h b/src/gallium/drivers/swr/swr_context.h
index be65a20..9d80c70 100644
--- a/src/gallium/drivers/swr/swr_context.h
+++ b/src/gallium/drivers/swr/swr_context.h
@@ -98,6 +98,8 @@ struct swr_draw_context {

   float userClipPlanes[PIPE_MAX_CLIP_PLANES][4];

+   uint32_t polyStipple[32];
+
   SWR_SURFACE_STATE renderTargets[SWR_NUM_ATTACHMENTS];
   void *pStats;
};
@@ -127,7 +129,7 @@ struct swr_context {
   struct pipe_constant_buffer
      constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
   struct pipe_framebuffer_state framebuffer;
-   struct pipe_poly_stipple poly_stipple;
+   struct swr_poly_stipple poly_stipple;
   struct pipe_scissor_state scissor;
   SWR_RECT swr_scissor;
   struct pipe_sampler_view *
diff --git a/src/gallium/drivers/swr/swr_shader.cpp b/src/gallium/drivers/swr/swr_shader.cpp
index 6fc0596..d8f5512 100644
--- a/src/gallium/drivers/swr/swr_shader.cpp
+++ b/src/gallium/drivers/swr/swr_shader.cpp
@@ -165,6 +165,9 @@ swr_generate_fs_key(struct swr_jit_fs_key &key,
          sizeof(key.vs_output_semantic_idx));

   swr_generate_sampler_key(swr_fs->info, ctx, PIPE_SHADER_FRAGMENT, key);
+
+   key.poly_stipple_enable = ctx->rasterizer->poly_stipple_enable &&
+      ctx->poly_stipple.prim_is_poly;
}

void
@@ -1099,17 +1102,58 @@ BuilderSWR::CompileFS(struct swr_context *ctx, swr_jit_fs_key &key)
   memset(&system_values, 0, sizeof(system_values));

   struct lp_build_mask_context mask;
+   bool uses_mask = false;

-   if (swr_fs->info.base.uses_kill) {
-      Value *mask_val = LOAD(pPS, {0, SWR_PS_CONTEXT_activeMask}, "activeMask");
+   if (swr_fs->info.base.uses_kill ||
+       key.poly_stipple_enable) {
+      Value *vActiveMask = NULL;
+      if (swr_fs->info.base.uses_kill) {
+         vActiveMask = LOAD(pPS, {0, SWR_PS_CONTEXT_activeMask}, "activeMask");
+      }
+      if (key.poly_stipple_enable) {
+         // first get fragment xy coords and clip to stipple bounds
+         Value *vXf = LOAD(pPS, {0, SWR_PS_CONTEXT_vX, PixelPositions_UL});
+         Value *vYf = LOAD(pPS, {0, SWR_PS_CONTEXT_vY, PixelPositions_UL});
+         Value *vXu = FP_TO_UI(vXf, mSimdInt32Ty);
+         Value *vYu = FP_TO_UI(vYf, mSimdInt32Ty);
+
+         // stipple pattern is 32x32, which means that one line of stipple
+         // is stored in one word:
+         // vXstipple is bit offset inside 32-bit stipple word
+         // vYstipple is word index is stipple array
+         Value *vXstipple = AND(vXu, VIMMED1(0x1f)); // & (32-1)
+         Value *vYstipple = AND(vYu, VIMMED1(0x1f)); // & (32-1)
+
+         // grab stipple pattern base address
+         Value *stipplePtr = GEP(hPrivateData, {0, swr_draw_context_polyStipple, 0});
+         stipplePtr = BITCAST(stipplePtr, mInt8PtrTy);
+
+         // peform a gather to grab stipple words for each lane
+         Value *vStipple = GATHERDD(VUNDEF_I(), stipplePtr, vYstipple,
+                                    VIMMED1(0xffffffff), C((char)4));
+
+         // create a mask with one bit corresponding to the x stipple
+         // and AND it with the pattern, to see if we have a bit
+         Value *vBitMask = LSHR(VIMMED1(0x80000000), vXstipple);
+         Value *vStippleMask = AND(vStipple, vBitMask);
+         vStippleMask = ICMP_NE(vStippleMask, VIMMED1(0));
+         vStippleMask = VMASK(vStippleMask);
+
+         if (swr_fs->info.base.uses_kill) {
+            vActiveMask = AND(vActiveMask, vStippleMask);
+         } else {
+            vActiveMask = vStippleMask;
+         }
+      }
      lp_build_mask_begin(
-         &mask, gallivm, lp_type_float_vec(32, 32 * 8), wrap(mask_val));
+         &mask, gallivm, lp_type_float_vec(32, 32 * 8), wrap(vActiveMask));
+      uses_mask = true;
   }

   lp_build_tgsi_soa(gallivm,
                     swr_fs->pipe.tokens,
                     lp_type_float_vec(32, 32 * 8),
-                     swr_fs->info.base.uses_kill ? &mask : NULL, // mask
+                     uses_mask ? &mask : NULL, // mask
                     wrap(consts_ptr),
                     wrap(const_sizes_ptr),
                     &system_values,
@@ -1172,13 +1216,13 @@ BuilderSWR::CompileFS(struct swr_context *ctx, swr_jit_fs_key &key)
   }

   LLVMValueRef mask_result = 0;
-   if (swr_fs->info.base.uses_kill) {
+   if (uses_mask) {
      mask_result = lp_build_mask_end(&mask);
   }

   IRB()->SetInsertPoint(unwrap(LLVMGetInsertBlock(gallivm->builder)));

-   if (swr_fs->info.base.uses_kill) {
+   if (uses_mask) {
      STORE(unwrap(mask_result), pPS, {0, SWR_PS_CONTEXT_activeMask});
   }

diff --git a/src/gallium/drivers/swr/swr_shader.h b/src/gallium/drivers/swr/swr_shader.h
index c9df5b0..1ab6846 100644
--- a/src/gallium/drivers/swr/swr_shader.h
+++ b/src/gallium/drivers/swr/swr_shader.h
@@ -66,6 +66,7 @@ struct swr_jit_fs_key : swr_jit_sampler_key {
   unsigned sprite_coord_enable;
   ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
   ubyte vs_output_semantic_idx[PIPE_MAX_SHADER_OUTPUTS];
+   bool poly_stipple_enable;
};

struct swr_jit_vs_key : swr_jit_sampler_key {
diff --git a/src/gallium/drivers/swr/swr_state.cpp b/src/gallium/drivers/swr/swr_state.cpp
index 5cc01dd..4f7ef66 100644
--- a/src/gallium/drivers/swr/swr_state.cpp
+++ b/src/gallium/drivers/swr/swr_state.cpp
@@ -39,6 +39,7 @@
#include "util/u_helpers.h"
#include "util/u_framebuffer.h"
#include "util/u_viewport.h"
+#include "util/u_prim.h"

#include "swr_state.h"
#include "swr_context.h"
@@ -608,7 +609,7 @@ swr_set_polygon_stipple(struct pipe_context *pipe,
{
   struct swr_context *ctx = swr_context(pipe);

-   ctx->poly_stipple = *stipple; /* struct copy */
+   ctx->poly_stipple.pipe = *stipple; /* struct copy */
   ctx->dirty |= SWR_NEW_STIPPLE;
}

@@ -952,6 +953,17 @@ swr_user_vbuf_range(const struct pipe_draw_info *info,
   }
}

+static void
+swr_update_poly_stipple(struct swr_context *ctx)
+{
+   struct swr_draw_context *pDC = &ctx->swrDC;
+
+   assert(sizeof(ctx->poly_stipple.pipe.stipple) == sizeof(pDC->polyStipple));
+   memcpy(pDC->polyStipple,
+          ctx->poly_stipple.pipe.stipple,
+          sizeof(ctx->poly_stipple.pipe.stipple));
+}
+
void
swr_update_derived(struct pipe_context *pipe,
                   const struct pipe_draw_info *p_draw_info)
@@ -1352,6 +1364,17 @@ swr_update_derived(struct pipe_context *pipe,
      }
   }

+   /* work around the fact that poly stipple also affects lines */
+   /* and points, since we rasterize them as triangles, too */
+   /* Has to be before fragment shader, since it sets SWR_NEW_FS */
+   if (p_draw_info) {
+      bool new_prim_is_poly = (u_reduced_prim(p_draw_info->mode) == PIPE_PRIM_TRIANGLES);

What about glPolygonMode and what about geometry shaders that take in
e.g. points and put out triangles? Perhaps you need to pass in a "is
this *really* a triangle" parameter to the shader generated by the
rasterizer.

Actually the GS thing won't happen since polygon stippling is a
compat-only feature and we don't support GS in compat profiles. You do
need to check that the polymode == FILL here though.

Well, currently we don’t have a working polygon mode.  Once we implement it, then we’ll look at stipple at that time.

Also it might be easy to just do all this masking directly in core
instead of as a frag shader variant implemented in swr_shader...

I still think this would be a better place. Note that line stippling
is also a thing.

We will consider pushing the implementation in the core, if we hear concerns regarding performance the way it’s currently implemented.  There are some other discussions that we need to do (internally) before moving it up in the core.

Regarding line stipple.  Yes, we have that in mind.  However, the right time to do this is when we get an actual line rasterizer, which is also in our list.  Currently we rasterize lines as triangles, with obvious side effects in line rasterization quality and precision.

Thanks for the feedback,

George


Cheers,

 -ilia
_______________________________________________
mesa-dev mailing list
mesa-dev at lists.freedesktop.org<mailto:mesa-dev at lists.freedesktop.org>
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170414/c548febd/attachment-0001.html>


More information about the mesa-dev mailing list