-
Notifications
You must be signed in to change notification settings - Fork 47
/
amprt.h
executable file
·3926 lines (3232 loc) · 155 KB
/
amprt.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/***
* ==++==
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* ==--==
* =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*
* amprt.h
*
* Define the C++ interfaces exported by the C++ AMP runtime
*
* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
****/
#pragma once
#ifndef _SILENCE_AMP_DEPRECATION_WARNINGS
#error <amprt.h> is part of C++ AMP which is deprecated by Microsoft and will be REMOVED. \
You can define _SILENCE_AMP_DEPRECATION_WARNINGS to acknowledge that you have received this warning.
#endif // _SILENCE_AMP_DEPRECATION_WARNINGS
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
#error ERROR: C++ AMP runtime is not supported for applications where WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP.
#endif
#if !(defined (_M_X64) || defined (_M_IX86) || defined (_M_ARM) || defined (_M_ARM64) )
#error ERROR: C++ AMP runtime is supported only on X64, X86, ARM, and _M_ARM64 architectures.
#endif
#if defined (_M_CEE)
#error ERROR: C++ AMP runtime is not supported when compiling /clr.
#endif
#ifndef __cplusplus
#error ERROR: C++ AMP runtime is supported only for C++.
#endif
#if !defined(_CXXAMP)
#if defined(_DEBUG)
#pragma comment(lib, "vcampd")
#else // _DEBUG
#pragma comment(lib, "vcamp")
#endif // _DEBUG
#endif // _CXXAMP
#if !defined(_CXXAMP)
#define __GPU restrict(amp,cpu)
#define __GPU_ONLY restrict(amp)
#define __CPU_ONLY restrict(cpu)
#else
#define __GPU
#define __GPU_ONLY
#define __CPU_ONLY
#endif // _CXXAMP
#include <Unknwn.h>
#include <crtdbg.h>
#include <string>
#include <vector>
#include <iterator>
#if defined(_CXXAMP)
#include <strsafe.h>
#endif // _CXXAMP
#include <future>
#include <functional>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <concrt.h>
#include <type_traits>
#include "amprt_exceptions.h"
#if !defined(_AMPIMP)
#define _AMPIMP __declspec(dllimport)
#endif
#pragma pack(push,8)
// Part of runtime-compiler interface
extern "C"
{
// Access mode of fields
enum _Access_mode
{
_No_access = 0,
_Read_access = (1 << 0),
_Write_access = (1 << 1),
_Is_array_mode = (1 << 30),
_Read_write_access = _Read_access | _Write_access,
};
}
namespace Concurrency
{
/// <summary>
/// Enumeration type used to denote the various types of access to data.
/// </summary>
enum access_type
{
access_type_none = 0,
access_type_read = (1 << 0),
access_type_write = (1 << 1),
access_type_read_write = access_type_read | access_type_write,
access_type_auto = (1 << 31),
};
// Forward declarations
class accelerator_view;
class accelerator;
namespace details
{
const size_t ERROR_MSG_BUFFER_SIZE = 1024;
// A reference counter to be used as the base class for all reference counted types.
class _Reference_counter
{
public:
// Constructor.
_Reference_counter() : _M_rc(0) {}
// Destructor.
virtual ~_Reference_counter() noexcept(false) {}
// Add a reference.
// Thread-safe.
size_t _Add_reference()
{
return InterlockedIncrement(reinterpret_cast<LONG volatile*>(&_M_rc));
}
// Remove a reference.
// Thread-safe.
size_t _Remove_reference()
{
_ASSERTE(_M_rc > 0);
size_t refCount = InterlockedDecrement(reinterpret_cast<LONG volatile*>(&_M_rc));
if (refCount == 0)
this->_Release();
return refCount;
}
// Release the counter
_AMPIMP void _Release();
// Return the reference count value
size_t _Get_reference_count()
{
return _M_rc;
}
private:
size_t _M_rc;
};
// A smart pointer to a reference counted object
// T must be a type derived from _Reference_counter
template <class T>
class _Reference_counted_obj_ptr
{
public:
// Constructor
_Reference_counted_obj_ptr(T* _Ptr = NULL) : _M_obj_ptr(_Ptr)
{
_Init();
}
// Copy constructor
_Reference_counted_obj_ptr(const _Reference_counted_obj_ptr &_Other) : _M_obj_ptr(_Other._M_obj_ptr)
{
_Init();
}
// Move constructor
_Reference_counted_obj_ptr(_Reference_counted_obj_ptr &&_Other) noexcept : _M_obj_ptr(_Other._M_obj_ptr)
{
_Other._M_obj_ptr = nullptr;
// No change to ref-count
}
// Destructor
~_Reference_counted_obj_ptr()
{
if (_M_obj_ptr != NULL) {
_UnInitialize(_M_obj_ptr);
}
}
// Assignment operator
_Reference_counted_obj_ptr& operator=(const _Reference_counted_obj_ptr &_Other)
{
if (_M_obj_ptr != _Other._M_obj_ptr)
{
T *oldPtr = _M_obj_ptr;
_M_obj_ptr = _Other._M_obj_ptr;
_Init();
if (oldPtr != NULL) {
_UnInitialize(oldPtr);
}
}
return *this;
}
// Move-assignment operator
_Reference_counted_obj_ptr& operator=(_Reference_counted_obj_ptr &&_Other) noexcept
{
if (_M_obj_ptr != _Other._M_obj_ptr)
{
T *oldPtr = _M_obj_ptr;
_M_obj_ptr = _Other._M_obj_ptr;
_Other._M_obj_ptr = nullptr;
// No change to ref-count of the adopted pointer.
if (oldPtr != nullptr)
{
_UnInitialize(oldPtr);
}
}
return *this;
}
_Ret_ T* operator->() const
{
return _M_obj_ptr;
}
T& operator*() const
{
return *_M_obj_ptr;
}
operator T*() const
{
return _M_obj_ptr;
}
_Ret_ T* _Get_ptr() const
{
return _M_obj_ptr;
}
private:
T *_M_obj_ptr;
void _Init()
{
if (_M_obj_ptr == NULL)
return;
reinterpret_cast<_Reference_counter*>(_M_obj_ptr)->_Add_reference();
}
static void _UnInitialize(_In_ T *_Obj_ptr)
{
reinterpret_cast<_Reference_counter*>(_Obj_ptr)->_Remove_reference();
}
};
// Forward declarations
class _Trace;
class _Amp_runtime_trace;
class _Buffer;
class _Texture;
class _Sampler;
class _Ubiquitous_buffer;
class _D3D_interop;
class _Accelerator_view_impl;
class _CPU_accelerator_view_impl;
class _D3D_accelerator_view_impl;
class _Accelerator_impl;
class _Event_impl;
class _DPC_runtime_factory;
class _View_shape;
struct _Buffer_descriptor;
class _Accelerator_view_hasher;
struct _DPC_shader_blob;
struct _View_info;
// The enum specifies the base type for short vector type.
enum _Short_vector_base_type_id : unsigned int
{
_Uint_type = 0,
_Int_type = 1,
_Float_type = 2,
_Unorm_type = 3,
_Norm_type = 4,
_Double_type = 5,
_Invalid_type = 0xFFFFFFFF
};
typedef enum _Short_vector_base_type_id _Texture_base_type_id;
} // namespace Concurrency::details
typedef details::_Reference_counted_obj_ptr<details::_Accelerator_view_impl> _Accelerator_view_impl_ptr;
typedef details::_Reference_counted_obj_ptr<details::_Accelerator_impl> _Accelerator_impl_ptr;
typedef details::_Reference_counted_obj_ptr<details::_Buffer> _Buffer_ptr;
typedef details::_Reference_counted_obj_ptr<details::_Texture> _Texture_ptr;
typedef details::_Reference_counted_obj_ptr<details::_Sampler> _Sampler_ptr;
typedef details::_Reference_counted_obj_ptr<details::_Ubiquitous_buffer> _Ubiquitous_buffer_ptr;
typedef details::_Reference_counted_obj_ptr<details::_Event_impl> _Event_impl_ptr;
typedef details::_Reference_counted_obj_ptr<details::_View_shape> _View_shape_ptr;
namespace details
{
// The _Event class.
class _Event
{
friend class _Buffer;
friend class _Texture;
friend class accelerator_view;
friend class _D3D_accelerator_view_impl;
public:
/// <summary>
/// Constructor of the _Event.
/// </summary>
_AMPIMP _Event();
/// <summary>
/// Destructor of the _Event.
/// </summary>
_AMPIMP ~_Event();
/// <summary>
/// Copy constructor
/// </summary>
_AMPIMP _Event(const _Event & _Other);
/// <summary>
/// Assignment operator
/// </summary>
_AMPIMP _Event & operator=(const _Event & _Other);
/// <summary>
/// Poll whether the _Event has completed or not. Swallows any exceptions
/// </summary>
/// <returns>
/// true, if the _Event has completed, false otherwise
/// </returns>
_AMPIMP bool _Is_finished_nothrow();
/// <summary>
/// Poll whether the _Event has completed or not and throws any exceptions that occur
/// </summary>
/// <returns>
/// true, if the _Event has completed, false otherwise
/// </returns>
_AMPIMP bool _Is_finished();
/// <summary>
/// Wait until the _Event completes and throw any exceptions that occur.
/// </summary>
_AMPIMP void _Get();
/// <summary>
/// Tells if this is an empty event
/// </summary>
/// <returns>
/// true, if the _Event is empty
/// false, otherwise
/// </returns>
_AMPIMP bool _Is_empty() const;
/// <summary>
/// Creates an event which is an ordered collection of this and _Ev
/// </summary>
/// <returns>
/// The composite event
/// </returns>
_AMPIMP _Event _Add_event(_Event _Ev);
/// <summary>
/// Creates an event which is an ordered collection of this and a continuation task
/// </summary>
/// <returns>
/// The composite event
/// </returns>
_AMPIMP _Event _Add_continuation(const std::function<_Event __cdecl ()> &_Continuation_task);
/// <summary>
/// Return true if the other _Event is same as this _Event; false otherwise
/// </summary>
_AMPIMP bool operator==(const _Event &_Other) const;
/// <summary>
/// Return false if the other _Event is same as this _Event; true otherwise
/// </summary>
_AMPIMP bool operator!=(const _Event &_Other) const;
private:
// Private constructor
_Event(_In_ _Event_impl* _Impl);
_Event_impl_ptr _M_ptr_event_impl;
};
typedef _Buffer_descriptor *_View_key;
_Ret_ _Accelerator_view_impl* _Get_accelerator_view_impl_ptr(const accelerator_view& _Accl_view);
_Ret_ _Accelerator_impl* _Get_accelerator_impl_ptr(const accelerator& _Accl);
_Event _Get_access_async(const _View_key _Key, accelerator_view _Av, _Access_mode _Mode, _Buffer_ptr &_Buf_ptr);
unsigned int _Get_mipmap_levels(const _Texture *_Tex);
inline bool _Is_valid_access_mode(_Access_mode _Mode)
{
if ((_Mode != _Read_access) &&
(_Mode != _Write_access) &&
(_Mode != _Read_write_access))
{
return false;
}
return true;
}
// Caution: Do not change this structure definition.
// This struct is special and is processed by the FE to identify the buffers
// used in a parallel_for_each and to setup the _M_data_ptr with the appropriate
// buffer ptr value in the device code.
typedef struct _Buffer_descriptor
{
friend _Event _Get_access_async(const _View_key _Key, accelerator_view _Av, _Access_mode _Mode, _Buffer_ptr &_Buf_ptr);
// _M_data_ptr points to the raw data underlying the buffer for accessing on host
mutable void *_M_data_ptr;
private:
// _M_buffer_ptr points to a _Ubiquitous_buffer that holds the data in an 1D array.
// This is private to ensure that all assignments to this data member
// only happen through public functions which properly manage the
// ref count of the underlying buffer
_Ubiquitous_buffer *_M_buffer_ptr;
public:
// _M_curr_cpu_access_mode specifies the current access mode of the data on the
// cpu accelerator_view specified at the time of registration of this view
_Access_mode _M_curr_cpu_access_mode;
// _M_type_acess_mode specifies the access mode of the overlay type
// array_views set it to the appropriate access mode and for arrays it is
// always _Is_array_mode.
_Access_mode _M_type_access_mode;
public:
// Public functions
// Default constructor
_Buffer_descriptor() __GPU
: _M_data_ptr(NULL), _M_buffer_ptr(NULL),
_M_curr_cpu_access_mode(_No_access), _M_type_access_mode(_Is_array_mode)
{
}
_Buffer_descriptor(_In_ void *_Data_ptr, _In_ _Ubiquitous_buffer *_Buffer_ptr,
_Access_mode _Curr_cpu_access_mode, _Access_mode _Type_mode) __GPU
: _M_data_ptr(_Data_ptr), _M_buffer_ptr(NULL),
_M_curr_cpu_access_mode(_Curr_cpu_access_mode), _M_type_access_mode(_Type_mode)
{
_Set_buffer_ptr(_Buffer_ptr);
}
// Destructor
~_Buffer_descriptor() __GPU
{
_Set_buffer_ptr(NULL);
}
// Copy constructor
_Buffer_descriptor(const _Buffer_descriptor &_Other) __GPU
: _M_data_ptr(_Other._M_data_ptr), _M_buffer_ptr(NULL),
_M_curr_cpu_access_mode(_Other._M_curr_cpu_access_mode), _M_type_access_mode(_Other._M_type_access_mode)
{
_Set_buffer_ptr(_Other._M_buffer_ptr);
}
// Assignment operator
_Buffer_descriptor& operator=(const _Buffer_descriptor &_Other) __GPU
{
if (this != &_Other)
{
_M_data_ptr = _Other._M_data_ptr;
_M_curr_cpu_access_mode = _Other._M_curr_cpu_access_mode;
_M_type_access_mode = _Other._M_type_access_mode;
_Set_buffer_ptr(_Other._M_buffer_ptr);
}
return *this;
}
_Ret_ _Ubiquitous_buffer* _Get_buffer_ptr() const __CPU_ONLY
{
return _M_buffer_ptr;
}
void _Set_buffer_ptr(_In_opt_ _Ubiquitous_buffer *_Buffer_ptr) __CPU_ONLY
{
if (_M_buffer_ptr != _Buffer_ptr)
{
if (_M_buffer_ptr != NULL) {
reinterpret_cast<_Reference_counter*>(_M_buffer_ptr)->_Remove_reference();
}
_M_buffer_ptr = _Buffer_ptr;
if (_M_buffer_ptr != NULL) {
reinterpret_cast<_Reference_counter*>(_M_buffer_ptr)->_Add_reference();
}
}
}
#if !defined(_CXXAMP)
void _Set_buffer_ptr(_In_opt_ _Ubiquitous_buffer *) __GPU_ONLY
{
// No need to set the buffer ptr on the GPU
_M_buffer_ptr = NULL;
}
#endif // _CXXAMP
bool _Is_array() const
{
return (_M_type_access_mode == _Is_array_mode);
}
_Ret_ _View_key _Get_view_key()
{
return this;
}
const _View_key _Get_view_key() const
{
return ((const _View_key)(this));
}
_AMPIMP void _Get_CPU_access(_Access_mode _Requested_mode) const;
} _Buffer_descriptor;
// Caution: Do not change this structure definition.
// This struct is special and is processed by the FE to identify the textures
// used in a parallel_for_each and to setup the _M_data_ptr with the appropriate
// texture ptr value in the device code.
typedef struct _Texture_descriptor
{
// _M_data_ptr points to the raw data underlying the texture
mutable IUnknown *_M_data_ptr;
private:
// _M_texture_ptr points to a _Texture that holds the data
// This is private to ensure that all assignments to this data member
// only happen through public functions which properly manage the
// ref count of the underlying texture
_Texture *_M_texture_ptr;
// The index of the most detailed (largest in size) mipmap level for the texture (or texture view)
// This value is always zero for the texture and might be non-zero for the texture views
unsigned int _M_most_detailed_mipmap_level;
// Number of accessible mipmap levels for the texture (or texture view),
// e.g. if the texture has 3 mipmap levels ([0, 1, 2]),
// then read-only texture view with most detailed mipmap level equal to 1, can have 1 or 2 mipmap levels ([1] or [1, 2]).
// Further texture_views created on top of the texture view defined above can only narrow down the range of accessible mipmap levels.
unsigned int _M_view_mipmap_levels;
public:
// Public functions
// Default constructor
_Texture_descriptor() __GPU
: _M_data_ptr(NULL), _M_texture_ptr(NULL), _M_most_detailed_mipmap_level(0), _M_view_mipmap_levels(0)
{
// Enables move constructor
}
// Constructor for the texture
_Texture_descriptor(unsigned int _Most_detailed_mipmap_level, unsigned int _View_mipmap_levels) __GPU
: _M_data_ptr(NULL), _M_texture_ptr(NULL), _M_most_detailed_mipmap_level(_Most_detailed_mipmap_level), _M_view_mipmap_levels(_View_mipmap_levels)
{
}
// Constructor for the interop texture
_Texture_descriptor(_In_ _Texture * _Texture_ptr) __CPU_ONLY
: _M_data_ptr(NULL), _M_texture_ptr(NULL), _M_most_detailed_mipmap_level(0)
{
_Set_texture_ptr(_Texture_ptr);
// Adopt number of mipmap levels from underlying texture object
_M_view_mipmap_levels = _Get_mipmap_levels(_M_texture_ptr);
}
// Destructor
~_Texture_descriptor() __GPU
{
_Set_texture_ptr(NULL);
}
// Copy constructor
_Texture_descriptor(const _Texture_descriptor &_Other) __GPU
: _M_data_ptr(_Other._M_data_ptr), _M_texture_ptr(NULL),
_M_most_detailed_mipmap_level(_Other._M_most_detailed_mipmap_level), _M_view_mipmap_levels(_Other._M_view_mipmap_levels)
{
_Set_texture_ptr(_Other._M_texture_ptr);
}
// Copy constructor with ability to redefine mipmap information
_Texture_descriptor(const _Texture_descriptor &_Other, unsigned int _Most_detailed_mipmap_level, unsigned int _View_mipmap_levels) __GPU
: _M_data_ptr(_Other._M_data_ptr), _M_texture_ptr(NULL),
_M_most_detailed_mipmap_level(_Most_detailed_mipmap_level), _M_view_mipmap_levels(_View_mipmap_levels)
{
_Set_texture_ptr(_Other._M_texture_ptr);
}
// Assignment operator
_Texture_descriptor& operator=(const _Texture_descriptor &_Other) __GPU
{
if (this != &_Other)
{
_M_data_ptr = _Other._M_data_ptr;
_Set_texture_ptr(_Other._M_texture_ptr);
_M_most_detailed_mipmap_level = _Other._M_most_detailed_mipmap_level;
_M_view_mipmap_levels = _Other._M_view_mipmap_levels;
}
return *this;
}
// Move constructor
_Texture_descriptor(_Texture_descriptor &&_Other) __CPU_ONLY noexcept
{
*this = std::move(_Other);
}
bool operator==(const _Texture_descriptor &_Other) const __GPU
{
return _M_texture_ptr == _Other._M_texture_ptr
&& _M_data_ptr == _Other._M_data_ptr
&& _M_most_detailed_mipmap_level == _Other._M_most_detailed_mipmap_level
&& _M_view_mipmap_levels == _Other._M_view_mipmap_levels;
}
_Ret_ _Texture* _Get_texture_ptr() const __CPU_ONLY
{
_ASSERTE(_M_texture_ptr);
return _M_texture_ptr;
}
unsigned int _Get_most_detailed_mipmap_level() const __GPU
{
return _M_most_detailed_mipmap_level;
}
unsigned int _Get_view_mipmap_levels() const __GPU
{
return _M_view_mipmap_levels;
}
void _Set_view_mipmap_levels(unsigned int _View_mipmap_levels) __CPU_ONLY
{
_M_view_mipmap_levels = _View_mipmap_levels;
}
void _Set_texture_ptr(_In_opt_ _Texture *_Texture_ptr) __CPU_ONLY
{
if (_M_texture_ptr != _Texture_ptr)
{
if (_M_texture_ptr != NULL) {
reinterpret_cast<_Reference_counter*>(_M_texture_ptr)->_Remove_reference();
}
_M_texture_ptr = _Texture_ptr;
if (_M_texture_ptr != NULL) {
reinterpret_cast<_Reference_counter*>(_M_texture_ptr)->_Add_reference();
}
}
}
#if !defined(_CXXAMP)
void _Set_texture_ptr(_In_opt_ _Texture *) __GPU_ONLY
{
// No need to set the texture ptr on the GPU
_M_texture_ptr = NULL;
}
#endif // _CXXAMP
// This helper function is used to determine aliasing and copy violations
bool _Are_mipmap_levels_overlapping(const _Texture_descriptor *_Other) const __CPU_ONLY
{
_ASSERTE(_Other);
if (this->_Get_texture_ptr() != _Other->_Get_texture_ptr())
{
return false;
}
return !((_M_most_detailed_mipmap_level < _Other->_M_most_detailed_mipmap_level) ? ((_M_most_detailed_mipmap_level + _M_view_mipmap_levels - 1) < _Other->_M_most_detailed_mipmap_level)
: ((_Other->_M_most_detailed_mipmap_level + _Other->_M_view_mipmap_levels - 1) < _M_most_detailed_mipmap_level));
}
} _Texture_descriptor;
// Caution: Do not change this structure definition.
// This struct is special and is processed by the FE to identify the samplers
// used in a parallel_for_each.
typedef struct _Sampler_descriptor
{
// _M_data_ptr points to the sampler on accelerator
mutable void *_M_data_ptr;
private:
// _M_sampler_ptr points to a _Sampler that holds the underlying sampler
// representation. This is private to ensure that all assignments to this data member
// only happen through public functions which properly manage the
// ref count of the underlying _Sampler object.
_Sampler *_M_sampler_ptr;
public:
// Public functions
// Default constructor
_Sampler_descriptor() __GPU
: _M_data_ptr(NULL), _M_sampler_ptr(NULL)
{
}
_Sampler_descriptor(_In_ _Sampler * _Sampler_ptr) __GPU
: _M_data_ptr(NULL), _M_sampler_ptr(NULL)
{
_Set_sampler_ptr(_Sampler_ptr);
}
// Destructor
~_Sampler_descriptor() __GPU
{
_Set_sampler_ptr(NULL);
}
// Copy constructor
_Sampler_descriptor(const _Sampler_descriptor &_Other) __GPU
: _M_data_ptr(_Other._M_data_ptr), _M_sampler_ptr(NULL)
{
_Set_sampler_ptr(_Other._M_sampler_ptr);
}
// Assignment operator
_Sampler_descriptor& operator=(const _Sampler_descriptor &_Other) __GPU
{
if (this != &_Other)
{
_M_data_ptr = _Other._M_data_ptr;
_Set_sampler_ptr(_Other._M_sampler_ptr);
}
return *this;
}
// Move constructor
_Sampler_descriptor(_Sampler_descriptor &&_Other) __CPU_ONLY noexcept
{
*this = std::move(_Other);
}
bool operator==(const _Sampler_descriptor &_Other) const __GPU
{
return _M_sampler_ptr == _Other._M_sampler_ptr && _M_data_ptr == _Other._M_data_ptr;
}
_Ret_ _Sampler* _Get_sampler_ptr() const __CPU_ONLY
{
return _M_sampler_ptr;
}
void _Set_sampler_ptr(_In_opt_ _Sampler *_Sampler_ptr) __CPU_ONLY
{
if (_M_sampler_ptr != _Sampler_ptr)
{
if (_M_sampler_ptr != NULL) {
reinterpret_cast<_Reference_counter*>(_M_sampler_ptr)->_Remove_reference();
}
_M_sampler_ptr = _Sampler_ptr;
if (_M_sampler_ptr != NULL) {
reinterpret_cast<_Reference_counter*>(_M_sampler_ptr)->_Add_reference();
}
}
}
#if !defined(_CXXAMP)
void _Set_sampler_ptr(_In_opt_ _Sampler *) __GPU_ONLY
{
// No need to set the sampler ptr on the GPU
_M_sampler_ptr = NULL;
}
#endif // _CXXAMP
} _Sampler_descriptor;
} // namespace Concurrency::details
// Forward declaration
class accelerator;
namespace details
{
_AMPIMP size_t __cdecl _Get_num_devices();
_AMPIMP _Ret_ _Accelerator_impl_ptr * __cdecl _Get_devices();
_AMPIMP accelerator __cdecl _Select_default_accelerator();
_AMPIMP bool __cdecl _Set_default_accelerator(_Accelerator_impl_ptr _Accl);
_AMPIMP bool __cdecl _Is_D3D_accelerator_view(const accelerator_view& _Av);
_AMPIMP void __cdecl _Register_async_event(const _Event &_Ev, const std::shared_future<void> &_Shared_future);
_AMPIMP _Access_mode __cdecl _Get_recommended_buffer_host_access_mode(const accelerator_view &_Av);
}
/// <summary>
/// Queuing modes supported for accelerator views
/// </summary>
enum queuing_mode {
queuing_mode_immediate,
queuing_mode_automatic
};
namespace direct3d
{
/// <summary>
/// Get the D3D device interface underlying a accelerator_view.
/// </summary>
/// <param name="_Av">
/// The D3D accelerator_view for which the underlying D3D device interface is returned.
/// </param>
/// <returns>
/// The IUnknown interface pointer of the D3D device underlying the accelerator_view.
/// </returns>
_AMPIMP _Ret_ IUnknown * __cdecl get_device(const accelerator_view &_Av);
/// <summary>
/// Create a accelerator_view from a D3D device interface pointer.
/// </summary>
/// <param name="_D3D_device">
/// The D3D device interface pointer to create the accelerator_view from.
/// </param>
/// <param name="_Qmode">
/// The queuing_mode to be used for the newly created accelerator_view.
/// This parameter has a default value of queuing_mode_automatic.
/// </param>
/// <returns>
/// The accelerator_view created from the passed D3D device interface.
/// </returns>
_AMPIMP accelerator_view __cdecl create_accelerator_view(_In_ IUnknown *_D3D_device, queuing_mode _Qmode = queuing_mode_automatic);
/// <summary>
/// Create and return a new accelerator view on the specified accelerator.
/// </summary>
/// <param name="_Accelerator">
/// The accelerator on which the new accelerator_view is to be created.
/// </param>
/// <param name="_Disable_timeout">
/// A boolean parameter that specifies whether timeout should be disabled
/// for the newly created accelerator_view. This corresponds to the
/// D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT flag for Direct3D device creation
/// and is used to indicate if the operating system should allow workloads
/// that take more than 2 seconds to execute, without resetting the device
/// per the Windows timeout detection and recovery mechanism. Use of this flag
/// is recommended if you need to perform time consuming tasks on the accelerator_view.
/// </param>
/// <param name="_Qmode">
/// The queuing_mode to be used for the newly created accelerator_view.
/// This parameter has a default value of queuing_mode_automatic.
/// </param>
/// <returns>
/// The newly created accelerator_view.
/// </returns>
_AMPIMP accelerator_view __cdecl create_accelerator_view(accelerator& _Accelerator, bool _Disable_timeout, queuing_mode _Qmode = queuing_mode_automatic);
/// <summary>
/// Returns a boolean flag indicating if timeout is disabled
/// for the specified accelerator_view. This corresponds to the
/// D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT flag for Direct3D device creation.
/// </summary>
/// <param name="_Accelerator_view">
/// The accelerator_view for which the timeout disabled setting is to be queried.
/// </param>
/// <returns>
/// A boolean flag indicating if timeout is disabled for the specified accelerator_view.
/// </returns>
_AMPIMP bool __cdecl is_timeout_disabled(const accelerator_view& _Accelerator_view);
/// <summary>
/// Acquire a lock on an accelerator_view for the purpose of safely performing D3D operations on resources shared
/// with the accelerator_view. The accelerator_view and all C++ AMP resources associated with this accelerator_view
/// internally take this lock when performing operations and will block while another thread holds the D3D access lock.
///
/// This lock is non-recursive: It is undefined behavior to call this function from a thread that already holds the lock.
/// It is undefined behavior to perform operations on the accelerator_view or any data container associated with the
/// accelerator_view from the thread that holds the D3D access lock.
///
/// See also scoped_d3d_access_lock, a RAII-style class for a scope-based D3D access lock.
/// </summary>
/// <param name="_Av">
/// The accelerator_view to lock.
/// </param>
_AMPIMP void __cdecl d3d_access_lock(accelerator_view &_Av);
/// <summary>
/// Attempt to acquire the D3D access lock on an accelerator_view without blocking.
/// </summary>
/// <param name="_Av">
/// The accelerator_view to lock.
/// </param>
/// <returns>
/// true if the lock was acquired, or false if it is currently held by another thread.
/// </returns>
_AMPIMP bool __cdecl d3d_access_try_lock(accelerator_view &_Av);
/// <summary>
/// Release the D3D access lock on the given accelerator_view. If the calling thread does
/// not hold the lock on the accelerator_view the results are undefined.
/// </summary>
/// <param name="_Av">
/// The accelerator_view for which the lock is to be released.
/// </param>
_AMPIMP void __cdecl d3d_access_unlock(accelerator_view &_Av);
/// <summary>
/// Tag type to indicate the D3D access lock should be adopted rather than
/// acquired.
/// </summary>
struct adopt_d3d_access_lock_t {};
/// <summary>
/// RAII wrapper for a D3D access lock on an accelerator_view.
/// </summary>
class scoped_d3d_access_lock
{
public:
/// <summary>
/// Acquire a D3D access lock on the given accelerator_view. The lock is released
/// when this object goes out of scope. Construction will block until the lock
/// is acquired.
/// </summary>
/// <param name="_Av">
/// The accelerator_view to lock.
/// </param>
_AMPIMP explicit scoped_d3d_access_lock(accelerator_view &_Av);
/// <summary>
/// Construct a scoped_d3d_access_lock on an accelerator_view for which the lock
/// is already held (e.g. was acquired by d3d_access_try_lock). The D3D access
/// lock must already be held by the calling thread and not controlled by any other
/// scoped_d3d_access_lock.
/// </summary>
/// <param name="_Av">
/// The accelerator_view for the lock to adopt.
/// </param>
/// <param name="_T">
/// The adopt_d3d_access_lock object.
/// </param>
_AMPIMP explicit scoped_d3d_access_lock(accelerator_view &_Av, adopt_d3d_access_lock_t _T);
/// <summary>
/// Destructor for scoped_d3d_access_lock: unlock the accelerator_view.
/// </summary>
_AMPIMP ~scoped_d3d_access_lock();
/// <summary>
/// Move constructor for scoped_d3d_access_lock: Take ownership of
/// a lock from another scoped_d3d_access_lock.
/// </summary>
/// <param name="_Other">
/// The accelerator_view from which to move.
/// </param>
_AMPIMP scoped_d3d_access_lock(scoped_d3d_access_lock &&_Other) noexcept;
/// <summary>
/// Move assignment operator for scoped_d3d_access_lock: Take ownership
/// of a lock from another scoped_d3d_access_lock, releasing the previous
/// lock.
/// </summary>
/// <param name="_Other">
/// The accelerator_view from which to move.
/// </param>
/// <returns>
/// A reference to this scoped_accelerator_view_lock.