Tom Stellard <thomas.stell...@amd.com> writes: > Events can be added to an OpenCL command queue concurrently from > multiple threads, but pipe_context and pipe_screen objects > are not threadsafe. The threadsafe wrappers protect all pipe_screen > and pipe_context function calls with a mutex, so we can safely use > them with multiple threads. > --- > src/gallium/state_trackers/clover/Makefile.am | 6 +- > src/gallium/state_trackers/clover/Makefile.sources | 4 + > src/gallium/state_trackers/clover/core/device.cpp | 2 + > .../clover/core/pipe_threadsafe_context.c | 272 > +++++++++++++++++++++ > .../clover/core/pipe_threadsafe_screen.c | 184 ++++++++++++++ > .../state_trackers/clover/core/threadsafe.h | 39 +++ > src/gallium/targets/opencl/Makefile.am | 3 +- > 7 files changed, 508 insertions(+), 2 deletions(-) > create mode 100644 > src/gallium/state_trackers/clover/core/pipe_threadsafe_context.c > create mode 100644 > src/gallium/state_trackers/clover/core/pipe_threadsafe_screen.c > create mode 100644 src/gallium/state_trackers/clover/core/threadsafe.h > > diff --git a/src/gallium/state_trackers/clover/Makefile.am > b/src/gallium/state_trackers/clover/Makefile.am > index f46d9ef..8b615ae 100644 > --- a/src/gallium/state_trackers/clover/Makefile.am > +++ b/src/gallium/state_trackers/clover/Makefile.am > @@ -1,5 +1,6 @@ > AUTOMAKE_OPTIONS = subdir-objects > > +include $(top_srcdir)/src/gallium/Automake.inc > include Makefile.sources > > AM_CPPFLAGS = \ > @@ -32,6 +33,9 @@ cl_HEADERS = \ > $(top_srcdir)/include/CL/opencl.h > endif > > +AM_CFLAGS = \ > + $(GALLIUM_CFLAGS) > + > noinst_LTLIBRARIES = libclover.la libcltgsi.la libclllvm.la > > libcltgsi_la_CXXFLAGS = \ > @@ -58,6 +62,6 @@ libclover_la_CXXFLAGS = \ > libclover_la_LIBADD = \ > libcltgsi.la libclllvm.la > > -libclover_la_SOURCES = $(CPP_SOURCES) > +libclover_la_SOURCES = $(CPP_SOURCES) $(C_SOURCES) > > EXTRA_DIST = Doxyfile > diff --git a/src/gallium/state_trackers/clover/Makefile.sources > b/src/gallium/state_trackers/clover/Makefile.sources > index 10bbda0..90e6b7e 100644 > --- a/src/gallium/state_trackers/clover/Makefile.sources > +++ b/src/gallium/state_trackers/clover/Makefile.sources > @@ -53,6 +53,10 @@ CPP_SOURCES := \ > util/range.hpp \ > util/tuple.hpp > > +C_SOURCES := \ > + core/pipe_threadsafe_context.c \ > + core/pipe_threadsafe_screen.c > + > LLVM_SOURCES := \ > llvm/invocation.cpp > > diff --git a/src/gallium/state_trackers/clover/core/device.cpp > b/src/gallium/state_trackers/clover/core/device.cpp > index 42b45b7..b145027 100644 > --- a/src/gallium/state_trackers/clover/core/device.cpp > +++ b/src/gallium/state_trackers/clover/core/device.cpp > @@ -22,6 +22,7 @@ > > #include "core/device.hpp" > #include "core/platform.hpp" > +#include "core/threadsafe.h" > #include "pipe/p_screen.h" > #include "pipe/p_state.h" > > @@ -47,6 +48,7 @@ device::device(clover::platform &platform, > pipe_loader_device *ldev) : > pipe->destroy(pipe); > throw error(CL_INVALID_DEVICE); > } > + pipe = pipe_threadsafe_screen(pipe); > } > > device::~device() { > diff --git a/src/gallium/state_trackers/clover/core/pipe_threadsafe_context.c > b/src/gallium/state_trackers/clover/core/pipe_threadsafe_context.c > new file mode 100644 > index 0000000..f08f56c > --- /dev/null > +++ b/src/gallium/state_trackers/clover/core/pipe_threadsafe_context.c > @@ -0,0 +1,272 @@ > +/* > + * Copyright 2015 Advanced Micro Devices, Inc. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > THE > + * SOFTWARE. > + * > + * Authors: Tom Stellard <thomas.stell...@amd.com> > + * > + */ > + > +#include <stdio.h> > + > +/** > + * \file > + * > + * threadsafe_context is a wrapper around a pipe_context to make it thread > + * safe. > + */ > + > +#include "os/os_thread.h" > +#include "pipe/p_context.h" > +#include "util/u_memory.h" > + > +#include "threadsafe.h" > + > + > + > +struct threadsafe_context { > + struct pipe_context base; > + struct pipe_context *ctx; > + pipe_mutex mutex; > +}; > + > +static struct pipe_context *unwrap(struct pipe_context *ctx) { > + if (!ctx) > + return NULL; > + struct threadsafe_context *ts_ctx = (struct threadsafe_context*)ctx; > + return ts_ctx->ctx; > +} > + > +#define THREADSAFE_CALL_VOID(ctx, function) \ > + struct threadsafe_context *ts_ctx = (struct threadsafe_context*)(ctx); \ > + pipe_mutex_lock(ts_ctx->mutex); \ > + (unwrap(ctx)->function); \ > + pipe_mutex_unlock(ts_ctx->mutex); > + > +#define THREADSAFE_CALL_RET(ctx, return_type, function) \ > + struct threadsafe_context *ts_ctx = (struct threadsafe_context*)(ctx); \ > + pipe_mutex_lock(ts_ctx->mutex); \ > + return_type ret = (unwrap(ctx)->function); \ > + pipe_mutex_unlock(ts_ctx->mutex); \ > + return ret; > + > + > +static void threadsafe_destroy(struct pipe_context *ctx) { > + THREADSAFE_CALL_VOID(ctx, destroy(unwrap(ctx))); > + FREE(ctx); > +} > + > +static void *threadsafe_create_sampler_state(struct pipe_context *ctx, > + const struct pipe_sampler_state > *state) { > + THREADSAFE_CALL_RET(ctx, void*, create_sampler_state(unwrap(ctx), state)); > +} > + > +static struct pipe_query *threadsafe_create_query(struct pipe_context *ctx, > + unsigned query_type, > + unsigned index) { > + THREADSAFE_CALL_RET(ctx, struct pipe_query*, > + create_query(unwrap(ctx), query_type, index)); > +} > + > +static void threadsafe_bind_compute_state(struct pipe_context *ctx, > + void * state) { > + THREADSAFE_CALL_VOID(ctx, bind_compute_state(unwrap(ctx), state)); > +} > + > +static void threadsafe_bind_sampler_states(struct pipe_context *ctx, > + unsigned shader, unsigned > start_slot, > + unsigned num_samplers, > + void **samplers) { > + THREADSAFE_CALL_VOID(ctx, > + bind_sampler_states(unwrap(ctx), shader, start_slot, num_samplers, > + samplers)); > +} > + > +static void threadsafe_set_sampler_views(struct pipe_context *ctx, > + unsigned shader, unsigned > start_slot, > + unsigned num_views, > + struct pipe_sampler_view ** views) { > + THREADSAFE_CALL_VOID(ctx, > + set_sampler_views(unwrap(ctx), shader, start_slot, num_views, views)); > +} > + > + > +static void threadsafe_set_compute_resources(struct pipe_context *ctx, > + unsigned start, unsigned count, > + struct pipe_surface > **resources) { > + THREADSAFE_CALL_VOID(ctx, > + set_compute_resources(unwrap(ctx), start, count, resources)); > +} > + > +static void threadsafe_set_global_binding(struct pipe_context *ctx, > + unsigned first, unsigned count, > + struct pipe_resource **resources, > + uint32_t **handles) { > + THREADSAFE_CALL_VOID(ctx, > + set_global_binding(unwrap(ctx), first, count, resources, handles)); > +} > + > +static void threadsafe_launch_grid(struct pipe_context *ctx, > + const uint *block_layout, > + const uint *grid_layout, > + uint32_t pc, const void *input) { > + THREADSAFE_CALL_VOID(ctx, > + launch_grid(unwrap(ctx), block_layout, grid_layout, pc, input)); > +} > + > +static void threadsafe_delete_compute_state(struct pipe_context *ctx, > + void *state) { > + THREADSAFE_CALL_VOID(ctx, delete_compute_state(unwrap(ctx), state)); > +} > + > +static void *threadsafe_create_compute_state(struct pipe_context *ctx, > + const struct pipe_compute_state > *state) { > + THREADSAFE_CALL_RET(ctx, void*, create_compute_state(unwrap(ctx), state)); > +} > + > +static void threadsafe_flush(struct pipe_context *ctx, > + struct pipe_fence_handle **fence, > + unsigned flags) { > + THREADSAFE_CALL_VOID(ctx, flush(unwrap(ctx), fence, flags)); > +} > + > +static struct pipe_sampler_view *threadsafe_create_sampler_view( > + struct pipe_context *ctx, > + struct pipe_resource *texture, > + const struct pipe_sampler_view > *templat) { > + THREADSAFE_CALL_RET(ctx, struct pipe_sampler_view*, > + create_sampler_view(unwrap(ctx), texture, templat)); > +} > + > +static void threadsafe_resource_copy_region(struct pipe_context *ctx, > + struct pipe_resource *dst, > + unsigned dst_level, > + unsigned dstx, unsigned dsty, unsigned dstz, > + struct pipe_resource *src, > + unsigned src_level, > + const struct pipe_box *src_box) { > + THREADSAFE_CALL_VOID(ctx, > + resource_copy_region(unwrap(ctx), dst, dst_level, dstx, dsty, dstz, > src, > + src_level, src_box)); > +} > + > +static void threadsafe_sampler_view_destroy(struct pipe_context *ctx, > + struct pipe_sampler_view *view) { > + THREADSAFE_CALL_VOID(ctx, sampler_view_destroy(unwrap(ctx), view)); > +} > + > +static struct pipe_surface *threadsafe_create_surface(struct pipe_context > *ctx, > + struct pipe_resource *resource, > + const struct pipe_surface > *templat) { > + THREADSAFE_CALL_RET(ctx, struct pipe_surface*, > + create_surface(unwrap(ctx), resource, templat)); > +} > + > + > +static void threadsafe_surface_destroy(struct pipe_context *ctx, > + struct pipe_surface *surface) { > + THREADSAFE_CALL_VOID(ctx, surface_destroy(unwrap(ctx), surface)); > +} > + > +static void threadsafe_transfer_inline_write(struct pipe_context *ctx, > + struct pipe_resource *resource, > + unsigned level, unsigned usage, > + const struct pipe_box *pipe_box, > + const void *data, > + unsigned stride, > + unsigned layer_stride) { > + THREADSAFE_CALL_VOID(ctx, > + transfer_inline_write(unwrap(ctx), resource, level, usage, pipe_box, > data, > + stride, layer_stride)); > +} > + > +static void *threadsafe_transfer_map(struct pipe_context *ctx, > + struct pipe_resource *resource, > + unsigned level, > + unsigned usage, > + const struct pipe_box *box, > + struct pipe_transfer **out_transfer) { > + THREADSAFE_CALL_RET(ctx, void*, > + transfer_map(unwrap(ctx), resource, level, usage, box, out_transfer)); > +} > + > +static void threadsafe_transfer_unmap(struct pipe_context *ctx, > + struct pipe_transfer *transfer) { > + THREADSAFE_CALL_VOID(ctx, transfer_unmap(unwrap(ctx), transfer)); > +} > + > +static void threadsafe_delete_sampler_state(struct pipe_context *ctx, > + void *state) { > + THREADSAFE_CALL_VOID(ctx, delete_sampler_state(unwrap(ctx), state)); > +} > + > +static void threadsafe_end_query(struct pipe_context *ctx, > + struct pipe_query *q) { > + THREADSAFE_CALL_VOID(ctx, end_query(unwrap(ctx), q)); > +} > + > +static void threadsafe_destroy_query(struct pipe_context *ctx, > + struct pipe_query *q) { > + THREADSAFE_CALL_VOID(ctx, destroy_query(unwrap(ctx), q)); > +} > + > +static boolean threadsafe_get_query_result(struct pipe_context *ctx, > + struct pipe_query *q, > + boolean wait, > + union pipe_query_result *result) { > + THREADSAFE_CALL_RET(ctx, boolean, > + get_query_result(unwrap(ctx), q, wait, result)); > +} > + > +#define INIT_FUNCTION(name) \ > + ts_ctx->base.name = threadsafe_ ## name; > + > +struct pipe_context *pipe_threadsafe_context(struct pipe_context *ctx) { > + struct threadsafe_context *ts_ctx = CALLOC_STRUCT(threadsafe_context); > + > + ts_ctx->ctx = ctx; > + pipe_mutex_init(ts_ctx->mutex); > + > + INIT_FUNCTION(destroy); > + INIT_FUNCTION(create_query); > + INIT_FUNCTION(bind_compute_state); > + INIT_FUNCTION(bind_sampler_states); > + INIT_FUNCTION(set_sampler_views); > + INIT_FUNCTION(set_compute_resources); > + INIT_FUNCTION(set_global_binding); > + INIT_FUNCTION(launch_grid); > + INIT_FUNCTION(delete_compute_state); > + INIT_FUNCTION(create_compute_state); > + INIT_FUNCTION(flush); > + INIT_FUNCTION(create_sampler_view); > + INIT_FUNCTION(resource_copy_region); > + INIT_FUNCTION(sampler_view_destroy); > + INIT_FUNCTION(create_surface); > + INIT_FUNCTION(surface_destroy); > + INIT_FUNCTION(transfer_inline_write); > + INIT_FUNCTION(transfer_map); > + INIT_FUNCTION(transfer_unmap); > + INIT_FUNCTION(create_sampler_state); > + INIT_FUNCTION(delete_sampler_state); > + INIT_FUNCTION(end_query); > + INIT_FUNCTION(destroy_query); > + INIT_FUNCTION(get_query_result); > + return &ts_ctx->base; > +} > diff --git a/src/gallium/state_trackers/clover/core/pipe_threadsafe_screen.c > b/src/gallium/state_trackers/clover/core/pipe_threadsafe_screen.c > new file mode 100644 > index 0000000..cc2f842 > --- /dev/null > +++ b/src/gallium/state_trackers/clover/core/pipe_threadsafe_screen.c > @@ -0,0 +1,184 @@ > +/* > + * Copyright 2015 Advanced Micro Devices, Inc. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > THE > + * SOFTWARE. > + * > + * Authors: Tom Stellard <thomas.stell...@amd.com> > + * > + */ > + > +#include <stdio.h> > + > + > +/** > + * \file > + * > + * threadsafe_screen is a wrapper around a pipe_screen to make it thread > + * safe. Some functions are already theadsafe and don't require the mutex > + * guard. > + */ > + > +#include "os/os_thread.h" > +#include "pipe/p_context.h" > +#include "pipe/p_screen.h" > +#include "util/u_memory.h" > + > +#include "threadsafe.h" > + > +struct threadsafe_screen { > + struct pipe_screen base; > + struct pipe_screen *screen; > + pipe_mutex mutex; > +}; > + > +static struct pipe_screen *unwrap(struct pipe_screen *screen) { > + if (!screen) > + return NULL; > + struct threadsafe_screen *ts_screen = (struct threadsafe_screen*)screen; > + return ts_screen->screen; > +} > + > +#define THREADSAFE_CALL_VOID(screen, function) \ > + struct threadsafe_screen *ts_screen = (struct > threadsafe_screen*)(screen); \ > + pipe_mutex_lock(ts_screen->mutex); \ > + (unwrap(screen)->function); \ > + pipe_mutex_unlock(ts_screen->mutex); > + > +#define THREADSAFE_CALL_RET(screen, return_type, function) \ > + struct threadsafe_screen *ts_screen = (struct > threadsafe_screen*)(screen); \ > + pipe_mutex_lock(ts_screen->mutex); \ > + return_type ret = (unwrap(screen)->function); \ > + pipe_mutex_unlock(ts_screen->mutex); \ > + return ret; > + > +static struct pipe_context *threadsafe_context_create( > + struct pipe_screen > *screen, > + void *priv) { > + struct threadsafe_screen *ts_screen = (struct threadsafe_screen*)(screen); > + struct pipe_context *ctx; > + > + pipe_mutex_lock(ts_screen->mutex); > + ctx = unwrap(screen)->context_create(unwrap(screen), priv); > + ctx = pipe_threadsafe_context(ctx); > + ctx->screen = screen; > + pipe_mutex_unlock(ts_screen->mutex); > + return ctx; > +} > + > +static void threadsafe_destroy(struct pipe_screen *screen) { > + THREADSAFE_CALL_VOID(screen, destroy(unwrap(screen))); > + FREE(screen); > +} > + > +static boolean threadsafe_is_format_supported(struct pipe_screen *screen, > + enum pipe_format format, > + enum pipe_texture_target > target, > + unsigned sample_count, > + unsigned bindings) { > + return unwrap(screen)->is_format_supported(unwrap(screen), format, target, > + sample_count, bindings); > +} > + > + > +static struct pipe_resource *threadsafe_resource_create( > + struct pipe_screen *screen, > + const struct pipe_resource > *templat) { > + THREADSAFE_CALL_RET(screen, struct pipe_resource*, > + resource_create(unwrap(screen), templat)); > +} > + > +static void threadsafe_resource_destroy(struct pipe_screen *screen, > + struct pipe_resource *pt) { > + THREADSAFE_CALL_VOID(screen, resource_destroy(unwrap(screen), pt)); > +} > + > +static int threadsafe_get_compute_param(struct pipe_screen *screen, > + enum pipe_compute_cap param, > + void *ret) { > + return unwrap(screen)->get_compute_param(unwrap(screen), param, ret); > +} > + > +static int threadsafe_get_param(struct pipe_screen *screen, > + enum pipe_cap param) { > + return unwrap(screen)->get_param(unwrap(screen), param); > +} > + > +static const char* threadsafe_get_name(struct pipe_screen *screen) { > + return unwrap(screen)->get_name(unwrap(screen)); > +} > + > +static const char* threadsafe_get_device_vendor(struct pipe_screen *screen) { > + return unwrap(screen)->get_device_vendor(unwrap(screen)); > +} > + > +static int threadsafe_get_shader_param(struct pipe_screen *screen, > + unsigned shader, > + enum pipe_shader_cap param) { > + return unwrap(screen)->get_shader_param(unwrap(screen), shader, param); > +} > + > +static void threadsafe_fence_reference(struct pipe_screen *screen, > + struct pipe_fence_handle **ptr, > + struct pipe_fence_handle *fence) { > + THREADSAFE_CALL_VOID(screen, fence_reference(unwrap(screen), ptr, fence)); > +} > + > +static uint64_t threadsafe_get_timestamp(struct pipe_screen *screen) { > + THREADSAFE_CALL_RET(screen, uint64_t, get_timestamp(unwrap(screen))); > +} > + > +static boolean threadsafe_fence_signalled(struct pipe_screen *screen, > + struct pipe_fence_handle *fence) { > + THREADSAFE_CALL_RET(screen, boolean, fence_signalled(unwrap(screen), > fence)); > +} > + > +static boolean threadsafe_fence_finish(struct pipe_screen *screen, > + struct pipe_fence_handle *fence, > + uint64_t timeout) { > + THREADSAFE_CALL_RET(screen, boolean, > + fence_finish(unwrap(screen), fence, timeout)); > +} > + > +#define INIT_FUNCTION(name) \ > + ts_screen->base.name = threadsafe_ ## name; > + > +struct pipe_screen *pipe_threadsafe_screen(struct pipe_screen *screen) { > + struct threadsafe_screen *ts_screen = CALLOC_STRUCT(threadsafe_screen); > + > + ts_screen->screen = screen; > + pipe_mutex_init(ts_screen->mutex); > + > + INIT_FUNCTION(context_create); > + INIT_FUNCTION(destroy); > + INIT_FUNCTION(is_format_supported); > + INIT_FUNCTION(resource_create); > + INIT_FUNCTION(resource_destroy); > + INIT_FUNCTION(get_compute_param); > + INIT_FUNCTION(get_param); > + INIT_FUNCTION(get_name); > + INIT_FUNCTION(get_device_vendor); > + INIT_FUNCTION(get_shader_param); > + INIT_FUNCTION(fence_reference); > + INIT_FUNCTION(get_timestamp); > + INIT_FUNCTION(fence_signalled); > + INIT_FUNCTION(fence_finish); > + > + return &ts_screen->base; > +} > diff --git a/src/gallium/state_trackers/clover/core/threadsafe.h > b/src/gallium/state_trackers/clover/core/threadsafe.h > new file mode 100644 > index 0000000..f49ff8c > --- /dev/null > +++ b/src/gallium/state_trackers/clover/core/threadsafe.h > @@ -0,0 +1,39 @@ > +/* > + * Copyright 2015 Advanced Micro Devices, Inc. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > THE > + * SOFTWARE. > + * > + * Authors: Tom Stellard <thomas.stell...@amd.com> > + * > + */ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +struct pipe_context; > +struct pipe_screen; > + > +struct pipe_context *pipe_threadsafe_context(struct pipe_context *ctx); > +struct pipe_screen *pipe_threadsafe_screen(struct pipe_screen *screen); > + > +#ifdef __cplusplus > +} > +#endif > diff --git a/src/gallium/targets/opencl/Makefile.am > b/src/gallium/targets/opencl/Makefile.am > index 5daf327..268370f 100644 > --- a/src/gallium/targets/opencl/Makefile.am > +++ b/src/gallium/targets/opencl/Makefile.am > @@ -38,7 +38,8 @@ lib@OPENCL_LIBNAME@_la_LIBADD = \ > -lclangEdit \ > -lclangLex \ > -lclangBasic \ > - $(LLVM_LIBS) > + $(LLVM_LIBS) \ > + $(PTHREAD_LIBS) > > nodist_EXTRA_lib@OPENCL_LIBNAME@_la_SOURCES = dummy.cpp > lib@OPENCL_LIBNAME@_la_SOURCES = > -- > 2.0.4
This seems to be growing into a wrapping pipe driver kind of like noop or trace, so it might deserve its own directory in gallium/drivers even if no other state tracker currently requires contexts to be thread safe. In any case it implements a lower-level API than anything else inside clover/core, so a separate directory would be a better fit if you decide to keep it inside clover (e.g. clover/pipe/threadsafe.h?). The situation with screens is different, because many APIs will want it to be thread-safe. I guess there are two ways to guarantee thread safety of screens: Make it the driver's responsibility or the state tracker's responsibility (in both cases your screen wrapper *might* be useful for state trackers other than clover or drivers to obtain a thread-safe screen out of a thread-unsafe one, but in the latter case drivers are likely to be able to implement things more efficiently, with finer-grained or no locking at all). You seem to have taken a mixed approach with some hooks being thread-safe and some others not, this seems strange and I guess it should be thoroughly documented if there is some reason to do it.
signature.asc
Description: PGP signature
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev