1 //
2 // Copyright 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 "common/utilities.h"
14 #include "libANGLE/Context.h"
15 #include "libANGLE/formatutils.h"
16 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
17 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
18 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
19 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
20 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
21 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
22 #include "libANGLE/trace.h"
23
24 namespace rx
25 {
26
27 namespace
28 {
29
30 // Include inline shaders in the anonymous namespace to make sure no symbols are exported
31 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
32 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
33
34 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
35 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
36
37 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h"
38 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h"
39 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h"
40 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h"
41
42 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
43 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
44 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
45 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
46 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
47 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
48 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
49 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
50 #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
51
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)52 void StretchedBlitNearest_RowByRow(const gl::Box &sourceArea,
53 const gl::Box &destArea,
54 const gl::Rectangle &clippedDestArea,
55 const gl::Extents &sourceSize,
56 unsigned int sourceRowPitch,
57 unsigned int destRowPitch,
58 size_t pixelSize,
59 const uint8_t *sourceData,
60 uint8_t *destData)
61 {
62 int srcHeightSubOne = (sourceArea.height - 1);
63 size_t copySize = pixelSize * clippedDestArea.width;
64 size_t srcOffset = sourceArea.x * pixelSize;
65 size_t destOffset = clippedDestArea.x * pixelSize;
66
67 for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++)
68 {
69 // TODO: Fix divide by zero when height == 1. http://anglebug.com/6099
70 float yPerc = static_cast<float>(y - destArea.y) / (destArea.height - 1);
71
72 // Interpolate using the original source rectangle to determine which row to sample from
73 // while clamping to the edges
74 unsigned int readRow = static_cast<unsigned int>(
75 gl::clamp(sourceArea.y + floor(yPerc * srcHeightSubOne + 0.5f), 0, srcHeightSubOne));
76 unsigned int writeRow = y;
77
78 const uint8_t *sourceRow = sourceData + readRow * sourceRowPitch + srcOffset;
79 uint8_t *destRow = destData + writeRow * destRowPitch + destOffset;
80 memcpy(destRow, sourceRow, copySize);
81 }
82 }
83
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)84 void StretchedBlitNearest_PixelByPixel(const gl::Box &sourceArea,
85 const gl::Box &destArea,
86 const gl::Rectangle &clippedDestArea,
87 const gl::Extents &sourceSize,
88 unsigned int sourceRowPitch,
89 unsigned int destRowPitch,
90 ptrdiff_t readOffset,
91 ptrdiff_t writeOffset,
92 size_t copySize,
93 size_t srcPixelStride,
94 size_t destPixelStride,
95 const uint8_t *sourceData,
96 uint8_t *destData)
97 {
98 auto xMax = clippedDestArea.x + clippedDestArea.width;
99 auto yMax = clippedDestArea.y + clippedDestArea.height;
100
101 for (int writeRow = clippedDestArea.y; writeRow < yMax; writeRow++)
102 {
103 // Interpolate using the original source rectangle to determine which row to sample from
104 // while clamping to the edges
105 float yPerc = static_cast<float>(writeRow - destArea.y) / (destArea.height - 1);
106 float yRounded = floor(yPerc * (sourceArea.height - 1) + 0.5f);
107 unsigned int readRow =
108 static_cast<unsigned int>(gl::clamp(sourceArea.y + yRounded, 0, sourceSize.height - 1));
109
110 for (int writeColumn = clippedDestArea.x; writeColumn < xMax; writeColumn++)
111 {
112 // Interpolate the original source rectangle to determine which column to sample
113 // from while clamping to the edges
114 float xPerc = static_cast<float>(writeColumn - destArea.x) / (destArea.width - 1);
115 float xRounded = floor(xPerc * (sourceArea.width - 1) + 0.5f);
116 unsigned int readColumn = static_cast<unsigned int>(
117 gl::clamp(sourceArea.x + xRounded, 0, sourceSize.width - 1));
118
119 const uint8_t *sourcePixel =
120 sourceData + readRow * sourceRowPitch + readColumn * srcPixelStride + readOffset;
121
122 uint8_t *destPixel =
123 destData + writeRow * destRowPitch + writeColumn * destPixelStride + writeOffset;
124
125 memcpy(destPixel, sourcePixel, copySize);
126 }
127 }
128 }
129
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)130 void StretchedBlitNearest(const gl::Box &sourceArea,
131 const gl::Box &destArea,
132 const gl::Rectangle &clipRect,
133 const gl::Extents &sourceSize,
134 unsigned int sourceRowPitch,
135 unsigned int destRowPitch,
136 ptrdiff_t readOffset,
137 ptrdiff_t writeOffset,
138 size_t copySize,
139 size_t srcPixelStride,
140 size_t destPixelStride,
141 const uint8_t *sourceData,
142 uint8_t *destData)
143 {
144 gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height);
145 if (!gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea))
146 {
147 return;
148 }
149
150 // Determine if entire rows can be copied at once instead of each individual pixel. There
151 // must be no out of bounds lookups, whole rows copies, and no scale.
152 if (sourceArea.width == clippedDestArea.width && sourceArea.x >= 0 &&
153 sourceArea.x + sourceArea.width <= sourceSize.width && copySize == srcPixelStride &&
154 copySize == destPixelStride)
155 {
156 StretchedBlitNearest_RowByRow(sourceArea, destArea, clippedDestArea, sourceSize,
157 sourceRowPitch, destRowPitch, srcPixelStride, sourceData,
158 destData);
159 }
160 else
161 {
162 StretchedBlitNearest_PixelByPixel(sourceArea, destArea, clippedDestArea, sourceSize,
163 sourceRowPitch, destRowPitch, readOffset, writeOffset,
164 copySize, srcPixelStride, destPixelStride, sourceData,
165 destData);
166 }
167 }
168
169 using DepthStencilLoader = void(const float *, uint8_t *);
170
LoadDepth16(const float * source,uint8_t * dest)171 void LoadDepth16(const float *source, uint8_t *dest)
172 {
173 uint32_t convertedDepth = gl::floatToNormalized<16, uint32_t>(source[0]);
174 memcpy(dest, &convertedDepth, 2u);
175 }
176
LoadDepth24(const float * source,uint8_t * dest)177 void LoadDepth24(const float *source, uint8_t *dest)
178 {
179 uint32_t convertedDepth = gl::floatToNormalized<24, uint32_t>(source[0]);
180 memcpy(dest, &convertedDepth, 3u);
181 }
182
LoadStencilHelper(const float * source,uint8_t * dest)183 void LoadStencilHelper(const float *source, uint8_t *dest)
184 {
185 uint32_t convertedStencil = gl::getShiftedData<8, 0>(static_cast<uint32_t>(source[1]));
186 memcpy(dest, &convertedStencil, 1u);
187 }
188
LoadStencil8(const float * source,uint8_t * dest)189 void LoadStencil8(const float *source, uint8_t *dest)
190 {
191 // STENCIL_INDEX8 is implemented with D24S8, with the depth bits unused. Writes zero for safety.
192 float zero = 0.0f;
193 LoadDepth24(&zero, &dest[0]);
194 LoadStencilHelper(source, &dest[3]);
195 }
196
LoadDepth24Stencil8(const float * source,uint8_t * dest)197 void LoadDepth24Stencil8(const float *source, uint8_t *dest)
198 {
199 LoadDepth24(source, &dest[0]);
200 LoadStencilHelper(source, &dest[3]);
201 }
202
LoadDepth32F(const float * source,uint8_t * dest)203 void LoadDepth32F(const float *source, uint8_t *dest)
204 {
205 memcpy(dest, source, sizeof(float));
206 }
207
LoadDepth32FStencil8(const float * source,uint8_t * dest)208 void LoadDepth32FStencil8(const float *source, uint8_t *dest)
209 {
210 LoadDepth32F(source, &dest[0]);
211 LoadStencilHelper(source, &dest[4]);
212 }
213
214 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)215 void CopyDepthStencil(const gl::Box &sourceArea,
216 const gl::Box &destArea,
217 const gl::Rectangle &clippedDestArea,
218 const gl::Extents &sourceSize,
219 unsigned int sourceRowPitch,
220 unsigned int destRowPitch,
221 ptrdiff_t readOffset,
222 ptrdiff_t writeOffset,
223 size_t copySize,
224 size_t srcPixelStride,
225 size_t destPixelStride,
226 const uint8_t *sourceData,
227 uint8_t *destData)
228 {
229 // No stretching or subregions are supported, only full blits.
230 ASSERT(sourceArea == destArea);
231 ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
232 sourceSize.depth == 1);
233 ASSERT(clippedDestArea.width == sourceSize.width &&
234 clippedDestArea.height == sourceSize.height);
235 ASSERT(readOffset == 0 && writeOffset == 0);
236 ASSERT(destArea.x == 0 && destArea.y == 0);
237
238 for (int row = 0; row < destArea.height; ++row)
239 {
240 for (int column = 0; column < destArea.width; ++column)
241 {
242 ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
243 const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
244
245 uint8_t *destPixel = destData + row * destRowPitch + column * destPixelStride;
246
247 loader(sourcePixel, destPixel);
248 }
249 }
250 }
251
Depth32FStencil8ToDepth32F(const float * source,float * dest)252 void Depth32FStencil8ToDepth32F(const float *source, float *dest)
253 {
254 *dest = *source;
255 }
256
Depth24Stencil8ToDepth32F(const uint32_t * source,float * dest)257 void Depth24Stencil8ToDepth32F(const uint32_t *source, float *dest)
258 {
259 uint32_t normDepth = source[0] & 0x00FFFFFF;
260 float floatDepth = gl::normalizedToFloat<24>(normDepth);
261 *dest = floatDepth;
262 }
263
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)264 void BlitD24S8ToD32F(const gl::Box &sourceArea,
265 const gl::Box &destArea,
266 const gl::Rectangle &clippedDestArea,
267 const gl::Extents &sourceSize,
268 unsigned int sourceRowPitch,
269 unsigned int destRowPitch,
270 ptrdiff_t readOffset,
271 ptrdiff_t writeOffset,
272 size_t copySize,
273 size_t srcPixelStride,
274 size_t destPixelStride,
275 const uint8_t *sourceData,
276 uint8_t *destData)
277 {
278 // No stretching or subregions are supported, only full blits.
279 ASSERT(sourceArea == destArea);
280 ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
281 sourceSize.depth == 1);
282 ASSERT(clippedDestArea.width == sourceSize.width &&
283 clippedDestArea.height == sourceSize.height);
284 ASSERT(readOffset == 0 && writeOffset == 0);
285 ASSERT(destArea.x == 0 && destArea.y == 0);
286
287 for (int row = 0; row < destArea.height; ++row)
288 {
289 for (int column = 0; column < destArea.width; ++column)
290 {
291 ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
292 const uint32_t *sourcePixel = reinterpret_cast<const uint32_t *>(sourceData + offset);
293
294 float *destPixel =
295 reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
296
297 Depth24Stencil8ToDepth32F(sourcePixel, destPixel);
298 }
299 }
300 }
301
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)302 void BlitD32FS8ToD32F(const gl::Box &sourceArea,
303 const gl::Box &destArea,
304 const gl::Rectangle &clippedDestArea,
305 const gl::Extents &sourceSize,
306 unsigned int sourceRowPitch,
307 unsigned int destRowPitch,
308 ptrdiff_t readOffset,
309 ptrdiff_t writeOffset,
310 size_t copySize,
311 size_t srcPixelStride,
312 size_t destPixelStride,
313 const uint8_t *sourceData,
314 uint8_t *destData)
315 {
316 // No stretching or subregions are supported, only full blits.
317 ASSERT(sourceArea == destArea);
318 ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height &&
319 sourceSize.depth == 1);
320 ASSERT(clippedDestArea.width == sourceSize.width &&
321 clippedDestArea.height == sourceSize.height);
322 ASSERT(readOffset == 0 && writeOffset == 0);
323 ASSERT(destArea.x == 0 && destArea.y == 0);
324
325 for (int row = 0; row < destArea.height; ++row)
326 {
327 for (int column = 0; column < destArea.width; ++column)
328 {
329 ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride;
330 const float *sourcePixel = reinterpret_cast<const float *>(sourceData + offset);
331 float *destPixel =
332 reinterpret_cast<float *>(destData + row * destRowPitch + column * destPixelStride);
333
334 Depth32FStencil8ToDepth32F(sourcePixel, destPixel);
335 }
336 }
337 }
338
GetCopyDepthStencilFunction(GLenum internalFormat)339 Blit11::BlitConvertFunction *GetCopyDepthStencilFunction(GLenum internalFormat)
340 {
341 switch (internalFormat)
342 {
343 case GL_DEPTH_COMPONENT16:
344 return &CopyDepthStencil<LoadDepth16>;
345 case GL_DEPTH_COMPONENT24:
346 return &CopyDepthStencil<LoadDepth24>;
347 case GL_DEPTH_COMPONENT32F:
348 return &CopyDepthStencil<LoadDepth32F>;
349 case GL_STENCIL_INDEX8:
350 return &CopyDepthStencil<LoadStencil8>;
351 case GL_DEPTH24_STENCIL8:
352 return &CopyDepthStencil<LoadDepth24Stencil8>;
353 case GL_DEPTH32F_STENCIL8:
354 return &CopyDepthStencil<LoadDepth32FStencil8>;
355 default:
356 UNREACHABLE();
357 return nullptr;
358 }
359 }
360
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)361 inline void GenerateVertexCoords(const gl::Box &sourceArea,
362 const gl::Extents &sourceSize,
363 const gl::Box &destArea,
364 const gl::Extents &destSize,
365 float *x1,
366 float *y1,
367 float *x2,
368 float *y2,
369 float *u1,
370 float *v1,
371 float *u2,
372 float *v2)
373 {
374 *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f;
375 *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f;
376 *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f;
377 *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f;
378
379 *u1 = sourceArea.x / float(sourceSize.width);
380 *v1 = sourceArea.y / float(sourceSize.height);
381 *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width);
382 *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height);
383 }
384
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)385 void Write2DVertices(const gl::Box &sourceArea,
386 const gl::Extents &sourceSize,
387 const gl::Box &destArea,
388 const gl::Extents &destSize,
389 void *outVertices,
390 unsigned int *outStride,
391 unsigned int *outVertexCount,
392 D3D11_PRIMITIVE_TOPOLOGY *outTopology)
393 {
394 float x1, y1, x2, y2, u1, v1, u2, v2;
395 GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
396 &u2, &v2);
397
398 d3d11::PositionTexCoordVertex *vertices =
399 static_cast<d3d11::PositionTexCoordVertex *>(outVertices);
400
401 d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2);
402 d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1);
403 d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2);
404 d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1);
405
406 *outStride = sizeof(d3d11::PositionTexCoordVertex);
407 *outVertexCount = 4;
408 *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
409 }
410
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)411 void Write3DVertices(const gl::Box &sourceArea,
412 const gl::Extents &sourceSize,
413 const gl::Box &destArea,
414 const gl::Extents &destSize,
415 void *outVertices,
416 unsigned int *outStride,
417 unsigned int *outVertexCount,
418 D3D11_PRIMITIVE_TOPOLOGY *outTopology)
419 {
420 ASSERT(sourceSize.depth > 0 && destSize.depth > 0);
421
422 float x1, y1, x2, y2, u1, v1, u2, v2;
423 GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1,
424 &u2, &v2);
425
426 d3d11::PositionLayerTexCoord3DVertex *vertices =
427 static_cast<d3d11::PositionLayerTexCoord3DVertex *>(outVertices);
428
429 for (int i = 0; i < destSize.depth; i++)
430 {
431 float readDepth = (float)i / std::max(destSize.depth - 1, 1);
432
433 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth);
434 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth);
435 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth);
436
437 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth);
438 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth);
439 d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth);
440 }
441
442 *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex);
443 *outVertexCount = destSize.depth * 6;
444 *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
445 }
446
GetSwizzleIndex(GLenum swizzle)447 unsigned int GetSwizzleIndex(GLenum swizzle)
448 {
449 unsigned int colorIndex = 0;
450
451 switch (swizzle)
452 {
453 case GL_RED:
454 colorIndex = 0;
455 break;
456 case GL_GREEN:
457 colorIndex = 1;
458 break;
459 case GL_BLUE:
460 colorIndex = 2;
461 break;
462 case GL_ALPHA:
463 colorIndex = 3;
464 break;
465 case GL_ZERO:
466 colorIndex = 4;
467 break;
468 case GL_ONE:
469 colorIndex = 5;
470 break;
471 default:
472 UNREACHABLE();
473 break;
474 }
475
476 return colorIndex;
477 }
478
GetAlphaMaskBlendStateDesc()479 D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc()
480 {
481 D3D11_BLEND_DESC desc;
482 memset(&desc, 0, sizeof(desc));
483 desc.RenderTarget[0].BlendEnable = TRUE;
484 desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
485 desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO;
486 desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
487 desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
488 desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
489 desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
490 desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED |
491 D3D11_COLOR_WRITE_ENABLE_GREEN |
492 D3D11_COLOR_WRITE_ENABLE_BLUE;
493 return desc;
494 }
495
496 D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = {
497 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
498 {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
499 };
500
501 D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = {
502 {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
503 {"LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0},
504 {"TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
505 };
506
GetStencilSRVFormat(const d3d11::Format & formatSet)507 DXGI_FORMAT GetStencilSRVFormat(const d3d11::Format &formatSet)
508 {
509 switch (formatSet.texFormat)
510 {
511 case DXGI_FORMAT_R32G8X24_TYPELESS:
512 return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT;
513 case DXGI_FORMAT_R24G8_TYPELESS:
514 return DXGI_FORMAT_X24_TYPELESS_G8_UINT;
515 default:
516 UNREACHABLE();
517 return DXGI_FORMAT_UNKNOWN;
518 }
519 }
520
521 } // namespace
522
523 #include "libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc"
524
525 Blit11::Shader::Shader() = default;
526
527 Blit11::Shader::Shader(Shader &&other) = default;
528
529 Blit11::Shader::~Shader() = default;
530
531 Blit11::Shader &Blit11::Shader::operator=(Blit11::Shader &&other) = default;
532
Blit11(Renderer11 * renderer)533 Blit11::Blit11(Renderer11 *renderer)
534 : mRenderer(renderer),
535 mResourcesInitialized(false),
536 mVertexBuffer(),
537 mPointSampler(),
538 mLinearSampler(),
539 mScissorEnabledRasterizerState(),
540 mScissorDisabledRasterizerState(),
541 mDepthStencilState(),
542 mQuad2DIL(quad2DLayout,
543 ArraySize(quad2DLayout),
544 g_VS_Passthrough2D,
545 ArraySize(g_VS_Passthrough2D),
546 "Blit11 2D input layout"),
547 mQuad2DVS(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D vertex shader"),
548 mDepthPS(g_PS_PassthroughDepth2D,
549 ArraySize(g_PS_PassthroughDepth2D),
550 "Blit11 2D depth pixel shader"),
551 mQuad3DIL(quad3DLayout,
552 ArraySize(quad3DLayout),
553 g_VS_Passthrough3D,
554 ArraySize(g_VS_Passthrough3D),
555 "Blit11 3D input layout"),
556 mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"),
557 mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"),
558 mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"),
559 mSwizzleCB(),
560 mResolveDepthStencilVS(g_VS_ResolveDepthStencil,
561 ArraySize(g_VS_ResolveDepthStencil),
562 "Blit11::mResolveDepthStencilVS"),
563 mResolveDepthPS(g_PS_ResolveDepth, ArraySize(g_PS_ResolveDepth), "Blit11::mResolveDepthPS"),
564 mResolveDepthStencilPS(g_PS_ResolveDepthStencil,
565 ArraySize(g_PS_ResolveDepthStencil),
566 "Blit11::mResolveDepthStencilPS"),
567 mResolveStencilPS(g_PS_ResolveStencil,
568 ArraySize(g_PS_ResolveStencil),
569 "Blit11::mResolveStencilPS"),
570 mStencilSRV(),
571 mResolvedDepthStencilRTView()
572 {}
573
~Blit11()574 Blit11::~Blit11() {}
575
initResources(const gl::Context * context)576 angle::Result Blit11::initResources(const gl::Context *context)
577 {
578 if (mResourcesInitialized)
579 {
580 return angle::Result::Continue;
581 }
582
583 ANGLE_TRACE_EVENT0("gpu.angle", "Blit11::initResources");
584
585 D3D11_BUFFER_DESC vbDesc;
586 vbDesc.ByteWidth =
587 static_cast<unsigned int>(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex),
588 sizeof(d3d11::PositionTexCoordVertex)) *
589 6 * mRenderer->getNativeCaps().max3DTextureSize);
590 vbDesc.Usage = D3D11_USAGE_DYNAMIC;
591 vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
592 vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
593 vbDesc.MiscFlags = 0;
594 vbDesc.StructureByteStride = 0;
595
596 Context11 *context11 = GetImplAs<Context11>(context);
597
598 ANGLE_TRY(mRenderer->allocateResource(context11, vbDesc, &mVertexBuffer));
599 mVertexBuffer.setDebugName("Blit11 vertex buffer");
600
601 D3D11_SAMPLER_DESC pointSamplerDesc;
602 pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR;
603 pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
604 pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
605 pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
606 pointSamplerDesc.MipLODBias = 0.0f;
607 pointSamplerDesc.MaxAnisotropy = 0;
608 pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
609 pointSamplerDesc.BorderColor[0] = 0.0f;
610 pointSamplerDesc.BorderColor[1] = 0.0f;
611 pointSamplerDesc.BorderColor[2] = 0.0f;
612 pointSamplerDesc.BorderColor[3] = 0.0f;
613 pointSamplerDesc.MinLOD = 0.0f;
614 pointSamplerDesc.MaxLOD = FLT_MAX;
615
616 ANGLE_TRY(mRenderer->allocateResource(context11, pointSamplerDesc, &mPointSampler));
617 mPointSampler.setDebugName("Blit11 point sampler");
618
619 D3D11_SAMPLER_DESC linearSamplerDesc;
620 linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
621 linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
622 linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
623 linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
624 linearSamplerDesc.MipLODBias = 0.0f;
625 linearSamplerDesc.MaxAnisotropy = 0;
626 linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
627 linearSamplerDesc.BorderColor[0] = 0.0f;
628 linearSamplerDesc.BorderColor[1] = 0.0f;
629 linearSamplerDesc.BorderColor[2] = 0.0f;
630 linearSamplerDesc.BorderColor[3] = 0.0f;
631 linearSamplerDesc.MinLOD = 0.0f;
632 linearSamplerDesc.MaxLOD = FLT_MAX;
633
634 ANGLE_TRY(mRenderer->allocateResource(context11, linearSamplerDesc, &mLinearSampler));
635 mLinearSampler.setDebugName("Blit11 linear sampler");
636
637 // Use a rasterizer state that will not cull so that inverted quads will not be culled
638 D3D11_RASTERIZER_DESC rasterDesc;
639 rasterDesc.FillMode = D3D11_FILL_SOLID;
640 rasterDesc.CullMode = D3D11_CULL_NONE;
641 rasterDesc.FrontCounterClockwise = FALSE;
642 rasterDesc.DepthBias = 0;
643 rasterDesc.SlopeScaledDepthBias = 0.0f;
644 rasterDesc.DepthBiasClamp = 0.0f;
645 rasterDesc.DepthClipEnable = TRUE;
646 rasterDesc.MultisampleEnable = FALSE;
647 rasterDesc.AntialiasedLineEnable = FALSE;
648
649 rasterDesc.ScissorEnable = TRUE;
650 ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mScissorEnabledRasterizerState));
651 mScissorEnabledRasterizerState.setDebugName("Blit11 scissoring rasterizer state");
652
653 rasterDesc.ScissorEnable = FALSE;
654 ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mScissorDisabledRasterizerState));
655 mScissorDisabledRasterizerState.setDebugName("Blit11 no scissoring rasterizer state");
656
657 D3D11_DEPTH_STENCIL_DESC depthStencilDesc;
658 depthStencilDesc.DepthEnable = TRUE;
659 depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
660 depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS;
661 depthStencilDesc.StencilEnable = FALSE;
662 depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
663 depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
664 depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
665 depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
666 depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
667 depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
668 depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
669 depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
670 depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
671 depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
672
673 ANGLE_TRY(mRenderer->allocateResource(context11, depthStencilDesc, &mDepthStencilState));
674 mDepthStencilState.setDebugName("Blit11 depth stencil state");
675
676 D3D11_BUFFER_DESC swizzleBufferDesc;
677 swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4;
678 swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
679 swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
680 swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
681 swizzleBufferDesc.MiscFlags = 0;
682 swizzleBufferDesc.StructureByteStride = 0;
683
684 ANGLE_TRY(mRenderer->allocateResource(context11, swizzleBufferDesc, &mSwizzleCB));
685 mSwizzleCB.setDebugName("Blit11 swizzle constant buffer");
686
687 mResourcesInitialized = true;
688
689 return angle::Result::Continue;
690 }
691
692 // static
GetSwizzleShaderType(GLenum type,D3D11_SRV_DIMENSION dimensionality)693 Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type,
694 D3D11_SRV_DIMENSION dimensionality)
695 {
696 switch (dimensionality)
697 {
698 case D3D11_SRV_DIMENSION_TEXTURE2D:
699 switch (type)
700 {
701 case GL_FLOAT:
702 return SWIZZLESHADER_2D_FLOAT;
703 case GL_UNSIGNED_INT:
704 return SWIZZLESHADER_2D_UINT;
705 case GL_INT:
706 return SWIZZLESHADER_2D_INT;
707 default:
708 UNREACHABLE();
709 return SWIZZLESHADER_INVALID;
710 }
711 case D3D11_SRV_DIMENSION_TEXTURECUBE:
712 switch (type)
713 {
714 case GL_FLOAT:
715 return SWIZZLESHADER_CUBE_FLOAT;
716 case GL_UNSIGNED_INT:
717 return SWIZZLESHADER_CUBE_UINT;
718 case GL_INT:
719 return SWIZZLESHADER_CUBE_INT;
720 default:
721 UNREACHABLE();
722 return SWIZZLESHADER_INVALID;
723 }
724 case D3D11_SRV_DIMENSION_TEXTURE3D:
725 switch (type)
726 {
727 case GL_FLOAT:
728 return SWIZZLESHADER_3D_FLOAT;
729 case GL_UNSIGNED_INT:
730 return SWIZZLESHADER_3D_UINT;
731 case GL_INT:
732 return SWIZZLESHADER_3D_INT;
733 default:
734 UNREACHABLE();
735 return SWIZZLESHADER_INVALID;
736 }
737 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
738 switch (type)
739 {
740 case GL_FLOAT:
741 return SWIZZLESHADER_ARRAY_FLOAT;
742 case GL_UNSIGNED_INT:
743 return SWIZZLESHADER_ARRAY_UINT;
744 case GL_INT:
745 return SWIZZLESHADER_ARRAY_INT;
746 default:
747 UNREACHABLE();
748 return SWIZZLESHADER_INVALID;
749 }
750 default:
751 UNREACHABLE();
752 return SWIZZLESHADER_INVALID;
753 }
754 }
755
getShaderSupport(const gl::Context * context,const Shader & shader,Blit11::ShaderSupport * supportOut)756 angle::Result Blit11::getShaderSupport(const gl::Context *context,
757 const Shader &shader,
758 Blit11::ShaderSupport *supportOut)
759 {
760
761 Context11 *context11 = GetImplAs<Context11>(context);
762
763 switch (shader.dimension)
764 {
765 case SHADER_2D:
766 {
767 ANGLE_TRY(mQuad2DIL.resolve(context11, mRenderer));
768 ANGLE_TRY(mQuad2DVS.resolve(context11, mRenderer));
769 supportOut->inputLayout = &mQuad2DIL.getObj();
770 supportOut->vertexShader = &mQuad2DVS.getObj();
771 supportOut->geometryShader = nullptr;
772 supportOut->vertexWriteFunction = Write2DVertices;
773 break;
774 }
775 case SHADER_3D:
776 case SHADER_2DARRAY:
777 {
778 ANGLE_TRY(mQuad3DIL.resolve(context11, mRenderer));
779 ANGLE_TRY(mQuad3DVS.resolve(context11, mRenderer));
780 ANGLE_TRY(mQuad3DGS.resolve(context11, mRenderer));
781 supportOut->inputLayout = &mQuad3DIL.getObj();
782 supportOut->vertexShader = &mQuad3DVS.getObj();
783 supportOut->geometryShader = &mQuad3DGS.getObj();
784 supportOut->vertexWriteFunction = Write3DVertices;
785 break;
786 }
787 default:
788 UNREACHABLE();
789 }
790
791 return angle::Result::Continue;
792 }
793
swizzleTexture(const gl::Context * context,const d3d11::SharedSRV & source,const d3d11::RenderTargetView & dest,const gl::Extents & size,const gl::SwizzleState & swizzleTarget)794 angle::Result Blit11::swizzleTexture(const gl::Context *context,
795 const d3d11::SharedSRV &source,
796 const d3d11::RenderTargetView &dest,
797 const gl::Extents &size,
798 const gl::SwizzleState &swizzleTarget)
799 {
800 ANGLE_TRY(initResources(context));
801
802 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
803
804 D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
805 source.get()->GetDesc(&sourceSRVDesc);
806
807 GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
808 if (componentType == GL_NONE)
809 {
810 // We're swizzling the depth component of a depth-stencil texture.
811 switch (sourceSRVDesc.Format)
812 {
813 case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
814 componentType = GL_UNSIGNED_NORMALIZED;
815 break;
816 case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
817 componentType = GL_FLOAT;
818 break;
819 default:
820 UNREACHABLE();
821 break;
822 }
823 }
824
825 GLenum shaderType = GL_NONE;
826 switch (componentType)
827 {
828 case GL_UNSIGNED_NORMALIZED:
829 case GL_SIGNED_NORMALIZED:
830 case GL_FLOAT:
831 shaderType = GL_FLOAT;
832 break;
833 case GL_INT:
834 shaderType = GL_INT;
835 break;
836 case GL_UNSIGNED_INT:
837 shaderType = GL_UNSIGNED_INT;
838 break;
839 default:
840 UNREACHABLE();
841 break;
842 }
843
844 const Shader *shader = nullptr;
845 ANGLE_TRY(getSwizzleShader(context, shaderType, sourceSRVDesc.ViewDimension, &shader));
846
847 // Set vertices
848 D3D11_MAPPED_SUBRESOURCE mappedResource;
849 ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
850 &mappedResource));
851
852 ShaderSupport support;
853 ANGLE_TRY(getShaderSupport(context, *shader, &support));
854
855 UINT stride = 0;
856 UINT drawCount = 0;
857 D3D11_PRIMITIVE_TOPOLOGY topology;
858
859 gl::Box area(0, 0, 0, size.width, size.height, size.depth);
860 support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount,
861 &topology);
862
863 deviceContext->Unmap(mVertexBuffer.get(), 0);
864
865 // Set constant buffer
866 ANGLE_TRY(mRenderer->mapResource(context, mSwizzleCB.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
867 &mappedResource));
868
869 unsigned int *swizzleIndices = static_cast<unsigned int *>(mappedResource.pData);
870 swizzleIndices[0] = GetSwizzleIndex(swizzleTarget.swizzleRed);
871 swizzleIndices[1] = GetSwizzleIndex(swizzleTarget.swizzleGreen);
872 swizzleIndices[2] = GetSwizzleIndex(swizzleTarget.swizzleBlue);
873 swizzleIndices[3] = GetSwizzleIndex(swizzleTarget.swizzleAlpha);
874
875 deviceContext->Unmap(mSwizzleCB.get(), 0);
876
877 StateManager11 *stateManager = mRenderer->getStateManager();
878
879 // Apply vertex buffer
880 stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
881
882 // Apply constant buffer
883 stateManager->setPixelConstantBuffer(0, &mSwizzleCB);
884
885 // Apply state
886 stateManager->setSimpleBlendState(nullptr);
887 stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
888 stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
889
890 // Apply shaders
891 stateManager->setInputLayout(support.inputLayout);
892 stateManager->setPrimitiveTopology(topology);
893
894 stateManager->setDrawShaders(support.vertexShader, support.geometryShader,
895 &shader->pixelShader);
896
897 // Apply render target
898 stateManager->setRenderTarget(dest.get(), nullptr);
899
900 // Set the viewport
901 stateManager->setSimpleViewport(size);
902
903 // Apply textures and sampler
904 stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
905
906 // Draw the quad
907 deviceContext->Draw(drawCount, 0);
908
909 return angle::Result::Continue;
910 }
911
copyTexture(const gl::Context * context,const d3d11::SharedSRV & source,const gl::Box & sourceArea,const gl::Extents & sourceSize,GLenum sourceFormat,const d3d11::RenderTargetView & dest,const gl::Box & destArea,const gl::Extents & destSize,const gl::Rectangle * scissor,GLenum destFormat,GLenum destTypeForDownsampling,GLenum filter,bool maskOffAlpha,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha)912 angle::Result Blit11::copyTexture(const gl::Context *context,
913 const d3d11::SharedSRV &source,
914 const gl::Box &sourceArea,
915 const gl::Extents &sourceSize,
916 GLenum sourceFormat,
917 const d3d11::RenderTargetView &dest,
918 const gl::Box &destArea,
919 const gl::Extents &destSize,
920 const gl::Rectangle *scissor,
921 GLenum destFormat,
922 GLenum destTypeForDownsampling,
923 GLenum filter,
924 bool maskOffAlpha,
925 bool unpackPremultiplyAlpha,
926 bool unpackUnmultiplyAlpha)
927 {
928 ANGLE_TRY(initResources(context));
929
930 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
931
932 // Determine if the source format is a signed integer format, the destFormat will already
933 // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned.
934 D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
935 source.get()->GetDesc(&sourceSRVDesc);
936
937 GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format);
938
939 ASSERT(componentType != GL_NONE);
940 ASSERT(componentType != GL_SIGNED_NORMALIZED);
941 bool isSrcSigned = (componentType == GL_INT);
942
943 D3D11_RENDER_TARGET_VIEW_DESC destRTVDesc;
944 dest.get()->GetDesc(&destRTVDesc);
945
946 GLenum destComponentType = d3d11::GetComponentType(destRTVDesc.Format);
947
948 ASSERT(componentType != GL_NONE);
949 bool isDestSigned = (destComponentType == GL_INT);
950
951 ShaderDimension dimension = SHADER_INVALID;
952
953 switch (sourceSRVDesc.ViewDimension)
954 {
955 case D3D11_SRV_DIMENSION_TEXTURE2D:
956 dimension = SHADER_2D;
957 break;
958 case D3D11_SRV_DIMENSION_TEXTURE3D:
959 dimension = SHADER_3D;
960 break;
961 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
962 dimension = SHADER_2DARRAY;
963 break;
964 default:
965 UNREACHABLE();
966 }
967
968 const Shader *shader = nullptr;
969
970 ANGLE_TRY(getBlitShader(context, destFormat, sourceFormat, isSrcSigned, isDestSigned,
971 unpackPremultiplyAlpha, unpackUnmultiplyAlpha, destTypeForDownsampling,
972 dimension, &shader));
973
974 ShaderSupport support;
975 ANGLE_TRY(getShaderSupport(context, *shader, &support));
976
977 // Set vertices
978 D3D11_MAPPED_SUBRESOURCE mappedResource;
979 ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
980 &mappedResource));
981
982 UINT stride = 0;
983 UINT drawCount = 0;
984 D3D11_PRIMITIVE_TOPOLOGY topology;
985
986 support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
987 &stride, &drawCount, &topology);
988
989 deviceContext->Unmap(mVertexBuffer.get(), 0);
990
991 StateManager11 *stateManager = mRenderer->getStateManager();
992
993 // Apply vertex buffer
994 stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
995
996 // Apply state
997 if (maskOffAlpha)
998 {
999 ANGLE_TRY(mAlphaMaskBlendState.resolve(GetImplAs<Context11>(context), mRenderer));
1000 stateManager->setSimpleBlendState(&mAlphaMaskBlendState.getObj());
1001 }
1002 else
1003 {
1004 stateManager->setSimpleBlendState(nullptr);
1005 }
1006 stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
1007
1008 if (scissor)
1009 {
1010 stateManager->setSimpleScissorRect(*scissor);
1011 stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
1012 }
1013 else
1014 {
1015 stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
1016 }
1017
1018 // Apply shaders
1019 stateManager->setInputLayout(support.inputLayout);
1020 stateManager->setPrimitiveTopology(topology);
1021
1022 stateManager->setDrawShaders(support.vertexShader, support.geometryShader,
1023 &shader->pixelShader);
1024
1025 // Apply render target
1026 stateManager->setRenderTarget(dest.get(), nullptr);
1027
1028 // Set the viewport
1029 stateManager->setSimpleViewport(destSize);
1030
1031 // Apply texture and sampler
1032 switch (filter)
1033 {
1034 case GL_NEAREST:
1035 stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
1036 break;
1037 case GL_LINEAR:
1038 stateManager->setSimplePixelTextureAndSampler(source, mLinearSampler);
1039 break;
1040
1041 default:
1042 UNREACHABLE();
1043 ANGLE_TRY_HR(GetImplAs<Context11>(context), E_FAIL,
1044 "Internal error, unknown blit filter mode.");
1045 }
1046
1047 // Draw the quad
1048 deviceContext->Draw(drawCount, 0);
1049
1050 return angle::Result::Continue;
1051 }
1052
copyStencil(const gl::Context * context,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)1053 angle::Result Blit11::copyStencil(const gl::Context *context,
1054 const TextureHelper11 &source,
1055 unsigned int sourceSubresource,
1056 const gl::Box &sourceArea,
1057 const gl::Extents &sourceSize,
1058 const TextureHelper11 &dest,
1059 unsigned int destSubresource,
1060 const gl::Box &destArea,
1061 const gl::Extents &destSize,
1062 const gl::Rectangle *scissor)
1063 {
1064 return copyDepthStencilImpl(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1065 destSubresource, destArea, destSize, scissor, true);
1066 }
1067
copyDepth(const gl::Context * context,const d3d11::SharedSRV & source,const gl::Box & sourceArea,const gl::Extents & sourceSize,const d3d11::DepthStencilView & dest,const gl::Box & destArea,const gl::Extents & destSize,const gl::Rectangle * scissor)1068 angle::Result Blit11::copyDepth(const gl::Context *context,
1069 const d3d11::SharedSRV &source,
1070 const gl::Box &sourceArea,
1071 const gl::Extents &sourceSize,
1072 const d3d11::DepthStencilView &dest,
1073 const gl::Box &destArea,
1074 const gl::Extents &destSize,
1075 const gl::Rectangle *scissor)
1076 {
1077 ANGLE_TRY(initResources(context));
1078
1079 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1080
1081 // Set vertices
1082 D3D11_MAPPED_SUBRESOURCE mappedResource;
1083 ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
1084 &mappedResource));
1085
1086 UINT stride = 0;
1087 UINT drawCount = 0;
1088 D3D11_PRIMITIVE_TOPOLOGY topology;
1089
1090 Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride,
1091 &drawCount, &topology);
1092
1093 deviceContext->Unmap(mVertexBuffer.get(), 0);
1094
1095 StateManager11 *stateManager = mRenderer->getStateManager();
1096
1097 // Apply vertex buffer
1098 stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
1099
1100 // Apply state
1101 stateManager->setSimpleBlendState(nullptr);
1102 stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
1103
1104 if (scissor)
1105 {
1106 stateManager->setSimpleScissorRect(*scissor);
1107 stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
1108 }
1109 else
1110 {
1111 stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
1112 }
1113
1114 Context11 *context11 = GetImplAs<Context11>(context);
1115
1116 ANGLE_TRY(mQuad2DIL.resolve(context11, mRenderer));
1117 ANGLE_TRY(mQuad2DVS.resolve(context11, mRenderer));
1118 ANGLE_TRY(mDepthPS.resolve(context11, mRenderer));
1119
1120 // Apply shaders
1121 stateManager->setInputLayout(&mQuad2DIL.getObj());
1122 stateManager->setPrimitiveTopology(topology);
1123
1124 stateManager->setDrawShaders(&mQuad2DVS.getObj(), nullptr, &mDepthPS.getObj());
1125
1126 // Apply render target
1127 stateManager->setRenderTarget(nullptr, dest.get());
1128
1129 // Set the viewport
1130 stateManager->setSimpleViewport(destSize);
1131
1132 // Apply texture and sampler
1133 stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
1134
1135 // Draw the quad
1136 deviceContext->Draw(drawCount, 0);
1137
1138 return angle::Result::Continue;
1139 }
1140
copyDepthStencil(const gl::Context * context,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)1141 angle::Result Blit11::copyDepthStencil(const gl::Context *context,
1142 const TextureHelper11 &source,
1143 unsigned int sourceSubresource,
1144 const gl::Box &sourceArea,
1145 const gl::Extents &sourceSize,
1146 const TextureHelper11 &dest,
1147 unsigned int destSubresource,
1148 const gl::Box &destArea,
1149 const gl::Extents &destSize,
1150 const gl::Rectangle *scissor)
1151 {
1152 return copyDepthStencilImpl(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1153 destSubresource, destArea, destSize, scissor, false);
1154 }
1155
copyDepthStencilImpl(const gl::Context * context,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)1156 angle::Result Blit11::copyDepthStencilImpl(const gl::Context *context,
1157 const TextureHelper11 &source,
1158 unsigned int sourceSubresource,
1159 const gl::Box &sourceArea,
1160 const gl::Extents &sourceSize,
1161 const TextureHelper11 &dest,
1162 unsigned int destSubresource,
1163 const gl::Box &destArea,
1164 const gl::Extents &destSize,
1165 const gl::Rectangle *scissor,
1166 bool stencilOnly)
1167 {
1168 auto srcDXGIFormat = source.getFormat();
1169 const auto &srcSizeInfo = d3d11::GetDXGIFormatSizeInfo(srcDXGIFormat);
1170 unsigned int srcPixelSize = srcSizeInfo.pixelBytes;
1171 unsigned int copyOffset = 0;
1172 unsigned int copySize = srcPixelSize;
1173 auto destDXGIFormat = dest.getFormat();
1174 const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destDXGIFormat);
1175 unsigned int destPixelSize = destSizeInfo.pixelBytes;
1176
1177 ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS);
1178
1179 if (stencilOnly)
1180 {
1181 const auto &srcFormat = source.getFormatSet().format();
1182
1183 // Stencil channel should be right after the depth channel. Some views to depth/stencil
1184 // resources have red channel for depth, in which case the depth channel bit width is in
1185 // redBits.
1186 ASSERT((srcFormat.redBits != 0) != (srcFormat.depthBits != 0));
1187 GLuint depthBits = srcFormat.redBits + srcFormat.depthBits;
1188 // Known formats have either 24 or 32 bits of depth.
1189 ASSERT(depthBits == 24 || depthBits == 32);
1190 copyOffset = depthBits / 8;
1191
1192 // Stencil is assumed to be 8-bit - currently this is true for all possible formats.
1193 copySize = 1;
1194 }
1195
1196 if (srcDXGIFormat != destDXGIFormat)
1197 {
1198 if (srcDXGIFormat == DXGI_FORMAT_R24G8_TYPELESS)
1199 {
1200 ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr);
1201 return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1202 destSubresource, destArea, destSize, scissor, copyOffset,
1203 copyOffset, copySize, srcPixelSize, destPixelSize,
1204 BlitD24S8ToD32F);
1205 }
1206 ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS);
1207 return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1208 destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
1209 copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F);
1210 }
1211
1212 return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1213 destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
1214 copySize, srcPixelSize, destPixelSize, StretchedBlitNearest);
1215 }
1216
copyAndConvertImpl(const gl::Context * context,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)1217 angle::Result Blit11::copyAndConvertImpl(const gl::Context *context,
1218 const TextureHelper11 &source,
1219 unsigned int sourceSubresource,
1220 const gl::Box &sourceArea,
1221 const gl::Extents &sourceSize,
1222 const TextureHelper11 &destStaging,
1223 const gl::Box &destArea,
1224 const gl::Extents &destSize,
1225 const gl::Rectangle *scissor,
1226 size_t readOffset,
1227 size_t writeOffset,
1228 size_t copySize,
1229 size_t srcPixelStride,
1230 size_t destPixelStride,
1231 BlitConvertFunction *convertFunction)
1232 {
1233 ANGLE_TRY(initResources(context));
1234
1235 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1236
1237 TextureHelper11 sourceStaging;
1238 ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D,
1239 source.getFormatSet(), sourceSize,
1240 StagingAccess::READ, &sourceStaging));
1241
1242 deviceContext->CopySubresourceRegion(sourceStaging.get(), 0, 0, 0, 0, source.get(),
1243 sourceSubresource, nullptr);
1244
1245 D3D11_MAPPED_SUBRESOURCE sourceMapping;
1246 ANGLE_TRY(
1247 mRenderer->mapResource(context, sourceStaging.get(), 0, D3D11_MAP_READ, 0, &sourceMapping));
1248
1249 D3D11_MAPPED_SUBRESOURCE destMapping;
1250 angle::Result error =
1251 mRenderer->mapResource(context, destStaging.get(), 0, D3D11_MAP_WRITE, 0, &destMapping);
1252 if (error == angle::Result::Stop)
1253 {
1254 deviceContext->Unmap(sourceStaging.get(), 0);
1255 return error;
1256 }
1257
1258 // Clip dest area to the destination size
1259 gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height);
1260
1261 // Clip dest area to the scissor
1262 if (scissor)
1263 {
1264 if (!gl::ClipRectangle(clipRect, *scissor, &clipRect))
1265 {
1266 return angle::Result::Continue;
1267 }
1268 }
1269
1270 convertFunction(sourceArea, destArea, clipRect, sourceSize, sourceMapping.RowPitch,
1271 destMapping.RowPitch, readOffset, writeOffset, copySize, srcPixelStride,
1272 destPixelStride, static_cast<const uint8_t *>(sourceMapping.pData),
1273 static_cast<uint8_t *>(destMapping.pData));
1274
1275 deviceContext->Unmap(sourceStaging.get(), 0);
1276 deviceContext->Unmap(destStaging.get(), 0);
1277
1278 return angle::Result::Continue;
1279 }
1280
copyAndConvert(const gl::Context * context,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)1281 angle::Result Blit11::copyAndConvert(const gl::Context *context,
1282 const TextureHelper11 &source,
1283 unsigned int sourceSubresource,
1284 const gl::Box &sourceArea,
1285 const gl::Extents &sourceSize,
1286 const TextureHelper11 &dest,
1287 unsigned int destSubresource,
1288 const gl::Box &destArea,
1289 const gl::Extents &destSize,
1290 const gl::Rectangle *scissor,
1291 size_t readOffset,
1292 size_t writeOffset,
1293 size_t copySize,
1294 size_t srcPixelStride,
1295 size_t destPixelStride,
1296 BlitConvertFunction *convertFunction)
1297 {
1298 ANGLE_TRY(initResources(context));
1299
1300 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1301
1302 // HACK: Create the destination staging buffer as a read/write texture so
1303 // ID3D11DevicContext::UpdateSubresource can be called
1304 // using it's mapped data as a source
1305 TextureHelper11 destStaging;
1306 ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D, dest.getFormatSet(),
1307 destSize, StagingAccess::READ_WRITE, &destStaging));
1308
1309 deviceContext->CopySubresourceRegion(destStaging.get(), 0, 0, 0, 0, dest.get(), destSubresource,
1310 nullptr);
1311
1312 ANGLE_TRY(copyAndConvertImpl(context, source, sourceSubresource, sourceArea, sourceSize,
1313 destStaging, destArea, destSize, scissor, readOffset, writeOffset,
1314 copySize, srcPixelStride, destPixelStride, convertFunction));
1315
1316 // Work around timeouts/TDRs in older NVIDIA drivers.
1317 if (mRenderer->getFeatures().depthStencilBlitExtraCopy.enabled)
1318 {
1319 D3D11_MAPPED_SUBRESOURCE mapped;
1320 ANGLE_TRY(
1321 mRenderer->mapResource(context, destStaging.get(), 0, D3D11_MAP_READ, 0, &mapped));
1322 deviceContext->UpdateSubresource(dest.get(), destSubresource, nullptr, mapped.pData,
1323 mapped.RowPitch, mapped.DepthPitch);
1324 deviceContext->Unmap(destStaging.get(), 0);
1325 }
1326 else
1327 {
1328 deviceContext->CopySubresourceRegion(dest.get(), destSubresource, 0, 0, 0,
1329 destStaging.get(), 0, nullptr);
1330 }
1331
1332 return angle::Result::Continue;
1333 }
1334
addBlitShaderToMap(const gl::Context * context,BlitShaderType blitShaderType,ShaderDimension dimension,const ShaderData & shaderData,const char * name)1335 angle::Result Blit11::addBlitShaderToMap(const gl::Context *context,
1336 BlitShaderType blitShaderType,
1337 ShaderDimension dimension,
1338 const ShaderData &shaderData,
1339 const char *name)
1340 {
1341 ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end());
1342
1343 d3d11::PixelShader ps;
1344 ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), shaderData, &ps));
1345 ps.setDebugName(name);
1346
1347 Shader shader;
1348 shader.dimension = dimension;
1349 shader.pixelShader = std::move(ps);
1350
1351 mBlitShaderMap[blitShaderType] = std::move(shader);
1352 return angle::Result::Continue;
1353 }
1354
addSwizzleShaderToMap(const gl::Context * context,SwizzleShaderType swizzleShaderType,ShaderDimension dimension,const ShaderData & shaderData,const char * name)1355 angle::Result Blit11::addSwizzleShaderToMap(const gl::Context *context,
1356 SwizzleShaderType swizzleShaderType,
1357 ShaderDimension dimension,
1358 const ShaderData &shaderData,
1359 const char *name)
1360 {
1361 ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end());
1362
1363 d3d11::PixelShader ps;
1364 ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), shaderData, &ps));
1365 ps.setDebugName(name);
1366
1367 Shader shader;
1368 shader.dimension = dimension;
1369 shader.pixelShader = std::move(ps);
1370
1371 mSwizzleShaderMap[swizzleShaderType] = std::move(shader);
1372 return angle::Result::Continue;
1373 }
1374
clearShaderMap()1375 void Blit11::clearShaderMap()
1376 {
1377 mBlitShaderMap.clear();
1378 mSwizzleShaderMap.clear();
1379 }
1380
getBlitShaderOperation(GLenum destinationFormat,GLenum sourceFormat,bool isSrcSigned,bool isDestSigned,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,GLenum destTypeForDownsampling)1381 Blit11::BlitShaderOperation Blit11::getBlitShaderOperation(GLenum destinationFormat,
1382 GLenum sourceFormat,
1383 bool isSrcSigned,
1384 bool isDestSigned,
1385 bool unpackPremultiplyAlpha,
1386 bool unpackUnmultiplyAlpha,
1387 GLenum destTypeForDownsampling)
1388 {
1389 bool floatToIntBlit =
1390 !gl::IsIntegerFormat(sourceFormat) && gl::IsIntegerFormat(destinationFormat);
1391
1392 if (isSrcSigned)
1393 {
1394 ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
1395 switch (destinationFormat)
1396 {
1397 case GL_RGBA_INTEGER:
1398 return RGBAI;
1399 case GL_RGB_INTEGER:
1400 return RGBI;
1401 case GL_RG_INTEGER:
1402 return RGI;
1403 case GL_RED_INTEGER:
1404 return RI;
1405 default:
1406 UNREACHABLE();
1407 return OPERATION_INVALID;
1408 }
1409 }
1410 else if (isDestSigned)
1411 {
1412 ASSERT(floatToIntBlit);
1413
1414 switch (destinationFormat)
1415 {
1416 case GL_RGBA_INTEGER:
1417 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1418 {
1419 return RGBAF_TOI;
1420 }
1421 return unpackPremultiplyAlpha ? RGBAF_TOI_PREMULTIPLY : RGBAF_TOI_UNMULTIPLY;
1422 case GL_RGB_INTEGER:
1423 case GL_RG_INTEGER:
1424 case GL_RED_INTEGER:
1425 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1426 {
1427 return RGBF_TOI;
1428 }
1429 return unpackPremultiplyAlpha ? RGBF_TOI_PREMULTIPLY : RGBF_TOI_UNMULTIPLY;
1430 default:
1431 UNREACHABLE();
1432 return OPERATION_INVALID;
1433 }
1434 }
1435 else
1436 {
1437 // Check for the downsample formats first
1438 switch (destTypeForDownsampling)
1439 {
1440 case GL_UNSIGNED_SHORT_4_4_4_4:
1441 ASSERT(destinationFormat == GL_RGBA && !floatToIntBlit);
1442 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1443 {
1444 return RGBAF_4444;
1445 }
1446 else if (unpackPremultiplyAlpha)
1447 {
1448 return RGBAF_4444_PREMULTIPLY;
1449 }
1450 else
1451 {
1452 return RGBAF_4444_UNMULTIPLY;
1453 }
1454
1455 case GL_UNSIGNED_SHORT_5_6_5:
1456 ASSERT(destinationFormat == GL_RGB && !floatToIntBlit);
1457 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1458 {
1459 return RGBF_565;
1460 }
1461 else
1462 {
1463 return unpackPremultiplyAlpha ? RGBF_565_PREMULTIPLY : RGBF_565_UNMULTIPLY;
1464 }
1465 case GL_UNSIGNED_SHORT_5_5_5_1:
1466 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1467 {
1468 return RGBAF_5551;
1469 }
1470 else
1471 {
1472 return unpackPremultiplyAlpha ? RGBAF_5551_PREMULTIPLY : RGBAF_5551_UNMULTIPLY;
1473 }
1474
1475 default:
1476 // By default, use the regular passthrough/multiply/unmultiply shaders. The above
1477 // shaders are only needed for some emulated texture formats.
1478 break;
1479 }
1480
1481 if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha || floatToIntBlit)
1482 {
1483 switch (destinationFormat)
1484 {
1485 case GL_RGBA:
1486 case GL_BGRA_EXT:
1487 ASSERT(!floatToIntBlit);
1488 return unpackPremultiplyAlpha ? RGBAF_PREMULTIPLY : RGBAF_UNMULTIPLY;
1489 case GL_RGB:
1490 case GL_RG:
1491 case GL_RED:
1492 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1493 {
1494 return RGBF_TOUI;
1495 }
1496 else
1497 {
1498 return unpackPremultiplyAlpha ? RGBF_PREMULTIPLY : RGBF_UNMULTIPLY;
1499 }
1500 case GL_RGBA_INTEGER:
1501 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1502 {
1503 return RGBAF_TOUI;
1504 }
1505 else
1506 {
1507 return unpackPremultiplyAlpha ? RGBAF_TOUI_PREMULTIPLY
1508 : RGBAF_TOUI_UNMULTIPLY;
1509 }
1510 case GL_RGB_INTEGER:
1511 case GL_RG_INTEGER:
1512 case GL_RED_INTEGER:
1513 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1514 {
1515 return RGBF_TOUI;
1516 }
1517 else
1518 {
1519 return unpackPremultiplyAlpha ? RGBF_TOUI_PREMULTIPLY
1520 : RGBF_TOUI_UNMULTIPLY;
1521 }
1522 case GL_LUMINANCE:
1523 ASSERT(!floatToIntBlit);
1524 return unpackPremultiplyAlpha ? LUMAF_PREMULTIPLY : LUMAF_UNMULTIPLY;
1525
1526 case GL_LUMINANCE_ALPHA:
1527 ASSERT(!floatToIntBlit);
1528 return unpackPremultiplyAlpha ? LUMAALPHAF_PREMULTIPLY : LUMAALPHAF_UNMULTIPLY;
1529 case GL_ALPHA:
1530 return ALPHA;
1531 default:
1532 UNREACHABLE();
1533 return OPERATION_INVALID;
1534 }
1535 }
1536 else
1537 {
1538 switch (destinationFormat)
1539 {
1540 case GL_RGBA:
1541 return RGBAF;
1542 case GL_RGBA_INTEGER:
1543 return RGBAUI;
1544 case GL_BGRA_EXT:
1545 return BGRAF;
1546 case GL_RGB:
1547 return RGBF;
1548 case GL_RGB_INTEGER:
1549 return RGBUI;
1550 case GL_RG:
1551 return RGF;
1552 case GL_RG_INTEGER:
1553 return RGUI;
1554 case GL_RED:
1555 return RF;
1556 case GL_RED_INTEGER:
1557 return RUI;
1558 case GL_ALPHA:
1559 return ALPHA;
1560 case GL_LUMINANCE:
1561 return LUMA;
1562 case GL_LUMINANCE_ALPHA:
1563 return LUMAALPHA;
1564 default:
1565 UNREACHABLE();
1566 return OPERATION_INVALID;
1567 }
1568 }
1569 }
1570 }
1571
getBlitShader(const gl::Context * context,GLenum destFormat,GLenum sourceFormat,bool isSrcSigned,bool isDestSigned,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,GLenum destTypeForDownsampling,ShaderDimension dimension,const Shader ** shader)1572 angle::Result Blit11::getBlitShader(const gl::Context *context,
1573 GLenum destFormat,
1574 GLenum sourceFormat,
1575 bool isSrcSigned,
1576 bool isDestSigned,
1577 bool unpackPremultiplyAlpha,
1578 bool unpackUnmultiplyAlpha,
1579 GLenum destTypeForDownsampling,
1580 ShaderDimension dimension,
1581 const Shader **shader)
1582 {
1583 BlitShaderOperation blitShaderOperation = OPERATION_INVALID;
1584
1585 blitShaderOperation = getBlitShaderOperation(destFormat, sourceFormat, isSrcSigned,
1586 isDestSigned, unpackPremultiplyAlpha,
1587 unpackUnmultiplyAlpha, destTypeForDownsampling);
1588
1589 BlitShaderType blitShaderType = BLITSHADER_INVALID;
1590
1591 blitShaderType = getBlitShaderType(blitShaderOperation, dimension);
1592
1593 ANGLE_CHECK_HR(GetImplAs<Context11>(context), blitShaderType != BLITSHADER_INVALID,
1594 "Internal blit shader type mismatch", E_FAIL);
1595
1596 auto blitShaderIt = mBlitShaderMap.find(blitShaderType);
1597 if (blitShaderIt != mBlitShaderMap.end())
1598 {
1599 *shader = &blitShaderIt->second;
1600 return angle::Result::Continue;
1601 }
1602
1603 ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable());
1604
1605 ANGLE_TRY(mapBlitShader(context, blitShaderType));
1606
1607 blitShaderIt = mBlitShaderMap.find(blitShaderType);
1608 ASSERT(blitShaderIt != mBlitShaderMap.end());
1609 *shader = &blitShaderIt->second;
1610 return angle::Result::Continue;
1611 }
1612
getSwizzleShader(const gl::Context * context,GLenum type,D3D11_SRV_DIMENSION viewDimension,const Shader ** shader)1613 angle::Result Blit11::getSwizzleShader(const gl::Context *context,
1614 GLenum type,
1615 D3D11_SRV_DIMENSION viewDimension,
1616 const Shader **shader)
1617 {
1618 SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension);
1619
1620 ANGLE_CHECK_HR(GetImplAs<Context11>(context), swizzleShaderType != SWIZZLESHADER_INVALID,
1621 "Swizzle shader type not found", E_FAIL);
1622
1623 auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
1624 if (swizzleShaderIt != mSwizzleShaderMap.end())
1625 {
1626 *shader = &swizzleShaderIt->second;
1627 return angle::Result::Continue;
1628 }
1629
1630 // Swizzling shaders (OpenGL ES 3+)
1631 ASSERT(mRenderer->isES3Capable());
1632
1633 switch (swizzleShaderType)
1634 {
1635 case SWIZZLESHADER_2D_FLOAT:
1636 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
1637 ShaderData(g_PS_SwizzleF2D),
1638 "Blit11 2D F swizzle pixel shader"));
1639 break;
1640 case SWIZZLESHADER_2D_UINT:
1641 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
1642 ShaderData(g_PS_SwizzleUI2D),
1643 "Blit11 2D UI swizzle pixel shader"));
1644 break;
1645 case SWIZZLESHADER_2D_INT:
1646 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
1647 ShaderData(g_PS_SwizzleI2D),
1648 "Blit11 2D I swizzle pixel shader"));
1649 break;
1650 case SWIZZLESHADER_CUBE_FLOAT:
1651 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1652 ShaderData(g_PS_SwizzleF2DArray),
1653 "Blit11 2D Cube F swizzle pixel shader"));
1654 break;
1655 case SWIZZLESHADER_CUBE_UINT:
1656 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1657 ShaderData(g_PS_SwizzleUI2DArray),
1658 "Blit11 2D Cube UI swizzle pixel shader"));
1659 break;
1660 case SWIZZLESHADER_CUBE_INT:
1661 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1662 ShaderData(g_PS_SwizzleI2DArray),
1663 "Blit11 2D Cube I swizzle pixel shader"));
1664 break;
1665 case SWIZZLESHADER_3D_FLOAT:
1666 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1667 ShaderData(g_PS_SwizzleF3D),
1668 "Blit11 3D F swizzle pixel shader"));
1669 break;
1670 case SWIZZLESHADER_3D_UINT:
1671 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1672 ShaderData(g_PS_SwizzleUI3D),
1673 "Blit11 3D UI swizzle pixel shader"));
1674 break;
1675 case SWIZZLESHADER_3D_INT:
1676 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1677 ShaderData(g_PS_SwizzleI3D),
1678 "Blit11 3D I swizzle pixel shader"));
1679 break;
1680 case SWIZZLESHADER_ARRAY_FLOAT:
1681 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1682 ShaderData(g_PS_SwizzleF2DArray),
1683 "Blit11 2D Array F swizzle pixel shader"));
1684 break;
1685 case SWIZZLESHADER_ARRAY_UINT:
1686 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1687 ShaderData(g_PS_SwizzleUI2DArray),
1688 "Blit11 2D Array UI swizzle pixel shader"));
1689 break;
1690 case SWIZZLESHADER_ARRAY_INT:
1691 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1692 ShaderData(g_PS_SwizzleI2DArray),
1693 "Blit11 2D Array I swizzle pixel shader"));
1694 break;
1695 default:
1696 ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1697 }
1698
1699 swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
1700 ASSERT(swizzleShaderIt != mSwizzleShaderMap.end());
1701 *shader = &swizzleShaderIt->second;
1702 return angle::Result::Continue;
1703 }
1704
resolveDepth(const gl::Context * context,RenderTarget11 * depth,TextureHelper11 * textureOut)1705 angle::Result Blit11::resolveDepth(const gl::Context *context,
1706 RenderTarget11 *depth,
1707 TextureHelper11 *textureOut)
1708 {
1709 ANGLE_TRY(initResources(context));
1710
1711 // Multisampled depth stencil SRVs are not available in feature level 10.0
1712 ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
1713
1714 const auto &extents = depth->getExtents();
1715 auto *deviceContext = mRenderer->getDeviceContext();
1716 auto *stateManager = mRenderer->getStateManager();
1717
1718 ANGLE_TRY(initResolveDepthOnly(context, depth->getFormatSet(), extents));
1719
1720 Context11 *context11 = GetImplAs<Context11>(context);
1721
1722 ANGLE_TRY(mResolveDepthStencilVS.resolve(context11, mRenderer));
1723 ANGLE_TRY(mResolveDepthPS.resolve(context11, mRenderer));
1724
1725 // Apply the necessary state changes to the D3D11 immediate device context.
1726 stateManager->setInputLayout(nullptr);
1727 stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1728 stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr,
1729 &mResolveDepthPS.getObj());
1730 stateManager->setRasterizerState(nullptr);
1731 stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
1732 stateManager->setRenderTargets(nullptr, 0, mResolvedDepthDSView.get());
1733 stateManager->setSimpleBlendState(nullptr);
1734 stateManager->setSimpleViewport(extents);
1735
1736 // Set the viewport
1737 stateManager->setShaderResourceShared(gl::ShaderType::Fragment, 0,
1738 &depth->getShaderResourceView(context));
1739
1740 // Trigger the blit on the GPU.
1741 deviceContext->Draw(6, 0);
1742
1743 *textureOut = mResolvedDepth;
1744 return angle::Result::Continue;
1745 }
1746
initResolveDepthOnly(const gl::Context * context,const d3d11::Format & format,const gl::Extents & extents)1747 angle::Result Blit11::initResolveDepthOnly(const gl::Context *context,
1748 const d3d11::Format &format,
1749 const gl::Extents &extents)
1750 {
1751 if (mResolvedDepth.valid() && extents == mResolvedDepth.getExtents() &&
1752 format.texFormat == mResolvedDepth.getFormat())
1753 {
1754 return angle::Result::Continue;
1755 }
1756
1757 D3D11_TEXTURE2D_DESC textureDesc;
1758 textureDesc.Width = extents.width;
1759 textureDesc.Height = extents.height;
1760 textureDesc.MipLevels = 1;
1761 textureDesc.ArraySize = 1;
1762 textureDesc.Format = format.texFormat;
1763 textureDesc.SampleDesc.Count = 1;
1764 textureDesc.SampleDesc.Quality = 0;
1765 textureDesc.Usage = D3D11_USAGE_DEFAULT;
1766 textureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
1767 textureDesc.CPUAccessFlags = 0;
1768 textureDesc.MiscFlags = 0;
1769
1770 Context11 *context11 = GetImplAs<Context11>(context);
1771
1772 ANGLE_TRY(mRenderer->allocateTexture(context11, textureDesc, format, &mResolvedDepth));
1773 mResolvedDepth.setDebugName("Blit11::mResolvedDepth");
1774
1775 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
1776 dsvDesc.Flags = 0;
1777 dsvDesc.Format = format.dsvFormat;
1778 dsvDesc.Texture2D.MipSlice = 0;
1779 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
1780
1781 ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, mResolvedDepth.get(),
1782 &mResolvedDepthDSView));
1783 mResolvedDepthDSView.setDebugName("Blit11::mResolvedDepthDSView");
1784
1785 // Possibly D3D11 bug or undefined behaviour: Clear the DSV so that our first render
1786 // works as expected. Otherwise the results of the first use seem to be incorrect.
1787 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1788 deviceContext->ClearDepthStencilView(mResolvedDepthDSView.get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
1789
1790 return angle::Result::Continue;
1791 }
1792
initResolveDepthStencil(const gl::Context * context,const gl::Extents & extents)1793 angle::Result Blit11::initResolveDepthStencil(const gl::Context *context,
1794 const gl::Extents &extents)
1795 {
1796 // Check if we need to recreate depth stencil view
1797 if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents())
1798 {
1799 ASSERT(mResolvedDepthStencil.getFormat() == DXGI_FORMAT_R32G32_FLOAT);
1800 return angle::Result::Continue;
1801 }
1802
1803 if (mResolvedDepthStencil.valid())
1804 {
1805 releaseResolveDepthStencilResources();
1806 }
1807
1808 const auto &formatSet = d3d11::Format::Get(GL_RG32F, mRenderer->getRenderer11DeviceCaps());
1809
1810 D3D11_TEXTURE2D_DESC textureDesc;
1811 textureDesc.Width = extents.width;
1812 textureDesc.Height = extents.height;
1813 textureDesc.MipLevels = 1;
1814 textureDesc.ArraySize = 1;
1815 textureDesc.Format = formatSet.texFormat;
1816 textureDesc.SampleDesc.Count = 1;
1817 textureDesc.SampleDesc.Quality = 0;
1818 textureDesc.Usage = D3D11_USAGE_DEFAULT;
1819 textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
1820 textureDesc.CPUAccessFlags = 0;
1821 textureDesc.MiscFlags = 0;
1822
1823 Context11 *context11 = GetImplAs<Context11>(context);
1824
1825 ANGLE_TRY(
1826 mRenderer->allocateTexture(context11, textureDesc, formatSet, &mResolvedDepthStencil));
1827 mResolvedDepthStencil.setDebugName("Blit11::mResolvedDepthStencil");
1828
1829 ANGLE_TRY(mRenderer->allocateResourceNoDesc(context11, mResolvedDepthStencil.get(),
1830 &mResolvedDepthStencilRTView));
1831 mResolvedDepthStencilRTView.setDebugName("Blit11::mResolvedDepthStencilRTView");
1832
1833 return angle::Result::Continue;
1834 }
1835
resolveStencil(const gl::Context * context,RenderTarget11 * depthStencil,bool alsoDepth,TextureHelper11 * textureOut)1836 angle::Result Blit11::resolveStencil(const gl::Context *context,
1837 RenderTarget11 *depthStencil,
1838 bool alsoDepth,
1839 TextureHelper11 *textureOut)
1840 {
1841 ANGLE_TRY(initResources(context));
1842
1843 // Multisampled depth stencil SRVs are not available in feature level 10.0
1844 ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
1845
1846 const auto &extents = depthStencil->getExtents();
1847
1848 ANGLE_TRY(initResolveDepthStencil(context, extents));
1849
1850 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1851 auto *stateManager = mRenderer->getStateManager();
1852 ID3D11Resource *stencilResource = depthStencil->getTexture().get();
1853
1854 // Check if we need to re-create the stencil SRV.
1855 if (mStencilSRV.valid())
1856 {
1857 ID3D11Resource *priorResource = nullptr;
1858 mStencilSRV.get()->GetResource(&priorResource);
1859
1860 if (stencilResource != priorResource)
1861 {
1862 mStencilSRV.reset();
1863 }
1864
1865 SafeRelease(priorResource);
1866 }
1867
1868 Context11 *context11 = GetImplAs<Context11>(context);
1869
1870 if (!mStencilSRV.valid())
1871 {
1872 D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc;
1873 srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet());
1874 srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
1875
1876 ANGLE_TRY(
1877 mRenderer->allocateResource(context11, srViewDesc, stencilResource, &mStencilSRV));
1878 mStencilSRV.setDebugName("Blit11::mStencilSRV");
1879 }
1880
1881 // Notify the Renderer that all state should be invalidated.
1882 ANGLE_TRY(mResolveDepthStencilVS.resolve(context11, mRenderer));
1883
1884 // Resolving the depth buffer works by sampling the depth in the shader using a SRV, then
1885 // writing to the resolved depth buffer using SV_Depth. We can't use this method for stencil
1886 // because SV_StencilRef isn't supported until HLSL 5.1/D3D11.3.
1887 const d3d11::PixelShader *pixelShader = nullptr;
1888 if (alsoDepth)
1889 {
1890 ANGLE_TRY(mResolveDepthStencilPS.resolve(context11, mRenderer));
1891 pixelShader = &mResolveDepthStencilPS.getObj();
1892 }
1893 else
1894 {
1895 ANGLE_TRY(mResolveStencilPS.resolve(context11, mRenderer));
1896 pixelShader = &mResolveStencilPS.getObj();
1897 }
1898
1899 // Apply the necessary state changes to the D3D11 immediate device context.
1900 stateManager->setInputLayout(nullptr);
1901 stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1902 stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr, pixelShader);
1903 stateManager->setRasterizerState(nullptr);
1904 stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
1905 stateManager->setRenderTarget(mResolvedDepthStencilRTView.get(), nullptr);
1906 stateManager->setSimpleBlendState(nullptr);
1907
1908 // Set the viewport
1909 stateManager->setSimpleViewport(extents);
1910 stateManager->setShaderResourceShared(gl::ShaderType::Fragment, 0,
1911 &depthStencil->getShaderResourceView(context));
1912 stateManager->setShaderResource(gl::ShaderType::Fragment, 1, &mStencilSRV);
1913
1914 // Trigger the blit on the GPU.
1915 deviceContext->Draw(6, 0);
1916
1917 gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
1918
1919 ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D,
1920 depthStencil->getFormatSet(), extents,
1921 StagingAccess::READ_WRITE, textureOut));
1922
1923 const auto ©Function = GetCopyDepthStencilFunction(depthStencil->getInternalFormat());
1924 const auto &dsFormatSet = depthStencil->getFormatSet();
1925 const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
1926
1927 ANGLE_TRY(copyAndConvertImpl(context, mResolvedDepthStencil, 0, copyBox, extents, *textureOut,
1928 copyBox, extents, nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes,
1929 copyFunction));
1930
1931 return angle::Result::Continue;
1932 }
1933
releaseResolveDepthStencilResources()1934 void Blit11::releaseResolveDepthStencilResources()
1935 {
1936 mStencilSRV.reset();
1937 mResolvedDepthStencilRTView.reset();
1938 }
1939
1940 } // namespace rx
1941