]> git.cworth.org Git - apitrace/blob - helpers/d3d10size.hpp
Merge branch 'master' into dxva
[apitrace] / helpers / d3d10size.hpp
1 /**************************************************************************
2  *
3  * Copyright 2012 Jose Fonseca
4  * All Rights Reserved.
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sub license,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  * 
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  * 
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
20  * AUTHORS,
21  * AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  *
26  **************************************************************************/
27
28
29 /*
30  * Auxiliary functions to compute the size of array/blob arguments.
31  */
32
33 #ifndef _D3D10SIZE_HPP_
34 #define _D3D10SIZE_HPP_
35
36
37 /* We purposedly don't include any D3D header, so that this header can be used
38  * with all D3D versions. */
39
40 #include <assert.h>
41
42 #include <algorithm>
43
44
45 static size_t
46 _calcDataSize(DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT Depth = 1, UINT DepthPitch = 0) {
47     if (Width == 0 || Height == 0 || Depth == 0) {
48         return 0;
49     }
50
51     size_t BlockSize = 0;
52     UINT BlockWidth = 1;
53     UINT BlockHeight = 1;
54     switch (Format) {
55     case DXGI_FORMAT_UNKNOWN:
56         return 0;
57     case DXGI_FORMAT_R32G32B32A32_TYPELESS:
58     case DXGI_FORMAT_R32G32B32A32_FLOAT:
59     case DXGI_FORMAT_R32G32B32A32_UINT:
60     case DXGI_FORMAT_R32G32B32A32_SINT:
61         BlockSize = 128;
62         break;
63     case DXGI_FORMAT_R32G32B32_TYPELESS:
64     case DXGI_FORMAT_R32G32B32_FLOAT:
65     case DXGI_FORMAT_R32G32B32_UINT:
66     case DXGI_FORMAT_R32G32B32_SINT:
67         BlockSize = 96;
68         break;
69     case DXGI_FORMAT_R16G16B16A16_TYPELESS:
70     case DXGI_FORMAT_R16G16B16A16_FLOAT:
71     case DXGI_FORMAT_R16G16B16A16_UNORM:
72     case DXGI_FORMAT_R16G16B16A16_UINT:
73     case DXGI_FORMAT_R16G16B16A16_SNORM:
74     case DXGI_FORMAT_R16G16B16A16_SINT:
75     case DXGI_FORMAT_R32G32_TYPELESS:
76     case DXGI_FORMAT_R32G32_FLOAT:
77     case DXGI_FORMAT_R32G32_UINT:
78     case DXGI_FORMAT_R32G32_SINT:
79     case DXGI_FORMAT_R32G8X24_TYPELESS:
80     case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
81     case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
82     case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT:
83         BlockSize = 64;
84         break;
85     case DXGI_FORMAT_R10G10B10A2_TYPELESS:
86     case DXGI_FORMAT_R10G10B10A2_UNORM:
87     case DXGI_FORMAT_R10G10B10A2_UINT:
88     case DXGI_FORMAT_R11G11B10_FLOAT:
89     case DXGI_FORMAT_R8G8B8A8_TYPELESS:
90     case DXGI_FORMAT_R8G8B8A8_UNORM:
91     case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
92     case DXGI_FORMAT_R8G8B8A8_UINT:
93     case DXGI_FORMAT_R8G8B8A8_SNORM:
94     case DXGI_FORMAT_R8G8B8A8_SINT:
95     case DXGI_FORMAT_R16G16_TYPELESS:
96     case DXGI_FORMAT_R16G16_FLOAT:
97     case DXGI_FORMAT_R16G16_UNORM:
98     case DXGI_FORMAT_R16G16_UINT:
99     case DXGI_FORMAT_R16G16_SNORM:
100     case DXGI_FORMAT_R16G16_SINT:
101     case DXGI_FORMAT_R32_TYPELESS:
102     case DXGI_FORMAT_D32_FLOAT:
103     case DXGI_FORMAT_R32_FLOAT:
104     case DXGI_FORMAT_R32_UINT:
105     case DXGI_FORMAT_R32_SINT:
106     case DXGI_FORMAT_R24G8_TYPELESS:
107     case DXGI_FORMAT_D24_UNORM_S8_UINT:
108     case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
109     case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
110     case DXGI_FORMAT_R9G9B9E5_SHAREDEXP:
111     case DXGI_FORMAT_B8G8R8A8_UNORM:
112     case DXGI_FORMAT_B8G8R8X8_UNORM:
113     case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM:
114     case DXGI_FORMAT_B8G8R8A8_TYPELESS:
115     case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
116     case DXGI_FORMAT_B8G8R8X8_TYPELESS:
117     case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
118         BlockSize = 32;
119         break;
120     case DXGI_FORMAT_R8G8_TYPELESS:
121     case DXGI_FORMAT_R8G8_UNORM:
122     case DXGI_FORMAT_R8G8_UINT:
123     case DXGI_FORMAT_R8G8_SNORM:
124     case DXGI_FORMAT_R8G8_SINT:
125     case DXGI_FORMAT_R16_TYPELESS:
126     case DXGI_FORMAT_R16_FLOAT:
127     case DXGI_FORMAT_D16_UNORM:
128     case DXGI_FORMAT_R16_UNORM:
129     case DXGI_FORMAT_R16_UINT:
130     case DXGI_FORMAT_R16_SNORM:
131     case DXGI_FORMAT_R16_SINT:
132     case DXGI_FORMAT_B5G6R5_UNORM:
133     case DXGI_FORMAT_B5G5R5A1_UNORM:
134         BlockSize = 16;
135         break;
136     case DXGI_FORMAT_R8_TYPELESS:
137     case DXGI_FORMAT_R8_UNORM:
138     case DXGI_FORMAT_R8_UINT:
139     case DXGI_FORMAT_R8_SNORM:
140     case DXGI_FORMAT_R8_SINT:
141     case DXGI_FORMAT_A8_UNORM:
142         BlockSize = 8;
143         break;
144     case DXGI_FORMAT_R1_UNORM:
145         BlockSize = 1;
146         break;
147     case DXGI_FORMAT_R8G8_B8G8_UNORM:
148     case DXGI_FORMAT_G8R8_G8B8_UNORM:
149         BlockSize = 32;
150         BlockWidth = 2;
151         break;
152     case DXGI_FORMAT_BC1_TYPELESS:
153     case DXGI_FORMAT_BC1_UNORM:
154     case DXGI_FORMAT_BC1_UNORM_SRGB:
155     case DXGI_FORMAT_BC4_TYPELESS:
156     case DXGI_FORMAT_BC4_UNORM:
157     case DXGI_FORMAT_BC4_SNORM:
158         BlockSize = 64;
159         BlockWidth = 4;
160         BlockHeight = 4;
161         break;
162     case DXGI_FORMAT_BC2_TYPELESS:
163     case DXGI_FORMAT_BC2_UNORM:
164     case DXGI_FORMAT_BC2_UNORM_SRGB:
165     case DXGI_FORMAT_BC3_TYPELESS:
166     case DXGI_FORMAT_BC3_UNORM:
167     case DXGI_FORMAT_BC3_UNORM_SRGB:
168     case DXGI_FORMAT_BC5_TYPELESS:
169     case DXGI_FORMAT_BC5_UNORM:
170     case DXGI_FORMAT_BC5_SNORM:
171     case DXGI_FORMAT_BC6H_TYPELESS:
172     case DXGI_FORMAT_BC6H_UF16:
173     case DXGI_FORMAT_BC6H_SF16:
174     case DXGI_FORMAT_BC7_TYPELESS:
175     case DXGI_FORMAT_BC7_UNORM:
176     case DXGI_FORMAT_BC7_UNORM_SRGB:
177         BlockSize = 128;
178         BlockWidth = 4;
179         BlockHeight = 4;
180         break;
181     default:
182         os::log("apitrace: warning: %s: unknown format 0x%04X\n", __FUNCTION__, Format);
183         return 0;
184     }
185
186     Width  = (Width  + BlockWidth - 1) / BlockWidth;
187     Height = (Height + BlockHeight - 1) / BlockHeight;
188
189     size_t size = (Width * BlockSize + 7)/ 8;
190
191     if (Height > 1) {
192         size += (Height - 1) * RowPitch;
193     }
194
195     if (Depth > 1) {
196         size += (Depth - 1) * DepthPitch;
197     }
198
199     return size;
200 }
201
202 static size_t
203 _calcMipDataSize(UINT MipLevel, DXGI_FORMAT Format, UINT Width, UINT Height, UINT RowPitch, UINT Depth = 1, UINT DepthPitch = 0) {
204     if (Width == 0 || Height == 0 || Depth == 0) {
205         return 0;
206     }
207
208     Width  = std::max(Width  >> MipLevel, UINT(1));
209     Height = std::max(Height >> MipLevel, UINT(1));
210     Depth  = std::max(Depth  >> MipLevel, UINT(1));
211
212     return _calcDataSize(Format, Width, Height, RowPitch, Depth, DepthPitch);
213 }
214
215
216 inline UINT
217 _getNumMipLevels(UINT Width, UINT Height = 1, UINT Depth = 1) {
218     UINT MipLevels = 0;
219     do {
220         ++MipLevels;
221         Width  >>= 1;
222         Height >>= 1;
223         Depth  >>= 1;
224     } while (Width || Height || Depth);
225     return MipLevels;
226 }
227
228 inline UINT
229 _getNumMipLevels(const D3D10_BUFFER_DESC *pDesc) {
230     return 1;
231 }
232
233 inline UINT
234 _getNumMipLevels(const D3D10_TEXTURE1D_DESC *pDesc) {
235     return pDesc->MipLevels != 0 ? pDesc->MipLevels : _getNumMipLevels(pDesc->Width);
236 }
237
238 inline UINT
239 _getNumMipLevels(const D3D10_TEXTURE2D_DESC *pDesc) {
240     return pDesc->MipLevels != 0 ? pDesc->MipLevels : _getNumMipLevels(pDesc->Width, pDesc->Height);
241 }
242
243 inline UINT
244 _getNumMipLevels(const D3D10_TEXTURE3D_DESC *pDesc) {
245     return pDesc->MipLevels != 0 ? pDesc->MipLevels : _getNumMipLevels(pDesc->Width, pDesc->Height, pDesc->Depth);
246 }
247
248 inline UINT
249 _getNumSubResources(const D3D10_BUFFER_DESC *pDesc) {
250     return 1;
251 }
252
253 inline UINT
254 _getNumSubResources(const D3D10_TEXTURE1D_DESC *pDesc) {
255     return _getNumMipLevels(pDesc) * pDesc->ArraySize;
256 }
257
258 inline UINT
259 _getNumSubResources(const D3D10_TEXTURE2D_DESC *pDesc) {
260     return _getNumMipLevels(pDesc) * pDesc->ArraySize;
261 }
262
263 inline UINT
264 _getNumSubResources(const D3D10_TEXTURE3D_DESC *pDesc) {
265     return _getNumMipLevels(pDesc);
266 }
267
268 static inline size_t
269 _calcSubresourceSize(const D3D10_BUFFER_DESC *pDesc, UINT Subresource, UINT RowPitch = 0, UINT SlicePitch = 0) {
270     return pDesc->ByteWidth;
271 }
272
273 static inline size_t
274 _calcSubresourceSize(const D3D10_TEXTURE1D_DESC *pDesc, UINT Subresource, UINT RowPitch = 0, UINT SlicePitch = 0) {
275     UINT MipLevel = Subresource % _getNumMipLevels(pDesc);
276     return _calcMipDataSize(MipLevel, pDesc->Format, pDesc->Width, 1, RowPitch, 1, SlicePitch);
277 }
278
279 static inline size_t
280 _calcSubresourceSize(const D3D10_TEXTURE2D_DESC *pDesc, UINT Subresource, UINT RowPitch, UINT SlicePitch = 0) {
281     UINT MipLevel = Subresource % _getNumMipLevels(pDesc);
282     return _calcMipDataSize(MipLevel, pDesc->Format, pDesc->Width, pDesc->Height, RowPitch, 1, SlicePitch);
283 }
284
285 static inline size_t
286 _calcSubresourceSize(const D3D10_TEXTURE3D_DESC *pDesc, UINT Subresource, UINT RowPitch, UINT SlicePitch) {
287     UINT MipLevel = Subresource;
288     return _calcMipDataSize(MipLevel, pDesc->Format, pDesc->Width, pDesc->Height, RowPitch, pDesc->Depth, SlicePitch);
289 }
290
291 static inline void
292 _getMapInfo(ID3D10Buffer *pResource, D3D10_MAP MapType, UINT MapFlags, void * * ppData,
293             void * & pMappedData, size_t & MappedSize) {
294     pMappedData = 0;
295     MappedSize = 0;
296
297     if (MapType == D3D10_MAP_READ) {
298         return;
299     }
300
301     D3D10_BUFFER_DESC Desc;
302     pResource->GetDesc(&Desc);
303
304     pMappedData = *ppData;
305     MappedSize = Desc.ByteWidth;
306 }
307
308 static inline void
309 _getMapInfo(ID3D10Texture1D *pResource, UINT Subresource, D3D10_MAP MapType, UINT MapFlags, void * * ppData,
310             void * & pMappedData, size_t & MappedSize) {
311     pMappedData = 0;
312     MappedSize = 0;
313
314     if (MapType == D3D10_MAP_READ) {
315         return;
316     }
317
318     D3D10_TEXTURE1D_DESC Desc;
319     pResource->GetDesc(&Desc);
320
321     pMappedData = *ppData;
322     MappedSize = _calcSubresourceSize(&Desc, Subresource);
323 }
324
325 static inline void
326 _getMapInfo(ID3D10Texture2D *pResource, UINT Subresource, D3D10_MAP MapType, UINT MapFlags, D3D10_MAPPED_TEXTURE2D * pMappedTex2D,
327             void * & pMappedData, size_t & MappedSize) {
328     pMappedData = 0;
329     MappedSize = 0;
330
331     if (MapType == D3D10_MAP_READ) {
332         return;
333     }
334
335     D3D10_TEXTURE2D_DESC Desc;
336     pResource->GetDesc(&Desc);
337
338     pMappedData = pMappedTex2D->pData;
339     MappedSize = _calcSubresourceSize(&Desc, Subresource, pMappedTex2D->RowPitch);
340 }
341
342 static inline void
343 _getMapInfo(ID3D10Texture3D *pResource, UINT Subresource, D3D10_MAP MapType, UINT MapFlags, D3D10_MAPPED_TEXTURE3D * pMappedTex3D,
344             void * & pMappedData, size_t & MappedSize) {
345     pMappedData = 0;
346     MappedSize = 0;
347
348     if (MapType == D3D10_MAP_READ) {
349         return;
350     }
351
352     D3D10_TEXTURE3D_DESC Desc;
353     pResource->GetDesc(&Desc);
354
355     pMappedData = pMappedTex3D->pData;
356     MappedSize = _calcSubresourceSize(&Desc, Subresource, pMappedTex3D->RowPitch, pMappedTex3D->DepthPitch);
357 }
358
359
360 static inline void
361 _getMapInfo(IDXGISurface *pResource, DXGI_MAPPED_RECT * pLockedRect, UINT MapFlags,
362             void * & pMappedData, size_t & MappedSize) {
363     pMappedData = 0;
364     MappedSize = 0;
365
366     if (!(MapFlags & DXGI_MAP_WRITE)) {
367         return;
368     }
369
370     DXGI_SURFACE_DESC Desc;
371     HRESULT hr = pResource->GetDesc(&Desc);
372     if (FAILED(hr)) {
373         return;
374     }
375
376     pMappedData = pLockedRect->pBits;
377     MappedSize = _calcDataSize(Desc.Format, Desc.Width, Desc.Height, pLockedRect->Pitch);
378 }
379
380
381 static inline size_t
382 _calcSubresourceSize(ID3D10Resource *pDstResource, UINT DstSubresource, const D3D10_BOX *pDstBox, UINT SrcRowPitch, UINT SrcDepthPitch) {
383     if (pDstBox &&
384         (pDstBox->left  >= pDstBox->right ||
385          pDstBox->top   >= pDstBox->bottom ||
386          pDstBox->front >= pDstBox->back)) {
387         return 0;
388     }
389
390     D3D10_RESOURCE_DIMENSION Type = D3D10_RESOURCE_DIMENSION_UNKNOWN;
391     pDstResource->GetType(&Type);
392
393     DXGI_FORMAT Format;
394     UINT Width;
395     UINT Height = 1;
396     UINT Depth = 1;
397     UINT MipLevel = 0;
398
399     switch (Type) {
400     case D3D10_RESOURCE_DIMENSION_BUFFER:
401         if (pDstBox) {
402             return pDstBox->right - pDstBox->left;
403         } else {
404             D3D10_BUFFER_DESC Desc;
405             static_cast<ID3D10Buffer *>(pDstResource)->GetDesc(&Desc);
406             return Desc.ByteWidth;
407         }
408     case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
409         {
410             D3D10_TEXTURE1D_DESC Desc;
411             static_cast<ID3D10Texture1D *>(pDstResource)->GetDesc(&Desc);
412             Format = Desc.Format;
413             Width = Desc.Width;
414             MipLevel = DstSubresource % Desc.MipLevels;
415         }
416         break;
417     case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
418         {
419             D3D10_TEXTURE2D_DESC Desc;
420             static_cast<ID3D10Texture2D *>(pDstResource)->GetDesc(&Desc);
421             Format = Desc.Format;
422             Width = Desc.Width;
423             Height = Desc.Height;
424             MipLevel = DstSubresource % Desc.MipLevels;
425         }
426         break;
427     case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
428         {
429             D3D10_TEXTURE3D_DESC Desc;
430             static_cast<ID3D10Texture3D *>(pDstResource)->GetDesc(&Desc);
431             Format = Desc.Format;
432             Width = Desc.Width;
433             Height = Desc.Height;
434             Depth = Desc.Depth;
435         }
436         break;
437     case D3D10_RESOURCE_DIMENSION_UNKNOWN:
438     default:
439         assert(0);
440         return 0;
441     }
442
443     return _calcMipDataSize(MipLevel, Format, Width, Height, SrcRowPitch, Depth, SrcDepthPitch);
444 }
445
446
447 #endif /* _D3D10SIZE_HPP_ */