• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 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 // Context11:
7 //   D3D11-specific functionality associated with a GL Context.
8 //
9 
10 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
11 
12 #include "common/entry_points_enum_autogen.h"
13 #include "common/string_utils.h"
14 #include "image_util/loadimage.h"
15 #include "libANGLE/Context.h"
16 #include "libANGLE/Context.inl.h"
17 #include "libANGLE/MemoryProgramCache.h"
18 #include "libANGLE/renderer/OverlayImpl.h"
19 #include "libANGLE/renderer/d3d/CompilerD3D.h"
20 #include "libANGLE/renderer/d3d/ProgramExecutableD3D.h"
21 #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
22 #include "libANGLE/renderer/d3d/SamplerD3D.h"
23 #include "libANGLE/renderer/d3d/ShaderD3D.h"
24 #include "libANGLE/renderer/d3d/TextureD3D.h"
25 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
26 #include "libANGLE/renderer/d3d/d3d11/Fence11.h"
27 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
28 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
29 #include "libANGLE/renderer/d3d/d3d11/Program11.h"
30 #include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h"
31 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
32 #include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
33 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
34 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
35 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
36 
37 namespace rx
38 {
39 
40 namespace
41 {
DrawCallHasDynamicAttribs(const gl::Context * context)42 ANGLE_INLINE bool DrawCallHasDynamicAttribs(const gl::Context *context)
43 {
44     VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(context->getState().getVertexArray());
45     return vertexArray11->hasActiveDynamicAttrib(context);
46 }
47 
InstancedPointSpritesActive(RendererD3D * renderer,ProgramExecutableD3D * executableD3D,gl::PrimitiveMode mode)48 bool InstancedPointSpritesActive(RendererD3D *renderer,
49                                  ProgramExecutableD3D *executableD3D,
50                                  gl::PrimitiveMode mode)
51 {
52     return executableD3D->usesPointSize() &&
53            executableD3D->usesInstancedPointSpriteEmulation(renderer) &&
54            mode == gl::PrimitiveMode::Points;
55 }
56 
DrawCallHasStreamingVertexArrays(const gl::Context * context,gl::PrimitiveMode mode)57 bool DrawCallHasStreamingVertexArrays(const gl::Context *context, gl::PrimitiveMode mode)
58 {
59     RendererD3D *renderer = GetImplAs<Context11>(context)->getRenderer();
60 
61     // Direct drawing doesn't support dynamic attribute storage since it needs the first and count
62     // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
63     // either since we need to simulate them in D3D.
64     if (DrawCallHasDynamicAttribs(context) || mode == gl::PrimitiveMode::LineLoop ||
65         mode == gl::PrimitiveMode::TriangleFan)
66     {
67         return true;
68     }
69 
70     ProgramExecutableD3D *executableD3D =
71         GetImplAs<ProgramExecutableD3D>(context->getState().getProgramExecutable());
72     if (InstancedPointSpritesActive(renderer, executableD3D, mode))
73     {
74         return true;
75     }
76 
77     return false;
78 }
79 
DrawCallHasStreamingElementArray(const gl::Context * context,gl::DrawElementsType srcType)80 bool DrawCallHasStreamingElementArray(const gl::Context *context, gl::DrawElementsType srcType)
81 {
82     const gl::State &glState       = context->getState();
83     gl::Buffer *elementArrayBuffer = glState.getVertexArray()->getElementArrayBuffer();
84 
85     bool primitiveRestartWorkaround =
86         UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType);
87     const gl::DrawElementsType dstType =
88         (srcType == gl::DrawElementsType::UnsignedInt || primitiveRestartWorkaround)
89             ? gl::DrawElementsType::UnsignedInt
90             : gl::DrawElementsType::UnsignedShort;
91 
92     // Not clear where the offset comes from here.
93     switch (ClassifyIndexStorage(glState, elementArrayBuffer, srcType, dstType, 0))
94     {
95         case IndexStorageType::Dynamic:
96             return true;
97         case IndexStorageType::Direct:
98             return false;
99         case IndexStorageType::Static:
100         {
101             BufferD3D *bufferD3D                     = GetImplAs<BufferD3D>(elementArrayBuffer);
102             StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
103             return (staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != dstType);
104         }
105         default:
106             UNREACHABLE();
107             return true;
108     }
109 }
110 
111 template <typename IndirectBufferT>
ReadbackIndirectBuffer(const gl::Context * context,const void * indirect,const IndirectBufferT ** bufferPtrOut)112 angle::Result ReadbackIndirectBuffer(const gl::Context *context,
113                                      const void *indirect,
114                                      const IndirectBufferT **bufferPtrOut)
115 {
116     const gl::State &glState       = context->getState();
117     gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
118     ASSERT(drawIndirectBuffer);
119     Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
120     uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);
121 
122     const uint8_t *bufferData = nullptr;
123     ANGLE_TRY(storage->getData(context, &bufferData));
124     ASSERT(bufferData);
125 
126     *bufferPtrOut = reinterpret_cast<const IndirectBufferT *>(bufferData + offset);
127     return angle::Result::Continue;
128 }
129 
IsSameExecutable(const gl::ProgramExecutable * a,const gl::ProgramExecutable * b)130 bool IsSameExecutable(const gl::ProgramExecutable *a, const gl::ProgramExecutable *b)
131 {
132     return GetImplAs<ProgramExecutableD3D>(a)->getSerial() ==
133            GetImplAs<ProgramExecutableD3D>(b)->getSerial();
134 }
135 }  // anonymous namespace
136 
Context11(const gl::State & state,gl::ErrorSet * errorSet,Renderer11 * renderer)137 Context11::Context11(const gl::State &state, gl::ErrorSet *errorSet, Renderer11 *renderer)
138     : ContextD3D(state, errorSet),
139       mRenderer(renderer),
140       mDisjointQueryStarted(false),
141       mDisjoint(false),
142       mFrequency(0)
143 {}
144 
~Context11()145 Context11::~Context11() {}
146 
initialize(const angle::ImageLoadContext & imageLoadContext)147 angle::Result Context11::initialize(const angle::ImageLoadContext &imageLoadContext)
148 {
149     mImageLoadContext = imageLoadContext;
150     return angle::Result::Continue;
151 }
152 
onDestroy(const gl::Context * context)153 void Context11::onDestroy(const gl::Context *context)
154 {
155     mIncompleteTextures.onDestroy(context);
156 
157     mImageLoadContext = {};
158 }
159 
createCompiler()160 CompilerImpl *Context11::createCompiler()
161 {
162     if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
163     {
164         return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT);
165     }
166     else
167     {
168         return new CompilerD3D(SH_HLSL_4_1_OUTPUT);
169     }
170 }
171 
createShader(const gl::ShaderState & data)172 ShaderImpl *Context11::createShader(const gl::ShaderState &data)
173 {
174     return new ShaderD3D(data, mRenderer);
175 }
176 
createProgram(const gl::ProgramState & data)177 ProgramImpl *Context11::createProgram(const gl::ProgramState &data)
178 {
179     return new Program11(data, mRenderer);
180 }
181 
createProgramExecutable(const gl::ProgramExecutable * executable)182 ProgramExecutableImpl *Context11::createProgramExecutable(const gl::ProgramExecutable *executable)
183 {
184     return new ProgramExecutableD3D(executable);
185 }
186 
createFramebuffer(const gl::FramebufferState & data)187 FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data)
188 {
189     return new Framebuffer11(data, mRenderer);
190 }
191 
createTexture(const gl::TextureState & state)192 TextureImpl *Context11::createTexture(const gl::TextureState &state)
193 {
194     switch (state.getType())
195     {
196         case gl::TextureType::_2D:
197         // GL_TEXTURE_VIDEO_IMAGE_WEBGL maps to native 2D texture on Windows platform
198         case gl::TextureType::VideoImage:
199             return new TextureD3D_2D(state, mRenderer);
200         case gl::TextureType::CubeMap:
201             return new TextureD3D_Cube(state, mRenderer);
202         case gl::TextureType::_3D:
203             return new TextureD3D_3D(state, mRenderer);
204         case gl::TextureType::_2DArray:
205             return new TextureD3D_2DArray(state, mRenderer);
206         case gl::TextureType::External:
207             return new TextureD3D_External(state, mRenderer);
208         case gl::TextureType::_2DMultisample:
209             return new TextureD3D_2DMultisample(state, mRenderer);
210         case gl::TextureType::_2DMultisampleArray:
211             return new TextureD3D_2DMultisampleArray(state, mRenderer);
212         case gl::TextureType::Buffer:
213             return new TextureD3D_Buffer(state, mRenderer);
214         default:
215             UNREACHABLE();
216     }
217 
218     return nullptr;
219 }
220 
createRenderbuffer(const gl::RenderbufferState & state)221 RenderbufferImpl *Context11::createRenderbuffer(const gl::RenderbufferState &state)
222 {
223     return new RenderbufferD3D(state, mRenderer);
224 }
225 
createBuffer(const gl::BufferState & state)226 BufferImpl *Context11::createBuffer(const gl::BufferState &state)
227 {
228     Buffer11 *buffer = new Buffer11(state, mRenderer);
229     mRenderer->onBufferCreate(buffer);
230     return buffer;
231 }
232 
createVertexArray(const gl::VertexArrayState & data)233 VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data)
234 {
235     return new VertexArray11(data);
236 }
237 
createQuery(gl::QueryType type)238 QueryImpl *Context11::createQuery(gl::QueryType type)
239 {
240     return new Query11(mRenderer, type);
241 }
242 
createFenceNV()243 FenceNVImpl *Context11::createFenceNV()
244 {
245     return new FenceNV11(mRenderer);
246 }
247 
createSync()248 SyncImpl *Context11::createSync()
249 {
250     return new Sync11(mRenderer);
251 }
252 
createTransformFeedback(const gl::TransformFeedbackState & state)253 TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state)
254 {
255     return new TransformFeedback11(state, mRenderer);
256 }
257 
createSampler(const gl::SamplerState & state)258 SamplerImpl *Context11::createSampler(const gl::SamplerState &state)
259 {
260     return new SamplerD3D(state);
261 }
262 
createProgramPipeline(const gl::ProgramPipelineState & data)263 ProgramPipelineImpl *Context11::createProgramPipeline(const gl::ProgramPipelineState &data)
264 {
265     return new ProgramPipeline11(data);
266 }
267 
createMemoryObject()268 MemoryObjectImpl *Context11::createMemoryObject()
269 {
270     UNREACHABLE();
271     return nullptr;
272 }
273 
createSemaphore()274 SemaphoreImpl *Context11::createSemaphore()
275 {
276     UNREACHABLE();
277     return nullptr;
278 }
279 
createOverlay(const gl::OverlayState & state)280 OverlayImpl *Context11::createOverlay(const gl::OverlayState &state)
281 {
282     // Not implemented.
283     return new OverlayImpl(state);
284 }
285 
flush(const gl::Context * context)286 angle::Result Context11::flush(const gl::Context *context)
287 {
288     return mRenderer->flush(this);
289 }
290 
finish(const gl::Context * context)291 angle::Result Context11::finish(const gl::Context *context)
292 {
293     return mRenderer->finish(this);
294 }
295 
drawArrays(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count)296 angle::Result Context11::drawArrays(const gl::Context *context,
297                                     gl::PrimitiveMode mode,
298                                     GLint first,
299                                     GLsizei count)
300 {
301     ASSERT(count > 0);
302     ANGLE_TRY(mRenderer->getStateManager()->updateState(
303         context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0, true));
304     return mRenderer->drawArrays(context, mode, first, count, 0, 0, false);
305 }
306 
drawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount)307 angle::Result Context11::drawArraysInstanced(const gl::Context *context,
308                                              gl::PrimitiveMode mode,
309                                              GLint first,
310                                              GLsizei count,
311                                              GLsizei instanceCount)
312 {
313     ASSERT(count > 0);
314     ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count,
315                                                         gl::DrawElementsType::InvalidEnum, nullptr,
316                                                         instanceCount, 0, 0, true));
317     return mRenderer->drawArrays(context, mode, first, count, instanceCount, 0, true);
318 }
319 
drawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount,GLuint baseInstance)320 angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *context,
321                                                          gl::PrimitiveMode mode,
322                                                          GLint first,
323                                                          GLsizei count,
324                                                          GLsizei instanceCount,
325                                                          GLuint baseInstance)
326 {
327     ASSERT(count > 0);
328     ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, first, count,
329                                                         gl::DrawElementsType::InvalidEnum, nullptr,
330                                                         instanceCount, 0, baseInstance, true));
331     return mRenderer->drawArrays(context, mode, first, count, instanceCount, baseInstance, true);
332 }
333 
drawElementsImpl(const gl::Context * context,gl::PrimitiveMode mode,GLsizei indexCount,gl::DrawElementsType indexType,const void * indices,GLsizei instanceCount,GLint baseVertex,GLuint baseInstance,bool promoteDynamic,bool isInstancedDraw)334 ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *context,
335                                                        gl::PrimitiveMode mode,
336                                                        GLsizei indexCount,
337                                                        gl::DrawElementsType indexType,
338                                                        const void *indices,
339                                                        GLsizei instanceCount,
340                                                        GLint baseVertex,
341                                                        GLuint baseInstance,
342                                                        bool promoteDynamic,
343                                                        bool isInstancedDraw)
344 {
345     ASSERT(indexCount > 0);
346 
347     if (DrawCallHasDynamicAttribs(context))
348     {
349         gl::IndexRange indexRange;
350         ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
351             context, indexType, indexCount, indices, &indexRange));
352         GLint startVertex;
353         ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, baseVertex,
354                                      &startVertex));
355         ANGLE_TRY(mRenderer->getStateManager()->updateState(
356             context, mode, startVertex, indexCount, indexType, indices, instanceCount, baseVertex,
357             baseInstance, promoteDynamic));
358         return mRenderer->drawElements(context, mode, startVertex, indexCount, indexType, indices,
359                                        instanceCount, baseVertex, baseInstance, isInstancedDraw);
360     }
361     else
362     {
363         ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, indexCount, indexType,
364                                                             indices, instanceCount, baseVertex,
365                                                             baseInstance, promoteDynamic));
366         return mRenderer->drawElements(context, mode, 0, indexCount, indexType, indices,
367                                        instanceCount, baseVertex, baseInstance, isInstancedDraw);
368     }
369 }
370 
drawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices)371 angle::Result Context11::drawElements(const gl::Context *context,
372                                       gl::PrimitiveMode mode,
373                                       GLsizei count,
374                                       gl::DrawElementsType type,
375                                       const void *indices)
376 {
377     return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0, true, false);
378 }
379 
drawElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)380 angle::Result Context11::drawElementsBaseVertex(const gl::Context *context,
381                                                 gl::PrimitiveMode mode,
382                                                 GLsizei count,
383                                                 gl::DrawElementsType type,
384                                                 const void *indices,
385                                                 GLint baseVertex)
386 {
387     return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0, true, false);
388 }
389 
drawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)390 angle::Result Context11::drawElementsInstanced(const gl::Context *context,
391                                                gl::PrimitiveMode mode,
392                                                GLsizei count,
393                                                gl::DrawElementsType type,
394                                                const void *indices,
395                                                GLsizei instances)
396 {
397     return drawElementsImpl(context, mode, count, type, indices, instances, 0, 0, true, true);
398 }
399 
drawElementsInstancedBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex)400 angle::Result Context11::drawElementsInstancedBaseVertex(const gl::Context *context,
401                                                          gl::PrimitiveMode mode,
402                                                          GLsizei count,
403                                                          gl::DrawElementsType type,
404                                                          const void *indices,
405                                                          GLsizei instances,
406                                                          GLint baseVertex)
407 {
408     return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex, 0, true,
409                             true);
410 }
411 
drawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex,GLuint baseInstance)412 angle::Result Context11::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
413                                                                      gl::PrimitiveMode mode,
414                                                                      GLsizei count,
415                                                                      gl::DrawElementsType type,
416                                                                      const void *indices,
417                                                                      GLsizei instances,
418                                                                      GLint baseVertex,
419                                                                      GLuint baseInstance)
420 {
421     return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex,
422                             baseInstance, true, true);
423 }
424 
drawRangeElements(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices)425 angle::Result Context11::drawRangeElements(const gl::Context *context,
426                                            gl::PrimitiveMode mode,
427                                            GLuint start,
428                                            GLuint end,
429                                            GLsizei count,
430                                            gl::DrawElementsType type,
431                                            const void *indices)
432 {
433     return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0, true, false);
434 }
435 
drawRangeElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)436 angle::Result Context11::drawRangeElementsBaseVertex(const gl::Context *context,
437                                                      gl::PrimitiveMode mode,
438                                                      GLuint start,
439                                                      GLuint end,
440                                                      GLsizei count,
441                                                      gl::DrawElementsType type,
442                                                      const void *indices,
443                                                      GLint baseVertex)
444 {
445     return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0, true, false);
446 }
447 
drawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect)448 angle::Result Context11::drawArraysIndirect(const gl::Context *context,
449                                             gl::PrimitiveMode mode,
450                                             const void *indirect)
451 {
452     if (DrawCallHasStreamingVertexArrays(context, mode))
453     {
454         const gl::DrawArraysIndirectCommand *cmd = nullptr;
455         ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
456 
457         if (cmd->count == 0)
458         {
459             return angle::Result::Continue;
460         }
461 
462         ANGLE_TRY(mRenderer->getStateManager()->updateState(
463             context, mode, cmd->first, cmd->count, gl::DrawElementsType::InvalidEnum, nullptr,
464             cmd->instanceCount, 0, 0, true));
465         return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount,
466                                      cmd->baseInstance, true);
467     }
468     else
469     {
470         ANGLE_TRY(mRenderer->getStateManager()->updateState(
471             context, mode, 0, 0, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0, 0, true));
472         return mRenderer->drawArraysIndirect(context, indirect);
473     }
474 }
475 
drawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect)476 angle::Result Context11::drawElementsIndirect(const gl::Context *context,
477                                               gl::PrimitiveMode mode,
478                                               gl::DrawElementsType type,
479                                               const void *indirect)
480 {
481     if (DrawCallHasStreamingVertexArrays(context, mode) ||
482         DrawCallHasStreamingElementArray(context, type))
483     {
484         const gl::DrawElementsIndirectCommand *cmd = nullptr;
485         ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
486 
487         if (cmd->count == 0)
488         {
489             return angle::Result::Continue;
490         }
491 
492         const GLuint typeBytes = gl::GetDrawElementsTypeSize(type);
493         const void *indices =
494             reinterpret_cast<const void *>(static_cast<uintptr_t>(cmd->firstIndex * typeBytes));
495 
496         // We must explicitly resolve the index range for the slow-path indirect drawElements to
497         // make sure we are using the correct 'baseVertex'. This parameter does not exist for the
498         // direct drawElements.
499         gl::IndexRange indexRange;
500         ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, cmd->count,
501                                                                       indices, &indexRange));
502 
503         GLint startVertex;
504         ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, cmd->baseVertex,
505                                      &startVertex));
506 
507         ANGLE_TRY(mRenderer->getStateManager()->updateState(
508             context, mode, startVertex, cmd->count, type, indices, cmd->primCount, cmd->baseVertex,
509             cmd->baseInstance, true));
510         return mRenderer->drawElements(context, mode, static_cast<GLint>(indexRange.start),
511                                        cmd->count, type, indices, cmd->primCount, 0,
512                                        cmd->baseInstance, true);
513     }
514     else
515     {
516         ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, 0, type, nullptr, 0,
517                                                             0, 0, true));
518         return mRenderer->drawElementsIndirect(context, indirect);
519     }
520 }
521 
522 #define DRAW_ARRAYS__                                                                           \
523     do                                                                                          \
524     {                                                                                           \
525         ANGLE_TRY(mRenderer->getStateManager()->updateState(                                    \
526             context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum,   \
527             nullptr, 0, 0, 0, false));                                                          \
528         ANGLE_TRY(                                                                              \
529             mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID], 0, 0, false)); \
530     } while (0)
531 #define DRAW_ARRAYS_INSTANCED_                                                                \
532     do                                                                                        \
533     {                                                                                         \
534         ANGLE_TRY(mRenderer->getStateManager()->updateState(                                  \
535             context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum, \
536             nullptr, instanceCounts[drawID], 0, 0, false));                                   \
537         ANGLE_TRY(mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID],        \
538                                         instanceCounts[drawID], 0, true));                    \
539     } while (0)
540 #define DRAW_ARRAYS_INSTANCED_BASE_INSTANCE                                                    \
541     do                                                                                         \
542     {                                                                                          \
543         ANGLE_TRY(mRenderer->getStateManager()->updateState(                                   \
544             context, mode, firsts[drawID], counts[drawID], gl::DrawElementsType::InvalidEnum,  \
545             nullptr, instanceCounts[drawID], 0, baseInstances[drawID], false));                \
546         ANGLE_TRY(mRenderer->drawArrays(context, mode, firsts[drawID], counts[drawID],         \
547                                         instanceCounts[drawID], baseInstances[drawID], true)); \
548     } while (0)
549 #define DRAW_ELEMENTS__                                                                       \
550     ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], 0, 0, 0, \
551                                false, false))
552 #define DRAW_ELEMENTS_INSTANCED_                                                     \
553     ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], \
554                                instanceCounts[drawID], 0, 0, false, true))
555 #define DRAW_ELEMENTS_INSTANCED_BASE_VERTEX_BASE_INSTANCE                            \
556     ANGLE_TRY(drawElementsImpl(context, mode, counts[drawID], type, indices[drawID], \
557                                instanceCounts[drawID], baseVertices[drawID],         \
558                                baseInstances[drawID], false, true))
559 
560 #define DRAW_CALL(drawType, instanced, bvbi) DRAW_##drawType##instanced##bvbi
561 
562 #define MULTI_DRAW_BLOCK(drawType, instanced, bvbi, hasDrawID, hasBaseVertex, hasBaseInstance) \
563     do                                                                                         \
564     {                                                                                          \
565         for (GLsizei drawID = 0; drawID < drawcount; ++drawID)                                 \
566         {                                                                                      \
567             if (ANGLE_NOOP_DRAW(instanced))                                                    \
568             {                                                                                  \
569                 continue;                                                                      \
570             }                                                                                  \
571             ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(drawID);                                      \
572             ANGLE_SET_BASE_VERTEX_UNIFORM(hasBaseVertex)(baseVertices[drawID]);                \
573             ANGLE_SET_BASE_INSTANCE_UNIFORM(hasBaseInstance)(baseInstances[drawID]);           \
574             ASSERT(counts[drawID] > 0);                                                        \
575             DRAW_CALL(drawType, instanced, bvbi);                                              \
576             ANGLE_MARK_TRANSFORM_FEEDBACK_USAGE(instanced);                                    \
577             gl::MarkShaderStorageUsage(context);                                               \
578         }                                                                                      \
579         /* reset the uniform to zero for non-multi-draw uses of the program */                 \
580         ANGLE_SET_DRAW_ID_UNIFORM(hasDrawID)(0);                                               \
581     } while (0)
582 
multiDrawArrays(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,GLsizei drawcount)583 angle::Result Context11::multiDrawArrays(const gl::Context *context,
584                                          gl::PrimitiveMode mode,
585                                          const GLint *firsts,
586                                          const GLsizei *counts,
587                                          GLsizei drawcount)
588 {
589     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
590     const bool hasDrawID              = executable->hasDrawIDUniform();
591     if (hasDrawID)
592     {
593         MULTI_DRAW_BLOCK(ARRAYS, _, _, 1, 0, 0);
594     }
595     else
596     {
597         MULTI_DRAW_BLOCK(ARRAYS, _, _, 0, 0, 0);
598     }
599 
600     return angle::Result::Continue;
601 }
602 
multiDrawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,GLsizei drawcount)603 angle::Result Context11::multiDrawArraysInstanced(const gl::Context *context,
604                                                   gl::PrimitiveMode mode,
605                                                   const GLint *firsts,
606                                                   const GLsizei *counts,
607                                                   const GLsizei *instanceCounts,
608                                                   GLsizei drawcount)
609 {
610     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
611     const bool hasDrawID              = executable->hasDrawIDUniform();
612     if (hasDrawID)
613     {
614         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 1, 0, 0);
615     }
616     else
617     {
618         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _, 0, 0, 0);
619     }
620 
621     return angle::Result::Continue;
622 }
623 
multiDrawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect,GLsizei drawcount,GLsizei stride)624 angle::Result Context11::multiDrawArraysIndirect(const gl::Context *context,
625                                                  gl::PrimitiveMode mode,
626                                                  const void *indirect,
627                                                  GLsizei drawcount,
628                                                  GLsizei stride)
629 {
630     return rx::MultiDrawArraysIndirectGeneral(this, context, mode, indirect, drawcount, stride);
631 }
632 
multiDrawElements(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,GLsizei drawcount)633 angle::Result Context11::multiDrawElements(const gl::Context *context,
634                                            gl::PrimitiveMode mode,
635                                            const GLsizei *counts,
636                                            gl::DrawElementsType type,
637                                            const GLvoid *const *indices,
638                                            GLsizei drawcount)
639 {
640     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
641     const bool hasDrawID              = executable->hasDrawIDUniform();
642     if (hasDrawID)
643     {
644         MULTI_DRAW_BLOCK(ELEMENTS, _, _, 1, 0, 0);
645     }
646     else
647     {
648         MULTI_DRAW_BLOCK(ELEMENTS, _, _, 0, 0, 0);
649     }
650 
651     return angle::Result::Continue;
652 }
653 
multiDrawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,GLsizei drawcount)654 angle::Result Context11::multiDrawElementsInstanced(const gl::Context *context,
655                                                     gl::PrimitiveMode mode,
656                                                     const GLsizei *counts,
657                                                     gl::DrawElementsType type,
658                                                     const GLvoid *const *indices,
659                                                     const GLsizei *instanceCounts,
660                                                     GLsizei drawcount)
661 {
662     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
663     const bool hasDrawID              = executable->hasDrawIDUniform();
664     if (hasDrawID)
665     {
666         MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 1, 0, 0);
667     }
668     else
669     {
670         MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _, 0, 0, 0);
671     }
672 
673     return angle::Result::Continue;
674 }
675 
multiDrawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect,GLsizei drawcount,GLsizei stride)676 angle::Result Context11::multiDrawElementsIndirect(const gl::Context *context,
677                                                    gl::PrimitiveMode mode,
678                                                    gl::DrawElementsType type,
679                                                    const void *indirect,
680                                                    GLsizei drawcount,
681                                                    GLsizei stride)
682 {
683     return rx::MultiDrawElementsIndirectGeneral(this, context, mode, type, indirect, drawcount,
684                                                 stride);
685 }
686 
multiDrawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLint * firsts,const GLsizei * counts,const GLsizei * instanceCounts,const GLuint * baseInstances,GLsizei drawcount)687 angle::Result Context11::multiDrawArraysInstancedBaseInstance(const gl::Context *context,
688                                                               gl::PrimitiveMode mode,
689                                                               const GLint *firsts,
690                                                               const GLsizei *counts,
691                                                               const GLsizei *instanceCounts,
692                                                               const GLuint *baseInstances,
693                                                               GLsizei drawcount)
694 {
695     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
696     const bool hasDrawID              = executable->hasDrawIDUniform();
697     const bool hasBaseInstance        = executable->hasBaseInstanceUniform();
698     ResetBaseVertexBaseInstance resetUniforms(executable, false, hasBaseInstance);
699 
700     if (hasDrawID && hasBaseInstance)
701     {
702         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 1);
703     }
704     else if (hasDrawID)
705     {
706         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 1, 0, 0);
707     }
708     else if (hasBaseInstance)
709     {
710         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 1);
711     }
712     else
713     {
714         MULTI_DRAW_BLOCK(ARRAYS, _INSTANCED, _BASE_INSTANCE, 0, 0, 0);
715     }
716 
717     return angle::Result::Continue;
718 }
719 
multiDrawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,const GLsizei * counts,gl::DrawElementsType type,const GLvoid * const * indices,const GLsizei * instanceCounts,const GLint * baseVertices,const GLuint * baseInstances,GLsizei drawcount)720 angle::Result Context11::multiDrawElementsInstancedBaseVertexBaseInstance(
721     const gl::Context *context,
722     gl::PrimitiveMode mode,
723     const GLsizei *counts,
724     gl::DrawElementsType type,
725     const GLvoid *const *indices,
726     const GLsizei *instanceCounts,
727     const GLint *baseVertices,
728     const GLuint *baseInstances,
729     GLsizei drawcount)
730 {
731     gl::ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
732     const bool hasDrawID              = executable->hasDrawIDUniform();
733     const bool hasBaseVertex          = executable->hasBaseVertexUniform();
734     const bool hasBaseInstance        = executable->hasBaseInstanceUniform();
735     ResetBaseVertexBaseInstance resetUniforms(executable, hasBaseVertex, hasBaseInstance);
736 
737     if (hasDrawID)
738     {
739         if (hasBaseVertex)
740         {
741             if (hasBaseInstance)
742             {
743                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 1);
744             }
745             else
746             {
747                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 1, 0);
748             }
749         }
750         else
751         {
752             if (hasBaseInstance)
753             {
754                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 1);
755             }
756             else
757             {
758                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 1, 0, 0);
759             }
760         }
761     }
762     else
763     {
764         if (hasBaseVertex)
765         {
766             if (hasBaseInstance)
767             {
768                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 1);
769             }
770             else
771             {
772                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 1, 0);
773             }
774         }
775         else
776         {
777             if (hasBaseInstance)
778             {
779                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 1);
780             }
781             else
782             {
783                 MULTI_DRAW_BLOCK(ELEMENTS, _INSTANCED, _BASE_VERTEX_BASE_INSTANCE, 0, 0, 0);
784             }
785         }
786     }
787 
788     return angle::Result::Continue;
789 }
790 
getResetStatus()791 gl::GraphicsResetStatus Context11::getResetStatus()
792 {
793     return mRenderer->getResetStatus();
794 }
795 
insertEventMarker(GLsizei length,const char * marker)796 angle::Result Context11::insertEventMarker(GLsizei length, const char *marker)
797 {
798     mRenderer->getDebugAnnotatorContext()->setMarker(marker);
799     return angle::Result::Continue;
800 }
801 
pushGroupMarker(GLsizei length,const char * marker)802 angle::Result Context11::pushGroupMarker(GLsizei length, const char *marker)
803 {
804     mRenderer->getDebugAnnotatorContext()->beginEvent(angle::EntryPoint::GLPushGroupMarkerEXT,
805                                                       marker, marker);
806     mMarkerStack.push(std::string(marker));
807     return angle::Result::Continue;
808 }
809 
popGroupMarker()810 angle::Result Context11::popGroupMarker()
811 {
812     const char *marker = nullptr;
813     if (!mMarkerStack.empty())
814     {
815         marker = mMarkerStack.top().c_str();
816         mMarkerStack.pop();
817         mRenderer->getDebugAnnotatorContext()->endEvent(marker,
818                                                         angle::EntryPoint::GLPopGroupMarkerEXT);
819     }
820     return angle::Result::Continue;
821 }
822 
pushDebugGroup(const gl::Context * context,GLenum source,GLuint id,const std::string & message)823 angle::Result Context11::pushDebugGroup(const gl::Context *context,
824                                         GLenum source,
825                                         GLuint id,
826                                         const std::string &message)
827 {
828     // Fall through to the EXT_debug_marker functions
829     return pushGroupMarker(static_cast<GLsizei>(message.size()), message.c_str());
830 }
831 
popDebugGroup(const gl::Context * context)832 angle::Result Context11::popDebugGroup(const gl::Context *context)
833 {
834     // Fall through to the EXT_debug_marker functions
835     return popGroupMarker();
836 }
837 
syncState(const gl::Context * context,const gl::state::DirtyBits dirtyBits,const gl::state::DirtyBits bitMask,const gl::state::ExtendedDirtyBits extendedDirtyBits,const gl::state::ExtendedDirtyBits extendedBitMask,gl::Command command)838 angle::Result Context11::syncState(const gl::Context *context,
839                                    const gl::state::DirtyBits dirtyBits,
840                                    const gl::state::DirtyBits bitMask,
841                                    const gl::state::ExtendedDirtyBits extendedDirtyBits,
842                                    const gl::state::ExtendedDirtyBits extendedBitMask,
843                                    gl::Command command)
844 {
845     mRenderer->getStateManager()->syncState(context, dirtyBits, extendedDirtyBits, command);
846     return angle::Result::Continue;
847 }
848 
checkDisjointQuery()849 angle::Result Context11::checkDisjointQuery()
850 {
851     if (!mDisjointQuery.valid())
852     {
853         D3D11_QUERY_DESC queryDesc;
854         queryDesc.Query     = gl_d3d11::ConvertQueryType(gl::QueryType::Timestamp);
855         queryDesc.MiscFlags = 0;
856 
857         ANGLE_TRY(mRenderer->allocateResource(this, queryDesc, &mDisjointQuery));
858         mRenderer->getDeviceContext()->Begin(mDisjointQuery.get());
859         mDisjointQueryStarted = true;
860     }
861     return angle::Result::Continue;
862 }
863 
checkDisjointQueryStatus()864 HRESULT Context11::checkDisjointQueryStatus()
865 {
866     HRESULT result = S_OK;
867     if (mDisjointQuery.valid())
868     {
869         ID3D11DeviceContext *context = mRenderer->getDeviceContext();
870         if (mDisjointQueryStarted)
871         {
872             context->End(mDisjointQuery.get());
873             mDisjointQueryStarted = false;
874         }
875         D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {};
876         result = context->GetData(mDisjointQuery.get(), &timeStats, sizeof(timeStats), 0);
877         if (result == S_OK)
878         {
879             mFrequency = timeStats.Frequency;
880             mDisjoint  = timeStats.Disjoint;
881             mDisjointQuery.reset();
882         }
883     }
884     return result;
885 }
886 
getDisjointFrequency()887 UINT64 Context11::getDisjointFrequency()
888 {
889     return mFrequency;
890 }
891 
setDisjointFrequency(UINT64 frequency)892 void Context11::setDisjointFrequency(UINT64 frequency)
893 {
894     mFrequency = frequency;
895 }
896 
setGPUDisjoint()897 void Context11::setGPUDisjoint()
898 {
899     mDisjoint = true;
900 }
901 
getGPUDisjoint()902 GLint Context11::getGPUDisjoint()
903 {
904     if (mRenderer->getFeatures().enableTimestampQueries.enabled)
905     {
906         checkDisjointQueryStatus();
907     }
908     bool disjoint = mDisjoint;
909 
910     // Disjoint flag is cleared when read
911     mDisjoint = false;
912 
913     return disjoint;
914 }
915 
getTimestamp()916 GLint64 Context11::getTimestamp()
917 {
918     return mRenderer->getTimestamp();
919 }
920 
onMakeCurrent(const gl::Context * context)921 angle::Result Context11::onMakeCurrent(const gl::Context *context)
922 {
923     // Immediately return if the device has been lost.
924     if (!mRenderer->getDevice())
925     {
926         return angle::Result::Continue;
927     }
928 
929     return mRenderer->getStateManager()->onMakeCurrent(context);
930 }
931 
getNativeCaps() const932 gl::Caps Context11::getNativeCaps() const
933 {
934     gl::Caps caps = mRenderer->getNativeCaps();
935 
936     // For pixel shaders, the render targets and unordered access views share the same resource
937     // slots, so the maximum number of fragment shader outputs depends on the current context
938     // version:
939     // - If current context is ES 3.0 and below, we use D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8)
940     //   as the value of max draw buffers because UAVs are not used.
941     // - If current context is ES 3.1 and the feature level is 11_0, the RTVs and UAVs share 8
942     //   slots. As ES 3.1 requires at least 1 atomic counter buffer in compute shaders, the value
943     //   of max combined shader output resources is limited to 7, thus only 7 RTV slots can be
944     //   used simultaneously.
945     // - If current context is ES 3.1 and the feature level is 11_1, the RTVs and UAVs share 64
946     //   slots. Currently we allocate 60 slots for combined shader output resources, so we can use
947     //   at most D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8) RTVs simultaneously.
948     if (mState.getClientVersion() >= gl::ES_3_1 &&
949         mRenderer->getRenderer11DeviceCaps().featureLevel == D3D_FEATURE_LEVEL_11_0)
950     {
951         caps.maxDrawBuffers      = caps.maxCombinedShaderOutputResources;
952         caps.maxColorAttachments = caps.maxCombinedShaderOutputResources;
953     }
954 
955     return caps;
956 }
957 
getNativeTextureCaps() const958 const gl::TextureCapsMap &Context11::getNativeTextureCaps() const
959 {
960     return mRenderer->getNativeTextureCaps();
961 }
962 
getNativeExtensions() const963 const gl::Extensions &Context11::getNativeExtensions() const
964 {
965     return mRenderer->getNativeExtensions();
966 }
967 
getNativeLimitations() const968 const gl::Limitations &Context11::getNativeLimitations() const
969 {
970     return mRenderer->getNativeLimitations();
971 }
972 
getNativePixelLocalStorageOptions() const973 const ShPixelLocalStorageOptions &Context11::getNativePixelLocalStorageOptions() const
974 {
975     return mRenderer->getNativePixelLocalStorageOptions();
976 }
977 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)978 angle::Result Context11::dispatchCompute(const gl::Context *context,
979                                          GLuint numGroupsX,
980                                          GLuint numGroupsY,
981                                          GLuint numGroupsZ)
982 {
983     return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
984 }
985 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)986 angle::Result Context11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
987 {
988     return mRenderer->dispatchComputeIndirect(context, indirect);
989 }
990 
triggerDrawCallProgramRecompilation(const gl::Context * context,gl::PrimitiveMode drawMode)991 angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context *context,
992                                                              gl::PrimitiveMode drawMode)
993 {
994     const auto &glState                 = context->getState();
995     const auto *va11                    = GetImplAs<VertexArray11>(glState.getVertexArray());
996     const auto *drawFBO                 = glState.getDrawFramebuffer();
997     gl::ProgramExecutable *executable   = glState.getProgramExecutable();
998     ProgramExecutableD3D *executableD3D = GetImplAs<ProgramExecutableD3D>(executable);
999 
1000     executableD3D->updateCachedInputLayout(mRenderer, va11->getCurrentStateSerial(), glState);
1001     executableD3D->updateCachedOutputLayout(context, drawFBO);
1002     executableD3D->updateCachedImage2DBindLayout(context, gl::ShaderType::Fragment);
1003 
1004     bool recompileVS = !executableD3D->hasVertexExecutableForCachedInputLayout();
1005     bool recompileGS =
1006         !executableD3D->hasGeometryExecutableForPrimitiveType(mRenderer, glState, drawMode);
1007     bool recompilePS = !executableD3D->hasPixelExecutableForCachedOutputLayout();
1008 
1009     if (!recompileVS && !recompileGS && !recompilePS)
1010     {
1011         return angle::Result::Continue;
1012     }
1013 
1014     // Load the compiler if necessary and recompile the programs.
1015     ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
1016 
1017     gl::InfoLog infoLog;
1018 
1019     if (recompileVS)
1020     {
1021         ShaderExecutableD3D *vertexExe = nullptr;
1022         ANGLE_TRY(executableD3D->getVertexExecutableForCachedInputLayout(this, mRenderer,
1023                                                                          &vertexExe, &infoLog));
1024         if (!executableD3D->hasVertexExecutableForCachedInputLayout())
1025         {
1026             ASSERT(infoLog.getLength() > 0);
1027             ERR() << "Error compiling dynamic vertex executable: " << infoLog.str();
1028             ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic vertex executable");
1029         }
1030     }
1031 
1032     if (recompileGS)
1033     {
1034         ShaderExecutableD3D *geometryExe = nullptr;
1035         ANGLE_TRY(executableD3D->getGeometryExecutableForPrimitiveType(
1036             this, mRenderer, glState.getCaps(), glState.getProvokingVertex(), drawMode,
1037             &geometryExe, &infoLog));
1038         if (!executableD3D->hasGeometryExecutableForPrimitiveType(mRenderer, glState, drawMode))
1039         {
1040             ASSERT(infoLog.getLength() > 0);
1041             ERR() << "Error compiling dynamic geometry executable: " << infoLog.str();
1042             ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic geometry executable");
1043         }
1044     }
1045 
1046     if (recompilePS)
1047     {
1048         ShaderExecutableD3D *pixelExe = nullptr;
1049         ANGLE_TRY(executableD3D->getPixelExecutableForCachedOutputLayout(this, mRenderer, &pixelExe,
1050                                                                          &infoLog));
1051         if (!executableD3D->hasPixelExecutableForCachedOutputLayout())
1052         {
1053             ASSERT(infoLog.getLength() > 0);
1054             ERR() << "Error compiling dynamic pixel executable: " << infoLog.str();
1055             ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic pixel executable");
1056         }
1057     }
1058 
1059     // Refresh the program cache entry.
1060     gl::Program *program = glState.getProgram();
1061     if (mMemoryProgramCache && IsSameExecutable(&program->getExecutable(), executable))
1062     {
1063         ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
1064     }
1065 
1066     return angle::Result::Continue;
1067 }
1068 
triggerDispatchCallProgramRecompilation(const gl::Context * context)1069 angle::Result Context11::triggerDispatchCallProgramRecompilation(const gl::Context *context)
1070 {
1071     const auto &glState                 = context->getState();
1072     gl::ProgramExecutable *executable   = glState.getProgramExecutable();
1073     ProgramExecutableD3D *executableD3D = GetImplAs<ProgramExecutableD3D>(executable);
1074 
1075     executableD3D->updateCachedImage2DBindLayout(context, gl::ShaderType::Compute);
1076 
1077     bool recompileCS = !executableD3D->hasComputeExecutableForCachedImage2DBindLayout();
1078 
1079     if (!recompileCS)
1080     {
1081         return angle::Result::Continue;
1082     }
1083 
1084     // Load the compiler if necessary and recompile the programs.
1085     ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
1086 
1087     gl::InfoLog infoLog;
1088 
1089     ShaderExecutableD3D *computeExe = nullptr;
1090     ANGLE_TRY(executableD3D->getComputeExecutableForImage2DBindLayout(this, mRenderer, &computeExe,
1091                                                                       &infoLog));
1092     if (!executableD3D->hasComputeExecutableForCachedImage2DBindLayout())
1093     {
1094         ASSERT(infoLog.getLength() > 0);
1095         ERR() << "Dynamic recompilation error log: " << infoLog.str();
1096         ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic compute executable");
1097     }
1098 
1099     // Refresh the program cache entry.
1100     gl::Program *program = glState.getProgram();
1101     if (mMemoryProgramCache && IsSameExecutable(&program->getExecutable(), executable))
1102     {
1103         ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
1104     }
1105 
1106     return angle::Result::Continue;
1107 }
1108 
memoryBarrier(const gl::Context * context,GLbitfield barriers)1109 angle::Result Context11::memoryBarrier(const gl::Context *context, GLbitfield barriers)
1110 {
1111     return angle::Result::Continue;
1112 }
1113 
memoryBarrierByRegion(const gl::Context * context,GLbitfield barriers)1114 angle::Result Context11::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
1115 {
1116     return angle::Result::Continue;
1117 }
1118 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::Texture ** textureOut)1119 angle::Result Context11::getIncompleteTexture(const gl::Context *context,
1120                                               gl::TextureType type,
1121                                               gl::Texture **textureOut)
1122 {
1123     return mIncompleteTextures.getIncompleteTexture(context, type, gl::SamplerFormat::Float, this,
1124                                                     textureOut);
1125 }
1126 
initializeMultisampleTextureToBlack(const gl::Context * context,gl::Texture * glTexture)1127 angle::Result Context11::initializeMultisampleTextureToBlack(const gl::Context *context,
1128                                                              gl::Texture *glTexture)
1129 {
1130     ASSERT(glTexture->getType() == gl::TextureType::_2DMultisample);
1131     TextureD3D *textureD3D        = GetImplAs<TextureD3D>(glTexture);
1132     gl::ImageIndex index          = gl::ImageIndex::Make2DMultisample();
1133     RenderTargetD3D *renderTarget = nullptr;
1134     GLsizei texSamples            = textureD3D->getRenderToTextureSamples();
1135     ANGLE_TRY(textureD3D->getRenderTarget(context, index, texSamples, &renderTarget));
1136     return mRenderer->clearRenderTarget(context, renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f),
1137                                         1.0f, 0);
1138 }
1139 
handleResult(HRESULT hr,const char * message,const char * file,const char * function,unsigned int line)1140 void Context11::handleResult(HRESULT hr,
1141                              const char *message,
1142                              const char *file,
1143                              const char *function,
1144                              unsigned int line)
1145 {
1146     ASSERT(FAILED(hr));
1147 
1148     GLenum glErrorCode = DefaultGLErrorCode(hr);
1149 
1150     std::stringstream errorStream;
1151     errorStream << "Internal D3D11 error: " << gl::FmtHR(hr);
1152 
1153     if (d3d11::isDeviceLostError(hr))
1154     {
1155         HRESULT removalReason = mRenderer->getDevice()->GetDeviceRemovedReason();
1156         errorStream << " (removal reason: " << gl::FmtHR(removalReason) << ")";
1157         mRenderer->notifyDeviceLost();
1158     }
1159 
1160     errorStream << ": " << message;
1161 
1162     mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
1163 }
1164 }  // namespace rx
1165