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