• 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/string_utils.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/MemoryProgramCache.h"
15 #include "libANGLE/renderer/OverlayImpl.h"
16 #include "libANGLE/renderer/d3d/CompilerD3D.h"
17 #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
18 #include "libANGLE/renderer/d3d/SamplerD3D.h"
19 #include "libANGLE/renderer/d3d/ShaderD3D.h"
20 #include "libANGLE/renderer/d3d/TextureD3D.h"
21 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
22 #include "libANGLE/renderer/d3d/d3d11/Fence11.h"
23 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
24 #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
25 #include "libANGLE/renderer/d3d/d3d11/Program11.h"
26 #include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h"
27 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
28 #include "libANGLE/renderer/d3d/d3d11/StateManager11.h"
29 #include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h"
30 #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
31 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
32 
33 namespace rx
34 {
35 
36 namespace
37 {
DrawCallHasDynamicAttribs(const gl::Context * context)38 ANGLE_INLINE bool DrawCallHasDynamicAttribs(const gl::Context *context)
39 {
40     VertexArray11 *vertexArray11 = GetImplAs<VertexArray11>(context->getState().getVertexArray());
41     return vertexArray11->hasActiveDynamicAttrib(context);
42 }
43 
DrawCallHasStreamingVertexArrays(const gl::Context * context,gl::PrimitiveMode mode)44 bool DrawCallHasStreamingVertexArrays(const gl::Context *context, gl::PrimitiveMode mode)
45 {
46     // Direct drawing doesn't support dynamic attribute storage since it needs the first and count
47     // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported
48     // either since we need to simulate them in D3D.
49     if (DrawCallHasDynamicAttribs(context) || mode == gl::PrimitiveMode::LineLoop ||
50         mode == gl::PrimitiveMode::TriangleFan)
51     {
52         return true;
53     }
54 
55     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(context->getState().getProgram());
56     if (InstancedPointSpritesActive(programD3D, mode))
57     {
58         return true;
59     }
60 
61     return false;
62 }
63 
DrawCallHasStreamingElementArray(const gl::Context * context,gl::DrawElementsType srcType)64 bool DrawCallHasStreamingElementArray(const gl::Context *context, gl::DrawElementsType srcType)
65 {
66     const gl::State &glState       = context->getState();
67     gl::Buffer *elementArrayBuffer = glState.getVertexArray()->getElementArrayBuffer();
68 
69     bool primitiveRestartWorkaround =
70         UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType);
71     const gl::DrawElementsType dstType =
72         (srcType == gl::DrawElementsType::UnsignedInt || primitiveRestartWorkaround)
73             ? gl::DrawElementsType::UnsignedInt
74             : gl::DrawElementsType::UnsignedShort;
75 
76     // Not clear where the offset comes from here.
77     switch (ClassifyIndexStorage(glState, elementArrayBuffer, srcType, dstType, 0))
78     {
79         case IndexStorageType::Dynamic:
80             return true;
81         case IndexStorageType::Direct:
82             return false;
83         case IndexStorageType::Static:
84         {
85             BufferD3D *bufferD3D                     = GetImplAs<BufferD3D>(elementArrayBuffer);
86             StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer();
87             return (staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != dstType);
88         }
89         default:
90             UNREACHABLE();
91             return true;
92     }
93 }
94 
95 template <typename IndirectBufferT>
ReadbackIndirectBuffer(const gl::Context * context,const void * indirect,const IndirectBufferT ** bufferPtrOut)96 angle::Result ReadbackIndirectBuffer(const gl::Context *context,
97                                      const void *indirect,
98                                      const IndirectBufferT **bufferPtrOut)
99 {
100     const gl::State &glState       = context->getState();
101     gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect);
102     ASSERT(drawIndirectBuffer);
103     Buffer11 *storage = GetImplAs<Buffer11>(drawIndirectBuffer);
104     uintptr_t offset  = reinterpret_cast<uintptr_t>(indirect);
105 
106     const uint8_t *bufferData = nullptr;
107     ANGLE_TRY(storage->getData(context, &bufferData));
108     ASSERT(bufferData);
109 
110     *bufferPtrOut = reinterpret_cast<const IndirectBufferT *>(bufferData + offset);
111     return angle::Result::Continue;
112 }
113 }  // anonymous namespace
114 
Context11(const gl::State & state,gl::ErrorSet * errorSet,Renderer11 * renderer)115 Context11::Context11(const gl::State &state, gl::ErrorSet *errorSet, Renderer11 *renderer)
116     : ContextD3D(state, errorSet), mRenderer(renderer)
117 {}
118 
~Context11()119 Context11::~Context11() {}
120 
initialize()121 angle::Result Context11::initialize()
122 {
123     return angle::Result::Continue;
124 }
125 
onDestroy(const gl::Context * context)126 void Context11::onDestroy(const gl::Context *context)
127 {
128     mIncompleteTextures.onDestroy(context);
129 }
130 
createCompiler()131 CompilerImpl *Context11::createCompiler()
132 {
133     if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3)
134     {
135         return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT);
136     }
137     else
138     {
139         return new CompilerD3D(SH_HLSL_4_1_OUTPUT);
140     }
141 }
142 
createShader(const gl::ShaderState & data)143 ShaderImpl *Context11::createShader(const gl::ShaderState &data)
144 {
145     return new ShaderD3D(data, mRenderer->getFeatures(), mRenderer->getNativeExtensions());
146 }
147 
createProgram(const gl::ProgramState & data)148 ProgramImpl *Context11::createProgram(const gl::ProgramState &data)
149 {
150     return new Program11(data, mRenderer);
151 }
152 
createFramebuffer(const gl::FramebufferState & data)153 FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data)
154 {
155     return new Framebuffer11(data, mRenderer);
156 }
157 
createTexture(const gl::TextureState & state)158 TextureImpl *Context11::createTexture(const gl::TextureState &state)
159 {
160     switch (state.getType())
161     {
162         case gl::TextureType::_2D:
163         // GL_TEXTURE_VIDEO_IMAGE_WEBGL maps to native 2D texture on Windows platform
164         case gl::TextureType::VideoImage:
165             return new TextureD3D_2D(state, mRenderer);
166         case gl::TextureType::CubeMap:
167             return new TextureD3D_Cube(state, mRenderer);
168         case gl::TextureType::_3D:
169             return new TextureD3D_3D(state, mRenderer);
170         case gl::TextureType::_2DArray:
171             return new TextureD3D_2DArray(state, mRenderer);
172         case gl::TextureType::External:
173             return new TextureD3D_External(state, mRenderer);
174         case gl::TextureType::_2DMultisample:
175             return new TextureD3D_2DMultisample(state, mRenderer);
176         case gl::TextureType::_2DMultisampleArray:
177             return new TextureD3D_2DMultisampleArray(state, mRenderer);
178         default:
179             UNREACHABLE();
180     }
181 
182     return nullptr;
183 }
184 
createRenderbuffer(const gl::RenderbufferState & state)185 RenderbufferImpl *Context11::createRenderbuffer(const gl::RenderbufferState &state)
186 {
187     return new RenderbufferD3D(state, mRenderer);
188 }
189 
createBuffer(const gl::BufferState & state)190 BufferImpl *Context11::createBuffer(const gl::BufferState &state)
191 {
192     Buffer11 *buffer = new Buffer11(state, mRenderer);
193     mRenderer->onBufferCreate(buffer);
194     return buffer;
195 }
196 
createVertexArray(const gl::VertexArrayState & data)197 VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data)
198 {
199     return new VertexArray11(data);
200 }
201 
createQuery(gl::QueryType type)202 QueryImpl *Context11::createQuery(gl::QueryType type)
203 {
204     return new Query11(mRenderer, type);
205 }
206 
createFenceNV()207 FenceNVImpl *Context11::createFenceNV()
208 {
209     return new FenceNV11(mRenderer);
210 }
211 
createSync()212 SyncImpl *Context11::createSync()
213 {
214     return new Sync11(mRenderer);
215 }
216 
createTransformFeedback(const gl::TransformFeedbackState & state)217 TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state)
218 {
219     return new TransformFeedback11(state, mRenderer);
220 }
221 
createSampler(const gl::SamplerState & state)222 SamplerImpl *Context11::createSampler(const gl::SamplerState &state)
223 {
224     return new SamplerD3D(state);
225 }
226 
createProgramPipeline(const gl::ProgramPipelineState & data)227 ProgramPipelineImpl *Context11::createProgramPipeline(const gl::ProgramPipelineState &data)
228 {
229     return new ProgramPipeline11(data);
230 }
231 
createMemoryObject()232 MemoryObjectImpl *Context11::createMemoryObject()
233 {
234     UNREACHABLE();
235     return nullptr;
236 }
237 
createSemaphore()238 SemaphoreImpl *Context11::createSemaphore()
239 {
240     UNREACHABLE();
241     return nullptr;
242 }
243 
createOverlay(const gl::OverlayState & state)244 OverlayImpl *Context11::createOverlay(const gl::OverlayState &state)
245 {
246     // Not implemented.
247     return new OverlayImpl(state);
248 }
249 
flush(const gl::Context * context)250 angle::Result Context11::flush(const gl::Context *context)
251 {
252     return mRenderer->flush(this);
253 }
254 
finish(const gl::Context * context)255 angle::Result Context11::finish(const gl::Context *context)
256 {
257     return mRenderer->finish(this);
258 }
259 
drawArrays(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count)260 angle::Result Context11::drawArrays(const gl::Context *context,
261                                     gl::PrimitiveMode mode,
262                                     GLint first,
263                                     GLsizei count)
264 {
265     ASSERT(count > 0);
266     ANGLE_TRY(mRenderer->getStateManager()->updateState(
267         context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0));
268     return mRenderer->drawArrays(context, mode, first, count, 0, 0);
269 }
270 
drawArraysInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount)271 angle::Result Context11::drawArraysInstanced(const gl::Context *context,
272                                              gl::PrimitiveMode mode,
273                                              GLint first,
274                                              GLsizei count,
275                                              GLsizei instanceCount)
276 {
277     ASSERT(count > 0);
278     ANGLE_TRY(mRenderer->getStateManager()->updateState(
279         context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, instanceCount, 0));
280     return mRenderer->drawArrays(context, mode, first, count, instanceCount, 0);
281 }
282 
drawArraysInstancedBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLint first,GLsizei count,GLsizei instanceCount,GLuint baseInstance)283 angle::Result Context11::drawArraysInstancedBaseInstance(const gl::Context *context,
284                                                          gl::PrimitiveMode mode,
285                                                          GLint first,
286                                                          GLsizei count,
287                                                          GLsizei instanceCount,
288                                                          GLuint baseInstance)
289 {
290     ASSERT(count > 0);
291     ANGLE_TRY(mRenderer->getStateManager()->updateState(
292         context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr, instanceCount, 0));
293     return mRenderer->drawArrays(context, mode, first, count, instanceCount, baseInstance);
294 }
295 
drawElementsImpl(const gl::Context * context,gl::PrimitiveMode mode,GLsizei indexCount,gl::DrawElementsType indexType,const void * indices,GLsizei instanceCount,GLint baseVertex,GLuint baseInstance)296 ANGLE_INLINE angle::Result Context11::drawElementsImpl(const gl::Context *context,
297                                                        gl::PrimitiveMode mode,
298                                                        GLsizei indexCount,
299                                                        gl::DrawElementsType indexType,
300                                                        const void *indices,
301                                                        GLsizei instanceCount,
302                                                        GLint baseVertex,
303                                                        GLuint baseInstance)
304 {
305     ASSERT(indexCount > 0);
306 
307     if (DrawCallHasDynamicAttribs(context))
308     {
309         gl::IndexRange indexRange;
310         ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(
311             context, indexType, indexCount, indices, &indexRange));
312         GLint startVertex;
313         ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, baseVertex,
314                                      &startVertex));
315         ANGLE_TRY(mRenderer->getStateManager()->updateState(
316             context, mode, startVertex, indexCount, indexType, indices, instanceCount, baseVertex));
317         return mRenderer->drawElements(context, mode, startVertex, indexCount, indexType, indices,
318                                        instanceCount, baseVertex, baseInstance);
319     }
320     else
321     {
322         ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, indexCount, indexType,
323                                                             indices, instanceCount, baseVertex));
324         return mRenderer->drawElements(context, mode, 0, indexCount, indexType, indices,
325                                        instanceCount, baseVertex, baseInstance);
326     }
327 }
328 
drawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices)329 angle::Result Context11::drawElements(const gl::Context *context,
330                                       gl::PrimitiveMode mode,
331                                       GLsizei count,
332                                       gl::DrawElementsType type,
333                                       const void *indices)
334 {
335     return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0);
336 }
337 
drawElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)338 angle::Result Context11::drawElementsBaseVertex(const gl::Context *context,
339                                                 gl::PrimitiveMode mode,
340                                                 GLsizei count,
341                                                 gl::DrawElementsType type,
342                                                 const void *indices,
343                                                 GLint baseVertex)
344 {
345     return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0);
346 }
347 
drawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)348 angle::Result Context11::drawElementsInstanced(const gl::Context *context,
349                                                gl::PrimitiveMode mode,
350                                                GLsizei count,
351                                                gl::DrawElementsType type,
352                                                const void *indices,
353                                                GLsizei instances)
354 {
355     return drawElementsImpl(context, mode, count, type, indices, instances, 0, 0);
356 }
357 
drawElementsInstancedBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex)358 angle::Result Context11::drawElementsInstancedBaseVertex(const gl::Context *context,
359                                                          gl::PrimitiveMode mode,
360                                                          GLsizei count,
361                                                          gl::DrawElementsType type,
362                                                          const void *indices,
363                                                          GLsizei instances,
364                                                          GLint baseVertex)
365 {
366     return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex, 0);
367 }
368 
drawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex,GLuint baseInstance)369 angle::Result Context11::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
370                                                                      gl::PrimitiveMode mode,
371                                                                      GLsizei count,
372                                                                      gl::DrawElementsType type,
373                                                                      const void *indices,
374                                                                      GLsizei instances,
375                                                                      GLint baseVertex,
376                                                                      GLuint baseInstance)
377 {
378     return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex,
379                             baseInstance);
380 }
381 
drawRangeElements(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices)382 angle::Result Context11::drawRangeElements(const gl::Context *context,
383                                            gl::PrimitiveMode mode,
384                                            GLuint start,
385                                            GLuint end,
386                                            GLsizei count,
387                                            gl::DrawElementsType type,
388                                            const void *indices)
389 {
390     return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0);
391 }
392 
drawRangeElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)393 angle::Result Context11::drawRangeElementsBaseVertex(const gl::Context *context,
394                                                      gl::PrimitiveMode mode,
395                                                      GLuint start,
396                                                      GLuint end,
397                                                      GLsizei count,
398                                                      gl::DrawElementsType type,
399                                                      const void *indices,
400                                                      GLint baseVertex)
401 {
402     return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0);
403 }
404 
drawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect)405 angle::Result Context11::drawArraysIndirect(const gl::Context *context,
406                                             gl::PrimitiveMode mode,
407                                             const void *indirect)
408 {
409     if (DrawCallHasStreamingVertexArrays(context, mode))
410     {
411         const gl::DrawArraysIndirectCommand *cmd = nullptr;
412         ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
413 
414         ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, cmd->first, cmd->count,
415                                                             gl::DrawElementsType::InvalidEnum,
416                                                             nullptr, cmd->instanceCount, 0));
417         return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount,
418                                      cmd->baseInstance);
419     }
420     else
421     {
422         ANGLE_TRY(mRenderer->getStateManager()->updateState(
423             context, mode, 0, 0, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0));
424         return mRenderer->drawArraysIndirect(context, indirect);
425     }
426 }
427 
drawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect)428 angle::Result Context11::drawElementsIndirect(const gl::Context *context,
429                                               gl::PrimitiveMode mode,
430                                               gl::DrawElementsType type,
431                                               const void *indirect)
432 {
433     if (DrawCallHasStreamingVertexArrays(context, mode) ||
434         DrawCallHasStreamingElementArray(context, type))
435     {
436         const gl::DrawElementsIndirectCommand *cmd = nullptr;
437         ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
438 
439         const GLuint typeBytes = gl::GetDrawElementsTypeSize(type);
440         const void *indices =
441             reinterpret_cast<const void *>(static_cast<uintptr_t>(cmd->firstIndex * typeBytes));
442 
443         // We must explicitly resolve the index range for the slow-path indirect drawElements to
444         // make sure we are using the correct 'baseVertex'. This parameter does not exist for the
445         // direct drawElements.
446         gl::IndexRange indexRange;
447         ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, cmd->count,
448                                                                       indices, &indexRange));
449 
450         GLint startVertex;
451         ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, cmd->baseVertex,
452                                      &startVertex));
453 
454         ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, startVertex, cmd->count,
455                                                             type, indices, cmd->primCount,
456                                                             cmd->baseVertex));
457         return mRenderer->drawElements(context, mode, static_cast<GLint>(indexRange.start),
458                                        cmd->count, type, indices, cmd->primCount, 0, 0);
459     }
460     else
461     {
462         ANGLE_TRY(
463             mRenderer->getStateManager()->updateState(context, mode, 0, 0, type, nullptr, 0, 0));
464         return mRenderer->drawElementsIndirect(context, indirect);
465     }
466 }
467 
getResetStatus()468 gl::GraphicsResetStatus Context11::getResetStatus()
469 {
470     return mRenderer->getResetStatus();
471 }
472 
getVendorString() const473 std::string Context11::getVendorString() const
474 {
475     return mRenderer->getVendorString();
476 }
477 
getRendererDescription() const478 std::string Context11::getRendererDescription() const
479 {
480     return mRenderer->getRendererDescription();
481 }
482 
insertEventMarker(GLsizei length,const char * marker)483 angle::Result Context11::insertEventMarker(GLsizei length, const char *marker)
484 {
485     mRenderer->getAnnotator()->setMarker(marker);
486     return angle::Result::Continue;
487 }
488 
pushGroupMarker(GLsizei length,const char * marker)489 angle::Result Context11::pushGroupMarker(GLsizei length, const char *marker)
490 {
491     mRenderer->getAnnotator()->beginEvent(marker, marker);
492     mMarkerStack.push(std::string(marker));
493     return angle::Result::Continue;
494 }
495 
popGroupMarker()496 angle::Result Context11::popGroupMarker()
497 {
498     const char *marker = nullptr;
499     if (!mMarkerStack.empty())
500     {
501         marker = mMarkerStack.top().c_str();
502         mMarkerStack.pop();
503         mRenderer->getAnnotator()->endEvent(marker);
504     }
505     return angle::Result::Continue;
506 }
507 
pushDebugGroup(const gl::Context * context,GLenum source,GLuint id,const std::string & message)508 angle::Result Context11::pushDebugGroup(const gl::Context *context,
509                                         GLenum source,
510                                         GLuint id,
511                                         const std::string &message)
512 {
513     // Fall through to the EXT_debug_marker functions
514     return pushGroupMarker(static_cast<GLsizei>(message.size()), message.c_str());
515 }
516 
popDebugGroup(const gl::Context * context)517 angle::Result Context11::popDebugGroup(const gl::Context *context)
518 {
519     // Fall through to the EXT_debug_marker functions
520     return popGroupMarker();
521 }
522 
syncState(const gl::Context * context,const gl::State::DirtyBits & dirtyBits,const gl::State::DirtyBits & bitMask)523 angle::Result Context11::syncState(const gl::Context *context,
524                                    const gl::State::DirtyBits &dirtyBits,
525                                    const gl::State::DirtyBits &bitMask)
526 {
527     mRenderer->getStateManager()->syncState(context, dirtyBits);
528     return angle::Result::Continue;
529 }
530 
getGPUDisjoint()531 GLint Context11::getGPUDisjoint()
532 {
533     return mRenderer->getGPUDisjoint();
534 }
535 
getTimestamp()536 GLint64 Context11::getTimestamp()
537 {
538     return mRenderer->getTimestamp();
539 }
540 
onMakeCurrent(const gl::Context * context)541 angle::Result Context11::onMakeCurrent(const gl::Context *context)
542 {
543     return mRenderer->getStateManager()->onMakeCurrent(context);
544 }
545 
getNativeCaps() const546 gl::Caps Context11::getNativeCaps() const
547 {
548     gl::Caps caps = mRenderer->getNativeCaps();
549 
550     // For pixel shaders, the render targets and unordered access views share the same resource
551     // slots, so the maximum number of fragment shader outputs depends on the current context
552     // version:
553     // - If current context is ES 3.0 and below, we use D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8)
554     //   as the value of max draw buffers because UAVs are not used.
555     // - If current context is ES 3.1 and the feature level is 11_0, the RTVs and UAVs share 8
556     //   slots. As ES 3.1 requires at least 1 atomic counter buffer in compute shaders, the value
557     //   of max combined shader output resources is limited to 7, thus only 7 RTV slots can be
558     //   used simultaneously.
559     // - If current context is ES 3.1 and the feature level is 11_1, the RTVs and UAVs share 64
560     //   slots. Currently we allocate 60 slots for combined shader output resources, so we can use
561     //   at most D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8) RTVs simultaneously.
562     if (mState.getClientVersion() >= gl::ES_3_1 &&
563         mRenderer->getRenderer11DeviceCaps().featureLevel == D3D_FEATURE_LEVEL_11_0)
564     {
565         caps.maxDrawBuffers      = caps.maxCombinedShaderOutputResources;
566         caps.maxColorAttachments = caps.maxCombinedShaderOutputResources;
567     }
568 
569     return caps;
570 }
571 
getNativeTextureCaps() const572 const gl::TextureCapsMap &Context11::getNativeTextureCaps() const
573 {
574     return mRenderer->getNativeTextureCaps();
575 }
576 
getNativeExtensions() const577 const gl::Extensions &Context11::getNativeExtensions() const
578 {
579     return mRenderer->getNativeExtensions();
580 }
581 
getNativeLimitations() const582 const gl::Limitations &Context11::getNativeLimitations() const
583 {
584     return mRenderer->getNativeLimitations();
585 }
586 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)587 angle::Result Context11::dispatchCompute(const gl::Context *context,
588                                          GLuint numGroupsX,
589                                          GLuint numGroupsY,
590                                          GLuint numGroupsZ)
591 {
592     return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
593 }
594 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)595 angle::Result Context11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
596 {
597     return mRenderer->dispatchComputeIndirect(context, indirect);
598 }
599 
triggerDrawCallProgramRecompilation(const gl::Context * context,gl::PrimitiveMode drawMode)600 angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context *context,
601                                                              gl::PrimitiveMode drawMode)
602 {
603     const auto &glState    = context->getState();
604     const auto *va11       = GetImplAs<VertexArray11>(glState.getVertexArray());
605     const auto *drawFBO    = glState.getDrawFramebuffer();
606     gl::Program *program   = glState.getProgram();
607     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
608 
609     programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState);
610     programD3D->updateCachedOutputLayout(context, drawFBO);
611 
612     bool recompileVS = !programD3D->hasVertexExecutableForCachedInputLayout();
613     bool recompileGS = !programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode);
614     bool recompilePS = !programD3D->hasPixelExecutableForCachedOutputLayout();
615 
616     if (!recompileVS && !recompileGS && !recompilePS)
617     {
618         return angle::Result::Continue;
619     }
620 
621     // Load the compiler if necessary and recompile the programs.
622     ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
623 
624     gl::InfoLog infoLog;
625 
626     if (recompileVS)
627     {
628         ShaderExecutableD3D *vertexExe = nullptr;
629         ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(this, &vertexExe, &infoLog));
630         if (!programD3D->hasVertexExecutableForCachedInputLayout())
631         {
632             ASSERT(infoLog.getLength() > 0);
633             ERR() << "Error compiling dynamic vertex executable: " << infoLog.str();
634             ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic vertex executable");
635         }
636     }
637 
638     if (recompileGS)
639     {
640         ShaderExecutableD3D *geometryExe = nullptr;
641         ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(this, glState, drawMode,
642                                                                     &geometryExe, &infoLog));
643         if (!programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode))
644         {
645             ASSERT(infoLog.getLength() > 0);
646             ERR() << "Error compiling dynamic geometry executable: " << infoLog.str();
647             ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic geometry executable");
648         }
649     }
650 
651     if (recompilePS)
652     {
653         ShaderExecutableD3D *pixelExe = nullptr;
654         ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(this, &pixelExe, &infoLog));
655         if (!programD3D->hasPixelExecutableForCachedOutputLayout())
656         {
657             ASSERT(infoLog.getLength() > 0);
658             ERR() << "Error compiling dynamic pixel executable: " << infoLog.str();
659             ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic pixel executable");
660         }
661     }
662 
663     // Refresh the program cache entry.
664     if (mMemoryProgramCache)
665     {
666         ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
667     }
668 
669     return angle::Result::Continue;
670 }
671 
triggerDispatchCallProgramRecompilation(const gl::Context * context)672 angle::Result Context11::triggerDispatchCallProgramRecompilation(const gl::Context *context)
673 {
674     const auto &glState    = context->getState();
675     gl::Program *program   = glState.getProgram();
676     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
677 
678     programD3D->updateCachedComputeImage2DBindLayout(context);
679 
680     bool recompileCS = !programD3D->hasComputeExecutableForCachedImage2DBindLayout();
681 
682     if (!recompileCS)
683     {
684         return angle::Result::Continue;
685     }
686 
687     // Load the compiler if necessary and recompile the programs.
688     ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
689 
690     gl::InfoLog infoLog;
691 
692     ShaderExecutableD3D *computeExe = nullptr;
693     ANGLE_TRY(programD3D->getComputeExecutableForImage2DBindLayout(this, &computeExe, &infoLog));
694     if (!programD3D->hasComputeExecutableForCachedImage2DBindLayout())
695     {
696         ASSERT(infoLog.getLength() > 0);
697         ERR() << "Dynamic recompilation error log: " << infoLog.str();
698         ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic compute executable");
699     }
700 
701     // Refresh the program cache entry.
702     if (mMemoryProgramCache)
703     {
704         ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
705     }
706 
707     return angle::Result::Continue;
708 }
709 
memoryBarrier(const gl::Context * context,GLbitfield barriers)710 angle::Result Context11::memoryBarrier(const gl::Context *context, GLbitfield barriers)
711 {
712     return angle::Result::Continue;
713 }
714 
memoryBarrierByRegion(const gl::Context * context,GLbitfield barriers)715 angle::Result Context11::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
716 {
717     return angle::Result::Continue;
718 }
719 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::Texture ** textureOut)720 angle::Result Context11::getIncompleteTexture(const gl::Context *context,
721                                               gl::TextureType type,
722                                               gl::Texture **textureOut)
723 {
724     return mIncompleteTextures.getIncompleteTexture(context, type, this, textureOut);
725 }
726 
initializeMultisampleTextureToBlack(const gl::Context * context,gl::Texture * glTexture)727 angle::Result Context11::initializeMultisampleTextureToBlack(const gl::Context *context,
728                                                              gl::Texture *glTexture)
729 {
730     ASSERT(glTexture->getType() == gl::TextureType::_2DMultisample);
731     TextureD3D *textureD3D        = GetImplAs<TextureD3D>(glTexture);
732     gl::ImageIndex index          = gl::ImageIndex::Make2DMultisample();
733     RenderTargetD3D *renderTarget = nullptr;
734     GLsizei texSamples            = textureD3D->getRenderToTextureSamples();
735     ANGLE_TRY(textureD3D->getRenderTarget(context, index, texSamples, &renderTarget));
736     return mRenderer->clearRenderTarget(context, renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f),
737                                         1.0f, 0);
738 }
739 
handleResult(HRESULT hr,const char * message,const char * file,const char * function,unsigned int line)740 void Context11::handleResult(HRESULT hr,
741                              const char *message,
742                              const char *file,
743                              const char *function,
744                              unsigned int line)
745 {
746     ASSERT(FAILED(hr));
747 
748     if (d3d11::isDeviceLostError(hr))
749     {
750         mRenderer->notifyDeviceLost();
751     }
752 
753     GLenum glErrorCode = DefaultGLErrorCode(hr);
754 
755     std::stringstream errorStream;
756     errorStream << "Internal D3D11 error: " << gl::FmtHR(hr) << ": " << message;
757 
758     mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
759 }
760 }  // namespace rx
761