1/*
2 * Copyright © Microsoft Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#ifndef D3D12_UTIL_H
25#define D3D12_UTIL_H
26
27//------------------------------------------------------------------------------------------------
28template <typename T, typename U, typename V>
29inline void D3D12DecomposeSubresource( UINT Subresource, UINT MipLevels, UINT ArraySize, _Out_ T& MipSlice, _Out_ U& ArraySlice, _Out_ V& PlaneSlice ) noexcept
30{
31    MipSlice = static_cast<T>(Subresource % MipLevels);
32    ArraySlice = static_cast<U>((Subresource / MipLevels) % ArraySize);
33    PlaneSlice = static_cast<V>(Subresource / (MipLevels * ArraySize));
34}
35
36//------------------------------------------------------------------------------------------------
37constexpr UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize ) noexcept
38{
39    return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize;
40}
41
42//------------------------------------------------------------------------------------------------
43struct CD3DX12_RESOURCE_BARRIER : public D3D12_RESOURCE_BARRIER
44{
45    CD3DX12_RESOURCE_BARRIER() = default;
46    explicit CD3DX12_RESOURCE_BARRIER(const D3D12_RESOURCE_BARRIER &o) noexcept :
47        D3D12_RESOURCE_BARRIER(o)
48    {}
49    static inline CD3DX12_RESOURCE_BARRIER Transition(
50        _In_ ID3D12Resource* pResource,
51        D3D12_RESOURCE_STATES stateBefore,
52        D3D12_RESOURCE_STATES stateAfter,
53        UINT subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
54        D3D12_RESOURCE_BARRIER_FLAGS flags = D3D12_RESOURCE_BARRIER_FLAG_NONE) noexcept
55    {
56        CD3DX12_RESOURCE_BARRIER result = {};
57        D3D12_RESOURCE_BARRIER &barrier = result;
58        result.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
59        result.Flags = flags;
60        barrier.Transition.pResource = pResource;
61        barrier.Transition.StateBefore = stateBefore;
62        barrier.Transition.StateAfter = stateAfter;
63        barrier.Transition.Subresource = subresource;
64        return result;
65    }
66    static inline CD3DX12_RESOURCE_BARRIER Aliasing(
67        _In_ ID3D12Resource* pResourceBefore,
68        _In_ ID3D12Resource* pResourceAfter) noexcept
69    {
70        CD3DX12_RESOURCE_BARRIER result = {};
71        D3D12_RESOURCE_BARRIER &barrier = result;
72        result.Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;
73        barrier.Aliasing.pResourceBefore = pResourceBefore;
74        barrier.Aliasing.pResourceAfter = pResourceAfter;
75        return result;
76    }
77    static inline CD3DX12_RESOURCE_BARRIER UAV(
78        _In_ ID3D12Resource* pResource) noexcept
79    {
80        CD3DX12_RESOURCE_BARRIER result = {};
81        D3D12_RESOURCE_BARRIER &barrier = result;
82        result.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
83        barrier.UAV.pResource = pResource;
84        return result;
85    }
86};
87
88//------------------------------------------------------------------------------------------------
89struct CD3DX12_RESOURCE_DESC : public D3D12_RESOURCE_DESC
90{
91    CD3DX12_RESOURCE_DESC() = default;
92    explicit CD3DX12_RESOURCE_DESC( const D3D12_RESOURCE_DESC& o ) noexcept :
93        D3D12_RESOURCE_DESC( o )
94    {}
95    CD3DX12_RESOURCE_DESC(
96        D3D12_RESOURCE_DIMENSION dimension,
97        UINT64 alignment,
98        UINT64 width,
99        UINT height,
100        UINT16 depthOrArraySize,
101        UINT16 mipLevels,
102        DXGI_FORMAT format,
103        UINT sampleCount,
104        UINT sampleQuality,
105        D3D12_TEXTURE_LAYOUT layout,
106        D3D12_RESOURCE_FLAGS flags ) noexcept
107    {
108        Dimension = dimension;
109        Alignment = alignment;
110        Width = width;
111        Height = height;
112        DepthOrArraySize = depthOrArraySize;
113        MipLevels = mipLevels;
114        Format = format;
115        SampleDesc.Count = sampleCount;
116        SampleDesc.Quality = sampleQuality;
117        Layout = layout;
118        Flags = flags;
119    }
120    static inline CD3DX12_RESOURCE_DESC Buffer(
121        const D3D12_RESOURCE_ALLOCATION_INFO& resAllocInfo,
122        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE ) noexcept
123    {
124        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, resAllocInfo.Alignment, resAllocInfo.SizeInBytes,
125            1, 1, 1, DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );
126    }
127    static inline CD3DX12_RESOURCE_DESC Buffer(
128        UINT64 width,
129        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
130        UINT64 alignment = 0 ) noexcept
131    {
132        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_BUFFER, alignment, width, 1, 1, 1,
133            DXGI_FORMAT_UNKNOWN, 1, 0, D3D12_TEXTURE_LAYOUT_ROW_MAJOR, flags );
134    }
135    static inline CD3DX12_RESOURCE_DESC Tex1D(
136        DXGI_FORMAT format,
137        UINT64 width,
138        UINT16 arraySize = 1,
139        UINT16 mipLevels = 0,
140        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
141        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
142        UINT64 alignment = 0 ) noexcept
143    {
144        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE1D, alignment, width, 1, arraySize,
145            mipLevels, format, 1, 0, layout, flags );
146    }
147    static inline CD3DX12_RESOURCE_DESC Tex2D(
148        DXGI_FORMAT format,
149        UINT64 width,
150        UINT height,
151        UINT16 arraySize = 1,
152        UINT16 mipLevels = 0,
153        UINT sampleCount = 1,
154        UINT sampleQuality = 0,
155        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
156        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
157        UINT64 alignment = 0 ) noexcept
158    {
159        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE2D, alignment, width, height, arraySize,
160            mipLevels, format, sampleCount, sampleQuality, layout, flags );
161    }
162    static inline CD3DX12_RESOURCE_DESC Tex3D(
163        DXGI_FORMAT format,
164        UINT64 width,
165        UINT height,
166        UINT16 depth,
167        UINT16 mipLevels = 0,
168        D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE,
169        D3D12_TEXTURE_LAYOUT layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
170        UINT64 alignment = 0 ) noexcept
171    {
172        return CD3DX12_RESOURCE_DESC( D3D12_RESOURCE_DIMENSION_TEXTURE3D, alignment, width, height, depth,
173            mipLevels, format, 1, 0, layout, flags );
174    }
175    inline UINT16 Depth() const noexcept
176    { return (Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1u); }
177    inline UINT16 ArraySize() const noexcept
178    { return (Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? DepthOrArraySize : 1u); }
179    inline UINT CalcSubresource(UINT MipSlice, UINT ArraySlice, UINT PlaneSlice) noexcept
180    { return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, MipLevels, ArraySize()); }
181};
182inline bool operator==( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) noexcept
183{
184    return l.Dimension == r.Dimension &&
185        l.Alignment == r.Alignment &&
186        l.Width == r.Width &&
187        l.Height == r.Height &&
188        l.DepthOrArraySize == r.DepthOrArraySize &&
189        l.MipLevels == r.MipLevels &&
190        l.Format == r.Format &&
191        l.SampleDesc.Count == r.SampleDesc.Count &&
192        l.SampleDesc.Quality == r.SampleDesc.Quality &&
193        l.Layout == r.Layout &&
194        l.Flags == r.Flags;
195}
196inline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& r ) noexcept
197{ return !( l == r ); }
198
199
200//------------------------------------------------------------------------------------------------
201struct CD3DX12_HEAP_PROPERTIES : public D3D12_HEAP_PROPERTIES
202{
203    CD3DX12_HEAP_PROPERTIES() = default;
204    explicit CD3DX12_HEAP_PROPERTIES(const D3D12_HEAP_PROPERTIES &o) noexcept :
205        D3D12_HEAP_PROPERTIES(o)
206    {}
207    CD3DX12_HEAP_PROPERTIES(
208        D3D12_CPU_PAGE_PROPERTY cpuPageProperty,
209        D3D12_MEMORY_POOL memoryPoolPreference,
210        UINT creationNodeMask = 1,
211        UINT nodeMask = 1 ) noexcept
212    {
213        Type = D3D12_HEAP_TYPE_CUSTOM;
214        CPUPageProperty = cpuPageProperty;
215        MemoryPoolPreference = memoryPoolPreference;
216        CreationNodeMask = creationNodeMask;
217        VisibleNodeMask = nodeMask;
218    }
219    explicit CD3DX12_HEAP_PROPERTIES(
220        D3D12_HEAP_TYPE type,
221        UINT creationNodeMask = 1,
222        UINT nodeMask = 1 ) noexcept
223    {
224        Type = type;
225        CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
226        MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
227        CreationNodeMask = creationNodeMask;
228        VisibleNodeMask = nodeMask;
229    }
230    bool IsCPUAccessible() const noexcept
231    {
232        return Type == D3D12_HEAP_TYPE_UPLOAD || Type == D3D12_HEAP_TYPE_READBACK || (Type == D3D12_HEAP_TYPE_CUSTOM &&
233            (CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE || CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK));
234    }
235};
236inline bool operator==( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) noexcept
237{
238    return l.Type == r.Type && l.CPUPageProperty == r.CPUPageProperty &&
239        l.MemoryPoolPreference == r.MemoryPoolPreference &&
240        l.CreationNodeMask == r.CreationNodeMask &&
241        l.VisibleNodeMask == r.VisibleNodeMask;
242}
243inline bool operator!=( const D3D12_HEAP_PROPERTIES& l, const D3D12_HEAP_PROPERTIES& r ) noexcept
244{ return !( l == r ); }
245
246#endif