• 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         ANGLE_TRY(mRenderer->getStateManager()->updateState(
313             context, mode, static_cast<GLint>(indexRange.start), indexCount, indexType, indices,
314             instanceCount, baseVertex));
315         return mRenderer->drawElements(context, mode, static_cast<GLint>(indexRange.start),
316                                        indexCount, indexType, indices, instanceCount, baseVertex,
317                                        baseInstance);
318     }
319     else
320     {
321         ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, 0, indexCount, indexType,
322                                                             indices, instanceCount, baseVertex));
323         return mRenderer->drawElements(context, mode, 0, indexCount, indexType, indices,
324                                        instanceCount, baseVertex, baseInstance);
325     }
326 }
327 
drawElements(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices)328 angle::Result Context11::drawElements(const gl::Context *context,
329                                       gl::PrimitiveMode mode,
330                                       GLsizei count,
331                                       gl::DrawElementsType type,
332                                       const void *indices)
333 {
334     return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0);
335 }
336 
drawElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)337 angle::Result Context11::drawElementsBaseVertex(const gl::Context *context,
338                                                 gl::PrimitiveMode mode,
339                                                 GLsizei count,
340                                                 gl::DrawElementsType type,
341                                                 const void *indices,
342                                                 GLint baseVertex)
343 {
344     return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0);
345 }
346 
drawElementsInstanced(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances)347 angle::Result Context11::drawElementsInstanced(const gl::Context *context,
348                                                gl::PrimitiveMode mode,
349                                                GLsizei count,
350                                                gl::DrawElementsType type,
351                                                const void *indices,
352                                                GLsizei instances)
353 {
354     return drawElementsImpl(context, mode, count, type, indices, instances, 0, 0);
355 }
356 
drawElementsInstancedBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex)357 angle::Result Context11::drawElementsInstancedBaseVertex(const gl::Context *context,
358                                                          gl::PrimitiveMode mode,
359                                                          GLsizei count,
360                                                          gl::DrawElementsType type,
361                                                          const void *indices,
362                                                          GLsizei instances,
363                                                          GLint baseVertex)
364 {
365     return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex, 0);
366 }
367 
drawElementsInstancedBaseVertexBaseInstance(const gl::Context * context,gl::PrimitiveMode mode,GLsizei count,gl::DrawElementsType type,const void * indices,GLsizei instances,GLint baseVertex,GLuint baseInstance)368 angle::Result Context11::drawElementsInstancedBaseVertexBaseInstance(const gl::Context *context,
369                                                                      gl::PrimitiveMode mode,
370                                                                      GLsizei count,
371                                                                      gl::DrawElementsType type,
372                                                                      const void *indices,
373                                                                      GLsizei instances,
374                                                                      GLint baseVertex,
375                                                                      GLuint baseInstance)
376 {
377     return drawElementsImpl(context, mode, count, type, indices, instances, baseVertex,
378                             baseInstance);
379 }
380 
drawRangeElements(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices)381 angle::Result Context11::drawRangeElements(const gl::Context *context,
382                                            gl::PrimitiveMode mode,
383                                            GLuint start,
384                                            GLuint end,
385                                            GLsizei count,
386                                            gl::DrawElementsType type,
387                                            const void *indices)
388 {
389     return drawElementsImpl(context, mode, count, type, indices, 0, 0, 0);
390 }
391 
drawRangeElementsBaseVertex(const gl::Context * context,gl::PrimitiveMode mode,GLuint start,GLuint end,GLsizei count,gl::DrawElementsType type,const void * indices,GLint baseVertex)392 angle::Result Context11::drawRangeElementsBaseVertex(const gl::Context *context,
393                                                      gl::PrimitiveMode mode,
394                                                      GLuint start,
395                                                      GLuint end,
396                                                      GLsizei count,
397                                                      gl::DrawElementsType type,
398                                                      const void *indices,
399                                                      GLint baseVertex)
400 {
401     return drawElementsImpl(context, mode, count, type, indices, 0, baseVertex, 0);
402 }
403 
drawArraysIndirect(const gl::Context * context,gl::PrimitiveMode mode,const void * indirect)404 angle::Result Context11::drawArraysIndirect(const gl::Context *context,
405                                             gl::PrimitiveMode mode,
406                                             const void *indirect)
407 {
408     if (DrawCallHasStreamingVertexArrays(context, mode))
409     {
410         const gl::DrawArraysIndirectCommand *cmd = nullptr;
411         ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
412 
413         ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, cmd->first, cmd->count,
414                                                             gl::DrawElementsType::InvalidEnum,
415                                                             nullptr, cmd->instanceCount, 0));
416         return mRenderer->drawArrays(context, mode, cmd->first, cmd->count, cmd->instanceCount,
417                                      cmd->baseInstance);
418     }
419     else
420     {
421         ANGLE_TRY(mRenderer->getStateManager()->updateState(
422             context, mode, 0, 0, gl::DrawElementsType::InvalidEnum, nullptr, 0, 0));
423         return mRenderer->drawArraysIndirect(context, indirect);
424     }
425 }
426 
drawElementsIndirect(const gl::Context * context,gl::PrimitiveMode mode,gl::DrawElementsType type,const void * indirect)427 angle::Result Context11::drawElementsIndirect(const gl::Context *context,
428                                               gl::PrimitiveMode mode,
429                                               gl::DrawElementsType type,
430                                               const void *indirect)
431 {
432     if (DrawCallHasStreamingVertexArrays(context, mode) ||
433         DrawCallHasStreamingElementArray(context, type))
434     {
435         const gl::DrawElementsIndirectCommand *cmd = nullptr;
436         ANGLE_TRY(ReadbackIndirectBuffer(context, indirect, &cmd));
437 
438         const GLuint typeBytes = gl::GetDrawElementsTypeSize(type);
439         const void *indices =
440             reinterpret_cast<const void *>(static_cast<uintptr_t>(cmd->firstIndex * typeBytes));
441 
442         // We must explicitly resolve the index range for the slow-path indirect drawElements to
443         // make sure we are using the correct 'baseVertex'. This parameter does not exist for the
444         // direct drawElements.
445         gl::IndexRange indexRange;
446         ANGLE_TRY(context->getState().getVertexArray()->getIndexRange(context, type, cmd->count,
447                                                                       indices, &indexRange));
448 
449         GLint startVertex;
450         ANGLE_TRY(ComputeStartVertex(GetImplAs<Context11>(context), indexRange, cmd->baseVertex,
451                                      &startVertex));
452 
453         ANGLE_TRY(mRenderer->getStateManager()->updateState(context, mode, startVertex, cmd->count,
454                                                             type, indices, cmd->primCount,
455                                                             cmd->baseVertex));
456         return mRenderer->drawElements(context, mode, static_cast<GLint>(indexRange.start),
457                                        cmd->count, type, indices, cmd->primCount, 0, 0);
458     }
459     else
460     {
461         ANGLE_TRY(
462             mRenderer->getStateManager()->updateState(context, mode, 0, 0, type, nullptr, 0, 0));
463         return mRenderer->drawElementsIndirect(context, indirect);
464     }
465 }
466 
getResetStatus()467 gl::GraphicsResetStatus Context11::getResetStatus()
468 {
469     return mRenderer->getResetStatus();
470 }
471 
getVendorString() const472 std::string Context11::getVendorString() const
473 {
474     return mRenderer->getVendorString();
475 }
476 
getRendererDescription() const477 std::string Context11::getRendererDescription() const
478 {
479     return mRenderer->getRendererDescription();
480 }
481 
insertEventMarker(GLsizei length,const char * marker)482 angle::Result Context11::insertEventMarker(GLsizei length, const char *marker)
483 {
484     mRenderer->getAnnotator()->setMarker(marker);
485     return angle::Result::Continue;
486 }
487 
pushGroupMarker(GLsizei length,const char * marker)488 angle::Result Context11::pushGroupMarker(GLsizei length, const char *marker)
489 {
490     mRenderer->getAnnotator()->beginEvent(marker, marker);
491     mMarkerStack.push(std::string(marker));
492     return angle::Result::Continue;
493 }
494 
popGroupMarker()495 angle::Result Context11::popGroupMarker()
496 {
497     const char *marker = nullptr;
498     if (!mMarkerStack.empty())
499     {
500         marker = mMarkerStack.top().c_str();
501         mMarkerStack.pop();
502         mRenderer->getAnnotator()->endEvent(marker);
503     }
504     return angle::Result::Continue;
505 }
506 
pushDebugGroup(const gl::Context * context,GLenum source,GLuint id,const std::string & message)507 angle::Result Context11::pushDebugGroup(const gl::Context *context,
508                                         GLenum source,
509                                         GLuint id,
510                                         const std::string &message)
511 {
512     // Fall through to the EXT_debug_marker functions
513     return pushGroupMarker(static_cast<GLsizei>(message.size()), message.c_str());
514 }
515 
popDebugGroup(const gl::Context * context)516 angle::Result Context11::popDebugGroup(const gl::Context *context)
517 {
518     // Fall through to the EXT_debug_marker functions
519     return popGroupMarker();
520 }
521 
syncState(const gl::Context * context,const gl::State::DirtyBits & dirtyBits,const gl::State::DirtyBits & bitMask)522 angle::Result Context11::syncState(const gl::Context *context,
523                                    const gl::State::DirtyBits &dirtyBits,
524                                    const gl::State::DirtyBits &bitMask)
525 {
526     mRenderer->getStateManager()->syncState(context, dirtyBits);
527     return angle::Result::Continue;
528 }
529 
getGPUDisjoint()530 GLint Context11::getGPUDisjoint()
531 {
532     return mRenderer->getGPUDisjoint();
533 }
534 
getTimestamp()535 GLint64 Context11::getTimestamp()
536 {
537     return mRenderer->getTimestamp();
538 }
539 
onMakeCurrent(const gl::Context * context)540 angle::Result Context11::onMakeCurrent(const gl::Context *context)
541 {
542     return mRenderer->getStateManager()->onMakeCurrent(context);
543 }
544 
getNativeCaps() const545 gl::Caps Context11::getNativeCaps() const
546 {
547     gl::Caps caps = mRenderer->getNativeCaps();
548 
549     // For pixel shaders, the render targets and unordered access views share the same resource
550     // slots, so the maximum number of fragment shader outputs depends on the current context
551     // version:
552     // - If current context is ES 3.0 and below, we use D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8)
553     //   as the value of max draw buffers because UAVs are not used.
554     // - If current context is ES 3.1 and the feature level is 11_0, the RTVs and UAVs share 8
555     //   slots. As ES 3.1 requires at least 1 atomic counter buffer in compute shaders, the value
556     //   of max combined shader output resources is limited to 7, thus only 7 RTV slots can be
557     //   used simultaneously.
558     // - If current context is ES 3.1 and the feature level is 11_1, the RTVs and UAVs share 64
559     //   slots. Currently we allocate 60 slots for combined shader output resources, so we can use
560     //   at most D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT(8) RTVs simultaneously.
561     if (mState.getClientVersion() >= gl::ES_3_1 &&
562         mRenderer->getRenderer11DeviceCaps().featureLevel == D3D_FEATURE_LEVEL_11_0)
563     {
564         caps.maxDrawBuffers      = caps.maxCombinedShaderOutputResources;
565         caps.maxColorAttachments = caps.maxCombinedShaderOutputResources;
566     }
567 
568     return caps;
569 }
570 
getNativeTextureCaps() const571 const gl::TextureCapsMap &Context11::getNativeTextureCaps() const
572 {
573     return mRenderer->getNativeTextureCaps();
574 }
575 
getNativeExtensions() const576 const gl::Extensions &Context11::getNativeExtensions() const
577 {
578     return mRenderer->getNativeExtensions();
579 }
580 
getNativeLimitations() const581 const gl::Limitations &Context11::getNativeLimitations() const
582 {
583     return mRenderer->getNativeLimitations();
584 }
585 
dispatchCompute(const gl::Context * context,GLuint numGroupsX,GLuint numGroupsY,GLuint numGroupsZ)586 angle::Result Context11::dispatchCompute(const gl::Context *context,
587                                          GLuint numGroupsX,
588                                          GLuint numGroupsY,
589                                          GLuint numGroupsZ)
590 {
591     return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ);
592 }
593 
dispatchComputeIndirect(const gl::Context * context,GLintptr indirect)594 angle::Result Context11::dispatchComputeIndirect(const gl::Context *context, GLintptr indirect)
595 {
596     return mRenderer->dispatchComputeIndirect(context, indirect);
597 }
598 
triggerDrawCallProgramRecompilation(const gl::Context * context,gl::PrimitiveMode drawMode)599 angle::Result Context11::triggerDrawCallProgramRecompilation(const gl::Context *context,
600                                                              gl::PrimitiveMode drawMode)
601 {
602     const auto &glState    = context->getState();
603     const auto *va11       = GetImplAs<VertexArray11>(glState.getVertexArray());
604     const auto *drawFBO    = glState.getDrawFramebuffer();
605     gl::Program *program   = glState.getProgram();
606     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
607 
608     programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState);
609     programD3D->updateCachedOutputLayout(context, drawFBO);
610 
611     bool recompileVS = !programD3D->hasVertexExecutableForCachedInputLayout();
612     bool recompileGS = !programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode);
613     bool recompilePS = !programD3D->hasPixelExecutableForCachedOutputLayout();
614 
615     if (!recompileVS && !recompileGS && !recompilePS)
616     {
617         return angle::Result::Continue;
618     }
619 
620     // Load the compiler if necessary and recompile the programs.
621     ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
622 
623     gl::InfoLog infoLog;
624 
625     if (recompileVS)
626     {
627         ShaderExecutableD3D *vertexExe = nullptr;
628         ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(this, &vertexExe, &infoLog));
629         if (!programD3D->hasVertexExecutableForCachedInputLayout())
630         {
631             ASSERT(infoLog.getLength() > 0);
632             ERR() << "Error compiling dynamic vertex executable: " << infoLog.str();
633             ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic vertex executable");
634         }
635     }
636 
637     if (recompileGS)
638     {
639         ShaderExecutableD3D *geometryExe = nullptr;
640         ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(this, glState, drawMode,
641                                                                     &geometryExe, &infoLog));
642         if (!programD3D->hasGeometryExecutableForPrimitiveType(glState, drawMode))
643         {
644             ASSERT(infoLog.getLength() > 0);
645             ERR() << "Error compiling dynamic geometry executable: " << infoLog.str();
646             ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic geometry executable");
647         }
648     }
649 
650     if (recompilePS)
651     {
652         ShaderExecutableD3D *pixelExe = nullptr;
653         ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(this, &pixelExe, &infoLog));
654         if (!programD3D->hasPixelExecutableForCachedOutputLayout())
655         {
656             ASSERT(infoLog.getLength() > 0);
657             ERR() << "Error compiling dynamic pixel executable: " << infoLog.str();
658             ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic pixel executable");
659         }
660     }
661 
662     // Refresh the program cache entry.
663     if (mMemoryProgramCache)
664     {
665         ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
666     }
667 
668     return angle::Result::Continue;
669 }
670 
triggerDispatchCallProgramRecompilation(const gl::Context * context)671 angle::Result Context11::triggerDispatchCallProgramRecompilation(const gl::Context *context)
672 {
673     const auto &glState    = context->getState();
674     gl::Program *program   = glState.getProgram();
675     ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
676 
677     programD3D->updateCachedComputeImage2DBindLayout(context);
678 
679     bool recompileCS = !programD3D->hasComputeExecutableForCachedImage2DBindLayout();
680 
681     if (!recompileCS)
682     {
683         return angle::Result::Continue;
684     }
685 
686     // Load the compiler if necessary and recompile the programs.
687     ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized(this));
688 
689     gl::InfoLog infoLog;
690 
691     ShaderExecutableD3D *computeExe = nullptr;
692     ANGLE_TRY(programD3D->getComputeExecutableForImage2DBindLayout(this, &computeExe, &infoLog));
693     if (!programD3D->hasComputeExecutableForCachedImage2DBindLayout())
694     {
695         ASSERT(infoLog.getLength() > 0);
696         ERR() << "Dynamic recompilation error log: " << infoLog.str();
697         ANGLE_TRY_HR(this, E_FAIL, "Error compiling dynamic compute executable");
698     }
699 
700     // Refresh the program cache entry.
701     if (mMemoryProgramCache)
702     {
703         ANGLE_TRY(mMemoryProgramCache->updateProgram(context, program));
704     }
705 
706     return angle::Result::Continue;
707 }
708 
memoryBarrier(const gl::Context * context,GLbitfield barriers)709 angle::Result Context11::memoryBarrier(const gl::Context *context, GLbitfield barriers)
710 {
711     return angle::Result::Continue;
712 }
713 
memoryBarrierByRegion(const gl::Context * context,GLbitfield barriers)714 angle::Result Context11::memoryBarrierByRegion(const gl::Context *context, GLbitfield barriers)
715 {
716     return angle::Result::Continue;
717 }
718 
getIncompleteTexture(const gl::Context * context,gl::TextureType type,gl::Texture ** textureOut)719 angle::Result Context11::getIncompleteTexture(const gl::Context *context,
720                                               gl::TextureType type,
721                                               gl::Texture **textureOut)
722 {
723     return mIncompleteTextures.getIncompleteTexture(context, type, this, textureOut);
724 }
725 
initializeMultisampleTextureToBlack(const gl::Context * context,gl::Texture * glTexture)726 angle::Result Context11::initializeMultisampleTextureToBlack(const gl::Context *context,
727                                                              gl::Texture *glTexture)
728 {
729     ASSERT(glTexture->getType() == gl::TextureType::_2DMultisample);
730     TextureD3D *textureD3D        = GetImplAs<TextureD3D>(glTexture);
731     gl::ImageIndex index          = gl::ImageIndex::Make2DMultisample();
732     RenderTargetD3D *renderTarget = nullptr;
733     GLsizei texSamples            = textureD3D->getRenderToTextureSamples();
734     ANGLE_TRY(textureD3D->getRenderTarget(context, index, texSamples, &renderTarget));
735     return mRenderer->clearRenderTarget(context, renderTarget, gl::ColorF(0.0f, 0.0f, 0.0f, 1.0f),
736                                         1.0f, 0);
737 }
738 
handleResult(HRESULT hr,const char * message,const char * file,const char * function,unsigned int line)739 void Context11::handleResult(HRESULT hr,
740                              const char *message,
741                              const char *file,
742                              const char *function,
743                              unsigned int line)
744 {
745     ASSERT(FAILED(hr));
746 
747     if (d3d11::isDeviceLostError(hr))
748     {
749         mRenderer->notifyDeviceLost();
750     }
751 
752     GLenum glErrorCode = DefaultGLErrorCode(hr);
753 
754     std::stringstream errorStream;
755     errorStream << "Internal D3D11 error: " << gl::FmtHR(hr) << ": " << message;
756 
757     mErrors->handleError(glErrorCode, errorStream.str().c_str(), file, function, line);
758 }
759 }  // namespace rx
760