summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Rowley <[email protected]>2018-01-03 11:58:50 -0600
committerTim Rowley <[email protected]>2018-01-10 09:44:07 -0600
commit3d4d34e380f33e9daa86ff3aa4c06a56c5fa1318 (patch)
treedcbb499fc4ba04032a861291f6cc491a0fa29f17
parentf5f1bbcb5c66c55a45e47c71685ca6709b714390 (diff)
swr/rast: don't use 32-bit gathers for elements < 32-bits in size
Using a gather for elements less than 32-bits in size can cause pagefaults when loading the last elements in a page-aligned-sized buffer. Reviewed-by: Bruce Cherniak <[email protected]>
-rw-r--r--src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp61
1 files changed, 60 insertions, 1 deletions
diff --git a/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp b/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp
index 99a936d1760..ad70cbe95d3 100644
--- a/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp
+++ b/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp
@@ -741,7 +741,66 @@ void FetchJit::CreateGatherOddFormats(SWR_FORMAT format, Value* pMask, Value* pB
// only works if pixel size is <= 32bits
SWR_ASSERT(info.bpp <= 32);
- Value *pGather = GATHERDD(VIMMED1(0), pBase, pOffsets, pMask);
+ Value *pGather;
+ if (info.bpp == 32)
+ {
+ pGather = GATHERDD(VIMMED1(0), pBase, pOffsets, pMask);
+ }
+ else
+ {
+ // Can't use 32-bit gather for items less than 32-bits, could cause page faults.
+ Value *pMem = ALLOCA(mSimdInt32Ty);
+ STORE(VIMMED1(0u), pMem);
+
+ pBase = BITCAST(pBase, PointerType::get(mInt8Ty, 0));
+ Value* pDstMem = BITCAST(pMem, mInt32PtrTy);
+
+ for (uint32_t lane = 0; lane < mVWidth; ++lane)
+ {
+ // Get index
+ Value* index = VEXTRACT(pOffsets, C(lane));
+ Value* mask = VEXTRACT(pMask, C(lane));
+ switch (info.bpp)
+ {
+ case 8:
+ {
+ Value* pDst = BITCAST(GEP(pDstMem, C(lane)), PointerType::get(mInt8Ty, 0));
+ Value* pSrc = BITCAST(GEP(pBase, index), PointerType::get(mInt8Ty, 0));
+ STORE(LOAD(SELECT(mask, pSrc, pDst)), pDst);
+ break;
+ }
+
+ case 16:
+ {
+ Value* pDst = BITCAST(GEP(pDstMem, C(lane)), PointerType::get(mInt16Ty, 0));
+ Value* pSrc = BITCAST(GEP(pBase, index), PointerType::get(mInt16Ty, 0));
+ STORE(LOAD(SELECT(mask, pSrc, pDst)), pDst);
+ break;
+ }
+ break;
+
+ case 24:
+ {
+ // First 16-bits of data
+ Value* pDst = BITCAST(GEP(pDstMem, C(lane)), PointerType::get(mInt16Ty, 0));
+ Value* pSrc = BITCAST(GEP(pBase, index), PointerType::get(mInt16Ty, 0));
+ STORE(LOAD(SELECT(mask, pSrc, pDst)), pDst);
+
+ // Last 8-bits of data
+ pDst = BITCAST(GEP(pDst, C(1)), PointerType::get(mInt8Ty, 0));
+ pSrc = BITCAST(GEP(pSrc, C(1)), PointerType::get(mInt8Ty, 0));
+ STORE(LOAD(SELECT(mask, pSrc, pDst)), pDst);
+ break;
+ }
+
+ default:
+ SWR_INVALID("Shouldn't have BPP = %d now", info.bpp);
+ break;
+ }
+ }
+
+ pGather = LOAD(pMem);
+ }
for (uint32_t comp = 0; comp < 4; ++comp)
{