• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can
5  * be found in the LICENSE file.
6  *
7  */
8 
9 //
10 //
11 //
12 
13 #include <stdlib.h>
14 #include <stdio.h>
15 
16 #include "hs/cl/hs_cl.h"
17 
18 #include "common/cl/assert_cl.h"
19 
20 #include "composition_cl_12.h"
21 #include "config_cl.h"
22 
23 #include "context.h"
24 #include "raster.h"
25 #include "handle.h"
26 
27 #include "runtime_cl_12.h"
28 
29 #include "common.h"
30 #include "tile.h"
31 
32 //
33 // TTCK (32-BIT COMPARE) v1:
34 //
35 //  0                                                           63
36 //  | PAYLOAD/TTSB/TTPB ID | PREFIX | ESCAPE | LAYER |  X  |  Y  |
37 //  +----------------------+--------+--------+-------+-----+-----+
38 //  |          30          |    1   |    1   |   18  |  7  |  7  |
39 //
40 //
41 // TTCK (32-BIT COMPARE) v2:
42 //
43 //  0                                                           63
44 //  | PAYLOAD/TTSB/TTPB ID | PREFIX | ESCAPE | LAYER |  X  |  Y  |
45 //  +----------------------+--------+--------+-------+-----+-----+
46 //  |          30          |    1   |    1   |   15  |  9  |  8  |
47 //
48 //
49 // TTCK (64-BIT COMPARE) -- achieves 4K x 4K with an 8x16 tile:
50 //
51 //  0                                                           63
52 //  | PAYLOAD/TTSB/TTPB ID | PREFIX | ESCAPE | LAYER |  X  |  Y  |
53 //  +----------------------+--------+--------+-------+-----+-----+
54 //  |          27          |    1   |    1   |   18  |  9  |  8  |
55 //
56 
57 union skc_ttck
58 {
59   skc_ulong   u64;
60   skc_uint2   u32v2;
61 
62   struct {
63     skc_uint  id         : SKC_TTCK_LO_BITS_ID;
64     skc_uint  prefix     : SKC_TTCK_LO_BITS_PREFIX;
65     skc_uint  escape     : SKC_TTCK_LO_BITS_ESCAPE;
66     skc_uint  layer_lo   : SKC_TTCK_LO_BITS_LAYER;
67     skc_uint  layer_hi   : SKC_TTCK_HI_BITS_LAYER;
68     skc_uint  x          : SKC_TTCK_HI_BITS_X;
69     skc_uint  y          : SKC_TTCK_HI_BITS_Y;
70   };
71 
72   struct {
73     skc_ulong na0        : SKC_TTCK_LO_BITS_ID_PREFIX_ESCAPE;
74     skc_ulong layer      : SKC_TTCK_BITS_LAYER;
75     skc_ulong na1        : SKC_TTCK_HI_BITS_YX;
76   };
77 
78   struct {
79     skc_uint  na2;
80     skc_uint  na3        : SKC_TTCK_HI_BITS_LAYER;
81     skc_uint  yx         : SKC_TTCK_HI_BITS_YX;
82   };
83 };
84 
85 //
86 // FIXME -- accept floats on host but convert to subpixel offsets
87 // before appending to command ring
88 //
89 
90 #define SKC_PLACE_CMD_TX_CONVERT(f)  0
91 #define SKC_PLACE_CMD_TY_CONVERT(f)  0
92 
93 //
94 // COMPOSITION PLACE
95 //
96 // This is a snapshot of the host-side command queue.
97 //
98 // Note that the composition command extent could be implemented as
99 // either a mapped buffer or simply copied to an ephemeral extent.
100 //
101 // This implementation may vary between compute platforms.
102 //
103 
104 struct skc_composition_place
105 {
106   struct skc_composition_impl      * impl;
107 
108   cl_command_queue                   cq;
109 
110   struct skc_extent_phw1g_tdrNs_snap cmds;
111 
112   skc_subbuf_id_t                    id;
113 };
114 
115 //
116 // Forward declarations
117 //
118 
119 static
120 void
121 skc_composition_unseal_block(struct skc_composition_impl * const impl,
122                              skc_bool                      const block);
123 
124 //
125 //
126 //
127 
128 static
129 void
skc_composition_pfn_release(struct skc_composition_impl * const impl)130 skc_composition_pfn_release(struct skc_composition_impl * const impl)
131 {
132   if (--impl->composition->ref_count != 0)
133     return;
134 
135   //
136   // otherwise, dispose of all resources
137   //
138 
139   // the unsealed state is a safe state to dispose of resources
140   skc_composition_unseal_block(impl,true); // block
141 
142   struct skc_runtime * const runtime = impl->runtime;
143 
144   // free host composition
145   skc_runtime_host_perm_free(runtime,impl->composition);
146 
147   // release the cq
148   skc_runtime_release_cq_in_order(runtime,impl->cq);
149 
150   // release kernels
151   cl(ReleaseKernel(impl->kernels.place));
152   cl(ReleaseKernel(impl->kernels.segment));
153 
154   // release extents
155   skc_extent_phw1g_tdrNs_free(runtime,&impl->cmds.extent);
156   skc_extent_phrw_free       (runtime,&impl->saved.extent);
157   skc_extent_phr_pdrw_free   (runtime,&impl->atomics);
158 
159   skc_extent_pdrw_free       (runtime,&impl->keys);
160   skc_extent_pdrw_free       (runtime,&impl->offsets);
161 
162   // free composition impl
163   skc_runtime_host_perm_free(runtime,impl);
164 }
165 
166 //
167 //
168 //
169 
170 static
171 void
skc_composition_place_grid_pfn_dispose(skc_grid_t const grid)172 skc_composition_place_grid_pfn_dispose(skc_grid_t const grid)
173 {
174   struct skc_composition_place * const place   = skc_grid_get_data(grid);
175   struct skc_composition_impl  * const impl    = place->impl;
176   struct skc_runtime           * const runtime = impl->runtime;
177 
178   // release cq
179   skc_runtime_release_cq_in_order(runtime,place->cq);
180 
181   // unmap the snapshot (could be a copy)
182   skc_extent_phw1g_tdrNs_snap_free(runtime,&place->cmds);
183 
184   // release place struct
185   skc_runtime_host_temp_free(runtime,place,place->id);
186 
187   // release impl
188   skc_composition_pfn_release(impl);
189 }
190 
191 //
192 //
193 //
194 
195 static
196 void
skc_composition_place_read_complete(skc_grid_t const grid)197 skc_composition_place_read_complete(skc_grid_t const grid)
198 {
199   skc_grid_complete(grid);
200 }
201 
202 static
203 void
skc_composition_place_read_cb(cl_event event,cl_int status,skc_grid_t const grid)204 skc_composition_place_read_cb(cl_event event, cl_int status, skc_grid_t const grid)
205 {
206   SKC_CL_CB(status);
207 
208   struct skc_composition_place * const place     = skc_grid_get_data(grid);
209   struct skc_composition_impl  * const impl      = place->impl;
210   struct skc_runtime           * const runtime   = impl->runtime;
211   struct skc_scheduler         * const scheduler = runtime->scheduler;
212 
213   // as quickly as possible, enqueue next stage in pipeline to context command scheduler
214   SKC_SCHEDULER_SCHEDULE(scheduler,skc_composition_place_read_complete,grid);
215 }
216 
217 static
218 void
skc_composition_place_grid_pfn_execute(skc_grid_t const grid)219 skc_composition_place_grid_pfn_execute(skc_grid_t const grid)
220 {
221   //
222   // FILLS EXPAND
223   //
224   // need result of cmd counts before launching RASTERIZE grids
225   //
226   // - OpenCL 1.2: copy atomic counters back to host and launch RASTERIZE grids from host
227   // - OpenCL 2.x: have a kernel size and launch RASTERIZE grids from device
228   // - or launch a device-wide grid that feeds itself but that's unsatisfying
229   //
230   struct skc_composition_place * const place   = skc_grid_get_data(grid);
231   struct skc_composition_impl  * const impl    = place->impl;
232   struct skc_runtime           * const runtime = impl->runtime;
233 
234   skc_uint  const work_size = skc_extent_ring_snap_count(place->cmds.snap);
235   skc_uint4 const clip      = { 0, 0, SKC_UINT_MAX, SKC_UINT_MAX };
236 
237   // initialize kernel args
238   cl(SetKernelArg(impl->kernels.place,0,SKC_CL_ARG(impl->runtime->block_pool.blocks.drw)));
239   cl(SetKernelArg(impl->kernels.place,1,SKC_CL_ARG(impl->atomics.drw)));
240   cl(SetKernelArg(impl->kernels.place,2,SKC_CL_ARG(impl->keys.drw)));
241   cl(SetKernelArg(impl->kernels.place,3,SKC_CL_ARG(place->cmds.drN)));
242   cl(SetKernelArg(impl->kernels.place,4,SKC_CL_ARG(runtime->handle_pool.map.drw)));
243   cl(SetKernelArg(impl->kernels.place,5,SKC_CL_ARG(clip))); // FIXME -- convert the clip to yx0/yx1 format
244   cl(SetKernelArg(impl->kernels.place,6,SKC_CL_ARG(work_size)));
245 
246   // launch kernel
247   skc_device_enqueue_kernel(runtime->device,
248                             SKC_DEVICE_KERNEL_ID_PLACE,
249                             place->cq,
250                             impl->kernels.place,
251                             work_size,
252                             0,NULL,NULL);
253   //
254   // copy atomics back after every place launch
255   //
256   cl_event complete;
257 
258   skc_extent_phr_pdrw_read(&impl->atomics,place->cq,&complete);
259 
260   cl(SetEventCallback(complete,CL_COMPLETE,skc_composition_place_read_cb,grid));
261   cl(ReleaseEvent(complete));
262 
263   // flush command queue
264   cl(Flush(place->cq));
265 }
266 
267 //
268 //
269 //
270 
271 static
272 void
skc_composition_snap(struct skc_composition_impl * const impl)273 skc_composition_snap(struct skc_composition_impl * const impl)
274 {
275   skc_composition_retain(impl->composition);
276 
277   skc_subbuf_id_t id;
278 
279   struct skc_composition_place * const place = skc_runtime_host_temp_alloc(impl->runtime,
280                                                                            SKC_MEM_FLAGS_READ_WRITE,
281                                                                            sizeof(*place),&id,NULL);
282 
283   // save the subbuf id
284   place->id = id;
285 
286   // save backpointer
287   place->impl = impl;
288 
289   // set grid data
290   skc_grid_set_data(impl->grids.place,place);
291 
292   // acquire command queue
293   place->cq = skc_runtime_acquire_cq_in_order(impl->runtime);
294 
295   // checkpoint the ring
296   skc_extent_ring_checkpoint(&impl->cmds.ring);
297 
298   // make a snapshot
299   skc_extent_phw1g_tdrNs_snap_init(impl->runtime,&impl->cmds.ring,&place->cmds);
300 
301   // unmap the snapshot (could be a copy)
302   skc_extent_phw1g_tdrNs_snap_alloc(impl->runtime,
303                                     &impl->cmds.extent,
304                                     &place->cmds,
305                                     place->cq,
306                                     NULL);
307 
308   skc_grid_force(impl->grids.place);
309 }
310 
311 //
312 //
313 //
314 
315 static
316 void
skc_composition_pfn_seal(struct skc_composition_impl * const impl)317 skc_composition_pfn_seal(struct skc_composition_impl * const impl)
318 {
319   // return if sealing or sealed
320   if (impl->state >= SKC_COMPOSITION_STATE_SEALING)
321     return;
322 
323   struct skc_runtime   * const runtime   = impl->runtime;
324   struct skc_scheduler * const scheduler = runtime->scheduler;
325 
326   //
327   // otherwise, wait for UNSEALING > UNSEALED transition
328   //
329   if (impl->state == SKC_COMPOSITION_STATE_UNSEALING)
330     {
331       SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->state != SKC_COMPOSITION_STATE_UNSEALED);
332     }
333   else // or we were already unsealed
334     {
335       // flush is there is work in progress
336       skc_uint const count = skc_extent_ring_wip_count(&impl->cmds.ring);
337 
338       if (count > 0) {
339         skc_composition_snap(impl);
340       }
341     }
342 
343   //
344   // now unsealed so we need to start sealing...
345   //
346   impl->state = SKC_COMPOSITION_STATE_SEALING;
347 
348   //
349   // the seal operation implies we should force start all dependencies
350   // that are still in a ready state
351   //
352   skc_grid_force(impl->grids.sort);
353 }
354 
355 //
356 //
357 //
358 
359 void
skc_composition_sort_execute_complete(struct skc_composition_impl * const impl)360 skc_composition_sort_execute_complete(struct skc_composition_impl * const impl)
361 {
362   // we're sealed
363   impl->state = SKC_COMPOSITION_STATE_SEALED;
364 
365   // this grid is done
366   skc_grid_complete(impl->grids.sort);
367 }
368 
369 static
370 void
skc_composition_sort_execute_cb(cl_event event,cl_int status,struct skc_composition_impl * const impl)371 skc_composition_sort_execute_cb(cl_event event, cl_int status, struct skc_composition_impl * const impl)
372 {
373   SKC_CL_CB(status);
374 
375   // as quickly as possible, enqueue next stage in pipeline to context command scheduler
376   SKC_SCHEDULER_SCHEDULE(impl->runtime->scheduler,skc_composition_sort_execute_complete,impl);
377 }
378 
379 static
380 void
skc_composition_sort_grid_pfn_execute(skc_grid_t const grid)381 skc_composition_sort_grid_pfn_execute(skc_grid_t const grid)
382 {
383   struct skc_composition_impl * const impl    = skc_grid_get_data(grid);
384   struct skc_runtime          * const runtime = impl->runtime;
385 
386   // we should be sealing
387   assert(impl->state == SKC_COMPOSITION_STATE_SEALING);
388 
389   struct skc_place_atomics * const atomics = impl->atomics.hr;
390 
391 #ifndef NDEBUG
392   fprintf(stderr,"composition sort: %u\n",atomics->keys);
393 #endif
394 
395   if (atomics->keys > 0)
396     {
397       uint32_t keys_padded_in, keys_padded_out;
398 
399       hs_cl_pad(runtime->hs,atomics->keys,&keys_padded_in,&keys_padded_out);
400 
401       hs_cl_sort(impl->runtime->hs,
402                  impl->cq,
403                  0,NULL,NULL,
404                  impl->keys.drw,
405                  NULL,
406                  atomics->keys,
407                  keys_padded_in,
408                  keys_padded_out,
409                  false);
410 
411       cl(SetKernelArg(impl->kernels.segment,0,SKC_CL_ARG(impl->keys.drw)));
412       cl(SetKernelArg(impl->kernels.segment,1,SKC_CL_ARG(impl->offsets.drw)));
413       cl(SetKernelArg(impl->kernels.segment,2,SKC_CL_ARG(impl->atomics.drw)));
414 
415       // find start of each tile
416       skc_device_enqueue_kernel(runtime->device,
417                                 SKC_DEVICE_KERNEL_ID_SEGMENT_TTCK,
418                                 impl->cq,
419                                 impl->kernels.segment,
420                                 atomics->keys,
421                                 0,NULL,NULL);
422     }
423 
424   cl_event complete;
425 
426   // next stage needs to know number of key segments
427   skc_extent_phr_pdrw_read(&impl->atomics,impl->cq,&complete);
428 
429   // register a callback
430   cl(SetEventCallback(complete,CL_COMPLETE,skc_composition_sort_execute_cb,impl));
431   cl(ReleaseEvent(complete));
432 
433   // flush cq
434   cl(Flush(impl->cq));
435 }
436 
437 //
438 //
439 //
440 
441 static
442 void
skc_composition_raster_release(struct skc_composition_impl * const impl)443 skc_composition_raster_release(struct skc_composition_impl * const impl)
444 {
445   //
446   // reference counts to rasters can only be released when the
447   // composition is unsealed and the atomics are reset.
448   //
449   skc_runtime_raster_device_release(impl->runtime,
450                                     impl->saved.extent.hrw,
451                                     impl->saved.count);
452   // reset count
453   impl->saved.count = 0;
454 }
455 
456 //
457 //
458 //
459 
460 static
461 void
skc_composition_unseal_block(struct skc_composition_impl * const impl,skc_bool const block)462 skc_composition_unseal_block(struct skc_composition_impl * const impl,
463                              skc_bool                      const block)
464 {
465   // return if already unsealed
466   if (impl->state == SKC_COMPOSITION_STATE_UNSEALED)
467     return;
468 
469   //
470   // otherwise, we're going to need to pump the scheduler
471   //
472   struct skc_scheduler * const scheduler = impl->runtime->scheduler;
473 
474   //
475   // wait for UNSEALING > UNSEALED transition
476   //
477   if (impl->state == SKC_COMPOSITION_STATE_UNSEALING)
478     {
479       if (block) {
480         SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->state != SKC_COMPOSITION_STATE_UNSEALED);
481       }
482       return;
483     }
484 
485   //
486   // wait for SEALING > SEALED transition ...
487   //
488   if (impl->state == SKC_COMPOSITION_STATE_SEALING)
489     {
490       // wait if sealing
491       SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->state != SKC_COMPOSITION_STATE_SEALED);
492     }
493 
494   // wait for rendering locks to be released
495   SKC_SCHEDULER_WAIT_WHILE(scheduler,impl->lock_count > 0);
496 
497   //
498   // no need to visit UNSEALING state with this implementation
499   //
500 
501   // acquire a new grid
502   impl->grids.sort = SKC_GRID_DEPS_ATTACH(impl->runtime->deps,
503                                           NULL,  // the composition state guards this
504                                           impl,
505                                           NULL,  // no waiting
506                                           skc_composition_sort_grid_pfn_execute,
507                                           NULL); // no dispose
508 
509   // mark composition as unsealed
510   impl->state = SKC_COMPOSITION_STATE_UNSEALED;
511 }
512 
513 //
514 // can only be called on a composition that was just unsealed
515 //
516 static
517 void
skc_composition_reset(struct skc_composition_impl * const impl)518 skc_composition_reset(struct skc_composition_impl * const impl)
519 {
520   // zero the atomics
521   skc_extent_phr_pdrw_zero(&impl->atomics,impl->cq,NULL);
522 
523   // flush it
524   cl(Flush(impl->cq));
525 
526   // release all the rasters
527   skc_composition_raster_release(impl);
528 }
529 
530 static
531 void
skc_composition_unseal_block_reset(struct skc_composition_impl * const impl,skc_bool const block,skc_bool const reset)532 skc_composition_unseal_block_reset(struct skc_composition_impl * const impl,
533                                    skc_bool                      const block,
534                                    skc_bool                      const reset)
535 {
536   skc_composition_unseal_block(impl,block);
537 
538   if (reset) {
539     skc_composition_reset(impl);
540   }
541 }
542 
543 //
544 //
545 //
546 
547 static
548 void
skc_composition_pfn_unseal(struct skc_composition_impl * const impl,skc_bool const reset)549 skc_composition_pfn_unseal(struct skc_composition_impl * const impl, skc_bool const reset)
550 {
551   skc_composition_unseal_block_reset(impl,false,reset);
552 }
553 
554 //
555 // only needs to create a grid
556 //
557 
558 static
559 void
skc_composition_place_create(struct skc_composition_impl * const impl)560 skc_composition_place_create(struct skc_composition_impl * const impl)
561 {
562   // acquire a grid
563   impl->grids.place = SKC_GRID_DEPS_ATTACH(impl->runtime->deps,
564                                            &impl->grids.place,
565                                            NULL,
566                                            NULL, // no waiting
567                                            skc_composition_place_grid_pfn_execute,
568                                            skc_composition_place_grid_pfn_dispose);
569 
570   // assign happens-after relationship
571   skc_grid_happens_after_grid(impl->grids.sort,impl->grids.place);
572 }
573 
574 
575 static
576 skc_err
skc_composition_pfn_place(struct skc_composition_impl * const impl,skc_raster_t const * rasters,skc_layer_id const * layer_ids,skc_float const * txs,skc_float const * tys,skc_uint count)577 skc_composition_pfn_place(struct skc_composition_impl * const impl,
578                           skc_raster_t          const *       rasters,
579                           skc_layer_id          const *       layer_ids,
580                           skc_float             const *       txs,
581                           skc_float             const *       tys,
582                           skc_uint                            count)
583 {
584   // block and yield if not unsealed
585   skc_composition_unseal_block(impl,true);
586 
587   //
588   // validate and retain all rasters
589   //
590   skc_err err;
591 
592   err = skc_runtime_handle_device_validate_retain(impl->runtime,
593                                                   SKC_TYPED_HANDLE_TYPE_IS_RASTER,
594                                                   rasters,
595                                                   count);
596   if (err)
597     return err;
598 
599   skc_runtime_handle_device_retain(impl->runtime,rasters,count);
600 
601   //
602   // save the stripped handles
603   //
604   skc_raster_t * saved = impl->saved.extent.hrw;
605 
606   saved             += impl->saved.count;
607   impl->saved.count += count;
608 
609   for (skc_uint ii=0; ii<count; ii++) {
610     saved[ii] = SKC_TYPED_HANDLE_TO_HANDLE(*rasters++);
611   }
612 
613   //
614   // - declare the place grid happens after the raster
615   // - copy place commands into ring
616   //
617   do {
618     skc_uint rem;
619 
620     // find out how much room is left in then ring's snap
621     // if the place ring is full -- let it drain
622     SKC_SCHEDULER_WAIT_WHILE(impl->runtime->scheduler,(rem = skc_extent_ring_wip_rem(&impl->cmds.ring)) == 0);
623 
624     // append commands
625     skc_uint avail = min(rem,count);
626 
627     // decrement count
628     count -= avail;
629 
630     // launch a place kernel after copying commands?
631     skc_bool const is_wip_full = (avail == rem);
632 
633     // if there is no place grid then create one
634     if (impl->grids.place == NULL)
635       {
636         skc_composition_place_create(impl);
637       }
638 
639     //
640     // FIXME -- OPTIMIZATION? -- the ring_wip_index_inc() test can
641     // be avoided by splitting into at most two intervals. It should
642     // be plenty fast as is though so leave for now.
643     //
644     union skc_cmd_place * const cmds = impl->cmds.extent.hw1;
645 
646     if ((txs == NULL) && (tys == NULL))
647       {
648         while (avail-- > 0)
649           {
650             skc_raster_t const raster = *saved++;
651 
652             skc_grid_happens_after_handle(impl->grids.place,raster);
653 
654             cmds[skc_extent_ring_wip_index_inc(&impl->cmds.ring)] =
655               (union skc_cmd_place){ raster, *layer_ids++, 0, 0 };
656           }
657       }
658     else if (txs == NULL)
659       {
660         while (avail-- > 0)
661           {
662             skc_raster_t const raster = *saved++;
663 
664             skc_grid_happens_after_handle(impl->grids.place,raster);
665 
666             cmds[skc_extent_ring_wip_index_inc(&impl->cmds.ring)] =
667               (union skc_cmd_place){ raster,
668                                      *layer_ids++,
669                                      0,
670                                      SKC_PLACE_CMD_TY_CONVERT(*tys++) };
671           }
672       }
673     else if (tys == NULL)
674       {
675         while (avail-- > 0)
676           {
677             skc_raster_t const raster = *saved++;
678 
679             skc_grid_happens_after_handle(impl->grids.place,raster);
680 
681             cmds[skc_extent_ring_wip_index_inc(&impl->cmds.ring)] =
682               (union skc_cmd_place){ raster,
683                                      *layer_ids++,
684                                      SKC_PLACE_CMD_TX_CONVERT(*txs++),
685                                      0 };
686           }
687       }
688     else
689       {
690         while (avail-- > 0)
691           {
692             skc_raster_t const raster = *saved++;
693 
694             skc_grid_happens_after_handle(impl->grids.place,raster);
695 
696             cmds[skc_extent_ring_wip_index_inc(&impl->cmds.ring)] =
697               (union skc_cmd_place){ raster,
698                                      *layer_ids++,
699                                      SKC_PLACE_CMD_TX_CONVERT(*txs++),
700                                      SKC_PLACE_CMD_TY_CONVERT(*tys++) };
701           }
702       }
703 
704     // launch place kernel?
705     if (is_wip_full) {
706       skc_composition_snap(impl);
707     }
708   } while (count > 0);
709 
710   return SKC_ERR_SUCCESS;
711 }
712 
713 //
714 //
715 //
716 
717 static
718 void
skc_composition_pfn_bounds(struct skc_composition_impl * const impl,skc_int bounds[4])719 skc_composition_pfn_bounds(struct skc_composition_impl * const impl, skc_int bounds[4])
720 {
721   //
722   // FIXME -- not implemented yet
723   //
724   // impl bounds will be copied back after sealing
725   //
726   bounds[0] = SKC_INT_MIN;
727   bounds[1] = SKC_INT_MIN;
728   bounds[2] = SKC_INT_MAX;
729   bounds[3] = SKC_INT_MAX;
730 }
731 
732 //
733 //
734 //
735 
736 void
skc_composition_retain_and_lock(struct skc_composition * const composition)737 skc_composition_retain_and_lock(struct skc_composition * const composition)
738 {
739   skc_composition_retain(composition);
740 
741   composition->impl->lock_count += 1;
742 }
743 
744 void
skc_composition_unlock_and_release(struct skc_composition * const composition)745 skc_composition_unlock_and_release(struct skc_composition * const composition)
746 {
747   composition->impl->lock_count -= 1;
748 
749   skc_composition_pfn_release(composition->impl);
750 }
751 
752 //
753 //
754 //
755 
756 skc_err
skc_composition_cl_12_create(struct skc_context * const context,struct skc_composition ** const composition)757 skc_composition_cl_12_create(struct skc_context       * const context,
758                              struct skc_composition * * const composition)
759 {
760   struct skc_runtime * const runtime = context->runtime;
761 
762   // retain the context
763   // skc_context_retain(context);
764 
765   // allocate impl
766   struct skc_composition_impl * const impl = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE,sizeof(*impl));
767 
768   // allocate composition
769   (*composition)            = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE,sizeof(**composition));
770 
771   (*composition)->context   = context;
772   (*composition)->impl      = impl;
773   (*composition)->ref_count = 1;
774 
775   (*composition)->place     = skc_composition_pfn_place;
776   (*composition)->unseal    = skc_composition_pfn_unseal;
777   (*composition)->seal      = skc_composition_pfn_seal;
778   (*composition)->bounds    = skc_composition_pfn_bounds;
779   (*composition)->release   = skc_composition_pfn_release;
780 
781   // intialize impl
782   impl->composition   = (*composition);
783   impl->runtime       = runtime;
784 
785   SKC_ASSERT_STATE_INIT(impl,SKC_COMPOSITION_STATE_SEALED);
786 
787   impl->lock_count    = 0;
788 
789   impl->grids.sort    = NULL;
790   impl->grids.place   = NULL;
791 
792   // acquire command queue for sealing/unsealing
793   impl->cq            = skc_runtime_acquire_cq_in_order(runtime);
794 
795   // acquire kernels
796   impl->kernels.place   = skc_device_acquire_kernel(runtime->device, SKC_DEVICE_KERNEL_ID_PLACE);
797   impl->kernels.segment = skc_device_acquire_kernel(runtime->device, SKC_DEVICE_KERNEL_ID_SEGMENT_TTCK);
798 
799   // get config
800   struct skc_config const * const config = runtime->config;
801 
802   // initialize ring size with config values
803   skc_extent_ring_init(&impl->cmds.ring,
804                        config->composition.cmds.elem_count,
805                        config->composition.cmds.snap_count,
806                        sizeof(union skc_cmd_place));
807 
808   skc_extent_phw1g_tdrNs_alloc(runtime,&impl->cmds.extent ,sizeof(union skc_cmd_place) * config->composition.cmds.elem_count);
809   skc_extent_phrw_alloc       (runtime,&impl->saved.extent,sizeof(skc_raster_t)        * config->composition.raster_ids.elem_count);
810   skc_extent_phr_pdrw_alloc   (runtime,&impl->atomics     ,sizeof(struct skc_place_atomics));
811 
812   skc_extent_pdrw_alloc       (runtime,&impl->keys        ,sizeof(skc_ttxk_t)          * config->composition.keys.elem_count);
813   skc_extent_pdrw_alloc       (runtime,&impl->offsets     ,sizeof(skc_uint)            * (1u << SKC_TTCK_HI_BITS_YX)); // 1MB
814 
815   // nothing saved
816   impl->saved.count = 0;
817 
818   // unseal the composition, zero the atomics, etc.
819   skc_composition_unseal_block_reset(impl,false,true);
820 
821   return SKC_ERR_SUCCESS;
822 }
823 
824 //
825 //
826 //
827