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