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