Re: [Mesa-dev] [PATCH 2/2] [swr] fix index buffers with non-zero indices
Reviewed-by: Bruce Cherniak> On Feb 17, 2017, at 2:30 PM, George Kyriazis > wrote: > > Fix issue with index buffers that do not contain a 0 index. 0 index > can be a non-valid index if the (copied) vertex buffers are a subset of the > user's (which happens because we only copy the range between min & max). > Core will use an index passed in from the driver to replace invalid indices. > > Only do this for calls that contain non-zero indices, to minimize performance > cost. > --- > src/gallium/drivers/swr/rasterizer/core/state.h| 1 + > .../drivers/swr/rasterizer/jitter/fetch_jit.cpp| 60 +++--- > .../drivers/swr/rasterizer/jitter/fetch_jit.h | 2 + > src/gallium/drivers/swr/swr_draw.cpp | 1 + > src/gallium/drivers/swr/swr_state.cpp | 4 ++ > 5 files changed, 62 insertions(+), 6 deletions(-) > > diff --git a/src/gallium/drivers/swr/rasterizer/core/state.h > b/src/gallium/drivers/swr/rasterizer/core/state.h > index 2f3b913..05347dc 100644 > --- a/src/gallium/drivers/swr/rasterizer/core/state.h > +++ b/src/gallium/drivers/swr/rasterizer/core/state.h > @@ -524,6 +524,7 @@ struct SWR_VERTEX_BUFFER_STATE > const uint8_t *pData; > uint32_t size; > uint32_t numaNode; > +uint32_t minVertex; // min vertex (for bounds checking) > uint32_t maxVertex; // size / pitch. precalculated value > used by fetch shader for OOB checks > uint32_t partialInboundsSize; // size % pitch. precalculated value > used by fetch shader for partially OOB vertices > }; > diff --git a/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp > b/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp > index 901bce6..ffa7605 100644 > --- a/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp > +++ b/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp > @@ -309,11 +309,29 @@ void FetchJit::JitLoadVertices(const > FETCH_COMPILE_STATE , Value* str > > Value* startVertexOffset = MUL(Z_EXT(startOffset, mInt64Ty), stride); > > +Value *minVertex = NULL; > +Value *minVertexOffset = NULL; > +if (fetchState.bPartialVertexBuffer) { > +// fetch min index for low bounds checking > +minVertex = GEP(streams, {C(ied.StreamIndex), > C(SWR_VERTEX_BUFFER_STATE_minVertex)}); > +minVertex = LOAD(minVertex); > +if (!fetchState.bDisableIndexOOBCheck) { > +minVertexOffset = MUL(Z_EXT(minVertex, mInt64Ty), stride); > +} > +} > + > // Load from the stream. > for(uint32_t lane = 0; lane < mVWidth; ++lane) > { > // Get index > Value* index = VEXTRACT(vCurIndices, C(lane)); > + > +if (fetchState.bPartialVertexBuffer) { > +// clamp below minvertex > +Value *isBelowMin = ICMP_SLT(index, minVertex); > +index = SELECT(isBelowMin, minVertex, index); > +} > + > index = Z_EXT(index, mInt64Ty); > > Value*offset = MUL(index, stride); > @@ -321,10 +339,14 @@ void FetchJit::JitLoadVertices(const > FETCH_COMPILE_STATE , Value* str > offset = ADD(offset, startVertexOffset); > > if (!fetchState.bDisableIndexOOBCheck) { > -// check for out of bound access, including partial OOB, and > mask them to 0 > +// check for out of bound access, including partial OOB, and > replace them with minVertex > Value *endOffset = ADD(offset, C((int64_t)info.Bpp)); > Value *oob = ICMP_ULE(endOffset, size); > -offset = SELECT(oob, offset, ConstantInt::get(mInt64Ty, 0)); > +if (fetchState.bPartialVertexBuffer) { > +offset = SELECT(oob, offset, minVertexOffset); > +} else { > +offset = SELECT(oob, offset, ConstantInt::get(mInt64Ty, > 0)); > +} > } > > Value*pointer = GEP(stream, offset); > @@ -732,6 +754,13 @@ void FetchJit::JitGatherVertices(const > FETCH_COMPILE_STATE , > Value *maxVertex = GEP(streams, {C(ied.StreamIndex), > C(SWR_VERTEX_BUFFER_STATE_maxVertex)}); > maxVertex = LOAD(maxVertex); > > +Value *minVertex = NULL; > +if (fetchState.bPartialVertexBuffer) { > +// min vertex index for low bounds OOB checking > +minVertex = GEP(streams, {C(ied.StreamIndex), > C(SWR_VERTEX_BUFFER_STATE_minVertex)}); > +minVertex = LOAD(minVertex); > +} > + > Value *vCurIndices; > Value *startOffset; > if(ied.InstanceEnable) > @@ -769,9 +798,16 @@ void FetchJit::JitGatherVertices(const > FETCH_COMPILE_STATE , > > // if we have a start offset, subtract from max vertex. Used for OOB > check > maxVertex = SUB(Z_EXT(maxVertex, mInt64Ty),
[Mesa-dev] [PATCH 2/2] [swr] fix index buffers with non-zero indices
Fix issue with index buffers that do not contain a 0 index. 0 index can be a non-valid index if the (copied) vertex buffers are a subset of the user's (which happens because we only copy the range between min & max). Core will use an index passed in from the driver to replace invalid indices. Only do this for calls that contain non-zero indices, to minimize performance cost. --- src/gallium/drivers/swr/rasterizer/core/state.h| 1 + .../drivers/swr/rasterizer/jitter/fetch_jit.cpp| 60 +++--- .../drivers/swr/rasterizer/jitter/fetch_jit.h | 2 + src/gallium/drivers/swr/swr_draw.cpp | 1 + src/gallium/drivers/swr/swr_state.cpp | 4 ++ 5 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/gallium/drivers/swr/rasterizer/core/state.h b/src/gallium/drivers/swr/rasterizer/core/state.h index 2f3b913..05347dc 100644 --- a/src/gallium/drivers/swr/rasterizer/core/state.h +++ b/src/gallium/drivers/swr/rasterizer/core/state.h @@ -524,6 +524,7 @@ struct SWR_VERTEX_BUFFER_STATE const uint8_t *pData; uint32_t size; uint32_t numaNode; +uint32_t minVertex; // min vertex (for bounds checking) uint32_t maxVertex; // size / pitch. precalculated value used by fetch shader for OOB checks uint32_t partialInboundsSize; // size % pitch. precalculated value used by fetch shader for partially OOB vertices }; diff --git a/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp b/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp index 901bce6..ffa7605 100644 --- a/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp +++ b/src/gallium/drivers/swr/rasterizer/jitter/fetch_jit.cpp @@ -309,11 +309,29 @@ void FetchJit::JitLoadVertices(const FETCH_COMPILE_STATE , Value* str Value* startVertexOffset = MUL(Z_EXT(startOffset, mInt64Ty), stride); +Value *minVertex = NULL; +Value *minVertexOffset = NULL; +if (fetchState.bPartialVertexBuffer) { +// fetch min index for low bounds checking +minVertex = GEP(streams, {C(ied.StreamIndex), C(SWR_VERTEX_BUFFER_STATE_minVertex)}); +minVertex = LOAD(minVertex); +if (!fetchState.bDisableIndexOOBCheck) { +minVertexOffset = MUL(Z_EXT(minVertex, mInt64Ty), stride); +} +} + // Load from the stream. for(uint32_t lane = 0; lane < mVWidth; ++lane) { // Get index Value* index = VEXTRACT(vCurIndices, C(lane)); + +if (fetchState.bPartialVertexBuffer) { +// clamp below minvertex +Value *isBelowMin = ICMP_SLT(index, minVertex); +index = SELECT(isBelowMin, minVertex, index); +} + index = Z_EXT(index, mInt64Ty); Value*offset = MUL(index, stride); @@ -321,10 +339,14 @@ void FetchJit::JitLoadVertices(const FETCH_COMPILE_STATE , Value* str offset = ADD(offset, startVertexOffset); if (!fetchState.bDisableIndexOOBCheck) { -// check for out of bound access, including partial OOB, and mask them to 0 +// check for out of bound access, including partial OOB, and replace them with minVertex Value *endOffset = ADD(offset, C((int64_t)info.Bpp)); Value *oob = ICMP_ULE(endOffset, size); -offset = SELECT(oob, offset, ConstantInt::get(mInt64Ty, 0)); +if (fetchState.bPartialVertexBuffer) { +offset = SELECT(oob, offset, minVertexOffset); +} else { +offset = SELECT(oob, offset, ConstantInt::get(mInt64Ty, 0)); +} } Value*pointer = GEP(stream, offset); @@ -732,6 +754,13 @@ void FetchJit::JitGatherVertices(const FETCH_COMPILE_STATE , Value *maxVertex = GEP(streams, {C(ied.StreamIndex), C(SWR_VERTEX_BUFFER_STATE_maxVertex)}); maxVertex = LOAD(maxVertex); +Value *minVertex = NULL; +if (fetchState.bPartialVertexBuffer) { +// min vertex index for low bounds OOB checking +minVertex = GEP(streams, {C(ied.StreamIndex), C(SWR_VERTEX_BUFFER_STATE_minVertex)}); +minVertex = LOAD(minVertex); +} + Value *vCurIndices; Value *startOffset; if(ied.InstanceEnable) @@ -769,9 +798,16 @@ void FetchJit::JitGatherVertices(const FETCH_COMPILE_STATE , // if we have a start offset, subtract from max vertex. Used for OOB check maxVertex = SUB(Z_EXT(maxVertex, mInt64Ty), Z_EXT(startOffset, mInt64Ty)); -Value* neg = ICMP_SLT(maxVertex, C((int64_t)0)); +Value* maxNeg = ICMP_SLT(maxVertex, C((int64_t)0)); // if we have a negative value, we're already OOB. clamp at 0. -maxVertex = SELECT(neg, C(0), TRUNC(maxVertex, mInt32Ty)); +maxVertex = SELECT(maxNeg,