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