• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2012 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 
7 // renderer11_utils.h: Conversion functions and other utility routines
8 // specific to the D3D11 renderer.
9 
10 #ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
11 #define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
12 
13 #include <array>
14 #include <functional>
15 #include <vector>
16 
17 #include "common/Color.h"
18 
19 #include "libANGLE/Caps.h"
20 #include "libANGLE/Error.h"
21 #include "libANGLE/renderer/d3d/RendererD3D.h"
22 #include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h"
23 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
24 
25 namespace gl
26 {
27 class FramebufferAttachment;
28 }
29 
30 namespace rx
31 {
32 class Context11;
33 class Renderer11;
34 class RenderTarget11;
35 struct Renderer11DeviceCaps;
36 
37 using RTVArray = std::array<ID3D11RenderTargetView *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS>;
38 
39 namespace gl_d3d11
40 {
41 
42 D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha);
43 D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp);
44 UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha);
45 
46 D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode);
47 
48 D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison);
49 D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled);
50 UINT8 ConvertStencilMask(GLuint stencilmask);
51 D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp);
52 
53 D3D11_FILTER ConvertFilter(GLenum minFilter,
54                            GLenum magFilter,
55                            float maxAnisotropy,
56                            GLenum comparisonMode);
57 D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap);
58 UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel);
59 
60 D3D11_QUERY ConvertQueryType(gl::QueryType type);
61 
62 UINT8 GetColorMask(const gl::InternalFormat &formatInfo);
63 
64 }  // namespace gl_d3d11
65 
66 namespace d3d11_gl
67 {
68 
69 unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel);
70 
71 unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel);
72 
73 gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel);
74 void GenerateCaps(ID3D11Device *device,
75                   ID3D11DeviceContext *deviceContext,
76                   const Renderer11DeviceCaps &renderer11DeviceCaps,
77                   const angle::FeaturesD3D &features,
78                   const char *description,
79                   gl::Caps *caps,
80                   gl::TextureCapsMap *textureCapsMap,
81                   gl::Extensions *extensions,
82                   gl::Limitations *limitations);
83 
84 D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31();
85 
86 }  // namespace d3d11_gl
87 
88 namespace d3d11
89 {
90 
91 enum ANGLED3D11DeviceType
92 {
93     ANGLE_D3D11_DEVICE_TYPE_UNKNOWN,
94     ANGLE_D3D11_DEVICE_TYPE_HARDWARE,
95     ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL,
96     ANGLE_D3D11_DEVICE_TYPE_WARP,
97 };
98 
99 ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device);
100 
101 void MakeValidSize(bool isImage,
102                    DXGI_FORMAT format,
103                    GLsizei *requestWidth,
104                    GLsizei *requestHeight,
105                    int *levelOffset);
106 
107 angle::Result GenerateInitialTextureData(
108     const gl::Context *context,
109     GLint internalFormat,
110     const Renderer11DeviceCaps &renderer11DeviceCaps,
111     GLuint width,
112     GLuint height,
113     GLuint depth,
114     GLuint mipLevels,
115     gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> *outSubresourceData);
116 
117 UINT GetPrimitiveRestartIndex();
118 
119 struct PositionTexCoordVertex
120 {
121     float x, y;
122     float u, v;
123 };
124 void SetPositionTexCoordVertex(PositionTexCoordVertex *vertex, float x, float y, float u, float v);
125 
126 struct PositionLayerTexCoord3DVertex
127 {
128     float x, y;
129     unsigned int l;
130     float u, v, s;
131 };
132 void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex *vertex,
133                                       float x,
134                                       float y,
135                                       unsigned int layer,
136                                       float u,
137                                       float v,
138                                       float s);
139 
140 struct PositionVertex
141 {
142     float x, y, z, w;
143 };
144 
145 struct BlendStateKey final
146 {
147     // This will zero-initialize the struct, including padding.
148     BlendStateKey();
149     BlendStateKey(const BlendStateKey &other);
150 
151     gl::BlendStateArray blendStateArray;
152 
153     uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT];
154 
155     // Use two 16-bit ints to round the struct nicely.
156     uint16_t rtvMax;
157     uint16_t sampleAlphaToCoverage;
158 };
159 
160 bool operator==(const BlendStateKey &a, const BlendStateKey &b);
161 bool operator!=(const BlendStateKey &a, const BlendStateKey &b);
162 
163 struct RasterizerStateKey final
164 {
165     // This will zero-initialize the struct, including padding.
166     RasterizerStateKey();
167 
168     gl::RasterizerState rasterizerState;
169 
170     // Use a 32-bit int to round the struct nicely.
171     uint32_t scissorEnabled;
172 };
173 
174 bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b);
175 bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b);
176 
177 template <typename outType>
DynamicCastComObject(IUnknown * object)178 outType *DynamicCastComObject(IUnknown *object)
179 {
180     outType *outObject = nullptr;
181     HRESULT result =
182         object->QueryInterface(__uuidof(outType), reinterpret_cast<void **>(&outObject));
183     if (SUCCEEDED(result))
184     {
185         return outObject;
186     }
187     else
188     {
189         SafeRelease(outObject);
190         return nullptr;
191     }
192 }
193 
194 template <typename outType>
DynamicCastComObjectToComPtr(IUnknown * object)195 angle::ComPtr<outType> DynamicCastComObjectToComPtr(IUnknown *object)
196 {
197     angle::ComPtr<outType> outObject;
198     const HRESULT hr = object->QueryInterface(IID_PPV_ARGS(&outObject));
199     if (SUCCEEDED(hr))
200     {
201         return outObject;
202     }
203     else
204     {
205         return nullptr;
206     }
207 }
208 
isDeviceLostError(HRESULT errorCode)209 inline bool isDeviceLostError(HRESULT errorCode)
210 {
211     switch (errorCode)
212     {
213         case DXGI_ERROR_DEVICE_HUNG:
214         case DXGI_ERROR_DEVICE_REMOVED:
215         case DXGI_ERROR_DEVICE_RESET:
216         case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
217         case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
218             return true;
219         default:
220             return false;
221     }
222 }
223 
224 template <ResourceType ResourceT>
225 class LazyResource : angle::NonCopyable
226 {
227   public:
LazyResource()228     constexpr LazyResource() : mResource() {}
~LazyResource()229     virtual ~LazyResource() {}
230 
231     virtual angle::Result resolve(d3d::Context *context, Renderer11 *renderer) = 0;
reset()232     void reset() { mResource.reset(); }
get()233     GetD3D11Type<ResourceT> *get() const
234     {
235         ASSERT(mResource.valid());
236         return mResource.get();
237     }
238 
getObj()239     const Resource11<GetD3D11Type<ResourceT>> &getObj() const { return mResource; }
240 
241   protected:
LazyResource(LazyResource && other)242     LazyResource(LazyResource &&other) : mResource(std::move(other.mResource)) {}
243 
244     // Specialized in the cpp file to avoid MSVS/Clang specific code.
245     angle::Result resolveImpl(d3d::Context *context,
246                               Renderer11 *renderer,
247                               const GetDescType<ResourceT> &desc,
248                               GetInitDataType<ResourceT> *initData,
249                               const char *name);
250 
251     Resource11<GetD3D11Type<ResourceT>> mResource;
252 };
253 
254 template <typename D3D11ShaderType>
255 class LazyShader final : public LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>
256 {
257   public:
258     // All parameters must be constexpr. Not supported in VS2013.
LazyShader(const BYTE * byteCode,size_t byteCodeSize,const char * name)259     constexpr LazyShader(const BYTE *byteCode, size_t byteCodeSize, const char *name)
260         : mByteCode(byteCode, byteCodeSize), mName(name)
261     {}
262 
LazyShader(LazyShader && shader)263     constexpr LazyShader(LazyShader &&shader)
264         : LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>(std::move(shader)),
265           mByteCode(std::move(shader.mByteCode)),
266           mName(shader.mName)
267     {}
268 
resolve(d3d::Context * context,Renderer11 * renderer)269     angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override
270     {
271         return this->resolveImpl(context, renderer, mByteCode, nullptr, mName);
272     }
273 
274   private:
275     ShaderData mByteCode;
276     const char *mName;
277 };
278 
279 class LazyInputLayout final : public LazyResource<ResourceType::InputLayout>
280 {
281   public:
282     LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
283                     size_t inputDescLen,
284                     const BYTE *byteCode,
285                     size_t byteCodeLen,
286                     const char *debugName);
287     ~LazyInputLayout() override;
288 
289     angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override;
290 
291   private:
292     InputElementArray mInputDesc;
293     ShaderData mByteCode;
294     const char *mDebugName;
295 };
296 
297 class LazyBlendState final : public LazyResource<ResourceType::BlendState>
298 {
299   public:
300     LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);
301 
302     angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override;
303 
304   private:
305     D3D11_BLEND_DESC mDesc;
306     const char *mDebugName;
307 };
308 
309 // Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to
310 // represent an entire buffer.
311 template <class T>
SetBufferData(ID3D11DeviceContext * context,ID3D11Buffer * constantBuffer,const T & value)312 void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value)
313 {
314     D3D11_MAPPED_SUBRESOURCE mappedResource = {};
315     HRESULT result = context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
316     ASSERT(SUCCEEDED(result));
317     if (SUCCEEDED(result))
318     {
319         memcpy(mappedResource.pData, &value, sizeof(T));
320         context->Unmap(constantBuffer, 0);
321     }
322 }
323 
324 void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
325                         const DXGI_ADAPTER_DESC &adapterDesc,
326                         angle::FeaturesD3D *features);
327 
328 enum ReservedConstantBufferSlot
329 {
330     RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK = 0,
331     RESERVED_CONSTANT_BUFFER_SLOT_DRIVER                = 1,
332 
333     RESERVED_CONSTANT_BUFFER_SLOT_COUNT = 2
334 };
335 
336 void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth);
337 
338 // Helper class for RAII patterning.
339 template <typename T>
340 class ScopedUnmapper final : angle::NonCopyable
341 {
342   public:
ScopedUnmapper(T * object)343     ScopedUnmapper(T *object) : mObject(object) {}
~ScopedUnmapper()344     ~ScopedUnmapper() { mObject->unmap(); }
345 
346   private:
347     T *mObject;
348 };
349 }  // namespace d3d11
350 
351 struct GenericData
352 {
GenericDataGenericData353     GenericData() {}
~GenericDataGenericData354     ~GenericData()
355     {
356         if (object)
357         {
358             // We can have a nullptr factory when holding passed-in resources.
359             if (manager)
360             {
361                 manager->onReleaseGeneric(resourceType, object);
362                 manager = nullptr;
363             }
364             object->Release();
365             object = nullptr;
366         }
367     }
368 
369     ResourceType resourceType  = ResourceType::Last;
370     ID3D11Resource *object     = nullptr;
371     ResourceManager11 *manager = nullptr;
372 };
373 
374 // A helper class which wraps a 2D or 3D texture.
375 class TextureHelper11 : public Resource11Base<ID3D11Resource, std::shared_ptr, GenericData>
376 {
377   public:
378     TextureHelper11();
379     TextureHelper11(TextureHelper11 &&other);
380     TextureHelper11(const TextureHelper11 &other);
381     ~TextureHelper11() override;
382     TextureHelper11 &operator=(TextureHelper11 &&other);
383     TextureHelper11 &operator=(const TextureHelper11 &other);
384 
is2D()385     bool is2D() const { return mData->resourceType == ResourceType::Texture2D; }
is3D()386     bool is3D() const { return mData->resourceType == ResourceType::Texture3D; }
getTextureType()387     ResourceType getTextureType() const { return mData->resourceType; }
getExtents()388     gl::Extents getExtents() const { return mExtents; }
getFormat()389     DXGI_FORMAT getFormat() const { return mFormatSet->texFormat; }
getFormatSet()390     const d3d11::Format &getFormatSet() const { return *mFormatSet; }
getSampleCount()391     int getSampleCount() const { return mSampleCount; }
392 
393     template <typename DescT, typename ResourceT>
init(Resource11<ResourceT> && texture,const DescT & desc,const d3d11::Format & format)394     void init(Resource11<ResourceT> &&texture, const DescT &desc, const d3d11::Format &format)
395     {
396         std::swap(mData->manager, texture.mData->manager);
397 
398         // Can't use std::swap because texture is typed, and here we use ID3D11Resource.
399         ID3D11Resource *temp  = mData->object;
400         mData->object         = texture.mData->object;
401         texture.mData->object = static_cast<ResourceT *>(temp);
402 
403         mFormatSet = &format;
404         initDesc(desc);
405     }
406 
407     template <typename ResourceT>
set(ResourceT * object,const d3d11::Format & format)408     void set(ResourceT *object, const d3d11::Format &format)
409     {
410         ASSERT(!valid());
411 
412         mFormatSet     = &format;
413         mData->object  = object;
414         mData->manager = nullptr;
415 
416         GetDescFromD3D11<ResourceT> desc;
417         getDesc(&desc);
418         initDesc(desc);
419     }
420 
421     bool operator==(const TextureHelper11 &other) const;
422     bool operator!=(const TextureHelper11 &other) const;
423 
424     void getDesc(D3D11_TEXTURE2D_DESC *desc) const;
425     void getDesc(D3D11_TEXTURE3D_DESC *desc) const;
426 
427   private:
428     void initDesc(const D3D11_TEXTURE2D_DESC &desc2D);
429     void initDesc(const D3D11_TEXTURE3D_DESC &desc3D);
430 
431     const d3d11::Format *mFormatSet;
432     gl::Extents mExtents;
433     int mSampleCount;
434 };
435 
436 enum class StagingAccess
437 {
438     READ,
439     READ_WRITE,
440 };
441 
442 bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer);
443 bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
444                                    gl::DrawElementsType type);
445 
446 enum class IndexStorageType
447 {
448     // Dynamic indexes are re-streamed every frame. They come from a client data pointer or
449     // from buffers that are updated frequently.
450     Dynamic,
451 
452     // Static indexes are translated from the original storage once, and re-used multiple times.
453     Static,
454 
455     // Direct indexes are never transated and are used directly from the source buffer. They are
456     // the fastest available path.
457     Direct,
458 
459     // Not a real storage type.
460     Invalid,
461 };
462 
463 IndexStorageType ClassifyIndexStorage(const gl::State &glState,
464                                       const gl::Buffer *elementArrayBuffer,
465                                       gl::DrawElementsType elementType,
466                                       gl::DrawElementsType destElementType,
467                                       unsigned int offset);
468 
469 }  // namespace rx
470 
471 #endif  // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
472