]> git.cworth.org Git - apitrace/blob - retrace/d3d11state_images.cpp
d3dretrace: Use DirectXTex for d3d10 state too.
[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 "image.hpp"
33 #include "d3d11imports.hpp"
34 #include "d3d10state.hpp"
35 #include "dxgistate.hpp"
36
37
38 namespace d3dstate {
39
40 static HRESULT
41 stageResource(ID3D11DeviceContext *pDeviceContext,
42               ID3D11Resource *pResource,
43               ID3D11Resource **ppStagingResource,
44               UINT *pWidth, UINT *pHeight, UINT *pDepth) {
45     D3D11_USAGE Usage = D3D11_USAGE_STAGING;
46     UINT BindFlags = 0;
47     UINT CPUAccessFlags = D3D11_CPU_ACCESS_READ;
48     UINT MiscFlags = 0;
49     union {
50          ID3D11Resource *pStagingResource;
51          ID3D11Buffer *pStagingBuffer;
52          ID3D11Texture1D *pStagingTexture1D;
53          ID3D11Texture2D *pStagingTexture2D;
54          ID3D11Texture3D *pStagingTexture3D;
55     };
56     HRESULT hr;
57
58     ID3D11Device *pDevice = NULL;
59     pDeviceContext->GetDevice(&pDevice);
60
61     D3D11_RESOURCE_DIMENSION Type = D3D11_RESOURCE_DIMENSION_UNKNOWN;
62     pResource->GetType(&Type);
63     switch (Type) {
64     case D3D11_RESOURCE_DIMENSION_BUFFER:
65         {
66             D3D11_BUFFER_DESC Desc;
67             static_cast<ID3D11Buffer *>(pResource)->GetDesc(&Desc);
68             Desc.Usage = Usage;
69             Desc.BindFlags = BindFlags;
70             Desc.CPUAccessFlags = CPUAccessFlags;
71             Desc.MiscFlags = MiscFlags;
72
73             *pWidth = Desc.ByteWidth;
74             *pHeight = 1;
75             *pDepth = 1;
76
77             hr = pDevice->CreateBuffer(&Desc, NULL, &pStagingBuffer);
78         }
79         break;
80     case D3D11_RESOURCE_DIMENSION_TEXTURE1D:
81         {
82             D3D11_TEXTURE1D_DESC Desc;
83             static_cast<ID3D11Texture1D *>(pResource)->GetDesc(&Desc);
84             Desc.Usage = Usage;
85             Desc.BindFlags = BindFlags;
86             Desc.CPUAccessFlags = CPUAccessFlags;
87             Desc.MiscFlags = MiscFlags;
88
89             *pWidth = Desc.Width;
90             *pHeight = 1;
91             *pDepth = 1;
92
93             hr = pDevice->CreateTexture1D(&Desc, NULL, &pStagingTexture1D);
94         }
95         break;
96     case D3D11_RESOURCE_DIMENSION_TEXTURE2D:
97         {
98             D3D11_TEXTURE2D_DESC Desc;
99             static_cast<ID3D11Texture2D *>(pResource)->GetDesc(&Desc);
100             Desc.Usage = Usage;
101             Desc.BindFlags = BindFlags;
102             Desc.CPUAccessFlags = CPUAccessFlags;
103             Desc.MiscFlags &= D3D11_RESOURCE_MISC_TEXTURECUBE;
104
105             *pWidth = Desc.Width;
106             *pHeight = Desc.Height;
107             *pDepth = 1;
108
109             hr = pDevice->CreateTexture2D(&Desc, NULL, &pStagingTexture2D);
110         }
111         break;
112     case D3D11_RESOURCE_DIMENSION_TEXTURE3D:
113         {
114             D3D11_TEXTURE3D_DESC Desc;
115             static_cast<ID3D11Texture3D *>(pResource)->GetDesc(&Desc);
116             Desc.Usage = Usage;
117             Desc.BindFlags = BindFlags;
118             Desc.CPUAccessFlags = CPUAccessFlags;
119             Desc.MiscFlags = MiscFlags;
120
121             *pWidth = Desc.Width;
122             *pHeight = Desc.Height;
123             *pDepth = Desc.Depth;
124
125             hr = pDevice->CreateTexture3D(&Desc, NULL, &pStagingTexture3D);
126         }
127         break;
128     default:
129         assert(0);
130         hr = E_NOTIMPL;
131         break;
132     }
133
134     if (SUCCEEDED(hr)) {
135         *ppStagingResource = pStagingResource;
136         pDeviceContext->CopyResource(pStagingResource, pResource);
137     }
138     
139     pDevice->Release();
140
141     return hr;
142 }
143
144 image::Image *
145 getRenderTargetViewImage(ID3D11DeviceContext *pDevice,
146                          ID3D11RenderTargetView *pRenderTargetView) {
147     image::Image *image = NULL;
148     D3D11_RENDER_TARGET_VIEW_DESC Desc;
149     ID3D11Resource *pResource = NULL;
150     ID3D11Resource *pStagingResource = NULL;
151     UINT Width, Height, Depth;
152     UINT MipSlice;
153     UINT Subresource;
154     D3D11_MAPPED_SUBRESOURCE MappedSubresource;
155     HRESULT hr;
156
157     if (!pRenderTargetView) {
158         return NULL;
159     }
160
161     pRenderTargetView->GetResource(&pResource);
162     assert(pResource);
163
164     pRenderTargetView->GetDesc(&Desc);
165
166     hr = stageResource(pDevice, pResource, &pStagingResource, &Width, &Height, &Depth);
167     if (FAILED(hr)) {
168         goto no_staging;
169     }
170
171     // TODO: Take the slice in consideration
172     switch (Desc.ViewDimension) {
173     case D3D11_RTV_DIMENSION_BUFFER:
174         MipSlice = 0;
175         break;
176     case D3D11_RTV_DIMENSION_TEXTURE1D:
177         MipSlice = Desc.Texture1D.MipSlice;
178         break;
179     case D3D11_RTV_DIMENSION_TEXTURE1DARRAY:
180         MipSlice = Desc.Texture1DArray.MipSlice;
181         break;
182     case D3D11_RTV_DIMENSION_TEXTURE2D:
183         MipSlice = Desc.Texture2D.MipSlice;
184         MipSlice = 0;
185         break;
186     case D3D11_RTV_DIMENSION_TEXTURE2DARRAY:
187         MipSlice = Desc.Texture2DArray.MipSlice;
188         break;
189     case D3D11_RTV_DIMENSION_TEXTURE2DMS:
190         MipSlice = 0;
191         break;
192     case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY:
193         MipSlice = 0;
194         break;
195     case D3D11_RTV_DIMENSION_TEXTURE3D:
196         MipSlice = Desc.Texture3D.MipSlice;
197         break;
198     case D3D11_SRV_DIMENSION_UNKNOWN:
199     default:
200         assert(0);
201         goto no_map;
202     }
203     Subresource = MipSlice;
204
205     Width  = std::max(Width  >> MipSlice, 1U);
206     Height = std::max(Height >> MipSlice, 1U);
207     Depth  = std::max(Depth  >> MipSlice, 1U);
208
209     hr = pDevice->Map(pStagingResource, Subresource, D3D11_MAP_READ, 0, &MappedSubresource);
210     if (FAILED(hr)) {
211         goto no_map;
212     }
213
214     image = new image::Image(Width, Height, 4);
215     if (!image) {
216         goto no_image;
217     }
218     assert(image->stride() > 0);
219
220     hr = ConvertFormat(Desc.Format,
221                        MappedSubresource.pData,
222                        MappedSubresource.RowPitch,
223                        DXGI_FORMAT_R8G8B8A8_UNORM,
224                        image->start(),
225                        image->stride(),
226                        Width, Height);
227     if (FAILED(hr)) {
228         delete image;
229         image = NULL;
230     }
231
232 no_image:
233     pDevice->Unmap(pStagingResource, Subresource);
234 no_map:
235     if (pStagingResource) {
236         pStagingResource->Release();
237     }
238 no_staging:
239     if (pResource) {
240         pResource->Release();
241     }
242     return image;
243 }
244
245
246 image::Image *
247 getRenderTargetImage(ID3D11DeviceContext *pDevice) {
248     ID3D11RenderTargetView *pRenderTargetView = NULL;
249     pDevice->OMGetRenderTargets(1, &pRenderTargetView, NULL);
250
251     image::Image *image = NULL;
252     if (pRenderTargetView) {
253         image = getRenderTargetViewImage(pDevice, pRenderTargetView);
254         pRenderTargetView->Release();
255     }
256
257     return image;
258 }
259
260
261 void
262 dumpFramebuffer(JSONWriter &json, ID3D11DeviceContext *pDevice)
263 {
264     json.beginMember("framebuffer");
265     json.beginObject();
266
267     ID3D11RenderTargetView *pRenderTargetViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
268     pDevice->OMGetRenderTargets(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT, pRenderTargetViews, NULL);
269
270     for (UINT i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i) {
271         if (!pRenderTargetViews[i]) {
272             continue;
273         }
274
275         image::Image *image;
276         image = getRenderTargetViewImage(pDevice, pRenderTargetViews[i]);
277         if (image) {
278             char label[64];
279             _snprintf(label, sizeof label, "RENDER_TARGET_%u", i);
280             json.beginMember(label);
281             json.writeImage(image, "UNKNOWN");
282             json.endMember(); // RENDER_TARGET_*
283         }
284
285         pRenderTargetViews[i]->Release();
286     }
287
288     json.endObject();
289     json.endMember(); // framebuffer
290 }
291
292
293 } /* namespace d3dstate */