vc4: Translate 4-byte index buffers to 2 bytes.
Fixes assertion failures in 14 piglit tests (half of which now pass).
This commit is contained in:
@@ -209,19 +209,23 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info)
|
|||||||
*/
|
*/
|
||||||
if (info->indexed) {
|
if (info->indexed) {
|
||||||
struct vc4_resource *rsc = vc4_resource(vc4->indexbuf.buffer);
|
struct vc4_resource *rsc = vc4_resource(vc4->indexbuf.buffer);
|
||||||
|
uint32_t offset = vc4->indexbuf.offset;
|
||||||
assert(vc4->indexbuf.index_size == 1 ||
|
uint32_t index_size = vc4->indexbuf.index_size;
|
||||||
vc4->indexbuf.index_size == 2);
|
if (rsc->shadow_parent) {
|
||||||
|
vc4_update_shadow_index_buffer(pctx, &vc4->indexbuf);
|
||||||
|
offset = 0;
|
||||||
|
index_size = 2;
|
||||||
|
}
|
||||||
|
|
||||||
cl_start_reloc(&vc4->bcl, 1);
|
cl_start_reloc(&vc4->bcl, 1);
|
||||||
cl_u8(&vc4->bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE);
|
cl_u8(&vc4->bcl, VC4_PACKET_GL_INDEXED_PRIMITIVE);
|
||||||
cl_u8(&vc4->bcl,
|
cl_u8(&vc4->bcl,
|
||||||
info->mode |
|
info->mode |
|
||||||
(vc4->indexbuf.index_size == 2 ?
|
(index_size == 2 ?
|
||||||
VC4_INDEX_BUFFER_U16:
|
VC4_INDEX_BUFFER_U16:
|
||||||
VC4_INDEX_BUFFER_U8));
|
VC4_INDEX_BUFFER_U8));
|
||||||
cl_u32(&vc4->bcl, info->count);
|
cl_u32(&vc4->bcl, info->count);
|
||||||
cl_reloc(vc4, &vc4->bcl, rsc->bo, vc4->indexbuf.offset);
|
cl_reloc(vc4, &vc4->bcl, rsc->bo, offset);
|
||||||
cl_u32(&vc4->bcl, max_index);
|
cl_u32(&vc4->bcl, max_index);
|
||||||
} else {
|
} else {
|
||||||
cl_u8(&vc4->bcl, VC4_PACKET_GL_ARRAY_PRIMITIVE);
|
cl_u8(&vc4->bcl, VC4_PACKET_GL_ARRAY_PRIMITIVE);
|
||||||
|
@@ -512,6 +512,52 @@ vc4_update_shadow_baselevel_texture(struct pipe_context *pctx,
|
|||||||
shadow->writes = orig->writes;
|
shadow->writes = orig->writes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a 4-byte index buffer to 2 bytes.
|
||||||
|
*
|
||||||
|
* Since GLES2 only has support for 1 and 2-byte indices, the hardware doesn't
|
||||||
|
* include 4-byte index support, and we have to shrink it down.
|
||||||
|
*
|
||||||
|
* There's no fallback support for when indices end up being larger than 2^16,
|
||||||
|
* though it will at least assertion fail. Also, if the original index data
|
||||||
|
* was in user memory, it would be nice to not have uploaded it to a VBO
|
||||||
|
* before translating.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vc4_update_shadow_index_buffer(struct pipe_context *pctx,
|
||||||
|
const struct pipe_index_buffer *ib)
|
||||||
|
{
|
||||||
|
struct vc4_resource *shadow = vc4_resource(ib->buffer);
|
||||||
|
struct vc4_resource *orig = vc4_resource(shadow->shadow_parent);
|
||||||
|
uint32_t count = shadow->base.b.width0 / 2;
|
||||||
|
|
||||||
|
if (shadow->writes == orig->writes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct pipe_transfer *src_transfer;
|
||||||
|
uint32_t *src = pipe_buffer_map_range(pctx, &orig->base.b,
|
||||||
|
ib->offset,
|
||||||
|
count * 4,
|
||||||
|
PIPE_TRANSFER_READ, &src_transfer);
|
||||||
|
|
||||||
|
struct pipe_transfer *dst_transfer;
|
||||||
|
uint16_t *dst = pipe_buffer_map_range(pctx, &shadow->base.b,
|
||||||
|
0,
|
||||||
|
count * 2,
|
||||||
|
PIPE_TRANSFER_WRITE, &dst_transfer);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
uint32_t src_index = src[i];
|
||||||
|
assert(src_index <= 0xffff);
|
||||||
|
dst[i] = src_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
pctx->transfer_unmap(pctx, dst_transfer);
|
||||||
|
pctx->transfer_unmap(pctx, src_transfer);
|
||||||
|
|
||||||
|
shadow->writes = orig->writes;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
vc4_resource_screen_init(struct pipe_screen *pscreen)
|
vc4_resource_screen_init(struct pipe_screen *pscreen)
|
||||||
{
|
{
|
||||||
|
@@ -67,9 +67,22 @@ struct vc4_resource {
|
|||||||
*
|
*
|
||||||
* This is used to track when we need to update this shadow resource
|
* This is used to track when we need to update this shadow resource
|
||||||
* from its parent in the case of GL_TEXTURE_BASE_LEVEL (which we
|
* from its parent in the case of GL_TEXTURE_BASE_LEVEL (which we
|
||||||
* can't support in hardware).
|
* can't support in hardware) or GL_UNSIGNED_INTEGER index buffers.
|
||||||
*/
|
*/
|
||||||
uint64_t writes;
|
uint64_t writes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource containing the non-GL_TEXTURE_BASE_LEVEL-rebased texture
|
||||||
|
* contents, or the 4-byte index buffer.
|
||||||
|
*
|
||||||
|
* If the parent is set for an texture, then this resource is actually
|
||||||
|
* the texture contents just starting from the sampler_view's
|
||||||
|
* first_level.
|
||||||
|
*
|
||||||
|
* If the parent is set for an index index buffer, then this resource
|
||||||
|
* is actually a shadow containing a 2-byte index buffer starting from
|
||||||
|
* the ib's offset.
|
||||||
|
*/
|
||||||
struct pipe_resource *shadow_parent;
|
struct pipe_resource *shadow_parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -97,5 +110,7 @@ struct pipe_resource *vc4_resource_create(struct pipe_screen *pscreen,
|
|||||||
const struct pipe_resource *tmpl);
|
const struct pipe_resource *tmpl);
|
||||||
void vc4_update_shadow_baselevel_texture(struct pipe_context *pctx,
|
void vc4_update_shadow_baselevel_texture(struct pipe_context *pctx,
|
||||||
struct pipe_sampler_view *view);
|
struct pipe_sampler_view *view);
|
||||||
|
void vc4_update_shadow_index_buffer(struct pipe_context *pctx,
|
||||||
|
const struct pipe_index_buffer *ib);
|
||||||
|
|
||||||
#endif /* VC4_RESOURCE_H */
|
#endif /* VC4_RESOURCE_H */
|
||||||
|
@@ -281,10 +281,27 @@ vc4_set_index_buffer(struct pipe_context *pctx,
|
|||||||
struct vc4_context *vc4 = vc4_context(pctx);
|
struct vc4_context *vc4 = vc4_context(pctx);
|
||||||
|
|
||||||
if (ib) {
|
if (ib) {
|
||||||
pipe_resource_reference(&vc4->indexbuf.buffer, ib->buffer);
|
assert(!ib->user_buffer);
|
||||||
vc4->indexbuf.index_size = ib->index_size;
|
|
||||||
vc4->indexbuf.offset = ib->offset;
|
if (ib->index_size == 4) {
|
||||||
vc4->indexbuf.user_buffer = ib->user_buffer;
|
struct pipe_resource tmpl = *ib->buffer;
|
||||||
|
assert(tmpl.format == PIPE_FORMAT_R8_UNORM);
|
||||||
|
assert(tmpl.height0 == 1);
|
||||||
|
tmpl.width0 = (tmpl.width0 - ib->offset) / 2;
|
||||||
|
struct pipe_resource *pshadow =
|
||||||
|
vc4_resource_create(&vc4->screen->base, &tmpl);
|
||||||
|
struct vc4_resource *shadow = vc4_resource(pshadow);
|
||||||
|
pipe_resource_reference(&shadow->shadow_parent, ib->buffer);
|
||||||
|
|
||||||
|
pipe_resource_reference(&vc4->indexbuf.buffer, NULL);
|
||||||
|
vc4->indexbuf.buffer = pshadow;
|
||||||
|
vc4->indexbuf.index_size = 2;
|
||||||
|
vc4->indexbuf.offset = 0;
|
||||||
|
} else {
|
||||||
|
pipe_resource_reference(&vc4->indexbuf.buffer, ib->buffer);
|
||||||
|
vc4->indexbuf.index_size = ib->index_size;
|
||||||
|
vc4->indexbuf.offset = ib->offset;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pipe_resource_reference(&vc4->indexbuf.buffer, NULL);
|
pipe_resource_reference(&vc4->indexbuf.buffer, NULL);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user