• 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(const Renderer11DeviceCaps &caps);
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                   ShPixelLocalStorageOptions *);
84 
85 D3D_FEATURE_LEVEL GetMinimumFeatureLevelForES31();
86 
87 }  // namespace d3d11_gl
88 
89 namespace d3d11
90 {
91 
92 enum ANGLED3D11DeviceType
93 {
94     ANGLE_D3D11_DEVICE_TYPE_UNKNOWN,
95     ANGLE_D3D11_DEVICE_TYPE_HARDWARE,
96     ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL,
97     ANGLE_D3D11_DEVICE_TYPE_WARP,
98 };
99 
100 ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device);
101 
102 void MakeValidSize(bool isImage,
103                    DXGI_FORMAT format,
104                    GLsizei *requestWidth,
105                    GLsizei *requestHeight,
106                    int *levelOffset);
107 
108 angle::Result GenerateInitialTextureData(
109     const gl::Context *context,
110     GLint internalFormat,
111     const Renderer11DeviceCaps &renderer11DeviceCaps,
112     GLuint width,
113     GLuint height,
114     GLuint depth,
115     GLuint mipLevels,
116     gl::TexLevelArray<D3D11_SUBRESOURCE_DATA> *outSubresourceData);
117 
118 UINT GetPrimitiveRestartIndex();
119 
120 struct PositionTexCoordVertex
121 {
122     float x, y;
123     float u, v;
124 };
125 void SetPositionTexCoordVertex(PositionTexCoordVertex *vertex, float x, float y, float u, float v);
126 
127 struct PositionLayerTexCoord3DVertex
128 {
129     float x, y;
130     unsigned int l;
131     float u, v, s;
132 };
133 void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex *vertex,
134                                       float x,
135                                       float y,
136                                       unsigned int layer,
137                                       float u,
138                                       float v,
139                                       float s);
140 
141 struct PositionVertex
142 {
143     float x, y, z, w;
144 };
145 
146 struct BlendStateKey final
147 {
148     // This will zero-initialize the struct, including padding.
149     BlendStateKey();
150     BlendStateKey(const BlendStateKey &other);
151 
152     gl::BlendStateExt blendStateExt;
153 
154     // Use two 16-bit ints to round the struct nicely.
155     uint16_t rtvMax;
156     uint16_t sampleAlphaToCoverage;
157 };
158 
159 bool operator==(const BlendStateKey &a, const BlendStateKey &b);
160 bool operator!=(const BlendStateKey &a, const BlendStateKey &b);
161 
162 struct RasterizerStateKey final
163 {
164     // This will zero-initialize the struct, including padding.
165     RasterizerStateKey();
166 
167     gl::RasterizerState rasterizerState;
168 
169     // Use a 32-bit int to round the struct nicely.
170     uint32_t scissorEnabled;
171 };
172 
173 bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b);
174 bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b);
175 
176 template <typename outType>
DynamicCastComObject(IUnknown * object)177 outType *DynamicCastComObject(IUnknown *object)
178 {
179     outType *outObject = nullptr;
180     HRESULT result =
181         object->QueryInterface(__uuidof(outType), reinterpret_cast<void **>(&outObject));
182     if (SUCCEEDED(result))
183     {
184         return outObject;
185     }
186     else
187     {
188         SafeRelease(outObject);
189         return nullptr;
190     }
191 }
192 
isDeviceLostError(HRESULT errorCode)193 inline bool isDeviceLostError(HRESULT errorCode)
194 {
195     switch (errorCode)
196     {
197         case DXGI_ERROR_DEVICE_HUNG:
198         case DXGI_ERROR_DEVICE_REMOVED:
199         case DXGI_ERROR_DEVICE_RESET:
200         case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
201         case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
202             return true;
203         default:
204             return false;
205     }
206 }
207 
208 template <ResourceType ResourceT>
209 class LazyResource : angle::NonCopyable
210 {
211   public:
LazyResource()212     constexpr LazyResource() : mResource() {}
~LazyResource()213     virtual ~LazyResource() {}
214 
215     virtual angle::Result resolve(d3d::Context *context, Renderer11 *renderer) = 0;
reset()216     void reset() { mResource.reset(); }
get()217     GetD3D11Type<ResourceT> *get() const
218     {
219         ASSERT(mResource.valid());
220         return mResource.get();
221     }
222 
getObj()223     const Resource11<GetD3D11Type<ResourceT>> &getObj() const { return mResource; }
224 
225   protected:
LazyResource(LazyResource && other)226     LazyResource(LazyResource &&other) : mResource(std::move(other.mResource)) {}
227 
228     // Specialized in the cpp file to avoid MSVS/Clang specific code.
229     angle::Result resolveImpl(d3d::Context *context,
230                               Renderer11 *renderer,
231                               const GetDescType<ResourceT> &desc,
232                               GetInitDataType<ResourceT> *initData,
233                               const char *name);
234 
235     Resource11<GetD3D11Type<ResourceT>> mResource;
236 };
237 
238 template <typename D3D11ShaderType>
239 class LazyShader final : public LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>
240 {
241   public:
242     // All parameters must be constexpr. Not supported in VS2013.
LazyShader(const BYTE * byteCode,size_t byteCodeSize,const char * name)243     constexpr LazyShader(const BYTE *byteCode, size_t byteCodeSize, const char *name)
244         : mByteCode(byteCode, byteCodeSize), mName(name)
245     {}
246 
LazyShader(LazyShader && shader)247     constexpr LazyShader(LazyShader &&shader)
248         : LazyResource<GetResourceTypeFromD3D11<D3D11ShaderType>()>(std::move(shader)),
249           mByteCode(std::move(shader.mByteCode)),
250           mName(shader.mName)
251     {}
252 
resolve(d3d::Context * context,Renderer11 * renderer)253     angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override
254     {
255         return this->resolveImpl(context, renderer, mByteCode, nullptr, mName);
256     }
257 
258   private:
259     ShaderData mByteCode;
260     const char *mName;
261 };
262 
263 class LazyInputLayout final : public LazyResource<ResourceType::InputLayout>
264 {
265   public:
266     LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc,
267                     size_t inputDescLen,
268                     const BYTE *byteCode,
269                     size_t byteCodeLen,
270                     const char *debugName);
271     ~LazyInputLayout() override;
272 
273     angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override;
274 
275   private:
276     InputElementArray mInputDesc;
277     ShaderData mByteCode;
278     const char *mDebugName;
279 };
280 
281 class LazyBlendState final : public LazyResource<ResourceType::BlendState>
282 {
283   public:
284     LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName);
285 
286     angle::Result resolve(d3d::Context *context, Renderer11 *renderer) override;
287 
288   private:
289     D3D11_BLEND_DESC mDesc;
290     const char *mDebugName;
291 };
292 
293 // Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to
294 // represent an entire buffer.
295 template <class T>
SetBufferData(ID3D11DeviceContext * context,ID3D11Buffer * constantBuffer,const T & value)296 void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value)
297 {
298     D3D11_MAPPED_SUBRESOURCE mappedResource = {};
299     HRESULT result = context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
300     ASSERT(SUCCEEDED(result));
301     if (SUCCEEDED(result))
302     {
303         memcpy(mappedResource.pData, &value, sizeof(T));
304         context->Unmap(constantBuffer, 0);
305     }
306 }
307 
308 void InitializeFeatures(const Renderer11DeviceCaps &deviceCaps,
309                         const DXGI_ADAPTER_DESC &adapterDesc,
310                         angle::FeaturesD3D *features);
311 
312 void InitializeFrontendFeatures(const DXGI_ADAPTER_DESC &adapterDesc,
313                                 angle::FrontendFeatures *features);
314 
315 enum ReservedConstantBufferSlot
316 {
317     RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK = 0,
318     RESERVED_CONSTANT_BUFFER_SLOT_DRIVER                = 1,
319 
320     RESERVED_CONSTANT_BUFFER_SLOT_COUNT = 2
321 };
322 
323 void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth);
324 
325 // Helper class for RAII patterning.
326 template <typename T>
327 class [[nodiscard]] ScopedUnmapper final : angle::NonCopyable
328 {
329   public:
ScopedUnmapper(T * object)330     ScopedUnmapper(T *object) : mObject(object) {}
~ScopedUnmapper()331     ~ScopedUnmapper() { mObject->unmap(); }
332 
333   private:
334     T *mObject;
335 };
336 }  // namespace d3d11
337 
338 struct GenericData
339 {
GenericDataGenericData340     GenericData() {}
~GenericDataGenericData341     ~GenericData()
342     {
343         if (object)
344         {
345             // We can have a nullptr factory when holding passed-in resources.
346             if (manager)
347             {
348                 manager->onReleaseGeneric(resourceType, object);
349                 manager = nullptr;
350             }
351             object->Release();
352             object = nullptr;
353         }
354     }
355 
356     ResourceType resourceType  = ResourceType::Last;
357     ID3D11Resource *object     = nullptr;
358     ResourceManager11 *manager = nullptr;
359 };
360 
361 // A helper class which wraps a 2D or 3D texture.
362 class TextureHelper11 : public Resource11Base<ID3D11Resource, std::shared_ptr, GenericData>
363 {
364   public:
365     TextureHelper11();
366     TextureHelper11(TextureHelper11 &&other);
367     TextureHelper11(const TextureHelper11 &other);
368     ~TextureHelper11() override;
369     TextureHelper11 &operator=(TextureHelper11 &&other);
370     TextureHelper11 &operator=(const TextureHelper11 &other);
371 
isBuffer()372     bool isBuffer() const { return mData->resourceType == ResourceType::Buffer; }
is2D()373     bool is2D() const { return mData->resourceType == ResourceType::Texture2D; }
is3D()374     bool is3D() const { return mData->resourceType == ResourceType::Texture3D; }
getTextureType()375     ResourceType getTextureType() const { return mData->resourceType; }
getExtents()376     gl::Extents getExtents() const { return mExtents; }
getFormat()377     DXGI_FORMAT getFormat() const { return mFormatSet->texFormat; }
getFormatSet()378     const d3d11::Format &getFormatSet() const { return *mFormatSet; }
getSampleCount()379     int getSampleCount() const { return mSampleCount; }
380 
381     template <typename DescT, typename ResourceT>
init(Resource11<ResourceT> && texture,const DescT & desc,const d3d11::Format & format)382     void init(Resource11<ResourceT> &&texture, const DescT &desc, const d3d11::Format &format)
383     {
384         std::swap(mData->manager, texture.mData->manager);
385 
386         // Can't use std::swap because texture is typed, and here we use ID3D11Resource.
387         ID3D11Resource *temp  = mData->object;
388         mData->object         = texture.mData->object;
389         texture.mData->object = static_cast<ResourceT *>(temp);
390 
391         mFormatSet = &format;
392         initDesc(desc);
393     }
394 
395     template <typename ResourceT>
set(ResourceT * object,const d3d11::Format & format)396     void set(ResourceT *object, const d3d11::Format &format)
397     {
398         ASSERT(!valid());
399 
400         mFormatSet     = &format;
401         mData->object  = object;
402         mData->manager = nullptr;
403 
404         GetDescFromD3D11<ResourceT> desc;
405         getDesc(&desc);
406         initDesc(desc);
407     }
408 
409     bool operator==(const TextureHelper11 &other) const;
410     bool operator!=(const TextureHelper11 &other) const;
411 
412     void getDesc(D3D11_TEXTURE2D_DESC *desc) const;
413     void getDesc(D3D11_TEXTURE3D_DESC *desc) const;
414     void getDesc(D3D11_BUFFER_DESC *desc) const;
415 
416   private:
417     void initDesc(const D3D11_TEXTURE2D_DESC &desc2D);
418     void initDesc(const D3D11_TEXTURE3D_DESC &desc3D);
419     void initDesc(const D3D11_BUFFER_DESC &descBuffer);
420 
421     const d3d11::Format *mFormatSet;
422     gl::Extents mExtents;
423     int mSampleCount;
424 };
425 
426 enum class StagingAccess
427 {
428     READ,
429     READ_WRITE,
430 };
431 
432 bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer);
433 bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled,
434                                    gl::DrawElementsType type);
435 
436 enum class IndexStorageType
437 {
438     // Dynamic indexes are re-streamed every frame. They come from a client data pointer or
439     // from buffers that are updated frequently.
440     Dynamic,
441 
442     // Static indexes are translated from the original storage once, and re-used multiple times.
443     Static,
444 
445     // Direct indexes are never transated and are used directly from the source buffer. They are
446     // the fastest available path.
447     Direct,
448 
449     // Not a real storage type.
450     Invalid,
451 };
452 
453 IndexStorageType ClassifyIndexStorage(const gl::State &glState,
454                                       const gl::Buffer *elementArrayBuffer,
455                                       gl::DrawElementsType elementType,
456                                       gl::DrawElementsType destElementType,
457                                       unsigned int offset);
458 
459 bool SwizzleRequired(const gl::TextureState &textureState);
460 gl::SwizzleState GetEffectiveSwizzle(const gl::TextureState &textureState);
461 
462 }  // namespace rx
463 
464 #endif  // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
465