yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Gangzheng TongConvert gfx unit tests and examples to use slang-rhi (#7577)43d0c2100

master
17.1 KiB643 linesraw
1/*
2This is an implementation of C++20's std::span
3http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
4*/
5
6//          Copyright Tristan Brindle 2018.
7// Distributed under the Boost Software License, Version 1.0.
8//    (See accompanying file ../../LICENSE_1_0.txt or copy at
9//          https://www.boost.org/LICENSE_1_0.txt)
10
11#pragma once
12
13#include <array>
14#include <cstddef>
15#include <cstdint>
16#include <type_traits>
17
18#ifndef TCB_SPAN_NO_EXCEPTIONS
19// Attempt to discover whether we're being compiled with exception support
20#if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
21#define TCB_SPAN_NO_EXCEPTIONS
22#endif
23#endif
24
25#ifndef TCB_SPAN_NO_EXCEPTIONS
26#include <cstdio>
27#include <stdexcept>
28#endif
29
30// Various feature test macros
31
32#ifndef TCB_SPAN_NAMESPACE_NAME
33#define TCB_SPAN_NAMESPACE_NAME rhi
34#endif
35
36#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
37#define TCB_SPAN_HAVE_CPP17
38#endif
39
40#if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
41#define TCB_SPAN_HAVE_CPP14
42#endif
43
44namespace TCB_SPAN_NAMESPACE_NAME
45{
46
47// Establish default contract checking behavior
48#if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) && \
49    !defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) && !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
50#if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14)
51#define TCB_SPAN_NO_CONTRACT_CHECKING
52#else
53#define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION
54#endif
55#endif
56
57#if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION)
58struct contract_violation_error : std::logic_error
59{
60    explicit contract_violation_error(const char* msg)
61        : std::logic_error(msg)
62    {
63    }
64};
65
66inline void contract_violation(const char* msg)
67{
68    throw contract_violation_error(msg);
69}
70
71#elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION)
72[[noreturn]] inline void contract_violation(const char* /*unused*/)
73{
74    std::terminate();
75}
76#endif
77
78#if !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
79#define TCB_SPAN_STRINGIFY(cond) #cond
80#define TCB_SPAN_EXPECT(cond) \
81    cond ? (void)0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond))
82#else
83#define TCB_SPAN_EXPECT(cond)
84#endif
85
86#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables)
87#define TCB_SPAN_INLINE_VAR inline
88#else
89#define TCB_SPAN_INLINE_VAR
90#endif
91
92#if defined(TCB_SPAN_HAVE_CPP14) || (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
93#define TCB_SPAN_HAVE_CPP14_CONSTEXPR
94#endif
95
96#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR)
97#define TCB_SPAN_CONSTEXPR14 constexpr
98#else
99#define TCB_SPAN_CONSTEXPR14
100#endif
101
102#if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) && (!defined(_MSC_VER) || _MSC_VER > 1900)
103#define TCB_SPAN_CONSTEXPR_ASSIGN constexpr
104#else
105#define TCB_SPAN_CONSTEXPR_ASSIGN
106#endif
107
108#if defined(TCB_SPAN_NO_CONTRACT_CHECKING)
109#define TCB_SPAN_CONSTEXPR11 constexpr
110#else
111#define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14
112#endif
113
114#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides)
115#define TCB_SPAN_HAVE_DEDUCTION_GUIDES
116#endif
117
118#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte)
119#define TCB_SPAN_HAVE_STD_BYTE
120#endif
121
122#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr)
123#define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC
124#endif
125
126#if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC)
127#define TCB_SPAN_ARRAY_CONSTEXPR constexpr
128#else
129#define TCB_SPAN_ARRAY_CONSTEXPR
130#endif
131
132#ifdef TCB_SPAN_HAVE_STD_BYTE
133using slang_byte = std::byte;
134#else
135using slang_byte = unsigned char;
136#endif
137
138#if defined(TCB_SPAN_HAVE_CPP17)
139#define TCB_SPAN_NODISCARD [[nodiscard]]
140#else
141#define TCB_SPAN_NODISCARD
142#endif
143
144TCB_SPAN_INLINE_VAR constexpr std::size_t dynamic_extent = SIZE_MAX;
145
146template<typename ElementType, std::size_t Extent = dynamic_extent>
147class span;
148
149namespace detail
150{
151
152template<typename E, std::size_t S>
153struct span_storage
154{
155    constexpr span_storage() noexcept = default;
156
157    constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept
158        : ptr(p_ptr)
159    {
160    }
161
162    E* ptr = nullptr;
163    static constexpr std::size_t size = S;
164};
165
166template<typename E>
167struct span_storage<E, dynamic_extent>
168{
169    constexpr span_storage() noexcept = default;
170
171    constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept
172        : ptr(p_ptr), size(p_size)
173    {
174    }
175
176    E* ptr = nullptr;
177    std::size_t size = 0;
178};
179
180// Reimplementation of C++17 std::size() and std::data()
181#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_nonmember_container_access)
182using std::data;
183using std::size;
184#else
185template<class C>
186constexpr auto size(const C& c) -> decltype(c.size())
187{
188    return c.size();
189}
190
191template<class T, std::size_t N>
192constexpr std::size_t size(const T (&)[N]) noexcept
193{
194    return N;
195}
196
197template<class C>
198constexpr auto data(C& c) -> decltype(c.data())
199{
200    return c.data();
201}
202
203template<class C>
204constexpr auto data(const C& c) -> decltype(c.data())
205{
206    return c.data();
207}
208
209template<class T, std::size_t N>
210constexpr T* data(T (&array)[N]) noexcept
211{
212    return array;
213}
214
215template<class E>
216constexpr const E* data(std::initializer_list<E> il) noexcept
217{
218    return il.begin();
219}
220#endif // TCB_SPAN_HAVE_CPP17
221
222#if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t)
223using std::void_t;
224#else
225template<typename...>
226using void_t = void;
227#endif
228
229template<typename T>
230using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
231
232template<typename>
233struct is_span : std::false_type
234{
235};
236
237template<typename T, std::size_t S>
238struct is_span<span<T, S>> : std::true_type
239{
240};
241
242template<typename>
243struct is_std_array : std::false_type
244{
245};
246
247template<typename T, std::size_t N>
248struct is_std_array<std::array<T, N>> : std::true_type
249{
250};
251
252template<typename, typename = void>
253struct has_size_and_data : std::false_type
254{
255};
256
257template<typename T>
258struct has_size_and_data<
259    T,
260    void_t<decltype(detail::size(std::declval<T>())), decltype(detail::data(std::declval<T>()))>>
261    : std::true_type
262{
263};
264
265template<typename C, typename U = uncvref_t<C>>
266struct is_container
267{
268    static constexpr bool value = !is_span<U>::value && !is_std_array<U>::value &&
269                                  !std::is_array<U>::value && has_size_and_data<C>::value;
270};
271
272template<typename T>
273using remove_pointer_t = typename std::remove_pointer<T>::type;
274
275template<typename, typename, typename = void>
276struct is_container_element_type_compatible : std::false_type
277{
278};
279
280template<typename T, typename E>
281struct is_container_element_type_compatible<
282    T,
283    E,
284    typename std::enable_if<
285        !std::is_same<
286            typename std::remove_cv<decltype(detail::data(std::declval<T>()))>::type,
287            void>::value &&
288        std::is_convertible<
289            remove_pointer_t<decltype(detail::data(std::declval<T>()))> (*)[],
290            E (*)[]>::value>::type> : std::true_type
291{
292};
293
294template<typename, typename = size_t>
295struct is_complete : std::false_type
296{
297};
298
299template<typename T>
300struct is_complete<T, decltype(sizeof(T))> : std::true_type
301{
302};
303
304} // namespace detail
305
306template<typename ElementType, std::size_t Extent>
307class span
308{
309    static_assert(
310        std::is_object<ElementType>::value,
311        "A span's ElementType must be an object type (not a "
312        "reference type or void)");
313    static_assert(
314        detail::is_complete<ElementType>::value,
315        "A span's ElementType must be a complete type (not a forward "
316        "declaration)");
317    static_assert(
318        !std::is_abstract<ElementType>::value,
319        "A span's ElementType cannot be an abstract class type");
320
321    using storage_type = detail::span_storage<ElementType, Extent>;
322
323public:
324    // constants and types
325    using element_type = ElementType;
326    using value_type = typename std::remove_cv<ElementType>::type;
327    using size_type = std::size_t;
328    using difference_type = std::ptrdiff_t;
329    using pointer = element_type*;
330    using const_pointer = const element_type*;
331    using reference = element_type&;
332    using const_reference = const element_type&;
333    using iterator = pointer;
334    using reverse_iterator = std::reverse_iterator<iterator>;
335
336    static constexpr size_type extent = Extent;
337
338    // [span.cons], span constructors, copy, assignment, and destructor
339    template<
340        std::size_t E = Extent,
341        typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
342    constexpr span() noexcept
343    {
344    }
345
346    TCB_SPAN_CONSTEXPR11 span(pointer ptr, size_type count)
347        : storage_(ptr, count)
348    {
349        TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent);
350    }
351
352    TCB_SPAN_CONSTEXPR11 span(pointer first_elem, pointer last_elem)
353        : storage_(first_elem, last_elem - first_elem)
354    {
355        TCB_SPAN_EXPECT(
356            extent == dynamic_extent ||
357            last_elem - first_elem == static_cast<std::ptrdiff_t>(extent));
358    }
359
360    template<
361        std::size_t N,
362        std::size_t E = Extent,
363        typename std::enable_if<
364            (E == dynamic_extent || N == E) &&
365                detail::is_container_element_type_compatible<element_type (&)[N], ElementType>::
366                    value,
367            int>::type = 0>
368    constexpr span(element_type (&arr)[N]) noexcept
369        : storage_(arr, N)
370    {
371    }
372
373    template<
374        typename T,
375        std::size_t N,
376        std::size_t E = Extent,
377        typename std::enable_if<
378            (E == dynamic_extent || N == E) &&
379                detail::is_container_element_type_compatible<std::array<T, N>&, ElementType>::value,
380            int>::type = 0>
381    TCB_SPAN_ARRAY_CONSTEXPR span(std::array<T, N>& arr) noexcept
382        : storage_(arr.data(), N)
383    {
384    }
385
386    template<
387        typename T,
388        std::size_t N,
389        std::size_t E = Extent,
390        typename std::enable_if<
391            (E == dynamic_extent || N == E) &&
392                detail::is_container_element_type_compatible<const std::array<T, N>&, ElementType>::
393                    value,
394            int>::type = 0>
395    TCB_SPAN_ARRAY_CONSTEXPR span(const std::array<T, N>& arr) noexcept
396        : storage_(arr.data(), N)
397    {
398    }
399
400    template<
401        typename Container,
402        std::size_t E = Extent,
403        typename std::enable_if<
404            E == dynamic_extent && detail::is_container<Container>::value &&
405                detail::is_container_element_type_compatible<Container&, ElementType>::value,
406            int>::type = 0>
407    constexpr span(Container& cont)
408        : storage_(detail::data(cont), detail::size(cont))
409    {
410    }
411
412    template<
413        typename Container,
414        std::size_t E = Extent,
415        typename std::enable_if<
416            E == dynamic_extent && detail::is_container<Container>::value &&
417                detail::is_container_element_type_compatible<const Container&, ElementType>::value,
418            int>::type = 0>
419    constexpr span(const Container& cont)
420        : storage_(detail::data(cont), detail::size(cont))
421    {
422    }
423
424    constexpr span(const span& other) noexcept = default;
425
426    template<
427        typename OtherElementType,
428        std::size_t OtherExtent,
429        typename std::enable_if<
430            (Extent == dynamic_extent || OtherExtent == dynamic_extent || Extent == OtherExtent) &&
431                std::is_convertible<OtherElementType (*)[], ElementType (*)[]>::value,
432            int>::type = 0>
433    constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
434        : storage_(other.data(), other.size())
435    {
436    }
437
438    ~span() noexcept = default;
439
440    TCB_SPAN_CONSTEXPR_ASSIGN span& operator=(const span& other) noexcept = default;
441
442    // [span.sub], span subviews
443    template<std::size_t Count>
444    TCB_SPAN_CONSTEXPR11 span<element_type, Count> first() const
445    {
446        TCB_SPAN_EXPECT(Count <= size());
447        return {data(), Count};
448    }
449
450    template<std::size_t Count>
451    TCB_SPAN_CONSTEXPR11 span<element_type, Count> last() const
452    {
453        TCB_SPAN_EXPECT(Count <= size());
454        return {data() + (size() - Count), Count};
455    }
456
457    template<std::size_t Offset, std::size_t Count = dynamic_extent>
458    using subspan_return_t = span<
459        ElementType,
460        Count != dynamic_extent ? Count
461                                : (Extent != dynamic_extent ? Extent - Offset : dynamic_extent)>;
462
463    template<std::size_t Offset, std::size_t Count = dynamic_extent>
464    TCB_SPAN_CONSTEXPR11 subspan_return_t<Offset, Count> subspan() const
465    {
466        TCB_SPAN_EXPECT(Offset <= size() && (Count == dynamic_extent || Offset + Count <= size()));
467        return {data() + Offset, Count != dynamic_extent ? Count : size() - Offset};
468    }
469
470    TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent> first(size_type count) const
471    {
472        TCB_SPAN_EXPECT(count <= size());
473        return {data(), count};
474    }
475
476    TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent> last(size_type count) const
477    {
478        TCB_SPAN_EXPECT(count <= size());
479        return {data() + (size() - count), count};
480    }
481
482    TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent> subspan(
483        size_type offset,
484        size_type count = dynamic_extent) const
485    {
486        TCB_SPAN_EXPECT(offset <= size() && (count == dynamic_extent || offset + count <= size()));
487        return {data() + offset, count == dynamic_extent ? size() - offset : count};
488    }
489
490    // [span.obs], span observers
491    constexpr size_type size() const noexcept { return storage_.size; }
492
493    constexpr size_type size_bytes() const noexcept { return size() * sizeof(element_type); }
494
495    TCB_SPAN_NODISCARD constexpr bool empty() const noexcept { return size() == 0; }
496
497    // [span.elem], span element access
498    TCB_SPAN_CONSTEXPR11 reference operator[](size_type idx) const
499    {
500        TCB_SPAN_EXPECT(idx < size());
501        return *(data() + idx);
502    }
503
504    TCB_SPAN_CONSTEXPR11 reference front() const
505    {
506        TCB_SPAN_EXPECT(!empty());
507        return *data();
508    }
509
510    TCB_SPAN_CONSTEXPR11 reference back() const
511    {
512        TCB_SPAN_EXPECT(!empty());
513        return *(data() + (size() - 1));
514    }
515
516    constexpr pointer data() const noexcept { return storage_.ptr; }
517
518    // [span.iterators], span iterator support
519    constexpr iterator begin() const noexcept { return data(); }
520
521    constexpr iterator end() const noexcept { return data() + size(); }
522
523    TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept
524    {
525        return reverse_iterator(end());
526    }
527
528    TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept
529    {
530        return reverse_iterator(begin());
531    }
532
533private:
534    storage_type storage_{};
535};
536
537#ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES
538
539/* Deduction Guides */
540template<class T, size_t N>
541span(T (&)[N]) -> span<T, N>;
542
543template<class T, size_t N>
544span(std::array<T, N>&) -> span<T, N>;
545
546template<class T, size_t N>
547span(const std::array<T, N>&) -> span<const T, N>;
548
549template<class Container>
550span(Container&) -> span<
551    typename std::remove_reference<decltype(*detail::data(std::declval<Container&>()))>::type>;
552
553template<class Container>
554span(const Container&) -> span<const typename Container::value_type>;
555
556#endif // TCB_HAVE_DEDUCTION_GUIDES
557
558template<typename ElementType, std::size_t Extent>
559constexpr span<ElementType, Extent> make_span(span<ElementType, Extent> s) noexcept
560{
561    return s;
562}
563
564template<typename T, std::size_t N>
565constexpr span<T, N> make_span(T (&arr)[N]) noexcept
566{
567    return {arr};
568}
569
570template<typename T, std::size_t N>
571TCB_SPAN_ARRAY_CONSTEXPR span<T, N> make_span(std::array<T, N>& arr) noexcept
572{
573    return {arr};
574}
575
576template<typename T, std::size_t N>
577TCB_SPAN_ARRAY_CONSTEXPR span<const T, N> make_span(const std::array<T, N>& arr) noexcept
578{
579    return {arr};
580}
581
582template<typename Container>
583constexpr span<
584    typename std::remove_reference<decltype(*detail::data(std::declval<Container&>()))>::type>
585make_span(Container& cont)
586{
587    return {cont};
588}
589
590template<typename Container>
591constexpr span<const typename Container::value_type> make_span(const Container& cont)
592{
593    return {cont};
594}
595
596template<typename ElementType, std::size_t Extent>
597span<const slang_byte, ((Extent == dynamic_extent) ? dynamic_extent : sizeof(ElementType) * Extent)>
598as_bytes(span<ElementType, Extent> s) noexcept
599{
600    return {reinterpret_cast<const slang_byte*>(s.data()), s.size_bytes()};
601}
602
603template<
604    class ElementType,
605    size_t Extent,
606    typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0>
607span<slang_byte, ((Extent == dynamic_extent) ? dynamic_extent : sizeof(ElementType) * Extent)>
608as_writable_bytes(span<ElementType, Extent> s) noexcept
609{
610    return {reinterpret_cast<slang_byte*>(s.data()), s.size_bytes()};
611}
612
613template<std::size_t N, typename E, std::size_t S>
614constexpr auto get(span<E, S> s) -> decltype(s[N])
615{
616    return s[N];
617}
618
619} // namespace TCB_SPAN_NAMESPACE_NAME
620
621namespace std
622{
623
624template<typename ElementType, size_t Extent>
625class tuple_size<TCB_SPAN_NAMESPACE_NAME::span<ElementType, Extent>>
626    : public integral_constant<size_t, Extent>
627{
628};
629
630template<typename ElementType>
631class tuple_size<
632    TCB_SPAN_NAMESPACE_NAME::span<ElementType, TCB_SPAN_NAMESPACE_NAME::dynamic_extent>>; // not
633                                                                                          // defined
634
635template<size_t I, typename ElementType, size_t Extent>
636class tuple_element<I, TCB_SPAN_NAMESPACE_NAME::span<ElementType, Extent>>
637{
638public:
639    static_assert(Extent != TCB_SPAN_NAMESPACE_NAME::dynamic_extent && I < Extent, "");
640    using type = ElementType;
641};
642
643} // end namespace std