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