]> git.cworth.org Git - apitrace/blob - retrace/d3d10state_images.cpp
image: Fix PNM dumping for 2/4 channels.
[apitrace] / retrace / d3d10state_images.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26
27 #include <assert.h>
28
29 #include <iostream>
30 #include <algorithm>
31
32 #include "os.hpp"
33 #include "json.hpp"
34 #include "d3d10imports.hpp"
35 #include "d3dstate.hpp"
36 #include "dxgistate.hpp"
37
38
39 namespace d3dstate {
40
41 static HRESULT
42 stageResource(ID3D10Device *pDevice,
43               ID3D10Resource *pResource,
44               ID3D10Resource **ppStagingResource,
45               UINT *pWidth, UINT *pHeight, UINT *pDepth) {
46     D3D10_USAGE Usage = D3D10_USAGE_STAGING;
47     UINT BindFlags = 0;
48     UINT CPUAccessFlags = D3D10_CPU_ACCESS_READ;
49     UINT MiscFlags = 0;
50     union {
51          ID3D10Resource *pStagingResource;
52          ID3D10Buffer *pStagingBuffer;
53          ID3D10Texture1D *pStagingTexture1D;
54          ID3D10Texture2D *pStagingTexture2D;
55          ID3D10Texture3D *pStagingTexture3D;
56     };
57     HRESULT hr;
58
59     D3D10_RESOURCE_DIMENSION Type = D3D10_RESOURCE_DIMENSION_UNKNOWN;
60     pResource->GetType(&Type);
61     switch (Type) {
62     case D3D10_RESOURCE_DIMENSION_BUFFER:
63         {
64             D3D10_BUFFER_DESC Desc;
65             static_cast<ID3D10Buffer *>(pResource)->GetDesc(&Desc);
66             Desc.Usage = Usage;
67             Desc.BindFlags = BindFlags;
68             Desc.CPUAccessFlags = CPUAccessFlags;
69             Desc.MiscFlags = MiscFlags;
70
71             *pWidth = Desc.ByteWidth;
72             *pHeight = 1;
73             *pDepth = 1;
74
75             hr = pDevice->CreateBuffer(&Desc, NULL, &pStagingBuffer);
76         }
77         break;
78     case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
79         {
80             D3D10_TEXTURE1D_DESC Desc;
81             static_cast<ID3D10Texture1D *>(pResource)->GetDesc(&Desc);
82             Desc.Usage = Usage;
83             Desc.BindFlags = BindFlags;
84             Desc.CPUAccessFlags = CPUAccessFlags;
85             Desc.MiscFlags = MiscFlags;
86
87             *pWidth = Desc.Width;
88             *pHeight = 1;
89             *pDepth = 1;
90
91             hr = pDevice->CreateTexture1D(&Desc, NULL, &pStagingTexture1D);
92         }
93         break;
94     case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
95         {
96             D3D10_TEXTURE2D_DESC Desc;
97             static_cast<ID3D10Texture2D *>(pResource)->GetDesc(&Desc);
98             Desc.Usage = Usage;
99             Desc.BindFlags = BindFlags;
100             Desc.CPUAccessFlags = CPUAccessFlags;
101             Desc.MiscFlags &= D3D10_RESOURCE_MISC_TEXTURECUBE;
102
103             *pWidth = Desc.Width;
104             *pHeight = Desc.Height;
105             *pDepth = 1;
106
107             hr = pDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture2D);
108         }
109         break;
110     case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
111         {
112             D3D10_TEXTURE3D_DESC Desc;
113             static_cast<ID3D10Texture3D *>(pResource)->GetDesc(&Desc);
114             Desc.Usage = Usage;
115             Desc.BindFlags = BindFlags;
116             Desc.CPUAccessFlags = CPUAccessFlags;
117             Desc.MiscFlags = MiscFlags;
118
119             *pWidth = Desc.Width;
120             *pHeight = Desc.Height;
121             *pDepth = Desc.Depth;
122
123             hr = pDevice->CreateTexture3D(&Desc, NULL, &pStagingTexture3D);
124         }
125         break;
126     default:
127         assert(0);
128         hr = E_NOTIMPL;
129         break;
130     }
131
132     if (SUCCEEDED(hr)) {
133         *ppStagingResource = pStagingResource;
134         pDevice->CopyResource(pStagingResource, pResource);
135     }
136     
137     return hr;
138 }
139
140 static HRESULT
141 mapResource(ID3D10Resource *pResource,
142             UINT SubResource, D3D10_MAP MapType, UINT MapFlags,
143             D3D10_MAPPED_TEXTURE3D *pMappedSubResource) {
144     D3D10_RESOURCE_DIMENSION Type = D3D10_RESOURCE_DIMENSION_UNKNOWN;
145     pResource->GetType(&Type);
146     switch (Type) {
147     case D3D10_RESOURCE_DIMENSION_BUFFER:
148         assert(SubResource == 0);
149         return static_cast<ID3D10Buffer *>(pResource)->Map(MapType, MapFlags, &pMappedSubResource->pData);
150     case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
151         return static_cast<ID3D10Texture1D *>(pResource)->Map(SubResource, MapType, MapFlags, &pMappedSubResource->pData);
152     case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
153         return static_cast<ID3D10Texture2D *>(pResource)->Map(SubResource, MapType, MapFlags, reinterpret_cast<D3D10_MAPPED_TEXTURE2D *>(pMappedSubResource));
154     case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
155         return static_cast<ID3D10Texture3D *>(pResource)->Map(SubResource, MapType, MapFlags, pMappedSubResource);
156     default:
157         assert(0);
158         return E_NOTIMPL;
159     }
160 }
161
162 static void
163 unmapResource(ID3D10Resource *pResource, UINT SubResource) {
164     D3D10_RESOURCE_DIMENSION Type = D3D10_RESOURCE_DIMENSION_UNKNOWN;
165     pResource->GetType(&Type);
166     switch (Type) {
167     case D3D10_RESOURCE_DIMENSION_BUFFER:
168         assert(SubResource == 0);
169         static_cast<ID3D10Buffer *>(pResource)->Unmap();
170         break;
171     case D3D10_RESOURCE_DIMENSION_TEXTURE1D:
172         static_cast<ID3D10Texture1D *>(pResource)->Unmap(SubResource);
173         break;
174     case D3D10_RESOURCE_DIMENSION_TEXTURE2D:
175         static_cast<ID3D10Texture2D *>(pResource)->Unmap(SubResource);
176         break;
177     case D3D10_RESOURCE_DIMENSION_TEXTURE3D:
178         static_cast<ID3D10Texture3D *>(pResource)->Unmap(SubResource);
179         break;
180     default:
181         assert(0);
182     }
183 }
184
185
186 static image::Image *
187 getSubResourceImage(ID3D10Device *pDevice,
188                     ID3D10Resource *pResource,
189                     DXGI_FORMAT Format,
190                     UINT MipSlice)
191 {
192     image::Image *image = NULL;
193     ID3D10Resource *pStagingResource = NULL;
194     UINT Width, Height, Depth;
195     UINT SubResource = MipSlice;
196     D3D10_MAPPED_TEXTURE3D MappedSubResource;
197     HRESULT hr;
198
199     if (!pResource) {
200         return NULL;
201     }
202
203     hr = stageResource(pDevice, pResource, &pStagingResource, &Width, &Height, &Depth);
204     if (FAILED(hr)) {
205         goto no_staging;
206     }
207
208     Width  = std::max(Width  >> MipSlice, 1U);
209     Height = std::max(Height >> MipSlice, 1U);
210     Depth  = std::max(Depth  >> MipSlice, 1U);
211
212     hr = mapResource(pStagingResource, SubResource, D3D10_MAP_READ, 0, &MappedSubResource);
213     if (FAILED(hr)) {
214         goto no_map;
215     }
216
217     image = ConvertImage(Format,
218                          MappedSubResource.pData,
219                          MappedSubResource.RowPitch,
220                          Width, Height);
221
222     unmapResource(pStagingResource, SubResource);
223 no_map:
224     if (pStagingResource) {
225         pStagingResource->Release();
226     }
227 no_staging:
228     if (pResource) {
229         pResource->Release();
230     }
231     return image;
232 }
233
234
235 static image::Image *
236 getShaderResourceViewImage(ID3D10Device *pDevice,
237                            ID3D10ShaderResourceView *pShaderResourceView) {
238     D3D10_SHADER_RESOURCE_VIEW_DESC Desc;
239     ID3D10Resource *pResource = NULL;
240     UINT MipSlice;
241
242     if (!pShaderResourceView) {
243         return NULL;
244     }
245
246     pShaderResourceView->GetResource(&pResource);
247     assert(pResource);
248
249     pShaderResourceView->GetDesc(&Desc);
250
251     // TODO: Take the slice in consideration
252     switch (Desc.ViewDimension) {
253     case D3D10_SRV_DIMENSION_BUFFER:
254         MipSlice = 0;
255         break;
256     case D3D10_SRV_DIMENSION_TEXTURE1D:
257         MipSlice = Desc.Texture1D.MostDetailedMip;
258         break;
259     case D3D10_SRV_DIMENSION_TEXTURE1DARRAY:
260         MipSlice = Desc.Texture1DArray.MostDetailedMip;
261         break;
262     case D3D10_SRV_DIMENSION_TEXTURE2D:
263         MipSlice = Desc.Texture2D.MostDetailedMip;
264         break;
265     case D3D10_SRV_DIMENSION_TEXTURE2DARRAY:
266         MipSlice = Desc.Texture2DArray.MostDetailedMip;
267         break;
268     case D3D10_SRV_DIMENSION_TEXTURE2DMS:
269         MipSlice = 0;
270         break;
271     case D3D10_SRV_DIMENSION_TEXTURE2DMSARRAY:
272         MipSlice = 0;
273         break;
274     case D3D10_SRV_DIMENSION_TEXTURE3D:
275         MipSlice = Desc.Texture3D.MostDetailedMip;
276         break;
277     case D3D10_SRV_DIMENSION_TEXTURECUBE:
278         MipSlice = Desc.TextureCube.MostDetailedMip;
279         break;
280     case D3D10_SRV_DIMENSION_UNKNOWN:
281     default:
282         assert(0);
283         return NULL;
284     }
285
286     return getSubResourceImage(pDevice, pResource, Desc.Format, MipSlice);
287 }
288
289
290 static image::Image *
291 getRenderTargetViewImage(ID3D10Device *pDevice,
292                          ID3D10RenderTargetView *pRenderTargetView) {
293     D3D10_RENDER_TARGET_VIEW_DESC Desc;
294     ID3D10Resource *pResource = NULL;
295     UINT MipSlice;
296
297     if (!pRenderTargetView) {
298         return NULL;
299     }
300
301     pRenderTargetView->GetResource(&pResource);
302     assert(pResource);
303
304     pRenderTargetView->GetDesc(&Desc);
305
306     // TODO: Take the slice in consideration
307     switch (Desc.ViewDimension) {
308     case D3D10_RTV_DIMENSION_BUFFER:
309         MipSlice = 0;
310         break;
311     case D3D10_RTV_DIMENSION_TEXTURE1D:
312         MipSlice = Desc.Texture1D.MipSlice;
313         break;
314     case D3D10_RTV_DIMENSION_TEXTURE1DARRAY:
315         MipSlice = Desc.Texture1DArray.MipSlice;
316         break;
317     case D3D10_RTV_DIMENSION_TEXTURE2D:
318         MipSlice = Desc.Texture2D.MipSlice;
319         MipSlice = 0;
320         break;
321     case D3D10_RTV_DIMENSION_TEXTURE2DARRAY:
322         MipSlice = Desc.Texture2DArray.MipSlice;
323         break;
324     case D3D10_RTV_DIMENSION_TEXTURE2DMS:
325         MipSlice = 0;
326         break;
327     case D3D10_RTV_DIMENSION_TEXTURE2DMSARRAY:
328         MipSlice = 0;
329         break;
330     case D3D10_RTV_DIMENSION_TEXTURE3D:
331         MipSlice = Desc.Texture3D.MipSlice;
332         break;
333     case D3D10_RTV_DIMENSION_UNKNOWN:
334     default:
335         assert(0);
336         return NULL;
337     }
338
339     return getSubResourceImage(pDevice, pResource, Desc.Format, MipSlice);
340 }
341
342
343 static image::Image *
344 getDepthStencilViewImage(ID3D10Device *pDevice,
345                          ID3D10DepthStencilView *pDepthStencilView) {
346     D3D10_DEPTH_STENCIL_VIEW_DESC Desc;
347     ID3D10Resource *pResource = NULL;
348     UINT MipSlice;
349
350     if (!pDepthStencilView) {
351         return NULL;
352     }
353
354     pDepthStencilView->GetResource(&pResource);
355     assert(pResource);
356
357     pDepthStencilView->GetDesc(&Desc);
358
359     // TODO: Take the slice in consideration
360     switch (Desc.ViewDimension) {
361     case D3D10_DSV_DIMENSION_TEXTURE1D:
362         MipSlice = Desc.Texture1D.MipSlice;
363         break;
364     case D3D10_DSV_DIMENSION_TEXTURE1DARRAY:
365         MipSlice = Desc.Texture1DArray.MipSlice;
366         break;
367     case D3D10_DSV_DIMENSION_TEXTURE2D:
368         MipSlice = Desc.Texture2D.MipSlice;
369         break;
370     case D3D10_DSV_DIMENSION_TEXTURE2DARRAY:
371         MipSlice = Desc.Texture2DArray.MipSlice;
372         break;
373     case D3D10_DSV_DIMENSION_TEXTURE2DMS:
374         MipSlice = 0;
375         break;
376     case D3D10_DSV_DIMENSION_TEXTURE2DMSARRAY:
377         MipSlice = 0;
378         break;
379     case D3D10_DSV_DIMENSION_UNKNOWN:
380     default:
381         assert(0);
382         return NULL;
383     }
384
385     return getSubResourceImage(pDevice, pResource, Desc.Format, MipSlice);
386 }
387
388
389 static void
390 dumpStageTextures(JSONWriter &json, ID3D10Device *pDevice, const char *stageName,
391                   UINT NumViews,
392                   ID3D10ShaderResourceView **ppShaderResourceViews)
393 {
394     for (UINT i = 0; i < NumViews; ++i) {
395         if (!ppShaderResourceViews[i]) {
396             continue;
397         }
398
399         image::Image *image;
400         image = getShaderResourceViewImage(pDevice, ppShaderResourceViews[i]);
401         if (image) {
402             char label[64];
403             _snprintf(label, sizeof label, "%s_RESOURCE_%u", stageName, i);
404             json.beginMember(label);
405             json.writeImage(image, "UNKNOWN");
406             json.endMember(); // *_RESOURCE_*
407         }
408
409         ppShaderResourceViews[i]->Release();
410     }
411 }
412
413
414 void
415 dumpTextures(JSONWriter &json, ID3D10Device *pDevice)
416 {
417     json.beginMember("textures");
418     json.beginObject();
419
420     ID3D10ShaderResourceView *pShaderResourceViews[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT];
421
422     pDevice->PSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
423     dumpStageTextures(json, pDevice, "PS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
424
425     pDevice->VSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
426     dumpStageTextures(json, pDevice, "VS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
427
428     pDevice->GSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
429     dumpStageTextures(json, pDevice, "GS", ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
430
431     json.endObject();
432     json.endMember(); // textures
433 }
434
435
436 image::Image *
437 getRenderTargetImage(ID3D10Device *pDevice) {
438     ID3D10RenderTargetView *pRenderTargetView = NULL;
439     pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL);
440
441     image::Image *image = NULL;
442     if (pRenderTargetView) {
443         image = getRenderTargetViewImage(pDevice, pRenderTargetView);
444         pRenderTargetView->Release();
445     }
446
447     return image;
448 }
449
450
451 void
452 dumpFramebuffer(JSONWriter &json, ID3D10Device *pDevice)
453 {
454     json.beginMember("framebuffer");
455     json.beginObject();
456
457     ID3D10RenderTargetView *pRenderTargetViews[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT];
458     ID3D10DepthStencilView *pDepthStencilView;
459     pDevice->OMGetRenderTargets(ARRAYSIZE(pRenderTargetViews), pRenderTargetViews,
460                                 &pDepthStencilView);
461
462     for (UINT i = 0; i < ARRAYSIZE(pRenderTargetViews); ++i) {
463         if (!pRenderTargetViews[i]) {
464             continue;
465         }
466
467         image::Image *image;
468         image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i]);
469         if (image) {
470             char label[64];
471             _snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
472             json.beginMember(label);
473             json.writeImage(image, "UNKNOWN");
474             json.endMember(); // RENDER_TARGET_*
475         }
476
477         pRenderTargetViews[i]->Release();
478     }
479
480     if (pDepthStencilView) {
481         image::Image *image;
482         image = getDepthStencilViewImage(pDevice, pDepthStencilView);
483         if (image) {
484             json.beginMember("DEPTH_STENCIL");
485             json.writeImage(image, "UNKNOWN");
486             json.endMember();
487         }
488
489         pDepthStencilView->Release();
490
491     }
492
493     json.endObject();
494     json.endMember(); // framebuffer
495 }
496
497
498 } /* namespace d3dstate */