1 2 // Copyright 2014 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 // RendererD3D.h: Defines a back-end specific class for the DirectX renderer. 8 9 #ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ 10 #define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ 11 12 #include <array> 13 14 #include "common/Color.h" 15 #include "common/MemoryBuffer.h" 16 #include "common/debug.h" 17 #include "libANGLE/Device.h" 18 #include "libANGLE/State.h" 19 #include "libANGLE/Version.h" 20 #include "libANGLE/angletypes.h" 21 #include "libANGLE/formatutils.h" 22 #include "libANGLE/renderer/d3d/ShaderD3D.h" 23 #include "libANGLE/renderer/d3d/VertexDataManager.h" 24 #include "libANGLE/renderer/d3d/formatutilsD3D.h" 25 #include "libANGLE/renderer/renderer_utils.h" 26 #include "libANGLE/renderer/serial_utils.h" 27 #include "platform/autogen/FeaturesD3D_autogen.h" 28 29 namespace egl 30 { 31 class ConfigSet; 32 } 33 34 namespace gl 35 { 36 class ErrorSet; 37 class FramebufferState; 38 class InfoLog; 39 class Texture; 40 struct LinkedVarying; 41 } // namespace gl 42 43 namespace rx 44 { 45 class ContextImpl; 46 struct D3DUniform; 47 struct D3DVarying; 48 class DeviceD3D; 49 class EGLImageD3D; 50 class FramebufferImpl; 51 class ImageD3D; 52 class IndexBuffer; 53 class NativeWindowD3D; 54 class ProgramD3D; 55 class RenderTargetD3D; 56 class ShaderExecutableD3D; 57 class SwapChainD3D; 58 class TextureStorage; 59 struct TranslatedIndexData; 60 class UniformStorageD3D; 61 class VertexBuffer; 62 63 struct DeviceIdentifier 64 { 65 UINT VendorId; 66 UINT DeviceId; 67 UINT SubSysId; 68 UINT Revision; 69 UINT FeatureLevel; 70 }; 71 72 enum RendererClass 73 { 74 RENDERER_D3D11, 75 RENDERER_D3D9 76 }; 77 78 struct BindFlags 79 { 80 bool renderTarget = false; 81 bool unorderedAccess = false; RenderTargetBindFlags82 static BindFlags RenderTarget() 83 { 84 BindFlags flags; 85 flags.renderTarget = true; 86 return flags; 87 } UnorderedAccessBindFlags88 static BindFlags UnorderedAccess() 89 { 90 BindFlags flags; 91 flags.unorderedAccess = true; 92 return flags; 93 } 94 }; 95 96 // A d3d::Context wraps error handling. 97 namespace d3d 98 { 99 class Context : angle::NonCopyable 100 { 101 public: Context()102 Context() {} ~Context()103 virtual ~Context() {} 104 105 virtual void handleResult(HRESULT hr, 106 const char *message, 107 const char *file, 108 const char *function, 109 unsigned int line) = 0; 110 }; 111 } // namespace d3d 112 113 // ANGLE_TRY for HRESULT errors. 114 #define ANGLE_TRY_HR(CONTEXT, EXPR, MESSAGE) \ 115 do \ 116 { \ 117 auto ANGLE_LOCAL_VAR = (EXPR); \ 118 if (ANGLE_UNLIKELY(FAILED(ANGLE_LOCAL_VAR))) \ 119 { \ 120 CONTEXT->handleResult(ANGLE_LOCAL_VAR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \ 121 return angle::Result::Stop; \ 122 } \ 123 } while (0) 124 125 #define ANGLE_CHECK_HR(CONTEXT, EXPR, MESSAGE, ERROR) \ 126 do \ 127 { \ 128 if (ANGLE_UNLIKELY(!(EXPR))) \ 129 { \ 130 CONTEXT->handleResult(ERROR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \ 131 return angle::Result::Stop; \ 132 } \ 133 } while (0) 134 135 #define ANGLE_HR_UNREACHABLE(context) \ 136 UNREACHABLE(); \ 137 ANGLE_CHECK_HR(context, false, "Unreachble code reached.", E_FAIL) 138 139 // Check if the device is lost every 10 failures to get the query data 140 constexpr unsigned int kPollingD3DDeviceLostCheckFrequency = 10; 141 142 // Useful for unit testing 143 class BufferFactoryD3D : angle::NonCopyable 144 { 145 public: BufferFactoryD3D()146 BufferFactoryD3D() {} ~BufferFactoryD3D()147 virtual ~BufferFactoryD3D() {} 148 149 virtual VertexBuffer *createVertexBuffer() = 0; 150 virtual IndexBuffer *createIndexBuffer() = 0; 151 152 // TODO(jmadill): add VertexFormatCaps 153 virtual VertexConversionType getVertexConversionType(angle::FormatID vertexFormatID) const = 0; 154 virtual GLenum getVertexComponentType(angle::FormatID vertexFormatID) const = 0; 155 156 // Warning: you should ensure binding really matches attrib.bindingIndex before using this 157 // function. 158 virtual angle::Result getVertexSpaceRequired(const gl::Context *context, 159 const gl::VertexAttribute &attrib, 160 const gl::VertexBinding &binding, 161 size_t count, 162 GLsizei instances, 163 GLuint baseInstance, 164 unsigned int *bytesRequiredOut) const = 0; 165 }; 166 167 using AttribIndexArray = gl::AttribArray<int>; 168 169 class RendererD3D : public BufferFactoryD3D 170 { 171 public: 172 explicit RendererD3D(egl::Display *display); 173 ~RendererD3D() override; 174 175 virtual egl::Error initialize() = 0; 176 177 virtual egl::ConfigSet generateConfigs() = 0; 178 virtual void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const = 0; 179 180 virtual ContextImpl *createContext(const gl::State &state, gl::ErrorSet *errorSet) = 0; 181 182 virtual std::string getRendererDescription() const = 0; 183 virtual std::string getVendorString() const = 0; 184 virtual std::string getVersionString(bool includeFullVersion) const = 0; 185 186 virtual int getMinorShaderModel() const = 0; 187 virtual std::string getShaderModelSuffix() const = 0; 188 189 // Direct3D Specific methods 190 virtual DeviceIdentifier getAdapterIdentifier() const = 0; 191 192 virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0; 193 virtual NativeWindowD3D *createNativeWindow(EGLNativeWindowType window, 194 const egl::Config *config, 195 const egl::AttributeMap &attribs) const = 0; 196 197 virtual SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow, 198 HANDLE shareHandle, 199 IUnknown *d3dTexture, 200 GLenum backBufferFormat, 201 GLenum depthBufferFormat, 202 EGLint orientation, 203 EGLint samples) = 0; 204 virtual egl::Error getD3DTextureInfo(const egl::Config *configuration, 205 IUnknown *d3dTexture, 206 const egl::AttributeMap &attribs, 207 EGLint *width, 208 EGLint *height, 209 GLsizei *samples, 210 gl::Format *glFormat, 211 const angle::Format **angleFormat, 212 UINT *arraySlice) const = 0; 213 virtual egl::Error validateShareHandle(const egl::Config *config, 214 HANDLE shareHandle, 215 const egl::AttributeMap &attribs) const = 0; 216 217 virtual int getMajorShaderModel() const = 0; 218 219 virtual void setGlobalDebugAnnotator() = 0; 220 221 const angle::FeaturesD3D &getFeatures() const; 222 223 // Pixel operations 224 virtual angle::Result copyImage2D(const gl::Context *context, 225 const gl::Framebuffer *framebuffer, 226 const gl::Rectangle &sourceRect, 227 GLenum destFormat, 228 const gl::Offset &destOffset, 229 TextureStorage *storage, 230 GLint level) = 0; 231 virtual angle::Result copyImageCube(const gl::Context *context, 232 const gl::Framebuffer *framebuffer, 233 const gl::Rectangle &sourceRect, 234 GLenum destFormat, 235 const gl::Offset &destOffset, 236 TextureStorage *storage, 237 gl::TextureTarget target, 238 GLint level) = 0; 239 virtual angle::Result copyImage3D(const gl::Context *context, 240 const gl::Framebuffer *framebuffer, 241 const gl::Rectangle &sourceRect, 242 GLenum destFormat, 243 const gl::Offset &destOffset, 244 TextureStorage *storage, 245 GLint level) = 0; 246 virtual angle::Result copyImage2DArray(const gl::Context *context, 247 const gl::Framebuffer *framebuffer, 248 const gl::Rectangle &sourceRect, 249 GLenum destFormat, 250 const gl::Offset &destOffset, 251 TextureStorage *storage, 252 GLint level) = 0; 253 254 virtual angle::Result copyTexture(const gl::Context *context, 255 const gl::Texture *source, 256 GLint sourceLevel, 257 gl::TextureTarget srcTarget, 258 const gl::Box &sourceBox, 259 GLenum destFormat, 260 GLenum destType, 261 const gl::Offset &destOffset, 262 TextureStorage *storage, 263 gl::TextureTarget destTarget, 264 GLint destLevel, 265 bool unpackFlipY, 266 bool unpackPremultiplyAlpha, 267 bool unpackUnmultiplyAlpha) = 0; 268 virtual angle::Result copyCompressedTexture(const gl::Context *context, 269 const gl::Texture *source, 270 GLint sourceLevel, 271 TextureStorage *storage, 272 GLint destLevel) = 0; 273 274 // RenderTarget creation 275 virtual angle::Result createRenderTarget(const gl::Context *context, 276 int width, 277 int height, 278 GLenum format, 279 GLsizei samples, 280 RenderTargetD3D **outRT) = 0; 281 virtual angle::Result createRenderTargetCopy(const gl::Context *context, 282 RenderTargetD3D *source, 283 RenderTargetD3D **outRT) = 0; 284 285 // Shader operations 286 virtual angle::Result loadExecutable(d3d::Context *context, 287 const uint8_t *function, 288 size_t length, 289 gl::ShaderType type, 290 const std::vector<D3DVarying> &streamOutVaryings, 291 bool separatedOutputBuffers, 292 ShaderExecutableD3D **outExecutable) = 0; 293 virtual angle::Result compileToExecutable(d3d::Context *context, 294 gl::InfoLog &infoLog, 295 const std::string &shaderHLSL, 296 gl::ShaderType type, 297 const std::vector<D3DVarying> &streamOutVaryings, 298 bool separatedOutputBuffers, 299 const CompilerWorkaroundsD3D &workarounds, 300 ShaderExecutableD3D **outExectuable) = 0; 301 virtual angle::Result ensureHLSLCompilerInitialized(d3d::Context *context) = 0; 302 303 virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0; 304 305 // Image operations 306 virtual ImageD3D *createImage() = 0; 307 virtual ExternalImageSiblingImpl *createExternalImageSibling( 308 const gl::Context *context, 309 EGLenum target, 310 EGLClientBuffer buffer, 311 const egl::AttributeMap &attribs) = 0; 312 virtual angle::Result generateMipmap(const gl::Context *context, 313 ImageD3D *dest, 314 ImageD3D *source) = 0; 315 virtual angle::Result generateMipmapUsingD3D(const gl::Context *context, 316 TextureStorage *storage, 317 const gl::TextureState &textureState) = 0; 318 virtual angle::Result copyImage(const gl::Context *context, 319 ImageD3D *dest, 320 ImageD3D *source, 321 const gl::Box &sourceBox, 322 const gl::Offset &destOffset, 323 bool unpackFlipY, 324 bool unpackPremultiplyAlpha, 325 bool unpackUnmultiplyAlpha) = 0; 326 virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain, 327 const std::string &label) = 0; 328 virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage, 329 RenderTargetD3D *renderTargetD3D, 330 const std::string &label) = 0; 331 virtual TextureStorage *createTextureStorageBuffer( 332 const gl::OffsetBindingPointer<gl::Buffer> &buffer, 333 GLenum internalFormat, 334 const std::string &label) = 0; 335 virtual TextureStorage *createTextureStorageExternal( 336 egl::Stream *stream, 337 const egl::Stream::GLTextureDescription &desc, 338 const std::string &label) = 0; 339 virtual TextureStorage *createTextureStorage2D(GLenum internalformat, 340 BindFlags bindFlags, 341 GLsizei width, 342 GLsizei height, 343 int levels, 344 const std::string &label, 345 bool hintLevelZeroOnly) = 0; 346 virtual TextureStorage *createTextureStorageCube(GLenum internalformat, 347 BindFlags bindFlags, 348 int size, 349 int levels, 350 bool hintLevelZeroOnly, 351 const std::string &label) = 0; 352 virtual TextureStorage *createTextureStorage3D(GLenum internalformat, 353 BindFlags bindFlags, 354 GLsizei width, 355 GLsizei height, 356 GLsizei depth, 357 int levels, 358 const std::string &label) = 0; 359 virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, 360 BindFlags bindFlags, 361 GLsizei width, 362 GLsizei height, 363 GLsizei depth, 364 int levels, 365 const std::string &label) = 0; 366 virtual TextureStorage *createTextureStorage2DMultisample(GLenum internalformat, 367 GLsizei width, 368 GLsizei height, 369 int levels, 370 int samples, 371 bool fixedSampleLocations, 372 const std::string &label) = 0; 373 virtual TextureStorage *createTextureStorage2DMultisampleArray(GLenum internalformat, 374 GLsizei width, 375 GLsizei height, 376 GLsizei depth, 377 int levels, 378 int samples, 379 bool fixedSampleLocations, 380 const std::string &label) = 0; 381 382 // Buffer-to-texture and Texture-to-buffer copies 383 virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; 384 virtual angle::Result fastCopyBufferToTexture(const gl::Context *context, 385 const gl::PixelUnpackState &unpack, 386 gl::Buffer *unpackBuffer, 387 unsigned int offset, 388 RenderTargetD3D *destRenderTarget, 389 GLenum destinationFormat, 390 GLenum sourcePixelsType, 391 const gl::Box &destArea) = 0; 392 393 // Device lost 394 gl::GraphicsResetStatus getResetStatus(); 395 void notifyDeviceLost(); 396 virtual bool resetDevice() = 0; 397 virtual bool testDeviceLost() = 0; 398 virtual bool testDeviceResettable() = 0; 399 400 virtual RendererClass getRendererClass() const = 0; 401 virtual void *getD3DDevice() = 0; 402 403 GLint64 getTimestamp(); 404 405 virtual angle::Result clearRenderTarget(const gl::Context *context, 406 RenderTargetD3D *renderTarget, 407 const gl::ColorF &clearColorValue, 408 const float clearDepthValue, 409 const unsigned int clearStencilValue) = 0; 410 411 virtual DeviceImpl *createEGLDevice() = 0; 412 presentPathFastEnabled()413 bool presentPathFastEnabled() const { return mPresentPathFastEnabled; } 414 415 // Stream creation 416 virtual StreamProducerImpl *createStreamProducerD3DTexture( 417 egl::Stream::ConsumerType consumerType, 418 const egl::AttributeMap &attribs) = 0; 419 420 const gl::Caps &getNativeCaps() const; 421 const gl::TextureCapsMap &getNativeTextureCaps() const; 422 const gl::Extensions &getNativeExtensions() const; 423 const gl::Limitations &getNativeLimitations() const; 424 const ShPixelLocalStorageOptions &getNativePixelLocalStorageOptions() const; 425 virtual void initializeFrontendFeatures(angle::FrontendFeatures *features) const = 0; 426 427 // Necessary hack for default framebuffers in D3D. 428 virtual FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) = 0; 429 430 virtual gl::Version getMaxSupportedESVersion() const = 0; 431 virtual gl::Version getMaxConformantESVersion() const = 0; 432 433 angle::Result initRenderTarget(const gl::Context *context, RenderTargetD3D *renderTarget); 434 435 virtual angle::Result getIncompleteTexture(const gl::Context *context, 436 gl::TextureType type, 437 gl::Texture **textureOut) = 0; 438 439 UniqueSerial generateSerial(); 440 441 virtual bool canSelectViewInVertexShader() const = 0; 442 getDisplay()443 egl::Display *getDisplay() const { return mDisplay; } 444 445 protected: 446 virtual bool getLUID(LUID *adapterLuid) const = 0; 447 virtual void generateCaps(gl::Caps *outCaps, 448 gl::TextureCapsMap *outTextureCaps, 449 gl::Extensions *outExtensions, 450 gl::Limitations *outLimitations, 451 ShPixelLocalStorageOptions *outPLSOptions) const = 0; 452 453 bool skipDraw(const gl::State &glState, gl::PrimitiveMode drawMode); 454 455 egl::Display *mDisplay; 456 457 bool mPresentPathFastEnabled; 458 459 private: 460 void ensureCapsInitialized() const; 461 462 virtual void initializeFeatures(angle::FeaturesD3D *features) const = 0; 463 464 mutable bool mCapsInitialized; 465 mutable gl::Caps mNativeCaps; 466 mutable gl::TextureCapsMap mNativeTextureCaps; 467 mutable gl::Extensions mNativeExtensions; 468 mutable gl::Limitations mNativeLimitations; 469 mutable ShPixelLocalStorageOptions mNativePLSOptions; 470 471 mutable bool mFeaturesInitialized; 472 mutable angle::FeaturesD3D mFeatures; 473 474 bool mDeviceLost; 475 476 UniqueSerialFactory mSerialFactory; 477 }; 478 479 unsigned int GetBlendSampleMask(const gl::State &glState, int samples); 480 bool InstancedPointSpritesActive(ProgramD3D *programD3D, gl::PrimitiveMode mode); 481 GLenum DefaultGLErrorCode(HRESULT hr); 482 483 // Define stubs so we don't need to include D3D9/D3D11 headers directly. 484 RendererD3D *CreateRenderer11(egl::Display *display); 485 RendererD3D *CreateRenderer9(egl::Display *display); 486 487 } // namespace rx 488 489 #endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ 490