aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/compute/skc/platforms/cl_12/styling_cl_12.c
diff options
context:
space:
mode:
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.c339
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;
+}
+
+//
+//
+//