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/42264628
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.setInternalName("Blit11VertexBuffer");
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.setInternalName("Blit11PointSampler");
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.setInternalName("Blit11LinearSampler");
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.setInternalName("Blit11ScissoringRasterizerState");
652
653 rasterDesc.ScissorEnable = FALSE;
654 ANGLE_TRY(mRenderer->allocateResource(context11, rasterDesc, &mScissorDisabledRasterizerState));
655 mScissorDisabledRasterizerState.setInternalName("Blit11NoScissoringRasterizerState");
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.setInternalName("Blit11DepthStencilState");
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.setInternalName("Blit11SwizzleConstantBuffer");
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 bool isSrcSigned = (componentType == GL_INT);
941
942 D3D11_RENDER_TARGET_VIEW_DESC destRTVDesc;
943 dest.get()->GetDesc(&destRTVDesc);
944
945 GLenum destComponentType = d3d11::GetComponentType(destRTVDesc.Format);
946
947 ASSERT(componentType != GL_NONE);
948 bool isDestSigned = (destComponentType == GL_INT);
949
950 ShaderDimension dimension = SHADER_INVALID;
951
952 switch (sourceSRVDesc.ViewDimension)
953 {
954 case D3D11_SRV_DIMENSION_TEXTURE2D:
955 dimension = SHADER_2D;
956 break;
957 case D3D11_SRV_DIMENSION_TEXTURE3D:
958 dimension = SHADER_3D;
959 break;
960 case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
961 dimension = SHADER_2DARRAY;
962 break;
963 default:
964 UNREACHABLE();
965 }
966
967 const Shader *shader = nullptr;
968
969 ANGLE_TRY(getBlitShader(context, destFormat, sourceFormat, isSrcSigned, isDestSigned,
970 unpackPremultiplyAlpha, unpackUnmultiplyAlpha, destTypeForDownsampling,
971 dimension, &shader));
972
973 ShaderSupport support;
974 ANGLE_TRY(getShaderSupport(context, *shader, &support));
975
976 // Set vertices
977 D3D11_MAPPED_SUBRESOURCE mappedResource;
978 ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
979 &mappedResource));
980
981 UINT stride = 0;
982 UINT drawCount = 0;
983 D3D11_PRIMITIVE_TOPOLOGY topology;
984
985 support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData,
986 &stride, &drawCount, &topology);
987
988 deviceContext->Unmap(mVertexBuffer.get(), 0);
989
990 StateManager11 *stateManager = mRenderer->getStateManager();
991
992 // Apply vertex buffer
993 stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
994
995 // Apply state
996 if (maskOffAlpha)
997 {
998 ANGLE_TRY(mAlphaMaskBlendState.resolve(GetImplAs<Context11>(context), mRenderer));
999 stateManager->setSimpleBlendState(&mAlphaMaskBlendState.getObj());
1000 }
1001 else
1002 {
1003 stateManager->setSimpleBlendState(nullptr);
1004 }
1005 stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
1006
1007 if (scissor)
1008 {
1009 stateManager->setSimpleScissorRect(*scissor);
1010 stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
1011 }
1012 else
1013 {
1014 stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
1015 }
1016
1017 // Apply shaders
1018 stateManager->setInputLayout(support.inputLayout);
1019 stateManager->setPrimitiveTopology(topology);
1020
1021 stateManager->setDrawShaders(support.vertexShader, support.geometryShader,
1022 &shader->pixelShader);
1023
1024 // Apply render target
1025 stateManager->setRenderTarget(dest.get(), nullptr);
1026
1027 // Set the viewport
1028 stateManager->setSimpleViewport(destSize);
1029
1030 // Apply texture and sampler
1031 switch (filter)
1032 {
1033 case GL_NEAREST:
1034 stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
1035 break;
1036 case GL_LINEAR:
1037 stateManager->setSimplePixelTextureAndSampler(source, mLinearSampler);
1038 break;
1039
1040 default:
1041 UNREACHABLE();
1042 ANGLE_TRY_HR(GetImplAs<Context11>(context), E_FAIL,
1043 "Internal error, unknown blit filter mode.");
1044 }
1045
1046 // Draw the quad
1047 deviceContext->Draw(drawCount, 0);
1048
1049 return angle::Result::Continue;
1050 }
1051
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)1052 angle::Result Blit11::copyStencil(const gl::Context *context,
1053 const TextureHelper11 &source,
1054 unsigned int sourceSubresource,
1055 const gl::Box &sourceArea,
1056 const gl::Extents &sourceSize,
1057 const TextureHelper11 &dest,
1058 unsigned int destSubresource,
1059 const gl::Box &destArea,
1060 const gl::Extents &destSize,
1061 const gl::Rectangle *scissor)
1062 {
1063 return copyDepthStencilImpl(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1064 destSubresource, destArea, destSize, scissor, true);
1065 }
1066
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)1067 angle::Result Blit11::copyDepth(const gl::Context *context,
1068 const d3d11::SharedSRV &source,
1069 const gl::Box &sourceArea,
1070 const gl::Extents &sourceSize,
1071 const d3d11::DepthStencilView &dest,
1072 const gl::Box &destArea,
1073 const gl::Extents &destSize,
1074 const gl::Rectangle *scissor)
1075 {
1076 ANGLE_TRY(initResources(context));
1077
1078 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1079
1080 // Set vertices
1081 D3D11_MAPPED_SUBRESOURCE mappedResource;
1082 ANGLE_TRY(mRenderer->mapResource(context, mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0,
1083 &mappedResource));
1084
1085 UINT stride = 0;
1086 UINT drawCount = 0;
1087 D3D11_PRIMITIVE_TOPOLOGY topology;
1088
1089 Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride,
1090 &drawCount, &topology);
1091
1092 deviceContext->Unmap(mVertexBuffer.get(), 0);
1093
1094 StateManager11 *stateManager = mRenderer->getStateManager();
1095
1096 // Apply vertex buffer
1097 stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0);
1098
1099 // Apply state
1100 stateManager->setSimpleBlendState(nullptr);
1101 stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
1102
1103 if (scissor)
1104 {
1105 stateManager->setSimpleScissorRect(*scissor);
1106 stateManager->setRasterizerState(&mScissorEnabledRasterizerState);
1107 }
1108 else
1109 {
1110 stateManager->setRasterizerState(&mScissorDisabledRasterizerState);
1111 }
1112
1113 Context11 *context11 = GetImplAs<Context11>(context);
1114
1115 ANGLE_TRY(mQuad2DIL.resolve(context11, mRenderer));
1116 ANGLE_TRY(mQuad2DVS.resolve(context11, mRenderer));
1117 ANGLE_TRY(mDepthPS.resolve(context11, mRenderer));
1118
1119 // Apply shaders
1120 stateManager->setInputLayout(&mQuad2DIL.getObj());
1121 stateManager->setPrimitiveTopology(topology);
1122
1123 stateManager->setDrawShaders(&mQuad2DVS.getObj(), nullptr, &mDepthPS.getObj());
1124
1125 // Apply render target
1126 stateManager->setRenderTarget(nullptr, dest.get());
1127
1128 // Set the viewport
1129 stateManager->setSimpleViewport(destSize);
1130
1131 // Apply texture and sampler
1132 stateManager->setSimplePixelTextureAndSampler(source, mPointSampler);
1133
1134 // Draw the quad
1135 deviceContext->Draw(drawCount, 0);
1136
1137 return angle::Result::Continue;
1138 }
1139
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)1140 angle::Result Blit11::copyDepthStencil(const gl::Context *context,
1141 const TextureHelper11 &source,
1142 unsigned int sourceSubresource,
1143 const gl::Box &sourceArea,
1144 const gl::Extents &sourceSize,
1145 const TextureHelper11 &dest,
1146 unsigned int destSubresource,
1147 const gl::Box &destArea,
1148 const gl::Extents &destSize,
1149 const gl::Rectangle *scissor)
1150 {
1151 return copyDepthStencilImpl(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1152 destSubresource, destArea, destSize, scissor, false);
1153 }
1154
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)1155 angle::Result Blit11::copyDepthStencilImpl(const gl::Context *context,
1156 const TextureHelper11 &source,
1157 unsigned int sourceSubresource,
1158 const gl::Box &sourceArea,
1159 const gl::Extents &sourceSize,
1160 const TextureHelper11 &dest,
1161 unsigned int destSubresource,
1162 const gl::Box &destArea,
1163 const gl::Extents &destSize,
1164 const gl::Rectangle *scissor,
1165 bool stencilOnly)
1166 {
1167 auto srcDXGIFormat = source.getFormat();
1168 const auto &srcSizeInfo = d3d11::GetDXGIFormatSizeInfo(srcDXGIFormat);
1169 unsigned int srcPixelSize = srcSizeInfo.pixelBytes;
1170 unsigned int copyOffset = 0;
1171 unsigned int copySize = srcPixelSize;
1172 auto destDXGIFormat = dest.getFormat();
1173 const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destDXGIFormat);
1174 unsigned int destPixelSize = destSizeInfo.pixelBytes;
1175
1176 ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS);
1177
1178 if (stencilOnly)
1179 {
1180 const auto &srcFormat = source.getFormatSet().format();
1181
1182 // Stencil channel should be right after the depth channel. Some views to depth/stencil
1183 // resources have red channel for depth, in which case the depth channel bit width is in
1184 // redBits.
1185 ASSERT((srcFormat.redBits != 0) != (srcFormat.depthBits != 0));
1186 GLuint depthBits = srcFormat.redBits + srcFormat.depthBits;
1187 // Known formats have either 24 or 32 bits of depth.
1188 ASSERT(depthBits == 24 || depthBits == 32);
1189 copyOffset = depthBits / 8;
1190
1191 // Stencil is assumed to be 8-bit - currently this is true for all possible formats.
1192 copySize = 1;
1193 }
1194
1195 if (srcDXGIFormat != destDXGIFormat)
1196 {
1197 if (srcDXGIFormat == DXGI_FORMAT_R24G8_TYPELESS)
1198 {
1199 ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr);
1200 return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1201 destSubresource, destArea, destSize, scissor, copyOffset,
1202 copyOffset, copySize, srcPixelSize, destPixelSize,
1203 BlitD24S8ToD32F);
1204 }
1205 ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS);
1206 return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1207 destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
1208 copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F);
1209 }
1210
1211 return copyAndConvert(context, source, sourceSubresource, sourceArea, sourceSize, dest,
1212 destSubresource, destArea, destSize, scissor, copyOffset, copyOffset,
1213 copySize, srcPixelSize, destPixelSize, StretchedBlitNearest);
1214 }
1215
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)1216 angle::Result Blit11::copyAndConvertImpl(const gl::Context *context,
1217 const TextureHelper11 &source,
1218 unsigned int sourceSubresource,
1219 const gl::Box &sourceArea,
1220 const gl::Extents &sourceSize,
1221 const TextureHelper11 &destStaging,
1222 const gl::Box &destArea,
1223 const gl::Extents &destSize,
1224 const gl::Rectangle *scissor,
1225 size_t readOffset,
1226 size_t writeOffset,
1227 size_t copySize,
1228 size_t srcPixelStride,
1229 size_t destPixelStride,
1230 BlitConvertFunction *convertFunction)
1231 {
1232 ANGLE_TRY(initResources(context));
1233
1234 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1235
1236 TextureHelper11 sourceStaging;
1237 ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D,
1238 source.getFormatSet(), sourceSize,
1239 StagingAccess::READ, &sourceStaging));
1240
1241 deviceContext->CopySubresourceRegion(sourceStaging.get(), 0, 0, 0, 0, source.get(),
1242 sourceSubresource, nullptr);
1243
1244 D3D11_MAPPED_SUBRESOURCE sourceMapping;
1245 ANGLE_TRY(
1246 mRenderer->mapResource(context, sourceStaging.get(), 0, D3D11_MAP_READ, 0, &sourceMapping));
1247
1248 D3D11_MAPPED_SUBRESOURCE destMapping;
1249 angle::Result error =
1250 mRenderer->mapResource(context, destStaging.get(), 0, D3D11_MAP_WRITE, 0, &destMapping);
1251 if (error == angle::Result::Stop)
1252 {
1253 deviceContext->Unmap(sourceStaging.get(), 0);
1254 return error;
1255 }
1256
1257 // Clip dest area to the destination size
1258 gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height);
1259
1260 // Clip dest area to the scissor
1261 if (scissor)
1262 {
1263 if (!gl::ClipRectangle(clipRect, *scissor, &clipRect))
1264 {
1265 return angle::Result::Continue;
1266 }
1267 }
1268
1269 convertFunction(sourceArea, destArea, clipRect, sourceSize, sourceMapping.RowPitch,
1270 destMapping.RowPitch, readOffset, writeOffset, copySize, srcPixelStride,
1271 destPixelStride, static_cast<const uint8_t *>(sourceMapping.pData),
1272 static_cast<uint8_t *>(destMapping.pData));
1273
1274 deviceContext->Unmap(sourceStaging.get(), 0);
1275 deviceContext->Unmap(destStaging.get(), 0);
1276
1277 return angle::Result::Continue;
1278 }
1279
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)1280 angle::Result Blit11::copyAndConvert(const gl::Context *context,
1281 const TextureHelper11 &source,
1282 unsigned int sourceSubresource,
1283 const gl::Box &sourceArea,
1284 const gl::Extents &sourceSize,
1285 const TextureHelper11 &dest,
1286 unsigned int destSubresource,
1287 const gl::Box &destArea,
1288 const gl::Extents &destSize,
1289 const gl::Rectangle *scissor,
1290 size_t readOffset,
1291 size_t writeOffset,
1292 size_t copySize,
1293 size_t srcPixelStride,
1294 size_t destPixelStride,
1295 BlitConvertFunction *convertFunction)
1296 {
1297 ANGLE_TRY(initResources(context));
1298
1299 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1300
1301 // HACK: Create the destination staging buffer as a read/write texture so
1302 // ID3D11DevicContext::UpdateSubresource can be called
1303 // using it's mapped data as a source
1304 TextureHelper11 destStaging;
1305 ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D, dest.getFormatSet(),
1306 destSize, StagingAccess::READ_WRITE, &destStaging));
1307
1308 deviceContext->CopySubresourceRegion(destStaging.get(), 0, 0, 0, 0, dest.get(), destSubresource,
1309 nullptr);
1310
1311 ANGLE_TRY(copyAndConvertImpl(context, source, sourceSubresource, sourceArea, sourceSize,
1312 destStaging, destArea, destSize, scissor, readOffset, writeOffset,
1313 copySize, srcPixelStride, destPixelStride, convertFunction));
1314
1315 // Work around timeouts/TDRs in older NVIDIA drivers.
1316 if (mRenderer->getFeatures().depthStencilBlitExtraCopy.enabled)
1317 {
1318 D3D11_MAPPED_SUBRESOURCE mapped;
1319 ANGLE_TRY(
1320 mRenderer->mapResource(context, destStaging.get(), 0, D3D11_MAP_READ, 0, &mapped));
1321 deviceContext->UpdateSubresource(dest.get(), destSubresource, nullptr, mapped.pData,
1322 mapped.RowPitch, mapped.DepthPitch);
1323 deviceContext->Unmap(destStaging.get(), 0);
1324 }
1325 else
1326 {
1327 deviceContext->CopySubresourceRegion(dest.get(), destSubresource, 0, 0, 0,
1328 destStaging.get(), 0, nullptr);
1329 }
1330
1331 return angle::Result::Continue;
1332 }
1333
addBlitShaderToMap(const gl::Context * context,BlitShaderType blitShaderType,ShaderDimension dimension,const ShaderData & shaderData,const char * name)1334 angle::Result Blit11::addBlitShaderToMap(const gl::Context *context,
1335 BlitShaderType blitShaderType,
1336 ShaderDimension dimension,
1337 const ShaderData &shaderData,
1338 const char *name)
1339 {
1340 ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end());
1341
1342 d3d11::PixelShader ps;
1343 ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), shaderData, &ps));
1344 ps.setInternalName(name);
1345
1346 Shader shader;
1347 shader.dimension = dimension;
1348 shader.pixelShader = std::move(ps);
1349
1350 mBlitShaderMap[blitShaderType] = std::move(shader);
1351 return angle::Result::Continue;
1352 }
1353
addSwizzleShaderToMap(const gl::Context * context,SwizzleShaderType swizzleShaderType,ShaderDimension dimension,const ShaderData & shaderData,const char * name)1354 angle::Result Blit11::addSwizzleShaderToMap(const gl::Context *context,
1355 SwizzleShaderType swizzleShaderType,
1356 ShaderDimension dimension,
1357 const ShaderData &shaderData,
1358 const char *name)
1359 {
1360 ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end());
1361
1362 d3d11::PixelShader ps;
1363 ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), shaderData, &ps));
1364 ps.setInternalName(name);
1365
1366 Shader shader;
1367 shader.dimension = dimension;
1368 shader.pixelShader = std::move(ps);
1369
1370 mSwizzleShaderMap[swizzleShaderType] = std::move(shader);
1371 return angle::Result::Continue;
1372 }
1373
clearShaderMap()1374 void Blit11::clearShaderMap()
1375 {
1376 mBlitShaderMap.clear();
1377 mSwizzleShaderMap.clear();
1378 }
1379
getBlitShaderOperation(GLenum destinationFormat,GLenum sourceFormat,bool isSrcSigned,bool isDestSigned,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,GLenum destTypeForDownsampling)1380 Blit11::BlitShaderOperation Blit11::getBlitShaderOperation(GLenum destinationFormat,
1381 GLenum sourceFormat,
1382 bool isSrcSigned,
1383 bool isDestSigned,
1384 bool unpackPremultiplyAlpha,
1385 bool unpackUnmultiplyAlpha,
1386 GLenum destTypeForDownsampling)
1387 {
1388 bool floatToIntBlit =
1389 !gl::IsIntegerFormat(sourceFormat) && gl::IsIntegerFormat(destinationFormat);
1390
1391 if (isSrcSigned)
1392 {
1393 ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha);
1394 switch (destinationFormat)
1395 {
1396 case GL_RGBA_INTEGER:
1397 return RGBAI;
1398 case GL_RGB_INTEGER:
1399 return RGBI;
1400 case GL_RG_INTEGER:
1401 return RGI;
1402 case GL_RED_INTEGER:
1403 return RI;
1404 default:
1405 UNREACHABLE();
1406 return OPERATION_INVALID;
1407 }
1408 }
1409 else if (isDestSigned)
1410 {
1411 ASSERT(floatToIntBlit);
1412
1413 switch (destinationFormat)
1414 {
1415 case GL_RGBA_INTEGER:
1416 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1417 {
1418 return RGBAF_TOI;
1419 }
1420 return unpackPremultiplyAlpha ? RGBAF_TOI_PREMULTIPLY : RGBAF_TOI_UNMULTIPLY;
1421 case GL_RGB_INTEGER:
1422 case GL_RG_INTEGER:
1423 case GL_RED_INTEGER:
1424 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1425 {
1426 return RGBF_TOI;
1427 }
1428 return unpackPremultiplyAlpha ? RGBF_TOI_PREMULTIPLY : RGBF_TOI_UNMULTIPLY;
1429 default:
1430 UNREACHABLE();
1431 return OPERATION_INVALID;
1432 }
1433 }
1434 else
1435 {
1436 // Check for the downsample formats first
1437 switch (destTypeForDownsampling)
1438 {
1439 case GL_UNSIGNED_SHORT_4_4_4_4:
1440 ASSERT(destinationFormat == GL_RGBA && !floatToIntBlit);
1441 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1442 {
1443 return RGBAF_4444;
1444 }
1445 else if (unpackPremultiplyAlpha)
1446 {
1447 return RGBAF_4444_PREMULTIPLY;
1448 }
1449 else
1450 {
1451 return RGBAF_4444_UNMULTIPLY;
1452 }
1453
1454 case GL_UNSIGNED_SHORT_5_6_5:
1455 ASSERT(destinationFormat == GL_RGB && !floatToIntBlit);
1456 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1457 {
1458 return RGBF_565;
1459 }
1460 else
1461 {
1462 return unpackPremultiplyAlpha ? RGBF_565_PREMULTIPLY : RGBF_565_UNMULTIPLY;
1463 }
1464 case GL_UNSIGNED_SHORT_5_5_5_1:
1465 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1466 {
1467 return RGBAF_5551;
1468 }
1469 else
1470 {
1471 return unpackPremultiplyAlpha ? RGBAF_5551_PREMULTIPLY : RGBAF_5551_UNMULTIPLY;
1472 }
1473
1474 default:
1475 // By default, use the regular passthrough/multiply/unmultiply shaders. The above
1476 // shaders are only needed for some emulated texture formats.
1477 break;
1478 }
1479
1480 if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha || floatToIntBlit)
1481 {
1482 switch (destinationFormat)
1483 {
1484 case GL_RGBA:
1485 case GL_BGRA_EXT:
1486 ASSERT(!floatToIntBlit);
1487 return unpackPremultiplyAlpha ? RGBAF_PREMULTIPLY : RGBAF_UNMULTIPLY;
1488 case GL_RGB:
1489 case GL_RG:
1490 case GL_RED:
1491 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1492 {
1493 return RGBF_TOUI;
1494 }
1495 else
1496 {
1497 return unpackPremultiplyAlpha ? RGBF_PREMULTIPLY : RGBF_UNMULTIPLY;
1498 }
1499 case GL_RGBA_INTEGER:
1500 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1501 {
1502 return RGBAF_TOUI;
1503 }
1504 else
1505 {
1506 return unpackPremultiplyAlpha ? RGBAF_TOUI_PREMULTIPLY
1507 : RGBAF_TOUI_UNMULTIPLY;
1508 }
1509 case GL_RGB_INTEGER:
1510 case GL_RG_INTEGER:
1511 case GL_RED_INTEGER:
1512 if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha)
1513 {
1514 return RGBF_TOUI;
1515 }
1516 else
1517 {
1518 return unpackPremultiplyAlpha ? RGBF_TOUI_PREMULTIPLY
1519 : RGBF_TOUI_UNMULTIPLY;
1520 }
1521 case GL_LUMINANCE:
1522 ASSERT(!floatToIntBlit);
1523 return unpackPremultiplyAlpha ? LUMAF_PREMULTIPLY : LUMAF_UNMULTIPLY;
1524
1525 case GL_LUMINANCE_ALPHA:
1526 ASSERT(!floatToIntBlit);
1527 return unpackPremultiplyAlpha ? LUMAALPHAF_PREMULTIPLY : LUMAALPHAF_UNMULTIPLY;
1528 case GL_ALPHA:
1529 return ALPHA;
1530 default:
1531 UNREACHABLE();
1532 return OPERATION_INVALID;
1533 }
1534 }
1535 else
1536 {
1537 switch (destinationFormat)
1538 {
1539 case GL_RGBA:
1540 return RGBAF;
1541 case GL_RGBA_INTEGER:
1542 return RGBAUI;
1543 case GL_BGRA_EXT:
1544 return BGRAF;
1545 case GL_RGB:
1546 return RGBF;
1547 case GL_RGB_INTEGER:
1548 return RGBUI;
1549 case GL_RG:
1550 return RGF;
1551 case GL_RG_INTEGER:
1552 return RGUI;
1553 case GL_RED:
1554 return RF;
1555 case GL_RED_INTEGER:
1556 return RUI;
1557 case GL_ALPHA:
1558 return ALPHA;
1559 case GL_LUMINANCE:
1560 return LUMA;
1561 case GL_LUMINANCE_ALPHA:
1562 return LUMAALPHA;
1563 default:
1564 UNREACHABLE();
1565 return OPERATION_INVALID;
1566 }
1567 }
1568 }
1569 }
1570
getBlitShader(const gl::Context * context,GLenum destFormat,GLenum sourceFormat,bool isSrcSigned,bool isDestSigned,bool unpackPremultiplyAlpha,bool unpackUnmultiplyAlpha,GLenum destTypeForDownsampling,ShaderDimension dimension,const Shader ** shader)1571 angle::Result Blit11::getBlitShader(const gl::Context *context,
1572 GLenum destFormat,
1573 GLenum sourceFormat,
1574 bool isSrcSigned,
1575 bool isDestSigned,
1576 bool unpackPremultiplyAlpha,
1577 bool unpackUnmultiplyAlpha,
1578 GLenum destTypeForDownsampling,
1579 ShaderDimension dimension,
1580 const Shader **shader)
1581 {
1582 BlitShaderOperation blitShaderOperation = OPERATION_INVALID;
1583
1584 blitShaderOperation = getBlitShaderOperation(destFormat, sourceFormat, isSrcSigned,
1585 isDestSigned, unpackPremultiplyAlpha,
1586 unpackUnmultiplyAlpha, destTypeForDownsampling);
1587
1588 BlitShaderType blitShaderType = BLITSHADER_INVALID;
1589
1590 blitShaderType = getBlitShaderType(blitShaderOperation, dimension);
1591
1592 ANGLE_CHECK_HR(GetImplAs<Context11>(context), blitShaderType != BLITSHADER_INVALID,
1593 "Internal blit shader type mismatch", E_FAIL);
1594
1595 auto blitShaderIt = mBlitShaderMap.find(blitShaderType);
1596 if (blitShaderIt != mBlitShaderMap.end())
1597 {
1598 *shader = &blitShaderIt->second;
1599 return angle::Result::Continue;
1600 }
1601
1602 ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable());
1603
1604 ANGLE_TRY(mapBlitShader(context, blitShaderType));
1605
1606 blitShaderIt = mBlitShaderMap.find(blitShaderType);
1607 ASSERT(blitShaderIt != mBlitShaderMap.end());
1608 *shader = &blitShaderIt->second;
1609 return angle::Result::Continue;
1610 }
1611
getSwizzleShader(const gl::Context * context,GLenum type,D3D11_SRV_DIMENSION viewDimension,const Shader ** shader)1612 angle::Result Blit11::getSwizzleShader(const gl::Context *context,
1613 GLenum type,
1614 D3D11_SRV_DIMENSION viewDimension,
1615 const Shader **shader)
1616 {
1617 SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension);
1618
1619 ANGLE_CHECK_HR(GetImplAs<Context11>(context), swizzleShaderType != SWIZZLESHADER_INVALID,
1620 "Swizzle shader type not found", E_FAIL);
1621
1622 auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
1623 if (swizzleShaderIt != mSwizzleShaderMap.end())
1624 {
1625 *shader = &swizzleShaderIt->second;
1626 return angle::Result::Continue;
1627 }
1628
1629 // Swizzling shaders (OpenGL ES 3+)
1630 ASSERT(mRenderer->isES3Capable());
1631
1632 switch (swizzleShaderType)
1633 {
1634 case SWIZZLESHADER_2D_FLOAT:
1635 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
1636 ShaderData(g_PS_SwizzleF2D),
1637 "Blit11 2D F swizzle pixel shader"));
1638 break;
1639 case SWIZZLESHADER_2D_UINT:
1640 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
1641 ShaderData(g_PS_SwizzleUI2D),
1642 "Blit11 2D UI swizzle pixel shader"));
1643 break;
1644 case SWIZZLESHADER_2D_INT:
1645 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_2D,
1646 ShaderData(g_PS_SwizzleI2D),
1647 "Blit11 2D I swizzle pixel shader"));
1648 break;
1649 case SWIZZLESHADER_CUBE_FLOAT:
1650 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1651 ShaderData(g_PS_SwizzleF2DArray),
1652 "Blit11 2D Cube F swizzle pixel shader"));
1653 break;
1654 case SWIZZLESHADER_CUBE_UINT:
1655 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1656 ShaderData(g_PS_SwizzleUI2DArray),
1657 "Blit11 2D Cube UI swizzle pixel shader"));
1658 break;
1659 case SWIZZLESHADER_CUBE_INT:
1660 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1661 ShaderData(g_PS_SwizzleI2DArray),
1662 "Blit11 2D Cube I swizzle pixel shader"));
1663 break;
1664 case SWIZZLESHADER_3D_FLOAT:
1665 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1666 ShaderData(g_PS_SwizzleF3D),
1667 "Blit11 3D F swizzle pixel shader"));
1668 break;
1669 case SWIZZLESHADER_3D_UINT:
1670 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1671 ShaderData(g_PS_SwizzleUI3D),
1672 "Blit11 3D UI swizzle pixel shader"));
1673 break;
1674 case SWIZZLESHADER_3D_INT:
1675 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1676 ShaderData(g_PS_SwizzleI3D),
1677 "Blit11 3D I swizzle pixel shader"));
1678 break;
1679 case SWIZZLESHADER_ARRAY_FLOAT:
1680 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1681 ShaderData(g_PS_SwizzleF2DArray),
1682 "Blit11 2D Array F swizzle pixel shader"));
1683 break;
1684 case SWIZZLESHADER_ARRAY_UINT:
1685 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1686 ShaderData(g_PS_SwizzleUI2DArray),
1687 "Blit11 2D Array UI swizzle pixel shader"));
1688 break;
1689 case SWIZZLESHADER_ARRAY_INT:
1690 ANGLE_TRY(addSwizzleShaderToMap(context, swizzleShaderType, SHADER_3D,
1691 ShaderData(g_PS_SwizzleI2DArray),
1692 "Blit11 2D Array I swizzle pixel shader"));
1693 break;
1694 default:
1695 ANGLE_HR_UNREACHABLE(GetImplAs<Context11>(context));
1696 }
1697
1698 swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType);
1699 ASSERT(swizzleShaderIt != mSwizzleShaderMap.end());
1700 *shader = &swizzleShaderIt->second;
1701 return angle::Result::Continue;
1702 }
1703
resolveDepth(const gl::Context * context,RenderTarget11 * depth,TextureHelper11 * textureOut)1704 angle::Result Blit11::resolveDepth(const gl::Context *context,
1705 RenderTarget11 *depth,
1706 TextureHelper11 *textureOut)
1707 {
1708 ANGLE_TRY(initResources(context));
1709
1710 // Multisampled depth stencil SRVs are not available in feature level 10.0
1711 ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
1712
1713 const auto &extents = depth->getExtents();
1714 auto *deviceContext = mRenderer->getDeviceContext();
1715 auto *stateManager = mRenderer->getStateManager();
1716
1717 ANGLE_TRY(initResolveDepthOnly(context, depth->getFormatSet(), extents));
1718
1719 Context11 *context11 = GetImplAs<Context11>(context);
1720
1721 ANGLE_TRY(mResolveDepthStencilVS.resolve(context11, mRenderer));
1722 ANGLE_TRY(mResolveDepthPS.resolve(context11, mRenderer));
1723
1724 // Apply the necessary state changes to the D3D11 immediate device context.
1725 stateManager->setInputLayout(nullptr);
1726 stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1727 stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr,
1728 &mResolveDepthPS.getObj());
1729 stateManager->setRasterizerState(nullptr);
1730 stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF);
1731 stateManager->setRenderTargets(nullptr, 0, mResolvedDepthDSView.get());
1732 stateManager->setSimpleBlendState(nullptr);
1733 stateManager->setSimpleViewport(extents);
1734
1735 // Set the viewport
1736 const d3d11::SharedSRV *srv;
1737 ANGLE_TRY(depth->getShaderResourceView(context, &srv));
1738
1739 stateManager->setShaderResourceShared(gl::ShaderType::Fragment, 0, srv);
1740
1741 // Trigger the blit on the GPU.
1742 deviceContext->Draw(6, 0);
1743
1744 *textureOut = mResolvedDepth;
1745 return angle::Result::Continue;
1746 }
1747
initResolveDepthOnly(const gl::Context * context,const d3d11::Format & format,const gl::Extents & extents)1748 angle::Result Blit11::initResolveDepthOnly(const gl::Context *context,
1749 const d3d11::Format &format,
1750 const gl::Extents &extents)
1751 {
1752 if (mResolvedDepth.valid() && extents == mResolvedDepth.getExtents() &&
1753 format.texFormat == mResolvedDepth.getFormat())
1754 {
1755 return angle::Result::Continue;
1756 }
1757
1758 D3D11_TEXTURE2D_DESC textureDesc;
1759 textureDesc.Width = extents.width;
1760 textureDesc.Height = extents.height;
1761 textureDesc.MipLevels = 1;
1762 textureDesc.ArraySize = 1;
1763 textureDesc.Format = format.texFormat;
1764 textureDesc.SampleDesc.Count = 1;
1765 textureDesc.SampleDesc.Quality = 0;
1766 textureDesc.Usage = D3D11_USAGE_DEFAULT;
1767 textureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
1768 textureDesc.CPUAccessFlags = 0;
1769 textureDesc.MiscFlags = 0;
1770
1771 Context11 *context11 = GetImplAs<Context11>(context);
1772
1773 ANGLE_TRY(mRenderer->allocateTexture(context11, textureDesc, format, &mResolvedDepth));
1774 mResolvedDepth.setInternalName("Blit11::mResolvedDepth");
1775
1776 D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc;
1777 dsvDesc.Flags = 0;
1778 dsvDesc.Format = format.dsvFormat;
1779 dsvDesc.Texture2D.MipSlice = 0;
1780 dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
1781
1782 ANGLE_TRY(mRenderer->allocateResource(context11, dsvDesc, mResolvedDepth.get(),
1783 &mResolvedDepthDSView));
1784 mResolvedDepthDSView.setInternalName("Blit11::mResolvedDepthDSView");
1785
1786 // Possibly D3D11 bug or undefined behaviour: Clear the DSV so that our first render
1787 // works as expected. Otherwise the results of the first use seem to be incorrect.
1788 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1789 deviceContext->ClearDepthStencilView(mResolvedDepthDSView.get(), D3D11_CLEAR_DEPTH, 1.0f, 0);
1790
1791 return angle::Result::Continue;
1792 }
1793
initResolveDepthStencil(const gl::Context * context,const gl::Extents & extents)1794 angle::Result Blit11::initResolveDepthStencil(const gl::Context *context,
1795 const gl::Extents &extents)
1796 {
1797 // Check if we need to recreate depth stencil view
1798 if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents())
1799 {
1800 ASSERT(mResolvedDepthStencil.getFormat() == DXGI_FORMAT_R32G32_FLOAT);
1801 return angle::Result::Continue;
1802 }
1803
1804 if (mResolvedDepthStencil.valid())
1805 {
1806 releaseResolveDepthStencilResources();
1807 }
1808
1809 const auto &formatSet = d3d11::Format::Get(GL_RG32F, mRenderer->getRenderer11DeviceCaps());
1810
1811 D3D11_TEXTURE2D_DESC textureDesc;
1812 textureDesc.Width = extents.width;
1813 textureDesc.Height = extents.height;
1814 textureDesc.MipLevels = 1;
1815 textureDesc.ArraySize = 1;
1816 textureDesc.Format = formatSet.texFormat;
1817 textureDesc.SampleDesc.Count = 1;
1818 textureDesc.SampleDesc.Quality = 0;
1819 textureDesc.Usage = D3D11_USAGE_DEFAULT;
1820 textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET;
1821 textureDesc.CPUAccessFlags = 0;
1822 textureDesc.MiscFlags = 0;
1823
1824 Context11 *context11 = GetImplAs<Context11>(context);
1825
1826 ANGLE_TRY(
1827 mRenderer->allocateTexture(context11, textureDesc, formatSet, &mResolvedDepthStencil));
1828 mResolvedDepthStencil.setInternalName("Blit11::mResolvedDepthStencil");
1829
1830 ANGLE_TRY(mRenderer->allocateResourceNoDesc(context11, mResolvedDepthStencil.get(),
1831 &mResolvedDepthStencilRTView));
1832 mResolvedDepthStencilRTView.setInternalName("Blit11::mResolvedDepthStencilRTView");
1833
1834 return angle::Result::Continue;
1835 }
1836
resolveStencil(const gl::Context * context,RenderTarget11 * depthStencil,bool alsoDepth,TextureHelper11 * textureOut)1837 angle::Result Blit11::resolveStencil(const gl::Context *context,
1838 RenderTarget11 *depthStencil,
1839 bool alsoDepth,
1840 TextureHelper11 *textureOut)
1841 {
1842 ANGLE_TRY(initResources(context));
1843
1844 // Multisampled depth stencil SRVs are not available in feature level 10.0
1845 ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0);
1846
1847 const auto &extents = depthStencil->getExtents();
1848
1849 ANGLE_TRY(initResolveDepthStencil(context, extents));
1850
1851 ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
1852 auto *stateManager = mRenderer->getStateManager();
1853 ID3D11Resource *stencilResource = depthStencil->getTexture().get();
1854
1855 // Check if we need to re-create the stencil SRV.
1856 if (mStencilSRV.valid())
1857 {
1858 ID3D11Resource *priorResource = nullptr;
1859 mStencilSRV.get()->GetResource(&priorResource);
1860
1861 if (stencilResource != priorResource)
1862 {
1863 mStencilSRV.reset();
1864 }
1865
1866 SafeRelease(priorResource);
1867 }
1868
1869 Context11 *context11 = GetImplAs<Context11>(context);
1870
1871 if (!mStencilSRV.valid())
1872 {
1873 D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc;
1874 srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet());
1875 srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
1876
1877 ANGLE_TRY(
1878 mRenderer->allocateResource(context11, srViewDesc, stencilResource, &mStencilSRV));
1879 mStencilSRV.setInternalName("Blit11::mStencilSRV");
1880 }
1881
1882 // Notify the Renderer that all state should be invalidated.
1883 ANGLE_TRY(mResolveDepthStencilVS.resolve(context11, mRenderer));
1884
1885 // Resolving the depth buffer works by sampling the depth in the shader using a SRV, then
1886 // writing to the resolved depth buffer using SV_Depth. We can't use this method for stencil
1887 // because SV_StencilRef isn't supported until HLSL 5.1/D3D11.3.
1888 const d3d11::PixelShader *pixelShader = nullptr;
1889 if (alsoDepth)
1890 {
1891 ANGLE_TRY(mResolveDepthStencilPS.resolve(context11, mRenderer));
1892 pixelShader = &mResolveDepthStencilPS.getObj();
1893 }
1894 else
1895 {
1896 ANGLE_TRY(mResolveStencilPS.resolve(context11, mRenderer));
1897 pixelShader = &mResolveStencilPS.getObj();
1898 }
1899
1900 // Apply the necessary state changes to the D3D11 immediate device context.
1901 stateManager->setInputLayout(nullptr);
1902 stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
1903 stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr, pixelShader);
1904 stateManager->setRasterizerState(nullptr);
1905 stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF);
1906 stateManager->setRenderTarget(mResolvedDepthStencilRTView.get(), nullptr);
1907 stateManager->setSimpleBlendState(nullptr);
1908
1909 // Set the viewport
1910 stateManager->setSimpleViewport(extents);
1911 const d3d11::SharedSRV *srv;
1912 ANGLE_TRY(depthStencil->getShaderResourceView(context, &srv));
1913 stateManager->setShaderResourceShared(gl::ShaderType::Fragment, 0, srv);
1914 stateManager->setShaderResource(gl::ShaderType::Fragment, 1, &mStencilSRV);
1915
1916 // Trigger the blit on the GPU.
1917 deviceContext->Draw(6, 0);
1918
1919 gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1);
1920
1921 ANGLE_TRY(mRenderer->createStagingTexture(context, ResourceType::Texture2D,
1922 depthStencil->getFormatSet(), extents,
1923 StagingAccess::READ_WRITE, textureOut));
1924
1925 const auto ©Function = GetCopyDepthStencilFunction(depthStencil->getInternalFormat());
1926 const auto &dsFormatSet = depthStencil->getFormatSet();
1927 const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat);
1928
1929 ANGLE_TRY(copyAndConvertImpl(context, mResolvedDepthStencil, 0, copyBox, extents, *textureOut,
1930 copyBox, extents, nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes,
1931 copyFunction));
1932
1933 return angle::Result::Continue;
1934 }
1935
releaseResolveDepthStencilResources()1936 void Blit11::releaseResolveDepthStencilResources()
1937 {
1938 mStencilSRV.reset();
1939 mResolvedDepthStencilRTView.reset();
1940 }
1941
1942 } // namespace rx
1943