zink: handle vertex buffer offset overflows
there's a screen limit for vertex buffer offsets (???), so if a buffer is going to overflow that limit, just rebind it as a new tmp buffer and clamp the offset to 0 this also applies to buffer rebinds Reviewed-by: Dave Airlie <airlied@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11836>
This commit is contained in:

committed by
Marge Bot

parent
d5dd1259c5
commit
9823b970fb
@@ -900,9 +900,35 @@ update_existing_vbo(struct zink_context *ctx, unsigned slot)
|
||||
return;
|
||||
struct zink_resource *res = zink_resource(ctx->vertex_buffers[slot].buffer.resource);
|
||||
res->vbo_bind_mask &= ~BITFIELD_BIT(slot);
|
||||
ctx->vbufs[slot] = VK_NULL_HANDLE;
|
||||
ctx->vbuf_offsets[slot] = 0;
|
||||
update_res_bind_count(ctx, res, false, true);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE static void
|
||||
set_vertex_buffer_clamped(struct zink_context *ctx, unsigned slot)
|
||||
{
|
||||
const struct pipe_vertex_buffer *ctx_vb = &ctx->vertex_buffers[slot];
|
||||
struct zink_resource *res = zink_resource(ctx_vb->buffer.resource);
|
||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||
if (ctx_vb->buffer_offset > screen->info.props.limits.maxVertexInputAttributeOffset) {
|
||||
/* buffer offset exceeds maximum: make a tmp buffer at this offset */
|
||||
ctx->vbufs[slot] = zink_resource_tmp_buffer(screen, res, ctx_vb->buffer_offset, 0, &ctx->vbuf_offsets[slot]);
|
||||
util_dynarray_append(&res->obj->tmp, VkBuffer, ctx->vbufs[slot]);
|
||||
/* the driver is broken and sets a min alignment that's larger than its max offset: rebind as staging buffer */
|
||||
if (unlikely(ctx->vbuf_offsets[slot] > screen->info.props.limits.maxVertexInputAttributeOffset)) {
|
||||
static bool warned = false;
|
||||
if (!warned)
|
||||
debug_printf("zink: this vulkan driver is BROKEN! maxVertexInputAttributeOffset < VkMemoryRequirements::alignment\n");
|
||||
warned = true;
|
||||
}
|
||||
} else {
|
||||
ctx->vbufs[slot] = res->obj->buffer;
|
||||
ctx->vbuf_offsets[slot] = ctx_vb->buffer_offset;
|
||||
}
|
||||
assert(ctx->vbufs[slot]);
|
||||
}
|
||||
|
||||
static void
|
||||
zink_set_vertex_buffers(struct pipe_context *pctx,
|
||||
unsigned start_slot,
|
||||
@@ -936,9 +962,11 @@ zink_set_vertex_buffers(struct pipe_context *pctx,
|
||||
update_res_bind_count(ctx, res, false, false);
|
||||
ctx_vb->stride = vb->stride;
|
||||
ctx_vb->buffer_offset = vb->buffer_offset;
|
||||
zink_batch_resource_usage_set(&ctx->batch, res, false);
|
||||
/* always barrier before possible rebind */
|
||||
zink_resource_buffer_barrier(ctx, NULL, res, VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
|
||||
VK_PIPELINE_STAGE_VERTEX_INPUT_BIT);
|
||||
set_vertex_buffer_clamped(ctx, start_slot + i);
|
||||
zink_batch_resource_usage_set(&ctx->batch, res, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -3128,10 +3156,10 @@ rebind_buffer(struct zink_context *ctx, struct zink_resource *res)
|
||||
u_foreach_bit(slot, res->vbo_bind_mask) {
|
||||
if (ctx->vertex_buffers[slot].buffer.resource != &res->base.b) //wrong context
|
||||
return;
|
||||
break;
|
||||
set_vertex_buffer_clamped(ctx, slot);
|
||||
num_rebinds++;
|
||||
}
|
||||
ctx->vertex_buffers_dirty = true;
|
||||
num_rebinds += util_bitcount(res->vbo_bind_mask);
|
||||
}
|
||||
for (unsigned shader = 0; num_rebinds < total_rebinds && shader < PIPE_SHADER_TYPES; shader++) {
|
||||
u_foreach_bit(slot, res->ubo_bind_mask[shader]) {
|
||||
|
@@ -224,6 +224,8 @@ struct zink_context {
|
||||
uint16_t clears_enabled;
|
||||
uint16_t rp_clears_enabled;
|
||||
|
||||
VkBuffer vbufs[PIPE_MAX_ATTRIBS];
|
||||
unsigned vbuf_offsets[PIPE_MAX_ATTRIBS];
|
||||
struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
|
||||
bool vertex_buffers_dirty;
|
||||
|
||||
|
@@ -137,12 +137,13 @@ zink_bind_vertex_buffers(struct zink_batch *batch, struct zink_context *ctx)
|
||||
return;
|
||||
|
||||
for (unsigned i = 0; i < elems->hw_state.num_bindings; i++) {
|
||||
struct pipe_vertex_buffer *vb = ctx->vertex_buffers + ctx->element_state->binding_map[i];
|
||||
const unsigned buffer_id = ctx->element_state->binding_map[i];
|
||||
struct pipe_vertex_buffer *vb = ctx->vertex_buffers + buffer_id;
|
||||
assert(vb);
|
||||
if (vb->buffer.resource) {
|
||||
struct zink_resource *res = zink_resource(vb->buffer.resource);
|
||||
buffers[i] = res->obj->buffer;
|
||||
buffer_offsets[i] = vb->buffer_offset;
|
||||
buffers[i] = ctx->vbufs[buffer_id];
|
||||
assert(buffers[i]);
|
||||
buffer_offsets[i] = ctx->vbuf_offsets[buffer_id];
|
||||
buffer_strides[i] = vb->stride;
|
||||
} else {
|
||||
buffers[i] = zink_resource(ctx->dummy_vertex_buffer)->obj->buffer;
|
||||
|
Reference in New Issue
Block a user