1 //
2 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // Blit11.cpp: Texture copy utility class.
8
9 #include "libANGLE/renderer/d3d/d3d11/Blit11.h"
10
11 #include <float.h>
12
13 #include "libANGLE/formatutils.h"
14 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
15 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
16 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
17 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
18 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
19 #include "third_party/trace_event/trace_event.h"
20
21 namespace rx
22 {
23
24 namespace
25 {
26
27 // Include inline shaders in the anonymous namespace to make sure no symbols are exported
28 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
29 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
30 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
31 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbapremultiply2d11ps.h"
32 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbaunmultiply2d11ps.h"
33 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h"
34 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h"
35 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h"
36 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbpremultiply2d11ps.h"
37 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgbunmultiply2d11ps.h"
38 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h"
39 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h"
40 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h"
41 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h"
42 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h"
43 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h"
44 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h"
45 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h"
46 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h"
47 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h"
48
49 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
50 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
51 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h"
52 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h"
53 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h"
54 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h"
55 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h"
56 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h"
57 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h"
58 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h"
59 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h"
60 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h"
61 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h"
62 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h"
63 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h"
64 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h"
65
66 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h"
67 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h"
68 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h"
69 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h"
70
71 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
72 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
73 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
74 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
75 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
76 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
77 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
78 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
79 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
80
StretchedBlitNearest_RowByRow(const gl::Box & sourceArea,const gl::Box & destArea,const gl::Rectangle & clippedDestArea,const gl::Extents & sourceSize,unsigned int sourceRowPitch,unsigned int destRowPitch,size_t pixelSize,const uint8_t * sourceData,uint8_t * destData)81 void StretchedBlitNearest_RowByRow(const gl::Box &sourceArea,
82 const gl::Box &destArea,
83 const gl::Rectangle &clippedDestArea,
84 const gl::Extents &sourceSize,
85 unsigned int sourceRowPitch,
86 unsigned int destRowPitch,
87 size_t pixelSize,
88 const uint8_t *sourceData,
89 uint8_t *destData)
90 {
91 int srcHeightSubOne = (sourceArea.height - 1);
92 size_t copySize = pixelSize * destArea.width;
93 size_t srcOffset = sourceArea.x * pixelSize;
94 size_t destOffset = destArea.x * pixelSize;
95
96 for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
97 {
98 float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
99
100 // Interpolate using the original source rectangle to determine which row to sample from
101 // while clamping to the edges
102 unsigned int readRow = static_cast<unsigned int>(
103 gl::clamp(sourceArea.y + floor(yPerc * srcHeightSubOne + 0.5f), 0, srcHeightSubOne));
104 unsigned int writeRow = y;
105
106 const uint8_t *sourceRow = sourceData + readRow * sourceRowPitch + srcOffset;
107 uint8_t *destRow = destData + writeRow * destRowPitch + destOffset;
108 memcpy(destRow, sourceRow, copySize);
109 }
110 }
111
StretchedBlitNearest_PixelByPixel(const gl::Box & sourceArea,const gl::Box & destArea,const gl::Rectangle & clippedDestArea,const gl::Extents & sourceSize,unsigned int sourceRowPitch,unsigned int destRowPitch,ptrdiff_t readOffset,ptrdiff_t writeOffset,size_t copySize,size_t srcPixelStride,size_t destPixelStride,const uint8_t * sourceData,uint8_t * destData)112 void StretchedBlitNearest_PixelByPixel(const gl::Box &sourceArea,
113 const gl::Box &destArea,
114 const gl::Rectangle &clippedDestArea,
115 const gl::Extents &sourceSize,
116 unsigned int sourceRowPitch,
117 unsigned int destRowPitch,
118 ptrdiff_t readOffset,
119 ptrdiff_t writeOffset,
120 size_t copySize,
121 size_t srcPixelStride,
122 size_t destPixelStride,
123 const uint8_t *sourceData,
124 uint8_t *destData)
125 {
126 auto xMax = clippedDestArea.x + clippedDestArea.width;
127 auto yMax = clippedDestArea.y + clippedDestArea.height;
128
129 for (int writeRow = clippedDestArea.y; writeRow < yMax; writeRow++)
130 {
131 // Interpolate using the original source rectangle to determine which row to sample from
132 // while clamping to the edges
133 float yPerc = static_cast<float>(writeRow - destArea.y) / (destArea.height - 1);
134 float yRounded = floor(yPerc * (sourceArea.height - 1) + 0.5f);
135 unsigned int readRow =
136 static_cast<unsigned int>(gl::clamp(sourceArea.y + yRounded, 0, sourceSize.height - 1));
137
138 for (int writeColumn = clippedDestArea.x; writeColumn < xMax; writeColumn++)
139 {
140 // Interpolate the original source rectangle to determine which column to sample
141 // from while clamping to the edges
142 float xPerc = static_cast<float>(writeColumn - destArea.x) / (destArea.width - 1);
143 float xRounded = floor(xPerc * (sourceArea.width - 1) + 0.5f);
144 unsigned int readColumn = static_cast<unsigned int>(
145 gl::clamp(sourceArea.x + xRounded, 0, sourceSize.height - 1));
146
147 const uint8_t *sourcePixel =
148 sourceData + readRow * sourceRowPitch + readColumn * srcPixelStride + readOffset;
149
150 uint8_t *destPixel =
151 destData + writeRow * destRowPitch + writeColumn * destPixelStride + writeOffset;
152
153 memcpy(destPixel, sourcePixel, copySize);
154 }
155 }
156 }
157
StretchedBlitNearest(const gl::Box & sourceArea,const gl::Box & destArea,const gl::Rectangle & clipRect,const gl::Extents & sourceSize,unsigned int sourceRowPitch,unsigned int destRowPitch,ptrdiff_t readOffset,ptrdiff_t writeOffset,size_t copySize,size_t srcPixelStride,size_t destPixelStride,const uint8_t * sourceData,uint8_t * destData)158 void StretchedBlitNearest(const gl::Box &sourceArea,
159 const gl::Box &destArea,
160 const gl::Rectangle &clipRect,
161 const gl::Extents &sourceSize,
162 unsigned int sourceRowPitch,
163 unsigned int destRowPitch,
164 ptrdiff_t readOffset,
165 ptrdiff_t writeOffset,
166 size_t copySize,
167 size_t srcPixelStride,
168 size_t destPixelStride,
169 const uint8_t *sourceData,
170 uint8_t *destData)
171 {
172 gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
173 gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea);
174
175 // Determine if entire rows can be copied at once instead of each individual pixel. There
176 // must be no out of bounds lookups, whole rows copies, and no scale.
177 if (sourceArea.width == clippedDestArea.width && sourceArea.x >= 0 &&
178 sourceArea.x + sourceArea.width <= sourceSize.width && copySize == srcPixelStride &&
179 copySize == destPixelStride)
180 {
181 StretchedBlitNearest_RowByRow(sourceArea, destArea, clippedDestArea, sourceSize,
182 sourceRowPitch, destRowPitch, srcPixelStride, sourceData,
183 destData);
184 }
185 else
186 {
187 StretchedBlitNearest_PixelByPixel(sourceArea, destArea, clippedDestArea, sourceSize,
188 sourceRowPitch, destRowPitch, readOffset, writeOffset,
189 copySize, srcPixelStride, destPixelStride, sourceData,
190 destData);
191 }
192 }
193
194 using DepthStencilLoader = void(const float *, uint8_t *);
195
LoadDepth16(const float * source,uint8_t * dest)196 void LoadDepth16(const float *source, uint8_t *dest)
197 {
198 uint32_t convertedDepth = gl::floatToNormalized<16, uint32_t>(source[0]);
199 memcpy(dest, &convertedDepth, 2u);
200 }
201
LoadDepth24(const float * source,uint8_t * dest)202 void LoadDepth24(const float *source, uint8_t *dest)
203 {
204 uint32_t convertedDepth = gl::floatToNormalized<24, uint32_t>(source[0]);
205 memcpy(dest, &convertedDepth, 3u);
206 }
207
LoadStencilHelper(const float * source,uint8_t * dest)208 void LoadStencilHelper(const float *source, uint8_t *dest)
209 {
210 uint32_t convertedStencil = gl::getShiftedData<8, 0>(static_cast<uint32_t>(source[1]));
211 memcpy(dest, &convertedStencil, 1u);
212 }
213
LoadStencil8(const float * source,uint8_t * dest)214 void LoadStencil8(const float *source, uint8_t *dest)
215 {
216 // STENCIL_INDEX8 is implemented with D24S8, with the depth bits unused. Writes zero for safety.
217 float zero = 0.0f;
218 LoadDepth24(&zero, &dest[0]);
219 LoadStencilHelper(source, &dest[3]);
220 }
221
LoadDepth24Stencil8(const float * source,uint8_t * dest)222 void LoadDepth24Stencil8(const float *source, uint8_t *dest)
223 {
224 LoadDepth24(source, &dest[0]);
225 LoadStencilHelper(source, &dest[3]);
226 }
227
LoadDepth32F(const float * source,uint8_t * dest)228 void LoadDepth32F(const float *source, uint8_t *dest)
229 {
230 memcpy(dest, source, sizeof(float));
231 }
232
LoadDepth32FStencil8(const float * source,uint8_t * dest)233 void LoadDepth32FStencil8(const float *source, uint8_t *dest)
234 {
235 LoadDepth32F(source, &dest[0]);
236 LoadStencilHelper(source, &dest[4]);
237 }
238
239 template <DepthStencilLoader loader>
CopyDepthStencil(const gl::Box & sourceArea,const gl::Box & destArea,const gl::Rectangle & clippedDestArea,const gl::Extents & sourceSize,unsigned int sourceRowPitch,unsigned int destRowPitch,ptrdiff_t readOffset,ptrdiff_t writeOffset,size_t copySize,size_t srcPixelStride,size_t destPixelStride,const uint8_t * sourceData,uint8_t * destData)240 void CopyDepthStencil(const gl::Box &sourceArea,
241 const gl::Box &destArea,
242 const gl::Rectangle &clippedDestArea,
243 const gl::Extents &sourceSize,
244 unsigned int sourceRowPitch,
245 unsigned int destRowPitch,
246 ptrdiff_t readOffset,
247 ptrdiff_t writeOffset,
248 size_t copySize,
249 size_t srcPixelStride,
250 size_t destPixelStride,
251 const uint8_t *sourceData,
252 uint8_t *destData)
253 {
254 // No stretching or subregions are supported, only full blits.
255 ASSERT(sourceArea == destArea);
256 ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
257 sourceSize.depth == 1);
258 ASSERT(clippedDestArea.width == sourceSize.width &&
259 clippedDestArea.height == sourceSize.height);
260 ASSERT(readOffset == 0 && writeOffset == 0);
261 ASSERT(destArea.x == 0 && destArea.y == 0);
262
263 for (int row = 0; row < destArea.height; ++row)
264 {
265 for (int column = 0; column < destArea.width; ++column)
266 {
267 ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
268 const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
269
270 uint8_t *destPixel = destData + row * destRowPitch + column * destPixelStride;
271
272 loader(sourcePixel, destPixel);
273 }
274 }
275 }
276
Depth32FStencil8ToDepth32F(const float * source,float * dest)277 void Depth32FStencil8ToDepth32F(const float *source, float *dest)
278 {
279 *dest = *source;
280 }
281
Depth24Stencil8ToDepth32F(const uint32_t * source,float * dest)282 void Depth24Stencil8ToDepth32F(const uint32_t *source, float *dest)
283 {
284 uint32_t normDepth = source[0] & 0x00FFFFFF;
285 float floatDepth = gl::normalizedToFloat<24>(normDepth);
286 *dest = floatDepth;
287 }
288
BlitD24S8ToD32F(const gl::Box & sourceArea,const gl::Box & destArea,const gl::Rectangle & clippedDestArea,const gl::Extents & sourceSize,unsigned int sourceRowPitch,unsigned int destRowPitch,ptrdiff_t readOffset,ptrdiff_t writeOffset,size_t copySize,size_t srcPixelStride,size_t destPixelStride,const uint8_t * sourceData,uint8_t * destData)289 void BlitD24S8ToD32F(const gl::Box &sourceArea,
290 const gl::Box &destArea,
291 const gl::Rectangle &clippedDestArea,
292 const gl::Extents &sourceSize,
293 unsigned int sourceRowPitch,
294 unsigned int destRowPitch,
295 ptrdiff_t readOffset,
296 ptrdiff_t writeOffset,
297 size_t copySize,
298 size_t srcPixelStride,
299 size_t destPixelStride,
300 const uint8_t *sourceData,
301 uint8_t *destData)
302 {
303 // No stretching or subregions are supported, only full blits.
304 ASSERT(sourceArea == destArea);
305 ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
306 sourceSize.depth == 1);
307 ASSERT(clippedDestArea.width == sourceSize.width &&
308 clippedDestArea.height == sourceSize.height);
309 ASSERT(readOffset == 0 && writeOffset == 0);
310 ASSERT(destArea.x == 0 && destArea.y == 0);
311
312 for (int row = 0; row < destArea.height; ++row)
313 {
314 for (int column = 0; column < destArea.width; ++column)
315 {
316 ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
317 const uint32_t *sourcePixel = reinterpret_cast<const uint32_t *>(sourceData + offset);
318
319 float *destPixel =
320 reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
321
322 Depth24Stencil8ToDepth32F(sourcePixel, destPixel);
323 }
324 }
325 }
326
BlitD32FS8ToD32F(const gl::Box & sourceArea,const gl::Box & destArea,const gl::Rectangle & clippedDestArea,const gl::Extents & sourceSize,unsigned int sourceRowPitch,unsigned int destRowPitch,ptrdiff_t readOffset,ptrdiff_t writeOffset,size_t copySize,size_t srcPixelStride,size_t destPixelStride,const uint8_t * sourceData,uint8_t * destData)327 void BlitD32FS8ToD32F(const gl::Box &sourceArea,
328 const gl::Box &destArea,
329 const gl::Rectangle &clippedDestArea,
330 const gl::Extents &sourceSize,
331 unsigned int sourceRowPitch,
332 unsigned int destRowPitch,
333 ptrdiff_t readOffset,
334 ptrdiff_t writeOffset,
335 size_t copySize,
336 size_t srcPixelStride,
337 size_t destPixelStride,
338 const uint8_t *sourceData,
339 uint8_t *destData)
340 {
341 // No stretching or subregions are supported, only full blits.
342 ASSERT(sourceArea == destArea);
343 ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
344 sourceSize.depth == 1);
345 ASSERT(clippedDestArea.width == sourceSize.width &&
346 clippedDestArea.height == sourceSize.height);
347 ASSERT(readOffset == 0 && writeOffset == 0);
348 ASSERT(destArea.x == 0 && destArea.y == 0);
349
350 for (int row = 0; row < destArea.height; ++row)
351 {
352 for (int column = 0; column < destArea.width; ++column)
353 {
354 ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
355 const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
356 float *destPixel =
357 reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
358
359 Depth32FStencil8ToDepth32F(sourcePixel, destPixel);
360 }
361 }
362 }
363
GetCopyDepthStencilFunction(GLenum internalFormat)364 Blit11::BlitConvertFunction *GetCopyDepthStencilFunction(GLenum internalFormat)
365 {
366 switch (internalFormat)
367 {
368 case GL_DEPTH_COMPONENT16:
369 return &CopyDepthStencil<LoadDepth16>;
370 case GL_DEPTH_COMPONENT24:
371 return &CopyDepthStencil<LoadDepth24>;
372 case GL_DEPTH_COMPONENT32F:
373 return &CopyDepthStencil<LoadDepth32F>;
374 case GL_STENCIL_INDEX8:
375 return &CopyDepthStencil<LoadStencil8>;
376 case GL_DEPTH24_STENCIL8:
377 return &CopyDepthStencil<LoadDepth24Stencil8>;
378 case GL_DEPTH32F_STENCIL8:
379 return &CopyDepthStencil<LoadDepth32FStencil8>;
380 default:
381 UNREACHABLE();
382 return nullptr;
383 }
384 }
385
GenerateVertexCoords(const gl::Box & sourceArea,const gl::Extents & sourceSize,const gl::Box & destArea,const gl::Extents & destSize,float * x1,float * y1,float * x2,float * y2,float * u1,float * v1,float * u2,float * v2)386 inline void GenerateVertexCoords(const gl::Box &sourceArea,
387 const gl::Extents &sourceSize,
388 const gl::Box &destArea,
389 const gl::Extents &destSize,
390 float *x1,
391 float *y1,
392 float *x2,
393 float *y2,
394 float *u1,
395 float *v1,
396 float *u2,
397 float *v2)
398 {
399 *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
400 *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f;
401 *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f;
402 *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f;
403
404 *u1 = sourceArea.x / float(sourceSize.width);
405 *v1 = sourceArea.y / float(sourceSize.height);
406 *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width);
407 *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height);
408 }
409
Write2DVertices(const gl::Box & sourceArea,const gl::Extents & sourceSize,const gl::Box & destArea,const gl::Extents & destSize,void * outVertices,unsigned int * outStride,unsigned int * outVertexCount,D3D11_PRIMITIVE_TOPOLOGY * outTopology)410 void Write2DVertices(const gl::Box &sourceArea,
411 const gl::Extents &sourceSize,
412 const gl::Box &destArea,
413 const gl::Extents &destSize,
414 void *outVertices,
415 unsigned int *outStride,
416 unsigned int *outVertexCount,
417 D3D11_PRIMITIVE_TOPOLOGY *outTopology)
418 {
419 float x1, y1, x2, y2, u1, v1, u2, v2;
420 GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
421 &u2, &v2);
422
423 d3d11::PositionTexCoordVertex *vertices =
424 static_cast<d3d11::PositionTexCoordVertex *>(outVertices);
425
426 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
427 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
428 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
429 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
430
431 *outStride = sizeof(d3d11::PositionTexCoordVertex);
432 *outVertexCount = 4;
433 *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
434 }
435
Write3DVertices(const gl::Box & sourceArea,const gl::Extents & sourceSize,const gl::Box & destArea,const gl::Extents & destSize,void * outVertices,unsigned int * outStride,unsigned int * outVertexCount,D3D11_PRIMITIVE_TOPOLOGY * outTopology)436 void Write3DVertices(const gl::Box &sourceArea,
437 const gl::Extents &sourceSize,
438 const gl::Box &destArea,
439 const gl::Extents &destSize,
440 void *outVertices,
441 unsigned int *outStride,
442 unsigned int *outVertexCount,
443 D3D11_PRIMITIVE_TOPOLOGY *outTopology)
444 {
445 ASSERT(sourceSize.depth > 0 && destSize.depth > 0);
446
447 float x1, y1, x2, y2, u1, v1, u2, v2;
448 GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
449 &u2, &v2);
450
451 d3d11::PositionLayerTexCoord3DVertex *vertices =
452 static_cast<d3d11::PositionLayerTexCoord3DVertex *>(outVertices);
453
454 for (int i = 0; i < destSize.depth; i++)
455 {
456 float readDepth = (float)i / std::max(destSize.depth - 1, 1);
457
458 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth);
459 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth);
460 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth);
461
462 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth);
463 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth);
464 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth);
465 }
466
467 *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex);
468 *outVertexCount = destSize.depth * 6;
469 *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
470 }
471
GetSwizzleIndex(GLenum swizzle)472 unsigned int GetSwizzleIndex(GLenum swizzle)
473 {
474 unsigned int colorIndex = 0;
475
476 switch (swizzle)
477 {
478 case GL_RED:
479 colorIndex = 0;
480 break;
481 case GL_GREEN:
482 colorIndex = 1;
483 break;
484 case GL_BLUE:
485 colorIndex = 2;
486 break;
487 case GL_ALPHA:
488 colorIndex = 3;
489 break;
490 case GL_ZERO:
491 colorIndex = 4;
492 break;
493 case GL_ONE:
494 colorIndex = 5;
495 break;
496 default:
497 UNREACHABLE();
498 break;
499 }
500
501 return colorIndex;
502 }
503
GetAlphaMaskBlendStateDesc()504 D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc()
505 {
506 D3D11_BLEND_DESC desc;
507 memset(&desc, 0, sizeof(desc));
508 desc.RenderTarget[0].BlendEnable = TRUE;
509 desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
510 desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
511 desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
512 desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
513 desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
514 desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
515 desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED |
516 D3D11_COLOR_WRITE_ENABLE_GREEN |
517 D3D11_COLOR_WRITE_ENABLE_BLUE;
518 return desc;
519 }
520
521 D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = {
522 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
523 {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
524 };
525
526 D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = {
527 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
528 {"LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
529 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
530 };
531
GetStencilSRVFormat(const d3d11::Format & formatSet)532 DXGI_FORMAT GetStencilSRVFormat(const d3d11::Format &formatSet)
533 {
534 switch (formatSet.texFormat)
535 {
536 case DXGI_FORMAT_R32G8X24_TYPELESS:
537 return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
538 case DXGI_FORMAT_R24G8_TYPELESS:
539 return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
540 default:
541 UNREACHABLE();
542 return DXGI_FORMAT_UNKNOWN;
543 }
544 }
545
546 } // namespace
547
Blit11(Renderer11 * renderer)548 Blit11::Blit11(Renderer11 *renderer)
549 : mRenderer(renderer),
550 mResourcesInitialized(false),
551 mVertexBuffer(nullptr),
552 mPointSampler(nullptr),
553 mLinearSampler(nullptr),
554 mScissorEnabledRasterizerState(nullptr),
555 mScissorDisabledRasterizerState(nullptr),
556 mDepthStencilState(nullptr),
557 mQuad2DIL(quad2DLayout,
558 ArraySize(quad2DLayout),
559 g_VS_Passthrough2D,
560 ArraySize(g_VS_Passthrough2D),
561 "Blit11 2D input layout"),
562 mQuad2DVS(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D vertex shader"),
563 mDepthPS(g_PS_PassthroughDepth2D,
564 ArraySize(g_PS_PassthroughDepth2D),
565 "Blit11 2D depth pixel shader"),
566 mQuad3DIL(quad3DLayout,
567 ArraySize(quad3DLayout),
568 g_VS_Passthrough3D,
569 ArraySize(g_VS_Passthrough3D),
570 "Blit11 3D input layout"),
571 mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"),
572 mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"),
573 mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"),
574 mSwizzleCB(nullptr),
575 mResolveDepthStencilVS(g_VS_ResolveDepthStencil,
576 ArraySize(g_VS_ResolveDepthStencil),
577 "Blit11::mResolveDepthStencilVS"),
578 mResolveDepthPS(g_PS_ResolveDepth, ArraySize(g_PS_ResolveDepth), "Blit11::mResolveDepthPS"),
579 mResolveDepthStencilPS(g_PS_ResolveDepthStencil,
580 ArraySize(g_PS_ResolveDepthStencil),
581 "Blit11::mResolveDepthStencilPS"),
582 mResolveStencilPS(g_PS_ResolveStencil,
583 ArraySize(g_PS_ResolveStencil),
584 "Blit11::mResolveStencilPS"),
585 mStencilSRV(nullptr),
586 mResolvedDepthStencilRTView(nullptr)
587 {
588 }
589
~Blit11()590 Blit11::~Blit11()
591 {
592 freeResources();
593
594 mQuad2DIL.release();
595 mQuad2DVS.release();
596 mDepthPS.release();
597
598 mQuad3DIL.release();
599 mQuad3DVS.release();
600 mQuad3DGS.release();
601
602 clearShaderMap();
603 releaseResolveDepthStencilResources();
604 }
605
initResources()606 gl::Error Blit11::initResources()
607 {
608 if (mResourcesInitialized)
609 {
610 return gl::Error(GL_NO_ERROR);
611 }
612
613 TRACE_EVENT0("gpu.angle", "Blit11::initResources");
614
615 HRESULT result;
616 ID3D11Device *device = mRenderer->getDevice();
617
618 D3D11_BUFFER_DESC vbDesc;
619 vbDesc.ByteWidth =
620 static_cast<unsigned int>(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex),
621 sizeof(d3d11::PositionTexCoordVertex)) *
622 6 * mRenderer->getNativeCaps().max3DTextureSize);
623 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
624 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
625 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
626 vbDesc.MiscFlags = 0;
627 vbDesc.StructureByteStride = 0;
628
629 result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer);
630 ASSERT(SUCCEEDED(result));
631 if (FAILED(result))
632 {
633 freeResources();
634 return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit vertex buffer, HRESULT: 0x%X",
635 result);
636 }
637 d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer");
638
639 D3D11_SAMPLER_DESC pointSamplerDesc;
640 pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
641 pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
642 pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
643 pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
644 pointSamplerDesc.MipLODBias = 0.0f;
645 pointSamplerDesc.MaxAnisotropy = 0;
646 pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
647 pointSamplerDesc.BorderColor[0] = 0.0f;
648 pointSamplerDesc.BorderColor[1] = 0.0f;
649 pointSamplerDesc.BorderColor[2] = 0.0f;
650 pointSamplerDesc.BorderColor[3] = 0.0f;
651 pointSamplerDesc.MinLOD = 0.0f;
652 pointSamplerDesc.MaxLOD = FLT_MAX;
653
654 result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
655 ASSERT(SUCCEEDED(result));
656 if (FAILED(result))
657 {
658 freeResources();
659 return gl::Error(GL_OUT_OF_MEMORY,
660 "Failed to create blit point sampler state, HRESULT: 0x%X", result);
661 }
662 d3d11::SetDebugName(mPointSampler, "Blit11 point sampler");
663
664 D3D11_SAMPLER_DESC linearSamplerDesc;
665 linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
666 linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
667 linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
668 linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
669 linearSamplerDesc.MipLODBias = 0.0f;
670 linearSamplerDesc.MaxAnisotropy = 0;
671 linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
672 linearSamplerDesc.BorderColor[0] = 0.0f;
673 linearSamplerDesc.BorderColor[1] = 0.0f;
674 linearSamplerDesc.BorderColor[2] = 0.0f;
675 linearSamplerDesc.BorderColor[3] = 0.0f;
676 linearSamplerDesc.MinLOD = 0.0f;
677 linearSamplerDesc.MaxLOD = FLT_MAX;
678
679 result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
680 ASSERT(SUCCEEDED(result));
681 if (FAILED(result))
682 {
683 freeResources();
684 return gl::Error(GL_OUT_OF_MEMORY,
685 "Failed to create blit linear sampler state, HRESULT: 0x%X", result);
686 }
687 d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler");
688
689 // Use a rasterizer state that will not cull so that inverted quads will not be culled
690 D3D11_RASTERIZER_DESC rasterDesc;
691 rasterDesc.FillMode = D3D11_FILL_SOLID;
692 rasterDesc.CullMode = D3D11_CULL_NONE;
693 rasterDesc.FrontCounterClockwise = FALSE;
694 rasterDesc.DepthBias = 0;
695 rasterDesc.SlopeScaledDepthBias = 0.0f;
696 rasterDesc.DepthBiasClamp = 0.0f;
697 rasterDesc.DepthClipEnable = TRUE;
698 rasterDesc.MultisampleEnable = FALSE;
699 rasterDesc.AntialiasedLineEnable = FALSE;
700
701 rasterDesc.ScissorEnable = TRUE;
702 result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState);
703 ASSERT(SUCCEEDED(result));
704 if (FAILED(result))
705 {
706 freeResources();
707 return gl::Error(GL_OUT_OF_MEMORY,
708 "Failed to create blit scissoring rasterizer state, HRESULT: 0x%X",
709 result);
710 }
711 d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state");
712
713 rasterDesc.ScissorEnable = FALSE;
714 result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState);
715 ASSERT(SUCCEEDED(result));
716 if (FAILED(result))
717 {
718 freeResources();
719 return gl::Error(GL_OUT_OF_MEMORY,
720 "Failed to create blit no scissoring rasterizer state, HRESULT: 0x%X",
721 result);
722 }
723 d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state");
724
725 D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
726 depthStencilDesc.DepthEnable = true;
727 depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
728 depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
729 depthStencilDesc.StencilEnable = FALSE;
730 depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
731 depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
732 depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
733 depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
734 depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
735 depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
736 depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
737 depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
738 depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
739 depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
740
741 result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState);
742 ASSERT(SUCCEEDED(result));
743 if (FAILED(result))
744 {
745 freeResources();
746 return gl::Error(GL_OUT_OF_MEMORY,
747 "Failed to create blit depth stencil state, HRESULT: 0x%X", result);
748 }
749 d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state");
750
751 D3D11_BUFFER_DESC swizzleBufferDesc;
752 swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4;
753 swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
754 swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
755 swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
756 swizzleBufferDesc.MiscFlags = 0;
757 swizzleBufferDesc.StructureByteStride = 0;
758
759 result = device->CreateBuffer(&swizzleBufferDesc, nullptr, &mSwizzleCB);
760 ASSERT(SUCCEEDED(result));
761 if (FAILED(result))
762 {
763 freeResources();
764 return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit swizzle buffer, HRESULT: 0x%X",
765 result);
766 }
767 d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer");
768
769 mResourcesInitialized = true;
770
771 return gl::Error(GL_NO_ERROR);
772 }
773
freeResources()774 void Blit11::freeResources()
775 {
776 SafeRelease(mVertexBuffer);
777 SafeRelease(mPointSampler);
778 SafeRelease(mLinearSampler);
779 SafeRelease(mScissorEnabledRasterizerState);
780 SafeRelease(mScissorDisabledRasterizerState);
781 SafeRelease(mDepthStencilState);
782 SafeRelease(mSwizzleCB);
783
784 mResourcesInitialized = false;
785 }
786
787 // static
GetBlitShaderType(GLenum destinationFormat,bool isSigned,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,ShaderDimension dimension)788 Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat,
789 bool isSigned,
790 bool unpackPremultiplyAlpha,
791 bool unpackUnmultiplyAlpha,
792 ShaderDimension dimension)
793 {
794 if (dimension == SHADER_3D)
795 {
796 ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
797
798 if (isSigned)
799 {
800 switch (destinationFormat)
801 {
802 case GL_RGBA_INTEGER:
803 return BLITSHADER_3D_RGBAI;
804 case GL_RGB_INTEGER:
805 return BLITSHADER_3D_RGBI;
806 case GL_RG_INTEGER:
807 return BLITSHADER_3D_RGI;
808 case GL_RED_INTEGER:
809 return BLITSHADER_3D_RI;
810 default:
811 UNREACHABLE();
812 return BLITSHADER_INVALID;
813 }
814 }
815 else
816 {
817 switch (destinationFormat)
818 {
819 case GL_RGBA:
820 return BLITSHADER_3D_RGBAF;
821 case GL_RGBA_INTEGER:
822 return BLITSHADER_3D_RGBAUI;
823 case GL_BGRA_EXT:
824 return BLITSHADER_3D_BGRAF;
825 case GL_RGB:
826 return BLITSHADER_3D_RGBF;
827 case GL_RGB_INTEGER:
828 return BLITSHADER_3D_RGBUI;
829 case GL_RG:
830 return BLITSHADER_3D_RGF;
831 case GL_RG_INTEGER:
832 return BLITSHADER_3D_RGUI;
833 case GL_RED:
834 return BLITSHADER_3D_RF;
835 case GL_RED_INTEGER:
836 return BLITSHADER_3D_RUI;
837 case GL_ALPHA:
838 return BLITSHADER_3D_ALPHA;
839 case GL_LUMINANCE:
840 return BLITSHADER_3D_LUMA;
841 case GL_LUMINANCE_ALPHA:
842 return BLITSHADER_3D_LUMAALPHA;
843 default:
844 UNREACHABLE();
845 return BLITSHADER_INVALID;
846 }
847 }
848 }
849 else if (isSigned)
850 {
851 ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
852
853 switch (destinationFormat)
854 {
855 case GL_RGBA_INTEGER:
856 return BLITSHADER_2D_RGBAI;
857 case GL_RGB_INTEGER:
858 return BLITSHADER_2D_RGBI;
859 case GL_RG_INTEGER:
860 return BLITSHADER_2D_RGI;
861 case GL_RED_INTEGER:
862 return BLITSHADER_2D_RI;
863 default:
864 UNREACHABLE();
865 return BLITSHADER_INVALID;
866 }
867 }
868 else
869 {
870 if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha)
871 {
872 switch (destinationFormat)
873 {
874 case GL_RGBA:
875 return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_PREMULTIPLY
876 : BLITSHADER_2D_RGBAF_UNMULTIPLY;
877 case GL_BGRA_EXT:
878 return unpackPremultiplyAlpha ? BLITSHADER_2D_BGRAF_PREMULTIPLY
879 : BLITSHADER_2D_BGRAF_UNMULTIPLY;
880 case GL_RGB:
881 return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_PREMULTIPLY
882 : BLITSHADER_2D_RGBF_UNMULTIPLY;
883 default:
884 UNREACHABLE();
885 return BLITSHADER_INVALID;
886 }
887 }
888 else
889 {
890 switch (destinationFormat)
891 {
892 case GL_RGBA:
893 return BLITSHADER_2D_RGBAF;
894 case GL_RGBA_INTEGER:
895 return BLITSHADER_2D_RGBAUI;
896 case GL_BGRA_EXT:
897 return BLITSHADER_2D_BGRAF;
898 case GL_RGB:
899 return BLITSHADER_2D_RGBF;
900 case GL_RGB_INTEGER:
901 return BLITSHADER_2D_RGBUI;
902 case GL_RG:
903 return BLITSHADER_2D_RGF;
904 case GL_RG_INTEGER:
905 return BLITSHADER_2D_RGUI;
906 case GL_RED:
907 return BLITSHADER_2D_RF;
908 case GL_RED_INTEGER:
909 return BLITSHADER_2D_RUI;
910 case GL_ALPHA:
911 return BLITSHADER_2D_ALPHA;
912 case GL_LUMINANCE:
913 return BLITSHADER_2D_LUMA;
914 case GL_LUMINANCE_ALPHA:
915 return BLITSHADER_2D_LUMAALPHA;
916 default:
917 UNREACHABLE();
918 return BLITSHADER_INVALID;
919 }
920 }
921 }
922 }
923
924 // static
GetSwizzleShaderType(GLenum type,D3D11_SRV_DIMENSION dimensionality)925 Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type,
926 D3D11_SRV_DIMENSION dimensionality)
927 {
928 switch (dimensionality)
929 {
930 case D3D11_SRV_DIMENSION_TEXTURE2D:
931 switch (type)
932 {
933 case GL_FLOAT:
934 return SWIZZLESHADER_2D_FLOAT;
935 case GL_UNSIGNED_INT:
936 return SWIZZLESHADER_2D_UINT;
937 case GL_INT:
938 return SWIZZLESHADER_2D_INT;
939 default:
940 UNREACHABLE();
941 return SWIZZLESHADER_INVALID;
942 }
943 case D3D11_SRV_DIMENSION_TEXTURECUBE:
944 switch (type)
945 {
946 case GL_FLOAT:
947 return SWIZZLESHADER_CUBE_FLOAT;
948 case GL_UNSIGNED_INT:
949 return SWIZZLESHADER_CUBE_UINT;
950 case GL_INT:
951 return SWIZZLESHADER_CUBE_INT;
952 default:
953 UNREACHABLE();
954 return SWIZZLESHADER_INVALID;
955 }
956 case D3D11_SRV_DIMENSION_TEXTURE3D:
957 switch (type)
958 {
959 case GL_FLOAT:
960 return SWIZZLESHADER_3D_FLOAT;
961 case GL_UNSIGNED_INT:
962 return SWIZZLESHADER_3D_UINT;
963 case GL_INT:
964 return SWIZZLESHADER_3D_INT;
965 default:
966 UNREACHABLE();
967 return SWIZZLESHADER_INVALID;
968 }
969 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
970 switch (type)
971 {
972 case GL_FLOAT:
973 return SWIZZLESHADER_ARRAY_FLOAT;
974 case GL_UNSIGNED_INT:
975 return SWIZZLESHADER_ARRAY_UINT;
976 case GL_INT:
977 return SWIZZLESHADER_ARRAY_INT;
978 default:
979 UNREACHABLE();
980 return SWIZZLESHADER_INVALID;
981 }
982 default:
983 UNREACHABLE();
984 return SWIZZLESHADER_INVALID;
985 }
986 }
987
getShaderSupport(const Shader & shader)988 Blit11::ShaderSupport Blit11::getShaderSupport(const Shader &shader)
989 {
990 ID3D11Device *device = mRenderer->getDevice();
991 ShaderSupport support;
992
993 if (shader.dimension == SHADER_2D)
994 {
995 support.inputLayout = mQuad2DIL.resolve(device);
996 support.vertexShader = mQuad2DVS.resolve(device);
997 support.geometryShader = nullptr;
998 support.vertexWriteFunction = Write2DVertices;
999 }
1000 else
1001 {
1002 ASSERT(shader.dimension == SHADER_3D);
1003 support.inputLayout = mQuad3DIL.resolve(device);
1004 support.vertexShader = mQuad3DVS.resolve(device);
1005 support.geometryShader = mQuad3DGS.resolve(device);
1006 support.vertexWriteFunction = Write3DVertices;
1007 }
1008
1009 return support;
1010 }
1011
swizzleTexture(ID3D11ShaderResourceView * source,ID3D11RenderTargetView * dest,const gl::Extents & size,const gl::SwizzleState & swizzleTarget)1012 gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source,
1013 ID3D11RenderTargetView *dest,
1014 const gl::Extents &size,
1015 const gl::SwizzleState &swizzleTarget)
1016 {
1017 ANGLE_TRY(initResources());
1018
1019 HRESULT result;
1020 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1021
1022 D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
1023 source->GetDesc(&sourceSRVDesc);
1024
1025 GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
1026 if (componentType == GL_NONE)
1027 {
1028 // We're swizzling the depth component of a depth-stencil texture.
1029 switch (sourceSRVDesc.Format)
1030 {
1031 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
1032 componentType = GL_UNSIGNED_NORMALIZED;
1033 break;
1034 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
1035 componentType = GL_FLOAT;
1036 break;
1037 default:
1038 UNREACHABLE();
1039 break;
1040 }
1041 }
1042
1043 GLenum shaderType = GL_NONE;
1044 switch (componentType)
1045 {
1046 case GL_UNSIGNED_NORMALIZED:
1047 case GL_SIGNED_NORMALIZED:
1048 case GL_FLOAT:
1049 shaderType = GL_FLOAT;
1050 break;
1051 case GL_INT:
1052 shaderType = GL_INT;
1053 break;
1054 case GL_UNSIGNED_INT:
1055 shaderType = GL_UNSIGNED_INT;
1056 break;
1057 default:
1058 UNREACHABLE();
1059 break;
1060 }
1061
1062 const Shader *shader = nullptr;
1063 ANGLE_TRY(getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader));
1064
1065 // Set vertices
1066 D3D11_MAPPED_SUBRESOURCE mappedResource;
1067 result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
1068 if (FAILED(result))
1069 {
1070 return gl::Error(GL_OUT_OF_MEMORY,
1071 "Failed to map internal vertex buffer for swizzle, HRESULT: 0x%X.",
1072 result);
1073 }
1074
1075 const ShaderSupport &support = getShaderSupport(*shader);
1076
1077 UINT stride = 0;
1078 UINT startIdx = 0;
1079 UINT drawCount = 0;
1080 D3D11_PRIMITIVE_TOPOLOGY topology;
1081
1082 gl::Box area(0, 0, 0, size.width, size.height, size.depth);
1083 support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount,
1084 &topology);
1085
1086 deviceContext->Unmap(mVertexBuffer, 0);
1087
1088 // Set constant buffer
1089 result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
1090 if (FAILED(result))
1091 {
1092 return gl::Error(GL_OUT_OF_MEMORY,
1093 "Failed to map internal constant buffer for swizzle, HRESULT: 0x%X.",
1094 result);
1095 }
1096
1097 unsigned int *swizzleIndices = reinterpret_cast<unsigned int *>(mappedResource.pData);
1098 swizzleIndices[0] = GetSwizzleIndex(swizzleTarget.swizzleRed);
1099 swizzleIndices[1] = GetSwizzleIndex(swizzleTarget.swizzleGreen);
1100 swizzleIndices[2] = GetSwizzleIndex(swizzleTarget.swizzleBlue);
1101 swizzleIndices[3] = GetSwizzleIndex(swizzleTarget.swizzleAlpha);
1102
1103 deviceContext->Unmap(mSwizzleCB, 0);
1104
1105 // Apply vertex buffer
1106 deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
1107
1108 // Apply constant buffer
1109 deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB);
1110
1111 // Apply state
1112 deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
1113 deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
1114 deviceContext->RSSetState(mScissorDisabledRasterizerState);
1115
1116 // Apply shaders
1117 deviceContext->IASetInputLayout(support.inputLayout);
1118 deviceContext->IASetPrimitiveTopology(topology);
1119 deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
1120
1121 deviceContext->PSSetShader(shader->pixelShader, nullptr, 0);
1122 deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
1123
1124 // Unset the currently bound shader resource to avoid conflicts
1125 auto stateManager = mRenderer->getStateManager();
1126 stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
1127
1128 // Apply render target
1129 stateManager->setOneTimeRenderTarget(dest, nullptr);
1130
1131 // Set the viewport
1132 D3D11_VIEWPORT viewport;
1133 viewport.TopLeftX = 0;
1134 viewport.TopLeftY = 0;
1135 viewport.Width = static_cast<FLOAT>(size.width);
1136 viewport.Height = static_cast<FLOAT>(size.height);
1137 viewport.MinDepth = 0.0f;
1138 viewport.MaxDepth = 1.0f;
1139 deviceContext->RSSetViewports(1, &viewport);
1140
1141 // Apply textures
1142 stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
1143
1144 // Apply samplers
1145 deviceContext->PSSetSamplers(0, 1, &mPointSampler);
1146
1147 // Draw the quad
1148 deviceContext->Draw(drawCount, 0);
1149
1150 // Unbind textures and render targets and vertex buffer
1151 stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
1152
1153 UINT zero = 0;
1154 ID3D11Buffer *const nullBuffer = nullptr;
1155 deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
1156
1157 mRenderer->markAllStateDirty();
1158
1159 return gl::Error(GL_NO_ERROR);
1160 }
1161
copyTexture(ID3D11ShaderResourceView * source,const gl::Box & sourceArea,const gl::Extents & sourceSize,ID3D11RenderTargetView * dest,const gl::Box & destArea,const gl::Extents & destSize,const gl::Rectangle * scissor,GLenum destFormat,GLenum filter,bool maskOffAlpha,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)1162 gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source,
1163 const gl::Box &sourceArea,
1164 const gl::Extents &sourceSize,
1165 ID3D11RenderTargetView *dest,
1166 const gl::Box &destArea,
1167 const gl::Extents &destSize,
1168 const gl::Rectangle *scissor,
1169 GLenum destFormat,
1170 GLenum filter,
1171 bool maskOffAlpha,
1172 bool unpackPremultiplyAlpha,
1173 bool unpackUnmultiplyAlpha)
1174 {
1175 ANGLE_TRY(initResources());
1176
1177 HRESULT result;
1178 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1179
1180 // Determine if the source format is a signed integer format, the destFormat will already
1181 // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned.
1182 D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
1183 source->GetDesc(&sourceSRVDesc);
1184
1185 GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
1186
1187 ASSERT(componentType != GL_NONE);
1188 ASSERT(componentType != GL_SIGNED_NORMALIZED);
1189 bool isSigned = (componentType == GL_INT);
1190
1191 ShaderDimension dimension =
1192 (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D;
1193
1194 const Shader *shader = nullptr;
1195 ANGLE_TRY(getBlitShader(destFormat, isSigned, unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
1196 dimension, &shader));
1197
1198 const ShaderSupport &support = getShaderSupport(*shader);
1199
1200 // Set vertices
1201 D3D11_MAPPED_SUBRESOURCE mappedResource;
1202 result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
1203 if (FAILED(result))
1204 {
1205 return gl::Error(GL_OUT_OF_MEMORY,
1206 "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.",
1207 result);
1208 }
1209
1210 UINT stride = 0;
1211 UINT startIdx = 0;
1212 UINT drawCount = 0;
1213 D3D11_PRIMITIVE_TOPOLOGY topology;
1214
1215 support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
1216 &stride, &drawCount, &topology);
1217
1218 deviceContext->Unmap(mVertexBuffer, 0);
1219
1220 // Apply vertex buffer
1221 deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
1222
1223 // Apply state
1224 if (maskOffAlpha)
1225 {
1226 ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice());
1227 ASSERT(blendState);
1228 deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF);
1229 }
1230 else
1231 {
1232 deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
1233 }
1234 deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
1235
1236 if (scissor)
1237 {
1238 D3D11_RECT scissorRect;
1239 scissorRect.left = scissor->x;
1240 scissorRect.right = scissor->x + scissor->width;
1241 scissorRect.top = scissor->y;
1242 scissorRect.bottom = scissor->y + scissor->height;
1243
1244 deviceContext->RSSetScissorRects(1, &scissorRect);
1245 deviceContext->RSSetState(mScissorEnabledRasterizerState);
1246 }
1247 else
1248 {
1249 deviceContext->RSSetState(mScissorDisabledRasterizerState);
1250 }
1251
1252 // Apply shaders
1253 deviceContext->IASetInputLayout(support.inputLayout);
1254 deviceContext->IASetPrimitiveTopology(topology);
1255 deviceContext->VSSetShader(support.vertexShader, nullptr, 0);
1256
1257 deviceContext->PSSetShader(shader->pixelShader, nullptr, 0);
1258 deviceContext->GSSetShader(support.geometryShader, nullptr, 0);
1259
1260 // Unset the currently bound shader resource to avoid conflicts
1261 auto stateManager = mRenderer->getStateManager();
1262 stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
1263
1264 // Apply render target
1265 stateManager->setOneTimeRenderTarget(dest, nullptr);
1266
1267 // Set the viewport
1268 D3D11_VIEWPORT viewport;
1269 viewport.TopLeftX = 0;
1270 viewport.TopLeftY = 0;
1271 viewport.Width = static_cast<FLOAT>(destSize.width);
1272 viewport.Height = static_cast<FLOAT>(destSize.height);
1273 viewport.MinDepth = 0.0f;
1274 viewport.MaxDepth = 1.0f;
1275 deviceContext->RSSetViewports(1, &viewport);
1276
1277 // Apply textures
1278 stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
1279
1280 // Apply samplers
1281 ID3D11SamplerState *sampler = nullptr;
1282 switch (filter)
1283 {
1284 case GL_NEAREST:
1285 sampler = mPointSampler;
1286 break;
1287 case GL_LINEAR:
1288 sampler = mLinearSampler;
1289 break;
1290
1291 default:
1292 UNREACHABLE();
1293 return gl::Error(GL_OUT_OF_MEMORY, "Internal error, unknown blit filter mode.");
1294 }
1295 deviceContext->PSSetSamplers(0, 1, &sampler);
1296
1297 // Draw the quad
1298 deviceContext->Draw(drawCount, 0);
1299
1300 // Unbind textures and render targets and vertex buffer
1301 stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
1302
1303 UINT zero = 0;
1304 ID3D11Buffer *const nullBuffer = nullptr;
1305 deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
1306
1307 mRenderer->markAllStateDirty();
1308
1309 return gl::NoError();
1310 }
1311
copyStencil(const TextureHelper11 & source,unsigned int sourceSubresource,const gl::Box & sourceArea,const gl::Extents & sourceSize,const TextureHelper11 & dest,unsigned int destSubresource,const gl::Box & destArea,const gl::Extents & destSize,const gl::Rectangle * scissor)1312 gl::Error Blit11::copyStencil(const TextureHelper11 &source,
1313 unsigned int sourceSubresource,
1314 const gl::Box &sourceArea,
1315 const gl::Extents &sourceSize,
1316 const TextureHelper11 &dest,
1317 unsigned int destSubresource,
1318 const gl::Box &destArea,
1319 const gl::Extents &destSize,
1320 const gl::Rectangle *scissor)
1321 {
1322 return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest,
1323 destSubresource, destArea, destSize, scissor, true);
1324 }
1325
copyDepth(ID3D11ShaderResourceView * source,const gl::Box & sourceArea,const gl::Extents & sourceSize,ID3D11DepthStencilView * dest,const gl::Box & destArea,const gl::Extents & destSize,const gl::Rectangle * scissor)1326 gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source,
1327 const gl::Box &sourceArea,
1328 const gl::Extents &sourceSize,
1329 ID3D11DepthStencilView *dest,
1330 const gl::Box &destArea,
1331 const gl::Extents &destSize,
1332 const gl::Rectangle *scissor)
1333 {
1334 ANGLE_TRY(initResources());
1335
1336 HRESULT result;
1337 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1338
1339 // Set vertices
1340 D3D11_MAPPED_SUBRESOURCE mappedResource;
1341 result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
1342 if (FAILED(result))
1343 {
1344 return gl::Error(GL_OUT_OF_MEMORY,
1345 "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.",
1346 result);
1347 }
1348
1349 UINT stride = 0;
1350 UINT startIdx = 0;
1351 UINT drawCount = 0;
1352 D3D11_PRIMITIVE_TOPOLOGY topology;
1353
1354 Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride,
1355 &drawCount, &topology);
1356
1357 deviceContext->Unmap(mVertexBuffer, 0);
1358
1359 // Apply vertex buffer
1360 deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx);
1361
1362 // Apply state
1363 deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
1364 deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF);
1365
1366 if (scissor)
1367 {
1368 D3D11_RECT scissorRect;
1369 scissorRect.left = scissor->x;
1370 scissorRect.right = scissor->x + scissor->width;
1371 scissorRect.top = scissor->y;
1372 scissorRect.bottom = scissor->y + scissor->height;
1373
1374 deviceContext->RSSetScissorRects(1, &scissorRect);
1375 deviceContext->RSSetState(mScissorEnabledRasterizerState);
1376 }
1377 else
1378 {
1379 deviceContext->RSSetState(mScissorDisabledRasterizerState);
1380 }
1381
1382 ID3D11Device *device = mRenderer->getDevice();
1383 ID3D11VertexShader *quad2DVS = mQuad2DVS.resolve(device);
1384 if (quad2DVS == nullptr)
1385 {
1386 return gl::Error(GL_INVALID_OPERATION, "Error compiling internal 2D blit vertex shader");
1387 }
1388
1389 // Apply shaders
1390 deviceContext->IASetInputLayout(mQuad2DIL.resolve(device));
1391 deviceContext->IASetPrimitiveTopology(topology);
1392 deviceContext->VSSetShader(quad2DVS, nullptr, 0);
1393
1394 deviceContext->PSSetShader(mDepthPS.resolve(device), nullptr, 0);
1395 deviceContext->GSSetShader(nullptr, nullptr, 0);
1396
1397 // Unset the currently bound shader resource to avoid conflicts
1398 auto stateManager = mRenderer->getStateManager();
1399 stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
1400
1401 // Apply render target
1402 stateManager->setOneTimeRenderTarget(nullptr, dest);
1403
1404 // Set the viewport
1405 D3D11_VIEWPORT viewport;
1406 viewport.TopLeftX = 0;
1407 viewport.TopLeftY = 0;
1408 viewport.Width = static_cast<FLOAT>(destSize.width);
1409 viewport.Height = static_cast<FLOAT>(destSize.height);
1410 viewport.MinDepth = 0.0f;
1411 viewport.MaxDepth = 1.0f;
1412 deviceContext->RSSetViewports(1, &viewport);
1413
1414 // Apply textures
1415 stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source);
1416
1417 // Apply samplers
1418 deviceContext->PSSetSamplers(0, 1, &mPointSampler);
1419
1420 // Draw the quad
1421 deviceContext->Draw(drawCount, 0);
1422
1423 // Unbind textures and render targets and vertex buffer
1424 stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr);
1425
1426 UINT zero = 0;
1427 ID3D11Buffer *const nullBuffer = nullptr;
1428 deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero);
1429
1430 mRenderer->markAllStateDirty();
1431
1432 return gl::Error(GL_NO_ERROR);
1433 }
1434
copyDepthStencil(const TextureHelper11 & source,unsigned int sourceSubresource,const gl::Box & sourceArea,const gl::Extents & sourceSize,const TextureHelper11 & dest,unsigned int destSubresource,const gl::Box & destArea,const gl::Extents & destSize,const gl::Rectangle * scissor)1435 gl::Error Blit11::copyDepthStencil(const TextureHelper11 &source,
1436 unsigned int sourceSubresource,
1437 const gl::Box &sourceArea,
1438 const gl::Extents &sourceSize,
1439 const TextureHelper11 &dest,
1440 unsigned int destSubresource,
1441 const gl::Box &destArea,
1442 const gl::Extents &destSize,
1443 const gl::Rectangle *scissor)
1444 {
1445 return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest,
1446 destSubresource, destArea, destSize, scissor, false);
1447 }
1448
copyDepthStencilImpl(const TextureHelper11 & source,unsigned int sourceSubresource,const gl::Box & sourceArea,const gl::Extents & sourceSize,const TextureHelper11 & dest,unsigned int destSubresource,const gl::Box & destArea,const gl::Extents & destSize,const gl::Rectangle * scissor,bool stencilOnly)1449 gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source,
1450 unsigned int sourceSubresource,
1451 const gl::Box &sourceArea,
1452 const gl::Extents &sourceSize,
1453 const TextureHelper11 &dest,
1454 unsigned int destSubresource,
1455 const gl::Box &destArea,
1456 const gl::Extents &destSize,
1457 const gl::Rectangle *scissor,
1458 bool stencilOnly)
1459 {
1460 auto srcDXGIFormat = source.getFormat();
1461 const auto &srcSizeInfo = d3d11::GetDXGIFormatSizeInfo(srcDXGIFormat);
1462 unsigned int srcPixelSize = srcSizeInfo.pixelBytes;
1463 unsigned int copyOffset = 0;
1464 unsigned int copySize = srcPixelSize;
1465 auto destDXGIFormat = dest.getFormat();
1466 const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destDXGIFormat);
1467 unsigned int destPixelSize = destSizeInfo.pixelBytes;
1468
1469 ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS);
1470
1471 if (stencilOnly)
1472 {
1473 const auto &srcFormat = source.getFormatSet().format();
1474
1475 // Stencil channel should be right after the depth channel. Some views to depth/stencil
1476 // resources have red channel for depth, in which case the depth channel bit width is in
1477 // redBits.
1478 ASSERT((srcFormat.redBits != 0) != (srcFormat.depthBits != 0));
1479 GLuint depthBits = srcFormat.redBits + srcFormat.depthBits;
1480 // Known formats have either 24 or 32 bits of depth.
1481 ASSERT(depthBits == 24 || depthBits == 32);
1482 copyOffset = depthBits / 8;
1483
1484 // Stencil is assumed to be 8-bit - currently this is true for all possible formats.
1485 copySize = 1;
1486 }
1487
1488 if (srcDXGIFormat != destDXGIFormat)
1489 {
1490 if (srcDXGIFormat == DXGI_FORMAT_R24G8_TYPELESS)
1491 {
1492 ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr);
1493 return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest,
1494 destSubresource, destArea, destSize, scissor, copyOffset,
1495 copyOffset, copySize, srcPixelSize, destPixelSize,
1496 BlitD24S8ToD32F);
1497 }
1498 ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS);
1499 return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest,
1500 destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
1501 copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F);
1502 }
1503
1504 return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource,
1505 destArea, destSize, scissor, copyOffset, copyOffset, copySize,
1506 srcPixelSize, destPixelSize, StretchedBlitNearest);
1507 }
1508
copyAndConvertImpl(const TextureHelper11 & source,unsigned int sourceSubresource,const gl::Box & sourceArea,const gl::Extents & sourceSize,const TextureHelper11 & destStaging,const gl::Box & destArea,const gl::Extents & destSize,const gl::Rectangle * scissor,size_t readOffset,size_t writeOffset,size_t copySize,size_t srcPixelStride,size_t destPixelStride,BlitConvertFunction * convertFunction)1509 gl::Error Blit11::copyAndConvertImpl(const TextureHelper11 &source,
1510 unsigned int sourceSubresource,
1511 const gl::Box &sourceArea,
1512 const gl::Extents &sourceSize,
1513 const TextureHelper11 &destStaging,
1514 const gl::Box &destArea,
1515 const gl::Extents &destSize,
1516 const gl::Rectangle *scissor,
1517 size_t readOffset,
1518 size_t writeOffset,
1519 size_t copySize,
1520 size_t srcPixelStride,
1521 size_t destPixelStride,
1522 BlitConvertFunction *convertFunction)
1523 {
1524 ANGLE_TRY(initResources());
1525
1526 ID3D11Device *device = mRenderer->getDevice();
1527 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1528
1529 TextureHelper11 sourceStaging;
1530 ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, source.getFormatSet(), sourceSize,
1531 StagingAccess::READ, device),
1532 sourceStaging);
1533
1534 deviceContext->CopySubresourceRegion(sourceStaging.getResource(), 0, 0, 0, 0,
1535 source.getResource(), sourceSubresource, nullptr);
1536
1537 D3D11_MAPPED_SUBRESOURCE sourceMapping;
1538 HRESULT result =
1539 deviceContext->Map(sourceStaging.getResource(), 0, D3D11_MAP_READ, 0, &sourceMapping);
1540 if (FAILED(result))
1541 {
1542 return gl::Error(
1543 GL_OUT_OF_MEMORY,
1544 "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.",
1545 result);
1546 }
1547
1548 D3D11_MAPPED_SUBRESOURCE destMapping;
1549 result = deviceContext->Map(destStaging.getResource(), 0, D3D11_MAP_WRITE, 0, &destMapping);
1550 if (FAILED(result))
1551 {
1552 deviceContext->Unmap(sourceStaging.getResource(), 0);
1553 return gl::Error(GL_OUT_OF_MEMORY,
1554 "Failed to map internal destination staging texture for depth stencil "
1555 "blit, HRESULT: 0x%X.",
1556 result);
1557 }
1558
1559 // Clip dest area to the destination size
1560 gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height);
1561
1562 // Clip dest area to the scissor
1563 if (scissor)
1564 {
1565 gl::ClipRectangle(clipRect, *scissor, &clipRect);
1566 }
1567
1568 convertFunction(sourceArea, destArea, clipRect, sourceSize, sourceMapping.RowPitch,
1569 destMapping.RowPitch, readOffset, writeOffset, copySize, srcPixelStride,
1570 destPixelStride, static_cast<const uint8_t *>(sourceMapping.pData),
1571 static_cast<uint8_t *>(destMapping.pData));
1572
1573 deviceContext->Unmap(sourceStaging.getResource(), 0);
1574 deviceContext->Unmap(destStaging.getResource(), 0);
1575
1576 return gl::NoError();
1577 }
1578
copyAndConvert(const TextureHelper11 & source,unsigned int sourceSubresource,const gl::Box & sourceArea,const gl::Extents & sourceSize,const TextureHelper11 & dest,unsigned int destSubresource,const gl::Box & destArea,const gl::Extents & destSize,const gl::Rectangle * scissor,size_t readOffset,size_t writeOffset,size_t copySize,size_t srcPixelStride,size_t destPixelStride,BlitConvertFunction * convertFunction)1579 gl::Error Blit11::copyAndConvert(const TextureHelper11 &source,
1580 unsigned int sourceSubresource,
1581 const gl::Box &sourceArea,
1582 const gl::Extents &sourceSize,
1583 const TextureHelper11 &dest,
1584 unsigned int destSubresource,
1585 const gl::Box &destArea,
1586 const gl::Extents &destSize,
1587 const gl::Rectangle *scissor,
1588 size_t readOffset,
1589 size_t writeOffset,
1590 size_t copySize,
1591 size_t srcPixelStride,
1592 size_t destPixelStride,
1593 BlitConvertFunction *convertFunction)
1594 {
1595 ANGLE_TRY(initResources());
1596
1597 ID3D11Device *device = mRenderer->getDevice();
1598 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1599
1600 // HACK: Create the destination staging buffer as a read/write texture so
1601 // ID3D11DevicContext::UpdateSubresource can be called
1602 // using it's mapped data as a source
1603 TextureHelper11 destStaging;
1604 ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, dest.getFormatSet(), destSize,
1605 StagingAccess::READ_WRITE, device),
1606 destStaging);
1607
1608 deviceContext->CopySubresourceRegion(destStaging.getResource(), 0, 0, 0, 0, dest.getResource(),
1609 destSubresource, nullptr);
1610
1611 copyAndConvertImpl(source, sourceSubresource, sourceArea, sourceSize, destStaging, destArea,
1612 destSize, scissor, readOffset, writeOffset, copySize, srcPixelStride,
1613 destPixelStride, convertFunction);
1614
1615 // Work around timeouts/TDRs in older NVIDIA drivers.
1616 if (mRenderer->getWorkarounds().depthStencilBlitExtraCopy)
1617 {
1618 D3D11_MAPPED_SUBRESOURCE mapped;
1619 deviceContext->Map(destStaging.getResource(), 0, D3D11_MAP_READ, 0, &mapped);
1620 deviceContext->UpdateSubresource(dest.getResource(), destSubresource, nullptr, mapped.pData,
1621 mapped.RowPitch, mapped.DepthPitch);
1622 deviceContext->Unmap(destStaging.getResource(), 0);
1623 }
1624 else
1625 {
1626 deviceContext->CopySubresourceRegion(dest.getResource(), destSubresource, 0, 0, 0,
1627 destStaging.getResource(), 0, nullptr);
1628 }
1629
1630 return gl::NoError();
1631 }
1632
addBlitShaderToMap(BlitShaderType blitShaderType,ShaderDimension dimension,ID3D11PixelShader * ps)1633 void Blit11::addBlitShaderToMap(BlitShaderType blitShaderType,
1634 ShaderDimension dimension,
1635 ID3D11PixelShader *ps)
1636 {
1637 ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end());
1638 ASSERT(ps);
1639
1640 Shader shader;
1641 shader.dimension = dimension;
1642 shader.pixelShader = ps;
1643
1644 mBlitShaderMap[blitShaderType] = shader;
1645 }
1646
addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType,ShaderDimension dimension,ID3D11PixelShader * ps)1647 void Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType,
1648 ShaderDimension dimension,
1649 ID3D11PixelShader *ps)
1650 {
1651 ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end());
1652 ASSERT(ps);
1653
1654 Shader shader;
1655 shader.dimension = dimension;
1656 shader.pixelShader = ps;
1657
1658 mSwizzleShaderMap[swizzleShaderType] = shader;
1659 }
1660
clearShaderMap()1661 void Blit11::clearShaderMap()
1662 {
1663 for (auto &blitShader : mBlitShaderMap)
1664 {
1665 SafeRelease(blitShader.second.pixelShader);
1666 }
1667 mBlitShaderMap.clear();
1668
1669 for (auto &swizzleShader : mSwizzleShaderMap)
1670 {
1671 SafeRelease(swizzleShader.second.pixelShader);
1672 }
1673 mSwizzleShaderMap.clear();
1674 }
1675
getBlitShader(GLenum destFormat,bool isSigned,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,ShaderDimension dimension,const Shader ** shader)1676 gl::Error Blit11::getBlitShader(GLenum destFormat,
1677 bool isSigned,
1678 bool unpackPremultiplyAlpha,
1679 bool unpackUnmultiplyAlpha,
1680 ShaderDimension dimension,
1681 const Shader **shader)
1682 {
1683 BlitShaderType blitShaderType = GetBlitShaderType(destFormat, isSigned, unpackPremultiplyAlpha,
1684 unpackUnmultiplyAlpha, dimension);
1685
1686 if (blitShaderType == BLITSHADER_INVALID)
1687 {
1688 return gl::Error(GL_INVALID_OPERATION, "Internal blit shader type mismatch");
1689 }
1690
1691 auto blitShaderIt = mBlitShaderMap.find(blitShaderType);
1692 if (blitShaderIt != mBlitShaderMap.end())
1693 {
1694 *shader = &blitShaderIt->second;
1695 return gl::Error(GL_NO_ERROR);
1696 }
1697
1698 ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable());
1699
1700 ID3D11Device *device = mRenderer->getDevice();
1701
1702 switch (blitShaderType)
1703 {
1704 case BLITSHADER_2D_RGBAF:
1705 addBlitShaderToMap(
1706 blitShaderType, SHADER_2D,
1707 d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader"));
1708 break;
1709 case BLITSHADER_2D_RGBAF_PREMULTIPLY:
1710 addBlitShaderToMap(blitShaderType, SHADER_2D,
1711 d3d11::CompilePS(device, g_PS_PassthroughRGBAPremultiply2D,
1712 "Blit11 2D RGBA premultiply pixel shader"));
1713 break;
1714 case BLITSHADER_2D_RGBAF_UNMULTIPLY:
1715 addBlitShaderToMap(blitShaderType, SHADER_2D,
1716 d3d11::CompilePS(device, g_PS_PassthroughRGBAUnmultiply2D,
1717 "Blit11 2D RGBA unmultiply pixel shader"));
1718 break;
1719 case BLITSHADER_2D_BGRAF:
1720 addBlitShaderToMap(
1721 blitShaderType, SHADER_2D,
1722 d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader"));
1723 break;
1724 case BLITSHADER_2D_BGRAF_PREMULTIPLY:
1725 addBlitShaderToMap(blitShaderType, SHADER_2D,
1726 d3d11::CompilePS(device, g_PS_PassthroughRGBAPremultiply2D,
1727 "Blit11 2D BGRA premultiply pixel shader"));
1728 break;
1729 case BLITSHADER_2D_BGRAF_UNMULTIPLY:
1730 addBlitShaderToMap(blitShaderType, SHADER_2D,
1731 d3d11::CompilePS(device, g_PS_PassthroughRGBAUnmultiply2D,
1732 "Blit11 2D BGRA unmultiply pixel shader"));
1733 break;
1734 case BLITSHADER_2D_RGBF:
1735 addBlitShaderToMap(
1736 blitShaderType, SHADER_2D,
1737 d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader"));
1738 break;
1739 case BLITSHADER_2D_RGBF_PREMULTIPLY:
1740 addBlitShaderToMap(blitShaderType, SHADER_2D,
1741 d3d11::CompilePS(device, g_PS_PassthroughRGBPremultiply2D,
1742 "Blit11 2D RGB premultiply pixel shader"));
1743 break;
1744 case BLITSHADER_2D_RGBF_UNMULTIPLY:
1745 addBlitShaderToMap(blitShaderType, SHADER_2D,
1746 d3d11::CompilePS(device, g_PS_PassthroughRGBUnmultiply2D,
1747 "Blit11 2D RGB unmultiply pixel shader"));
1748 break;
1749 case BLITSHADER_2D_RGF:
1750 addBlitShaderToMap(
1751 blitShaderType, SHADER_2D,
1752 d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader"));
1753 break;
1754 case BLITSHADER_2D_RF:
1755 addBlitShaderToMap(
1756 blitShaderType, SHADER_2D,
1757 d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader"));
1758 break;
1759 case BLITSHADER_2D_ALPHA:
1760 addBlitShaderToMap(
1761 blitShaderType, SHADER_2D,
1762 d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader"));
1763 break;
1764 case BLITSHADER_2D_LUMA:
1765 addBlitShaderToMap(
1766 blitShaderType, SHADER_2D,
1767 d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader"));
1768 break;
1769 case BLITSHADER_2D_LUMAALPHA:
1770 addBlitShaderToMap(blitShaderType, SHADER_2D,
1771 d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D,
1772 "Blit11 2D luminance alpha pixel shader"));
1773 break;
1774 case BLITSHADER_2D_RGBAUI:
1775 addBlitShaderToMap(blitShaderType, SHADER_2D,
1776 d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI,
1777 "Blit11 2D RGBA UI pixel shader"));
1778 break;
1779 case BLITSHADER_2D_RGBAI:
1780 addBlitShaderToMap(
1781 blitShaderType, SHADER_2D,
1782 d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader"));
1783 break;
1784 case BLITSHADER_2D_RGBUI:
1785 addBlitShaderToMap(
1786 blitShaderType, SHADER_2D,
1787 d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader"));
1788 break;
1789 case BLITSHADER_2D_RGBI:
1790 addBlitShaderToMap(
1791 blitShaderType, SHADER_2D,
1792 d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader"));
1793 break;
1794 case BLITSHADER_2D_RGUI:
1795 addBlitShaderToMap(
1796 blitShaderType, SHADER_2D,
1797 d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader"));
1798 break;
1799 case BLITSHADER_2D_RGI:
1800 addBlitShaderToMap(
1801 blitShaderType, SHADER_2D,
1802 d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader"));
1803 break;
1804 case BLITSHADER_2D_RUI:
1805 addBlitShaderToMap(
1806 blitShaderType, SHADER_2D,
1807 d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader"));
1808 break;
1809 case BLITSHADER_2D_RI:
1810 addBlitShaderToMap(
1811 blitShaderType, SHADER_2D,
1812 d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader"));
1813 break;
1814 case BLITSHADER_3D_RGBAF:
1815 addBlitShaderToMap(
1816 blitShaderType, SHADER_3D,
1817 d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader"));
1818 break;
1819 case BLITSHADER_3D_RGBAUI:
1820 addBlitShaderToMap(blitShaderType, SHADER_3D,
1821 d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI,
1822 "Blit11 3D UI RGBA pixel shader"));
1823 break;
1824 case BLITSHADER_3D_RGBAI:
1825 addBlitShaderToMap(
1826 blitShaderType, SHADER_3D,
1827 d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader"));
1828 break;
1829 case BLITSHADER_3D_BGRAF:
1830 addBlitShaderToMap(
1831 blitShaderType, SHADER_3D,
1832 d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader"));
1833 break;
1834 case BLITSHADER_3D_RGBF:
1835 addBlitShaderToMap(
1836 blitShaderType, SHADER_3D,
1837 d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader"));
1838 break;
1839 case BLITSHADER_3D_RGBUI:
1840 addBlitShaderToMap(
1841 blitShaderType, SHADER_3D,
1842 d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader"));
1843 break;
1844 case BLITSHADER_3D_RGBI:
1845 addBlitShaderToMap(
1846 blitShaderType, SHADER_3D,
1847 d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader"));
1848 break;
1849 case BLITSHADER_3D_RGF:
1850 addBlitShaderToMap(
1851 blitShaderType, SHADER_3D,
1852 d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader"));
1853 break;
1854 case BLITSHADER_3D_RGUI:
1855 addBlitShaderToMap(
1856 blitShaderType, SHADER_3D,
1857 d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader"));
1858 break;
1859 case BLITSHADER_3D_RGI:
1860 addBlitShaderToMap(
1861 blitShaderType, SHADER_3D,
1862 d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader"));
1863 break;
1864 case BLITSHADER_3D_RF:
1865 addBlitShaderToMap(
1866 blitShaderType, SHADER_3D,
1867 d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader"));
1868 break;
1869 case BLITSHADER_3D_RUI:
1870 addBlitShaderToMap(
1871 blitShaderType, SHADER_3D,
1872 d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader"));
1873 break;
1874 case BLITSHADER_3D_RI:
1875 addBlitShaderToMap(
1876 blitShaderType, SHADER_3D,
1877 d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader"));
1878 break;
1879 case BLITSHADER_3D_ALPHA:
1880 addBlitShaderToMap(
1881 blitShaderType, SHADER_3D,
1882 d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader"));
1883 break;
1884 case BLITSHADER_3D_LUMA:
1885 addBlitShaderToMap(blitShaderType, SHADER_3D,
1886 d3d11::CompilePS(device, g_PS_PassthroughLum3D,
1887 "Blit11 3D luminance pixel shader"));
1888 break;
1889 case BLITSHADER_3D_LUMAALPHA:
1890 addBlitShaderToMap(blitShaderType, SHADER_3D,
1891 d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D,
1892 "Blit11 3D luminance alpha pixel shader"));
1893 break;
1894 default:
1895 UNREACHABLE();
1896 return gl::Error(GL_INVALID_OPERATION, "Internal error");
1897 }
1898
1899 blitShaderIt = mBlitShaderMap.find(blitShaderType);
1900 ASSERT(blitShaderIt != mBlitShaderMap.end());
1901 *shader = &blitShaderIt->second;
1902 return gl::Error(GL_NO_ERROR);
1903 }
1904
getSwizzleShader(GLenum type,D3D11_SRV_DIMENSION viewDimension,const Shader ** shader)1905 gl::Error Blit11::getSwizzleShader(GLenum type,
1906 D3D11_SRV_DIMENSION viewDimension,
1907 const Shader **shader)
1908 {
1909 SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension);
1910
1911 if (swizzleShaderType == SWIZZLESHADER_INVALID)
1912 {
1913 return gl::Error(GL_INVALID_OPERATION, "Swizzle shader type not found");
1914 }
1915
1916 auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
1917 if (swizzleShaderIt != mSwizzleShaderMap.end())
1918 {
1919 *shader = &swizzleShaderIt->second;
1920 return gl::Error(GL_NO_ERROR);
1921 }
1922
1923 // Swizzling shaders (OpenGL ES 3+)
1924 ASSERT(mRenderer->isES3Capable());
1925
1926 ID3D11Device *device = mRenderer->getDevice();
1927
1928 switch (swizzleShaderType)
1929 {
1930 case SWIZZLESHADER_2D_FLOAT:
1931 addSwizzleShaderToMap(
1932 swizzleShaderType, SHADER_2D,
1933 d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader"));
1934 break;
1935 case SWIZZLESHADER_2D_UINT:
1936 addSwizzleShaderToMap(
1937 swizzleShaderType, SHADER_2D,
1938 d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader"));
1939 break;
1940 case SWIZZLESHADER_2D_INT:
1941 addSwizzleShaderToMap(
1942 swizzleShaderType, SHADER_2D,
1943 d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader"));
1944 break;
1945 case SWIZZLESHADER_CUBE_FLOAT:
1946 addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
1947 d3d11::CompilePS(device, g_PS_SwizzleF2DArray,
1948 "Blit11 2D Cube F swizzle pixel shader"));
1949 break;
1950 case SWIZZLESHADER_CUBE_UINT:
1951 addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
1952 d3d11::CompilePS(device, g_PS_SwizzleUI2DArray,
1953 "Blit11 2D Cube UI swizzle pixel shader"));
1954 break;
1955 case SWIZZLESHADER_CUBE_INT:
1956 addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
1957 d3d11::CompilePS(device, g_PS_SwizzleI2DArray,
1958 "Blit11 2D Cube I swizzle pixel shader"));
1959 break;
1960 case SWIZZLESHADER_3D_FLOAT:
1961 addSwizzleShaderToMap(
1962 swizzleShaderType, SHADER_3D,
1963 d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader"));
1964 break;
1965 case SWIZZLESHADER_3D_UINT:
1966 addSwizzleShaderToMap(
1967 swizzleShaderType, SHADER_3D,
1968 d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader"));
1969 break;
1970 case SWIZZLESHADER_3D_INT:
1971 addSwizzleShaderToMap(
1972 swizzleShaderType, SHADER_3D,
1973 d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader"));
1974 break;
1975 case SWIZZLESHADER_ARRAY_FLOAT:
1976 addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
1977 d3d11::CompilePS(device, g_PS_SwizzleF2DArray,
1978 "Blit11 2D Array F swizzle pixel shader"));
1979 break;
1980 case SWIZZLESHADER_ARRAY_UINT:
1981 addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
1982 d3d11::CompilePS(device, g_PS_SwizzleUI2DArray,
1983 "Blit11 2D Array UI swizzle pixel shader"));
1984 break;
1985 case SWIZZLESHADER_ARRAY_INT:
1986 addSwizzleShaderToMap(swizzleShaderType, SHADER_3D,
1987 d3d11::CompilePS(device, g_PS_SwizzleI2DArray,
1988 "Blit11 2D Array I swizzle pixel shader"));
1989 break;
1990 default:
1991 UNREACHABLE();
1992 return gl::Error(GL_INVALID_OPERATION, "Internal error");
1993 }
1994
1995 swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
1996 ASSERT(swizzleShaderIt != mSwizzleShaderMap.end());
1997 *shader = &swizzleShaderIt->second;
1998 return gl::NoError();
1999 }
2000
resolveDepth(RenderTarget11 * depth)2001 gl::ErrorOrResult<TextureHelper11> Blit11::resolveDepth(RenderTarget11 *depth)
2002 {
2003 // Multisampled depth stencil SRVs are not available in feature level 10.0
2004 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
2005 {
2006 return gl::Error(GL_INVALID_OPERATION,
2007 "Resolving multisampled depth stencil textures is not supported in "
2008 "feature level 10.0.");
2009 }
2010
2011 const auto &extents = depth->getExtents();
2012 ID3D11Device *device = mRenderer->getDevice();
2013 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
2014
2015 ANGLE_TRY(initResolveDepthStencil(extents));
2016
2017 // Notify the Renderer that all state should be invalidated.
2018 mRenderer->markAllStateDirty();
2019
2020 // Apply the necessary state changes to the D3D11 immediate device context.
2021 context->IASetInputLayout(nullptr);
2022 context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
2023 context->VSSetShader(mResolveDepthStencilVS.resolve(device), nullptr, 0);
2024 context->GSSetShader(nullptr, nullptr, 0);
2025 context->RSSetState(nullptr);
2026 context->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
2027 context->OMSetRenderTargets(1, &mResolvedDepthStencilRTView, nullptr);
2028 context->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
2029
2030 // Set the viewport
2031 D3D11_VIEWPORT viewport;
2032 viewport.TopLeftX = 0;
2033 viewport.TopLeftY = 0;
2034 viewport.Width = static_cast<FLOAT>(extents.width);
2035 viewport.Height = static_cast<FLOAT>(extents.height);
2036 viewport.MinDepth = 0.0f;
2037 viewport.MaxDepth = 1.0f;
2038 context->RSSetViewports(1, &viewport);
2039
2040 ID3D11ShaderResourceView *pixelViews[] = {depth->getShaderResourceView()};
2041
2042 context->PSSetShaderResources(0, 1, pixelViews);
2043
2044 context->PSSetShader(mResolveDepthPS.resolve(device), nullptr, 0);
2045
2046 // Trigger the blit on the GPU.
2047 context->Draw(6, 0);
2048
2049 gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
2050
2051 const auto ©Function = GetCopyDepthStencilFunction(depth->getInternalFormat());
2052 const auto &dsFormatSet = depth->getFormatSet();
2053 const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
2054
2055 ID3D11Texture2D *destTex = nullptr;
2056
2057 D3D11_TEXTURE2D_DESC destDesc;
2058 destDesc.Width = extents.width;
2059 destDesc.Height = extents.height;
2060 destDesc.MipLevels = 1;
2061 destDesc.ArraySize = 1;
2062 destDesc.Format = dsFormatSet.texFormat;
2063 destDesc.SampleDesc.Count = 1;
2064 destDesc.SampleDesc.Quality = 0;
2065 destDesc.Usage = D3D11_USAGE_DEFAULT;
2066 destDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
2067 destDesc.CPUAccessFlags = 0;
2068 destDesc.MiscFlags = 0;
2069
2070 HRESULT hr = device->CreateTexture2D(&destDesc, nullptr, &destTex);
2071 if (FAILED(hr))
2072 {
2073 return gl::Error(GL_OUT_OF_MEMORY, "Error creating depth resolve dest texture.");
2074 }
2075 d3d11::SetDebugName(destTex, "resolveDepthDest");
2076
2077 TextureHelper11 dest = TextureHelper11::MakeAndPossess2D(destTex, depth->getFormatSet());
2078 ANGLE_TRY(copyAndConvert(mResolvedDepthStencil, 0, copyBox, extents, dest, 0, copyBox, extents,
2079 nullptr, 0, 0, 0, 8, dsDxgiInfo.pixelBytes, copyFunction));
2080 return dest;
2081 }
2082
initResolveDepthStencil(const gl::Extents & extents)2083 gl::Error Blit11::initResolveDepthStencil(const gl::Extents &extents)
2084 {
2085 // Check if we need to recreate depth stencil view
2086 if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents())
2087 {
2088 return gl::NoError();
2089 }
2090
2091 if (mResolvedDepthStencil.valid())
2092 {
2093 releaseResolveDepthStencilResources();
2094 }
2095
2096 const auto &formatSet = d3d11::Format::Get(GL_RG32F, mRenderer->getRenderer11DeviceCaps());
2097
2098 D3D11_TEXTURE2D_DESC textureDesc;
2099 textureDesc.Width = extents.width;
2100 textureDesc.Height = extents.height;
2101 textureDesc.MipLevels = 1;
2102 textureDesc.ArraySize = 1;
2103 textureDesc.Format = formatSet.texFormat;
2104 textureDesc.SampleDesc.Count = 1;
2105 textureDesc.SampleDesc.Quality = 0;
2106 textureDesc.Usage = D3D11_USAGE_DEFAULT;
2107 textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
2108 textureDesc.CPUAccessFlags = 0;
2109 textureDesc.MiscFlags = 0;
2110
2111 ID3D11Device *device = mRenderer->getDevice();
2112
2113 ID3D11Texture2D *resolvedDepthStencil = nullptr;
2114 HRESULT hr = device->CreateTexture2D(&textureDesc, nullptr, &resolvedDepthStencil);
2115 if (FAILED(hr))
2116 {
2117 return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate resolved depth stencil texture");
2118 }
2119 d3d11::SetDebugName(resolvedDepthStencil, "Blit11::mResolvedDepthStencil");
2120
2121 ASSERT(mResolvedDepthStencilRTView == nullptr);
2122 hr =
2123 device->CreateRenderTargetView(resolvedDepthStencil, nullptr, &mResolvedDepthStencilRTView);
2124 if (FAILED(hr))
2125 {
2126 return gl::Error(GL_OUT_OF_MEMORY,
2127 "Failed to allocate Blit11::mResolvedDepthStencilRTView");
2128 }
2129 d3d11::SetDebugName(mResolvedDepthStencilRTView, "Blit11::mResolvedDepthStencilRTView");
2130
2131 mResolvedDepthStencil = TextureHelper11::MakeAndPossess2D(resolvedDepthStencil, formatSet);
2132
2133 return gl::NoError();
2134 }
2135
resolveStencil(RenderTarget11 * depthStencil,bool alsoDepth)2136 gl::ErrorOrResult<TextureHelper11> Blit11::resolveStencil(RenderTarget11 *depthStencil,
2137 bool alsoDepth)
2138 {
2139 // Multisampled depth stencil SRVs are not available in feature level 10.0
2140 if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0)
2141 {
2142 return gl::Error(GL_INVALID_OPERATION,
2143 "Resolving multisampled depth stencil textures is not supported in "
2144 "feature level 10.0.");
2145 }
2146
2147 const auto &extents = depthStencil->getExtents();
2148
2149 ANGLE_TRY(initResolveDepthStencil(extents));
2150
2151 ID3D11Device *device = mRenderer->getDevice();
2152 ID3D11DeviceContext *context = mRenderer->getDeviceContext();
2153
2154 ID3D11Resource *stencilResource = depthStencil->getTexture();
2155
2156 // Check if we need to re-create the stencil SRV.
2157 if (mStencilSRV)
2158 {
2159 ID3D11Resource *priorResource = nullptr;
2160 mStencilSRV->GetResource(&priorResource);
2161
2162 if (stencilResource != priorResource)
2163 {
2164 SafeRelease(mStencilSRV);
2165 }
2166 }
2167
2168 if (!mStencilSRV)
2169 {
2170 D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc;
2171 srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet());
2172 srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
2173
2174 HRESULT hr = device->CreateShaderResourceView(stencilResource, &srViewDesc, &mStencilSRV);
2175 if (FAILED(hr))
2176 {
2177 return gl::Error(GL_OUT_OF_MEMORY, "Error creating Blit11 stencil SRV");
2178 }
2179 d3d11::SetDebugName(mStencilSRV, "Blit11::mStencilSRV");
2180 }
2181
2182 // Notify the Renderer that all state should be invalidated.
2183 mRenderer->markAllStateDirty();
2184
2185 // Apply the necessary state changes to the D3D11 immediate device context.
2186 context->IASetInputLayout(nullptr);
2187 context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
2188 context->VSSetShader(mResolveDepthStencilVS.resolve(device), nullptr, 0);
2189 context->GSSetShader(nullptr, nullptr, 0);
2190 context->RSSetState(nullptr);
2191 context->OMSetDepthStencilState(nullptr, 0xFFFFFFFF);
2192 context->OMSetRenderTargets(1, &mResolvedDepthStencilRTView, nullptr);
2193 context->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF);
2194
2195 // Set the viewport
2196 D3D11_VIEWPORT viewport;
2197 viewport.TopLeftX = 0;
2198 viewport.TopLeftY = 0;
2199 viewport.Width = static_cast<FLOAT>(extents.width);
2200 viewport.Height = static_cast<FLOAT>(extents.height);
2201 viewport.MinDepth = 0.0f;
2202 viewport.MaxDepth = 1.0f;
2203 context->RSSetViewports(1, &viewport);
2204
2205 ID3D11ShaderResourceView *pixelViews[] = {
2206 depthStencil->getShaderResourceView(), mStencilSRV,
2207 };
2208
2209 context->PSSetShaderResources(0, 2, pixelViews);
2210
2211 // Resolving the depth buffer works by sampling the depth in the shader using a SRV, then
2212 // writing to the resolved depth buffer using SV_Depth. We can't use this method for stencil
2213 // because SV_StencilRef isn't supported until HLSL 5.1/D3D11.3.
2214 if (alsoDepth)
2215 {
2216 context->PSSetShader(mResolveDepthStencilPS.resolve(device), nullptr, 0);
2217 }
2218 else
2219 {
2220 context->PSSetShader(mResolveStencilPS.resolve(device), nullptr, 0);
2221 }
2222
2223 // Trigger the blit on the GPU.
2224 context->Draw(6, 0);
2225
2226 gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
2227
2228 TextureHelper11 dest;
2229 ANGLE_TRY_RESULT(CreateStagingTexture(GL_TEXTURE_2D, depthStencil->getFormatSet(), extents,
2230 StagingAccess::READ_WRITE, device),
2231 dest);
2232
2233 const auto ©Function = GetCopyDepthStencilFunction(depthStencil->getInternalFormat());
2234 const auto &dsFormatSet = depthStencil->getFormatSet();
2235 const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
2236
2237 ANGLE_TRY(copyAndConvertImpl(mResolvedDepthStencil, 0, copyBox, extents, dest, copyBox, extents,
2238 nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes, copyFunction));
2239
2240 // Return the resolved depth texture, which the caller must Release.
2241 return dest;
2242 }
2243
releaseResolveDepthStencilResources()2244 void Blit11::releaseResolveDepthStencilResources()
2245 {
2246 SafeRelease(mStencilSRV);
2247 SafeRelease(mResolvedDepthStencilRTView);
2248 }
2249
2250 } // namespace rx
2251