• 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 "common/cl/assert_cl.h"
14 
15 #include "skc_cl.h"
16 #include "interop.h"
17 #include "extent_cl_12.h"
18 #include "runtime_cl_12.h"
19 #include "styling_cl_12.h"
20 #include "composition_cl_12.h"
21 
22 #include "context.h"
23 #include "surface.h"
24 
25 //
26 //
27 //
28 
29 #include <stdio.h>
30 
31 //
32 // BUILD
33 //
34 
35 struct skc_surface_impl
36 {
37   struct skc_surface * surface;
38   struct skc_runtime * runtime;
39 
40   // framebuffer
41   // struct skc_extent_pdrw      fb;
42   // struct skc_extent_phrN_pdwN fb;
43 
44   // for now, a single in-order command queue
45   cl_command_queue     cq;
46 
47   struct {
48     cl_kernel          render;
49   } kernels;
50 };
51 
52 //
53 //
54 //
55 
56 struct skc_surface_render
57 {
58   skc_uint                      clip[4];
59   skc_uint                      txty[2];
60 
61   struct skc_surface_impl     * impl;
62   struct skc_styling          * styling;
63   struct skc_composition      * composition;
64 
65   struct skc_framebuffer_cl   * fb;
66 
67   skc_surface_render_notify     notify;
68   void                        * data;
69 
70   skc_grid_t                    grid;
71 
72   skc_subbuf_id_t               id;
73 };
74 
75 //
76 // FIXME -- we only need this because (I think) RBO<>CL interop
77 // results in glClear() on the FBO not working...
78 //
79 
80 static
81 void
skc_surface_debug_clear(struct skc_surface_impl * const impl,skc_framebuffer_t fb,float const rgba[4],uint32_t const rect[4])82 skc_surface_debug_clear(struct skc_surface_impl * const impl,
83                         skc_framebuffer_t               fb,
84                         float                     const rgba[4],
85                         uint32_t                  const rect[4])
86 {
87   size_t const origin[3] = { rect[0], rect[1], 0 };
88   size_t const region[3] = { rect[2], rect[3], 1 };
89 
90   cl(EnqueueFillImage(impl->cq,
91                       ((struct skc_framebuffer_cl *)fb)->mem,
92                       rgba,
93                       origin,
94                       region,
95                       0,NULL,NULL));
96 }
97 
98 //
99 //
100 //
101 
102 #if 0 // #ifndef NDEBUG
103 
104 static
105 void
106 skc_surface_debug(struct skc_surface_impl * const impl)
107 {
108   //
109   // MAP
110   //
111   cl_uchar4 * const rgba = skc_extent_phrN_pdwN_map(&impl->fb,
112                                                     impl->cq,
113                                                     NULL);
114   cl(Finish(impl->cq));
115 
116   //
117   // WRITE
118   //
119   FILE* file;
120 
121   errno_t ferr = fopen_s(&file,"surface.ppm","wb");
122 
123   fprintf(file,"P6\n%u %u\n255\n",SKC_SURFACE_WIDTH,SKC_SURFACE_HEIGHT);
124 
125   for (skc_uint ii=0; ii<SKC_SURFACE_HEIGHT*SKC_SURFACE_WIDTH; ii++)
126     fwrite(rgba + ii,sizeof(skc_uchar),3,file); // R,G,B
127 
128   ferr = fclose(file);
129 
130   //
131   // UNMAP
132   //
133   skc_extent_phrN_pdwN_unmap(&impl->fb,rgba,impl->cq,NULL);
134 
135   cl(Flush(impl->cq));
136 }
137 
138 #endif
139 
140 //
141 //
142 //
143 
144 static
145 void
skc_surface_pfn_release(struct skc_surface_impl * const impl)146 skc_surface_pfn_release(struct skc_surface_impl * const impl)
147 {
148   if (--impl->surface->ref_count != 0)
149     return;
150 
151   //
152   // otherwise, release all resources
153   //
154 
155   // drain the command queue
156   cl(Finish(impl->cq));
157 
158   struct skc_runtime * const runtime = impl->runtime;
159 
160   // release the kernel
161   cl(ReleaseKernel(impl->kernels.render));
162 
163   // free surface host
164   skc_runtime_host_perm_free(runtime,impl->surface);
165 
166   // release the cq
167   skc_runtime_release_cq_in_order(runtime,impl->cq);
168 
169   // release fb
170   // skc_extent_phrN_pdwN_free(runtime,&impl->fb);
171 
172   // free surface impl
173   skc_runtime_host_perm_free(runtime,impl);
174 }
175 
176 //
177 //
178 //
179 
180 void
skc_surface_render_complete(struct skc_surface_render * const render)181 skc_surface_render_complete(struct skc_surface_render * const render)
182 {
183 #ifdef SKC_SURFACE_DEBUG
184   // write fb out
185   skc_surface_debug(render->impl);
186 #endif
187 
188   // notify
189   if (render->notify != NULL) {
190     render->notify(render->impl->surface,
191                    render->styling,
192                    render->composition,
193                    render->fb,
194                    render->data);
195   }
196 
197   // unlock and release the styling and composition
198   skc_styling_unlock_and_release(render->styling);
199   skc_composition_unlock_and_release(render->composition);
200 
201   // grid is now complete
202   skc_grid_complete(render->grid);
203 
204   struct skc_surface_impl * const impl    = render->impl;
205   struct skc_runtime      * const runtime = impl->runtime;
206 
207   // release the surface
208   skc_surface_pfn_release(impl);
209 
210   // free the render object
211   skc_runtime_host_temp_free(runtime,render,render->id);
212 }
213 
214 static
215 void
skc_surface_render_cb(cl_event event,cl_int status,struct skc_surface_render * const render)216 skc_surface_render_cb(cl_event event, cl_int status, struct skc_surface_render * const render)
217 {
218   SKC_CL_CB(status);
219 
220   // as quickly as possible, enqueue next stage in pipeline to context command scheduler
221   SKC_SCHEDULER_SCHEDULE(render->impl->runtime->scheduler,
222                          skc_surface_render_complete,
223                          render);
224 }
225 
226 //
227 //
228 //
229 
230 static
231 void
skc_surface_grid_pfn_execute(skc_grid_t const grid)232 skc_surface_grid_pfn_execute(skc_grid_t const grid)
233 {
234   struct skc_surface_render   * const render  = skc_grid_get_data(grid);
235   struct skc_surface_impl     * const impl    = render->impl;
236   struct skc_runtime          * const runtime = impl->runtime;
237 
238   // get the composition args
239   struct skc_composition_impl * const ci      = render->composition->impl;
240   struct skc_place_atomics    * const atomics = ci->atomics.hr;
241 
242   if (atomics->offsets > 0)
243     {
244       // acquire the rbo/tex
245       if (render->fb->type != SKC_FRAMEBUFFER_CL_IMAGE2D)
246         cl(EnqueueAcquireGLObjects(impl->cq,1,&render->fb->mem,0,NULL,NULL));
247 
248       // get the styling args
249       struct skc_styling_impl * const si = render->styling->impl;
250 
251       cl(SetKernelArg(impl->kernels.render,0,SKC_CL_ARG(si->layers.drN)));
252       cl(SetKernelArg(impl->kernels.render,1,SKC_CL_ARG(si->groups.drN)));
253       cl(SetKernelArg(impl->kernels.render,2,SKC_CL_ARG(si->extras.drN)));
254 
255       cl(SetKernelArg(impl->kernels.render,3,SKC_CL_ARG(ci->keys.drw)));
256       cl(SetKernelArg(impl->kernels.render,4,SKC_CL_ARG(atomics->keys)));
257       cl(SetKernelArg(impl->kernels.render,5,SKC_CL_ARG(ci->offsets.drw)));
258       cl(SetKernelArg(impl->kernels.render,6,SKC_CL_ARG(atomics->offsets)));
259 
260       // block pool
261       cl(SetKernelArg(impl->kernels.render,7,SKC_CL_ARG(impl->runtime->block_pool.blocks.drw)));
262 
263       // surface
264       cl(SetKernelArg(impl->kernels.render,8,SKC_CL_ARG(render->fb->mem)));
265 
266 #if 1
267       // tile clip
268       cl(SetKernelArg(impl->kernels.render,9,sizeof(skc_uint4),render->clip));
269 #else
270       // surface pitch (height)
271       skc_uint const surface_pitch = SKC_SURFACE_HEIGHT;
272       cl(SetKernelArg(impl->kernels.render,9,SKC_CL_ARG(surface_pitch)));
273       // tile clip
274       cl(SetKernelArg(impl->kernels.render,10,sizeof(skc_uint4),render->clip));
275 #endif
276 
277       // launch render kernel
278       skc_device_enqueue_kernel(runtime->device,
279                                 SKC_DEVICE_KERNEL_ID_RENDER,
280                                 impl->cq,
281                                 impl->kernels.render,
282                                 atomics->offsets,
283                                 0,NULL,NULL);
284 
285 
286       cl_event complete;
287 
288       // give the rbo back
289       if (render->fb->type != SKC_FRAMEBUFFER_CL_IMAGE2D)
290         {
291           cl(EnqueueReleaseGLObjects(impl->cq,1,&render->fb->mem,0,NULL,&complete));
292 
293           //
294           // blit the rbo to fbo0
295           //
296           render->fb->post_render(render->fb->interop);
297 
298           //
299           // clear the rbo -- FIXME -- we shouldn't have to do this here
300           //
301           float    const rgba[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
302           uint32_t       rect[4] = { 0 };
303 
304           skc_interop_get_size(render->fb->interop,rect+2,rect+3);
305 
306           skc_surface_debug_clear(impl,render->fb,rgba,rect);
307         }
308 
309       // notify anyone listening...
310       cl(SetEventCallback(complete,CL_COMPLETE,skc_surface_render_cb,render));
311       cl(ReleaseEvent(complete));
312 
313       // flush it
314       cl(Flush(impl->cq));
315     }
316   else
317     {
318       skc_surface_render_complete(render);
319     }
320 }
321 
322 //
323 //
324 //
325 
326 static
327 void
skc_surface_pfn_render(struct skc_surface_impl * const impl,skc_styling_t styling,skc_composition_t composition,skc_framebuffer_t fb,uint32_t const clip[4],int32_t const txty[2],skc_surface_render_notify notify,void * data)328 skc_surface_pfn_render(struct skc_surface_impl * const impl,
329                        skc_styling_t                   styling,
330                        skc_composition_t               composition,
331                        skc_framebuffer_t               fb,
332                        uint32_t                  const clip[4],
333                        int32_t                   const txty[2],
334                        skc_surface_render_notify       notify,
335                        void                          * data)
336 {
337   // retain surface
338   skc_surface_retain(impl->surface);
339 
340   //
341   // FIXME -- we used to seal the styling and composition objects if
342   // they weren't already.  Either test that they're sealed or seal
343   // them here.
344   //
345 
346   // retain and lock the styling and composition
347   skc_styling_retain_and_lock(styling);
348   skc_composition_retain_and_lock(composition);
349 
350   //
351   // allocate a render instance
352   //
353   skc_subbuf_id_t                   id;
354   struct skc_surface_render * const render = skc_runtime_host_temp_alloc(impl->runtime,
355                                                                          SKC_MEM_FLAGS_READ_WRITE,
356                                                                          sizeof(*render),&id,NULL);
357   render->id          = id;
358 
359   render->clip[0]     = clip[0];
360   render->clip[1]     = clip[1];
361   render->clip[2]     = clip[2];
362   render->clip[3]     = clip[3];
363 
364   render->txty[0]     = txty[0];
365   render->txty[1]     = txty[1];
366 
367   render->impl        = impl;
368   render->styling     = styling;
369   render->composition = composition;
370 
371   render->notify      = notify;
372   render->data        = data;
373 
374   render->fb          = fb;
375 
376   render->grid        = SKC_GRID_DEPS_ATTACH(impl->runtime->deps,
377                                              NULL, // invalidation not necessary
378                                              render,
379                                              NULL,  // no waiting
380                                              skc_surface_grid_pfn_execute,
381                                              NULL); // no disposal
382   //
383   // declare happens-after relationships
384   //
385   if (styling->impl->state != SKC_STYLING_STATE_SEALED)
386     skc_grid_happens_after_grid(render->grid,styling->impl->grid);
387 
388   if (composition->impl->state != SKC_COMPOSITION_STATE_SEALED)
389     skc_grid_happens_after_grid(render->grid,composition->impl->grids.sort);
390 
391   //
392   // start render but possibly wait for styling and composition
393   //
394   skc_grid_start(render->grid);
395 }
396 
397 //
398 //
399 //
400 
401 skc_err
skc_surface_cl_12_create(struct skc_context * const context,struct skc_surface ** const surface)402 skc_surface_cl_12_create(struct skc_context   * const context,
403                          struct skc_surface * * const surface)
404 {
405   struct skc_runtime * const runtime = context->runtime;
406 
407   // allocate surface
408   (*surface) = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE,sizeof(**surface));
409 
410   // allocate impl
411   struct skc_surface_impl * const impl = skc_runtime_host_perm_alloc(runtime,SKC_MEM_FLAGS_READ_WRITE,sizeof(*impl));
412 
413   // initialize surface
414   // SKC_ASSERT_STATE_INIT((*impl),SKC_SURFACE_STATE_READY);
415 
416   (*surface)->context    = context;
417   (*surface)->impl       = impl;
418   (*surface)->ref_count  = 1;
419 
420   (*surface)->release    = skc_surface_pfn_release;
421   (*surface)->render     = skc_surface_pfn_render;
422 
423   // intialize impl
424   impl->surface          = *surface;
425   impl->runtime          = runtime;
426 
427 #if 0
428   // FIXME -- 4K x 4K -- temporarily fixed size
429   size_t const fb_size = sizeof(skc_uchar4) * SKC_SURFACE_WIDTH * SKC_SURFACE_HEIGHT;
430 
431   // create framebuffer
432   skc_extent_phrN_pdwN_alloc(runtime,&impl->fb,fb_size);
433 #endif
434 
435   // acquire a command queue
436   impl->cq               = skc_runtime_acquire_cq_in_order(runtime);
437 
438   // acquire kernel
439   impl->kernels.render   = skc_device_acquire_kernel(runtime->device,SKC_DEVICE_KERNEL_ID_RENDER);
440 
441   return SKC_ERR_SUCCESS;
442 }
443 
444 //
445 //
446 //
447