mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 22:38:05 +02:00
gallium/u_threaded: clear valid buffer range only if it's not bound for write
We can't invalidate the range if a buffer is bound for write because we would need to add the range that is bound, which we don't track. This fixes buffer mappings incorrectly promoted to unsynchronized because the valid range was cleared while the buffers were bound for write. It also clears the valid range if the invalidation is allowed but skipped. Reviewed-by: Rob Clark <robdclark@chromium.org> Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11335>
This commit is contained in:
parent
2b1677860e
commit
988d091720
2 changed files with 80 additions and 2 deletions
|
|
@ -567,6 +567,61 @@ tc_rebind_buffer(struct threaded_context *tc, uint32_t old_id, uint32_t new_id,
|
|||
return rebound;
|
||||
}
|
||||
|
||||
static bool
|
||||
tc_is_buffer_bound_with_mask(uint32_t id, uint32_t *bindings, unsigned binding_mask)
|
||||
{
|
||||
while (binding_mask) {
|
||||
if (bindings[u_bit_scan(&binding_mask)] == id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
tc_is_buffer_shader_bound_for_write(struct threaded_context *tc, uint32_t id,
|
||||
enum pipe_shader_type shader)
|
||||
{
|
||||
if (tc->seen_shader_buffers[shader] &&
|
||||
tc_is_buffer_bound_with_mask(id, tc->shader_buffers[shader],
|
||||
tc->shader_buffers_writeable_mask[shader]))
|
||||
return true;
|
||||
|
||||
if (tc->seen_image_buffers[shader] &&
|
||||
tc_is_buffer_bound_with_mask(id, tc->image_buffers[shader],
|
||||
tc->image_buffers_writeable_mask[shader]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
tc_is_buffer_bound_for_write(struct threaded_context *tc, uint32_t id)
|
||||
{
|
||||
if (tc->seen_streamout_buffers &&
|
||||
tc_is_buffer_bound_with_mask(id, tc->streamout_buffers,
|
||||
BITFIELD_MASK(PIPE_MAX_SO_BUFFERS)))
|
||||
return true;
|
||||
|
||||
if (tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_VERTEX) ||
|
||||
tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_FRAGMENT) ||
|
||||
tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_COMPUTE))
|
||||
return true;
|
||||
|
||||
if (tc->seen_tcs &&
|
||||
tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_TESS_CTRL))
|
||||
return true;
|
||||
|
||||
if (tc->seen_tes &&
|
||||
tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_TESS_EVAL))
|
||||
return true;
|
||||
|
||||
if (tc->seen_gs &&
|
||||
tc_is_buffer_shader_bound_for_write(tc, id, PIPE_SHADER_GEOMETRY))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
tc_is_buffer_busy(struct threaded_context *tc, struct threaded_resource *tbuf,
|
||||
unsigned map_usage)
|
||||
|
|
@ -1367,6 +1422,7 @@ tc_set_shader_images(struct pipe_context *_pipe,
|
|||
struct tc_shader_images *p =
|
||||
tc_add_slot_based_call(tc, TC_CALL_set_shader_images, tc_shader_images,
|
||||
images ? count : 0);
|
||||
unsigned writable_buffers = 0;
|
||||
|
||||
p->shader = shader;
|
||||
p->start = start;
|
||||
|
|
@ -1391,6 +1447,7 @@ tc_set_shader_images(struct pipe_context *_pipe,
|
|||
util_range_add(&tres->b, &tres->valid_buffer_range,
|
||||
images[i].u.buf.offset,
|
||||
images[i].u.buf.offset + images[i].u.buf.size);
|
||||
writable_buffers |= BITFIELD_BIT(start + i);
|
||||
}
|
||||
} else {
|
||||
tc_unbind_buffer(&tc->image_buffers[shader][start + i]);
|
||||
|
|
@ -1408,6 +1465,9 @@ tc_set_shader_images(struct pipe_context *_pipe,
|
|||
tc_unbind_buffers(&tc->image_buffers[shader][start],
|
||||
count + unbind_num_trailing_slots);
|
||||
}
|
||||
|
||||
tc->image_buffers_writeable_mask[shader] &= ~BITFIELD_RANGE(start, count);
|
||||
tc->image_buffers_writeable_mask[shader] |= writable_buffers << start;
|
||||
}
|
||||
|
||||
struct tc_shader_buffers {
|
||||
|
|
@ -1488,6 +1548,9 @@ tc_set_shader_buffers(struct pipe_context *_pipe,
|
|||
} else {
|
||||
tc_unbind_buffers(&tc->shader_buffers[shader][start], count);
|
||||
}
|
||||
|
||||
tc->shader_buffers_writeable_mask[shader] &= ~BITFIELD_RANGE(start, count);
|
||||
tc->shader_buffers_writeable_mask[shader] |= writable_bitmask << start;
|
||||
}
|
||||
|
||||
struct tc_vertex_buffers {
|
||||
|
|
@ -1855,8 +1918,17 @@ static bool
|
|||
tc_invalidate_buffer(struct threaded_context *tc,
|
||||
struct threaded_resource *tbuf)
|
||||
{
|
||||
if (!tc_is_buffer_busy(tc, tbuf, PIPE_MAP_READ_WRITE))
|
||||
if (!tc_is_buffer_busy(tc, tbuf, PIPE_MAP_READ_WRITE)) {
|
||||
/* It's idle, so invalidation would be a no-op, but we can still clear
|
||||
* the valid range because we are technically doing invalidation, but
|
||||
* skipping it because it's useless.
|
||||
*
|
||||
* If the buffer is bound for write, we can't invalidate the range.
|
||||
*/
|
||||
if (!tc_is_buffer_bound_for_write(tc, tbuf->buffer_id_unique))
|
||||
util_range_set_empty(&tbuf->valid_buffer_range);
|
||||
return true;
|
||||
}
|
||||
|
||||
struct pipe_screen *screen = tc->base.screen;
|
||||
struct pipe_resource *new_buf;
|
||||
|
|
@ -1892,10 +1964,14 @@ tc_invalidate_buffer(struct threaded_context *tc,
|
|||
p->rebind_mask = 0;
|
||||
|
||||
/* Treat the current buffer as the new buffer. */
|
||||
bool bound_for_write = tc_is_buffer_bound_for_write(tc, tbuf->buffer_id_unique);
|
||||
p->num_rebinds = tc_rebind_buffer(tc, tbuf->buffer_id_unique,
|
||||
threaded_resource(new_buf)->buffer_id_unique,
|
||||
&p->rebind_mask);
|
||||
util_range_set_empty(&tbuf->valid_buffer_range);
|
||||
|
||||
/* If the buffer is not bound for write, clear the valid range. */
|
||||
if (!bound_for_write)
|
||||
util_range_set_empty(&tbuf->valid_buffer_range);
|
||||
|
||||
tbuf->buffer_id_unique = threaded_resource(new_buf)->buffer_id_unique;
|
||||
threaded_resource(new_buf)->buffer_id_unique = 0;
|
||||
|
|
|
|||
|
|
@ -481,6 +481,8 @@ struct threaded_context {
|
|||
uint32_t const_buffers[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
|
||||
uint32_t shader_buffers[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_BUFFERS];
|
||||
uint32_t image_buffers[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_IMAGES];
|
||||
uint32_t shader_buffers_writeable_mask[PIPE_SHADER_TYPES];
|
||||
uint32_t image_buffers_writeable_mask[PIPE_SHADER_TYPES];
|
||||
/* Don't use PIPE_MAX_SHADER_SAMPLER_VIEWS because it's too large. */
|
||||
uint32_t sampler_buffers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue