swr: fix provoking vertex
authorTim Rowley <timothy.o.rowley@intel.com>
Wed, 1 Jun 2016 14:56:26 +0000 (09:56 -0500)
committerTim Rowley <timothy.o.rowley@intel.com>
Tue, 7 Jun 2016 16:47:52 +0000 (11:47 -0500)
Use rasterizer provoking vertex API.

Fix rasterizer provoking vertex for tristrips and quad list/strips.

v2: make provoking vertex tables static const

Reviewed-by: Bruce Cherniak <bruce.cherniak@intel.com>
src/gallium/drivers/swr/rasterizer/core/frontend.cpp
src/gallium/drivers/swr/swr_draw.cpp
src/gallium/drivers/swr/swr_screen.cpp
src/gallium/drivers/swr/swr_shader.cpp
src/gallium/drivers/swr/swr_shader.h
src/gallium/drivers/swr/swr_state.cpp
src/gallium/drivers/swr/swr_state.h

index ef90a24fe75d21af7ee1b9b1804f05afe5014e6d..6e1bc0e3d27c949cfc012050b3c02756ccce4fd2 100644 (file)
@@ -1467,6 +1467,7 @@ INLINE void ProcessAttributes(
     uint32_t mapIdx = 0;
     LONG constantInterpMask = pDC->pState->state.backendState.constantInterpolationMask;
     const uint32_t provokingVertex = pDC->pState->state.frontendState.topologyProvokingVertex;
+    const PRIMITIVE_TOPOLOGY topo = pDC->pState->state.topology;
 
     while (_BitScanForward(&slot, linkageMask))
     {
@@ -1476,18 +1477,51 @@ INLINE void ProcessAttributes(
         uint32_t inputSlot = VERTEX_ATTRIB_START_SLOT + pLinkageMap[mapIdx];
 
         __m128 attrib[3];    // triangle attribs (always 4 wide)
-        pa.AssembleSingle(inputSlot, triIndex, attrib);
 
         if (_bittest(&constantInterpMask, mapIdx))
         {
+            uint32_t vid;
+            static const uint32_t tristripProvokingVertex[] = {0, 2, 1};
+            static const int32_t quadProvokingTri[2][4] = {{0, 0, 0, 1}, {0, -1, 0, 0}};
+            static const uint32_t quadProvokingVertex[2][4] = {{0, 1, 2, 2}, {0, 1, 1, 2}};
+            static const int32_t qstripProvokingTri[2][4] = {{0, 0, 0, 1}, {-1, 0, 0, 0}};
+            static const uint32_t qstripProvokingVertex[2][4] = {{0, 1, 2, 1}, {0, 0, 2, 1}};
+
+            switch (topo) {
+            case TOP_QUAD_LIST:
+                pa.AssembleSingle(inputSlot,
+                                  triIndex + quadProvokingTri[triIndex & 1][provokingVertex],
+                                  attrib);
+                vid = quadProvokingVertex[triIndex & 1][provokingVertex];
+                break;
+            case TOP_QUAD_STRIP:
+                pa.AssembleSingle(inputSlot,
+                                  triIndex + qstripProvokingTri[triIndex & 1][provokingVertex],
+                                  attrib);
+                vid = qstripProvokingVertex[triIndex & 1][provokingVertex];
+                break;
+            case TOP_TRIANGLE_STRIP:
+               pa.AssembleSingle(inputSlot, triIndex, attrib);
+               vid = (triIndex & 1)
+                   ? tristripProvokingVertex[provokingVertex]
+                   : provokingVertex;
+               break;
+            default:
+                pa.AssembleSingle(inputSlot, triIndex, attrib);
+                vid = provokingVertex;
+                break;
+            }
+
             for (uint32_t i = 0; i < NumVerts; ++i)
             {
-                _mm_store_ps(pBuffer, attrib[provokingVertex]);
+                _mm_store_ps(pBuffer, attrib[vid]);
                 pBuffer += 4;
             }
         }
         else
         {
+            pa.AssembleSingle(inputSlot, triIndex, attrib);
+
             for (uint32_t i = 0; i < NumVerts; ++i)
             {
                 _mm_store_ps(pBuffer, attrib[i]);
index 7a4c89626fb14637f8a3aaf044b1851a2224f69a..ab8d275062334d6daf7251d566407fb0330ef6cc 100644 (file)
@@ -162,6 +162,36 @@ swr_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    /* Set up frontend state
     * XXX setup provokingVertex & topologyProvokingVertex */
    SWR_FRONTEND_STATE feState = {0};
+   if (ctx->rasterizer->flatshade_first) {
+      feState.provokingVertex = {1, 0, 0};
+   } else {
+      feState.provokingVertex = {2, 1, 2};
+   }
+
+   switch (info->mode) {
+   case PIPE_PRIM_TRIANGLE_FAN:
+      feState.topologyProvokingVertex = feState.provokingVertex.triFan;
+      break;
+   case PIPE_PRIM_TRIANGLE_STRIP:
+   case PIPE_PRIM_TRIANGLES:
+      feState.topologyProvokingVertex = feState.provokingVertex.triStripList;
+      break;
+   case PIPE_PRIM_QUAD_STRIP:
+   case PIPE_PRIM_QUADS:
+      if (ctx->rasterizer->flatshade_first)
+         feState.topologyProvokingVertex = 0;
+      else
+         feState.topologyProvokingVertex = 3;
+      break;
+   case PIPE_PRIM_LINES:
+   case PIPE_PRIM_LINE_LOOP:
+   case PIPE_PRIM_LINE_STRIP:
+      feState.topologyProvokingVertex = feState.provokingVertex.lineStripList;
+      break;
+   default:
+      feState.topologyProvokingVertex = 0;
+   }
+
    feState.bEnableCutIndex = info->primitive_restart;
    SwrSetFrontendState(ctx->swrContext, &feState);
 
index 361b17ac55bb7421a3d8c6f2df55ba160320834f..ca3920240fb380ee7d32de3a4286ef585788c445 100644 (file)
@@ -239,7 +239,7 @@ swr_get_param(struct pipe_screen *screen, enum pipe_cap param)
    case PIPE_CAP_GLSL_FEATURE_LEVEL:
       return 330;
    case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
-      return 0;
+      return 1;
    case PIPE_CAP_COMPUTE:
       return 0;
    case PIPE_CAP_USER_VERTEX_BUFFERS:
index f693f51bb496536d0b55387f22c2391ad2e15069..f26467e078e8f9e995679cafaa1b2faa06dd16f9 100644 (file)
@@ -102,7 +102,6 @@ swr_generate_fs_key(struct swr_jit_fs_key &key,
 
    key.nr_cbufs = ctx->framebuffer.nr_cbufs;
    key.light_twoside = ctx->rasterizer->light_twoside;
-   key.flatshade = ctx->rasterizer->flatshade;
    memcpy(&key.vs_output_semantic_name,
           &ctx->vs->info.base.output_semantic_name,
           sizeof(key.vs_output_semantic_name));
@@ -351,15 +350,13 @@ BuilderSWR::CompileFS(struct swr_context *ctx, swr_jit_fs_key &key)
       GEP(hPrivateData, {0, swr_draw_context_num_constantsFS});
    const_sizes_ptr->setName("num_fs_constants");
 
-   // xxx should check for flat shading versus interpolation
-
-
    // load *pAttribs, *pPerspAttribs
    Value *pRawAttribs = LOAD(pPS, {0, SWR_PS_CONTEXT_pAttribs}, "pRawAttribs");
    Value *pPerspAttribs =
       LOAD(pPS, {0, SWR_PS_CONTEXT_pPerspAttribs}, "pPerspAttribs");
 
    swr_fs->constantMask = 0;
+   swr_fs->flatConstantMask = 0;
    swr_fs->pointSpriteMask = 0;
 
    for (int attrib = 0; attrib < PIPE_MAX_SHADER_INPUTS; attrib++) {
@@ -457,6 +454,8 @@ BuilderSWR::CompileFS(struct swr_context *ctx, swr_jit_fs_key &key)
 
       if (interpMode == TGSI_INTERPOLATE_CONSTANT) {
          swr_fs->constantMask |= 1 << linkedAttrib;
+      } else if (interpMode == TGSI_INTERPOLATE_COLOR) {
+         swr_fs->flatConstantMask |= 1 << linkedAttrib;
       }
 
       for (int channel = 0; channel < TGSI_NUM_CHANNELS; channel++) {
@@ -484,6 +483,8 @@ BuilderSWR::CompileFS(struct swr_context *ctx, swr_jit_fs_key &key)
 
                if (interpMode == TGSI_INTERPOLATE_CONSTANT) {
                   swr_fs->constantMask |= 1 << bcolorAttrib;
+               } else if (interpMode == TGSI_INTERPOLATE_COLOR) {
+                  swr_fs->flatConstantMask |= 1 << bcolorAttrib;
                }
             }
 
@@ -493,9 +494,6 @@ BuilderSWR::CompileFS(struct swr_context *ctx, swr_jit_fs_key &key)
 
             if (interpMode == TGSI_INTERPOLATE_CONSTANT) {
                inputs[attrib][channel] = wrap(va);
-            } else if ((interpMode == TGSI_INTERPOLATE_COLOR) &&
-                       (key.flatshade == true)) {
-               inputs[attrib][channel] = wrap(vc);
             } else {
                Value *vk = FSUB(FSUB(VIMMED1(1.0f), vi), vj);
 
index 11d50c3848fb70bdd362c174fc3bfb4713dda859..1b604b5a3c235848f70e00a50d30524a6a559f69 100644 (file)
@@ -51,7 +51,6 @@ struct swr_jit_sampler_key {
 struct swr_jit_fs_key : swr_jit_sampler_key {
    unsigned nr_cbufs;
    unsigned light_twoside;
-   unsigned flatshade;
    ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
    ubyte vs_output_semantic_idx[PIPE_MAX_SHADER_OUTPUTS];
 };
index f9326f352308cdcb641290556010453a623ef9a5..f50537f3a61018361768636c096995269ff26ab2 100644 (file)
@@ -1351,7 +1351,10 @@ swr_update_derived(struct pipe_context *pipe,
    SWR_BACKEND_STATE backendState = {0};
    backendState.numAttributes = 1;
    backendState.numComponents[0] = 4;
-   backendState.constantInterpolationMask = ctx->fs->constantMask;
+   backendState.constantInterpolationMask =
+      ctx->rasterizer->flatshade ?
+      ctx->fs->flatConstantMask :
+      ctx->fs->constantMask;
    backendState.pointSpriteTexCoordMask = ctx->fs->pointSpriteMask;
 
    SwrSetBackendState(ctx->swrContext, &backendState);
index 82ee20f73c1451d90ed007196055226da346c62a..cb69964127476a8af72e10426c31fd97fac5fd00 100644 (file)
@@ -63,6 +63,7 @@ struct swr_fragment_shader {
    struct pipe_shader_state pipe;
    struct lp_tgsi_info info;
    uint32_t constantMask;
+   uint32_t flatConstantMask;
    uint32_t pointSpriteMask;
    std::unordered_map<swr_jit_fs_key, std::unique_ptr<VariantFS>> map;
 };