diff options
Diffstat (limited to 'src/compute/skc/platforms/cl_12/styling_cl_12.c')
-rw-r--r-- | src/compute/skc/platforms/cl_12/styling_cl_12.c | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/src/compute/skc/platforms/cl_12/styling_cl_12.c b/src/compute/skc/platforms/cl_12/styling_cl_12.c new file mode 100644 index 0000000000..6c84fe6f70 --- /dev/null +++ b/src/compute/skc/platforms/cl_12/styling_cl_12.c @@ -0,0 +1,339 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can + * be found in the LICENSE file. + * + */ + +// +// NOTES: +// +// - this particular object only needs a command queue for a short +// time so consider acquiring/releasing the command queue on demand +// but only if command queues are cached and expensive to keep +// + +#include "common/cl/assert_cl.h" + +#include "styling_cl_12.h" +#include "extent_cl_12.h" +#include "runtime_cl_12.h" + +#include "context.h" +#include "styling_types.h" + +// +// +// + +static +void +skc_styling_unmap_complete(skc_grid_t const grid) +{ + struct skc_styling_impl * const impl = skc_grid_get_data(grid); + + impl->state = SKC_STYLING_STATE_SEALED; + + skc_grid_complete(grid); +} + +static +void +skc_styling_unmap_cb(cl_event event, cl_int status, skc_grid_t const grid) +{ + SKC_CL_CB(status); + + struct skc_styling_impl * const impl = skc_grid_get_data(grid); + struct skc_scheduler * const scheduler = impl->runtime->scheduler; + + // as quickly as possible, enqueue next stage in pipeline to context command scheduler + SKC_SCHEDULER_SCHEDULE(scheduler,skc_styling_unmap_complete,grid); +} + +static +void +skc_styling_grid_pfn_execute(skc_grid_t const grid) +{ + struct skc_styling_impl * const impl = skc_grid_get_data(grid); + struct skc_styling * const styling = impl->styling; + + // + // unmap all extents + // + cl_event complete; + + skc_extent_phwN_pdrN_unmap(&impl->layers,styling->layers.extent,impl->cq,NULL); + skc_extent_phwN_pdrN_unmap(&impl->groups,styling->groups.extent,impl->cq,NULL); + skc_extent_phwN_pdrN_unmap(&impl->extras,styling->extras.extent,impl->cq,&complete); + + // set the event + cl(SetEventCallback(complete,CL_COMPLETE,skc_styling_unmap_cb,grid)); + cl(ReleaseEvent(complete)); + + // flush command queue + cl(Flush(impl->cq)); +} + +// +// +// + +static +void +skc_styling_pfn_seal(struct skc_styling_impl * const impl) +{ + // return if sealing or sealed + if (impl->state >= SKC_STYLING_STATE_SEALING) + return; + + struct skc_runtime * const runtime = impl->runtime; + struct skc_scheduler * const scheduler = runtime->scheduler; + + // + // otherwise, wait for UNSEALING > UNSEALED transition + // + if (impl->state == SKC_STYLING_STATE_UNSEALING) + { + SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->state != SKC_STYLING_STATE_UNSEALED); + } + + // + // we're unsealed so we need to seal and start the grid + // + impl->state = SKC_STYLING_STATE_SEALING; + impl->grid = SKC_GRID_DEPS_ATTACH(runtime->deps, + NULL, + impl, + NULL, // no waiting + skc_styling_grid_pfn_execute, + NULL); // no dispose + + // no need to force -- styling has no dependencies + skc_grid_start(impl->grid); +} + +// +// +// + +void +skc_styling_unseal_complete(struct skc_styling_impl * const impl) +{ + struct skc_runtime * const runtime = impl->runtime; + + // we're now unsealed + impl->state = SKC_STYLING_STATE_UNSEALED; +} + +static +void +skc_styling_unseal_cb(cl_event event, cl_int status, struct skc_styling_impl * const impl) +{ + SKC_CL_CB(status); + + // as quickly as possible, enqueue next stage in pipeline to context command scheduler + SKC_SCHEDULER_SCHEDULE(impl->runtime->scheduler,skc_styling_unseal_complete,impl); +} + +static +void +skc_styling_pfn_unseal(struct skc_styling_impl * const impl, skc_bool const block) +{ + // return if already unsealed + if (impl->state == SKC_STYLING_STATE_UNSEALED) + return; + + // + // otherwise, we're going to need to pump the scheduler + // + struct skc_runtime * const runtime = impl->runtime; + struct skc_scheduler * const scheduler = runtime->scheduler; + + // + // wait for UNSEALING > UNSEALED transition + // + if (impl->state == SKC_STYLING_STATE_UNSEALING) + { + if (block) { + SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->state != SKC_STYLING_STATE_UNSEALED); + } + return; + } + + // + // otherwise, wait for SEALING > SEALED transition ... + // + if (impl->state == SKC_STYLING_STATE_SEALING) + { + // wait if sealing + SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->state != SKC_STYLING_STATE_SEALED); + } + + // wait for rendering locks to be released + SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->lock_count > 0); + + // ... and then unseal the styling object + impl->state = SKC_STYLING_STATE_UNSEALING; + + // defensively NULL the grid reference + impl->grid = NULL; // defensive + + // set styling pointers with mapped extents + cl_event complete; + + struct skc_styling * const styling = impl->styling; + + styling->layers.extent = skc_extent_phwN_pdrN_map(&impl->layers,impl->cq,NULL); + styling->groups.extent = skc_extent_phwN_pdrN_map(&impl->groups,impl->cq,NULL); + styling->extras.extent = skc_extent_phwN_pdrN_map(&impl->extras,impl->cq,&complete); + + cl(SetEventCallback(complete,CL_COMPLETE,skc_styling_unseal_cb,impl)); + cl(ReleaseEvent(complete)); + + // flush it + cl(Flush(impl->cq)); + + // wait until unsealed... + if (block) { + SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->state != SKC_STYLING_STATE_UNSEALED); + } +} + +// +// +// + +static +void +skc_styling_pfn_release(struct skc_styling_impl * const impl) +{ + if (--impl->styling->ref_count != 0) + return; + + // + // otherwise, unmap all resources by sealing and delete + // + skc_styling_pfn_seal(impl); + + struct skc_runtime * const runtime = impl->runtime; + struct skc_scheduler * const scheduler = runtime->scheduler; + + // wait until sealed + SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->state != SKC_STYLING_STATE_SEALED); + + // wait for locks to drain + SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->lock_count > 0) + + // + // styling is now disposable + // + + // free styling host + skc_runtime_host_perm_free(runtime,impl->styling); + + // release the cq + skc_runtime_release_cq_in_order(runtime,impl->cq); + + // free extents + skc_extent_phwN_pdrN_free(runtime,&impl->layers); + skc_extent_phwN_pdrN_free(runtime,&impl->groups); + skc_extent_phwN_pdrN_free(runtime,&impl->extras); + + // free styling impl + skc_runtime_host_perm_free(runtime,impl); +} + +// +// +// + +void +skc_styling_retain_and_lock(struct skc_styling * const styling) +{ + skc_styling_retain(styling); + + styling->impl->lock_count += 1; +} + +void +skc_styling_unlock_and_release(struct skc_styling * const styling) +{ + styling->impl->lock_count -= 1; + + skc_styling_pfn_release(styling->impl); +} + +// +// +// + +skc_err +skc_styling_cl_12_create(struct skc_context * const context, + struct skc_styling * * const styling, + skc_uint const layers_count, + skc_uint const groups_count, + skc_uint const extras_count) +{ + // retain the context + // skc_context_retain(context); + + // allocate the impl + struct skc_runtime * const runtime = context->runtime; + struct skc_styling_impl * const impl = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE,sizeof(*impl)); + + // allocate styling + (*styling) = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE,sizeof(**styling)); + (*styling)->context = context; + (*styling)->impl = impl; + + // intialize impl + impl->styling = (*styling); + impl->runtime = runtime; + + SKC_ASSERT_STATE_INIT(impl,SKC_STYLING_STATE_SEALED); + + impl->lock_count = 0; + + impl->cq = skc_runtime_acquire_cq_in_order(runtime); + + // + // The styling object is unique in that the API lets the user + // specify resource limits + // + // The styling object is a simple container that can have wildly + // varying resource requirements (but still relatively modest). + // + // Additionally, an advanced SKC programmer may want to create many + // styling and composition objects as they're relatively cheap. + // + skc_extent_phwN_pdrN_alloc(runtime,&impl->layers,sizeof(*(*styling)->layers.extent) * layers_count); + skc_extent_phwN_pdrN_alloc(runtime,&impl->groups,sizeof(*(*styling)->groups.extent) * groups_count); + skc_extent_phwN_pdrN_alloc(runtime,&impl->extras,sizeof(*(*styling)->extras.extent) * extras_count); + + // initialize styling + (*styling)->layers.size = layers_count; + (*styling)->groups.size = groups_count; + (*styling)->extras.size = extras_count; + + (*styling)->layers.count = 0; + (*styling)->groups.count = 0; + (*styling)->extras.count = 0; + + // save pfns + (*styling)->seal = skc_styling_pfn_seal; + (*styling)->unseal = skc_styling_pfn_unseal; + (*styling)->release = skc_styling_pfn_release; + + // set ref count + (*styling)->ref_count = 1; + + // map the extents by unsealing + skc_styling_pfn_unseal(impl,false); + + return SKC_ERR_SUCCESS; +} + +// +// +// |