st/mesa: add a mechanism to bypass atomics when binding sampler views

This is the same mechanism we already use for buffers. The code is mostly
copied from there. See the big comment for explanation.

This will be very effective when take_ownership is added into pipe_context
::set_sampler_views because that and this commit together will eliminate
atomics for sample views almost entirely.

Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11428>
This commit is contained in:
Marek Olšák
2021-06-06 06:08:07 -04:00
committed by Marge Bot
parent 798518e510
commit ef5d427413
2 changed files with 48 additions and 6 deletions

View File

@@ -41,15 +41,35 @@
#include "st_cb_bufferobjects.h"
#include "st_cb_texture.h"
/* Subtract remaining private references. Typically used before
* destruction. See the header file for explanation.
*/
static void
st_remove_private_references(struct st_sampler_view *sv)
{
if (sv->private_refcount) {
assert(sv->private_refcount > 0);
p_atomic_add(&sv->view->reference.count, -sv->private_refcount);
sv->private_refcount = 0;
}
}
/* Return a sampler view while incrementing the refcount by 1. */
static struct pipe_sampler_view *
get_sampler_view_reference(struct st_sampler_view *sv,
struct pipe_sampler_view *view)
{
struct pipe_sampler_view *ret = NULL;
if (unlikely(sv->private_refcount <= 0)) {
assert(sv->private_refcount == 0);
pipe_sampler_view_reference(&ret, view);
return ret;
/* This is the number of atomic increments we will skip. */
sv->private_refcount = 100000000;
p_atomic_add(&view->reference.count, sv->private_refcount);
}
/* Return a reference while decrementing the private refcount. */
sv->private_refcount--;
return view;
}
/**
@@ -85,6 +105,7 @@ st_texture_set_sampler_view(struct st_context *st,
if (sv->view) {
/* check if the context matches */
if (sv->view->context == st->pipe) {
st_remove_private_references(sv);
pipe_sampler_view_reference(&sv->view, NULL);
goto found;
}
@@ -208,10 +229,11 @@ st_texture_release_context_sampler_view(struct st_context *st,
simple_mtx_lock(&stObj->validate_mutex);
struct st_sampler_views *views = stObj->sampler_views;
for (i = 0; i < views->count; ++i) {
struct pipe_sampler_view **sv = &views->views[i].view;
struct st_sampler_view *sv = &views->views[i];
if (*sv && (*sv)->context == st->pipe) {
pipe_sampler_view_reference(sv, NULL);
if (sv->view && sv->view->context == st->pipe) {
st_remove_private_references(sv);
pipe_sampler_view_reference(&sv->view, NULL);
break;
}
}
@@ -240,6 +262,8 @@ st_texture_release_all_sampler_views(struct st_context *st,
for (unsigned i = 0; i < views->count; ++i) {
struct st_sampler_view *stsv = &views->views[i];
if (stsv->view) {
st_remove_private_references(stsv);
if (stsv->st && stsv->st != st) {
/* Transfer this reference to the zombie list. It will
* likely be freed when the zombie list is freed.