]> git.cworth.org Git - apitrace/blob - retrace/d3d11state_images.cpp
Allow float-based attrib_lists as found in WGL.
[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         MipSlice = 0;
224         break;
225     case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
226         MipSlice = Desc.Texture2DArray.MostDetailedMip;
227         break;
228     case D3D11_SRV_DIMENSION_TEXTURE2DMS:
229         MipSlice = 0;
230         break;
231     case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY:
232         MipSlice = 0;
233         break;
234     case D3D11_SRV_DIMENSION_TEXTURE3D:
235         MipSlice = Desc.Texture3D.MostDetailedMip;
236         break;
237     case D3D11_SRV_DIMENSION_TEXTURECUBE:
238         MipSlice = Desc.TextureCube.MostDetailedMip;
239         break;
240     case D3D11_SRV_DIMENSION_UNKNOWN:
241     default:
242         assert(0);
243         return NULL;
244     }
245
246     return getSubResourceImage(pDevice, pResource, Desc.Format, MipSlice);
247 }
248
249
250 static image::Image *
251 getRenderTargetViewImage(ID3D11DeviceContext *pDevice,
252                          ID3D11RenderTargetView *pRenderTargetView) {
253     D3D11_RENDER_TARGET_VIEW_DESC Desc;
254     ID3D11Resource *pResource = NULL;
255     UINT MipSlice;
256
257     if (!pRenderTargetView) {
258         return NULL;
259     }
260
261     pRenderTargetView->GetResource(&pResource);
262     assert(pResource);
263
264     pRenderTargetView->GetDesc(&Desc);
265
266     // TODO: Take the slice in consideration
267     switch (Desc.ViewDimension) {
268     case D3D11_RTV_DIMENSION_BUFFER:
269         MipSlice = 0;
270         break;
271     case D3D11_RTV_DIMENSION_TEXTURE1D:
272         MipSlice = Desc.Texture1D.MipSlice;
273         break;
274     case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
275         MipSlice = Desc.Texture1DArray.MipSlice;
276         break;
277     case D3D11_RTV_DIMENSION_TEXTURE2D:
278         MipSlice = Desc.Texture2D.MipSlice;
279         MipSlice = 0;
280         break;
281     case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
282         MipSlice = Desc.Texture2DArray.MipSlice;
283         break;
284     case D3D11_RTV_DIMENSION_TEXTURE2DMS:
285         MipSlice = 0;
286         break;
287     case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
288         MipSlice = 0;
289         break;
290     case D3D11_RTV_DIMENSION_TEXTURE3D:
291         MipSlice = Desc.Texture3D.MipSlice;
292         break;
293     case D3D11_RTV_DIMENSION_UNKNOWN:
294     default:
295         assert(0);
296         return NULL;
297     }
298
299     return getSubResourceImage(pDevice, pResource, Desc.Format, MipSlice);
300 }
301
302
303 static image::Image *
304 getDepthStencilViewImage(ID3D11DeviceContext *pDevice,
305                          ID3D11DepthStencilView *pDepthStencilView) {
306     D3D11_DEPTH_STENCIL_VIEW_DESC Desc;
307     ID3D11Resource *pResource = NULL;
308     UINT MipSlice;
309
310     if (!pDepthStencilView) {
311         return NULL;
312     }
313
314     pDepthStencilView->GetResource(&pResource);
315     assert(pResource);
316
317     pDepthStencilView->GetDesc(&Desc);
318
319     // TODO: Take the slice in consideration
320     switch (Desc.ViewDimension) {
321     case D3D11_DSV_DIMENSION_TEXTURE1D:
322         MipSlice = Desc.Texture1D.MipSlice;
323         break;
324     case D3D11_DSV_DIMENSION_TEXTURE1DARRAY:
325         MipSlice = Desc.Texture1DArray.MipSlice;
326         break;
327     case D3D11_DSV_DIMENSION_TEXTURE2D:
328         MipSlice = Desc.Texture2D.MipSlice;
329         MipSlice = 0;
330         break;
331     case D3D11_DSV_DIMENSION_TEXTURE2DARRAY:
332         MipSlice = Desc.Texture2DArray.MipSlice;
333         break;
334     case D3D11_DSV_DIMENSION_TEXTURE2DMS:
335         MipSlice = 0;
336         break;
337     case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY:
338         MipSlice = 0;
339         break;
340     case D3D11_DSV_DIMENSION_UNKNOWN:
341     default:
342         assert(0);
343         return NULL;
344     }
345
346     return getSubResourceImage(pDevice, pResource, Desc.Format, MipSlice);
347 }
348
349
350 void
351 dumpTextures(JSONWriter &json, ID3D11DeviceContext *pDevice)
352 {
353     json.beginMember("textures");
354     json.beginObject();
355
356     ID3D11ShaderResourceView *pShaderResourceViews[D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT];
357     pDevice->PSGetShaderResources(0, ARRAYSIZE(pShaderResourceViews), pShaderResourceViews);
358
359     for (UINT i = 0; i < ARRAYSIZE(pShaderResourceViews); ++i) {
360         if (!pShaderResourceViews[i]) {
361             continue;
362         }
363
364         image::Image *image;
365         image = getShaderResourceViewImage(pDevice, pShaderResourceViews[i]);
366         if (image) {
367             char label[64];
368             _snprintf(label, sizeof label, "PS_RESOURCE_%u", i);
369             json.beginMember(label);
370             json.writeImage(image, "UNKNOWN");
371             json.endMember(); // PS_RESOURCE_*
372         }
373
374         pShaderResourceViews[i]->Release();
375     }
376
377     json.endObject();
378     json.endMember(); // textures
379 }
380
381
382 image::Image *
383 getRenderTargetImage(ID3D11DeviceContext *pDevice) {
384     ID3D11RenderTargetView *pRenderTargetView = NULL;
385     pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL);
386
387     image::Image *image = NULL;
388     if (pRenderTargetView) {
389         image = getRenderTargetViewImage(pDevice, pRenderTargetView);
390         pRenderTargetView->Release();
391     }
392
393     return image;
394 }
395
396
397 void
398 dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDevice)
399 {
400     json.beginMember("framebuffer");
401     json.beginObject();
402
403     ID3D11RenderTargetView *pRenderTargetViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
404     ID3D11DepthStencilView *pDepthStencilView;
405     pDevice->OMGetRenderTargets(ARRAYSIZE(pRenderTargetViews), pRenderTargetViews,
406                                 &pDepthStencilView);
407
408     for (UINT i = 0; i < ARRAYSIZE(pRenderTargetViews); ++i) {
409         if (!pRenderTargetViews[i]) {
410             continue;
411         }
412
413         image::Image *image;
414         image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i]);
415         if (image) {
416             char label[64];
417             _snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
418             json.beginMember(label);
419             json.writeImage(image, "UNKNOWN");
420             json.endMember(); // RENDER_TARGET_*
421         }
422
423         pRenderTargetViews[i]->Release();
424     }
425
426     if (pDepthStencilView) {
427         image::Image *image;
428         image = getDepthStencilViewImage(pDevice, pDepthStencilView);
429         if (image) {
430             json.beginMember("DEPTH_STENCIL");
431             json.writeImage(image, "UNKNOWN");
432             json.endMember();
433         }
434
435         pDepthStencilView->Release();
436
437     }
438
439     json.endObject();
440     json.endMember(); // framebuffer
441 }
442
443
444 } /* namespace d3dstate */