1 //
2 //   Copyright 2013 Pixar
3 //
4 //   Licensed under the Apache License, Version 2.0 (the "Apache License")
5 //   with the following modification; you may not use this file except in
6 //   compliance with the Apache License and the following modification to it:
7 //   Section 6. Trademarks. is deleted and replaced with:
8 //
9 //   6. Trademarks. This License does not grant permission to use the trade
10 //      names, trademarks, service marks, or product names of the Licensor
11 //      and its affiliates, except as required to comply with Section 4(c) of
12 //      the License and to reproduce the content of the NOTICE file.
13 //
14 //   You may obtain a copy of the Apache License at
15 //
16 //       http://www.apache.org/licenses/LICENSE-2.0
17 //
18 //   Unless required by applicable law or agreed to in writing, software
19 //   distributed under the Apache License with the above modification is
20 //   distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 //   KIND, either express or implied. See the Apache License for the specific
22 //   language governing permissions and limitations under the Apache License.
23 //
24 
25 #ifndef OPENSUBDIV3_OSD_MTL_COMPUTE_EVALUATOR_H
26 #define OPENSUBDIV3_OSD_MTL_COMPUTE_EVALUATOR_H
27 
28 #include "../version.h"
29 
30 #include "../osd/types.h"
31 #include "../osd/bufferDescriptor.h"
32 #include "../osd/mtlCommon.h"
33 
34 @protocol MTLDevice;
35 @protocol MTLBuffer;
36 @protocol MTLLibrary;
37 @protocol MTLComputePipelineState;
38 
39 namespace OpenSubdiv {
40 namespace OPENSUBDIV_VERSION {
41 
42 namespace Far {
43     class PatchTable;
44     class StencilTable;
45     class LimitStencilTable;
46 }
47 
48 namespace Osd {
49 
50 class MTLStencilTable
51 {
52 public:
53     template<typename STENCIL_TABLE, typename DEVICE_CONTEXT>
Create(STENCIL_TABLE * stencilTable,DEVICE_CONTEXT context)54     static MTLStencilTable* Create(STENCIL_TABLE* stencilTable,
55                                    DEVICE_CONTEXT context)
56     {
57         return new MTLStencilTable(stencilTable, context);
58     }
59 
60 
61     MTLStencilTable(Far::StencilTable const* stencilTable, MTLContext* context);
62     MTLStencilTable(Far::LimitStencilTable const* stencilTable, MTLContext* context);
63     ~MTLStencilTable();
64 
GetSizesBuffer()65     id<MTLBuffer> GetSizesBuffer() const { return _sizesBuffer; }
GetOffsetsBuffer()66     id<MTLBuffer> GetOffsetsBuffer() const { return _offsetsBuffer; }
GetIndicesBuffer()67     id<MTLBuffer> GetIndicesBuffer() const  { return _indicesBuffer; }
GetWeightsBuffer()68     id<MTLBuffer> GetWeightsBuffer() const { return _weightsBuffer; }
GetDuWeightsBuffer()69     id<MTLBuffer> GetDuWeightsBuffer() const { return _duWeightsBuffer; }
GetDvWeightsBuffer()70     id<MTLBuffer> GetDvWeightsBuffer() const { return _dvWeightsBuffer; }
GetDuuWeightsBuffer()71     id<MTLBuffer> GetDuuWeightsBuffer() const { return _duuWeightsBuffer; }
GetDuvWeightsBuffer()72     id<MTLBuffer> GetDuvWeightsBuffer() const { return _duvWeightsBuffer; }
GetDvvWeightsBuffer()73     id<MTLBuffer> GetDvvWeightsBuffer() const { return _dvvWeightsBuffer; }
74 
GetNumStencils()75     int GetNumStencils() const  { return _numStencils; }
76 
77 private:
78     id<MTLBuffer> _sizesBuffer;
79     id<MTLBuffer> _offsetsBuffer;
80     id<MTLBuffer> _indicesBuffer;
81     id<MTLBuffer> _weightsBuffer;
82     id<MTLBuffer> _duWeightsBuffer;
83     id<MTLBuffer> _dvWeightsBuffer;
84     id<MTLBuffer> _duuWeightsBuffer;
85     id<MTLBuffer> _duvWeightsBuffer;
86     id<MTLBuffer> _dvvWeightsBuffer;
87 
88     int _numStencils;
89 };
90 
91 class MTLComputeEvaluator
92 {
93 public:
94     typedef bool Instantiatable;
95 
96     static MTLComputeEvaluator * Create(BufferDescriptor const &srcDesc,
97                                         BufferDescriptor const &dstDesc,
98                                         BufferDescriptor const &duDesc,
99                                         BufferDescriptor const &dvDesc,
100                                         MTLContext* context);
101 
102     static MTLComputeEvaluator * Create(BufferDescriptor const &srcDesc,
103                                         BufferDescriptor const &dstDesc,
104                                         BufferDescriptor const &duDesc,
105                                         BufferDescriptor const &dvDesc,
106                                         BufferDescriptor const &duuDesc,
107                                         BufferDescriptor const &duvDesc,
108                                         BufferDescriptor const &dvvDesc,
109                                         MTLContext* context);
110 
111     MTLComputeEvaluator();
112     ~MTLComputeEvaluator();
113 
114     /// ----------------------------------------------------------------------
115     ///
116     ///   Stencil evaluations with StencilTable
117     ///
118     /// ----------------------------------------------------------------------
119 
120     /// \brief Generic static stencil function. This function has a same
121     ///        signature as other device kernels have so that it can be called
122     ///        transparently from OsdMesh template interface.
123     ///
124     /// @param srcBuffer      Input primvar buffer.
125     ///                       must have BindVBO() method returning an
126     ///                       MTLBuffer object of source data
127     ///
128     /// @param srcDesc        vertex buffer descriptor for the input buffer
129     ///
130     /// @param dstBuffer      Output primvar buffer
131     ///                       must have BindVBO() method returning an
132     ///                       MTLBuffer object of destination data
133     ///
134     /// @param dstDesc        vertex buffer descriptor for the output buffer
135     ///
136     /// @param stencilTable   stencil table to be applied. The table must have
137     ///                       MTLBuffer interfaces.
138     ///
139     /// @param instance       cached compiled instance. Clients are supposed to
140     ///                       pre-compile an instance of this class and provide
141     ///                       to this function. If it's null the kernel still
142     ///                       compute by instantiating on-demand kernel although
143     ///                       it may cause a performance problem.
144     ///
145     /// @param context        used to obtain the MTLDevice object and command queue
146     ///                       to obtain command buffers from.
147     ///
148     template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
EvalStencils(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,STENCIL_TABLE const * stencilTable,MTLComputeEvaluator const * instance,MTLContext * context)149     static bool EvalStencils(
150         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
151         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
152         STENCIL_TABLE const *stencilTable,
153         MTLComputeEvaluator const *instance,
154         MTLContext* context)
155     {
156         if (instance) {
157             return instance->EvalStencils(srcBuffer, srcDesc,
158                                           dstBuffer, dstDesc,
159                                           stencilTable,
160                                           context);
161         } else {
162             // Create an instance on demand (slow)
163             instance = Create(srcDesc, dstDesc,
164                               BufferDescriptor(),
165                               BufferDescriptor(),
166                               context);
167             if (instance) {
168                 bool r = instance->EvalStencils(srcBuffer, srcDesc,
169                                                 dstBuffer, dstDesc,
170                                                 stencilTable,
171                                                 context);
172                 delete instance;
173                 return r;
174             }
175             return false;
176         }
177     }
178 
179     /// \brief Generic static stencil function. This function has a same
180     ///        signature as other device kernels have so that it can be called
181     ///        transparently from OsdMesh template interface.
182     ///
183     /// @param srcBuffer      Input primvar buffer.
184     ///                       must have BindVBO() method returning an
185     ///                       MTLBuffer object of source data
186     ///
187     /// @param srcDesc        vertex buffer descriptor for the input buffer
188     ///
189     /// @param dstBuffer      Output primvar buffer
190     ///                       must have BindVBO() method returning an
191     ///                       MTLBuffer object of destination data
192     ///
193     /// @param dstDesc        vertex buffer descriptor for the dstBuffer
194     ///
195     /// @param duBuffer       Output buffer derivative wrt u
196     ///                       must have BindVBO() method returning an
197     ///                       MTLBuffer object of destination data
198     ///
199     /// @param duDesc         vertex buffer descriptor for the duBuffer
200     ///
201     /// @param dvBuffer       Output buffer derivative wrt v
202     ///                       must have BindVBO() method returning an
203     ///                       MTLBuffer object of destination data
204     ///
205     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
206     ///
207     /// @param stencilTable   stencil table to be applied. The table must have
208     ///                       MTLBuffer interfaces.
209     ///
210     /// @param instance       cached compiled instance. Clients are supposed to
211     ///                       pre-compile an instance of this class and provide
212     ///                       to this function. If it's null the kernel still
213     ///                       compute by instantiating on-demand kernel although
214     ///                       it may cause a performance problem.
215     ///
216     /// @param context        used to obtain the MTLDevice object and command queue
217     ///                       to obtain command buffers from.
218     ///
219     template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
EvalStencils(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,STENCIL_TABLE const * stencilTable,MTLComputeEvaluator const * instance,MTLContext * context)220     static bool EvalStencils(
221         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
222         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
223         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
224         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
225         STENCIL_TABLE const *stencilTable,
226         MTLComputeEvaluator const *instance,
227         MTLContext* context) {
228 
229         if (instance) {
230             return instance->EvalStencils(srcBuffer, srcDesc,
231                                           dstBuffer, dstDesc,
232                                           duBuffer,  duDesc,
233                                           dvBuffer,  dvDesc,
234                                           stencilTable,
235                                           context);
236         } else {
237             // Create an instance on demand (slow)
238             instance = Create(srcDesc, dstDesc, duDesc, dvDesc, context);
239             if (instance) {
240                 bool r = instance->EvalStencils(srcBuffer, srcDesc,
241                                                 dstBuffer, dstDesc,
242                                                 duBuffer,  duDesc,
243                                                 dvBuffer,  dvDesc,
244                                                 stencilTable,
245                                                 context);
246                 delete instance;
247                 return r;
248             }
249             return false;
250         }
251     }
252 
253     /// \brief Generic static stencil function. This function has a same
254     ///        signature as other device kernels have so that it can be called
255     ///        transparently from OsdMesh template interface.
256     ///
257     /// @param srcBuffer      Input primvar buffer.
258     ///                       must have BindVBO() method returning an
259     ///                       MTLBuffer object of source data
260     ///
261     /// @param srcDesc        vertex buffer descriptor for the input buffer
262     ///
263     /// @param dstBuffer      Output primvar buffer
264     ///                       must have BindVBO() method returning an
265     ///                       MTLBuffer object of destination data
266     ///
267     /// @param dstDesc        vertex buffer descriptor for the dstBuffer
268     ///
269     /// @param duBuffer       Output buffer derivative wrt u
270     ///                       must have BindVBO() method returning an
271     ///                       MTLBuffer object of destination data
272     ///
273     /// @param duDesc         vertex buffer descriptor for the duBuffer
274     ///
275     /// @param dvBuffer       Output buffer derivative wrt v
276     ///                       must have BindVBO() method returning an
277     ///                       MTLBuffer object of destination data
278     ///
279     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
280     ///
281     /// @param duuBuffer      Output buffer 2nd derivative wrt u
282     ///                       must have BindVBO() method returning an
283     ///                       MTLBuffer object of destination data
284     ///
285     /// @param duuDesc        vertex buffer descriptor for the duuBuffer
286     ///
287     /// @param duvBuffer      Output buffer 2nd derivative wrt u and v
288     ///                       must have BindVBO() method returning an
289     ///                       MTLBuffer object of destination data
290     ///
291     /// @param duvDesc        vertex buffer descriptor for the duvBuffer
292     ///
293     /// @param dvvBuffer      Output buffer 2nd derivative wrt v
294     ///                       must have BindVBO() method returning an
295     ///                       MTLBuffer object of destination data
296     ///
297     /// @param dvvDesc        vertex buffer descriptor for the dvvBuffer
298     ///
299     /// @param stencilTable   stencil table to be applied. The table must have
300     ///                       MTLBuffer interfaces.
301     ///
302     /// @param instance       cached compiled instance. Clients are supposed to
303     ///                       pre-compile an instance of this class and provide
304     ///                       to this function. If it's null the kernel still
305     ///                       compute by instantiating on-demand kernel although
306     ///                       it may cause a performance problem.
307     ///
308     /// @param context        used to obtain the MTLDevice object and command queue
309     ///                       to obtain command buffers from.
310     ///
311     template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
EvalStencils(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,DST_BUFFER * duuBuffer,BufferDescriptor const & duuDesc,DST_BUFFER * duvBuffer,BufferDescriptor const & duvDesc,DST_BUFFER * dvvBuffer,BufferDescriptor const & dvvDesc,STENCIL_TABLE const * stencilTable,MTLComputeEvaluator const * instance,MTLContext * context)312     static bool EvalStencils(
313         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
314         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
315         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
316         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
317         DST_BUFFER *duuBuffer, BufferDescriptor const &duuDesc,
318         DST_BUFFER *duvBuffer, BufferDescriptor const &duvDesc,
319         DST_BUFFER *dvvBuffer, BufferDescriptor const &dvvDesc,
320         STENCIL_TABLE const *stencilTable,
321         MTLComputeEvaluator const *instance,
322         MTLContext* context) {
323 
324         if (instance) {
325             return instance->EvalStencils(srcBuffer, srcDesc,
326                                           dstBuffer, dstDesc,
327                                           duBuffer,  duDesc,
328                                           dvBuffer,  dvDesc,
329                                           duuBuffer, duuDesc,
330                                           duvBuffer, duvDesc,
331                                           dvvBuffer, dvvDesc,
332                                           stencilTable,
333                                           context);
334         } else {
335             // Create an instance on demand (slow)
336             instance = Create(srcDesc, dstDesc, duDesc, dvDesc,
337                               duuDesc, duvDesc, dvvDesc, context);
338             if (instance) {
339                 bool r = instance->EvalStencils(srcBuffer, srcDesc,
340                                                 dstBuffer, dstDesc,
341                                                 duBuffer,  duDesc,
342                                                 dvBuffer,  dvDesc,
343                                                 duuBuffer, duuDesc,
344                                                 duvBuffer, duvDesc,
345                                                 dvvBuffer, dvvDesc,
346                                                 stencilTable,
347                                                 context);
348                 delete instance;
349                 return r;
350             }
351             return false;
352         }
353     }
354 
355     /// \brief Generic stencil function.
356     ///
357     /// @param srcBuffer      Input primvar buffer.
358     ///                       must have BindVBO() method returning an
359     ///                       MTLBuffer object of source data
360     ///
361     /// @param srcDesc        vertex buffer descriptor for the input buffer
362     ///
363     /// @param dstBuffer      Output primvar buffer
364     ///                       must have BindVBO() method returning an
365     ///                       MTLBuffer object of destination data
366     ///
367     /// @param dstDesc        vertex buffer descriptor for the output buffer
368     ///
369     /// @param stencilTable   stencil table to be applied. The table must have
370     ///                       MTLBuffer interfaces.
371     ///
372     /// @param context        used to obtain the MTLDevice object and command queue
373     ///                       to obtain command buffers from.
374     ///
375     template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
EvalStencils(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,STENCIL_TABLE const * stencilTable,MTLContext * context)376     bool EvalStencils(
377                       SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
378                       DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
379                       STENCIL_TABLE const *stencilTable,
380                       MTLContext* context) const
381     {
382         return EvalStencils(srcBuffer->BindMTLBuffer(context), srcDesc,
383                             dstBuffer->BindMTLBuffer(context), dstDesc,
384                             0, BufferDescriptor(),
385                             0, BufferDescriptor(),
386                             stencilTable->GetSizesBuffer(),
387                             stencilTable->GetOffsetsBuffer(),
388                             stencilTable->GetIndicesBuffer(),
389                             stencilTable->GetWeightsBuffer(),
390                             0,
391                             0,
392                             /* start = */ 0,
393                             /* end   = */ stencilTable->GetNumStencils(),
394                             context);
395     }
396 
397     /// \brief Generic stencil function.
398     ///
399     /// @param srcBuffer      Input primvar buffer.
400     ///                       must have BindVBO() method returning an
401     ///                       MTLBuffer object of source data
402     ///
403     /// @param srcDesc        vertex buffer descriptor for the input buffer
404     ///
405     /// @param dstBuffer      Output primvar buffer
406     ///                       must have BindVBO() method returning an
407     ///                       MTLBuffer object of destination data
408     ///
409     /// @param dstDesc        vertex buffer descriptor for the dstBuffer
410     ///
411     /// @param duBuffer       Output buffer derivative wrt u
412     ///                       must have BindVBO() method returning an
413     ///                       MTLBuffer object of destination data
414     ///
415     /// @param duDesc         vertex buffer descriptor for the duBuffer
416     ///
417     /// @param dvBuffer       Output buffer derivative wrt v
418     ///                       must have BindVBO() method returning an
419     ///                       MTLBuffer object of destination data
420     ///
421     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
422     ///
423     /// @param stencilTable   stencil table to be applied. The table must have
424     ///                       MTLBuffer interfaces.
425     ///
426     /// @param context        used to obtain the MTLDevice object and command queue
427     ///                       to obtain command buffers from.
428     ///
429     template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
EvalStencils(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,STENCIL_TABLE const * stencilTable,MTLContext * context)430     bool EvalStencils(
431         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
432         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
433         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
434         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
435         STENCIL_TABLE const *stencilTable,
436         MTLContext* context) const
437     {
438         return EvalStencils(srcBuffer->BindMTLBuffer(context), srcDesc,
439                             dstBuffer->BindMTLBuffer(context), dstDesc,
440                             duBuffer->BindMTLBuffer(context),  duDesc,
441                             dvBuffer->BindMTLBuffer(context),  dvDesc,
442                             stencilTable->GetSizesBuffer(),
443                             stencilTable->GetOffsetsBuffer(),
444                             stencilTable->GetIndicesBuffer(),
445                             stencilTable->GetWeightsBuffer(),
446                             stencilTable->GetDuWeightsBuffer(),
447                             stencilTable->GetDvWeightsBuffer(),
448                             /* start = */ 0,
449                             /* end   = */ stencilTable->GetNumStencils(),
450                             context);
451     }
452 
453     /// \brief Generic stencil function.
454     ///
455     /// @param srcBuffer      Input primvar buffer.
456     ///                       must have BindVBO() method returning an
457     ///                       MTLBuffer object of source data
458     ///
459     /// @param srcDesc        vertex buffer descriptor for the input buffer
460     ///
461     /// @param dstBuffer      Output primvar buffer
462     ///                       must have BindVBO() method returning an
463     ///                       MTLBuffer object of destination data
464     ///
465     /// @param dstDesc        vertex buffer descriptor for the dstBuffer
466     ///
467     /// @param duBuffer       Output buffer derivative wrt u
468     ///                       must have BindVBO() method returning an
469     ///                       MTLBuffer object of destination data
470     ///
471     /// @param duDesc         vertex buffer descriptor for the duBuffer
472     ///
473     /// @param dvBuffer       Output buffer derivative wrt v
474     ///                       must have BindVBO() method returning an
475     ///                       MTLBuffer object of destination data
476     ///
477     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
478     ///
479     /// @param duuBuffer      Output buffer 2nd derivative wrt u
480     ///                       must have BindVBO() method returning an
481     ///                       MTLBuffer object of destination data
482     ///
483     /// @param duuDesc         vertex buffer descriptor for the duuBuffer
484     ///
485     /// @param duvBuffer      Output buffer 2nd derivative wrt u and v
486     ///                       must have BindVBO() method returning an
487     ///                       MTLBuffer object of destination data
488     ///
489     /// @param duvDesc        vertex buffer descriptor for the duvBuffer
490     ///
491     /// @param dvvBuffer      Output buffer 2nd derivative wrt v
492     ///                       must have BindVBO() method returning an
493     ///                       MTLBuffer object of destination data
494     ///
495     /// @param dvvDesc        vertex buffer descriptor for the dvvBuffer
496     ///
497     /// @param stencilTable   stencil table to be applied. The table must have
498     ///                       MTLBuffer interfaces.
499     ///
500     /// @param context        used to obtain the MTLDevice object and command queue
501     ///                       to obtain command buffers from.
502     ///
503     template <typename SRC_BUFFER, typename DST_BUFFER, typename STENCIL_TABLE>
EvalStencils(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,DST_BUFFER * duuBuffer,BufferDescriptor const & duuDesc,DST_BUFFER * duvBuffer,BufferDescriptor const & duvDesc,DST_BUFFER * dvvBuffer,BufferDescriptor const & dvvDesc,STENCIL_TABLE const * stencilTable,MTLContext * context)504     bool EvalStencils(
505         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
506         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
507         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
508         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
509         DST_BUFFER *duuBuffer, BufferDescriptor const &duuDesc,
510         DST_BUFFER *duvBuffer, BufferDescriptor const &duvDesc,
511         DST_BUFFER *dvvBuffer, BufferDescriptor const &dvvDesc,
512         STENCIL_TABLE const *stencilTable,
513         MTLContext* context) const
514     {
515         return EvalStencils(srcBuffer->BindMTLBuffer(context), srcDesc,
516                             dstBuffer->BindMTLBuffer(context), dstDesc,
517                             duBuffer->BindMTLBuffer(context),  duDesc,
518                             dvBuffer->BindMTLBuffer(context),  dvDesc,
519                             duuBuffer->BindMTLBuffer(context), duuDesc,
520                             duvBuffer->BindMTLBuffer(context), duvDesc,
521                             dvvBuffer->BindMTLBuffer(context), dvvDesc,
522                             stencilTable->GetSizesBuffer(),
523                             stencilTable->GetOffsetsBuffer(),
524                             stencilTable->GetIndicesBuffer(),
525                             stencilTable->GetWeightsBuffer(),
526                             stencilTable->GetDuWeightsBuffer(),
527                             stencilTable->GetDvWeightsBuffer(),
528                             stencilTable->GetDuuWeightsBuffer(),
529                             stencilTable->GetDuvWeightsBuffer(),
530                             stencilTable->GetDvvWeightsBuffer(),
531                             /* start = */ 0,
532                             /* end   = */ stencilTable->GetNumStencils(),
533                             context);
534     }
535 
536     /// \brief Dispatch the MTL compute kernel on GPU asynchronously
537     /// returns false if the kernel hasn't been compiled yet.
538     ///
539     /// @param srcBuffer        MTLBuffer of input primvar source data
540     ///
541     /// @param srcDesc          vertex buffer descriptor for the srcBuffer
542     ///
543     /// @param dstBuffer        MTLBuffer of output primvar destination data
544     ///
545     /// @param dstDesc          vertex buffer descriptor for the dstBuffer
546     ///
547     /// @param duBuffer         MTLBuffer of output derivative wrt u
548     ///
549     /// @param duDesc           vertex buffer descriptor for the duBuffer
550     ///
551     /// @param dvBuffer         MTLBuffer of output derivative wrt v
552     ///
553     /// @param dvDesc           vertex buffer descriptor for the dvBuffer
554     ///
555     /// @param sizesBuffer      MTLBuffer of the sizes in the stencil table
556     ///
557     /// @param offsetsBuffer    MTLBuffer of the offsets in the stencil table
558     ///
559     /// @param indicesBuffer    MTLBuffer of the indices in the stencil table
560     ///
561     /// @param weightsBuffer    MTLBuffer of the weights in the stencil table
562     ///
563     /// @param duWeightsBuffer  MTLBuffer of the du weights in the stencil table
564     ///
565     /// @param dvWeightsBuffer  MTLBuffer of the dv weights in the stencil table
566     ///
567     /// @param start            start index of stencil table
568     ///
569     /// @param end              end index of stencil table
570     ///
571     /// @param context          used to obtain the MTLDevice object and command queue
572     ///                         to obtain command buffers from.
573     ///
574     bool EvalStencils(id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
575                       id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
576                       id<MTLBuffer> duBuffer,  BufferDescriptor const &duDesc,
577                       id<MTLBuffer> dvBuffer,  BufferDescriptor const &dvDesc,
578                       id<MTLBuffer> sizesBuffer,
579                       id<MTLBuffer> offsetsBuffer,
580                       id<MTLBuffer> indicesBuffer,
581                       id<MTLBuffer> weightsBuffer,
582                       id<MTLBuffer> duWeightsBuffer,
583                       id<MTLBuffer> dvWeightsBuffer,
584                       int start,
585                       int end,
586                       MTLContext* context) const;
587 
588     /// \brief Dispatch the MTL compute kernel on GPU asynchronously
589     /// returns false if the kernel hasn't been compiled yet.
590     ///
591     /// @param srcBuffer        MTLBuffer of input primvar source data
592     ///
593     /// @param srcDesc          vertex buffer descriptor for the srcBuffer
594     ///
595     /// @param dstBuffer        MTLBuffer of output primvar destination data
596     ///
597     /// @param dstDesc          vertex buffer descriptor for the dstBuffer
598     ///
599     /// @param duBuffer         MTLBuffer of output derivative wrt u
600     ///
601     /// @param duDesc           vertex buffer descriptor for the duBuffer
602     ///
603     /// @param dvBuffer         MTLBuffer of output derivative wrt v
604     ///
605     /// @param dvDesc           vertex buffer descriptor for the dvBuffer
606     ///
607     /// @param duuBuffer        MTLBuffer of output 2nd derivative wrt u
608     ///
609     /// @param duuDesc          vertex buffer descriptor for the duuBuffer
610     ///
611     /// @param duvBuffer        MTLBuffer of output 2nd derivative wrt u and v
612     ///
613     /// @param duvDesc          vertex buffer descriptor for the duvBuffer
614     ///
615     /// @param dvvBuffer        MTLBuffer of output 2nd derivative wrt v
616     ///
617     /// @param dvvDesc          vertex buffer descriptor for the dvvBuffer
618     ///
619     /// @param sizesBuffer      MTLBuffer of the sizes in the stencil table
620     ///
621     /// @param offsetsBuffer    MTLBuffer of the offsets in the stencil table
622     ///
623     /// @param indicesBuffer    MTLBuffer of the indices in the stencil table
624     ///
625     /// @param weightsBuffer    MTLBuffer of the weights in the stencil table
626     ///
627     /// @param duWeightsBuffer  MTLBuffer of the du weights in the stencil table
628     ///
629     /// @param dvWeightsBuffer  MTLBuffer of the dv weights in the stencil table
630     ///
631     /// @param duuWeightsBuffer MTLBuffer of the duu weights in the stencil table
632     ///
633     /// @param duvWeightsBuffer MTLBuffer of the duv weights in the stencil table
634     ///
635     /// @param dvvWeightsBuffer MTLBuffer of the dvv weights in the stencil table
636     ///
637     /// @param start            start index of stencil table
638     ///
639     /// @param end              end index of stencil table
640     ///
641     /// @param context          used to obtain the MTLDevice object and command queue
642     ///                         to obtain command buffers from.
643     ///
644     bool EvalStencils(id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
645                       id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
646                       id<MTLBuffer> duBuffer,  BufferDescriptor const &duDesc,
647                       id<MTLBuffer> dvBuffer,  BufferDescriptor const &dvDesc,
648                       id<MTLBuffer> duuBuffer, BufferDescriptor const &duuDesc,
649                       id<MTLBuffer> duvBuffer, BufferDescriptor const &duvDesc,
650                       id<MTLBuffer> dvvBuffer, BufferDescriptor const &dvvDesc,
651                       id<MTLBuffer> sizesBuffer,
652                       id<MTLBuffer> offsetsBuffer,
653                       id<MTLBuffer> indicesBuffer,
654                       id<MTLBuffer> weightsBuffer,
655                       id<MTLBuffer> duWeightsBuffer,
656                       id<MTLBuffer> dvWeightsBuffer,
657                       id<MTLBuffer> duuWeightsBuffer,
658                       id<MTLBuffer> duvWeightsBuffer,
659                       id<MTLBuffer> dvvWeightsBuffer,
660                       int start,
661                       int end,
662                       MTLContext* context) const;
663 
664     /// ----------------------------------------------------------------------
665     ///
666     ///   Limit evaluations with PatchTable
667     ///
668     /// ----------------------------------------------------------------------
669 
670     /// \brief Generic limit eval function. This function has a same
671     ///        signature as other device kernels have so that it can be called
672     ///        in the same way.
673     ///
674     /// @param srcBuffer      Input primvar buffer.
675     ///                       must have BindVBO() method returning an
676     ///                       MTLBuffer object of source data
677     ///
678     /// @param srcDesc        vertex buffer descriptor for the input buffer
679     ///
680     /// @param dstBuffer      Output primvar buffer
681     ///                       must have BindVBO() method returning an
682     ///                       MTLBuffer object of destination data
683     ///
684     /// @param dstDesc        vertex buffer descriptor for the output buffer
685     ///
686     /// @param numPatchCoords number of patchCoords.
687     ///
688     /// @param patchCoords    array of locations to be evaluated.
689     ///                       must have BindVBO() method returning an
690     ///                       array of PatchCoord struct in VBO.
691     ///
692     /// @param patchTable     MTLPatchTable or equivalent
693     ///
694     /// @param instance       cached compiled instance. Clients are supposed to
695     ///                       pre-compile an instance of this class and provide
696     ///                       to this function. If it's null the kernel still
697     ///                       compute by instantiating on-demand kernel although
698     ///                       it may cause a performance problem.
699     ///
700     /// @param context        used to obtain the MTLDevice object and command queue
701     ///                       to obtain command buffers from.
702     ///
703     template <typename SRC_BUFFER, typename DST_BUFFER,
704               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatches(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLComputeEvaluator const * instance,MTLContext * context)705     static bool EvalPatches(
706         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
707         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
708         int numPatchCoords,
709         PATCHCOORD_BUFFER *patchCoords,
710         PATCH_TABLE *patchTable,
711         MTLComputeEvaluator const *instance,
712         MTLContext* context) {
713 
714         if (instance) {
715             return instance->EvalPatches(srcBuffer, srcDesc,
716                                          dstBuffer, dstDesc,
717                                          numPatchCoords, patchCoords,
718                                          patchTable,
719                                          context);
720         } else {
721             // Create an instance on demand (slow)
722             instance = Create(srcDesc, dstDesc,
723                               BufferDescriptor(),
724                               BufferDescriptor(),
725                               context);
726             if (instance) {
727                 bool r = instance->EvalPatches(srcBuffer, srcDesc,
728                                                dstBuffer, dstDesc,
729                                                numPatchCoords, patchCoords,
730                                                patchTable,
731                                                context);
732                 delete instance;
733                 return r;
734             }
735             return false;
736         }
737     }
738 
739     /// \brief Generic limit eval function. This function has a same
740     ///        signature as other device kernels have so that it can be called
741     ///        in the same way.
742     ///
743     /// @param srcBuffer      Input primvar buffer.
744     ///                       must have BindVBO() method returning an
745     ///                       MTLBuffer object of source data
746     ///
747     /// @param srcDesc        vertex buffer descriptor for the input buffer
748     ///
749     /// @param dstBuffer      Output primvar buffer
750     ///                       must have BindVBO() method returning an
751     ///                       MTLBuffer object of destination data
752     ///
753     /// @param dstDesc        vertex buffer descriptor for the output buffer
754     ///
755     /// @param duBuffer       Output buffer derivative wrt u
756     ///                       must have BindVBO() method returning an
757     ///                       MTLBuffer object of destination data
758     ///
759     /// @param duDesc         vertex buffer descriptor for the duBuffer
760     ///
761     /// @param dvBuffer       Output buffer derivative wrt v
762     ///                       must have BindVBO() method returning an
763     ///                       MTLBuffer object of destination data
764     ///
765     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
766     ///
767     /// @param numPatchCoords number of patchCoords.
768     ///
769     /// @param patchCoords    array of locations to be evaluated.
770     ///                       must have BindVBO() method returning an
771     ///                       array of PatchCoord struct in VBO.
772     ///
773     /// @param patchTable     MTLPatchTable or equivalent
774     ///
775     /// @param instance       cached compiled instance. Clients are supposed to
776     ///                       pre-compile an instance of this class and provide
777     ///                       to this function. If it's null the kernel still
778     ///                       compute by instantiating on-demand kernel although
779     ///                       it may cause a performance problem.
780     ///
781     /// @param context        used to obtain the MTLDevice object and command queue
782     ///                       to obtain command buffers from.
783     ///
784     template <typename SRC_BUFFER, typename DST_BUFFER,
785               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatches(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLComputeEvaluator * instance,MTLContext * context)786     static bool EvalPatches(
787         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
788         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
789         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
790         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
791         int numPatchCoords,
792         PATCHCOORD_BUFFER *patchCoords,
793         PATCH_TABLE *patchTable,
794         MTLComputeEvaluator* instance,
795         MTLContext* context) {
796 
797         if (instance) {
798             return instance->EvalPatches(srcBuffer, srcDesc,
799                                          dstBuffer, dstDesc,
800                                          duBuffer, duDesc,
801                                          dvBuffer, dvDesc,
802                                          numPatchCoords, patchCoords,
803                                          patchTable,
804                                          context);
805         } else {
806             // Create an instance on demand (slow)
807             instance = Create(srcDesc, dstDesc,
808                               duDesc, dvDesc, context);
809             if (instance) {
810                 bool r = instance->EvalPatches(srcBuffer, srcDesc,
811                                                dstBuffer, dstDesc,
812                                                duBuffer, duDesc,
813                                                dvBuffer, dvDesc,
814                                                numPatchCoords, patchCoords,
815                                                patchTable,
816                                                context);
817                 delete instance;
818                 return r;
819             }
820             return false;
821         }
822     }
823 
824     /// \brief Generic limit eval function. This function has a same
825     ///        signature as other device kernels have so that it can be called
826     ///        in the same way.
827     ///
828     /// @param srcBuffer      Input primvar buffer.
829     ///                       must have BindVBO() method returning an
830     ///                       MTLBuffer object of source data
831     ///
832     /// @param srcDesc        vertex buffer descriptor for the input buffer
833     ///
834     /// @param dstBuffer      Output primvar buffer
835     ///                       must have BindVBO() method returning an
836     ///                       MTLBuffer object of destination data
837     ///
838     /// @param dstDesc        vertex buffer descriptor for the output buffer
839     ///
840     /// @param duBuffer       Output buffer derivative wrt u
841     ///                       must have BindVBO() method returning an
842     ///                       MTLBuffer object of destination data
843     ///
844     /// @param duDesc         vertex buffer descriptor for the duBuffer
845     ///
846     /// @param dvBuffer       Output buffer derivative wrt v
847     ///                       must have BindVBO() method returning an
848     ///                       MTLBuffer object of destination data
849     ///
850     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
851     ///
852     /// @param duuBuffer      Output buffer 2nd derivative wrt u
853     ///                       must have BindVBO() method returning an
854     ///                       MTLBuffer object of destination data
855     ///
856     /// @param duuDesc        vertex buffer descriptor for the duuBuffer
857     ///
858     /// @param duvBuffer      Output buffer 2nd derivative wrt u and v
859     ///                       must have BindVBO() method returning an
860     ///                       MTLBuffer object of destination data
861     ///
862     /// @param duvDesc        vertex buffer descriptor for the duvBuffer
863     ///
864     /// @param dvvBuffer      Output buffer 2nd derivative wrt v
865     ///                       must have BindVBO() method returning an
866     ///                       MTLBuffer object of destination data
867     ///
868     /// @param dvvDesc        vertex buffer descriptor for the dvvBuffer
869     ///
870     /// @param numPatchCoords number of patchCoords.
871     ///
872     /// @param patchCoords    array of locations to be evaluated.
873     ///                       must have BindVBO() method returning an
874     ///                       array of PatchCoord struct in VBO.
875     ///
876     /// @param patchTable     MTLPatchTable or equivalent
877     ///
878     /// @param instance       cached compiled instance. Clients are supposed to
879     ///                       pre-compile an instance of this class and provide
880     ///                       to this function. If it's null the kernel still
881     ///                       compute by instantiating on-demand kernel although
882     ///                       it may cause a performance problem.
883     ///
884     /// @param context        used to obtain the MTLDevice object and command queue
885     ///                       to obtain command buffers from.
886     ///
887     template <typename SRC_BUFFER, typename DST_BUFFER,
888               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatches(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,DST_BUFFER * duuBuffer,BufferDescriptor const & duuDesc,DST_BUFFER * duvBuffer,BufferDescriptor const & duvDesc,DST_BUFFER * dvvBuffer,BufferDescriptor const & dvvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLComputeEvaluator * instance,MTLContext * context)889     static bool EvalPatches(
890         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
891         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
892         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
893         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
894         DST_BUFFER *duuBuffer, BufferDescriptor const &duuDesc,
895         DST_BUFFER *duvBuffer, BufferDescriptor const &duvDesc,
896         DST_BUFFER *dvvBuffer, BufferDescriptor const &dvvDesc,
897         int numPatchCoords,
898         PATCHCOORD_BUFFER *patchCoords,
899         PATCH_TABLE *patchTable,
900         MTLComputeEvaluator* instance,
901         MTLContext* context) {
902 
903         if (instance) {
904             return instance->EvalPatches(srcBuffer, srcDesc,
905                                          dstBuffer, dstDesc,
906                                          duBuffer, duDesc,
907                                          dvBuffer, dvDesc,
908                                          duuBuffer, duuDesc,
909                                          duvBuffer, duvDesc,
910                                          dvvBuffer, dvvDesc,
911                                          numPatchCoords, patchCoords,
912                                          patchTable,
913                                          context);
914         } else {
915             // Create an instance on demand (slow)
916             instance = Create(srcDesc, dstDesc,
917                               duDesc, dvDesc,
918                               duuDesc, duvDesc, dvvDesc, context);
919             if (instance) {
920                 bool r = instance->EvalPatches(srcBuffer, srcDesc,
921                                                dstBuffer, dstDesc,
922                                                duBuffer, duDesc,
923                                                dvBuffer, dvDesc,
924                                                duuBuffer, duuDesc,
925                                                duvBuffer, duvDesc,
926                                                dvvBuffer, dvvDesc,
927                                                numPatchCoords, patchCoords,
928                                                patchTable,
929                                                context);
930                 delete instance;
931                 return r;
932             }
933             return false;
934         }
935     }
936 
937     /// \brief Generic limit eval function. This function has a same
938     ///        signature as other device kernels have so that it can be called
939     ///        in the same way.
940     ///
941     /// @param srcBuffer      Input primvar buffer.
942     ///                       must have BindVBO() method returning an
943     ///                       MTLBuffer object of source data
944     ///
945     /// @param srcDesc        vertex buffer descriptor for the input buffer
946     ///
947     /// @param dstBuffer      Output primvar buffer
948     ///                       must have BindVBOBuffer() method returning an
949     ///                       MTLBuffer object of destination data
950     ///
951     /// @param dstDesc        vertex buffer descriptor for the output buffer
952     ///
953     /// @param numPatchCoords number of patchCoords.
954     ///
955     /// @param patchCoords    array of locations to be evaluated.
956     ///                       must have BindVBO() method returning an
957     ///                       array of PatchCoord struct in VBO.
958     ///
959     /// @param patchTable     MTLPatchTable or equivalent
960     ///
961     /// @param context        used to obtain the MTLDevice object and command queue
962     ///                       to obtain command buffers from.
963     ///
964     template <typename SRC_BUFFER, typename DST_BUFFER,
965               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatches(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLContext * context)966     bool EvalPatches(
967         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
968         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
969         int numPatchCoords,
970         PATCHCOORD_BUFFER *patchCoords,
971         PATCH_TABLE *patchTable,
972         MTLContext* context) const {
973 
974         return EvalPatches(srcBuffer->BindMTLBuffer(context), srcDesc,
975                            dstBuffer->BindMTLBuffer(context), dstDesc,
976                            0, BufferDescriptor(),
977                            0, BufferDescriptor(),
978                            numPatchCoords,
979                            patchCoords->BindMTLBuffer(context),
980                            patchTable->GetPatchArrays(),
981                            patchTable->GetPatchIndexBuffer(),
982                            patchTable->GetPatchParamBuffer(),
983                            context);
984     }
985 
986     /// \brief Generic limit eval function with derivatives. This function has
987     ///        a same signature as other device kernels have so that it can be
988     ///        called in the same way.
989     ///
990     /// @param srcBuffer        Input primvar buffer.
991     ///                         must have BindVBO() method returning an
992     ///                         MTLBuffer object of source data
993     ///
994     /// @param srcDesc          vertex buffer descriptor for the input buffer
995     ///
996     /// @param dstBuffer        Output primvar buffer
997     ///                         must have BindVBO() method returning an
998     ///                         MTLBuffer object of destination data
999     ///
1000     /// @param dstDesc          vertex buffer descriptor for the output buffer
1001     ///
1002     /// @param duBuffer         Output buffer derivative wrt u
1003     ///                         must have BindVBO() method returning an
1004     ///                         MTLBuffer object of destination data
1005     ///
1006     /// @param duDesc           vertex buffer descriptor for the duBuffer
1007     ///
1008     /// @param dvBuffer         Output buffer derivative wrt v
1009     ///                         must have BindVBO() method returning an
1010     ///                         MTLBuffer object of destination data
1011     ///
1012     /// @param dvDesc           vertex buffer descriptor for the dvBuffer
1013     ///
1014     /// @param numPatchCoords   number of patchCoords.
1015     ///
1016     /// @param patchCoords      array of locations to be evaluated.
1017     ///
1018     /// @param patchTable       MTLPatchTable or equivalent
1019     ///
1020     /// @param context          used to obtain the MTLDevice object and command queue
1021     ///                         to obtain command buffers from.
1022     ///
1023     template <typename SRC_BUFFER, typename DST_BUFFER,
1024               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatches(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLContext * context)1025     bool EvalPatches(
1026         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1027         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1028         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
1029         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
1030         int numPatchCoords,
1031         PATCHCOORD_BUFFER *patchCoords,
1032         PATCH_TABLE *patchTable,
1033         MTLContext* context) const {
1034 
1035         return EvalPatches(srcBuffer->BindMTLBuffer(context), srcDesc,
1036                            dstBuffer->BindMTLBuffer(context), dstDesc,
1037                            duBuffer->BindMTLBuffer(context),  duDesc,
1038                            dvBuffer->BindMTLBuffer(context),  dvDesc,
1039                            numPatchCoords,
1040                            patchCoords->BindMTLBuffer(context),
1041                            patchTable->GetPatchArrays(),
1042                            patchTable->GetPatchIndexBuffer(),
1043                            patchTable->GetPatchParamBuffer(),
1044                            context);
1045     }
1046 
1047     /// \brief Generic limit eval function with derivatives. This function has
1048     ///        a same signature as other device kernels have so that it can be
1049     ///        called in the same way.
1050     ///
1051     /// @param srcBuffer        Input primvar buffer.
1052     ///                         must have BindVBO() method returning a
1053     ///                         MTLBuffer object of source data
1054     ///
1055     /// @param srcDesc          vertex buffer descriptor for the input buffer
1056     ///
1057     /// @param dstBuffer        Output primvar buffer
1058     ///                         must have BindVBO() method returning a
1059     ///                         MTLBuffer object of destination data
1060     ///
1061     /// @param dstDesc          vertex buffer descriptor for the output buffer
1062     ///
1063     /// @param duBuffer         Output buffer derivative wrt u
1064     ///                         must have BindVBO() method returning a
1065     ///                         MTLBuffer object of destination data
1066     ///
1067     /// @param duDesc           vertex buffer descriptor for the duBuffer
1068     ///
1069     /// @param dvBuffer         Output buffer derivative wrt v
1070     ///                         must have BindVBO() method returning a
1071     ///                         MTLBuffer object of destination data
1072     ///
1073     /// @param dvDesc           vertex buffer descriptor for the dvBuffer
1074     ///
1075     /// @param duuBuffer        Output buffer 2nd derivative wrt u
1076     ///                         must have BindVBO() method returning a
1077     ///                         MTLBuffer object of destination data
1078     ///
1079     /// @param duuDesc          vertex buffer descriptor for the duuBuffer
1080     ///
1081     /// @param duvBuffer        Output buffer 2nd derivative wrt u and v
1082     ///                         must have BindVBO() method returning a
1083     ///                         MTLBuffer object of destination data
1084     ///
1085     /// @param duvDesc          vertex buffer descriptor for the duvBuffer
1086     ///
1087     /// @param dvvBuffer        Output buffer 2nd derivative wrt v
1088     ///                         must have BindVBO() method returning a
1089     ///                         MTLBuffer object of destination data
1090     ///
1091     /// @param dvvDesc          vertex buffer descriptor for the dvvBuffer
1092     ///
1093     /// @param numPatchCoords   number of patchCoords.
1094     ///
1095     /// @param patchCoords      array of locations to be evaluated.
1096     ///
1097     /// @param patchTable       MTLPatchTable or equivalent
1098     ///
1099     /// @param context          used to obtain the MTLDevice object and command queue
1100     ///                         to obtain command buffers from.
1101     ///
1102     template <typename SRC_BUFFER, typename DST_BUFFER,
1103               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatches(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,DST_BUFFER * duuBuffer,BufferDescriptor const & duuDesc,DST_BUFFER * duvBuffer,BufferDescriptor const & duvDesc,DST_BUFFER * dvvBuffer,BufferDescriptor const & dvvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLContext * context)1104     bool EvalPatches(
1105         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1106         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1107         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
1108         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
1109         DST_BUFFER *duuBuffer, BufferDescriptor const &duuDesc,
1110         DST_BUFFER *duvBuffer, BufferDescriptor const &duvDesc,
1111         DST_BUFFER *dvvBuffer, BufferDescriptor const &dvvDesc,
1112         int numPatchCoords,
1113         PATCHCOORD_BUFFER *patchCoords,
1114         PATCH_TABLE *patchTable,
1115         MTLContext* context) const {
1116 
1117         return EvalPatches(srcBuffer->BindMTLBuffer(context), srcDesc,
1118                            dstBuffer->BindMTLBuffer(context), dstDesc,
1119                            duBuffer->BindMTLBuffer(context),  duDesc,
1120                            dvBuffer->BindMTLBuffer(context),  dvDesc,
1121                            duuBuffer->BindMTLBuffer(context), duuDesc,
1122                            duvBuffer->BindMTLBuffer(context), duvDesc,
1123                            dvvBuffer->BindMTLBuffer(context), dvvDesc,
1124                            numPatchCoords,
1125                            patchCoords->BindMTLBuffer(context),
1126                            patchTable->GetPatchArrays(),
1127                            patchTable->GetPatchIndexBuffer(),
1128                            patchTable->GetPatchParamBuffer(),
1129                            context);
1130     }
1131 
1132     bool EvalPatches(id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
1133                      id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
1134                      id<MTLBuffer> duBuffer,  BufferDescriptor const &duDesc,
1135                      id<MTLBuffer> dvBuffer,  BufferDescriptor const &dvDesc,
1136                      int numPatchCoords,
1137                      id<MTLBuffer> patchCoordsBuffer,
1138                      const PatchArrayVector &patchArrays,
1139                      id<MTLBuffer> patchIndexBuffer,
1140                      id<MTLBuffer> patchParamsBuffer,
1141                      MTLContext* context) const;
1142 
1143     bool EvalPatches(id<MTLBuffer> srcBuffer, BufferDescriptor const &srcDesc,
1144                      id<MTLBuffer> dstBuffer, BufferDescriptor const &dstDesc,
1145                      id<MTLBuffer> duBuffer,  BufferDescriptor const &duDesc,
1146                      id<MTLBuffer> dvBuffer,  BufferDescriptor const &dvDesc,
1147                      id<MTLBuffer> duuBuffer, BufferDescriptor const &duuDesc,
1148                      id<MTLBuffer> duvBuffer, BufferDescriptor const &duvDesc,
1149                      id<MTLBuffer> dvvBuffer, BufferDescriptor const &dvvDesc,
1150                      int numPatchCoords,
1151                      id<MTLBuffer> patchCoordsBuffer,
1152                      const PatchArrayVector &patchArrays,
1153                      id<MTLBuffer> patchIndexBuffer,
1154                      id<MTLBuffer> patchParamsBuffer,
1155                      MTLContext* context) const;
1156 
1157     /// \brief Generic limit eval function. This function has a same
1158     ///        signature as other device kernels have so that it can be called
1159     ///        in the same way.
1160     ///
1161     /// @param srcBuffer      Input primvar buffer.
1162     ///                       must have BindVBO() method returning an
1163     ///                       MTLBuffer object of source data
1164     ///
1165     /// @param srcDesc        vertex buffer descriptor for the input buffer
1166     ///
1167     /// @param dstBuffer      Output primvar buffer
1168     ///                       must have BindVBO() method returning an
1169     ///                       MTLBuffer object of destination data
1170     ///
1171     /// @param dstDesc        vertex buffer descriptor for the output buffer
1172     ///
1173     /// @param numPatchCoords number of patchCoords.
1174     ///
1175     /// @param patchCoords    array of locations to be evaluated.
1176     ///                       must have BindVBO() method returning an
1177     ///                       array of PatchCoord struct in VBO.
1178     ///
1179     /// @param patchTable     MTLPatchTable or equivalent
1180     ///
1181     /// @param instance       cached compiled instance. Clients are supposed to
1182     ///                       pre-compile an instance of this class and provide
1183     ///                       to this function. If it's null the kernel still
1184     ///                       compute by instantiating on-demand kernel although
1185     ///                       it may cause a performance problem.
1186     ///
1187     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1188     ///                       to obtain command buffers from.
1189     ///
1190     template <typename SRC_BUFFER, typename DST_BUFFER,
1191               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLComputeEvaluator const * instance,MTLContext * deviceContext)1192     static bool EvalPatchesVarying(
1193         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1194         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1195         int numPatchCoords,
1196         PATCHCOORD_BUFFER *patchCoords,
1197         PATCH_TABLE *patchTable,
1198         MTLComputeEvaluator const *instance,
1199         MTLContext* deviceContext) {
1200 
1201         if (instance) {
1202             return instance->EvalPatchesVarying(
1203                                          srcBuffer, srcDesc,
1204                                          dstBuffer, dstDesc,
1205                                          numPatchCoords, patchCoords,
1206                                          patchTable,
1207                                          deviceContext);
1208         } else {
1209             // Create an instance on demand (slow)
1210             instance = Create(srcDesc, dstDesc,
1211                               BufferDescriptor(),
1212                               BufferDescriptor(),
1213                               deviceContext);
1214             if (instance) {
1215                 bool r = instance->EvalPatchesVarying(
1216                                                srcBuffer, srcDesc,
1217                                                dstBuffer, dstDesc,
1218                                                numPatchCoords, patchCoords,
1219                                                patchTable,
1220                                                deviceContext);
1221                 delete instance;
1222                 return r;
1223             }
1224             return false;
1225         }
1226     }
1227 
1228     /// \brief Generic limit eval function. This function has a same
1229     ///        signature as other device kernels have so that it can be called
1230     ///        in the same way.
1231     ///
1232     /// @param srcBuffer      Input primvar buffer.
1233     ///                       must have BindVBO() method returning an
1234     ///                       MTLBuffer object of source data
1235     ///
1236     /// @param srcDesc        vertex buffer descriptor for the input buffer
1237     ///
1238     /// @param dstBuffer      Output primvar buffer
1239     ///                       must have BindVBO() method returning an
1240     ///                       MTLBuffer object of destination data
1241     ///
1242     /// @param dstDesc        vertex buffer descriptor for the output buffer
1243     ///
1244     /// @param numPatchCoords number of patchCoords.
1245     ///
1246     /// @param patchCoords    array of locations to be evaluated.
1247     ///                       must have BindVBO() method returning an
1248     ///                       array of PatchCoord struct in VBO.
1249     ///
1250     /// @param patchTable     MTLPatchTable or equivalent
1251     ///
1252     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1253     ///                       to obtain command buffers from.
1254     ///
1255     template <typename SRC_BUFFER, typename DST_BUFFER,
1256               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLContext * deviceContext)1257     bool EvalPatchesVarying(
1258         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1259         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1260         int numPatchCoords,
1261         PATCHCOORD_BUFFER *patchCoords,
1262         PATCH_TABLE *patchTable,
1263         MTLContext* deviceContext) const {
1264 
1265         return EvalPatches(srcBuffer->BindMTLBuffer(deviceContext), srcDesc,
1266                            dstBuffer->BindMTLBuffer(deviceContext), dstDesc,
1267                            0, BufferDescriptor(),
1268                            0, BufferDescriptor(),
1269                            numPatchCoords,
1270                            patchCoords->BindMTLBuffer(deviceContext),
1271                            patchTable->GetVaryingPatchArrays(),
1272                            patchTable->GetVaryingPatchIndexBuffer(),
1273                            patchTable->GetPatchParamBuffer(),
1274                            deviceContext
1275                            );
1276     }
1277 
1278     /// \brief Generic limit eval function. This function has a same
1279     ///        signature as other device kernels have so that it can be called
1280     ///        in the same way.
1281     ///
1282     /// @param srcBuffer      Input primvar buffer.
1283     ///                       must have BindVBO() method returning an
1284     ///                       MTLBuffer object of source data
1285     ///
1286     /// @param srcDesc        vertex buffer descriptor for the input buffer
1287     ///
1288     /// @param dstBuffer      Output primvar buffer
1289     ///                       must have BindVBO() method returning an
1290     ///                       MTLBuffer object of destination data
1291     ///
1292     /// @param dstDesc        vertex buffer descriptor for the output buffer
1293     ///
1294     /// @param duBuffer       Output buffer derivative wrt u
1295     ///                       must have BindVBO() method returning an
1296     ///                       MTLBuffer object of destination data
1297     ///
1298     /// @param duDesc         vertex buffer descriptor for the duBuffer
1299     ///
1300     /// @param dvBuffer       Output buffer derivative wrt v
1301     ///                       must have BindVBO() method returning an
1302     ///                       MTLBuffer object of destination data
1303     ///
1304     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
1305     ///
1306     /// @param numPatchCoords number of patchCoords.
1307     ///
1308     /// @param patchCoords    array of locations to be evaluated.
1309     ///                       must have BindVBO() method returning an
1310     ///                       array of PatchCoord struct in VBO.
1311     ///
1312     /// @param patchTable     MTLPatchTable or equivalent
1313     ///
1314     /// @param instance       cached compiled instance. Clients are supposed to
1315     ///                       pre-compile an instance of this class and provide
1316     ///                       to this function. If it's null the kernel still
1317     ///                       compute by instantiating on-demand kernel although
1318     ///                       it may cause a performance problem.
1319     ///
1320     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1321     ///                       to obtain command buffers from.
1322     ///
1323     template <typename SRC_BUFFER, typename DST_BUFFER,
1324               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLComputeEvaluator const * instance,MTLContext * deviceContext)1325     static bool EvalPatchesVarying(
1326         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1327         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1328         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
1329         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
1330         int numPatchCoords,
1331         PATCHCOORD_BUFFER *patchCoords,
1332         PATCH_TABLE *patchTable,
1333         MTLComputeEvaluator const *instance,
1334         MTLContext* deviceContext) {
1335 
1336         if (instance) {
1337             return instance->EvalPatchesVarying(
1338                                          srcBuffer, srcDesc,
1339                                          dstBuffer, dstDesc,
1340                                          duBuffer, duDesc,
1341                                          dvBuffer, dvDesc,
1342                                          numPatchCoords, patchCoords,
1343                                          patchTable,
1344                                          deviceContext);
1345         } else {
1346             // Create an instance on demand (slow)
1347             instance = Create(srcDesc, dstDesc,
1348                               duDesc, dvDesc,
1349                               deviceContext);
1350             if (instance) {
1351                 bool r = instance->EvalPatchesVarying(
1352                                                srcBuffer, srcDesc,
1353                                                dstBuffer, dstDesc,
1354                                                duBuffer, duDesc,
1355                                                dvBuffer, dvDesc,
1356                                                numPatchCoords, patchCoords,
1357                                                patchTable,
1358                                                deviceContext);
1359                 delete instance;
1360                 return r;
1361             }
1362             return false;
1363         }
1364     }
1365 
1366     /// \brief Generic limit eval function. This function has a same
1367     ///        signature as other device kernels have so that it can be called
1368     ///        in the same way.
1369     ///
1370     /// @param srcBuffer      Input primvar buffer.
1371     ///                       must have BindVBO() method returning a
1372     ///                       MTLBuffer object of source data
1373     ///
1374     /// @param srcDesc        vertex buffer descriptor for the input buffer
1375     ///
1376     /// @param dstBuffer      Output primvar buffer
1377     ///                       must have BindVBO() method returning a
1378     ///                       MTLBuffer object of destination data
1379     ///
1380     /// @param dstDesc        vertex buffer descriptor for the output buffer
1381     ///
1382     /// @param duBuffer       Output buffer derivative wrt u
1383     ///                       must have BindVBO() method returning a
1384     ///                       MTLBuffer object of destination data
1385     ///
1386     /// @param duDesc         vertex buffer descriptor for the duBuffer
1387     ///
1388     /// @param dvBuffer       Output buffer derivative wrt v
1389     ///                       must have BindVBO() method returning a
1390     ///                       MTLBuffer object of destination data
1391     ///
1392     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
1393     ///
1394     /// @param numPatchCoords number of patchCoords.
1395     ///
1396     /// @param patchCoords    array of locations to be evaluated.
1397     ///                       must have BindVBO() method returning an
1398     ///                       array of PatchCoord struct in VBO.
1399     ///
1400     /// @param patchTable     MTLPatchTable or equivalent
1401     ///
1402     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1403     ///                       to obtain command buffers from.
1404     ///
1405     template <typename SRC_BUFFER, typename DST_BUFFER,
1406               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLContext * deviceContext)1407     bool EvalPatchesVarying(
1408         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1409         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1410         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
1411         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
1412         int numPatchCoords,
1413         PATCHCOORD_BUFFER *patchCoords,
1414         PATCH_TABLE *patchTable,
1415         MTLContext* deviceContext) const {
1416 
1417         return EvalPatches(srcBuffer->BindMTLBuffer(deviceContext), srcDesc,
1418                            dstBuffer->BindMTLBuffer(deviceContext), dstDesc,
1419                            duBuffer->BindMTLBuffer(deviceContext),  duDesc,
1420                            dvBuffer->BindMTLBuffer(deviceContext),  dvDesc,
1421                            numPatchCoords,
1422                            patchCoords->BindMTLBuffer(deviceContext),
1423                            patchTable->GetVaryingPatchArrays(),
1424                            patchTable->GetVaryingPatchIndexBuffer(),
1425                            patchTable->GetPatchParamBuffer(),
1426                            deviceContext
1427                            );
1428     }
1429 
1430 
1431     /// \brief Generic limit eval function. This function has a same
1432     ///        signature as other device kernels have so that it can be called
1433     ///        in the same way.
1434     ///
1435     /// @param srcBuffer      Input primvar buffer.
1436     ///                       must have BindVBO() method returning an
1437     ///                       MTLBuffer object of source data
1438     ///
1439     /// @param srcDesc        vertex buffer descriptor for the input buffer
1440     ///
1441     /// @param dstBuffer      Output primvar buffer
1442     ///                       must have BindVBO() method returning an
1443     ///                       MTLBuffer object of destination data
1444     ///
1445     /// @param dstDesc        vertex buffer descriptor for the output buffer
1446     ///
1447     /// @param duBuffer       Output buffer derivative wrt u
1448     ///                       must have BindVBO() method returning an
1449     ///                       MTLBuffer object of destination data
1450     ///
1451     /// @param duDesc         vertex buffer descriptor for the duBuffer
1452     ///
1453     /// @param dvBuffer       Output buffer derivative wrt v
1454     ///                       must have BindVBO() method returning an
1455     ///                       MTLBuffer object of destination data
1456     ///
1457     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
1458     ///
1459     /// @param duuBuffer      Output buffer 2nd derivative wrt u
1460     ///                       must have BindVBO() method returning an
1461     ///                       MTLBuffer object of destination data
1462     ///
1463     /// @param duuDesc        vertex buffer descriptor for the duuBuffer
1464     ///
1465     /// @param duvBuffer      Output buffer 2nd derivative wrt u and v
1466     ///                       must have BindVBO() method returning an
1467     ///                       MTLBuffer object of destination data
1468     ///
1469     /// @param duvDesc        vertex buffer descriptor for the duvBuffer
1470     ///
1471     /// @param dvvBuffer      Output buffer 2nd derivative wrt v
1472     ///                       must have BindVBO() method returning an
1473     ///                       MTLBuffer object of destination data
1474     ///
1475     /// @param dvvDesc       vertex buffer descriptor for the dvvBuffer
1476     ///
1477     /// @param numPatchCoords number of patchCoords.
1478     ///
1479     /// @param patchCoords    array of locations to be evaluated.
1480     ///                       must have BindVBO() method returning an
1481     ///                       array of PatchCoord struct in VBO.
1482     ///
1483     /// @param patchTable     MTLPatchTable or equivalent
1484     ///
1485     /// @param instance       cached compiled instance. Clients are supposed to
1486     ///                       pre-compile an instance of this class and provide
1487     ///                       to this function. If it's null the kernel still
1488     ///                       compute by instantiating on-demand kernel although
1489     ///                       it may cause a performance problem.
1490     ///
1491     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1492     ///                       to obtain command buffers from.
1493     ///
1494     template <typename SRC_BUFFER, typename DST_BUFFER,
1495               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,DST_BUFFER * duuBuffer,BufferDescriptor const & duuDesc,DST_BUFFER * duvBuffer,BufferDescriptor const & duvDesc,DST_BUFFER * dvvBuffer,BufferDescriptor const & dvvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLComputeEvaluator const * instance,MTLContext * deviceContext)1496     static bool EvalPatchesVarying(
1497         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1498         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1499         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
1500         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
1501         DST_BUFFER *duuBuffer, BufferDescriptor const &duuDesc,
1502         DST_BUFFER *duvBuffer, BufferDescriptor const &duvDesc,
1503         DST_BUFFER *dvvBuffer, BufferDescriptor const &dvvDesc,
1504         int numPatchCoords,
1505         PATCHCOORD_BUFFER *patchCoords,
1506         PATCH_TABLE *patchTable,
1507         MTLComputeEvaluator const *instance,
1508         MTLContext* deviceContext) {
1509 
1510         if (instance) {
1511             return instance->EvalPatchesVarying(
1512                                          srcBuffer, srcDesc,
1513                                          dstBuffer, dstDesc,
1514                                          duBuffer, duDesc,
1515                                          dvBuffer, dvDesc,
1516                                          duuBuffer, duuDesc,
1517                                          duvBuffer, duvDesc,
1518                                          dvvBuffer, dvvDesc,
1519                                          numPatchCoords, patchCoords,
1520                                          patchTable,
1521                                          deviceContext);
1522         } else {
1523             // Create an instance on demand (slow)
1524             instance = Create(srcDesc, dstDesc,
1525                               duDesc, dvDesc,
1526                               duuDesc, duvDesc, dvvDesc,
1527                               deviceContext);
1528             if (instance) {
1529                 bool r = instance->EvalPatchesVarying(
1530                                                srcBuffer, srcDesc,
1531                                                dstBuffer, dstDesc,
1532                                                duBuffer, duDesc,
1533                                                dvBuffer, dvDesc,
1534                                                duuBuffer, duuDesc,
1535                                                duvBuffer, duvDesc,
1536                                                dvvBuffer, dvvDesc,
1537                                                numPatchCoords, patchCoords,
1538                                                patchTable,
1539                                                deviceContext);
1540                 delete instance;
1541                 return r;
1542             }
1543             return false;
1544         }
1545     }
1546 
1547     /// \brief Generic limit eval function. This function has a same
1548     ///        signature as other device kernels have so that it can be called
1549     ///        in the same way.
1550     ///
1551     /// @param srcBuffer      Input primvar buffer.
1552     ///                       must have BindVBO() method returning a
1553     ///                       MTLBuffer object of source data
1554     ///
1555     /// @param srcDesc        vertex buffer descriptor for the input buffer
1556     ///
1557     /// @param dstBuffer      Output primvar buffer
1558     ///                       must have BindVBO() method returning a
1559     ///                       MTLBuffer object of destination data
1560     ///
1561     /// @param dstDesc        vertex buffer descriptor for the output buffer
1562     ///
1563     /// @param duBuffer       Output buffer derivative wrt u
1564     ///                       must have BindVBO() method returning a
1565     ///                       MTLBuffer object of destination data
1566     ///
1567     /// @param duDesc         vertex buffer descriptor for the duBuffer
1568     ///
1569     /// @param dvBuffer       Output buffer derivative wrt v
1570     ///                       must have BindVBO() method returning a
1571     ///                       MTLBuffer object of destination data
1572     ///
1573     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
1574     ///
1575     /// @param duuBuffer      Output buffer 2nd derivative wrt u
1576     ///                       must have BindVBO() method returning a
1577     ///                       MTLBuffer object of destination data
1578     ///
1579     /// @param duuDesc        vertex buffer descriptor for the duuBuffer
1580     ///
1581     /// @param duvBuffer      Output buffer 2nd derivative wrt u and v
1582     ///                       must have BindVBO() method returning a
1583     ///                       MTLBuffer object of destination data
1584     ///
1585     /// @param duvDesc        vertex buffer descriptor for the duvBuffer
1586     ///
1587     /// @param dvvBuffer      Output buffer 2nd derivative wrt v
1588     ///                       must have BindVBO() method returning a
1589     ///                       MTLBuffer object of destination data
1590     ///
1591     /// @param dvvDesc        vertex buffer descriptor for the dvvBuffer
1592     ///
1593     /// @param numPatchCoords number of patchCoords.
1594     ///
1595     /// @param patchCoords    array of locations to be evaluated.
1596     ///                       must have BindVBO() method returning an
1597     ///                       array of PatchCoord struct in VBO.
1598     ///
1599     /// @param patchTable     MTLPatchTable or equivalent
1600     ///
1601     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1602     ///                       to obtain command buffers from.
1603     ///
1604     template <typename SRC_BUFFER, typename DST_BUFFER,
1605               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,DST_BUFFER * duuBuffer,BufferDescriptor const & duuDesc,DST_BUFFER * duvBuffer,BufferDescriptor const & duvDesc,DST_BUFFER * dvvBuffer,BufferDescriptor const & dvvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,MTLContext * deviceContext)1606     bool EvalPatchesVarying(
1607         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1608         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1609         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
1610         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
1611         DST_BUFFER *duuBuffer, BufferDescriptor const &duuDesc,
1612         DST_BUFFER *duvBuffer, BufferDescriptor const &duvDesc,
1613         DST_BUFFER *dvvBuffer, BufferDescriptor const &dvvDesc,
1614         int numPatchCoords,
1615         PATCHCOORD_BUFFER *patchCoords,
1616         PATCH_TABLE *patchTable,
1617         MTLContext* deviceContext) const {
1618 
1619         return EvalPatches(srcBuffer->BindMTLBuffer(deviceContext), srcDesc,
1620                            dstBuffer->BindMTLBuffer(deviceContext), dstDesc,
1621                            duBuffer->BindMTLBuffer(deviceContext),  duDesc,
1622                            dvBuffer->BindMTLBuffer(deviceContext),  dvDesc,
1623                            duuBuffer->BindMTLBuffer(deviceContext), duuDesc,
1624                            duvBuffer->BindMTLBuffer(deviceContext), duvDesc,
1625                            dvvBuffer->BindMTLBuffer(deviceContext), dvvDesc,
1626                            numPatchCoords,
1627                            patchCoords->BindMTLBuffer(deviceContext),
1628                            patchTable->GetVaryingPatchArrays(),
1629                            patchTable->GetVaryingPatchIndexBuffer(),
1630                            patchTable->GetPatchParamBuffer(),
1631                            deviceContext
1632                            );
1633     }
1634 
1635     /// \brief Generic limit eval function. This function has a same
1636     ///        signature as other device kernels have so that it can be called
1637     ///        in the same way.
1638     ///
1639     /// @param srcBuffer      Input primvar buffer.
1640     ///                       must have BindVBO() method returning an
1641     ///                       MTLBuffer object of source data
1642     ///
1643     /// @param srcDesc        vertex buffer descriptor for the input buffer
1644     ///
1645     /// @param dstBuffer      Output primvar buffer
1646     ///                       must have BindVBO() method returning an
1647     ///                       MTLBuffer object of destination data
1648     ///
1649     /// @param dstDesc        vertex buffer descriptor for the output buffer
1650     ///
1651     /// @param numPatchCoords number of patchCoords.
1652     ///
1653     /// @param patchCoords    array of locations to be evaluated.
1654     ///                       must have BindVBO() method returning an
1655     ///                       array of PatchCoord struct in VBO.
1656     ///
1657     /// @param patchTable     MTLPatchTable or equivalent
1658     ///
1659     /// @param fvarChannel    face-varying channel
1660     ///
1661     /// @param instance       cached compiled instance. Clients are supposed to
1662     ///                       pre-compile an instance of this class and provide
1663     ///                       to this function. If it's null the kernel still
1664     ///                       compute by instantiating on-demand kernel although
1665     ///                       it may cause a performance problem.
1666     ///
1667     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1668     ///                       to obtain command buffers from.
1669     ///
1670     template <typename SRC_BUFFER, typename DST_BUFFER,
1671               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesFaceVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,int fvarChannel,MTLComputeEvaluator const * instance,MTLContext * deviceContext)1672     static bool EvalPatchesFaceVarying(
1673         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1674         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1675         int numPatchCoords,
1676         PATCHCOORD_BUFFER *patchCoords,
1677         PATCH_TABLE *patchTable,
1678         int fvarChannel,
1679         MTLComputeEvaluator const *instance,
1680         MTLContext* deviceContext) {
1681 
1682         if (instance) {
1683             return instance->EvalPatchesFaceVarying(
1684                                          srcBuffer, srcDesc,
1685                                          dstBuffer, dstDesc,
1686                                          numPatchCoords, patchCoords,
1687                                          patchTable,
1688                                          fvarChannel,
1689                                          deviceContext);
1690         } else {
1691             // Create an instance on demand (slow)
1692             instance = Create(srcDesc, dstDesc,
1693                               BufferDescriptor(),
1694                               BufferDescriptor(),
1695                               deviceContext);
1696             if (instance) {
1697                 bool r = instance->EvalPatchesFaceVarying(
1698                                                srcBuffer, srcDesc,
1699                                                dstBuffer, dstDesc,
1700                                                numPatchCoords, patchCoords,
1701                                                patchTable,
1702                                                fvarChannel,
1703                                                deviceContext);
1704                 delete instance;
1705                 return r;
1706             }
1707             return false;
1708         }
1709     }
1710 
1711     /// \brief Generic limit eval function. This function has a same
1712     ///        signature as other device kernels have so that it can be called
1713     ///        in the same way.
1714     ///
1715     /// @param srcBuffer      Input primvar buffer.
1716     ///                       must have BindVBO() method returning a
1717     ///                       MTLBuffer object of source data
1718     ///
1719     /// @param srcDesc        vertex buffer descriptor for the input buffer
1720     ///
1721     /// @param dstBuffer      Output primvar buffer
1722     ///                       must have BindVBO() method returning a
1723     ///                       MTLBuffer object of destination data
1724     ///
1725     /// @param dstDesc        vertex buffer descriptor for the output buffer
1726     ///
1727     /// @param numPatchCoords number of patchCoords.
1728     ///
1729     /// @param patchCoords    array of locations to be evaluated.
1730     ///                       must have BindVBO() method returning an
1731     ///                       array of PatchCoord struct in VBO.
1732     ///
1733     /// @param patchTable     MTLPatchTable or equivalent
1734     ///
1735     /// @param fvarChannel    face-varying channel
1736     ///
1737     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1738     ///                       to obtain command buffers from.
1739     ///
1740     template <typename SRC_BUFFER, typename DST_BUFFER,
1741               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesFaceVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,int fvarChannel,MTLContext * deviceContext)1742     bool EvalPatchesFaceVarying(
1743         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1744         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1745         int numPatchCoords,
1746         PATCHCOORD_BUFFER *patchCoords,
1747         PATCH_TABLE *patchTable,
1748         int fvarChannel,
1749         MTLContext* deviceContext) const {
1750 
1751         return EvalPatches(srcBuffer->BindMTLBuffer(deviceContext), srcDesc,
1752                            dstBuffer->BindMTLBuffer(deviceContext), dstDesc,
1753                            0, BufferDescriptor(),
1754                            0, BufferDescriptor(),
1755                            numPatchCoords,
1756                            patchCoords->BindMTLBuffer(deviceContext),
1757                            patchTable->GetFVarPatchArrays(fvarChannel),
1758                            patchTable->GetFVarPatchIndexBuffer(fvarChannel),
1759                            patchTable->GetFVarPatchParamBuffer(fvarChannel),
1760                            deviceContext
1761                            );
1762     }
1763 
1764     /// \brief Generic limit eval function. This function has a same
1765     ///        signature as other device kernels have so that it can be called
1766     ///        in the same way.
1767     ///
1768     /// @param srcBuffer      Input primvar buffer.
1769     ///                       must have BindVBO() method returning an
1770     ///                       MTLBuffer object of source data
1771     ///
1772     /// @param srcDesc        vertex buffer descriptor for the input buffer
1773     ///
1774     /// @param dstBuffer      Output primvar buffer
1775     ///                       must have BindVBO() method returning an
1776     ///                       MTLBuffer object of destination data
1777     ///
1778     /// @param dstDesc        vertex buffer descriptor for the output buffer
1779     ///
1780     /// @param duBuffer       Output buffer derivative wrt u
1781     ///                       must have BindVBO() method returning an
1782     ///                       MTLBuffer object of destination data
1783     ///
1784     /// @param duDesc         vertex buffer descriptor for the duBuffer
1785     ///
1786     /// @param dvBuffer       Output buffer derivative wrt v
1787     ///                       must have BindVBO() method returning an
1788     ///                       MTLBuffer object of destination data
1789     ///
1790     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
1791     ///
1792     /// @param numPatchCoords number of patchCoords.
1793     ///
1794     /// @param patchCoords    array of locations to be evaluated.
1795     ///                       must have BindVBO() method returning an
1796     ///                       array of PatchCoord struct in VBO.
1797     ///
1798     /// @param patchTable     MTLPatchTable or equivalent
1799     ///
1800     /// @param fvarChannel    face-varying channel
1801     ///
1802     /// @param instance       cached compiled instance. Clients are supposed to
1803     ///                       pre-compile an instance of this class and provide
1804     ///                       to this function. If it's null the kernel still
1805     ///                       compute by instantiating on-demand kernel although
1806     ///                       it may cause a performance problem.
1807     ///
1808     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1809     ///                       to obtain command buffers from.
1810     ///
1811     template <typename SRC_BUFFER, typename DST_BUFFER,
1812               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesFaceVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,int fvarChannel,MTLComputeEvaluator const * instance,MTLContext * deviceContext)1813     static bool EvalPatchesFaceVarying(
1814         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1815         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1816         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
1817         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
1818         int numPatchCoords,
1819         PATCHCOORD_BUFFER *patchCoords,
1820         PATCH_TABLE *patchTable,
1821         int fvarChannel,
1822         MTLComputeEvaluator const *instance,
1823         MTLContext* deviceContext) {
1824 
1825         if (instance) {
1826             return instance->EvalPatchesFaceVarying(
1827                                          srcBuffer, srcDesc,
1828                                          dstBuffer, dstDesc,
1829                                          duBuffer, duDesc,
1830                                          dvBuffer, dvDesc,
1831                                          numPatchCoords, patchCoords,
1832                                          patchTable,
1833                                          fvarChannel,
1834                                          deviceContext);
1835         } else {
1836             // Create an instance on demand (slow)
1837             instance = Create(srcDesc, dstDesc,
1838                               duDesc, dvDesc,
1839                               deviceContext);
1840             if (instance) {
1841                 bool r = instance->EvalPatchesFaceVarying(
1842                                                srcBuffer, srcDesc,
1843                                                dstBuffer, dstDesc,
1844                                                duBuffer, duDesc,
1845                                                dvBuffer, dvDesc,
1846                                                numPatchCoords, patchCoords,
1847                                                patchTable,
1848                                                fvarChannel,
1849                                                deviceContext);
1850                 delete instance;
1851                 return r;
1852             }
1853             return false;
1854         }
1855     }
1856 
1857     /// \brief Generic limit eval function. This function has a same
1858     ///        signature as other device kernels have so that it can be called
1859     ///        in the same way.
1860     ///
1861     /// @param srcBuffer      Input primvar buffer.
1862     ///                       must have BindVBO() method returning a
1863     ///                       MTLBuffer object of source data
1864     ///
1865     /// @param srcDesc        vertex buffer descriptor for the input buffer
1866     ///
1867     /// @param dstBuffer      Output primvar buffer
1868     ///                       must have BindVBO() method returning a
1869     ///                       MTLBuffer object of destination data
1870     ///
1871     /// @param dstDesc        vertex buffer descriptor for the output buffer
1872     ///
1873     /// @param duBuffer       Output buffer derivative wrt u
1874     ///                       must have BindVBO() method returning a
1875     ///                       MTLBuffer object of destination data
1876     ///
1877     /// @param duDesc         vertex buffer descriptor for the duBuffer
1878     ///
1879     /// @param dvBuffer       Output buffer derivative wrt v
1880     ///                       must have BindVBO() method returning a
1881     ///                       MTLBuffer object of destination data
1882     ///
1883     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
1884     ///
1885     /// @param numPatchCoords number of patchCoords.
1886     ///
1887     /// @param patchCoords    array of locations to be evaluated.
1888     ///                       must have BindVBO() method returning an
1889     ///                       array of PatchCoord struct in VBO.
1890     ///
1891     /// @param patchTable     MTLPatchTable or equivalent
1892     ///
1893     /// @param fvarChannel    face-varying channel
1894     ///
1895     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1896     ///                       to obtain command buffers from.
1897     ///
1898     template <typename SRC_BUFFER, typename DST_BUFFER,
1899               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesFaceVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,int fvarChannel,MTLContext * deviceContext)1900     bool EvalPatchesFaceVarying(
1901         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1902         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1903         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
1904         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
1905         int numPatchCoords,
1906         PATCHCOORD_BUFFER *patchCoords,
1907         PATCH_TABLE *patchTable,
1908         int fvarChannel,
1909         MTLContext* deviceContext) const {
1910 
1911         return EvalPatches(srcBuffer->BindMTLBuffer(deviceContext), srcDesc,
1912                            dstBuffer->BindMTLBuffer(deviceContext), dstDesc,
1913                            duBuffer->BindMTLBuffer(deviceContext),  duDesc,
1914                            dvBuffer->BindMTLBuffer(deviceContext),  dvDesc,
1915                            numPatchCoords,
1916                            patchCoords->BindMTLBuffer(deviceContext),
1917                            patchTable->GetFVarPatchArrays(fvarChannel),
1918                            patchTable->GetFVarPatchIndexBuffer(fvarChannel),
1919                            patchTable->GetFVarPatchParamBuffer(fvarChannel),
1920                            deviceContext
1921                            );
1922     }
1923 
1924     /// \brief Generic limit eval function. This function has a same
1925     ///        signature as other device kernels have so that it can be called
1926     ///        in the same way.
1927     ///
1928     /// @param srcBuffer      Input primvar buffer.
1929     ///                       must have BindVBO() method returning an
1930     ///                       MTLBuffer object of source data
1931     ///
1932     /// @param srcDesc        vertex buffer descriptor for the input buffer
1933     ///
1934     /// @param dstBuffer      Output primvar buffer
1935     ///                       must have BindVBO() method returning an
1936     ///                       MTLBuffer object of destination data
1937     ///
1938     /// @param dstDesc        vertex buffer descriptor for the output buffer
1939     ///
1940     /// @param duBuffer       Output buffer derivative wrt u
1941     ///                       must have BindVBO() method returning an
1942     ///                       MTLBuffer object of destination data
1943     ///
1944     /// @param duDesc         vertex buffer descriptor for the duBuffer
1945     ///
1946     /// @param dvBuffer       Output buffer derivative wrt v
1947     ///                       must have BindVBO() method returning an
1948     ///                       MTLBuffer object of destination data
1949     ///
1950     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
1951     ///
1952     /// @param duuBuffer      Output buffer 2nd derivative wrt u
1953     ///                       must have BindVBO() method returning an
1954     ///                       MTLBuffer object of destination data
1955     ///
1956     /// @param duuDesc        vertex buffer descriptor for the duuBuffer
1957     ///
1958     /// @param duvBuffer      Output buffer 2nd derivative wrt u and v
1959     ///                       must have BindVBO() method returning an
1960     ///                       MTLBuffer object of destination data
1961     ///
1962     /// @param duvDesc        vertex buffer descriptor for the duvBuffer
1963     ///
1964     /// @param dvvBuffer      Output buffer 2nd derivative wrt v
1965     ///                       must have BindVBO() method returning an
1966     ///                       MTLBuffer object of destination data
1967     ///
1968     /// @param dvvDesc       vertex buffer descriptor for the dvvBuffer
1969     ///
1970     /// @param numPatchCoords number of patchCoords.
1971     ///
1972     /// @param patchCoords    array of locations to be evaluated.
1973     ///                       must have BindVBO() method returning an
1974     ///                       array of PatchCoord struct in VBO.
1975     ///
1976     /// @param patchTable     MTLPatchTable or equivalent
1977     ///
1978     /// @param fvarChannel    face-varying channel
1979     ///
1980     /// @param instance       cached compiled instance. Clients are supposed to
1981     ///                       pre-compile an instance of this class and provide
1982     ///                       to this function. If it's null the kernel still
1983     ///                       compute by instantiating on-demand kernel although
1984     ///                       it may cause a performance problem.
1985     ///
1986     /// @param deviceContext  used to obtain the MTLDevice object and command queue
1987     ///                       to obtain command buffers from.
1988     ///
1989     template <typename SRC_BUFFER, typename DST_BUFFER,
1990               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesFaceVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,DST_BUFFER * duuBuffer,BufferDescriptor const & duuDesc,DST_BUFFER * duvBuffer,BufferDescriptor const & duvDesc,DST_BUFFER * dvvBuffer,BufferDescriptor const & dvvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,int fvarChannel,MTLComputeEvaluator const * instance,MTLContext * deviceContext)1991     static bool EvalPatchesFaceVarying(
1992         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
1993         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
1994         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
1995         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
1996         DST_BUFFER *duuBuffer, BufferDescriptor const &duuDesc,
1997         DST_BUFFER *duvBuffer, BufferDescriptor const &duvDesc,
1998         DST_BUFFER *dvvBuffer, BufferDescriptor const &dvvDesc,
1999         int numPatchCoords,
2000         PATCHCOORD_BUFFER *patchCoords,
2001         PATCH_TABLE *patchTable,
2002         int fvarChannel,
2003         MTLComputeEvaluator const *instance,
2004         MTLContext* deviceContext) {
2005 
2006         if (instance) {
2007             return instance->EvalPatchesFaceVarying(
2008                                          srcBuffer, srcDesc,
2009                                          dstBuffer, dstDesc,
2010                                          duBuffer, duDesc,
2011                                          dvBuffer, dvDesc,
2012                                          duuBuffer, duuDesc,
2013                                          duvBuffer, duvDesc,
2014                                          dvvBuffer, dvvDesc,
2015                                          numPatchCoords, patchCoords,
2016                                          patchTable,
2017                                          fvarChannel,
2018                                          deviceContext);
2019         } else {
2020             // Create an instance on demand (slow)
2021             instance = Create(srcDesc, dstDesc,
2022                               duDesc, dvDesc,
2023                               duuDesc, duvDesc, dvvDesc,
2024                               deviceContext);
2025             if (instance) {
2026                 bool r = instance->EvalPatchesFaceVarying(
2027                                                srcBuffer, srcDesc,
2028                                                dstBuffer, dstDesc,
2029                                                duBuffer, duDesc,
2030                                                dvBuffer, dvDesc,
2031                                                duuBuffer, duuDesc,
2032                                                duvBuffer, duvDesc,
2033                                                dvvBuffer, dvvDesc,
2034                                                numPatchCoords, patchCoords,
2035                                                patchTable,
2036                                                fvarChannel,
2037                                                deviceContext);
2038                 delete instance;
2039                 return r;
2040             }
2041             return false;
2042         }
2043     }
2044 
2045     /// \brief Generic limit eval function. This function has a same
2046     ///        signature as other device kernels have so that it can be called
2047     ///        in the same way.
2048     ///
2049     /// @param srcBuffer      Input primvar buffer.
2050     ///                       must have BindVBO() method returning a
2051     ///                       MTLBuffer object of source data
2052     ///
2053     /// @param srcDesc        vertex buffer descriptor for the input buffer
2054     ///
2055     /// @param dstBuffer      Output primvar buffer
2056     ///                       must have BindVBO() method returning a
2057     ///                       MTLBuffer object of destination data
2058     ///
2059     /// @param dstDesc        vertex buffer descriptor for the output buffer
2060     ///
2061     /// @param duBuffer       Output buffer derivative wrt u
2062     ///                       must have BindVBO() method returning a
2063     ///                       MTLBuffer object of destination data
2064     ///
2065     /// @param duDesc         vertex buffer descriptor for the duBuffer
2066     ///
2067     /// @param dvBuffer       Output buffer derivative wrt v
2068     ///                       must have BindVBO() method returning a
2069     ///                       MTLBuffer object of destination data
2070     ///
2071     /// @param dvDesc         vertex buffer descriptor for the dvBuffer
2072     ///
2073     /// @param duuBuffer      Output buffer 2nd derivative wrt u
2074     ///                       must have BindVBO() method returning a
2075     ///                       MTLBuffer object of destination data
2076     ///
2077     /// @param duuDesc        vertex buffer descriptor for the duuBuffer
2078     ///
2079     /// @param duvBuffer      Output buffer 2nd derivative wrt u and v
2080     ///                       must have BindVBO() method returning a
2081     ///                       MTLBuffer object of destination data
2082     ///
2083     /// @param duvDesc        vertex buffer descriptor for the duvBuffer
2084     ///
2085     /// @param dvvBuffer      Output buffer 2nd derivative wrt v
2086     ///                       must have BindVBO() method returning a
2087     ///                       MTLBuffer object of destination data
2088     ///
2089     /// @param dvvDesc        vertex buffer descriptor for the dvvBuffer
2090     ///
2091     /// @param numPatchCoords number of patchCoords.
2092     ///
2093     /// @param patchCoords    array of locations to be evaluated.
2094     ///                       must have BindVBO() method returning an
2095     ///                       array of PatchCoord struct in VBO.
2096     ///
2097     /// @param patchTable     MTLPatchTable or equivalent
2098     ///
2099     /// @param fvarChannel    face-varying channel
2100     ///
2101     /// @param deviceContext  used to obtain the MTLDevice object and command queue
2102     ///                       to obtain command buffers from.
2103     ///
2104     template <typename SRC_BUFFER, typename DST_BUFFER,
2105               typename PATCHCOORD_BUFFER, typename PATCH_TABLE>
EvalPatchesFaceVarying(SRC_BUFFER * srcBuffer,BufferDescriptor const & srcDesc,DST_BUFFER * dstBuffer,BufferDescriptor const & dstDesc,DST_BUFFER * duBuffer,BufferDescriptor const & duDesc,DST_BUFFER * dvBuffer,BufferDescriptor const & dvDesc,DST_BUFFER * duuBuffer,BufferDescriptor const & duuDesc,DST_BUFFER * duvBuffer,BufferDescriptor const & duvDesc,DST_BUFFER * dvvBuffer,BufferDescriptor const & dvvDesc,int numPatchCoords,PATCHCOORD_BUFFER * patchCoords,PATCH_TABLE * patchTable,int fvarChannel,MTLContext * deviceContext)2106     bool EvalPatchesFaceVarying(
2107         SRC_BUFFER *srcBuffer, BufferDescriptor const &srcDesc,
2108         DST_BUFFER *dstBuffer, BufferDescriptor const &dstDesc,
2109         DST_BUFFER *duBuffer,  BufferDescriptor const &duDesc,
2110         DST_BUFFER *dvBuffer,  BufferDescriptor const &dvDesc,
2111         DST_BUFFER *duuBuffer, BufferDescriptor const &duuDesc,
2112         DST_BUFFER *duvBuffer, BufferDescriptor const &duvDesc,
2113         DST_BUFFER *dvvBuffer, BufferDescriptor const &dvvDesc,
2114         int numPatchCoords,
2115         PATCHCOORD_BUFFER *patchCoords,
2116         PATCH_TABLE *patchTable,
2117         int fvarChannel,
2118         MTLContext* deviceContext) const {
2119 
2120         return EvalPatches(srcBuffer->BindMTLBuffer(deviceContext), srcDesc,
2121                            dstBuffer->BindMTLBuffer(deviceContext), dstDesc,
2122                            duBuffer->BindMTLBuffer(deviceContext),  duDesc,
2123                            dvBuffer->BindMTLBuffer(deviceContext),  dvDesc,
2124                            duuBuffer->BindMTLBuffer(deviceContext), duuDesc,
2125                            duvBuffer->BindMTLBuffer(deviceContext), duvDesc,
2126                            dvvBuffer->BindMTLBuffer(deviceContext), dvvDesc,
2127                            numPatchCoords,
2128                            patchCoords->BindMTLBuffer(deviceContext),
2129                            patchTable->GetFVarPatchArrays(fvarChannel),
2130                            patchTable->GetFVarPatchIndexBuffer(fvarChannel),
2131                            patchTable->GetFVarPatchParamBuffer(fvarChannel),
2132                            fvarChannel,
2133                            deviceContext
2134                            );
2135     }
2136 
2137     /// Configure compute pipline state. Returns false if it fails to create the pipeline state.
2138     bool Compile(BufferDescriptor const &srcDesc,
2139                  BufferDescriptor const &dstDesc,
2140                  BufferDescriptor const &duDesc,
2141                  BufferDescriptor const &dvDesc,
2142                  BufferDescriptor const &duuDesc,
2143                  BufferDescriptor const &duvDesc,
2144                  BufferDescriptor const &dvvDesc,
2145                  MTLContext* context);
2146 
2147     /// Wait for the dispatched kernel to finish.
2148     static void Synchronize(MTLContext* context);
2149 
2150     private:
2151 
2152     id<MTLLibrary> _computeLibrary;
2153     id<MTLComputePipelineState> _evalStencils;
2154     id<MTLComputePipelineState> _evalPatches;
2155     id<MTLBuffer> _parameterBuffer;
2156 
2157     int _workGroupSize;
2158 };
2159 
2160 } //end namespace Osd
2161 
2162 } //end namespace OPENSUBDIV_VERSION
2163 using namespace OPENSUBDIV_VERSION;
2164 
2165 } //end namespace OpenSubdiv
2166 
2167 #endif // OPENSUBDIV3_OSD_MTL_COMPUTE_EVALUATOR_H
2168