From 7c3ca2e704801af1119999473a505335a2749bf6 Mon Sep 17 00:00:00 2001 From: Tim Rowley Date: Mon, 7 Nov 2016 15:23:09 -0600 Subject: [PATCH] swr: [rasterizer core] fix culling issues - Do proper culling of wireframe triangles (including non-culling of degenerates) - Fix degenerate culling of CCW front-facing triangles in wireframe and conservative rast Reviewed-by: Bruce Cherniak --- .../drivers/swr/rasterizer/core/binner.cpp | 185 +++++++++++------- 1 file changed, 119 insertions(+), 66 deletions(-) diff --git a/src/gallium/drivers/swr/rasterizer/core/binner.cpp b/src/gallium/drivers/swr/rasterizer/core/binner.cpp index f015f21d837..6f9259fcf66 100644 --- a/src/gallium/drivers/swr/rasterizer/core/binner.cpp +++ b/src/gallium/drivers/swr/rasterizer/core/binner.cpp @@ -34,6 +34,9 @@ #include "rdtsc_core.h" #include "tilemgr.h" +// Function Prototype +void BinPostSetupLines(DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prims[3], simdscalar vRecipW[2], uint32_t primMask, simdscalari primID, simdscalari viewportIdx); + ////////////////////////////////////////////////////////////////////////// /// @brief Offsets added to post-viewport vertex positions based on /// raster state. @@ -447,27 +450,6 @@ void BinTriangles( const SWR_GS_STATE& gsState = state.gsState; MacroTileMgr *pTileMgr = pDC->pTileMgr; - // Simple non-conformant wireframe mode, useful for debugging - if (rastState.fillMode == SWR_FILLMODE_WIREFRAME) - { - // construct 3 SIMD lines out of the triangle and call the line binner for each SIMD - simdvector line[2]; - line[0] = tri[0]; - line[1] = tri[1]; - BinLines(pDC, pa, workerId, line, triMask, primID, viewportIdx); - - line[0] = tri[1]; - line[1] = tri[2]; - BinLines(pDC, pa, workerId, line, triMask, primID, viewportIdx); - - line[0] = tri[2]; - line[1] = tri[0]; - BinLines(pDC, pa, workerId, line, triMask, primID, viewportIdx); - - AR_END(FEBinTriangles, 1); - return; - } - simdscalar vRecipW0 = _simd_set1_ps(1.0f); simdscalar vRecipW1 = _simd_set1_ps(1.0f); simdscalar vRecipW2 = _simd_set1_ps(1.0f); @@ -540,27 +522,28 @@ void BinTriangles( uint32_t origTriMask = triMask; // don't cull degenerate triangles if we're conservatively rasterizing - if (!CT::IsConservativeT::value) + if (rastState.fillMode == SWR_FILLMODE_SOLID && !CT::IsConservativeT::value) { triMask &= ~cullZeroAreaMask; } // determine front winding tris // CW +det - // CCW det <= 0; 0 area triangles are marked as backfacing, which is required behavior for conservative rast - maskLo = _simd_movemask_pd(_simd_castsi_pd(_simd_cmpgt_epi64(vDet[0], _simd_setzero_si()))); - maskHi = _simd_movemask_pd(_simd_castsi_pd(_simd_cmpgt_epi64(vDet[1], _simd_setzero_si()))); - int cwTriMask = maskLo | (maskHi << (KNOB_SIMD_WIDTH / 2)); - + // CCW det < 0; + // 0 area triangles are marked as backfacing regardless of winding order, + // which is required behavior for conservative rast and wireframe rendering uint32_t frontWindingTris; if (rastState.frontWinding == SWR_FRONTWINDING_CW) { - frontWindingTris = cwTriMask; + maskLo = _simd_movemask_pd(_simd_castsi_pd(_simd_cmpgt_epi64(vDet[0], _simd_setzero_si()))); + maskHi = _simd_movemask_pd(_simd_castsi_pd(_simd_cmpgt_epi64(vDet[1], _simd_setzero_si()))); } else { - frontWindingTris = ~cwTriMask; + maskLo = _simd_movemask_pd(_simd_castsi_pd(_simd_cmpgt_epi64(_simd_setzero_si(), vDet[0]))); + maskHi = _simd_movemask_pd(_simd_castsi_pd(_simd_cmpgt_epi64(_simd_setzero_si(), vDet[1]))); } + frontWindingTris = maskLo | (maskHi << (KNOB_SIMD_WIDTH / 2)); // cull uint32_t cullTris; @@ -581,6 +564,34 @@ void BinTriangles( RDTSC_EVENT(FECullZeroAreaAndBackface, _mm_popcnt_u32(origTriMask ^ triMask), 0); } + // Simple non-conformant wireframe mode, useful for debugging + if (rastState.fillMode == SWR_FILLMODE_WIREFRAME) + { + // construct 3 SIMD lines out of the triangle and call the line binner for each SIMD + simdvector line[2]; + simdscalar recipW[2]; + line[0] = tri[0]; + line[1] = tri[1]; + recipW[0] = vRecipW0; + recipW[1] = vRecipW1; + BinPostSetupLines(pDC, pa, workerId, line, recipW, triMask, primID, viewportIdx); + + line[0] = tri[1]; + line[1] = tri[2]; + recipW[0] = vRecipW1; + recipW[1] = vRecipW2; + BinPostSetupLines(pDC, pa, workerId, line, recipW, triMask, primID, viewportIdx); + + line[0] = tri[2]; + line[1] = tri[0]; + recipW[0] = vRecipW2; + recipW[1] = vRecipW0; + BinPostSetupLines(pDC, pa, workerId, line, recipW, triMask, primID, viewportIdx); + + AR_END(FEBinTriangles, 1); + return; + } + /// Note: these variable initializations must stay above any 'goto endBenTriangles' // compute per tri backface uint32_t frontFaceMask = frontWindingTris; @@ -1206,11 +1217,12 @@ void BinPoints( /// @param tri - Contains line position data for SIMDs worth of points. /// @param primID - Primitive ID for each line. /// @param viewportIdx - Viewport Array Index for each line. -void BinLines( +void BinPostSetupLines( DRAW_CONTEXT *pDC, PA_STATE& pa, uint32_t workerId, simdvector prim[], + simdscalar recipW[], uint32_t primMask, simdscalari primID, simdscalari viewportIdx) @@ -1228,42 +1240,8 @@ void BinLines( PFN_PROCESS_ATTRIBUTES pfnProcessAttribs = GetProcessAttributesFunc(2, state.backendState.swizzleEnable, state.backendState.constantInterpolationMask); - simdscalar vRecipW0 = _simd_set1_ps(1.0f); - simdscalar vRecipW1 = _simd_set1_ps(1.0f); - - if (!feState.vpTransformDisable) - { - // perspective divide - vRecipW0 = _simd_div_ps(_simd_set1_ps(1.0f), prim[0].w); - vRecipW1 = _simd_div_ps(_simd_set1_ps(1.0f), prim[1].w); - - prim[0].v[0] = _simd_mul_ps(prim[0].v[0], vRecipW0); - prim[1].v[0] = _simd_mul_ps(prim[1].v[0], vRecipW1); - - prim[0].v[1] = _simd_mul_ps(prim[0].v[1], vRecipW0); - prim[1].v[1] = _simd_mul_ps(prim[1].v[1], vRecipW1); - - prim[0].v[2] = _simd_mul_ps(prim[0].v[2], vRecipW0); - prim[1].v[2] = _simd_mul_ps(prim[1].v[2], vRecipW1); - - // viewport transform to screen coords - if (state.gsState.emitsViewportArrayIndex) - { - viewportTransform<2>(prim, state.vpMatrices, viewportIdx); - } - else - { - viewportTransform<2>(prim, state.vpMatrices); - } - } - - // adjust for pixel center location - simdscalar offset = g_pixelOffsets[rastState.pixelLocation]; - prim[0].x = _simd_add_ps(prim[0].x, offset); - prim[0].y = _simd_add_ps(prim[0].y, offset); - - prim[1].x = _simd_add_ps(prim[1].x, offset); - prim[1].y = _simd_add_ps(prim[1].y, offset); + simdscalar& vRecipW0 = recipW[0]; + simdscalar& vRecipW1 = recipW[1]; // convert to fixed point simdscalari vXi[2], vYi[2]; @@ -1442,3 +1420,78 @@ endBinLines: AR_END(FEBinLines, 1); } + +////////////////////////////////////////////////////////////////////////// +/// @brief Bin SIMD lines to the backend. +/// @param pDC - pointer to draw context. +/// @param pa - The primitive assembly object. +/// @param workerId - thread's worker id. Even thread has a unique id. +/// @param tri - Contains line position data for SIMDs worth of points. +/// @param primID - Primitive ID for each line. +/// @param viewportIdx - Viewport Array Index for each line. +void BinLines( + DRAW_CONTEXT *pDC, + PA_STATE& pa, + uint32_t workerId, + simdvector prim[], + uint32_t primMask, + simdscalari primID, + simdscalari viewportIdx) +{ + SWR_CONTEXT *pContext = pDC->pContext; + + const API_STATE& state = GetApiState(pDC); + const SWR_RASTSTATE& rastState = state.rastState; + const SWR_FRONTEND_STATE& feState = state.frontendState; + const SWR_GS_STATE& gsState = state.gsState; + + // Select attribute processor + PFN_PROCESS_ATTRIBUTES pfnProcessAttribs = GetProcessAttributesFunc(2, + state.backendState.swizzleEnable, state.backendState.constantInterpolationMask); + + simdscalar vRecipW[2] = { _simd_set1_ps(1.0f), _simd_set1_ps(1.0f) }; + + if (!feState.vpTransformDisable) + { + // perspective divide + vRecipW[0] = _simd_div_ps(_simd_set1_ps(1.0f), prim[0].w); + vRecipW[1] = _simd_div_ps(_simd_set1_ps(1.0f), prim[1].w); + + prim[0].v[0] = _simd_mul_ps(prim[0].v[0], vRecipW[0]); + prim[1].v[0] = _simd_mul_ps(prim[1].v[0], vRecipW[1]); + + prim[0].v[1] = _simd_mul_ps(prim[0].v[1], vRecipW[0]); + prim[1].v[1] = _simd_mul_ps(prim[1].v[1], vRecipW[1]); + + prim[0].v[2] = _simd_mul_ps(prim[0].v[2], vRecipW[0]); + prim[1].v[2] = _simd_mul_ps(prim[1].v[2], vRecipW[1]); + + // viewport transform to screen coords + if (state.gsState.emitsViewportArrayIndex) + { + viewportTransform<2>(prim, state.vpMatrices, viewportIdx); + } + else + { + viewportTransform<2>(prim, state.vpMatrices); + } + } + + // adjust for pixel center location + simdscalar offset = g_pixelOffsets[rastState.pixelLocation]; + prim[0].x = _simd_add_ps(prim[0].x, offset); + prim[0].y = _simd_add_ps(prim[0].y, offset); + + prim[1].x = _simd_add_ps(prim[1].x, offset); + prim[1].y = _simd_add_ps(prim[1].y, offset); + + BinPostSetupLines( + pDC, + pa, + workerId, + prim, + vRecipW, + primMask, + primID, + viewportIdx); +} -- 2.30.2