]> git.cworth.org Git - apitrace/blob - retrace/d3d11state_images.cpp
Merge branch 'attrib_list'
[apitrace] / retrace / d3d11state_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 "d3d11imports.hpp"
35 #include "d3d10state.hpp"
36 #include "dxgistate.hpp"
37
38
39 namespace d3dstate {
40
41 static HRESULT
42 stageResource(ID3D11DeviceContext *pDeviceContext,
43               ID3D11Resource *pResource,
44               ID3D11Resource **ppStagingResource,
45               UINT *pWidth, UINT *pHeight, UINT *pDepth) {
46     D3D11_USAGE Usage = D3D11_USAGE_STAGING;
47     UINT BindFlags = 0;
48     UINT CPUAccessFlags = D3D11_CPU_ACCESS_READ;
49     UINT MiscFlags = 0;
50     union {
51          ID3D11Resource *pStagingResource;
52          ID3D11Buffer *pStagingBuffer;
53          ID3D11Texture1D *pStagingTexture1D;
54          ID3D11Texture2D *pStagingTexture2D;
55          ID3D11Texture3D *pStagingTexture3D;
56     };
57     HRESULT hr;
58
59     ID3D11Device *pDevice = NULL;
60     pDeviceContext->GetDevice(&pDevice);
61
62     D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
63     pResource->GetType(&Type);
64     switch (Type) {
65     case D3D11_RESOURCE_DIMENSION_BUFFER:
66         {
67             D3D11_BUFFER_DESC Desc;
68             static_cast<ID3D11Buffer *>(pResource)->GetDesc(&Desc);
69             Desc.Usage = Usage;
70             Desc.BindFlags = BindFlags;
71             Desc.CPUAccessFlags = CPUAccessFlags;
72             Desc.MiscFlags = MiscFlags;
73
74             *pWidth = Desc.ByteWidth;
75             *pHeight = 1;
76             *pDepth = 1;
77
78             hr = pDevice->CreateBuffer(&Desc, NULL, &pStagingBuffer);
79         }
80         break;
81     case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
82         {
83             D3D11_TEXTURE1D_DESC Desc;
84             static_cast<ID3D11Texture1D *>(pResource)->GetDesc(&Desc);
85             Desc.Usage = Usage;
86             Desc.BindFlags = BindFlags;
87             Desc.CPUAccessFlags = CPUAccessFlags;
88             Desc.MiscFlags = MiscFlags;
89
90             *pWidth = Desc.Width;
91             *pHeight = 1;
92             *pDepth = 1;
93
94             hr = pDevice->CreateTexture1D(&Desc, NULL, &pStagingTexture1D);
95         }
96         break;
97     case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
98         {
99             D3D11_TEXTURE2D_DESC Desc;
100             static_cast<ID3D11Texture2D *>(pResource)->GetDesc(&Desc);
101             Desc.Usage = Usage;
102             Desc.BindFlags = BindFlags;
103             Desc.CPUAccessFlags = CPUAccessFlags;
104             Desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;
105
106             *pWidth = Desc.Width;
107             *pHeight = Desc.Height;
108             *pDepth = 1;
109
110             hr = pDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture2D);
111         }
112         break;
113     case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
114         {
115             D3D11_TEXTURE3D_DESC Desc;
116             static_cast<ID3D11Texture3D *>(pResource)->GetDesc(&Desc);
117             Desc.Usage = Usage;
118             Desc.BindFlags = BindFlags;
119             Desc.CPUAccessFlags = CPUAccessFlags;
120             Desc.MiscFlags = MiscFlags;
121
122             *pWidth = Desc.Width;
123             *pHeight = Desc.Height;
124             *pDepth = Desc.Depth;
125
126             hr = pDevice->CreateTexture3D(&Desc, NULL, &pStagingTexture3D);
127         }
128         break;
129     default:
130         assert(0);
131         hr = E_NOTIMPL;
132         break;
133     }
134
135     if (SUCCEEDED(hr)) {
136         *ppStagingResource = pStagingResource;
137         pDeviceContext->CopyResource(pStagingResource, pResource);
138     }
139     
140     pDevice->Release();
141
142     return hr;
143 }
144
145 static image::Image *
146 getSubResourceImage(ID3D11DeviceContext *pDevice,
147                     ID3D11Resource *pResource,
148                     DXGI_FORMAT Format,
149                     UINT MipSlice)
150 {
151     image::Image *image = NULL;
152     ID3D11Resource *pStagingResource = NULL;
153     UINT Width, Height, Depth;
154     UINT SubResource = MipSlice;
155     D3D11_MAPPED_SUBRESOURCE MappedSubResource;
156     HRESULT hr;
157
158     if (!pResource) {
159         return NULL;
160     }
161
162     hr = stageResource(pDevice, pResource, &pStagingResource, &Width, &Height, &Depth);
163     if (FAILED(hr)) {
164         goto no_staging;
165     }
166
167     Width  = std::max(Width  >> MipSlice, 1U);
168     Height = std::max(Height >> MipSlice, 1U);
169     Depth  = std::max(Depth  >> MipSlice, 1U);
170
171     hr = pDevice->Map(pStagingResource, SubResource, D3D11_MAP_READ, 0, &MappedSubResource);
172     if (FAILED(hr)) {
173         goto no_map;
174     }
175
176     image = ConvertImage(Format,
177                          MappedSubResource.pData,
178                          MappedSubResource.RowPitch,
179                          Width, Height);
180
181     pDevice->Unmap(pStagingResource, SubResource);
182 no_map:
183     if (pStagingResource) {
184         pStagingResource->Release();
185     }
186 no_staging:
187     if (pResource) {
188         pResource->Release();
189     }
190     return image;
191 }
192
193
194 static image::Image *
195 getShaderResourceViewImage(ID3D11DeviceContext *pDevice,
196                            ID3D11ShaderResourceView *pShaderResourceView) {
197     D3D11_SHADER_RESOURCE_VIEW_DESC Desc;
198     ID3D11Resource *pResource = NULL;
199     UINT MipSlice;
200
201     if (!pShaderResourceView) {
202         return NULL;
203     }
204
205     pShaderResourceView->GetResource(&pResource);
206     assert(pResource);
207
208     pShaderResourceView->GetDesc(&Desc);
209
210     // TODO: Take the slice in consideration
211     switch (Desc.ViewDimension) {
212     case D3D11_SRV_DIMENSION_BUFFER:
213         MipSlice = 0;
214         break;
215     case D3D11_SRV_DIMENSION_TEXTURE1D:
216         MipSlice = Desc.Texture1D.MostDetailedMip;
217         break;
218     case D3D11_SRV_DIMENSION_TEXTURE1DARRAY:
219         MipSlice = Desc.Texture1DArray.MostDetailedMip;
220         break;
221     case D3D11_SRV_DIMENSION_TEXTURE2D:
222         MipSlice = Desc.Texture2D.MostDetailedMip;
223         break;
224     case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
225         MipSlice = Desc.Texture2DArray.MostDetailedMip;
226         break;
227     case D3D11_SRV_DIMENSION_TEXTURE2DMS:
228         MipSlice = 0;
229         break;
230     case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
231         MipSlice = 0;
232         break;
233     case D3D11_SRV_DIMENSION_TEXTURE3D:
234         MipSlice = Desc.Texture3D.MostDetailedMip;
235         break;
236     case D3D11_SRV_DIMENSION_TEXTURECUBE:
237         MipSlice = Desc.TextureCube.MostDetailedMip;
238         break;
239     case D3D11_SRV_DIMENSION_UNKNOWN:
240     default:
241         assert(0);
242         return NULL;
243     }
244
245     return getSubResourceImage(pDevice, pResource, Desc.Format, MipSlice);
246 }
247
248
249 static image::Image *
250 getRenderTargetViewImage(ID3D11DeviceContext *pDevice,
251                          ID3D11RenderTargetView *pRenderTargetView) {
252     D3D11_RENDER_TARGET_VIEW_DESC Desc;
253     ID3D11Resource *pResource = NULL;
254     UINT MipSlice;
255
256     if (!pRenderTargetView) {
257         return NULL;
258     }
259
260     pRenderTargetView->GetResource(&pResource);
261     assert(pResource);
262
263     pRenderTargetView->GetDesc(&Desc);
264
265     // TODO: Take the slice in consideration
266     switch (Desc.ViewDimension) {
267     case D3D11_RTV_DIMENSION_BUFFER:
268         MipSlice = 0;
269         break;
270     case D3D11_RTV_DIMENSION_TEXTURE1D:
271         MipSlice = Desc.Texture1D.MipSlice;
272         break;
273     case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
274         MipSlice = Desc.Texture1DArray.MipSlice;
275         break;
276     case D3D11_RTV_DIMENSION_TEXTURE2D:
277         MipSlice = Desc.Texture2D.MipSlice;
278         MipSlice = 0;
279         break;
280     case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
281         MipSlice = Desc.Texture2DArray.MipSlice;
282         break;
283     case D3D11_RTV_DIMENSION_TEXTURE2DMS:
284         MipSlice = 0;
285         break;
286     case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
287         MipSlice = 0;
288         break;
289     case D3D11_RTV_DIMENSION_TEXTURE3D:
290         MipSlice = Desc.Texture3D.MipSlice;
291         break;
292     case D3D11_RTV_DIMENSION_UNKNOWN:
293     default:
294         assert(0);
295         return NULL;
296     }
297
298     return getSubResourceImage(pDevice, pResource, Desc.Format, MipSlice);
299 }
300
301
302 static image::Image *
303 getDepthStencilViewImage(ID3D11DeviceContext *pDevice,
304                          ID3D11DepthStencilView *pDepthStencilView) {
305     D3D11_DEPTH_STENCIL_VIEW_DESC Desc;
306     ID3D11Resource *pResource = NULL;
307     UINT MipSlice;
308
309     if (!pDepthStencilView) {
310         return NULL;
311     }
312
313     pDepthStencilView->GetResource(&pResource);
314     assert(pResource);
315
316     pDepthStencilView->GetDesc(&Desc);
317
318     // TODO: Take the slice in consideration
319     switch (Desc.ViewDimension) {
320     case D3D11_DSV_DIMENSION_TEXTURE1D:
321         MipSlice = Desc.Texture1D.MipSlice;
322         break;
323     case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
324         MipSlice = Desc.Texture1DArray.MipSlice;
325         break;
326     case D3D11_DSV_DIMENSION_TEXTURE2D:
327         MipSlice = Desc.Texture2D.MipSlice;
328         break;
329     case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
330         MipSlice = Desc.Texture2DArray.MipSlice;
331         break;
332     case D3D11_DSV_DIMENSION_TEXTURE2DMS:
333         MipSlice = 0;
334         break;
335     case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
336         MipSlice = 0;
337         break;
338     case D3D11_DSV_DIMENSION_UNKNOWN:
339     default:
340         assert(0);
341         return NULL;
342     }
343
344     return getSubResourceImage(pDevice, pResource, Desc.Format, MipSlice);
345 }
346
347
348 void
349 dumpTextures(JSONWriter &json, ID3D11DeviceContext *pDevice)
350 {
351     json.beginMember("textures");
352     json.beginObject();
353
354     ID3D11ShaderResourceView *pShaderResourceViews[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
355     pDevice->PSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
356
357     for (UINT i = 0; i < ARRAYSIZE(pShaderResourceViews); ++i) {
358         if (!pShaderResourceViews[i]) {
359             continue;
360         }
361
362         image::Image *image;
363         image = getShaderResourceViewImage(pDevice, pShaderResourceViews[i]);
364         if (image) {
365             char label[64];
366             _snprintf(label, sizeof label, "PS_RESOURCE_%u", i);
367             json.beginMember(label);
368             json.writeImage(image, "UNKNOWN");
369             json.endMember(); // PS_RESOURCE_*
370         }
371
372         pShaderResourceViews[i]->Release();
373     }
374
375     json.endObject();
376     json.endMember(); // textures
377 }
378
379
380 image::Image *
381 getRenderTargetImage(ID3D11DeviceContext *pDevice) {
382     ID3D11RenderTargetView *pRenderTargetView = NULL;
383     pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL);
384
385     image::Image *image = NULL;
386     if (pRenderTargetView) {
387         image = getRenderTargetViewImage(pDevice, pRenderTargetView);
388         pRenderTargetView->Release();
389     }
390
391     return image;
392 }
393
394
395 void
396 dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDevice)
397 {
398     json.beginMember("framebuffer");
399     json.beginObject();
400
401     ID3D11RenderTargetView *pRenderTargetViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
402     ID3D11DepthStencilView *pDepthStencilView;
403     pDevice->OMGetRenderTargets(ARRAYSIZE(pRenderTargetViews), pRenderTargetViews,
404                                 &pDepthStencilView);
405
406     for (UINT i = 0; i < ARRAYSIZE(pRenderTargetViews); ++i) {
407         if (!pRenderTargetViews[i]) {
408             continue;
409         }
410
411         image::Image *image;
412         image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i]);
413         if (image) {
414             char label[64];
415             _snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
416             json.beginMember(label);
417             json.writeImage(image, "UNKNOWN");
418             json.endMember(); // RENDER_TARGET_*
419         }
420
421         pRenderTargetViews[i]->Release();
422     }
423
424     if (pDepthStencilView) {
425         image::Image *image;
426         image = getDepthStencilViewImage(pDevice, pDepthStencilView);
427         if (image) {
428             json.beginMember("DEPTH_STENCIL");
429             json.writeImage(image, "UNKNOWN");
430             json.endMember();
431         }
432
433         pDepthStencilView->Release();
434
435     }
436
437     json.endObject();
438     json.endMember(); // framebuffer
439 }
440
441
442 } /* namespace d3dstate */