draw: simplify vsplit elts code a bit

vsplit_get_base_idx explicitly returned idx 0 and set the ofbit
in case of overflow. We'd then check the ofbit and use idx 0 instead of
looking it up. This was necessary because DRAW_GET_IDX used to return
DRAW_MAX_FETCH_IDX and not 0 in case of overflows.
However, this is all unnecessary, we can just let DRAW_GET_IDX return 0
in case of overflow. In fact before bbd1e60198
the code already did that, not sure why this particular bit was changed
(might have been one half of an attempt to get these indices to actual draw
shader execution - in fact I think this would make things less awkward, it
would require moving the eltBias handling to the shader as well).
Note there's other callers of DRAW_GET_IDX - those code paths however
explicitly do not handle index buffer overflows, therefore the overflow
value doesn't matter for them.

Also do some trivial simplification - for (unsigned) a + b, checking res < a
is sufficient for overflow detection, we don't need to check for res < b too
(similar for signed).

And an index buffer overflow check looked bogus - eltMax is the number of
elements in the index buffer, not the maximum element which can be fetched.
(Drop the start check against the idx buffer though, this is already covered
by end check and end < start).

Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
This commit is contained in:
Roland Scheidegger 2016-11-12 22:47:22 +01:00
parent 9aae167e94
commit 7a55c436c6
3 changed files with 18 additions and 40 deletions

View File

@ -489,11 +489,10 @@ void draw_update_viewport_flags(struct draw_context *draw);
/**
* Return index i from the index buffer.
* If the index buffer would overflow we return the
* maximum possible index.
* If the index buffer would overflow we return index 0.
*/
#define DRAW_GET_IDX(_elts, _i) \
(((_i) >= draw->pt.user.eltMax) ? DRAW_MAX_FETCH_IDX : (_elts)[_i])
(((_i) >= draw->pt.user.eltMax) ? 0 : (_elts)[_i])
/**
* Return index of the given viewport clamping it
@ -515,7 +514,7 @@ draw_overflow_uadd(unsigned a, unsigned b,
unsigned overflow_value)
{
unsigned res = a + b;
if (res < a || res < b) {
if (res < a) {
res = overflow_value;
}
return res;

View File

@ -33,7 +33,7 @@
#define SEGMENT_SIZE 1024
#define MAP_SIZE 256
/* The largest possible index withing an index buffer */
/* The largest possible index within an index buffer */
#define MAX_ELT_IDX 0xffffffff
struct vsplit_frontend {
@ -108,55 +108,36 @@ vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch, unsigned ofbias
/**
* Returns the base index to the elements array.
* The value is checked for overflows (both integer overflows
* and the elements array overflow).
* The value is checked for integer overflow.
*/
static inline unsigned
vsplit_get_base_idx(struct vsplit_frontend *vsplit,
unsigned start, unsigned fetch, unsigned *ofbit)
vsplit_get_base_idx(unsigned start, unsigned fetch)
{
struct draw_context *draw = vsplit->draw;
unsigned elt_idx = draw_overflow_uadd(start, fetch, MAX_ELT_IDX);
if (ofbit)
*ofbit = 0;
/* Overflown indices need to wrap to the first element
* in the index buffer */
if (elt_idx >= draw->pt.user.eltMax) {
if (ofbit)
*ofbit = 1;
elt_idx = 0;
}
return elt_idx;
return draw_overflow_uadd(start, fetch, MAX_ELT_IDX);
}
/**
* Returns the element index adjust for the element bias.
* The final element index is created from the actual element
* index, plus the element bias, clamped to maximum elememt
* index, plus the element bias, clamped to maximum element
* index if that addition overflows.
*/
static inline unsigned
vsplit_get_bias_idx(struct vsplit_frontend *vsplit,
int idx, int bias, unsigned *ofbias)
vsplit_get_bias_idx(int idx, int bias, unsigned *ofbias)
{
int res = idx + bias;
if (ofbias)
*ofbias = 0;
*ofbias = 0;
if (idx > 0 && bias > 0) {
if (res < idx || res < bias) {
if (res < idx) {
res = DRAW_MAX_FETCH_IDX;
if (ofbias)
*ofbias = 1;
*ofbias = 1;
}
} else if (idx < 0 && bias < 0) {
if (res > idx || res > bias) {
if (res > idx) {
res = DRAW_MAX_FETCH_IDX;
if (ofbias)
*ofbias = 1;
*ofbias = 1;
}
}
@ -165,10 +146,9 @@ vsplit_get_bias_idx(struct vsplit_frontend *vsplit,
#define VSPLIT_CREATE_IDX(elts, start, fetch, elt_bias) \
unsigned elt_idx; \
unsigned ofbit; \
unsigned ofbias; \
elt_idx = vsplit_get_base_idx(vsplit, start, fetch, &ofbit); \
elt_idx = vsplit_get_bias_idx(vsplit, ofbit ? 0 : DRAW_GET_IDX(elts, elt_idx), elt_bias, &ofbias)
elt_idx = vsplit_get_base_idx(start, fetch); \
elt_idx = vsplit_get_bias_idx(DRAW_GET_IDX(elts, elt_idx), elt_bias, &ofbias)
static inline void
vsplit_add_cache_ubyte(struct vsplit_frontend *vsplit, const ubyte *elts,

View File

@ -49,9 +49,8 @@ CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend *vsplit,
/* If the index buffer overflows we'll need to run
* through the normal paths */
if (start >= draw->pt.user.eltMax ||
end > draw->pt.user.eltMax ||
end < istart || end < icount)
if (end >= draw->pt.user.eltMax ||
end < istart)
return FALSE;
/* use the ib directly */