From e12ba07322cd61c5cf50c25ed8d1f08f6b1ff879 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 24 Mar 2016 12:38:18 +0100 Subject: Update ANGLE to chromium/2651 Change-Id: I1cd32b780b1a0b913fab870e155ae1f4f9ac40d7 Reviewed-by: Maurice Kalinowski --- src/3rdparty/angle/src/libANGLE/AttributeMap.h | 8 +- src/3rdparty/angle/src/libANGLE/BinaryStream.h | 16 +- src/3rdparty/angle/src/libANGLE/Buffer.cpp | 91 +- src/3rdparty/angle/src/libANGLE/Buffer.h | 37 +- src/3rdparty/angle/src/libANGLE/Caps.cpp | 314 +- src/3rdparty/angle/src/libANGLE/Caps.h | 173 +- src/3rdparty/angle/src/libANGLE/Compiler.cpp | 114 +- src/3rdparty/angle/src/libANGLE/Compiler.h | 20 +- src/3rdparty/angle/src/libANGLE/Config.cpp | 8 +- src/3rdparty/angle/src/libANGLE/Config.h | 1 + src/3rdparty/angle/src/libANGLE/Context.cpp | 1333 +++++++-- src/3rdparty/angle/src/libANGLE/Context.h | 176 +- src/3rdparty/angle/src/libANGLE/Data.cpp | 55 +- src/3rdparty/angle/src/libANGLE/Data.h | 48 +- src/3rdparty/angle/src/libANGLE/Debug.cpp | 303 ++ src/3rdparty/angle/src/libANGLE/Debug.h | 120 + src/3rdparty/angle/src/libANGLE/Debug2.cpp | 303 ++ src/3rdparty/angle/src/libANGLE/Debug2.h | 120 + src/3rdparty/angle/src/libANGLE/Device.cpp | 130 + src/3rdparty/angle/src/libANGLE/Device.h | 58 + src/3rdparty/angle/src/libANGLE/Display.cpp | 426 ++- src/3rdparty/angle/src/libANGLE/Display.h | 28 +- src/3rdparty/angle/src/libANGLE/Error.cpp | 48 +- src/3rdparty/angle/src/libANGLE/Error.h | 37 +- src/3rdparty/angle/src/libANGLE/Error.inl | 66 +- src/3rdparty/angle/src/libANGLE/Fence.cpp | 46 +- src/3rdparty/angle/src/libANGLE/Fence.h | 22 +- .../angle/src/libANGLE/Float16ToFloat32.cpp | 2203 -------------- src/3rdparty/angle/src/libANGLE/Framebuffer.cpp | 619 ++-- src/3rdparty/angle/src/libANGLE/Framebuffer.h | 136 +- .../angle/src/libANGLE/FramebufferAttachment.cpp | 286 +- .../angle/src/libANGLE/FramebufferAttachment.h | 238 +- .../angle/src/libANGLE/HandleAllocator.cpp | 15 +- src/3rdparty/angle/src/libANGLE/HandleAllocator.h | 2 +- src/3rdparty/angle/src/libANGLE/Image.cpp | 192 ++ src/3rdparty/angle/src/libANGLE/Image.h | 91 + src/3rdparty/angle/src/libANGLE/ImageIndex.cpp | 23 +- src/3rdparty/angle/src/libANGLE/ImageIndex.h | 8 +- .../angle/src/libANGLE/IndexRangeCache.cpp | 113 + src/3rdparty/angle/src/libANGLE/IndexRangeCache.h | 60 + src/3rdparty/angle/src/libANGLE/Platform.cpp | 6 +- src/3rdparty/angle/src/libANGLE/Program.cpp | 1840 +++++++++--- src/3rdparty/angle/src/libANGLE/Program.h | 336 ++- src/3rdparty/angle/src/libANGLE/Query.cpp | 45 +- src/3rdparty/angle/src/libANGLE/Query.h | 18 +- src/3rdparty/angle/src/libANGLE/RefCountObject.h | 41 +- src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp | 78 +- src/3rdparty/angle/src/libANGLE/Renderbuffer.h | 37 +- .../angle/src/libANGLE/ResourceManager.cpp | 8 +- src/3rdparty/angle/src/libANGLE/ResourceManager.h | 11 +- src/3rdparty/angle/src/libANGLE/Sampler.cpp | 151 +- src/3rdparty/angle/src/libANGLE/Sampler.h | 88 +- src/3rdparty/angle/src/libANGLE/Shader.cpp | 279 +- src/3rdparty/angle/src/libANGLE/Shader.h | 102 +- src/3rdparty/angle/src/libANGLE/State.cpp | 655 ++++- src/3rdparty/angle/src/libANGLE/State.h | 175 +- src/3rdparty/angle/src/libANGLE/Surface.cpp | 137 +- src/3rdparty/angle/src/libANGLE/Surface.h | 49 +- src/3rdparty/angle/src/libANGLE/Texture.cpp | 502 +++- src/3rdparty/angle/src/libANGLE/Texture.h | 198 +- .../angle/src/libANGLE/TransformFeedback.cpp | 127 +- .../angle/src/libANGLE/TransformFeedback.h | 44 +- src/3rdparty/angle/src/libANGLE/Uniform.cpp | 136 +- src/3rdparty/angle/src/libANGLE/Uniform.h | 65 +- src/3rdparty/angle/src/libANGLE/Version.h | 33 + src/3rdparty/angle/src/libANGLE/Version.inl | 33 + src/3rdparty/angle/src/libANGLE/VertexArray.cpp | 115 +- src/3rdparty/angle/src/libANGLE/VertexArray.h | 83 +- .../angle/src/libANGLE/VertexAttribute.cpp | 37 +- src/3rdparty/angle/src/libANGLE/VertexAttribute.h | 73 +- .../angle/src/libANGLE/VertexAttribute.inl | 103 + src/3rdparty/angle/src/libANGLE/angletypes.cpp | 187 +- src/3rdparty/angle/src/libANGLE/angletypes.h | 181 +- src/3rdparty/angle/src/libANGLE/angletypes.inl | 78 + src/3rdparty/angle/src/libANGLE/features.h | 19 +- src/3rdparty/angle/src/libANGLE/formatutils.cpp | 978 +++++- src/3rdparty/angle/src/libANGLE/formatutils.h | 157 +- src/3rdparty/angle/src/libANGLE/histogram_macros.h | 107 + .../angle/src/libANGLE/queryconversions.cpp | 98 +- src/3rdparty/angle/src/libANGLE/queryconversions.h | 19 + .../angle/src/libANGLE/renderer/BufferImpl.h | 18 +- .../angle/src/libANGLE/renderer/BufferImpl_mock.h | 38 + .../angle/src/libANGLE/renderer/CompilerImpl.h | 4 + .../angle/src/libANGLE/renderer/DeviceImpl.cpp | 22 + .../angle/src/libANGLE/renderer/DeviceImpl.h | 37 + .../angle/src/libANGLE/renderer/DisplayImpl.cpp | 7 +- .../angle/src/libANGLE/renderer/DisplayImpl.h | 39 +- .../angle/src/libANGLE/renderer/FenceNVImpl.h | 6 +- .../angle/src/libANGLE/renderer/FenceSyncImpl.h | 2 +- .../angle/src/libANGLE/renderer/FramebufferImpl.h | 34 +- .../src/libANGLE/renderer/FramebufferImpl_mock.h | 72 + .../angle/src/libANGLE/renderer/ImageImpl.h | 32 + .../angle/src/libANGLE/renderer/ImageImpl_mock.h | 28 + .../angle/src/libANGLE/renderer/ImplFactory.h | 16 +- .../src/libANGLE/renderer/IndexRangeCache.cpp | 114 - .../angle/src/libANGLE/renderer/IndexRangeCache.h | 53 - .../angle/src/libANGLE/renderer/ProgramImpl.h | 90 +- .../angle/src/libANGLE/renderer/ProgramImpl_mock.h | 75 + .../angle/src/libANGLE/renderer/QueryImpl.h | 6 +- .../angle/src/libANGLE/renderer/RenderbufferImpl.h | 15 +- .../src/libANGLE/renderer/RenderbufferImpl_mock.h | 35 + .../angle/src/libANGLE/renderer/Renderer.cpp | 36 +- .../angle/src/libANGLE/renderer/Renderer.h | 70 +- .../angle/src/libANGLE/renderer/SamplerImpl.h | 25 + .../angle/src/libANGLE/renderer/ShaderImpl.h | 35 +- .../angle/src/libANGLE/renderer/SurfaceImpl.h | 10 +- .../angle/src/libANGLE/renderer/TextureImpl.h | 27 +- .../angle/src/libANGLE/renderer/TextureImpl_mock.h | 43 + .../src/libANGLE/renderer/TransformFeedbackImpl.h | 3 + .../libANGLE/renderer/TransformFeedbackImpl_mock.h | 37 + .../angle/src/libANGLE/renderer/VertexArrayImpl.h | 11 +- .../angle/src/libANGLE/renderer/d3d/BufferD3D.cpp | 194 +- .../angle/src/libANGLE/renderer/d3d/BufferD3D.h | 43 +- .../src/libANGLE/renderer/d3d/CompilerD3D.cpp | 122 +- .../angle/src/libANGLE/renderer/d3d/CompilerD3D.h | 27 +- .../angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp | 102 + .../angle/src/libANGLE/renderer/d3d/DeviceD3D.h | 39 + .../angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp | 195 +- .../angle/src/libANGLE/renderer/d3d/DisplayD3D.h | 39 +- .../src/libANGLE/renderer/d3d/DynamicHLSL.cpp | 1554 +++++----- .../angle/src/libANGLE/renderer/d3d/DynamicHLSL.h | 89 +- .../src/libANGLE/renderer/d3d/EGLImageD3D.cpp | 132 + .../angle/src/libANGLE/renderer/d3d/EGLImageD3D.h | 56 + .../src/libANGLE/renderer/d3d/FramebufferD3D.cpp | 271 +- .../src/libANGLE/renderer/d3d/FramebufferD3D.h | 66 +- .../src/libANGLE/renderer/d3d/HLSLCompiler.cpp | 163 +- .../angle/src/libANGLE/renderer/d3d/HLSLCompiler.h | 8 +- .../angle/src/libANGLE/renderer/d3d/ImageD3D.cpp | 21 +- .../angle/src/libANGLE/renderer/d3d/ImageD3D.h | 12 +- .../angle/src/libANGLE/renderer/d3d/IndexBuffer.h | 1 - .../src/libANGLE/renderer/d3d/IndexDataManager.cpp | 373 ++- .../src/libANGLE/renderer/d3d/IndexDataManager.h | 29 +- .../angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp | 2365 ++++++++------- .../angle/src/libANGLE/renderer/d3d/ProgramD3D.h | 360 ++- .../src/libANGLE/renderer/d3d/RenderTargetD3D.h | 3 +- .../src/libANGLE/renderer/d3d/RenderbufferD3D.cpp | 54 +- .../src/libANGLE/renderer/d3d/RenderbufferD3D.h | 18 +- .../src/libANGLE/renderer/d3d/RendererD3D.cpp | 421 +-- .../angle/src/libANGLE/renderer/d3d/RendererD3D.h | 231 +- .../angle/src/libANGLE/renderer/d3d/SamplerD3D.h | 25 + .../angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp | 347 +-- .../angle/src/libANGLE/renderer/d3d/ShaderD3D.h | 50 +- .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 187 +- .../angle/src/libANGLE/renderer/d3d/SurfaceD3D.h | 35 +- .../angle/src/libANGLE/renderer/d3d/SwapChainD3D.h | 7 +- .../angle/src/libANGLE/renderer/d3d/TextureD3D.cpp | 458 ++- .../angle/src/libANGLE/renderer/d3d/TextureD3D.h | 59 +- .../src/libANGLE/renderer/d3d/TextureStorage.h | 15 +- .../libANGLE/renderer/d3d/TransformFeedbackD3D.cpp | 8 + .../libANGLE/renderer/d3d/TransformFeedbackD3D.h | 11 +- .../src/libANGLE/renderer/d3d/VaryingPacking.cpp | 397 +++ .../src/libANGLE/renderer/d3d/VaryingPacking.h | 175 ++ .../src/libANGLE/renderer/d3d/VertexBuffer.cpp | 71 +- .../angle/src/libANGLE/renderer/d3d/VertexBuffer.h | 36 +- .../libANGLE/renderer/d3d/VertexDataManager.cpp | 374 +-- .../src/libANGLE/renderer/d3d/VertexDataManager.h | 57 +- .../src/libANGLE/renderer/d3d/WorkaroundsD3D.h | 66 + .../src/libANGLE/renderer/d3d/d3d11/Blit11.cpp | 926 ++++-- .../angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h | 145 +- .../src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp | 875 ++++-- .../src/libANGLE/renderer/d3d/d3d11/Buffer11.h | 52 +- .../src/libANGLE/renderer/d3d/d3d11/Clear11.cpp | 229 +- .../src/libANGLE/renderer/d3d/d3d11/Clear11.h | 39 +- .../renderer/d3d/d3d11/DebugAnnotator11.cpp | 83 +- .../libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h | 4 +- .../src/libANGLE/renderer/d3d/d3d11/Fence11.cpp | 22 +- .../src/libANGLE/renderer/d3d/d3d11/Fence11.h | 18 +- .../libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp | 294 +- .../libANGLE/renderer/d3d/d3d11/Framebuffer11.h | 15 +- .../src/libANGLE/renderer/d3d/d3d11/Image11.cpp | 336 +-- .../src/libANGLE/renderer/d3d/d3d11/Image11.h | 17 +- .../libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp | 17 +- .../libANGLE/renderer/d3d/d3d11/IndexBuffer11.h | 2 - .../renderer/d3d/d3d11/InputLayoutCache.cpp | 693 +++-- .../libANGLE/renderer/d3d/d3d11/InputLayoutCache.h | 104 +- .../src/libANGLE/renderer/d3d/d3d11/NativeWindow.h | 17 +- .../renderer/d3d/d3d11/PixelTransfer11.cpp | 31 +- .../src/libANGLE/renderer/d3d/d3d11/Query11.cpp | 164 +- .../src/libANGLE/renderer/d3d/d3d11/Query11.h | 13 +- .../renderer/d3d/d3d11/RenderStateCache.cpp | 116 +- .../libANGLE/renderer/d3d/d3d11/RenderStateCache.h | 5 +- .../libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp | 14 +- .../libANGLE/renderer/d3d/d3d11/RenderTarget11.h | 5 - .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 3108 ++++++++++++-------- .../src/libANGLE/renderer/d3d/d3d11/Renderer11.h | 285 +- .../renderer/d3d/d3d11/ShaderExecutable11.cpp | 14 +- .../renderer/d3d/d3d11/ShaderExecutable11.h | 4 - .../libANGLE/renderer/d3d/d3d11/StateManager11.cpp | 1040 +++++++ .../libANGLE/renderer/d3d/d3d11/StateManager11.h | 181 ++ .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 446 ++- .../src/libANGLE/renderer/d3d/d3d11/SwapChain11.h | 35 +- .../renderer/d3d/d3d11/TextureStorage11.cpp | 724 ++++- .../libANGLE/renderer/d3d/d3d11/TextureStorage11.h | 74 +- .../angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h | 2 + .../libANGLE/renderer/d3d/d3d11/VertexArray11.h | 15 +- .../libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp | 69 +- .../libANGLE/renderer/d3d/d3d11/VertexBuffer11.h | 11 +- .../src/libANGLE/renderer/d3d/d3d11/copyvertex.inl | 6 +- .../renderer/d3d/d3d11/dxgi_support_data.json | 1164 ++++++++ .../renderer/d3d/d3d11/dxgi_support_table.cpp | 1846 ++++++++++++ .../renderer/d3d/d3d11/dxgi_support_table.h | 44 + .../libANGLE/renderer/d3d/d3d11/formatutils11.cpp | 1501 ++++------ .../libANGLE/renderer/d3d/d3d11/formatutils11.h | 44 +- .../d3d/d3d11/gen_load_functions_table.cpp | 0 .../d3d11/internal_format_initializer_table.cpp | 170 ++ .../d3d/d3d11/internal_format_initializer_table.h | 31 + .../renderer/d3d/d3d11/load_functions_data.json | 1116 +++++++ .../renderer/d3d/d3d11/load_functions_table.h | 31 + .../d3d/d3d11/load_functions_table_autogen.cpp | 2098 +++++++++++++ .../renderer/d3d/d3d11/renderer11_utils.cpp | 744 +++-- .../libANGLE/renderer/d3d/d3d11/renderer11_utils.h | 276 +- .../renderer/d3d/d3d11/swizzle_format_data.json | 77 + .../renderer/d3d/d3d11/swizzle_format_info.h | 51 + .../d3d/d3d11/swizzle_format_info_autogen.cpp | 203 ++ .../renderer/d3d/d3d11/texture_format_data.json | 692 +++++ .../renderer/d3d/d3d11/texture_format_table.h | 64 + .../d3d/d3d11/texture_format_table_autogen.cpp | 1791 +++++++++++ .../renderer/d3d/d3d11/win32/NativeWindow.cpp | 156 +- .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 75 +- .../d3d/d3d11/winrt/CoreWindowNativeWindow.h | 64 +- .../d3d/d3d11/winrt/InspectableNativeWindow.cpp | 160 +- .../d3d/d3d11/winrt/InspectableNativeWindow.h | 71 +- .../d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp | 232 +- .../d3d/d3d11/winrt/SwapChainPanelNativeWindow.h | 21 +- .../angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp | 24 +- .../src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp | 31 +- .../angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h | 10 +- .../libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp | 8 +- .../libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h | 4 +- .../src/libANGLE/renderer/d3d/d3d9/Fence9.cpp | 44 +- .../angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h | 10 +- .../libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp | 78 +- .../src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h | 16 +- .../src/libANGLE/renderer/d3d/d3d9/Image9.cpp | 89 +- .../angle/src/libANGLE/renderer/d3d/d3d9/Image9.h | 13 +- .../libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp | 6 - .../src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h | 2 - .../src/libANGLE/renderer/d3d/d3d9/Query9.cpp | 36 +- .../angle/src/libANGLE/renderer/d3d/d3d9/Query9.h | 11 +- .../libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp | 43 +- .../src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h | 26 +- .../src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp | 1067 +++---- .../src/libANGLE/renderer/d3d/d3d9/Renderer9.h | 203 +- .../renderer/d3d/d3d9/ShaderExecutable9.cpp | 6 - .../libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h | 2 - .../libANGLE/renderer/d3d/d3d9/StateManager9.cpp | 903 ++++++ .../src/libANGLE/renderer/d3d/d3d9/StateManager9.h | 206 ++ .../src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp | 43 +- .../src/libANGLE/renderer/d3d/d3d9/SwapChain9.h | 12 +- .../libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp | 272 +- .../libANGLE/renderer/d3d/d3d9/TextureStorage9.h | 44 +- .../src/libANGLE/renderer/d3d/d3d9/VertexArray9.h | 13 +- .../libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp | 58 +- .../src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h | 11 +- .../renderer/d3d/d3d9/VertexDeclarationCache.cpp | 56 +- .../renderer/d3d/d3d9/VertexDeclarationCache.h | 6 +- .../libANGLE/renderer/d3d/d3d9/formatutils9.cpp | 43 +- .../src/libANGLE/renderer/d3d/d3d9/formatutils9.h | 10 +- .../libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp | 108 +- .../libANGLE/renderer/d3d/d3d9/renderer9_utils.h | 24 +- .../libANGLE/renderer/d3d/d3d9/vertexconversion.h | 5 +- .../src/libANGLE/renderer/d3d/formatutilsD3D.cpp | 4 +- .../angle/src/libANGLE/renderer/d3d/imageformats.h | 168 +- .../angle/src/libANGLE/renderer/d3d/loadimage.cpp | 105 +- .../angle/src/libANGLE/renderer/d3d/loadimage.h | 8 + .../src/libANGLE/renderer/d3d/loadimage_etc.cpp | 1435 +++++++++ .../src/libANGLE/renderer/d3d/loadimage_etc.h | 140 + src/3rdparty/angle/src/libANGLE/validationEGL.cpp | 566 +++- src/3rdparty/angle/src/libANGLE/validationEGL.h | 20 + src/3rdparty/angle/src/libANGLE/validationES.cpp | 1381 +++++++-- src/3rdparty/angle/src/libANGLE/validationES.h | 202 +- src/3rdparty/angle/src/libANGLE/validationES2.cpp | 922 +++++- src/3rdparty/angle/src/libANGLE/validationES2.h | 108 +- src/3rdparty/angle/src/libANGLE/validationES3.cpp | 718 ++++- src/3rdparty/angle/src/libANGLE/validationES3.h | 226 +- 275 files changed, 43237 insertions(+), 15203 deletions(-) create mode 100644 src/3rdparty/angle/src/libANGLE/Debug.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Debug.h create mode 100644 src/3rdparty/angle/src/libANGLE/Debug2.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Debug2.h create mode 100644 src/3rdparty/angle/src/libANGLE/Device.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Device.h delete mode 100644 src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Image.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/Image.h create mode 100644 src/3rdparty/angle/src/libANGLE/IndexRangeCache.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/IndexRangeCache.h create mode 100644 src/3rdparty/angle/src/libANGLE/Version.h create mode 100644 src/3rdparty/angle/src/libANGLE/Version.inl create mode 100644 src/3rdparty/angle/src/libANGLE/VertexAttribute.inl create mode 100644 src/3rdparty/angle/src/libANGLE/angletypes.inl create mode 100644 src/3rdparty/angle/src/libANGLE/histogram_macros.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/BufferImpl_mock.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/DeviceImpl.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/DeviceImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl_mock.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/ImageImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/ImageImpl_mock.h delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl_mock.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/SamplerImpl.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/TextureImpl_mock.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h (limited to 'src/3rdparty/angle/src/libANGLE') diff --git a/src/3rdparty/angle/src/libANGLE/AttributeMap.h b/src/3rdparty/angle/src/libANGLE/AttributeMap.h index 72b6edc3c7..56f1684415 100644 --- a/src/3rdparty/angle/src/libANGLE/AttributeMap.h +++ b/src/3rdparty/angle/src/libANGLE/AttributeMap.h @@ -15,15 +15,15 @@ namespace egl { -class AttributeMap +class AttributeMap final { public: AttributeMap(); explicit AttributeMap(const EGLint *attributes); - virtual void insert(EGLint key, EGLint value); - virtual bool contains(EGLint key) const; - virtual EGLint get(EGLint key, EGLint defaultValue) const; + void insert(EGLint key, EGLint value); + bool contains(EGLint key) const; + EGLint get(EGLint key, EGLint defaultValue) const; typedef std::map::const_iterator const_iterator; diff --git a/src/3rdparty/angle/src/libANGLE/BinaryStream.h b/src/3rdparty/angle/src/libANGLE/BinaryStream.h index 50392e1d3f..3e6ccc7446 100644 --- a/src/3rdparty/angle/src/libANGLE/BinaryStream.h +++ b/src/3rdparty/angle/src/libANGLE/BinaryStream.h @@ -47,7 +47,7 @@ class BinaryInputStream : angle::NonCopyable template IntT readInt() { - int value; + int value = 0; read(&value); return static_cast(value); } @@ -60,7 +60,7 @@ class BinaryInputStream : angle::NonCopyable bool readBool() { - int value; + int value = 0; read(&value); return (value > 0); } @@ -92,7 +92,7 @@ class BinaryInputStream : angle::NonCopyable return; } - if (mOffset + length > mLength) + if (!rx::IsUnsignedAdditionSafe(mOffset, length) || mOffset + length > mLength) { mError = true; return; @@ -104,7 +104,7 @@ class BinaryInputStream : angle::NonCopyable void skip(size_t length) { - if (mOffset + length > mLength) + if (!rx::IsUnsignedAdditionSafe(mOffset, length) || mOffset + length > mLength) { mError = true; return; @@ -144,9 +144,15 @@ class BinaryInputStream : angle::NonCopyable { StaticAssertIsFundamental(); + if (!rx::IsUnsignedMultiplicationSafe(num, sizeof(T))) + { + mError = true; + return; + } + size_t length = num * sizeof(T); - if (mOffset + length > mLength) + if (!rx::IsUnsignedAdditionSafe(mOffset, length) || mOffset + length > mLength) { mError = true; return; diff --git a/src/3rdparty/angle/src/libANGLE/Buffer.cpp b/src/3rdparty/angle/src/libANGLE/Buffer.cpp index f394a6b1d1..589735c5a8 100644 --- a/src/3rdparty/angle/src/libANGLE/Buffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/Buffer.cpp @@ -18,9 +18,11 @@ namespace gl Buffer::Buffer(rx::BufferImpl *impl, GLuint id) : RefCountObject(id), mBuffer(impl), - mUsage(GL_DYNAMIC_DRAW), + mLabel(), + mUsage(GL_STATIC_DRAW), mSize(0), mAccessFlags(0), + mAccess(GL_WRITE_ONLY_OES), mMapped(GL_FALSE), mMapPointer(NULL), mMapOffset(0), @@ -33,6 +35,16 @@ Buffer::~Buffer() SafeDelete(mBuffer); } +void Buffer::setLabel(const std::string &label) +{ + mLabel = label; +} + +const std::string &Buffer::getLabel() const +{ + return mLabel; +} + Error Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) { gl::Error error = mBuffer->setData(data, size, usage); @@ -56,7 +68,7 @@ Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) return error; } - mIndexRangeCache.invalidateRange(offset, size); + mIndexRangeCache.invalidateRange(static_cast(offset), static_cast(size)); return error; } @@ -69,7 +81,30 @@ Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr return error; } - mIndexRangeCache.invalidateRange(destOffset, size); + mIndexRangeCache.invalidateRange(static_cast(destOffset), static_cast(size)); + + return error; +} + +Error Buffer::map(GLenum access) +{ + ASSERT(!mMapped); + + Error error = mBuffer->map(access, &mMapPointer); + if (error.isError()) + { + mMapPointer = NULL; + return error; + } + + ASSERT(access == GL_WRITE_ONLY_OES); + + mMapped = GL_TRUE; + mMapOffset = 0; + mMapLength = mSize; + mAccess = access; + mAccessFlags = GL_MAP_WRITE_BIT; + mIndexRangeCache.clear(); return error; } @@ -79,7 +114,7 @@ Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) ASSERT(!mMapped); ASSERT(offset + length <= mSize); - Error error = mBuffer->map(offset, length, access, &mMapPointer); + Error error = mBuffer->mapRange(offset, length, access, &mMapPointer); if (error.isError()) { mMapPointer = NULL; @@ -89,23 +124,30 @@ Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) mMapped = GL_TRUE; mMapOffset = static_cast(offset); mMapLength = static_cast(length); - mAccessFlags = static_cast(access); + mAccess = GL_WRITE_ONLY_OES; + mAccessFlags = access; + + // The OES_mapbuffer extension states that GL_WRITE_ONLY_OES is the only valid + // value for GL_BUFFER_ACCESS_OES because it was written against ES2. Since there is + // no update for ES3 and the GL_READ_ONLY and GL_READ_WRITE enums don't exist for ES, + // we cannot properly set GL_BUFFER_ACCESS_OES when glMapBufferRange is called. if ((access & GL_MAP_WRITE_BIT) > 0) { - mIndexRangeCache.invalidateRange(offset, length); + mIndexRangeCache.invalidateRange(static_cast(offset), static_cast(length)); } return error; } -Error Buffer::unmap() +Error Buffer::unmap(GLboolean *result) { ASSERT(mMapped); - Error error = mBuffer->unmap(); + Error error = mBuffer->unmap(result); if (error.isError()) { + *result = GL_FALSE; return error; } @@ -113,9 +155,42 @@ Error Buffer::unmap() mMapPointer = NULL; mMapOffset = 0; mMapLength = 0; + mAccess = GL_WRITE_ONLY_OES; mAccessFlags = 0; return error; } +void Buffer::onTransformFeedback() +{ + mIndexRangeCache.clear(); +} + +void Buffer::onPixelUnpack() +{ + mIndexRangeCache.clear(); +} + +Error Buffer::getIndexRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + IndexRange *outRange) const +{ + if (mIndexRangeCache.findRange(type, offset, count, primitiveRestartEnabled, outRange)) + { + return gl::Error(GL_NO_ERROR); + } + + Error error = mBuffer->getIndexRange(type, offset, count, primitiveRestartEnabled, outRange); + if (error.isError()) + { + return error; + } + + mIndexRangeCache.addRange(type, offset, count, primitiveRestartEnabled, *outRange); + + return Error(GL_NO_ERROR); +} + } diff --git a/src/3rdparty/angle/src/libANGLE/Buffer.h b/src/3rdparty/angle/src/libANGLE/Buffer.h index 6793028e3b..6c951ef586 100644 --- a/src/3rdparty/angle/src/libANGLE/Buffer.h +++ b/src/3rdparty/angle/src/libANGLE/Buffer.h @@ -11,11 +11,11 @@ #ifndef LIBANGLE_BUFFER_H_ #define LIBANGLE_BUFFER_H_ +#include "common/angleutils.h" +#include "libANGLE/Debug.h" #include "libANGLE/Error.h" +#include "libANGLE/IndexRangeCache.h" #include "libANGLE/RefCountObject.h" -#include "libANGLE/renderer/IndexRangeCache.h" - -#include "common/angleutils.h" namespace rx { @@ -25,21 +25,34 @@ class BufferImpl; namespace gl { -class Buffer : public RefCountObject +class Buffer final : public RefCountObject, public LabeledObject { public: Buffer(rx::BufferImpl *impl, GLuint id); - virtual ~Buffer(); + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + Error bufferData(const void *data, GLsizeiptr size, GLenum usage); Error bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); Error copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); + Error map(GLenum access); Error mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access); - Error unmap(); + Error unmap(GLboolean *result); + + void onTransformFeedback(); + void onPixelUnpack(); + + Error getIndexRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + IndexRange *outRange) const; GLenum getUsage() const { return mUsage; } - GLint getAccessFlags() const { return mAccessFlags; } + GLbitfield getAccessFlags() const { return mAccessFlags; } + GLenum getAccess() const { return mAccess; } GLboolean isMapped() const { return mMapped; } GLvoid *getMapPointer() const { return mMapPointer; } GLint64 getMapOffset() const { return mMapOffset; } @@ -48,21 +61,21 @@ class Buffer : public RefCountObject rx::BufferImpl *getImplementation() const { return mBuffer; } - rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; } - const rx::IndexRangeCache *getIndexRangeCache() const { return &mIndexRangeCache; } - private: rx::BufferImpl *mBuffer; + std::string mLabel; + GLenum mUsage; GLint64 mSize; - GLint mAccessFlags; + GLbitfield mAccessFlags; + GLenum mAccess; GLboolean mMapped; GLvoid *mMapPointer; GLint64 mMapOffset; GLint64 mMapLength; - rx::IndexRangeCache mIndexRangeCache; + mutable IndexRangeCache mIndexRangeCache; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Caps.cpp b/src/3rdparty/angle/src/libANGLE/Caps.cpp index 086d0a02a2..1eb54a1589 100644 --- a/src/3rdparty/angle/src/libANGLE/Caps.cpp +++ b/src/3rdparty/angle/src/libANGLE/Caps.cpp @@ -58,7 +58,7 @@ GLuint TextureCaps::getNearestSamples(GLuint requestedSamples) const void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps) { - mCapsMap.insert(std::make_pair(internalFormat, caps)); + mCapsMap[internalFormat] = caps; } void TextureCapsMap::remove(GLenum internalFormat) @@ -102,6 +102,7 @@ Extensions::Extensions() pixelBufferObject(false), mapBuffer(false), mapBufferRange(false), + colorBufferHalfFloat(false), textureHalfFloat(false), textureHalfFloatLinear(false), textureFloat(false), @@ -110,15 +111,22 @@ Extensions::Extensions() textureCompressionDXT1(false), textureCompressionDXT3(false), textureCompressionDXT5(false), + textureCompressionASTCHDR(false), + textureCompressionASTCLDR(false), + compressedETC1RGB8Texture(false), depthTextures(false), + depth32(false), + textureStorage(false), textureNPOT(false), drawBuffers(false), - textureStorage(false), textureFilterAnisotropic(false), maxTextureAnisotropy(false), occlusionQueryBoolean(false), fence(false), timerQuery(false), + disjointTimerQuery(false), + queryCounterBitsTimeElapsed(0), + queryCounterBitsTimestamp(0), robustness(false), blendMinMax(false), framebufferBlit(false), @@ -133,6 +141,22 @@ Extensions::Extensions() fragDepth(false), textureUsage(false), translatedShaderSource(false), + fboRenderMipmap(false), + discardFramebuffer(false), + debugMarker(false), + eglImage(false), + eglImageExternal(false), + eglImageExternalEssl3(false), + unpackSubimage(false), + packSubimage(false), + vertexArrayObject(false), + debug(false), + maxDebugMessageLength(0), + maxDebugLoggedMessages(0), + maxDebugGroupStackDepth(0), + maxLabelLength(0), + noError(false), + lossyETCDecode(false), colorBufferFloat(false) { } @@ -141,52 +165,84 @@ std::vector Extensions::getStrings() const { std::vector extensionStrings; - // | Extension name | Supported flag | Output vector | - InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings); - InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings); - InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings); - InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings); - InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings); - InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings); - InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings); - InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings); - InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings); - InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings); - InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings); - InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings); - InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings); - InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings); - InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings); - InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings); - InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings); - InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings); - InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings); - InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings); - InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings); - InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings); - InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings); - InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings); - InsertExtensionString("GL_NV_fence", fence, &extensionStrings); - InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings); - InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings); - InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings); - InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings); - InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings); - InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings); - InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings); - InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings); - InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings); - InsertExtensionString("GL_NV_shader_framebuffer_fetch", NVshaderFramebufferFetch, &extensionStrings); - InsertExtensionString("GL_ARM_shader_framebuffer_fetch", ARMshaderFramebufferFetch,&extensionStrings); - InsertExtensionString("GL_EXT_shader_framebuffer_fetch", shaderFramebufferFetch, &extensionStrings); - InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings); - InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings); - InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings); - InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings); + // clang-format off + // | Extension name | Supported flag | Output vector | + InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings); + InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings); + InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings); + InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings); + InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings); + InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings); + InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings); + InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings); + InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings); + InsertExtensionString("GL_EXT_color_buffer_half_float", colorBufferHalfFloat, &extensionStrings); + InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings); + InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings); + InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings); + InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings); + InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings); + InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings); + InsertExtensionString("GL_KHR_texture_compression_astc_hdr", textureCompressionASTCHDR, &extensionStrings); + InsertExtensionString("GL_KHR_texture_compression_astc_ldr", textureCompressionASTCLDR, &extensionStrings); + InsertExtensionString("GL_OES_compressed_ETC1_RGB8_texture", compressedETC1RGB8Texture, &extensionStrings); + InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings); + InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings); + InsertExtensionString("GL_OES_depth32", depth32, &extensionStrings); + InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings); + InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings); + InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings); + InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings); + InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings); + InsertExtensionString("GL_NV_fence", fence, &extensionStrings); + InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings); + InsertExtensionString("GL_EXT_disjoint_timer_query", disjointTimerQuery, &extensionStrings); + InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings); + InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings); + InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings); + InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings); + InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings); + InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings); + InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings); + InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings); + InsertExtensionString("GL_NV_shader_framebuffer_fetch", NVshaderFramebufferFetch, &extensionStrings); + InsertExtensionString("GL_ARM_shader_framebuffer_fetch", ARMshaderFramebufferFetch, &extensionStrings); + InsertExtensionString("GL_EXT_shader_framebuffer_fetch", shaderFramebufferFetch, &extensionStrings); + InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings); + InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings); + InsertExtensionString("GL_OES_fbo_render_mipmap", fboRenderMipmap, &extensionStrings); + InsertExtensionString("GL_EXT_discard_framebuffer", discardFramebuffer, &extensionStrings); + InsertExtensionString("GL_EXT_debug_marker", debugMarker, &extensionStrings); + InsertExtensionString("GL_OES_EGL_image", eglImage, &extensionStrings); + InsertExtensionString("GL_OES_EGL_image_external", eglImageExternal, &extensionStrings); + InsertExtensionString("GL_OES_EGL_image_external_essl3", eglImageExternalEssl3, &extensionStrings); + InsertExtensionString("GL_EXT_unpack_subimage", unpackSubimage, &extensionStrings); + InsertExtensionString("GL_NV_pack_subimage", packSubimage, &extensionStrings); + InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings); + InsertExtensionString("GL_OES_vertex_array_object", vertexArrayObject, &extensionStrings); + InsertExtensionString("GL_KHR_debug", debug, &extensionStrings); + // TODO(jmadill): Enable this when complete. + //InsertExtensionString("GL_KHR_no_error", noError, &extensionStrings); + + InsertExtensionString("GL_ANGLE_lossy_etc_decode", lossyETCDecode, &extensionStrings); + // clang-format on return extensionStrings; } +Limitations::Limitations() + : noFrontFacingSupport(false), + noSampleAlphaToCoverageSupport(false), + attributeZeroRequiresZeroDivisorInEXT(false), + noSeparateStencilRefsAndMasks(false), + shadersRequireIndexedLoopValidation(false), + noSimultaneousConstantColorAndAlphaBlendFunc(false) +{ +} + static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector &requiredFormats, bool requiresTexturing, bool requiresFiltering, bool requiresRendering) { @@ -213,6 +269,15 @@ static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vecto return true; } +// Check for GL_OES_packed_depth_stencil +static bool DeterminePackedDepthStencilSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_DEPTH24_STENCIL8); + + return GetFormatSupport(textureCaps, requiredFormats, false, false, true); +} + // Checks for GL_OES_rgb8_rgba8 support static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps) { @@ -232,6 +297,18 @@ static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps) return GetFormatSupport(textureCaps, requiredFormats, true, true, true); } +// Checks for GL_OES_color_buffer_half_float support +static bool DetermineColorBufferHalfFloatSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGBA16F); + requiredFormats.push_back(GL_RGB16F); + requiredFormats.push_back(GL_RG16F); + requiredFormats.push_back(GL_R16F); + + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); +} + // Checks for GL_OES_texture_half_float support static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps) { @@ -249,7 +326,8 @@ static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &text requiredFormats.push_back(GL_RGB16F); requiredFormats.push_back(GL_RGBA16F); - return GetFormatSupport(textureCaps, requiredFormats, true, true, false); + return DetermineHalfFloatTextureSupport(textureCaps) && + GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Checks for GL_OES_texture_float support @@ -269,7 +347,8 @@ static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureC requiredFormats.push_back(GL_RGB32F); requiredFormats.push_back(GL_RGBA32F); - return GetFormatSupport(textureCaps, requiredFormats, true, true, false); + return DetermineFloatTextureSupport(textureCaps) && + GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Checks for GL_EXT_texture_rg support @@ -320,6 +399,51 @@ static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps) return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } +// Check for GL_KHR_texture_compression_astc_hdr and GL_KHR_texture_compression_astc_ldr +static bool DetermineASTCTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_4x4_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_5x4_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_5x5_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_6x5_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_6x6_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_8x5_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_8x6_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_8x8_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x5_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x6_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x8_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_10x10_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_12x10_KHR); + requiredFormats.push_back(GL_COMPRESSED_RGBA_ASTC_12x12_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR); + requiredFormats.push_back(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); +} + +// Check for GL_ETC1_RGB8_OES +static bool DetermineETC1RGB8TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_ETC1_RGB8_OES); + + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); +} + // Check for GL_ANGLE_texture_compression_dxt5 static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps) { @@ -345,6 +469,15 @@ static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps) return GetFormatSupport(textureCaps, requiredFormats, true, true, true); } +// Check for GL_OES_depth32 +static bool DetermineDepth32Support(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES); + + return GetFormatSupport(textureCaps, requiredFormats, false, false, true); +} + // Check for GL_EXT_color_buffer_float static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps) { @@ -362,8 +495,10 @@ static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps) void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps) { + packedDepthStencil = DeterminePackedDepthStencilSupport(textureCaps); rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps); textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps); + colorBufferHalfFloat = DetermineColorBufferHalfFloatSupport(textureCaps); textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps); textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps); textureFloat = DetermineFloatTextureSupport(textureCaps); @@ -372,8 +507,12 @@ void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps) textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps); textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps); textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps); + textureCompressionASTCHDR = DetermineASTCTextureSupport(textureCaps); + textureCompressionASTCLDR = textureCompressionASTCHDR; + compressedETC1RGB8Texture = DetermineETC1RGB8TextureSupport(textureCaps); sRGB = DetermineSRGBTextureSupport(textureCaps); depthTextures = DetermineDepthTextureSupport(textureCaps); + depth32 = DetermineDepth32Support(textureCaps); colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps); } @@ -446,7 +585,7 @@ Caps::Caps() maxTextureImageUnits(0), minProgramTexelOffset(0), maxProgramTexelOffset(0), - + // Table 6.33 maxUniformBufferBindings(0), maxUniformBlockSize(0), uniformBufferOffsetAlignment(0), @@ -456,10 +595,12 @@ Caps::Caps() maxVaryingComponents(0), maxVaryingVectors(0), maxCombinedTextureImageUnits(0), - + // Table 6.34 maxTransformFeedbackInterleavedComponents(0), maxTransformFeedbackSeparateAttributes(0), - maxTransformFeedbackSeparateComponents(0) + maxTransformFeedbackSeparateComponents(0), + // Table 6.35 + maxSamples(0) { } @@ -479,8 +620,22 @@ DisplayExtensions::DisplayExtensions() surfaceD3DTexture2DShareHandle(false), querySurfacePointer(false), windowFixedSize(false), + keyedMutex(false), + surfaceOrientation(false), postSubBuffer(false), - createContext(false) + createContext(false), + deviceQuery(false), + image(false), + imageBase(false), + imagePixmap(false), + glTexture2DImage(false), + glTextureCubemapImage(false), + glTexture3DImage(false), + glRenderbufferImage(false), + getAllProcAddresses(false), + flexibleSurfaceCompatibility(false), + directComposition(false), + createContextNoError(false) { } @@ -488,25 +643,62 @@ std::vector DisplayExtensions::getStrings() const { std::vector extensionStrings; + // clang-format off // | Extension name | Supported flag | Output vector | InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings); InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings); InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings); InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings); InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings); + InsertExtensionString("EGL_ANGLE_keyed_mutex", keyedMutex, &extensionStrings); + InsertExtensionString("EGL_ANGLE_surface_orientation", surfaceOrientation, &extensionStrings); + InsertExtensionString("EGL_ANGLE_direct_composition", directComposition, &extensionStrings); InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings); InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings); + InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings); + InsertExtensionString("EGL_KHR_image", image, &extensionStrings); + InsertExtensionString("EGL_KHR_image_base", imageBase, &extensionStrings); + InsertExtensionString("EGL_KHR_image_pixmap", imagePixmap, &extensionStrings); + InsertExtensionString("EGL_KHR_gl_texture_2D_image", glTexture2DImage, &extensionStrings); + InsertExtensionString("EGL_KHR_gl_texture_cubemap_image", glTextureCubemapImage, &extensionStrings); + InsertExtensionString("EGL_KHR_gl_texture_3D_image", glTexture3DImage, &extensionStrings); + InsertExtensionString("EGL_KHR_gl_renderbuffer_image", glRenderbufferImage, &extensionStrings); + InsertExtensionString("EGL_KHR_get_all_proc_addresses", getAllProcAddresses, &extensionStrings); + InsertExtensionString("EGL_ANGLE_flexible_surface_compatibility", flexibleSurfaceCompatibility, &extensionStrings); + // TODO(jmadill): Enable this when complete. + //InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings); + // clang-format on return extensionStrings; } +DeviceExtensions::DeviceExtensions() + : deviceD3D(false) +{ +} + +std::vector DeviceExtensions::getStrings() const +{ + std::vector extensionStrings; + + // | Extension name | Supported flag | Output vector | + InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings); + + return extensionStrings; +} ClientExtensions::ClientExtensions() : clientExtensions(false), platformBase(false), + platformDevice(false), platformANGLE(false), platformANGLED3D(false), - platformANGLEOpenGL(false) + platformANGLEOpenGL(false), + deviceCreation(false), + deviceCreationD3D11(false), + x11Visual(false), + experimentalPresentPath(false), + clientGetAllProcAddresses(false) { } @@ -514,12 +706,20 @@ std::vector ClientExtensions::getStrings() const { std::vector extensionStrings; - // | Extension name | Supported flag | Output vector | - InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings); - InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings); - InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings); - InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings); - InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings); + // clang-format off + // | Extension name | Supported flag | Output vector | + InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings); + InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings); + InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings); + InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings); + InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings); + InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings); + InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings); + InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings); + InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings); + InsertExtensionString("EGL_ANGLE_experimental_present_path", experimentalPresentPath, &extensionStrings); + InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings); + // clang-format on return extensionStrings; } diff --git a/src/3rdparty/angle/src/libANGLE/Caps.h b/src/3rdparty/angle/src/libANGLE/Caps.h index 37a634226a..d0e839a2ba 100644 --- a/src/3rdparty/angle/src/libANGLE/Caps.h +++ b/src/3rdparty/angle/src/libANGLE/Caps.h @@ -33,6 +33,7 @@ struct TextureCaps // Support for being used as a framebuffer attachment or renderbuffer format bool renderable; + // Set of supported sample counts, only guaranteed to be valid in ES3. SupportedSampleSet sampleCounts; // Get the maximum number of samples supported @@ -72,14 +73,19 @@ struct Extensions // Set all texture related extension support based on the supported textures. // Determines support for: + // GL_OES_packed_depth_stencil // GL_OES_rgb8_rgba8 // GL_EXT_texture_format_BGRA8888 + // GL_EXT_color_buffer_half_float, // GL_OES_texture_half_float, GL_OES_texture_half_float_linear // GL_OES_texture_float, GL_OES_texture_float_linear // GL_EXT_texture_rg - // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3, GL_ANGLE_texture_compression_dxt5 + // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3, + // GL_ANGLE_texture_compression_dxt5 + // GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr + // GL_OES_compressed_ETC1_RGB8_texture // GL_EXT_sRGB - // GL_ANGLE_depth_texture + // GL_ANGLE_depth_texture, GL_OES_depth32 // GL_EXT_color_buffer_float void setTextureExtensionSupport(const TextureCapsMap &textureCaps); @@ -112,6 +118,11 @@ struct Extensions bool mapBuffer; bool mapBufferRange; + // GL_EXT_color_buffer_half_float + // Together with GL_OES_texture_half_float in a GLES 2.0 context, implies that half-float + // textures are renderable. + bool colorBufferHalfFloat; + // GL_OES_texture_half_float and GL_OES_texture_half_float_linear // Implies that TextureCaps for GL_RGB16F, GL_RGBA16F, GL_ALPHA32F_EXT, GL_LUMINANCE32F_EXT and // GL_LUMINANCE_ALPHA32F_EXT exist @@ -136,6 +147,16 @@ struct Extensions bool textureCompressionDXT3; bool textureCompressionDXT5; + // GL_KHR_texture_compression_astc_hdr + bool textureCompressionASTCHDR; + + // GL_KHR_texture_compression_astc_ldr + bool textureCompressionASTCLDR; + + // GL_OES_compressed_ETC1_RGB8_texture + // Implies that TextureCaps for GL_ETC1_RGB8_OES exist + bool compressedETC1RGB8Texture; + // GL_EXT_sRGB // Implies that TextureCaps for GL_SRGB8_ALPHA8 and GL_SRGB8 exist // TODO: Don't advertise this extension in ES3 @@ -144,6 +165,10 @@ struct Extensions // GL_ANGLE_depth_texture bool depthTextures; + // GL_OES_depth32 + // Allows DEPTH_COMPONENT32_OES as a valid Renderbuffer format. + bool depth32; + // GL_EXT_texture_storage bool textureStorage; @@ -166,6 +191,11 @@ struct Extensions // GL_ANGLE_timer_query bool timerQuery; + // GL_EXT_disjoint_timer_query + bool disjointTimerQuery; + GLuint queryCounterBitsTimeElapsed; + GLuint queryCounterBitsTimestamp; + // GL_EXT_robustness bool robustness; @@ -177,7 +207,6 @@ struct Extensions // GL_ANGLE_framebuffer_multisample bool framebufferMultisample; - GLuint maxSamples; // GL_ANGLE_instanced_arrays bool instancedArrays; @@ -209,12 +238,76 @@ struct Extensions // GL_ANGLE_translated_shader_source bool translatedShaderSource; + // GL_OES_fbo_render_mipmap + bool fboRenderMipmap; + + // GL_EXT_discard_framebuffer + bool discardFramebuffer; + + // EXT_debug_marker + bool debugMarker; + + // GL_OES_EGL_image + bool eglImage; + + // GL_OES_EGL_image_external + bool eglImageExternal; + + // GL_OES_EGL_image_external_essl3 + bool eglImageExternalEssl3; + + // EXT_unpack_subimage + bool unpackSubimage; + + // NV_pack_subimage + bool packSubimage; + + // GL_OES_vertex_array_object + bool vertexArrayObject; + + // GL_KHR_debug + bool debug; + GLuint maxDebugMessageLength; + GLuint maxDebugLoggedMessages; + GLuint maxDebugGroupStackDepth; + GLuint maxLabelLength; + + // KHR_no_error + bool noError; + + // GL_ANGLE_lossy_etc_decode + bool lossyETCDecode; + // ES3 Extension support // GL_EXT_color_buffer_float bool colorBufferFloat; }; +struct Limitations +{ + Limitations(); + + // Renderer doesn't support gl_FrontFacing in fragment shaders + bool noFrontFacingSupport; + + // Renderer doesn't support GL_SAMPLE_ALPHA_TO_COVERAGE + bool noSampleAlphaToCoverageSupport; + + // In glVertexAttribDivisorANGLE, attribute zero must have a zero divisor + bool attributeZeroRequiresZeroDivisorInEXT; + + // Unable to support different values for front and back faces for stencil refs and masks + bool noSeparateStencilRefsAndMasks; + + // Renderer doesn't support non-constant indexing loops in fragment shader + bool shadersRequireIndexedLoopValidation; + + // Renderer doesn't support Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA + // and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR blend functions. + bool noSimultaneousConstantColorAndAlphaBlendFunc; +}; + struct TypePrecision { TypePrecision(); @@ -302,6 +395,9 @@ struct Caps GLuint maxTransformFeedbackInterleavedComponents; GLuint maxTransformFeedbackSeparateAttributes; GLuint maxTransformFeedbackSeparateComponents; + + // Table 6.35, Framebuffer Dependent Values + GLuint maxSamples; }; } @@ -339,11 +435,64 @@ struct DisplayExtensions // EGL_ANGLE_window_fixed_size bool windowFixedSize; + // EGL_ANGLE_keyed_mutex + bool keyedMutex; + + // EGL_ANGLE_surface_orientation + bool surfaceOrientation; + // EGL_NV_post_sub_buffer bool postSubBuffer; // EGL_KHR_create_context bool createContext; + + // EGL_EXT_device_query + bool deviceQuery; + + // EGL_KHR_image + bool image; + + // EGL_KHR_image_base + bool imageBase; + + // EGL_KHR_image_pixmap + bool imagePixmap; + + // EGL_KHR_gl_texture_2D_image + bool glTexture2DImage; + + // EGL_KHR_gl_texture_cubemap_image + bool glTextureCubemapImage; + + // EGL_KHR_gl_texture_3D_image + bool glTexture3DImage; + + // EGL_KHR_gl_renderbuffer_image + bool glRenderbufferImage; + + // EGL_KHR_get_all_proc_addresses + bool getAllProcAddresses; + + // EGL_ANGLE_flexible_surface_compatibility + bool flexibleSurfaceCompatibility; + + // EGL_ANGLE_direct_composition + bool directComposition; + + // KHR_create_context_no_error + bool createContextNoError; +}; + +struct DeviceExtensions +{ + DeviceExtensions(); + + // Generate a vector of supported extension strings + std::vector getStrings() const; + + // EGL_ANGLE_device_d3d + bool deviceD3D; }; struct ClientExtensions @@ -359,6 +508,9 @@ struct ClientExtensions // EGL_EXT_platform_base bool platformBase; + // EGL_EXT_platform_device + bool platformDevice; + // EGL_ANGLE_platform_angle bool platformANGLE; @@ -367,6 +519,21 @@ struct ClientExtensions // EGL_ANGLE_platform_angle_opengl bool platformANGLEOpenGL; + + // EGL_ANGLE_device_creation + bool deviceCreation; + + // EGL_ANGLE_device_creation_d3d11 + bool deviceCreationD3D11; + + // EGL_ANGLE_x11_visual + bool x11Visual; + + // EGL_ANGLE_experimental_present_path + bool experimentalPresentPath; + + // EGL_KHR_client_get_all_proc_addresses + bool clientGetAllProcAddresses; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.cpp b/src/3rdparty/angle/src/libANGLE/Compiler.cpp index 7d0efea220..348c41bef3 100644 --- a/src/3rdparty/angle/src/libANGLE/Compiler.cpp +++ b/src/3rdparty/angle/src/libANGLE/Compiler.cpp @@ -7,32 +7,128 @@ // Compiler.cpp: implements the gl::Compiler class. #include "libANGLE/Compiler.h" -#include "libANGLE/renderer/CompilerImpl.h" #include "common/debug.h" +#include "libANGLE/Data.h" +#include "libANGLE/renderer/CompilerImpl.h" +#include "libANGLE/renderer/ImplFactory.h" namespace gl { -Compiler::Compiler(rx::CompilerImpl *impl) - : mCompiler(impl) +namespace +{ + +// Global count of active shader compiler handles. Needed to know when to call ShInitialize and +// ShFinalize. +size_t activeCompilerHandles = 0; + +} // anonymous namespace + +Compiler::Compiler(rx::ImplFactory *implFactory, const gl::Data &data) + : mImplementation(implFactory->createCompiler()), + mSpec(data.clientVersion > 2 ? SH_GLES3_SPEC : SH_GLES2_SPEC), + mOutputType(mImplementation->getTranslatorOutputType()), + mResources(), + mFragmentCompiler(nullptr), + mVertexCompiler(nullptr) { - ASSERT(mCompiler); + ASSERT(data.clientVersion == 2 || data.clientVersion == 3); + + const gl::Caps &caps = *data.caps; + const gl::Extensions &extensions = *data.extensions; + + ShInitBuiltInResources(&mResources); + mResources.MaxVertexAttribs = caps.maxVertexAttributes; + mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; + mResources.MaxVaryingVectors = caps.maxVaryingVectors; + mResources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits; + mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; + mResources.MaxTextureImageUnits = caps.maxTextureImageUnits; + mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors; + mResources.MaxDrawBuffers = caps.maxDrawBuffers; + mResources.OES_standard_derivatives = extensions.standardDerivatives; + mResources.EXT_draw_buffers = extensions.drawBuffers; + mResources.EXT_shader_texture_lod = extensions.shaderTextureLOD; + // TODO: disabled until the extension is actually supported. + mResources.OES_EGL_image_external = 0; + // TODO: use shader precision caps to determine if high precision is supported? + mResources.FragmentPrecisionHigh = 1; + mResources.EXT_frag_depth = extensions.fragDepth; + + // GLSL ES 3.0 constants + mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4; + mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4; + mResources.MinProgramTexelOffset = caps.minProgramTexelOffset; + mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; } Compiler::~Compiler() { - SafeDelete(mCompiler); + release(); + SafeDelete(mImplementation); } Error Compiler::release() { - return mCompiler->release(); + if (mFragmentCompiler) + { + ShDestruct(mFragmentCompiler); + mFragmentCompiler = nullptr; + + ASSERT(activeCompilerHandles > 0); + activeCompilerHandles--; + } + + if (mVertexCompiler) + { + ShDestruct(mVertexCompiler); + mVertexCompiler = nullptr; + + ASSERT(activeCompilerHandles > 0); + activeCompilerHandles--; + } + + if (activeCompilerHandles == 0) + { + ShFinalize(); + } + + mImplementation->release(); + + return gl::Error(GL_NO_ERROR); } -rx::CompilerImpl *Compiler::getImplementation() +ShHandle Compiler::getCompilerHandle(GLenum type) { - return mCompiler; -} + ShHandle *compiler = nullptr; + switch (type) + { + case GL_VERTEX_SHADER: + compiler = &mVertexCompiler; + break; + case GL_FRAGMENT_SHADER: + compiler = &mFragmentCompiler; + break; + + default: + UNREACHABLE(); + return nullptr; + } + + if (!(*compiler)) + { + if (activeCompilerHandles == 0) + { + ShInitialize(); + } + + *compiler = ShConstructCompiler(type, mSpec, mOutputType, &mResources); + activeCompilerHandles++; + } + + return *compiler; } + +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.h b/src/3rdparty/angle/src/libANGLE/Compiler.h index 05de15ec97..8634e39a45 100644 --- a/src/3rdparty/angle/src/libANGLE/Compiler.h +++ b/src/3rdparty/angle/src/libANGLE/Compiler.h @@ -11,29 +11,39 @@ #define LIBANGLE_COMPILER_H_ #include "libANGLE/Error.h" +#include "GLSLANG/ShaderLang.h" namespace rx { class CompilerImpl; +class ImplFactory; } namespace gl { +struct Data; -class Compiler final +class Compiler final : angle::NonCopyable { public: - explicit Compiler(rx::CompilerImpl *impl); + Compiler(rx::ImplFactory *implFactory, const Data &data); ~Compiler(); Error release(); - rx::CompilerImpl *getImplementation(); + ShHandle getCompilerHandle(GLenum type); + ShShaderOutput getShaderOutputType() const { return mOutputType; } private: - rx::CompilerImpl *mCompiler; + rx::CompilerImpl *mImplementation; + ShShaderSpec mSpec; + ShShaderOutput mOutputType; + ShBuiltInResources mResources; + + ShHandle mFragmentCompiler; + ShHandle mVertexCompiler; }; -} +} // namespace gl #endif // LIBANGLE_COMPILER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Config.cpp b/src/3rdparty/angle/src/libANGLE/Config.cpp index 1b1fc50cb3..d511df3a69 100644 --- a/src/3rdparty/angle/src/libANGLE/Config.cpp +++ b/src/3rdparty/angle/src/libANGLE/Config.cpp @@ -57,14 +57,15 @@ Config::Config() transparentType(EGL_NONE), transparentRedValue(0), transparentGreenValue(0), - transparentBlueValue(0) + transparentBlueValue(0), + optimalOrientation(0) { } EGLint ConfigSet::add(const Config &config) { // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4) - EGLint id = mConfigs.size() + 1; + EGLint id = static_cast(mConfigs.size()) + 1; Config copyConfig(config); copyConfig.configID = id; @@ -251,6 +252,9 @@ std::vector ConfigSet::filter(const AttributeMap &attributeMap) c case EGL_MAX_PBUFFER_WIDTH: match = config.maxPBufferWidth >= attributeValue; break; case EGL_MAX_PBUFFER_HEIGHT: match = config.maxPBufferHeight >= attributeValue; break; case EGL_MAX_PBUFFER_PIXELS: match = config.maxPBufferPixels >= attributeValue; break; + case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE: + match = config.optimalOrientation == attributeValue; + break; default: UNREACHABLE(); } diff --git a/src/3rdparty/angle/src/libANGLE/Config.h b/src/3rdparty/angle/src/libANGLE/Config.h index aed8aedb1d..00f5673b59 100644 --- a/src/3rdparty/angle/src/libANGLE/Config.h +++ b/src/3rdparty/angle/src/libANGLE/Config.h @@ -64,6 +64,7 @@ struct Config EGLint transparentRedValue; // Transparent red value EGLint transparentGreenValue; // Transparent green value EGLint transparentBlueValue; // Transparent blue value + EGLint optimalOrientation; // Optimal window surface orientation }; class ConfigSet diff --git a/src/3rdparty/angle/src/libANGLE/Context.cpp b/src/3rdparty/angle/src/libANGLE/Context.cpp index 1da5fdae95..26f2970068 100644 --- a/src/3rdparty/angle/src/libANGLE/Context.cpp +++ b/src/3rdparty/angle/src/libANGLE/Context.cpp @@ -33,22 +33,124 @@ #include "libANGLE/validationES.h" #include "libANGLE/renderer/Renderer.h" -namespace gl +namespace +{ + +template +gl::Error GetQueryObjectParameter(gl::Context *context, GLuint id, GLenum pname, T *params) +{ + gl::Query *queryObject = context->getQuery(id, false, GL_NONE); + ASSERT(queryObject != nullptr); + + switch (pname) + { + case GL_QUERY_RESULT_EXT: + return queryObject->getResult(params); + case GL_QUERY_RESULT_AVAILABLE_EXT: + { + bool available; + gl::Error error = queryObject->isResultAvailable(&available); + if (!error.isError()) + { + *params = static_cast(available ? GL_TRUE : GL_FALSE); + } + return error; + } + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION, "Unreachable Error"); + } +} + +void MarkTransformFeedbackBufferUsage(gl::TransformFeedback *transformFeedback) +{ + if (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused()) + { + for (size_t tfBufferIndex = 0; tfBufferIndex < transformFeedback->getIndexedBufferCount(); + tfBufferIndex++) + { + const OffsetBindingPointer &buffer = + transformFeedback->getIndexedBuffer(tfBufferIndex); + if (buffer.get() != nullptr) + { + buffer->onTransformFeedback(); + } + } + } +} + +// Attribute map queries. +EGLint GetClientVersion(const egl::AttributeMap &attribs) +{ + return attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1); +} + +GLenum GetResetStrategy(const egl::AttributeMap &attribs) +{ + EGLenum attrib = attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, + EGL_NO_RESET_NOTIFICATION_EXT); + switch (attrib) + { + case EGL_NO_RESET_NOTIFICATION: + return GL_NO_RESET_NOTIFICATION_EXT; + case EGL_LOSE_CONTEXT_ON_RESET: + return GL_LOSE_CONTEXT_ON_RESET_EXT; + default: + UNREACHABLE(); + return GL_NONE; + } +} + +bool GetRobustAccess(const egl::AttributeMap &attribs) +{ + return (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE); +} + +bool GetDebug(const egl::AttributeMap &attribs) { + return (attribs.get(EGL_CONTEXT_OPENGL_DEBUG, EGL_FALSE) == EGL_TRUE); +} -Context::Context(const egl::Config *config, int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) - : mRenderer(renderer) +bool GetNoError(const egl::AttributeMap &attribs) { - ASSERT(robustAccess == false); // Unimplemented + return (attribs.get(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, EGL_FALSE) == EGL_TRUE); +} - initCaps(clientVersion); - mState.initialize(mCaps, clientVersion); +} // anonymous namespace - mClientVersion = clientVersion; +namespace gl +{ - mConfigID = config->configID; - mClientType = EGL_OPENGL_ES_API; - mRenderBuffer = EGL_NONE; +Context::Context(const egl::Config *config, + const Context *shareContext, + rx::Renderer *renderer, + const egl::AttributeMap &attribs) + : ValidationContext(GetClientVersion(attribs), + mState, + mCaps, + mTextureCaps, + mExtensions, + nullptr, + mLimitations, + GetNoError(attribs)), + mCompiler(nullptr), + mRenderer(renderer), + mClientVersion(GetClientVersion(attribs)), + mConfig(config), + mClientType(EGL_OPENGL_ES_API), + mHasBeenCurrent(false), + mContextLost(false), + mResetStatus(GL_NO_ERROR), + mResetStrategy(GetResetStrategy(attribs)), + mRobustAccess(GetRobustAccess(attribs)), + mCurrentSurface(nullptr), + mResourceManager(nullptr) +{ + ASSERT(!mRobustAccess); // Unimplemented + + initCaps(mClientVersion); + + mState.initialize(mCaps, mExtensions, mClientVersion, GetDebug(attribs)); mFenceNVHandleAllocator.setBaseHandle(0); @@ -62,6 +164,8 @@ Context::Context(const egl::Config *config, int clientVersion, const Context *sh mResourceManager = new ResourceManager(mRenderer); } + mData.resourceManager = mResourceManager; + // [OpenGL ES 2.0.24] section 3.7 page 83: // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional // and cube map texture state vectors respectively associated with them. @@ -90,8 +194,6 @@ Context::Context(const egl::Config *config, int clientVersion, const Context *sh bindArrayBuffer(0); bindElementArrayBuffer(0); - bindReadFramebuffer(0); - bindDrawFramebuffer(0); bindRenderbuffer(0); bindGenericUniformBuffer(0); @@ -100,70 +202,73 @@ Context::Context(const egl::Config *config, int clientVersion, const Context *sh bindIndexedUniformBuffer(0, i, 0, -1); } - bindGenericTransformFeedbackBuffer(0); - for (unsigned int i = 0; i < mCaps.maxTransformFeedbackSeparateAttributes; i++) - { - bindIndexedTransformFeedbackBuffer(0, i, 0, -1); - } - bindCopyReadBuffer(0); bindCopyWriteBuffer(0); bindPixelPackBuffer(0); bindPixelUnpackBuffer(0); - // [OpenGL ES 3.0.2] section 2.14.1 pg 85: - // In the initial state, a default transform feedback object is bound and treated as - // a transform feedback object with a name of zero. That object is bound any time - // BindTransformFeedback is called with id of zero - mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0)); - bindTransformFeedback(0); - - mHasBeenCurrent = false; - mContextLost = false; - mResetStatus = GL_NO_ERROR; - mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); - mRobustAccess = robustAccess; + if (mClientVersion >= 3) + { + // [OpenGL ES 3.0.2] section 2.14.1 pg 85: + // In the initial state, a default transform feedback object is bound and treated as + // a transform feedback object with a name of zero. That object is bound any time + // BindTransformFeedback is called with id of zero + bindTransformFeedback(0); + } - mCompiler = new Compiler(mRenderer->createCompiler(getData())); + mCompiler = new Compiler(mRenderer, getData()); } Context::~Context() { mState.reset(); - while (!mFramebufferMap.empty()) + for (auto framebuffer : mFramebufferMap) { - // Delete the framebuffer in reverse order to destroy the framebuffer zero last. - deleteFramebuffer(mFramebufferMap.rbegin()->first); + // Default framebuffer are owned by their respective Surface + if (framebuffer.second != nullptr && framebuffer.second->id() != 0) + { + SafeDelete(framebuffer.second); + } } - while (!mFenceNVMap.empty()) + for (auto fence : mFenceNVMap) { - deleteFenceNV(mFenceNVMap.begin()->first); + SafeDelete(fence.second); } - while (!mQueryMap.empty()) + for (auto query : mQueryMap) { - deleteQuery(mQueryMap.begin()->first); + if (query.second != nullptr) + { + query.second->release(); + } } - while (!mVertexArrayMap.empty()) + for (auto vertexArray : mVertexArrayMap) { - deleteVertexArray(mVertexArrayMap.begin()->first); + SafeDelete(vertexArray.second); } - mTransformFeedbackZero.set(NULL); - while (!mTransformFeedbackMap.empty()) + for (auto transformFeedback : mTransformFeedbackMap) { - deleteTransformFeedback(mTransformFeedbackMap.begin()->first); + if (transformFeedback.second != nullptr) + { + transformFeedback.second->release(); + } } - for (auto it = mZeroTextures.begin(); it != mZeroTextures.end(); ++it) + for (auto &zeroTexture : mZeroTextures) { - it->second.set(NULL); + zeroTexture.second.set(NULL); } mZeroTextures.clear(); + if (mCurrentSurface != nullptr) + { + releaseSurface(); + } + if (mResourceManager) { mResourceManager->release(); @@ -174,6 +279,8 @@ Context::~Context() void Context::makeCurrent(egl::Surface *surface) { + ASSERT(surface != nullptr); + if (!mHasBeenCurrent) { initRendererString(); @@ -185,12 +292,55 @@ void Context::makeCurrent(egl::Surface *surface) mHasBeenCurrent = true; } - // TODO(jmadill): do not allocate new pointers here - Framebuffer *framebufferZero = new DefaultFramebuffer(mCaps, mRenderer, surface); + // TODO(jmadill): Rework this when we support ContextImpl + mState.setAllDirtyBits(); - setFramebufferZero(framebufferZero); + if (mCurrentSurface) + { + releaseSurface(); + } + surface->setIsCurrent(true); + mCurrentSurface = surface; + + // Update default framebuffer, the binding of the previous default + // framebuffer (or lack of) will have a nullptr. + { + Framebuffer *newDefault = surface->getDefaultFramebuffer(); + if (mState.getReadFramebuffer() == nullptr) + { + mState.setReadFramebufferBinding(newDefault); + } + if (mState.getDrawFramebuffer() == nullptr) + { + mState.setDrawFramebufferBinding(newDefault); + } + mFramebufferMap[0] = newDefault; + } - mRenderBuffer = surface->getRenderBuffer(); + // Notify the renderer of a context switch + mRenderer->onMakeCurrent(getData()); +} + +void Context::releaseSurface() +{ + ASSERT(mCurrentSurface != nullptr); + + // Remove the default framebuffer + { + Framebuffer *currentDefault = mCurrentSurface->getDefaultFramebuffer(); + if (mState.getReadFramebuffer() == currentDefault) + { + mState.setReadFramebufferBinding(nullptr); + } + if (mState.getDrawFramebuffer() == currentDefault) + { + mState.setDrawFramebufferBinding(nullptr); + } + mFramebufferMap.erase(0); + } + + mCurrentSurface->setIsCurrent(false); + mCurrentSurface = nullptr; } // NOTE: this function should not assume that this context is current! @@ -218,7 +368,7 @@ GLuint Context::createProgram() GLuint Context::createShader(GLenum type) { - return mResourceManager->createShader(getData(), type); + return mResourceManager->createShader(mRenderer->getRendererLimitations(), type); } GLuint Context::createTexture() @@ -240,14 +390,9 @@ GLsync Context::createFenceSync() GLuint Context::createVertexArray() { - GLuint handle = mVertexArrayHandleAllocator.allocate(); - - // Although the spec states VAO state is not initialized until the object is bound, - // we create it immediately. The resulting behaviour is transparent to the application, - // since it's not currently possible to access the state until the object is bound. - VertexArray *vertexArray = new VertexArray(mRenderer->createVertexArray(), handle, MAX_VERTEX_ATTRIBS); - mVertexArrayMap[handle] = vertexArray; - return handle; + GLuint vertexArray = mVertexArrayHandleAllocator.allocate(); + mVertexArrayMap[vertexArray] = nullptr; + return vertexArray; } GLuint Context::createSampler() @@ -257,11 +402,9 @@ GLuint Context::createSampler() GLuint Context::createTransformFeedback() { - GLuint handle = mTransformFeedbackAllocator.allocate(); - TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle); - transformFeedback->addRef(); - mTransformFeedbackMap[handle] = transformFeedback; - return handle; + GLuint transformFeedback = mTransformFeedbackAllocator.allocate(); + mTransformFeedbackMap[transformFeedback] = nullptr; + return transformFeedback; } // Returns an unused framebuffer name @@ -339,20 +482,23 @@ void Context::deleteFenceSync(GLsync fenceSync) // wait commands finish. However, since the name becomes invalid, we cannot query the fence, // and since our API is currently designed for being called from a single thread, we can delete // the fence immediately. - mResourceManager->deleteFenceSync(reinterpret_cast(fenceSync)); + mResourceManager->deleteFenceSync(static_cast(reinterpret_cast(fenceSync))); } void Context::deleteVertexArray(GLuint vertexArray) { - auto vertexArrayObject = mVertexArrayMap.find(vertexArray); - - if (vertexArrayObject != mVertexArrayMap.end()) + auto iter = mVertexArrayMap.find(vertexArray); + if (iter != mVertexArrayMap.end()) { - detachVertexArray(vertexArray); + VertexArray *vertexArrayObject = iter->second; + if (vertexArrayObject != nullptr) + { + detachVertexArray(vertexArray); + delete vertexArrayObject; + } - mVertexArrayHandleAllocator.release(vertexArrayObject->first); - delete vertexArrayObject->second; - mVertexArrayMap.erase(vertexArrayObject); + mVertexArrayMap.erase(iter); + mVertexArrayHandleAllocator.release(vertexArray); } } @@ -371,10 +517,15 @@ void Context::deleteTransformFeedback(GLuint transformFeedback) auto iter = mTransformFeedbackMap.find(transformFeedback); if (iter != mTransformFeedbackMap.end()) { - detachTransformFeedback(transformFeedback); - mTransformFeedbackAllocator.release(transformFeedback); - iter->second->release(); + TransformFeedback *transformFeedbackObject = iter->second; + if (transformFeedbackObject != nullptr) + { + detachTransformFeedback(transformFeedback); + transformFeedbackObject->release(); + } + mTransformFeedbackMap.erase(iter); + mTransformFeedbackAllocator.release(transformFeedback); } } @@ -418,7 +569,7 @@ void Context::deleteQuery(GLuint query) } } -Buffer *Context::getBuffer(GLuint handle) +Buffer *Context::getBuffer(GLuint handle) const { return mResourceManager->getBuffer(handle); } @@ -438,28 +589,20 @@ Texture *Context::getTexture(GLuint handle) const return mResourceManager->getTexture(handle); } -Renderbuffer *Context::getRenderbuffer(GLuint handle) +Renderbuffer *Context::getRenderbuffer(GLuint handle) const { return mResourceManager->getRenderbuffer(handle); } FenceSync *Context::getFenceSync(GLsync handle) const { - return mResourceManager->getFenceSync(reinterpret_cast(handle)); + return mResourceManager->getFenceSync(static_cast(reinterpret_cast(handle))); } VertexArray *Context::getVertexArray(GLuint handle) const { auto vertexArray = mVertexArrayMap.find(handle); - - if (vertexArray == mVertexArrayMap.end()) - { - return NULL; - } - else - { - return vertexArray->second; - } + return (vertexArray != mVertexArrayMap.end()) ? vertexArray->second : nullptr; } Sampler *Context::getSampler(GLuint handle) const @@ -469,17 +612,45 @@ Sampler *Context::getSampler(GLuint handle) const TransformFeedback *Context::getTransformFeedback(GLuint handle) const { - if (handle == 0) - { - return mTransformFeedbackZero.get(); - } - else + auto iter = mTransformFeedbackMap.find(handle); + return (iter != mTransformFeedbackMap.end()) ? iter->second : nullptr; +} + +LabeledObject *Context::getLabeledObject(GLenum identifier, GLuint name) const +{ + switch (identifier) { - TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(handle); - return (iter != mTransformFeedbackMap.end()) ? iter->second : NULL; + case GL_BUFFER: + return getBuffer(name); + case GL_SHADER: + return getShader(name); + case GL_PROGRAM: + return getProgram(name); + case GL_VERTEX_ARRAY: + return getVertexArray(name); + case GL_QUERY: + return getQuery(name); + case GL_TRANSFORM_FEEDBACK: + return getTransformFeedback(name); + case GL_SAMPLER: + return getSampler(name); + case GL_TEXTURE: + return getTexture(name); + case GL_RENDERBUFFER: + return getRenderbuffer(name); + case GL_FRAMEBUFFER: + return getFramebuffer(name); + default: + UNREACHABLE(); + return nullptr; } } +LabeledObject *Context::getLabeledObjectFromPtr(const void *ptr) const +{ + return getFenceSync(reinterpret_cast(const_cast(ptr))); +} + bool Context::isSampler(GLuint samplerName) const { return mResourceManager->isSampler(samplerName); @@ -518,24 +689,16 @@ void Context::bindTexture(GLenum target, GLuint handle) mState.setSamplerTexture(target, texture); } -void Context::bindReadFramebuffer(GLuint framebuffer) +void Context::bindReadFramebuffer(GLuint framebufferHandle) { - if (!getFramebuffer(framebuffer)) - { - mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer); - } - - mState.setReadFramebufferBinding(getFramebuffer(framebuffer)); + Framebuffer *framebuffer = checkFramebufferAllocation(framebufferHandle); + mState.setReadFramebufferBinding(framebuffer); } -void Context::bindDrawFramebuffer(GLuint framebuffer) +void Context::bindDrawFramebuffer(GLuint framebufferHandle) { - if (!getFramebuffer(framebuffer)) - { - mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer); - } - - mState.setDrawFramebufferBinding(getFramebuffer(framebuffer)); + Framebuffer *framebuffer = checkFramebufferAllocation(framebufferHandle); + mState.setDrawFramebufferBinding(framebuffer); } void Context::bindRenderbuffer(GLuint renderbuffer) @@ -547,11 +710,7 @@ void Context::bindRenderbuffer(GLuint renderbuffer) void Context::bindVertexArray(GLuint vertexArray) { - if (!getVertexArray(vertexArray)) - { - VertexArray *vertexArrayObject = new VertexArray(mRenderer->createVertexArray(), vertexArray, MAX_VERTEX_ATTRIBS); - mVertexArrayMap[vertexArray] = vertexArrayObject; - } + checkVertexArrayAllocation(vertexArray); mState.setVertexArrayBinding(getVertexArray(vertexArray)); } @@ -582,14 +741,14 @@ void Context::bindGenericTransformFeedbackBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.setGenericTransformFeedbackBufferBinding(getBuffer(buffer)); + mState.getCurrentTransformFeedback()->bindGenericBuffer(getBuffer(buffer)); } void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) { mResourceManager->checkBufferAllocation(buffer); - mState.setIndexedTransformFeedbackBufferBinding(index, getBuffer(buffer), offset, size); + mState.getCurrentTransformFeedback()->bindIndexedBuffer(index, getBuffer(buffer), offset, size); } void Context::bindCopyReadBuffer(GLuint buffer) @@ -627,6 +786,8 @@ void Context::useProgram(GLuint program) void Context::bindTransformFeedback(GLuint transformFeedback) { + checkTransformFeedbackAllocation(transformFeedback); + mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback)); } @@ -661,37 +822,68 @@ Error Context::endQuery(GLenum target) return error; } -void Context::setFramebufferZero(Framebuffer *buffer) +Error Context::queryCounter(GLuint id, GLenum target) { - // First, check to see if the old default framebuffer - // was set for draw or read framebuffer, and change - // the bindings to point to the new one before deleting it. - if (mState.getDrawFramebuffer()->id() == 0) - { - mState.setDrawFramebufferBinding(buffer); - } + ASSERT(target == GL_TIMESTAMP_EXT); + + Query *queryObject = getQuery(id, true, target); + ASSERT(queryObject); + + return queryObject->queryCounter(); +} - if (mState.getReadFramebuffer()->id() == 0) +void Context::getQueryiv(GLenum target, GLenum pname, GLint *params) +{ + switch (pname) { - mState.setReadFramebufferBinding(buffer); + case GL_CURRENT_QUERY_EXT: + params[0] = getState().getActiveQueryId(target); + break; + case GL_QUERY_COUNTER_BITS_EXT: + switch (target) + { + case GL_TIME_ELAPSED_EXT: + params[0] = getExtensions().queryCounterBitsTimeElapsed; + break; + case GL_TIMESTAMP_EXT: + params[0] = getExtensions().queryCounterBitsTimestamp; + break; + default: + UNREACHABLE(); + params[0] = 0; + break; + } + break; + default: + UNREACHABLE(); + return; } +} - delete mFramebufferMap[0]; - mFramebufferMap[0] = buffer; +Error Context::getQueryObjectiv(GLuint id, GLenum pname, GLint *params) +{ + return GetQueryObjectParameter(this, id, pname, params); } -Framebuffer *Context::getFramebuffer(unsigned int handle) const +Error Context::getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params) { - FramebufferMap::const_iterator framebuffer = mFramebufferMap.find(handle); + return GetQueryObjectParameter(this, id, pname, params); +} - if (framebuffer == mFramebufferMap.end()) - { - return NULL; - } - else - { - return framebuffer->second; - } +Error Context::getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params) +{ + return GetQueryObjectParameter(this, id, pname, params); +} + +Error Context::getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params) +{ + return GetQueryObjectParameter(this, id, pname, params); +} + +Framebuffer *Context::getFramebuffer(unsigned int handle) const +{ + auto framebufferIt = mFramebufferMap.find(handle); + return ((framebufferIt == mFramebufferMap.end()) ? nullptr : framebufferIt->second); } FenceNV *Context::getFenceNV(unsigned int handle) @@ -727,11 +919,16 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type) } } +Query *Context::getQuery(GLuint handle) const +{ + auto iter = mQueryMap.find(handle); + return (iter != mQueryMap.end()) ? iter->second : nullptr; +} + Texture *Context::getTargetTexture(GLenum target) const { ASSERT(ValidTextureTarget(this, target)); - - return getSamplerTexture(mState.getActiveSampler(), target); + return mState.getTargetTexture(target); } Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const @@ -774,6 +971,9 @@ void Context::getFloatv(GLenum pname, GLfloat *params) ASSERT(mExtensions.textureFilterAnisotropic); *params = mExtensions.maxTextureAnisotropy; break; + case GL_MAX_TEXTURE_LOD_BIAS: + *params = mCaps.maxLODBias; + break; default: mState.getFloatv(pname, params); break; @@ -796,7 +996,7 @@ void Context::getIntegerv(GLenum pname, GLint *params) case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxVertexTextureImageUnits; break; case GL_MAX_TEXTURE_IMAGE_UNITS: *params = mCaps.maxTextureImageUnits; break; case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mCaps.maxFragmentUniformVectors; break; - case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mCaps.maxFragmentInputComponents; break; + case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mCaps.maxFragmentUniformComponents; break; case GL_MAX_RENDERBUFFER_SIZE: *params = mCaps.maxRenderbufferSize; break; case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mCaps.maxColorAttachments; break; case GL_MAX_DRAW_BUFFERS_EXT: *params = mCaps.maxDrawBuffers; break; @@ -811,6 +1011,10 @@ void Context::getIntegerv(GLenum pname, GLint *params) case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mCaps.maxVertexUniformBlocks; break; case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mCaps.maxFragmentUniformBlocks; break; case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = mCaps.maxCombinedTextureImageUnits; break; + case GL_MAX_VERTEX_OUTPUT_COMPONENTS: *params = mCaps.maxVertexOutputComponents; break; + case GL_MAX_FRAGMENT_INPUT_COMPONENTS: *params = mCaps.maxFragmentInputComponents; break; + case GL_MIN_PROGRAM_TEXEL_OFFSET: *params = mCaps.minProgramTexelOffset; break; + case GL_MAX_PROGRAM_TEXEL_OFFSET: *params = mCaps.maxProgramTexelOffset; break; case GL_MAJOR_VERSION: *params = mClientVersion; break; case GL_MINOR_VERSION: *params = 0; break; case GL_MAX_ELEMENTS_INDICES: *params = mCaps.maxElementsIndices; break; @@ -818,8 +1022,10 @@ void Context::getIntegerv(GLenum pname, GLint *params) case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mCaps.maxTransformFeedbackInterleavedComponents; break; case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mCaps.maxTransformFeedbackSeparateAttributes; break; case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mCaps.maxTransformFeedbackSeparateComponents; break; - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = mCaps.compressedTextureFormats.size(); break; - case GL_MAX_SAMPLES_ANGLE: *params = mExtensions.maxSamples; break; + case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + *params = static_cast(mCaps.compressedTextureFormats.size()); + break; + case GL_MAX_SAMPLES_ANGLE: *params = mCaps.maxSamples; break; case GL_MAX_VIEWPORT_DIMS: { params[0] = mCaps.maxViewportWidth; @@ -833,13 +1039,13 @@ void Context::getIntegerv(GLenum pname, GLint *params) *params = mResetStrategy; break; case GL_NUM_SHADER_BINARY_FORMATS: - *params = mCaps.shaderBinaryFormats.size(); + *params = static_cast(mCaps.shaderBinaryFormats.size()); break; case GL_SHADER_BINARY_FORMATS: std::copy(mCaps.shaderBinaryFormats.begin(), mCaps.shaderBinaryFormats.end(), params); break; case GL_NUM_PROGRAM_BINARY_FORMATS: - *params = mCaps.programBinaryFormats.size(); + *params = static_cast(mCaps.programBinaryFormats.size()); break; case GL_PROGRAM_BINARY_FORMATS: std::copy(mCaps.programBinaryFormats.begin(), mCaps.programBinaryFormats.end(), params); @@ -847,6 +1053,26 @@ void Context::getIntegerv(GLenum pname, GLint *params) case GL_NUM_EXTENSIONS: *params = static_cast(mExtensionStrings.size()); break; + + // GL_KHR_debug + case GL_MAX_DEBUG_MESSAGE_LENGTH: + *params = mExtensions.maxDebugMessageLength; + break; + case GL_MAX_DEBUG_LOGGED_MESSAGES: + *params = mExtensions.maxDebugLoggedMessages; + break; + case GL_MAX_DEBUG_GROUP_STACK_DEPTH: + *params = mExtensions.maxDebugGroupStackDepth; + break; + case GL_MAX_LABEL_LENGTH: + *params = mExtensions.maxLabelLength; + break; + + // GL_EXT_disjoint_timer_query + case GL_GPU_DISJOINT_EXT: + *params = mRenderer->getGPUDisjoint(); + break; + default: mState.getIntegerv(getData(), pname, params); break; @@ -874,17 +1100,27 @@ void Context::getInteger64v(GLenum pname, GLint64 *params) case GL_MAX_SERVER_WAIT_TIMEOUT: *params = mCaps.maxServerWaitTimeout; break; + + // GL_EXT_disjoint_timer_query + case GL_TIMESTAMP_EXT: + *params = mRenderer->getTimestamp(); + break; default: UNREACHABLE(); break; } } +void Context::getPointerv(GLenum pname, void **params) const +{ + mState.getPointerv(pname, params); +} + bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) { // Queries about context capabilities and maximums are answered by Context. // Queries about current GL state values are answered by State. - // Indexed integer queries all refer to current state, so this function is a + // Indexed integer queries all refer to current state, so this function is a // mere passthrough. return mState.getIndexedIntegerv(target, index, data); } @@ -893,7 +1129,7 @@ bool Context::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) { // Queries about context capabilities and maximums are answered by Context. // Queries about current GL state values are answered by State. - // Indexed integer queries all refer to current state, so this function is a + // Indexed integer queries all refer to current state, so this function is a // mere passthrough. return mState.getIndexedInteger64v(target, index, data); } @@ -919,19 +1155,19 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_COMPRESSED_TEXTURE_FORMATS: { *type = GL_INT; - *numParams = mCaps.compressedTextureFormats.size(); + *numParams = static_cast(mCaps.compressedTextureFormats.size()); } return true; case GL_PROGRAM_BINARY_FORMATS_OES: { *type = GL_INT; - *numParams = mCaps.programBinaryFormats.size(); + *numParams = static_cast(mCaps.programBinaryFormats.size()); } return true; case GL_SHADER_BINARY_FORMATS: { *type = GL_INT; - *numParams = mCaps.shaderBinaryFormats.size(); + *numParams = static_cast(mCaps.shaderBinaryFormats.size()); } return true; @@ -1019,20 +1255,6 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu } } return true; - case GL_PIXEL_PACK_BUFFER_BINDING: - case GL_PIXEL_UNPACK_BUFFER_BINDING: - { - if (mExtensions.pixelBufferObject) - { - *type = GL_INT; - *numParams = 1; - } - else - { - return false; - } - } - return true; case GL_MAX_VIEWPORT_DIMS: { *type = GL_INT; @@ -1103,6 +1325,87 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu *type = GL_FLOAT; *numParams = 1; return true; + case GL_TIMESTAMP_EXT: + if (!mExtensions.disjointTimerQuery) + { + return false; + } + *type = GL_INT_64_ANGLEX; + *numParams = 1; + return true; + case GL_GPU_DISJOINT_EXT: + if (!mExtensions.disjointTimerQuery) + { + return false; + } + *type = GL_INT; + *numParams = 1; + return true; + } + + if (mExtensions.debug) + { + switch (pname) + { + case GL_DEBUG_LOGGED_MESSAGES: + case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH: + case GL_DEBUG_GROUP_STACK_DEPTH: + case GL_MAX_DEBUG_MESSAGE_LENGTH: + case GL_MAX_DEBUG_LOGGED_MESSAGES: + case GL_MAX_DEBUG_GROUP_STACK_DEPTH: + case GL_MAX_LABEL_LENGTH: + *type = GL_INT; + *numParams = 1; + return true; + + case GL_DEBUG_OUTPUT_SYNCHRONOUS: + case GL_DEBUG_OUTPUT: + *type = GL_BOOL; + *numParams = 1; + return true; + } + } + + // Check for ES3.0+ parameter names which are also exposed as ES2 extensions + switch (pname) + { + case GL_PACK_ROW_LENGTH: + case GL_PACK_SKIP_ROWS: + case GL_PACK_SKIP_PIXELS: + if ((mClientVersion < 3) && !mExtensions.packSubimage) + { + return false; + } + *type = GL_INT; + *numParams = 1; + return true; + case GL_UNPACK_ROW_LENGTH: + case GL_UNPACK_SKIP_ROWS: + case GL_UNPACK_SKIP_PIXELS: + if ((mClientVersion < 3) && !mExtensions.unpackSubimage) + { + return false; + } + *type = GL_INT; + *numParams = 1; + return true; + case GL_VERTEX_ARRAY_BINDING: + if ((mClientVersion < 3) && !mExtensions.vertexArrayObject) + { + return false; + } + *type = GL_INT; + *numParams = 1; + return true; + case GL_PIXEL_PACK_BUFFER_BINDING: + case GL_PIXEL_UNPACK_BUFFER_BINDING: + if ((mClientVersion < 3) && !mExtensions.pixelBufferObject) + { + return false; + } + *type = GL_INT; + *numParams = 1; + return true; } if (mClientVersion < 3) @@ -1117,6 +1420,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: case GL_UNIFORM_BUFFER_BINDING: case GL_TRANSFORM_FEEDBACK_BINDING: + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: case GL_COPY_READ_BUFFER_BINDING: case GL_COPY_WRITE_BUFFER_BINDING: case GL_TEXTURE_BINDING_3D: @@ -1126,10 +1430,13 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_MAX_VERTEX_UNIFORM_BLOCKS: case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: case GL_MAX_COMBINED_UNIFORM_BLOCKS: + case GL_MAX_VERTEX_OUTPUT_COMPONENTS: + case GL_MAX_FRAGMENT_INPUT_COMPONENTS: case GL_MAX_VARYING_COMPONENTS: - case GL_VERTEX_ARRAY_BINDING: case GL_MAX_VERTEX_UNIFORM_COMPONENTS: case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: + case GL_MIN_PROGRAM_TEXEL_OFFSET: + case GL_MAX_PROGRAM_TEXEL_OFFSET: case GL_NUM_EXTENSIONS: case GL_MAJOR_VERSION: case GL_MINOR_VERSION: @@ -1138,6 +1445,8 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: + case GL_UNPACK_IMAGE_HEIGHT: + case GL_UNPACK_SKIP_IMAGES: { *type = GL_INT; *numParams = 1; @@ -1157,11 +1466,20 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_TRANSFORM_FEEDBACK_ACTIVE: case GL_TRANSFORM_FEEDBACK_PAUSED: + case GL_PRIMITIVE_RESTART_FIXED_INDEX: + case GL_RASTERIZER_DISCARD: { *type = GL_BOOL; *numParams = 1; } return true; + + case GL_MAX_TEXTURE_LOD_BIAS: + { + *type = GL_FLOAT; + *numParams = 1; + } + return true; } return false; @@ -1196,16 +1514,67 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned return false; } -Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) +Error Context::drawArrays(GLenum mode, GLint first, GLsizei count) { - return mRenderer->drawArrays(getData(), mode, first, count, instances); + syncRendererState(); + Error error = mRenderer->drawArrays(getData(), mode, first, count); + if (error.isError()) + { + return error; + } + + MarkTransformFeedbackBufferUsage(mState.getCurrentTransformFeedback()); + + return Error(GL_NO_ERROR); } -Error Context::drawElements(GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const rx::RangeUI &indexRange) +Error Context::drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) { - return mRenderer->drawElements(getData(), mode, count, type, indices, instances, indexRange); + syncRendererState(); + Error error = mRenderer->drawArraysInstanced(getData(), mode, first, count, instanceCount); + if (error.isError()) + { + return error; + } + + MarkTransformFeedbackBufferUsage(mState.getCurrentTransformFeedback()); + + return Error(GL_NO_ERROR); +} + +Error Context::drawElements(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const IndexRange &indexRange) +{ + syncRendererState(); + return mRenderer->drawElements(getData(), mode, count, type, indices, indexRange); +} + +Error Context::drawElementsInstanced(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const IndexRange &indexRange) +{ + syncRendererState(); + return mRenderer->drawElementsInstanced(getData(), mode, count, type, indices, instances, + indexRange); +} + +Error Context::drawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const IndexRange &indexRange) +{ + syncRendererState(); + return mRenderer->drawRangeElements(getData(), mode, start, end, count, type, indices, + indexRange); } Error Context::flush() @@ -1218,11 +1587,36 @@ Error Context::finish() return mRenderer->finish(); } +void Context::insertEventMarker(GLsizei length, const char *marker) +{ + ASSERT(mRenderer); + mRenderer->insertEventMarker(length, marker); +} + +void Context::pushGroupMarker(GLsizei length, const char *marker) +{ + ASSERT(mRenderer); + mRenderer->pushGroupMarker(length, marker); +} + +void Context::popGroupMarker() +{ + ASSERT(mRenderer); + mRenderer->popGroupMarker(); +} + void Context::recordError(const Error &error) { if (error.isError()) { mErrors.insert(error.getCode()); + + if (!error.getMessage().empty()) + { + auto &debug = mState.getDebug(); + debug.insertMessage(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_ERROR, error.getID(), + GL_DEBUG_SEVERITY_HIGH, error.getMessage()); + } } } @@ -1275,14 +1669,9 @@ bool Context::isResetNotificationEnabled() return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT); } -int Context::getClientVersion() const +const egl::Config *Context::getConfig() const { - return mClientVersion; -} - -EGLint Context::getConfigID() const -{ - return mConfigID; + return mConfig; } EGLenum Context::getClientType() const @@ -1292,22 +1681,73 @@ EGLenum Context::getClientType() const EGLenum Context::getRenderBuffer() const { - return mRenderBuffer; + auto framebufferIt = mFramebufferMap.find(0); + if (framebufferIt != mFramebufferMap.end()) + { + const Framebuffer *framebuffer = framebufferIt->second; + const FramebufferAttachment *backAttachment = framebuffer->getAttachment(GL_BACK); + + ASSERT(backAttachment != nullptr); + return backAttachment->getSurface()->getRenderBuffer(); + } + else + { + return EGL_NONE; + } +} + +void Context::checkVertexArrayAllocation(GLuint vertexArray) +{ + // Only called after a prior call to Gen. + if (!getVertexArray(vertexArray)) + { + VertexArray *vertexArrayObject = + new VertexArray(mRenderer, vertexArray, MAX_VERTEX_ATTRIBS); + mVertexArrayMap[vertexArray] = vertexArrayObject; + } +} + +void Context::checkTransformFeedbackAllocation(GLuint transformFeedback) +{ + // Only called after a prior call to Gen. + if (!getTransformFeedback(transformFeedback)) + { + TransformFeedback *transformFeedbackObject = + new TransformFeedback(mRenderer->createTransformFeedback(), transformFeedback, mCaps); + transformFeedbackObject->addRef(); + mTransformFeedbackMap[transformFeedback] = transformFeedbackObject; + } } -const Caps &Context::getCaps() const +Framebuffer *Context::checkFramebufferAllocation(GLuint framebuffer) { - return mCaps; + // Can be called from Bind without a prior call to Gen. + auto framebufferIt = mFramebufferMap.find(framebuffer); + bool neverCreated = framebufferIt == mFramebufferMap.end(); + if (neverCreated || framebufferIt->second == nullptr) + { + Framebuffer *newFBO = new Framebuffer(mCaps, mRenderer, framebuffer); + if (neverCreated) + { + mFramebufferHandleAllocator.reserve(framebuffer); + mFramebufferMap[framebuffer] = newFBO; + return newFBO; + } + + framebufferIt->second = newFBO; + } + + return framebufferIt->second; } -const TextureCapsMap &Context::getTextureCaps() const +bool Context::isVertexArrayGenerated(GLuint vertexArray) { - return mTextureCaps; + return mVertexArrayMap.find(vertexArray) != mVertexArrayMap.end(); } -const Extensions &Context::getExtensions() const +bool Context::isTransformFeedbackGenerated(GLuint transformFeedback) { - return mExtensions; + return mTransformFeedbackMap.find(transformFeedback) != mTransformFeedbackMap.end(); } void Context::detachTexture(GLuint texture) @@ -1321,20 +1761,15 @@ void Context::detachTexture(GLuint texture) void Context::detachBuffer(GLuint buffer) { - // Buffer detachment is handled by Context, because the buffer must also be - // attached from any VAOs in existence, and Context holds the VAO map. + // Simple pass-through to State's detachBuffer method, since + // only buffer attachments to container objects that are bound to the current context + // should be detached. And all those are available in State. - // [OpenGL ES 2.0.24] section 2.9 page 22: - // If a buffer object is deleted while it is bound, all bindings to that object in the current context - // (i.e. in the thread that called Delete-Buffers) are reset to zero. - - mState.removeArrayBufferBinding(buffer); - - // mark as freed among the vertex array objects - for (auto vaoIt = mVertexArrayMap.begin(); vaoIt != mVertexArrayMap.end(); vaoIt++) - { - vaoIt->second->detachBuffer(buffer); - } + // [OpenGL ES 3.2] section 5.1.2 page 45: + // Attachments to unbound container objects, such as + // deletion of a buffer attached to a vertex array object which is not bound to the context, + // are not affected and continue to act as references on the deleted object + mState.detachBuffer(buffer); } void Context::detachFramebuffer(GLuint framebuffer) @@ -1365,8 +1800,8 @@ void Context::detachRenderbuffer(GLuint renderbuffer) void Context::detachVertexArray(GLuint vertexArray) { - // Vertex array detachment is handled by Context, because 0 is a valid - // VAO, and a pointer to it must be passed from Context to State at + // Vertex array detachment is handled by Context, because 0 is a valid + // VAO, and a pointer to it must be passed from Context to State at // binding time. // [OpenGL ES 3.0.2] section 2.10 page 43: @@ -1390,7 +1825,7 @@ void Context::detachSampler(GLuint sampler) void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) { - mState.getVertexArray()->setVertexAttribDivisor(index, divisor); + mState.setVertexAttribDivisor(index, divisor); } void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) @@ -1400,19 +1835,22 @@ void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) Sampler *samplerObject = getSampler(sampler); ASSERT(samplerObject); + // clang-format off switch (pname) { - case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast(param)); break; - case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast(param)); break; - case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast(param)); break; - case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast(param)); break; - case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast(param)); break; - case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast(param)); break; - case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast(param)); break; - case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(static_cast(param)); break; - case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(static_cast(param)); break; - default: UNREACHABLE(); break; + case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast(param)); break; + case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast(param)); break; + case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast(param)); break; + case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast(param)); break; + case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: samplerObject->setMaxAnisotropy(std::min(static_cast(param), getExtensions().maxTextureAnisotropy)); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast(param)); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast(param)); break; + case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(static_cast(param)); break; + case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(static_cast(param)); break; + default: UNREACHABLE(); break; } + // clang-format on } void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) @@ -1422,19 +1860,22 @@ void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) Sampler *samplerObject = getSampler(sampler); ASSERT(samplerObject); + // clang-format off switch (pname) { - case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(uiround(param)); break; - case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(uiround(param)); break; - case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(uiround(param)); break; - case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(uiround(param)); break; - case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(uiround(param)); break; - case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; - case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; - case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(uiround(param)); break; - case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(uiround(param)); break; - default: UNREACHABLE(); break; + case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(uiround(param)); break; + case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(uiround(param)); break; + case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(uiround(param)); break; + case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(uiround(param)); break; + case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(uiround(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: samplerObject->setMaxAnisotropy(std::min(param, getExtensions().maxTextureAnisotropy)); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; + case GL_TEXTURE_COMPARE_MODE: samplerObject->setCompareMode(uiround(param)); break; + case GL_TEXTURE_COMPARE_FUNC: samplerObject->setCompareFunc(uiround(param)); break; + default: UNREACHABLE(); break; } + // clang-format on } GLint Context::getSamplerParameteri(GLuint sampler, GLenum pname) @@ -1444,19 +1885,22 @@ GLint Context::getSamplerParameteri(GLuint sampler, GLenum pname) Sampler *samplerObject = getSampler(sampler); ASSERT(samplerObject); + // clang-format off switch (pname) { - case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); - case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); - case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); - case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); - case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); - case GL_TEXTURE_MIN_LOD: return uiround(samplerObject->getMinLod()); - case GL_TEXTURE_MAX_LOD: return uiround(samplerObject->getMaxLod()); - case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); - case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); - default: UNREACHABLE(); return 0; + case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); + case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); + case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); + case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); + case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); + case GL_TEXTURE_MAX_ANISOTROPY_EXT: return static_cast(samplerObject->getMaxAnisotropy()); + case GL_TEXTURE_MIN_LOD: return uiround(samplerObject->getMinLod()); + case GL_TEXTURE_MAX_LOD: return uiround(samplerObject->getMaxLod()); + case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getCompareMode()); + case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getCompareFunc()); + default: UNREACHABLE(); return 0; } + // clang-format on } GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname) @@ -1466,19 +1910,22 @@ GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname) Sampler *samplerObject = getSampler(sampler); ASSERT(samplerObject); + // clang-format off switch (pname) { - case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); - case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); - case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); - case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); - case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); - case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod(); - case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod(); - case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); - case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); - default: UNREACHABLE(); return 0; + case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); + case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); + case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); + case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); + case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); + case GL_TEXTURE_MAX_ANISOTROPY_EXT: return samplerObject->getMaxAnisotropy(); + case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod(); + case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod(); + case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getCompareMode()); + case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getCompareFunc()); + default: UNREACHABLE(); return 0; } + // clang-format on } void Context::initRendererString() @@ -1526,6 +1973,8 @@ void Context::initCaps(GLuint clientVersion) mExtensions = mRenderer->getRendererExtensions(); + mLimitations = mRenderer->getRendererLimitations(); + if (clientVersion < 3) { // Disable ES3+ extensions @@ -1538,6 +1987,13 @@ void Context::initCaps(GLuint clientVersion) //mExtensions.sRGB = false; } + // Explicitly enable GL_KHR_debug + mExtensions.debug = true; + mExtensions.maxDebugMessageLength = 1024; + mExtensions.maxDebugLoggedMessages = 1024; + mExtensions.maxDebugGroupStackDepth = 1024; + mExtensions.maxLabelLength = 1024; + // Apply implementation limits mCaps.maxVertexAttributes = std::min(mCaps.maxVertexAttributes, MAX_VERTEX_ATTRIBS); mCaps.maxVertexUniformBlocks = std::min(mCaps.maxVertexUniformBlocks, IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS); @@ -1545,7 +2001,6 @@ void Context::initCaps(GLuint clientVersion) mCaps.maxFragmentInputComponents = std::min(mCaps.maxFragmentInputComponents, IMPLEMENTATION_MAX_VARYING_VECTORS * 4); - GLuint maxSamples = 0; mCaps.compressedTextureFormats.clear(); const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps(); @@ -1556,17 +2011,21 @@ void Context::initCaps(GLuint clientVersion) const InternalFormat &formatInfo = GetInternalFormatInfo(format); - // Update the format caps based on the client version and extensions - formatCaps.texturable = formatInfo.textureSupport(clientVersion, mExtensions); - formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions); - formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions); + // Update the format caps based on the client version and extensions. + // Caps are AND'd with the renderer caps because some core formats are still unsupported in + // ES3. + formatCaps.texturable = + formatCaps.texturable && formatInfo.textureSupport(clientVersion, mExtensions); + formatCaps.renderable = + formatCaps.renderable && formatInfo.renderSupport(clientVersion, mExtensions); + formatCaps.filterable = + formatCaps.filterable && formatInfo.filterSupport(clientVersion, mExtensions); // OpenGL ES does not support multisampling with integer formats if (!formatInfo.renderSupport || formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT) { formatCaps.sampleCounts.clear(); } - maxSamples = std::max(maxSamples, formatCaps.getMaxSamples()); if (formatCaps.texturable && formatInfo.compressed) { @@ -1575,13 +2034,391 @@ void Context::initCaps(GLuint clientVersion) mTextureCaps.insert(format, formatCaps); } +} + +void Context::syncRendererState() +{ + const State::DirtyBits &dirtyBits = mState.getDirtyBits(); + mRenderer->syncState(mState, dirtyBits); + mState.clearDirtyBits(); + mState.syncDirtyObjects(); +} + +void Context::syncRendererState(const State::DirtyBits &bitMask) +{ + const State::DirtyBits &dirtyBits = (mState.getDirtyBits() & bitMask); + mRenderer->syncState(mState, dirtyBits); + mState.clearDirtyBits(dirtyBits); + + // TODO(jmadill): Filter objects by bitMask somehow? + mState.syncDirtyObjects(); +} + +void Context::blitFramebuffer(GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter) +{ + Framebuffer *readFramebuffer = mState.getReadFramebuffer(); + ASSERT(readFramebuffer); + + Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); + ASSERT(drawFramebuffer); + + Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); + Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); + + syncRendererState(mState.blitStateBitMask()); + + Error error = drawFramebuffer->blit(mState, srcArea, dstArea, mask, filter, readFramebuffer); + if (error.isError()) + { + recordError(error); + return; + } +} + +void Context::clear(GLbitfield mask) +{ + // Sync the clear state + syncRendererState(mState.clearStateBitMask()); + + Error error = mState.getDrawFramebuffer()->clear(mData, mask); + if (error.isError()) + { + recordError(error); + } +} + +void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values) +{ + // Sync the clear state + syncRendererState(mState.clearStateBitMask()); + + Error error = mState.getDrawFramebuffer()->clearBufferfv(mData, buffer, drawbuffer, values); + if (error.isError()) + { + recordError(error); + } +} + +void Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values) +{ + // Sync the clear state + syncRendererState(mState.clearStateBitMask()); + + Error error = mState.getDrawFramebuffer()->clearBufferuiv(mData, buffer, drawbuffer, values); + if (error.isError()) + { + recordError(error); + } +} + +void Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values) +{ + // Sync the clear state + syncRendererState(mState.clearStateBitMask()); + + Error error = mState.getDrawFramebuffer()->clearBufferiv(mData, buffer, drawbuffer, values); + if (error.isError()) + { + recordError(error); + } +} + +void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +{ + Framebuffer *framebufferObject = mState.getDrawFramebuffer(); + ASSERT(framebufferObject); + + // If a buffer is not present, the clear has no effect + if (framebufferObject->getDepthbuffer() == nullptr && + framebufferObject->getStencilbuffer() == nullptr) + { + return; + } + + // Sync the clear state + syncRendererState(mState.clearStateBitMask()); + + Error error = framebufferObject->clearBufferfi(mData, buffer, drawbuffer, depth, stencil); + if (error.isError()) + { + recordError(error); + } +} + +void Context::readPixels(GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLvoid *pixels) +{ + // Sync pack state + syncRendererState(mState.packStateBitMask()); + + Framebuffer *framebufferObject = mState.getReadFramebuffer(); + ASSERT(framebufferObject); + + Rectangle area(x, y, width, height); + Error error = framebufferObject->readPixels(mState, area, format, type, pixels); + if (error.isError()) + { + recordError(error); + } +} + +void Context::copyTexImage2D(GLenum target, + GLint level, + GLenum internalformat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) +{ + // Only sync the read FBO + mState.syncDirtyObject(GL_READ_FRAMEBUFFER); + + Rectangle sourceArea(x, y, width, height); + + const Framebuffer *framebuffer = mState.getReadFramebuffer(); + Texture *texture = + getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->copyImage(target, level, sourceArea, internalformat, framebuffer); + if (error.isError()) + { + recordError(error); + } +} + +void Context::copyTexSubImage2D(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + // Only sync the read FBO + mState.syncDirtyObject(GL_READ_FRAMEBUFFER); + + Offset destOffset(xoffset, yoffset, 0); + Rectangle sourceArea(x, y, width, height); + + const Framebuffer *framebuffer = mState.getReadFramebuffer(); + Texture *texture = + getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer); + if (error.isError()) + { + recordError(error); + } +} + +void Context::copyTexSubImage3D(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + // Only sync the read FBO + mState.syncDirtyObject(GL_READ_FRAMEBUFFER); + + Offset destOffset(xoffset, yoffset, zoffset); + Rectangle sourceArea(x, y, width, height); + + const Framebuffer *framebuffer = mState.getReadFramebuffer(); + Texture *texture = getTargetTexture(target); + Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer); + if (error.isError()) + { + recordError(error); + } +} + +void Context::framebufferTexture2D(GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture, + GLint level) +{ + Framebuffer *framebuffer = mState.getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (texture != 0) + { + Texture *textureObj = getTexture(texture); + + ImageIndex index = ImageIndex::MakeInvalid(); + + if (textarget == GL_TEXTURE_2D) + { + index = ImageIndex::Make2D(level); + } + else + { + ASSERT(IsCubeMapTextureTarget(textarget)); + index = ImageIndex::MakeCube(textarget, level); + } + + framebuffer->setAttachment(GL_TEXTURE, attachment, index, textureObj); + } + else + { + framebuffer->resetAttachment(attachment); + } + + mState.setObjectDirty(target); +} + +void Context::framebufferRenderbuffer(GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer) +{ + Framebuffer *framebuffer = mState.getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (renderbuffer != 0) + { + Renderbuffer *renderbufferObject = getRenderbuffer(renderbuffer); + framebuffer->setAttachment(GL_RENDERBUFFER, attachment, gl::ImageIndex::MakeInvalid(), + renderbufferObject); + } + else + { + framebuffer->resetAttachment(attachment); + } - mExtensions.maxSamples = maxSamples; + mState.setObjectDirty(target); } -Data Context::getData() const +void Context::framebufferTextureLayer(GLenum target, + GLenum attachment, + GLuint texture, + GLint level, + GLint layer) { - return Data(mClientVersion, mState, mCaps, mTextureCaps, mExtensions, mResourceManager); + Framebuffer *framebuffer = mState.getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (texture != 0) + { + Texture *textureObject = getTexture(texture); + + ImageIndex index = ImageIndex::MakeInvalid(); + + if (textureObject->getTarget() == GL_TEXTURE_3D) + { + index = ImageIndex::Make3D(level, layer); + } + else + { + ASSERT(textureObject->getTarget() == GL_TEXTURE_2D_ARRAY); + index = ImageIndex::Make2DArray(level, layer); + } + + framebuffer->setAttachment(GL_TEXTURE, attachment, index, textureObject); + } + else + { + framebuffer->resetAttachment(attachment); + } + + mState.setObjectDirty(target); +} + +void Context::drawBuffers(GLsizei n, const GLenum *bufs) +{ + Framebuffer *framebuffer = mState.getDrawFramebuffer(); + ASSERT(framebuffer); + framebuffer->setDrawBuffers(n, bufs); + mState.setObjectDirty(GL_DRAW_FRAMEBUFFER); } +void Context::readBuffer(GLenum mode) +{ + Framebuffer *readFBO = mState.getReadFramebuffer(); + readFBO->setReadBuffer(mode); + mState.setObjectDirty(GL_READ_FRAMEBUFFER); } + +void Context::discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments) +{ + // Only sync the FBO + mState.syncDirtyObject(target); + + Framebuffer *framebuffer = mState.getTargetFramebuffer(target); + ASSERT(framebuffer); + + // The specification isn't clear what should be done when the framebuffer isn't complete. + // We leave it up to the framebuffer implementation to decide what to do. + Error error = framebuffer->discard(numAttachments, attachments); + if (error.isError()) + { + recordError(error); + } +} + +void Context::invalidateFramebuffer(GLenum target, + GLsizei numAttachments, + const GLenum *attachments) +{ + // Only sync the FBO + mState.syncDirtyObject(target); + + Framebuffer *framebuffer = mState.getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (framebuffer->checkStatus(mData) == GL_FRAMEBUFFER_COMPLETE) + { + Error error = framebuffer->invalidate(numAttachments, attachments); + if (error.isError()) + { + recordError(error); + return; + } + } +} + +void Context::invalidateSubFramebuffer(GLenum target, + GLsizei numAttachments, + const GLenum *attachments, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + // Only sync the FBO + mState.syncDirtyObject(target); + + Framebuffer *framebuffer = mState.getTargetFramebuffer(target); + ASSERT(framebuffer); + + if (framebuffer->checkStatus(mData) == GL_FRAMEBUFFER_COMPLETE) + { + Rectangle area(x, y, width, height); + Error error = framebuffer->invalidateSub(numAttachments, attachments, area); + if (error.isError()) + { + recordError(error); + return; + } + } +} + +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/Context.h b/src/3rdparty/angle/src/libANGLE/Context.h index eeada43355..6b82eb7cb9 100644 --- a/src/3rdparty/angle/src/libANGLE/Context.h +++ b/src/3rdparty/angle/src/libANGLE/Context.h @@ -33,6 +33,7 @@ class Renderer; namespace egl { +class AttributeMap; class Surface; struct Config; } @@ -55,19 +56,23 @@ class VertexArray; class Sampler; class TransformFeedback; -class Context final : angle::NonCopyable +class Context final : public ValidationContext { public: - Context(const egl::Config *config, int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); + Context(const egl::Config *config, + const Context *shareContext, + rx::Renderer *renderer, + const egl::AttributeMap &attribs); virtual ~Context(); void makeCurrent(egl::Surface *surface); + void releaseSurface(); virtual void markContextLost(); bool isContextLost(); - // These create and destroy methods are merely pass-throughs to + // These create and destroy methods are merely pass-throughs to // ResourceManager, which owns these object types GLuint createBuffer(); GLuint createShader(GLenum type); @@ -94,7 +99,7 @@ class Context final : angle::NonCopyable // NV Fences are owned by the Context. GLuint createFenceNV(); void deleteFenceNV(GLuint fence); - + // Queries are owned by the Context; GLuint createQuery(); void deleteQuery(GLuint query); @@ -106,8 +111,8 @@ class Context final : angle::NonCopyable void bindArrayBuffer(GLuint buffer); void bindElementArrayBuffer(GLuint buffer); void bindTexture(GLenum target, GLuint handle); - void bindReadFramebuffer(GLuint framebuffer); - void bindDrawFramebuffer(GLuint framebuffer); + void bindReadFramebuffer(GLuint framebufferHandle); + void bindDrawFramebuffer(GLuint framebufferHandle); void bindRenderbuffer(GLuint renderbuffer); void bindVertexArray(GLuint vertexArray); void bindSampler(GLuint textureUnit, GLuint sampler); @@ -124,8 +129,12 @@ class Context final : angle::NonCopyable Error beginQuery(GLenum target, GLuint query); Error endQuery(GLenum target); - - void setFramebufferZero(Framebuffer *framebuffer); + Error queryCounter(GLuint id, GLenum target); + void getQueryiv(GLenum target, GLenum pname, GLint *params); + Error getQueryObjectiv(GLuint id, GLenum pname, GLint *params); + Error getQueryObjectuiv(GLuint id, GLenum pname, GLuint *params); + Error getQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params); + Error getQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params); void setVertexAttribDivisor(GLuint index, GLuint divisor); @@ -134,18 +143,21 @@ class Context final : angle::NonCopyable GLint getSamplerParameteri(GLuint sampler, GLenum pname); GLfloat getSamplerParameterf(GLuint sampler, GLenum pname); - Buffer *getBuffer(GLuint handle); + Buffer *getBuffer(GLuint handle) const; FenceNV *getFenceNV(GLuint handle); FenceSync *getFenceSync(GLsync handle) const; Shader *getShader(GLuint handle) const; Program *getProgram(GLuint handle) const; Texture *getTexture(GLuint handle) const; Framebuffer *getFramebuffer(GLuint handle) const; - Renderbuffer *getRenderbuffer(GLuint handle); + Renderbuffer *getRenderbuffer(GLuint handle) const; VertexArray *getVertexArray(GLuint handle) const; Sampler *getSampler(GLuint handle) const; Query *getQuery(GLuint handle, bool create, GLenum type); + Query *getQuery(GLuint handle) const; TransformFeedback *getTransformFeedback(GLuint handle) const; + LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const; + LabeledObject *getLabeledObjectFromPtr(const void *ptr) const; Texture *getTargetTexture(GLenum target) const; Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; @@ -154,10 +166,14 @@ class Context final : angle::NonCopyable bool isSampler(GLuint samplerName) const; + bool isVertexArrayGenerated(GLuint vertexArray); + bool isTransformFeedbackGenerated(GLuint vertexArray); + void getBooleanv(GLenum pname, GLboolean *params); void getFloatv(GLenum pname, GLfloat *params); void getIntegerv(GLenum pname, GLint *params); void getInteger64v(GLenum pname, GLint64 *params); + void getPointerv(GLenum pname, void **params) const; bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); @@ -165,29 +181,128 @@ class Context final : angle::NonCopyable bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams); bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams); - Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); - Error drawElements(GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const rx::RangeUI &indexRange); + void clear(GLbitfield mask); + void clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values); + void clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values); + void clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values); + void clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + + Error drawArrays(GLenum mode, GLint first, GLsizei count); + Error drawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); + + Error drawElements(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const IndexRange &indexRange); + Error drawElementsInstanced(GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const IndexRange &indexRange); + Error drawRangeElements(GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const IndexRange &indexRange); + + void blitFramebuffer(GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter); + + void readPixels(GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLvoid *pixels); + + void copyTexImage2D(GLenum target, + GLint level, + GLenum internalformat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border); + + void copyTexSubImage2D(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height); + + void copyTexSubImage3D(GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height); + + void framebufferTexture2D(GLenum target, + GLenum attachment, + GLenum textarget, + GLuint texture, + GLint level); + + void framebufferRenderbuffer(GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer); + + void framebufferTextureLayer(GLenum target, + GLenum attachment, + GLuint texture, + GLint level, + GLint layer); + + void drawBuffers(GLsizei n, const GLenum *bufs); + void readBuffer(GLenum mode); + + void discardFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments); + void invalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments); + void invalidateSubFramebuffer(GLenum target, + GLsizei numAttachments, + const GLenum *attachments, + GLint x, + GLint y, + GLsizei width, + GLsizei height); + Error flush(); Error finish(); - void recordError(const Error &error); + void insertEventMarker(GLsizei length, const char *marker); + void pushGroupMarker(GLsizei length, const char *marker); + void popGroupMarker(); + + void recordError(const Error &error) override; GLenum getError(); GLenum getResetStatus(); virtual bool isResetNotificationEnabled(); - virtual int getClientVersion() const; - - EGLint getConfigID() const; + const egl::Config *getConfig() const; EGLenum getClientType() const; EGLenum getRenderBuffer() const; - const Caps &getCaps() const; - const TextureCapsMap &getTextureCaps() const; - const Extensions &getExtensions() const; - const std::string &getRendererString() const; const std::string &getExtensionString() const; @@ -197,11 +312,15 @@ class Context final : angle::NonCopyable rx::Renderer *getRenderer() { return mRenderer; } State &getState() { return mState; } - const State &getState() const { return mState; } - Data getData() const; + void syncRendererState(); + void syncRendererState(const State::DirtyBits &bitMask); private: + void checkVertexArrayAllocation(GLuint vertexArray); + void checkTransformFeedbackAllocation(GLuint transformFeedback); + Framebuffer *checkFramebufferAllocation(GLuint framebufferHandle); + void detachBuffer(GLuint buffer); void detachTexture(GLuint texture); void detachFramebuffer(GLuint framebuffer); @@ -219,6 +338,7 @@ class Context final : angle::NonCopyable Caps mCaps; TextureCapsMap mTextureCaps; Extensions mExtensions; + Limitations mLimitations; // Shader compiler Compiler *mCompiler; @@ -228,9 +348,8 @@ class Context final : angle::NonCopyable int mClientVersion; - EGLint mConfigID; + const egl::Config *mConfig; EGLenum mClientType; - EGLenum mRenderBuffer; TextureMap mZeroTextures; @@ -250,7 +369,6 @@ class Context final : angle::NonCopyable VertexArrayMap mVertexArrayMap; HandleAllocator mVertexArrayHandleAllocator; - BindingPointer mTransformFeedbackZero; typedef std::map TransformFeedbackMap; TransformFeedbackMap mTransformFeedbackMap; HandleAllocator mTransformFeedbackAllocator; @@ -269,9 +387,11 @@ class Context final : angle::NonCopyable GLenum mResetStatus; GLenum mResetStrategy; bool mRobustAccess; + egl::Surface *mCurrentSurface; ResourceManager *mResourceManager; }; -} + +} // namespace gl #endif // LIBANGLE_CONTEXT_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Data.cpp b/src/3rdparty/angle/src/libANGLE/Data.cpp index 7832e21b23..83f04b5a0b 100644 --- a/src/3rdparty/angle/src/libANGLE/Data.cpp +++ b/src/3rdparty/angle/src/libANGLE/Data.cpp @@ -12,40 +12,45 @@ namespace gl { -Data::Data(GLint clientVersionIn, const State &stateIn, const Caps &capsIn, - const TextureCapsMap &textureCapsIn, const Extensions &extensionsIn, - const ResourceManager *resourceManagerIn) - : clientVersion(clientVersionIn), +Data::Data(uintptr_t contextIn, + GLint clientVersionIn, + const State &stateIn, + const Caps &capsIn, + const TextureCapsMap &textureCapsIn, + const Extensions &extensionsIn, + const ResourceManager *resourceManagerIn, + const Limitations &limitationsIn) + : context(contextIn), + clientVersion(clientVersionIn), state(&stateIn), caps(&capsIn), textureCaps(&textureCapsIn), extensions(&extensionsIn), - resourceManager(resourceManagerIn) + resourceManager(resourceManagerIn), + limitations(&limitationsIn) {} Data::~Data() { } -Data::Data(const Data &other) - : clientVersion(other.clientVersion), - state(other.state), - caps(other.caps), - textureCaps(other.textureCaps), - extensions(other.extensions), - resourceManager(other.resourceManager) +ValidationContext::ValidationContext(GLint clientVersion, + const State &state, + const Caps &caps, + const TextureCapsMap &textureCaps, + const Extensions &extensions, + const ResourceManager *resourceManager, + const Limitations &limitations, + bool skipValidation) + : mData(reinterpret_cast(this), + clientVersion, + state, + caps, + textureCaps, + extensions, + resourceManager, + limitations), + mSkipValidation(skipValidation) { } - -Data &Data::operator=(const Data &other) -{ - clientVersion = other.clientVersion; - state = other.state; - caps = other.caps; - textureCaps = other.textureCaps; - extensions = other.extensions; - resourceManager = other.resourceManager; - return *this; -} - -} +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/Data.h b/src/3rdparty/angle/src/libANGLE/Data.h index 7eb6827dfc..f7230d74bc 100644 --- a/src/3rdparty/angle/src/libANGLE/Data.h +++ b/src/3rdparty/angle/src/libANGLE/Data.h @@ -9,28 +9,62 @@ #ifndef LIBANGLE_DATA_H_ #define LIBANGLE_DATA_H_ +#include "common/angleutils.h" #include "libANGLE/State.h" namespace gl { -struct Data final +struct Data final : public angle::NonCopyable { public: - Data(GLint clientVersion, const State &state, const Caps &caps, - const TextureCapsMap &textureCaps, const Extensions &extensions, - const ResourceManager *resourceManager); + Data(uintptr_t context, + GLint clientVersion, + const State &state, + const Caps &caps, + const TextureCapsMap &textureCaps, + const Extensions &extensions, + const ResourceManager *resourceManager, + const Limitations &limitations); ~Data(); - Data(const Data &other); - Data &operator=(const Data &other); - + uintptr_t context; GLint clientVersion; const State *state; const Caps *caps; const TextureCapsMap *textureCaps; const Extensions *extensions; const ResourceManager *resourceManager; + const Limitations *limitations; +}; + +class ValidationContext : angle::NonCopyable +{ + public: + ValidationContext(GLint clientVersion, + const State &state, + const Caps &caps, + const TextureCapsMap &textureCaps, + const Extensions &extensions, + const ResourceManager *resourceManager, + const Limitations &limitations, + bool skipValidation); + virtual ~ValidationContext() {} + + virtual void recordError(const Error &error) = 0; + + const Data &getData() const { return mData; } + int getClientVersion() const { return mData.clientVersion; } + const State &getState() const { return *mData.state; } + const Caps &getCaps() const { return *mData.caps; } + const TextureCapsMap &getTextureCaps() const { return *mData.textureCaps; } + const Extensions &getExtensions() const { return *mData.extensions; } + const Limitations &getLimitations() const { return *mData.limitations; } + bool skipValidation() const { return mSkipValidation; } + + protected: + Data mData; + bool mSkipValidation; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Debug.cpp b/src/3rdparty/angle/src/libANGLE/Debug.cpp new file mode 100644 index 0000000000..30321f4160 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Debug.cpp @@ -0,0 +1,303 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Debug.cpp: Defines debug state used for GL_KHR_debug + +#include "libANGLE/Debug.h" + +#include "common/debug.h" + +#include +#include + +namespace gl +{ + +Debug::Debug() + : mOutputEnabled(false), + mCallbackFunction(nullptr), + mCallbackUserParam(nullptr), + mMessages(), + mMaxLoggedMessages(0), + mOutputSynchronous(false), + mGroups() +{ + pushDefaultGroup(); +} + +void Debug::setMaxLoggedMessages(GLuint maxLoggedMessages) +{ + mMaxLoggedMessages = maxLoggedMessages; +} + +void Debug::setOutputEnabled(bool enabled) +{ + mOutputEnabled = enabled; +} + +bool Debug::isOutputEnabled() const +{ + return mOutputEnabled; +} + +void Debug::setOutputSynchronous(bool synchronous) +{ + mOutputSynchronous = synchronous; +} + +bool Debug::isOutputSynchronous() const +{ + return mOutputSynchronous; +} + +void Debug::setCallback(GLDEBUGPROCKHR callback, const void *userParam) +{ + mCallbackFunction = callback; + mCallbackUserParam = userParam; +} + +GLDEBUGPROCKHR Debug::getCallback() const +{ + return mCallbackFunction; +} + +const void *Debug::getUserParam() const +{ + return mCallbackUserParam; +} + +void Debug::insertMessage(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + const std::string &message) +{ + std::string messageCopy(message); + insertMessage(source, type, id, severity, std::move(messageCopy)); +} + +void Debug::insertMessage(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + std::string &&message) +{ + if (!isMessageEnabled(source, type, id, severity)) + { + return; + } + + if (mCallbackFunction != nullptr) + { + // TODO(geofflang) Check the synchronous flag and potentially flush messages from another + // thread. + mCallbackFunction(source, type, id, severity, static_cast(message.length()), + message.c_str(), mCallbackUserParam); + } + else + { + if (mMessages.size() >= mMaxLoggedMessages) + { + // Drop messages over the limit + return; + } + + Message m; + m.source = source; + m.type = type; + m.id = id; + m.severity = severity; + m.message = std::move(message); + + mMessages.push_back(std::move(m)); + } +} + +size_t Debug::getMessages(GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog) +{ + size_t messageCount = 0; + size_t messageStringIndex = 0; + while (messageCount <= count && !mMessages.empty()) + { + const Message &m = mMessages.front(); + + if (messageLog != nullptr) + { + // Check that this message can fit in the message buffer + if (messageStringIndex + m.message.length() + 1 > static_cast(bufSize)) + { + break; + } + + std::copy(m.message.begin(), m.message.end(), messageLog + messageStringIndex); + messageStringIndex += m.message.length(); + + messageLog[messageStringIndex] = '\0'; + messageStringIndex += 1; + } + + if (sources != nullptr) + { + sources[messageCount] = m.source; + } + + if (types != nullptr) + { + types[messageCount] = m.type; + } + + if (ids != nullptr) + { + ids[messageCount] = m.id; + } + + if (severities != nullptr) + { + severities[messageCount] = m.severity; + } + + if (lengths != nullptr) + { + lengths[messageCount] = static_cast(m.message.length()); + } + + mMessages.pop_front(); + + messageCount++; + } + + return messageCount; +} + +size_t Debug::getNextMessageLength() const +{ + return mMessages.empty() ? 0 : mMessages.front().message.length(); +} + +size_t Debug::getMessageCount() const +{ + return mMessages.size(); +} + +void Debug::setMessageControl(GLenum source, + GLenum type, + GLenum severity, + std::vector &&ids, + bool enabled) +{ + Control c; + c.source = source; + c.type = type; + c.severity = severity; + c.ids = std::move(ids); + c.enabled = enabled; + + auto &controls = mGroups.back().controls; + controls.push_back(std::move(c)); +} + +void Debug::pushGroup(GLenum source, GLuint id, std::string &&message) +{ + insertMessage(source, GL_DEBUG_TYPE_PUSH_GROUP, id, GL_DEBUG_SEVERITY_NOTIFICATION, + std::string(message)); + + Group g; + g.source = source; + g.id = id; + g.message = std::move(message); + mGroups.push_back(std::move(g)); +} + +void Debug::popGroup() +{ + // Make sure the default group is not about to be popped + ASSERT(mGroups.size() > 1); + + Group g = mGroups.back(); + mGroups.pop_back(); + + insertMessage(g.source, GL_DEBUG_TYPE_POP_GROUP, g.id, GL_DEBUG_SEVERITY_NOTIFICATION, + g.message); +} + +size_t Debug::getGroupStackDepth() const +{ + return mGroups.size(); +} + +bool Debug::isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const +{ + if (!mOutputEnabled) + { + return false; + } + + for (auto groupIter = mGroups.rbegin(); groupIter != mGroups.rend(); groupIter++) + { + const auto &controls = groupIter->controls; + for (auto controlIter = controls.rbegin(); controlIter != controls.rend(); controlIter++) + { + const auto &control = *controlIter; + + if (control.source != GL_DONT_CARE && control.source != source) + { + continue; + } + + if (control.type != GL_DONT_CARE && control.type != type) + { + continue; + } + + if (control.severity != GL_DONT_CARE && control.severity != severity) + { + continue; + } + + if (!control.ids.empty() && + std::find(control.ids.begin(), control.ids.end(), id) == control.ids.end()) + { + continue; + } + + return control.enabled; + } + } + + return true; +} + +void Debug::pushDefaultGroup() +{ + Group g; + g.source = GL_NONE; + g.id = 0; + g.message = ""; + + Control c0; + c0.source = GL_DONT_CARE; + c0.type = GL_DONT_CARE; + c0.severity = GL_DONT_CARE; + c0.enabled = true; + g.controls.push_back(std::move(c0)); + + Control c1; + c1.source = GL_DONT_CARE; + c1.type = GL_DONT_CARE; + c1.severity = GL_DEBUG_SEVERITY_LOW; + c1.enabled = false; + g.controls.push_back(std::move(c1)); + + mGroups.push_back(std::move(g)); +} +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/Debug.h b/src/3rdparty/angle/src/libANGLE/Debug.h new file mode 100644 index 0000000000..f545b815e4 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Debug.h @@ -0,0 +1,120 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Debug.h: Defines debug state used for GL_KHR_debug + +#ifndef LIBANGLE_DEBUG_H_ +#define LIBANGLE_DEBUG_H_ + +#include "angle_gl.h" +#include "common/angleutils.h" + +#include +#include +#include + +namespace gl +{ + +class LabeledObject +{ + public: + virtual ~LabeledObject() {} + virtual void setLabel(const std::string &label) = 0; + virtual const std::string &getLabel() const = 0; +}; + +class Debug : angle::NonCopyable +{ + public: + Debug(); + + void setMaxLoggedMessages(GLuint maxLoggedMessages); + + void setOutputEnabled(bool enabled); + bool isOutputEnabled() const; + + void setOutputSynchronous(bool synchronous); + bool isOutputSynchronous() const; + + void setCallback(GLDEBUGPROCKHR callback, const void *userParam); + GLDEBUGPROCKHR getCallback() const; + const void *getUserParam() const; + + void insertMessage(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + const std::string &message); + void insertMessage(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + std::string &&message); + + void setMessageControl(GLenum source, + GLenum type, + GLenum severity, + std::vector &&ids, + bool enabled); + size_t getMessages(GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog); + size_t getNextMessageLength() const; + size_t getMessageCount() const; + + void pushGroup(GLenum source, GLuint id, std::string &&message); + void popGroup(); + size_t getGroupStackDepth() const; + + private: + bool isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const; + + void pushDefaultGroup(); + + struct Message + { + GLenum source; + GLenum type; + GLuint id; + GLenum severity; + std::string message; + }; + + struct Control + { + GLenum source; + GLenum type; + GLenum severity; + std::vector ids; + bool enabled; + }; + + struct Group + { + GLenum source; + GLuint id; + std::string message; + + std::vector controls; + }; + + bool mOutputEnabled; + GLDEBUGPROCKHR mCallbackFunction; + const void *mCallbackUserParam; + std::deque mMessages; + GLuint mMaxLoggedMessages; + bool mOutputSynchronous; + std::vector mGroups; +}; +} // namespace gl + +#endif // LIBANGLE_DEBUG_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Debug2.cpp b/src/3rdparty/angle/src/libANGLE/Debug2.cpp new file mode 100644 index 0000000000..30321f4160 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Debug2.cpp @@ -0,0 +1,303 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Debug.cpp: Defines debug state used for GL_KHR_debug + +#include "libANGLE/Debug.h" + +#include "common/debug.h" + +#include +#include + +namespace gl +{ + +Debug::Debug() + : mOutputEnabled(false), + mCallbackFunction(nullptr), + mCallbackUserParam(nullptr), + mMessages(), + mMaxLoggedMessages(0), + mOutputSynchronous(false), + mGroups() +{ + pushDefaultGroup(); +} + +void Debug::setMaxLoggedMessages(GLuint maxLoggedMessages) +{ + mMaxLoggedMessages = maxLoggedMessages; +} + +void Debug::setOutputEnabled(bool enabled) +{ + mOutputEnabled = enabled; +} + +bool Debug::isOutputEnabled() const +{ + return mOutputEnabled; +} + +void Debug::setOutputSynchronous(bool synchronous) +{ + mOutputSynchronous = synchronous; +} + +bool Debug::isOutputSynchronous() const +{ + return mOutputSynchronous; +} + +void Debug::setCallback(GLDEBUGPROCKHR callback, const void *userParam) +{ + mCallbackFunction = callback; + mCallbackUserParam = userParam; +} + +GLDEBUGPROCKHR Debug::getCallback() const +{ + return mCallbackFunction; +} + +const void *Debug::getUserParam() const +{ + return mCallbackUserParam; +} + +void Debug::insertMessage(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + const std::string &message) +{ + std::string messageCopy(message); + insertMessage(source, type, id, severity, std::move(messageCopy)); +} + +void Debug::insertMessage(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + std::string &&message) +{ + if (!isMessageEnabled(source, type, id, severity)) + { + return; + } + + if (mCallbackFunction != nullptr) + { + // TODO(geofflang) Check the synchronous flag and potentially flush messages from another + // thread. + mCallbackFunction(source, type, id, severity, static_cast(message.length()), + message.c_str(), mCallbackUserParam); + } + else + { + if (mMessages.size() >= mMaxLoggedMessages) + { + // Drop messages over the limit + return; + } + + Message m; + m.source = source; + m.type = type; + m.id = id; + m.severity = severity; + m.message = std::move(message); + + mMessages.push_back(std::move(m)); + } +} + +size_t Debug::getMessages(GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog) +{ + size_t messageCount = 0; + size_t messageStringIndex = 0; + while (messageCount <= count && !mMessages.empty()) + { + const Message &m = mMessages.front(); + + if (messageLog != nullptr) + { + // Check that this message can fit in the message buffer + if (messageStringIndex + m.message.length() + 1 > static_cast(bufSize)) + { + break; + } + + std::copy(m.message.begin(), m.message.end(), messageLog + messageStringIndex); + messageStringIndex += m.message.length(); + + messageLog[messageStringIndex] = '\0'; + messageStringIndex += 1; + } + + if (sources != nullptr) + { + sources[messageCount] = m.source; + } + + if (types != nullptr) + { + types[messageCount] = m.type; + } + + if (ids != nullptr) + { + ids[messageCount] = m.id; + } + + if (severities != nullptr) + { + severities[messageCount] = m.severity; + } + + if (lengths != nullptr) + { + lengths[messageCount] = static_cast(m.message.length()); + } + + mMessages.pop_front(); + + messageCount++; + } + + return messageCount; +} + +size_t Debug::getNextMessageLength() const +{ + return mMessages.empty() ? 0 : mMessages.front().message.length(); +} + +size_t Debug::getMessageCount() const +{ + return mMessages.size(); +} + +void Debug::setMessageControl(GLenum source, + GLenum type, + GLenum severity, + std::vector &&ids, + bool enabled) +{ + Control c; + c.source = source; + c.type = type; + c.severity = severity; + c.ids = std::move(ids); + c.enabled = enabled; + + auto &controls = mGroups.back().controls; + controls.push_back(std::move(c)); +} + +void Debug::pushGroup(GLenum source, GLuint id, std::string &&message) +{ + insertMessage(source, GL_DEBUG_TYPE_PUSH_GROUP, id, GL_DEBUG_SEVERITY_NOTIFICATION, + std::string(message)); + + Group g; + g.source = source; + g.id = id; + g.message = std::move(message); + mGroups.push_back(std::move(g)); +} + +void Debug::popGroup() +{ + // Make sure the default group is not about to be popped + ASSERT(mGroups.size() > 1); + + Group g = mGroups.back(); + mGroups.pop_back(); + + insertMessage(g.source, GL_DEBUG_TYPE_POP_GROUP, g.id, GL_DEBUG_SEVERITY_NOTIFICATION, + g.message); +} + +size_t Debug::getGroupStackDepth() const +{ + return mGroups.size(); +} + +bool Debug::isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const +{ + if (!mOutputEnabled) + { + return false; + } + + for (auto groupIter = mGroups.rbegin(); groupIter != mGroups.rend(); groupIter++) + { + const auto &controls = groupIter->controls; + for (auto controlIter = controls.rbegin(); controlIter != controls.rend(); controlIter++) + { + const auto &control = *controlIter; + + if (control.source != GL_DONT_CARE && control.source != source) + { + continue; + } + + if (control.type != GL_DONT_CARE && control.type != type) + { + continue; + } + + if (control.severity != GL_DONT_CARE && control.severity != severity) + { + continue; + } + + if (!control.ids.empty() && + std::find(control.ids.begin(), control.ids.end(), id) == control.ids.end()) + { + continue; + } + + return control.enabled; + } + } + + return true; +} + +void Debug::pushDefaultGroup() +{ + Group g; + g.source = GL_NONE; + g.id = 0; + g.message = ""; + + Control c0; + c0.source = GL_DONT_CARE; + c0.type = GL_DONT_CARE; + c0.severity = GL_DONT_CARE; + c0.enabled = true; + g.controls.push_back(std::move(c0)); + + Control c1; + c1.source = GL_DONT_CARE; + c1.type = GL_DONT_CARE; + c1.severity = GL_DEBUG_SEVERITY_LOW; + c1.enabled = false; + g.controls.push_back(std::move(c1)); + + mGroups.push_back(std::move(g)); +} +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/Debug2.h b/src/3rdparty/angle/src/libANGLE/Debug2.h new file mode 100644 index 0000000000..f545b815e4 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Debug2.h @@ -0,0 +1,120 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Debug.h: Defines debug state used for GL_KHR_debug + +#ifndef LIBANGLE_DEBUG_H_ +#define LIBANGLE_DEBUG_H_ + +#include "angle_gl.h" +#include "common/angleutils.h" + +#include +#include +#include + +namespace gl +{ + +class LabeledObject +{ + public: + virtual ~LabeledObject() {} + virtual void setLabel(const std::string &label) = 0; + virtual const std::string &getLabel() const = 0; +}; + +class Debug : angle::NonCopyable +{ + public: + Debug(); + + void setMaxLoggedMessages(GLuint maxLoggedMessages); + + void setOutputEnabled(bool enabled); + bool isOutputEnabled() const; + + void setOutputSynchronous(bool synchronous); + bool isOutputSynchronous() const; + + void setCallback(GLDEBUGPROCKHR callback, const void *userParam); + GLDEBUGPROCKHR getCallback() const; + const void *getUserParam() const; + + void insertMessage(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + const std::string &message); + void insertMessage(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + std::string &&message); + + void setMessageControl(GLenum source, + GLenum type, + GLenum severity, + std::vector &&ids, + bool enabled); + size_t getMessages(GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog); + size_t getNextMessageLength() const; + size_t getMessageCount() const; + + void pushGroup(GLenum source, GLuint id, std::string &&message); + void popGroup(); + size_t getGroupStackDepth() const; + + private: + bool isMessageEnabled(GLenum source, GLenum type, GLuint id, GLenum severity) const; + + void pushDefaultGroup(); + + struct Message + { + GLenum source; + GLenum type; + GLuint id; + GLenum severity; + std::string message; + }; + + struct Control + { + GLenum source; + GLenum type; + GLenum severity; + std::vector ids; + bool enabled; + }; + + struct Group + { + GLenum source; + GLuint id; + std::string message; + + std::vector controls; + }; + + bool mOutputEnabled; + GLDEBUGPROCKHR mCallbackFunction; + const void *mCallbackUserParam; + std::deque mMessages; + GLuint mMaxLoggedMessages; + bool mOutputSynchronous; + std::vector mGroups; +}; +} // namespace gl + +#endif // LIBANGLE_DEBUG_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Device.cpp b/src/3rdparty/angle/src/libANGLE/Device.cpp new file mode 100644 index 0000000000..eb30b2023f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Device.cpp @@ -0,0 +1,130 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Device.cpp: Implements the egl::Device class, representing the abstract +// device. Implements EGLDevice. + +#include "libANGLE/Device.h" + +#include + +#include +#include + +#include "common/debug.h" +#include "common/platform.h" +#include "libANGLE/renderer/DeviceImpl.h" + +#if defined(ANGLE_ENABLE_D3D11) +#include "libANGLE/renderer/d3d/DeviceD3D.h" +#endif + +namespace egl +{ + +template +static std::string GenerateExtensionsString(const T &extensions) +{ + std::vector extensionsVector = extensions.getStrings(); + + std::ostringstream stream; + std::copy(extensionsVector.begin(), extensionsVector.end(), std::ostream_iterator(stream, " ")); + return stream.str(); +} + +typedef std::set DeviceSet; +static DeviceSet *GetDeviceSet() +{ + static DeviceSet devices; + return &devices; +} + +// Static factory methods +egl::Error Device::CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice) +{ +#if defined(ANGLE_ENABLE_D3D11) + if (deviceType == EGL_D3D11_DEVICE_ANGLE) + { + rx::DeviceD3D *deviceD3D = new rx::DeviceD3D(); + egl::Error error = deviceD3D->initialize(devicePointer, deviceType, EGL_TRUE); + if (error.isError()) + { + *outDevice = nullptr; + return error; + } + + *outDevice = new Device(nullptr, deviceD3D); + GetDeviceSet()->insert(*outDevice); + return egl::Error(EGL_SUCCESS); + } +#endif + + // Note that creating an EGL device from inputted D3D9 parameters isn't currently supported + *outDevice = nullptr; + return egl::Error(EGL_BAD_ATTRIBUTE); +} + +egl::Error Device::CreateDevice(Display *owningDisplay, rx::DeviceImpl *impl, Device **outDevice) +{ + *outDevice = new Device(owningDisplay, impl); + GetDeviceSet()->insert(*outDevice); + return egl::Error(EGL_SUCCESS); +} + +bool Device::IsValidDevice(Device *device) +{ + const DeviceSet *deviceSet = GetDeviceSet(); + return deviceSet->find(device) != deviceSet->end(); +} + +Device::Device(Display *owningDisplay, rx::DeviceImpl *impl) + : mOwningDisplay(owningDisplay), mImplementation(impl) +{ + initDeviceExtensions(); +} + +Device::~Device() +{ + ASSERT(GetDeviceSet()->find(this) != GetDeviceSet()->end()); + GetDeviceSet()->erase(this); + + if (mImplementation->deviceExternallySourced()) + { + // If the device isn't externally sourced then it is up to the renderer to delete the impl + SafeDelete(mImplementation); + } +} + +Error Device::getDevice(EGLAttrib *value) +{ + void *nativeDevice = nullptr; + egl::Error error = getImplementation()->getDevice(&nativeDevice); + *value = reinterpret_cast(nativeDevice); + return error; +} + +EGLint Device::getType() +{ + return getImplementation()->getType(); +} + +void Device::initDeviceExtensions() +{ + mImplementation->generateExtensions(&mDeviceExtensions); + mDeviceExtensionString = GenerateExtensionsString(mDeviceExtensions); +} + +const DeviceExtensions &Device::getExtensions() const +{ + return mDeviceExtensions; +} + +const std::string &Device::getExtensionString() const +{ + return mDeviceExtensionString; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/Device.h b/src/3rdparty/angle/src/libANGLE/Device.h new file mode 100644 index 0000000000..4bc58ff043 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Device.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Device.h: Implements the egl::Device class, representing the abstract +// device. Implements EGLDevice. + +#ifndef LIBANGLE_DEVICE_H_ +#define LIBANGLE_DEVICE_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" +#include "libANGLE/Display.h" + +namespace rx +{ +class DeviceImpl; +} + +namespace egl +{ +class Device final : angle::NonCopyable +{ + public: + virtual ~Device(); + + Error getDevice(EGLAttrib *value); + Display *getOwningDisplay() { return mOwningDisplay; }; + EGLint getType(); + + const DeviceExtensions &getExtensions() const; + const std::string &getExtensionString() const; + + rx::DeviceImpl *getImplementation() { return mImplementation; } + + static egl::Error CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice); + static egl::Error CreateDevice(Display *owningDisplay, + rx::DeviceImpl *impl, + Device **outDevice); + + static bool IsValidDevice(Device *device); + + private: + Device(Display *owningDisplay, rx::DeviceImpl *impl); + void initDeviceExtensions(); + + Display *mOwningDisplay; + rx::DeviceImpl *mImplementation; + + DeviceExtensions mDeviceExtensions; + std::string mDeviceExtensionString; +}; + +} + +#endif // LIBANGLE_DEVICE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp index 1f54f82dea..486c74abc0 100644 --- a/src/3rdparty/angle/src/libANGLE/Display.cpp +++ b/src/3rdparty/angle/src/libANGLE/Display.cpp @@ -22,9 +22,15 @@ #include "common/debug.h" #include "common/mathutil.h" #include "common/platform.h" +#include "common/utilities.h" #include "libANGLE/Context.h" +#include "libANGLE/Device.h" +#include "libANGLE/histogram_macros.h" +#include "libANGLE/Image.h" #include "libANGLE/Surface.h" #include "libANGLE/renderer/DisplayImpl.h" +#include "libANGLE/renderer/ImageImpl.h" +#include "third_party/trace_event/trace_event.h" #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) # include "libANGLE/renderer/d3d/DisplayD3D.h" @@ -33,6 +39,10 @@ #if defined(ANGLE_ENABLE_OPENGL) # if defined(ANGLE_PLATFORM_WINDOWS) # include "libANGLE/renderer/gl/wgl/DisplayWGL.h" +# elif defined(ANGLE_USE_X11) +# include "libANGLE/renderer/gl/glx/DisplayGLX.h" +# elif defined(ANGLE_PLATFORM_APPLE) +# include "libANGLE/renderer/gl/cgl/DisplayCGL.h" # else # error Unsupported OpenGL platform. # endif @@ -66,19 +76,6 @@ void InitDefaultPlatformImpl() } } -void DeinitDefaultPlatformImpl() -{ - if (defaultPlatform != nullptr) - { - if (ANGLEPlatformCurrent() == defaultPlatform) - { - ANGLEPlatformShutdown(); - } - - SafeDelete(defaultPlatform); - } -} - typedef std::map WindowSurfaceMap; // Get a map of all EGL window surfaces to validate that no window has more than one EGL surface // associated with it. @@ -88,14 +85,52 @@ static WindowSurfaceMap *GetWindowSurfaces() return &windowSurfaces; } -typedef std::map DisplayMap; -static DisplayMap *GetDisplayMap() +typedef std::map ANGLEPlatformDisplayMap; +static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap() +{ + static ANGLEPlatformDisplayMap displays; + return &displays; +} + +typedef std::map DevicePlatformDisplayMap; +static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap() { - static DisplayMap displays; + static DevicePlatformDisplayMap displays; return &displays; } -rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap) +rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice) +{ + rx::DisplayImpl *impl = nullptr; + + switch (eglDevice->getType()) + { +#if defined(ANGLE_ENABLE_D3D11) + case EGL_D3D11_DEVICE_ANGLE: + impl = new rx::DisplayD3D(); + break; +#endif +#if defined(ANGLE_ENABLE_D3D9) + case EGL_D3D9_DEVICE_ANGLE: + // Currently the only way to get EGLDeviceEXT representing a D3D9 device + // is to retrieve one from an already-existing EGLDisplay. + // When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT, + // the already-existing display should be returned. + // Therefore this codepath to create a new display from the device + // should never be hit. + UNREACHABLE(); + break; +#endif + default: + UNREACHABLE(); + break; + } + + ASSERT(impl != nullptr); + return impl; +} + +rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap) { rx::DisplayImpl *impl = nullptr; EGLint displayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); @@ -105,6 +140,10 @@ rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap) #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) // Default to D3D displays impl = new rx::DisplayD3D(); +#elif defined(ANGLE_USE_X11) + impl = new rx::DisplayGLX(); +#elif defined(ANGLE_PLATFORM_APPLE) + impl = new rx::DisplayCGL(); #else // No display available UNREACHABLE(); @@ -125,6 +164,10 @@ rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap) #if defined(ANGLE_ENABLE_OPENGL) #if defined(ANGLE_PLATFORM_WINDOWS) impl = new rx::DisplayWGL(); +#elif defined(ANGLE_USE_X11) + impl = new rx::DisplayGLX(); +#elif defined(ANGLE_PLATFORM_APPLE) + impl = new rx::DisplayCGL(); #else #error Unsupported OpenGL platform. #endif @@ -133,26 +176,40 @@ rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap) #endif break; +#if defined(ANGLE_ENABLE_OPENGL) + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: +#if defined(ANGLE_PLATFORM_WINDOWS) + impl = new rx::DisplayWGL(); +#elif defined(ANGLE_USE_X11) + impl = new rx::DisplayGLX(); +#else + // No GLES support on this platform, fail display creation. + impl = nullptr; +#endif + break; +#endif + default: UNREACHABLE(); break; } - ASSERT(impl != nullptr); return impl; } } -Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap) +Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap) { // Initialize the global platform if not already InitDefaultPlatformImpl(); - Display *display = NULL; + Display *display = nullptr; + + EGLNativeDisplayType displayId = reinterpret_cast(native_display); - DisplayMap *displays = GetDisplayMap(); - DisplayMap::const_iterator iter = displays->find(displayId); + ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap(); + ANGLEPlatformDisplayMap::const_iterator iter = displays->find(displayId); if (iter != displays->end()) { display = iter->second; @@ -166,21 +223,77 @@ Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap return NULL; } - display = new Display(displayId); + display = new Display(EGL_PLATFORM_ANGLE_ANGLE, displayId, nullptr); displays->insert(std::make_pair(displayId, display)); } // Apply new attributes if the display is not initialized yet. if (!display->isInitialized()) { - rx::DisplayImpl* impl = CreateDisplayImpl(attribMap); + rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap); + if (impl == nullptr) + { + // No valid display implementation for these attributes + return nullptr; + } + display->setAttributes(impl, attribMap); } return display; } -Display::Display(EGLNativeDisplayType displayId) +Display *Display::GetDisplayFromDevice(void *native_display) +{ + // Initialize the global platform if not already + InitDefaultPlatformImpl(); + + Display *display = nullptr; + + Device *eglDevice = reinterpret_cast(native_display); + ASSERT(Device::IsValidDevice(eglDevice)); + + ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap(); + DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap(); + + // First see if this eglDevice is in use by a Display created using ANGLE platform + for (auto &displayMapEntry : *anglePlatformDisplays) + { + egl::Display *iterDisplay = displayMapEntry.second; + if (iterDisplay->getDevice() == eglDevice) + { + display = iterDisplay; + } + } + + if (display == nullptr) + { + // See if the eglDevice is in use by a Display created using the DEVICE platform + DevicePlatformDisplayMap::const_iterator iter = devicePlatformDisplays->find(eglDevice); + if (iter != devicePlatformDisplays->end()) + { + display = iter->second; + } + } + + if (display == nullptr) + { + // Otherwise create a new Display + display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, eglDevice); + devicePlatformDisplays->insert(std::make_pair(eglDevice, display)); + } + + // Apply new attributes if the display is not initialized yet. + if (!display->isInitialized()) + { + rx::DisplayImpl *impl = CreateDisplayFromDevice(eglDevice); + display->setAttributes(impl, egl::AttributeMap()); + } + + return display; +} + +Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice) : mImplementation(nullptr), mDisplayId(displayId), mAttributeMap(), @@ -190,7 +303,9 @@ Display::Display(EGLNativeDisplayType displayId) mCaps(), mDisplayExtensions(), mDisplayExtensionString(), - mVendorString() + mVendorString(), + mDevice(eglDevice), + mPlatform(platform) { } @@ -198,13 +313,30 @@ Display::~Display() { terminate(); - DisplayMap *displays = GetDisplayMap(); - DisplayMap::iterator iter = displays->find(mDisplayId); - if (iter != displays->end()) + if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE) + { + ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap(); + ANGLEPlatformDisplayMap::iterator iter = displays->find(mDisplayId); + if (iter != displays->end()) + { + displays->erase(iter); + } + } + else if (mPlatform == EGL_PLATFORM_DEVICE_EXT) + { + DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap(); + DevicePlatformDisplayMap::iterator iter = displays->find(mDevice); + if (iter != displays->end()) + { + displays->erase(iter); + } + } + else { - displays->erase(iter); + UNREACHABLE(); } + SafeDelete(mDevice); SafeDelete(mImplementation); } @@ -221,6 +353,12 @@ void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap Error Display::initialize() { + // Re-initialize default platform if it's needed + InitDefaultPlatformImpl(); + + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.DisplayInitializeMS"); + TRACE_EVENT0("gpu.angle", "egl::Display::initialize"); + ASSERT(mImplementation != nullptr); if (isInitialized()) @@ -231,6 +369,11 @@ Error Display::initialize() Error error = mImplementation->initialize(this); if (error.isError()) { + // Log extended error message here + std::stringstream errorStream; + errorStream << "ANGLE Display::initialize error " << error.getID() << ": " + << error.getMessage(); + ANGLEPlatformCurrent()->logError(errorStream.str().c_str()); return error; } @@ -246,7 +389,38 @@ Error Display::initialize() initDisplayExtensions(); initVendorString(); + // Populate the Display's EGLDeviceEXT if the Display wasn't created using one + if (mPlatform != EGL_PLATFORM_DEVICE_EXT) + { + if (mDisplayExtensions.deviceQuery) + { + rx::DeviceImpl *impl = nullptr; + error = mImplementation->getDevice(&impl); + if (error.isError()) + { + return error; + } + + error = Device::CreateDevice(this, impl, &mDevice); + if (error.isError()) + { + return error; + } + } + else + { + mDevice = nullptr; + } + } + else + { + // For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using + // an external device + ASSERT(mDevice != nullptr); + } + mInitialized = true; + return Error(EGL_SUCCESS); } @@ -259,13 +433,30 @@ void Display::terminate() destroyContext(*mContextSet.begin()); } + while (!mImageSet.empty()) + { + destroyImage(*mImageSet.begin()); + } + + while (!mImplementation->getSurfaceSet().empty()) + { + destroySurface(*mImplementation->getSurfaceSet().begin()); + } + mConfigSet.clear(); + if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr) + { + // Don't delete the device if it was created externally using eglCreateDeviceANGLE + // We also shouldn't set it to null in case eglInitialize() is called again later + SafeDelete(mDevice); + } + mImplementation->terminate(); + mInitialized = false; - // De-init default platform - DeinitDefaultPlatformImpl(); + // Never de-init default platform.. terminate is not that final. } std::vector Display::getConfigs(const egl::AttributeMap &attribs) const @@ -288,6 +479,7 @@ bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGL case EGL_CONFIG_ID: *value = configuration->configID; break; case EGL_LEVEL: *value = configuration->level; break; case EGL_NATIVE_RENDERABLE: *value = configuration->nativeRenderable; break; + case EGL_NATIVE_VISUAL_ID: *value = configuration->nativeVisualID; break; case EGL_NATIVE_VISUAL_TYPE: *value = configuration->nativeVisualType; break; case EGL_SAMPLES: *value = configuration->samples; break; case EGL_SAMPLE_BUFFERS: *value = configuration->sampleBuffers; break; @@ -309,6 +501,15 @@ bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGL case EGL_MAX_PBUFFER_WIDTH: *value = configuration->maxPBufferWidth; break; case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->maxPBufferHeight; break; case EGL_MAX_PBUFFER_PIXELS: *value = configuration->maxPBufferPixels; break; + + case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE: + if (!getExtensions().surfaceOrientation) + { + return false; + } + *value = configuration->optimalOrientation; + break; + default: return false; } @@ -328,14 +529,16 @@ Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowT } } - rx::SurfaceImpl *surfaceImpl = nullptr; - Error error = mImplementation->createWindowSurface(configuration, window, attribs, &surfaceImpl); + rx::SurfaceImpl *surfaceImpl = mImplementation->createWindowSurface(configuration, window, attribs); + ASSERT(surfaceImpl != nullptr); + + Error error = surfaceImpl->initialize(); if (error.isError()) { + SafeDelete(surfaceImpl); return error; } - ASSERT(surfaceImpl != nullptr); Surface *surface = new Surface(surfaceImpl, EGL_WINDOW_BIT, configuration, attribs); mImplementation->getSurfaceSet().insert(surface); @@ -361,14 +564,16 @@ Error Display::createPbufferSurface(const Config *configuration, const Attribute } } - rx::SurfaceImpl *surfaceImpl = nullptr; - Error error = mImplementation->createPbufferSurface(configuration, attribs, &surfaceImpl); + rx::SurfaceImpl *surfaceImpl = mImplementation->createPbufferSurface(configuration, attribs); + ASSERT(surfaceImpl != nullptr); + + Error error = surfaceImpl->initialize(); if (error.isError()) { + SafeDelete(surfaceImpl); return error; } - ASSERT(surfaceImpl != nullptr); Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs); mImplementation->getSurfaceSet().insert(surface); @@ -391,14 +596,16 @@ Error Display::createPbufferFromClientBuffer(const Config *configuration, EGLCli } } - rx::SurfaceImpl *surfaceImpl = nullptr; - Error error = mImplementation->createPbufferFromClientBuffer(configuration, shareHandle, attribs, &surfaceImpl); + rx::SurfaceImpl *surfaceImpl = mImplementation->createPbufferFromClientBuffer(configuration, shareHandle, attribs); + ASSERT(surfaceImpl != nullptr); + + Error error = surfaceImpl->initialize(); if (error.isError()) { + SafeDelete(surfaceImpl); return error; } - ASSERT(surfaceImpl != nullptr); Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs); mImplementation->getSurfaceSet().insert(surface); @@ -421,14 +628,16 @@ Error Display::createPixmapSurface(const Config *configuration, NativePixmapType } } - rx::SurfaceImpl *surfaceImpl = nullptr; - Error error = mImplementation->createPixmapSurface(configuration, nativePixmap, attribs, &surfaceImpl); + rx::SurfaceImpl *surfaceImpl = mImplementation->createPixmapSurface(configuration, nativePixmap, attribs); + ASSERT(surfaceImpl != nullptr); + + Error error = surfaceImpl->initialize(); if (error.isError()) { + SafeDelete(surfaceImpl); return error; } - ASSERT(surfaceImpl != nullptr); Surface *surface = new Surface(surfaceImpl, EGL_PIXMAP_BIT, configuration, attribs); mImplementation->getSurfaceSet().insert(surface); @@ -437,8 +646,11 @@ Error Display::createPixmapSurface(const Config *configuration, NativePixmapType return Error(EGL_SUCCESS); } -Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs, - gl::Context **outContext) +Error Display::createImage(gl::Context *context, + EGLenum target, + EGLClientBuffer buffer, + const AttributeMap &attribs, + Image **outImage) { ASSERT(isInitialized()); @@ -451,13 +663,59 @@ Error Display::createContext(const Config *configuration, gl::Context *shareCont } } - gl::Context *context = nullptr; - Error error = mImplementation->createContext(configuration, shareContext, attribs, &context); + egl::ImageSibling *sibling = nullptr; + if (IsTextureTarget(target)) + { + sibling = context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); + } + else if (IsRenderbufferTarget(target)) + { + sibling = context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); + } + else + { + UNREACHABLE(); + } + ASSERT(sibling != nullptr); + + rx::ImageImpl *imageImpl = mImplementation->createImage(target, sibling, attribs); + ASSERT(imageImpl != nullptr); + + Error error = imageImpl->initialize(); if (error.isError()) { return error; } + Image *image = new Image(imageImpl, target, sibling, attribs); + + ASSERT(outImage != nullptr); + *outImage = image; + + // Add this image to the list of all images and hold a ref to it. + image->addRef(); + mImageSet.insert(image); + + return Error(EGL_SUCCESS); +} + +Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs, + gl::Context **outContext) +{ + ASSERT(isInitialized()); + + if (mImplementation->testDeviceLost()) + { + Error error = restoreLostDevice(); + if (error.isError()) + { + return error; + } + } + + gl::Context *context = *outContext = + mImplementation->createContext(configuration, shareContext, attribs); + ASSERT(context != nullptr); mContextSet.insert(context); @@ -474,8 +732,9 @@ Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, return error; } - if (context && drawSurface) + if (context != nullptr && drawSurface != nullptr) { + ASSERT(readSurface == drawSurface); context->makeCurrent(drawSurface); } @@ -515,11 +774,20 @@ void Display::destroySurface(Surface *surface) } ASSERT(surfaceRemoved); + UNUSED_ASSERTION_VARIABLE(surfaceRemoved); } mImplementation->destroySurface(surface); } +void Display::destroyImage(egl::Image *image) +{ + auto iter = mImageSet.find(image); + ASSERT(iter != mImageSet.end()); + (*iter)->release(); + mImageSet.erase(iter); +} + void Display::destroyContext(gl::Context *context) { mContextSet.erase(context); @@ -546,6 +814,16 @@ void Display::notifyDeviceLost() } } +Error Display::waitClient() const +{ + return mImplementation->waitClient(); +} + +Error Display::waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const +{ + return mImplementation->waitNative(engine, drawSurface, readSurface); +} + const Caps &Display::getCaps() const { return mCaps; @@ -571,6 +849,11 @@ bool Display::isValidSurface(Surface *surface) const return mImplementation->getSurfaceSet().find(surface) != mImplementation->getSurfaceSet().end(); } +bool Display::isValidImage(const Image *image) const +{ + return mImageSet.find(const_cast(image)) != mImageSet.end(); +} + bool Display::hasExistingWindowSurface(EGLNativeWindowType window) { WindowSurfaceMap *windowSurfaces = GetWindowSurfaces(); @@ -589,12 +872,25 @@ static ClientExtensions GenerateClientExtensions() #if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) extensions.platformANGLED3D = true; + extensions.platformDevice = true; #endif #if defined(ANGLE_ENABLE_OPENGL) extensions.platformANGLEOpenGL = true; #endif +#if defined(ANGLE_ENABLE_D3D11) + extensions.deviceCreation = true; + extensions.deviceCreationD3D11 = true; + extensions.experimentalPresentPath = true; +#endif + +#if defined(ANGLE_USE_X11) + extensions.x11Visual = true; +#endif + + extensions.clientGetAllProcAddresses = true; + return extensions; } @@ -623,6 +919,10 @@ const std::string &Display::getClientExtensionString() void Display::initDisplayExtensions() { mDisplayExtensions = mImplementation->getExtensions(); + + // Force EGL_KHR_get_all_proc_addresses on. + mDisplayExtensions.getAllProcAddresses = true; + mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions); } @@ -631,6 +931,29 @@ bool Display::isValidNativeWindow(EGLNativeWindowType window) const return mImplementation->isValidNativeWindow(window); } +bool Display::isValidDisplay(const egl::Display *display) +{ + const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap(); + for (const auto &displayPair : *anglePlatformDisplayMap) + { + if (displayPair.second == display) + { + return true; + } + } + + const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap(); + for (const auto &displayPair : *devicePlatformDisplayMap) + { + if (displayPair.second == display) + { + return true; + } + } + + return false; +} + bool Display::isValidNativeDisplay(EGLNativeDisplayType display) { // TODO(jmadill): handle this properly @@ -672,4 +995,9 @@ const std::string &Display::getVendorString() const return mVendorString; } +Device *Display::getDevice() const +{ + return mDevice; +} + } diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h index 5ab3f9c0e9..f80e308347 100644 --- a/src/3rdparty/angle/src/libANGLE/Display.h +++ b/src/3rdparty/angle/src/libANGLE/Display.h @@ -18,6 +18,7 @@ #include "libANGLE/Caps.h" #include "libANGLE/Config.h" #include "libANGLE/AttributeMap.h" +#include "libANGLE/renderer/Renderer.h" namespace gl { @@ -31,6 +32,8 @@ class DisplayImpl; namespace egl { +class Device; +class Image; class Surface; class Display final : angle::NonCopyable @@ -41,7 +44,8 @@ class Display final : angle::NonCopyable Error initialize(); void terminate(); - static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap); + static egl::Display *GetDisplayFromDevice(void *native_display); + static egl::Display *GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap); static const ClientExtensions &getClientExtensions(); static const std::string &getClientExtensionString(); @@ -57,20 +61,29 @@ class Display final : angle::NonCopyable Error createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs, Surface **outSurface); + Error createImage(gl::Context *context, + EGLenum target, + EGLClientBuffer buffer, + const AttributeMap &attribs, + Image **outImage); + Error createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs, gl::Context **outContext); Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context); void destroySurface(egl::Surface *surface); + void destroyImage(egl::Image *image); void destroyContext(gl::Context *context); bool isInitialized() const; bool isValidConfig(const Config *config) const; bool isValidContext(gl::Context *context) const; bool isValidSurface(egl::Surface *surface) const; + bool isValidImage(const Image *image) const; bool isValidNativeWindow(EGLNativeWindowType window) const; + static bool isValidDisplay(const egl::Display *display); static bool isValidNativeDisplay(EGLNativeDisplayType display); static bool hasExistingWindowSurface(EGLNativeWindowType window); @@ -78,6 +91,9 @@ class Display final : angle::NonCopyable bool testDeviceLost(); void notifyDeviceLost(); + Error waitClient() const; + Error waitNative(EGLint engine, egl::Surface *drawSurface, egl::Surface *readSurface) const; + const Caps &getCaps() const; const DisplayExtensions &getExtensions() const; @@ -88,9 +104,11 @@ class Display final : angle::NonCopyable EGLNativeDisplayType getNativeDisplayId() const { return mDisplayId; } rx::DisplayImpl *getImplementation() { return mImplementation; } + Device *getDevice() const; + EGLenum getPlatform() const { return mPlatform; } private: - Display(EGLNativeDisplayType displayId); + Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice); void setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap); @@ -109,6 +127,9 @@ class Display final : angle::NonCopyable typedef std::set ContextSet; ContextSet mContextSet; + typedef std::set ImageSet; + ImageSet mImageSet; + bool mInitialized; Caps mCaps; @@ -117,6 +138,9 @@ class Display final : angle::NonCopyable std::string mDisplayExtensionString; std::string mVendorString; + + Device *mDevice; + EGLenum mPlatform; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Error.cpp b/src/3rdparty/angle/src/libANGLE/Error.cpp index e17f26bec4..fed1594972 100644 --- a/src/3rdparty/angle/src/libANGLE/Error.cpp +++ b/src/3rdparty/angle/src/libANGLE/Error.cpp @@ -16,9 +16,16 @@ namespace gl { -Error::Error(GLenum errorCode, const char *msg, ...) - : mCode(errorCode), - mMessage(nullptr) +Error::Error(GLenum errorCode, const char *msg, ...) : mCode(errorCode), mID(errorCode) +{ + va_list vararg; + va_start(vararg, msg); + createMessageString(); + *mMessage = FormatString(msg, vararg); + va_end(vararg); +} + +Error::Error(GLenum errorCode, GLuint id, const char *msg, ...) : mCode(errorCode), mID(id) { va_list vararg; va_start(vararg, msg); @@ -29,9 +36,9 @@ Error::Error(GLenum errorCode, const char *msg, ...) void Error::createMessageString() const { - if (mMessage == nullptr) + if (!mMessage) { - mMessage = new std::string(); + mMessage.reset(new std::string); } } @@ -41,15 +48,28 @@ const std::string &Error::getMessage() const return *mMessage; } +bool Error::operator==(const Error &other) const +{ + if (mCode != other.mCode) + return false; + + // TODO(jmadill): Compare extended error codes instead of strings. + if ((!mMessage || !other.mMessage) && (!mMessage != !other.mMessage)) + return false; + + return (*mMessage == *other.mMessage); +} + +bool Error::operator!=(const Error &other) const +{ + return !(*this == other); +} } namespace egl { -Error::Error(EGLint errorCode, const char *msg, ...) - : mCode(errorCode), - mID(0), - mMessage(nullptr) +Error::Error(EGLint errorCode, const char *msg, ...) : mCode(errorCode), mID(0) { va_list vararg; va_start(vararg, msg); @@ -58,10 +78,7 @@ Error::Error(EGLint errorCode, const char *msg, ...) va_end(vararg); } -Error::Error(EGLint errorCode, EGLint id, const char *msg, ...) - : mCode(errorCode), - mID(id), - mMessage(nullptr) +Error::Error(EGLint errorCode, EGLint id, const char *msg, ...) : mCode(errorCode), mID(id) { va_list vararg; va_start(vararg, msg); @@ -69,11 +86,12 @@ Error::Error(EGLint errorCode, EGLint id, const char *msg, ...) *mMessage = FormatString(msg, vararg); va_end(vararg); } + void Error::createMessageString() const { - if (mMessage == nullptr) + if (!mMessage) { - mMessage = new std::string(); + mMessage.reset(new std::string); } } diff --git a/src/3rdparty/angle/src/libANGLE/Error.h b/src/3rdparty/angle/src/libANGLE/Error.h index 896b777567..a5f760956a 100644 --- a/src/3rdparty/angle/src/libANGLE/Error.h +++ b/src/3rdparty/angle/src/libANGLE/Error.h @@ -10,10 +10,10 @@ #define LIBANGLE_ERROR_H_ #include "angle_gl.h" -#include "common/platform.h" #include #include +#include namespace gl { @@ -23,27 +23,48 @@ class Error final public: explicit inline Error(GLenum errorCode); Error(GLenum errorCode, const char *msg, ...); + Error(GLenum errorCode, GLuint id, const char *msg, ...); inline Error(const Error &other); inline Error(Error &&other); - inline ~Error(); - inline Error &operator=(const Error &other); inline Error &operator=(Error &&other); inline GLenum getCode() const; + inline GLuint getID() const; inline bool isError() const; const std::string &getMessage() const; + // Useful for mocking and testing + bool operator==(const Error &other) const; + bool operator!=(const Error &other) const; + private: void createMessageString() const; GLenum mCode; - mutable std::string *mMessage; + GLuint mID; + mutable std::unique_ptr mMessage; +}; + +template +class ErrorOrResult +{ + public: + ErrorOrResult(const gl::Error &error) : mError(error) {} + ErrorOrResult(T &&result) : mError(GL_NO_ERROR), mResult(std::move(result)) {} + + bool isError() const { return mError.isError(); } + const gl::Error &getError() const { return mError; } + T &&getResult() { return std::move(mResult); } + + private: + Error mError; + T mResult; }; -} +} // namespace gl namespace egl { @@ -57,8 +78,6 @@ class Error final inline Error(const Error &other); inline Error(Error &&other); - inline ~Error(); - inline Error &operator=(const Error &other); inline Error &operator=(Error &&other); @@ -73,10 +92,10 @@ class Error final EGLint mCode; EGLint mID; - mutable std::string *mMessage; + mutable std::unique_ptr mMessage; }; -} +} // namespace egl #include "Error.inl" diff --git a/src/3rdparty/angle/src/libANGLE/Error.inl b/src/3rdparty/angle/src/libANGLE/Error.inl index 32e8f05828..900fc5fd03 100644 --- a/src/3rdparty/angle/src/libANGLE/Error.inl +++ b/src/3rdparty/angle/src/libANGLE/Error.inl @@ -15,15 +15,15 @@ namespace gl Error::Error(GLenum errorCode) : mCode(errorCode), - mMessage(nullptr) + mID(errorCode) { } Error::Error(const Error &other) : mCode(other.mCode), - mMessage(nullptr) + mID(other.mID) { - if (other.mMessage != nullptr) + if (other.mMessage) { createMessageString(); *mMessage = *(other.mMessage); @@ -32,28 +32,24 @@ Error::Error(const Error &other) Error::Error(Error &&other) : mCode(other.mCode), - mMessage(other.mMessage) -{ - other.mMessage = nullptr; -} - -Error::~Error() + mID(other.mID), + mMessage(std::move(other.mMessage)) { - SafeDelete(mMessage); } Error &Error::operator=(const Error &other) { mCode = other.mCode; + mID = other.mID; - if (other.mMessage != nullptr) + if (other.mMessage) { createMessageString(); *mMessage = *(other.mMessage); } else { - SafeDelete(mMessage); + mMessage.release(); } return *this; @@ -61,10 +57,12 @@ Error &Error::operator=(const Error &other) Error &Error::operator=(Error &&other) { - mCode = other.mCode; - mMessage = other.mMessage; - - other.mMessage = nullptr; + if (this != &other) + { + mCode = other.mCode; + mID = other.mID; + mMessage = std::move(other.mMessage); + } return *this; } @@ -74,6 +72,11 @@ GLenum Error::getCode() const return mCode; } +GLuint Error::getID() const +{ + return mID; +} + bool Error::isError() const { return (mCode != GL_NO_ERROR); @@ -86,17 +89,15 @@ namespace egl Error::Error(EGLint errorCode) : mCode(errorCode), - mID(0), - mMessage(nullptr) + mID(0) { } Error::Error(const Error &other) : mCode(other.mCode), - mID(other.mID), - mMessage(nullptr) + mID(other.mID) { - if (other.mMessage != nullptr) + if (other.mMessage) { createMessageString(); *mMessage = *(other.mMessage); @@ -106,14 +107,8 @@ Error::Error(const Error &other) Error::Error(Error &&other) : mCode(other.mCode), mID(other.mID), - mMessage(other.mMessage) -{ - other.mMessage = nullptr; -} - -Error::~Error() + mMessage(std::move(other.mMessage)) { - SafeDelete(mMessage); } Error &Error::operator=(const Error &other) @@ -121,14 +116,14 @@ Error &Error::operator=(const Error &other) mCode = other.mCode; mID = other.mID; - if (other.mMessage != nullptr) + if (other.mMessage) { createMessageString(); *mMessage = *(other.mMessage); } else { - SafeDelete(mMessage); + mMessage.release(); } return *this; @@ -136,11 +131,12 @@ Error &Error::operator=(const Error &other) Error &Error::operator=(Error &&other) { - mCode = other.mCode; - mID = other.mID; - mMessage = other.mMessage; - - other.mMessage = nullptr; + if (this != &other) + { + mCode = other.mCode; + mID = other.mID; + mMessage = std::move(other.mMessage); + } return *this; } diff --git a/src/3rdparty/angle/src/libANGLE/Fence.cpp b/src/3rdparty/angle/src/libANGLE/Fence.cpp index 8ab4cc9daa..ff32f4bbe9 100644 --- a/src/3rdparty/angle/src/libANGLE/Fence.cpp +++ b/src/3rdparty/angle/src/libANGLE/Fence.cpp @@ -32,16 +32,9 @@ FenceNV::~FenceNV() SafeDelete(mFence); } -GLboolean FenceNV::isFence() const +Error FenceNV::set(GLenum condition) { - // GL_NV_fence spec: - // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return (mIsSet ? GL_TRUE : GL_FALSE); -} - -Error FenceNV::setFence(GLenum condition) -{ - Error error = mFence->set(); + Error error = mFence->set(condition); if (error.isError()) { return error; @@ -54,10 +47,10 @@ Error FenceNV::setFence(GLenum condition) return Error(GL_NO_ERROR); } -Error FenceNV::testFence(GLboolean *outResult) +Error FenceNV::test(GLboolean *outResult) { // Flush the command buffer by default - Error error = mFence->test(true, &mStatus); + Error error = mFence->test(&mStatus); if (error.isError()) { return error; @@ -67,17 +60,23 @@ Error FenceNV::testFence(GLboolean *outResult) return Error(GL_NO_ERROR); } -Error FenceNV::finishFence() +Error FenceNV::finish() { ASSERT(mIsSet); - return mFence->finishFence(&mStatus); + gl::Error error = mFence->finish(); + if (error.isError()) + { + return error; + } + + mStatus = GL_TRUE; + + return Error(GL_NO_ERROR); } FenceSync::FenceSync(rx::FenceSyncImpl *impl, GLuint id) - : RefCountObject(id), - mFence(impl), - mCondition(GL_NONE) + : RefCountObject(id), mFence(impl), mLabel(), mCondition(GL_NONE), mFlags(0) { } @@ -86,15 +85,26 @@ FenceSync::~FenceSync() SafeDelete(mFence); } -Error FenceSync::set(GLenum condition) +void FenceSync::setLabel(const std::string &label) +{ + mLabel = label; +} + +const std::string &FenceSync::getLabel() const +{ + return mLabel; +} + +Error FenceSync::set(GLenum condition, GLbitfield flags) { - Error error = mFence->set(); + Error error = mFence->set(condition, flags); if (error.isError()) { return error; } mCondition = condition; + mFlags = flags; return Error(GL_NO_ERROR); } diff --git a/src/3rdparty/angle/src/libANGLE/Fence.h b/src/3rdparty/angle/src/libANGLE/Fence.h index bcd66b6831..b2daed6f0e 100644 --- a/src/3rdparty/angle/src/libANGLE/Fence.h +++ b/src/3rdparty/angle/src/libANGLE/Fence.h @@ -10,6 +10,7 @@ #ifndef LIBANGLE_FENCE_H_ #define LIBANGLE_FENCE_H_ +#include "libANGLE/Debug.h" #include "libANGLE/Error.h" #include "libANGLE/RefCountObject.h" @@ -30,11 +31,11 @@ class FenceNV final : angle::NonCopyable explicit FenceNV(rx::FenceNVImpl *impl); virtual ~FenceNV(); - GLboolean isFence() const; - Error setFence(GLenum condition); - Error testFence(GLboolean *outResult); - Error finishFence(); + Error set(GLenum condition); + Error test(GLboolean *outResult); + Error finish(); + bool isSet() const { return mIsSet; } GLboolean getStatus() const { return mStatus; } GLenum getCondition() const { return mCondition; } @@ -47,23 +48,30 @@ class FenceNV final : angle::NonCopyable GLenum mCondition; }; -class FenceSync final : public RefCountObject +class FenceSync final : public RefCountObject, public LabeledObject { public: - explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id); + FenceSync(rx::FenceSyncImpl *impl, GLuint id); virtual ~FenceSync(); - Error set(GLenum condition); + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + + Error set(GLenum condition, GLbitfield flags); Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult); Error serverWait(GLbitfield flags, GLuint64 timeout); Error getStatus(GLint *outResult) const; GLenum getCondition() const { return mCondition; } + GLbitfield getFlags() const { return mFlags; } private: rx::FenceSyncImpl *mFence; + std::string mLabel; + GLenum mCondition; + GLbitfield mFlags; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp deleted file mode 100644 index 5bf7b3fce8..0000000000 --- a/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp +++ /dev/null @@ -1,2203 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// This file is automatically generated. - -namespace gl -{ - -const static unsigned g_mantissa[2048] = { - 0x00000000, - 0x33800000, - 0x34000000, - 0x34400000, - 0x34800000, - 0x34a00000, - 0x34c00000, - 0x34e00000, - 0x35000000, - 0x35100000, - 0x35200000, - 0x35300000, - 0x35400000, - 0x35500000, - 0x35600000, - 0x35700000, - 0x35800000, - 0x35880000, - 0x35900000, - 0x35980000, - 0x35a00000, - 0x35a80000, - 0x35b00000, - 0x35b80000, - 0x35c00000, - 0x35c80000, - 0x35d00000, - 0x35d80000, - 0x35e00000, - 0x35e80000, - 0x35f00000, - 0x35f80000, - 0x36000000, - 0x36040000, - 0x36080000, - 0x360c0000, - 0x36100000, - 0x36140000, - 0x36180000, - 0x361c0000, - 0x36200000, - 0x36240000, - 0x36280000, - 0x362c0000, - 0x36300000, - 0x36340000, - 0x36380000, - 0x363c0000, - 0x36400000, - 0x36440000, - 0x36480000, - 0x364c0000, - 0x36500000, - 0x36540000, - 0x36580000, - 0x365c0000, - 0x36600000, - 0x36640000, - 0x36680000, - 0x366c0000, - 0x36700000, - 0x36740000, - 0x36780000, - 0x367c0000, - 0x36800000, - 0x36820000, - 0x36840000, - 0x36860000, - 0x36880000, - 0x368a0000, - 0x368c0000, - 0x368e0000, - 0x36900000, - 0x36920000, - 0x36940000, - 0x36960000, - 0x36980000, - 0x369a0000, - 0x369c0000, - 0x369e0000, - 0x36a00000, - 0x36a20000, - 0x36a40000, - 0x36a60000, - 0x36a80000, - 0x36aa0000, - 0x36ac0000, - 0x36ae0000, - 0x36b00000, - 0x36b20000, - 0x36b40000, - 0x36b60000, - 0x36b80000, - 0x36ba0000, - 0x36bc0000, - 0x36be0000, - 0x36c00000, - 0x36c20000, - 0x36c40000, - 0x36c60000, - 0x36c80000, - 0x36ca0000, - 0x36cc0000, - 0x36ce0000, - 0x36d00000, - 0x36d20000, - 0x36d40000, - 0x36d60000, - 0x36d80000, - 0x36da0000, - 0x36dc0000, - 0x36de0000, - 0x36e00000, - 0x36e20000, - 0x36e40000, - 0x36e60000, - 0x36e80000, - 0x36ea0000, - 0x36ec0000, - 0x36ee0000, - 0x36f00000, - 0x36f20000, - 0x36f40000, - 0x36f60000, - 0x36f80000, - 0x36fa0000, - 0x36fc0000, - 0x36fe0000, - 0x37000000, - 0x37010000, - 0x37020000, - 0x37030000, - 0x37040000, - 0x37050000, - 0x37060000, - 0x37070000, - 0x37080000, - 0x37090000, - 0x370a0000, - 0x370b0000, - 0x370c0000, - 0x370d0000, - 0x370e0000, - 0x370f0000, - 0x37100000, - 0x37110000, - 0x37120000, - 0x37130000, - 0x37140000, - 0x37150000, - 0x37160000, - 0x37170000, - 0x37180000, - 0x37190000, - 0x371a0000, - 0x371b0000, - 0x371c0000, - 0x371d0000, - 0x371e0000, - 0x371f0000, - 0x37200000, - 0x37210000, - 0x37220000, - 0x37230000, - 0x37240000, - 0x37250000, - 0x37260000, - 0x37270000, - 0x37280000, - 0x37290000, - 0x372a0000, - 0x372b0000, - 0x372c0000, - 0x372d0000, - 0x372e0000, - 0x372f0000, - 0x37300000, - 0x37310000, - 0x37320000, - 0x37330000, - 0x37340000, - 0x37350000, - 0x37360000, - 0x37370000, - 0x37380000, - 0x37390000, - 0x373a0000, - 0x373b0000, - 0x373c0000, - 0x373d0000, - 0x373e0000, - 0x373f0000, - 0x37400000, - 0x37410000, - 0x37420000, - 0x37430000, - 0x37440000, - 0x37450000, - 0x37460000, - 0x37470000, - 0x37480000, - 0x37490000, - 0x374a0000, - 0x374b0000, - 0x374c0000, - 0x374d0000, - 0x374e0000, - 0x374f0000, - 0x37500000, - 0x37510000, - 0x37520000, - 0x37530000, - 0x37540000, - 0x37550000, - 0x37560000, - 0x37570000, - 0x37580000, - 0x37590000, - 0x375a0000, - 0x375b0000, - 0x375c0000, - 0x375d0000, - 0x375e0000, - 0x375f0000, - 0x37600000, - 0x37610000, - 0x37620000, - 0x37630000, - 0x37640000, - 0x37650000, - 0x37660000, - 0x37670000, - 0x37680000, - 0x37690000, - 0x376a0000, - 0x376b0000, - 0x376c0000, - 0x376d0000, - 0x376e0000, - 0x376f0000, - 0x37700000, - 0x37710000, - 0x37720000, - 0x37730000, - 0x37740000, - 0x37750000, - 0x37760000, - 0x37770000, - 0x37780000, - 0x37790000, - 0x377a0000, - 0x377b0000, - 0x377c0000, - 0x377d0000, - 0x377e0000, - 0x377f0000, - 0x37800000, - 0x37808000, - 0x37810000, - 0x37818000, - 0x37820000, - 0x37828000, - 0x37830000, - 0x37838000, - 0x37840000, - 0x37848000, - 0x37850000, - 0x37858000, - 0x37860000, - 0x37868000, - 0x37870000, - 0x37878000, - 0x37880000, - 0x37888000, - 0x37890000, - 0x37898000, - 0x378a0000, - 0x378a8000, - 0x378b0000, - 0x378b8000, - 0x378c0000, - 0x378c8000, - 0x378d0000, - 0x378d8000, - 0x378e0000, - 0x378e8000, - 0x378f0000, - 0x378f8000, - 0x37900000, - 0x37908000, - 0x37910000, - 0x37918000, - 0x37920000, - 0x37928000, - 0x37930000, - 0x37938000, - 0x37940000, - 0x37948000, - 0x37950000, - 0x37958000, - 0x37960000, - 0x37968000, - 0x37970000, - 0x37978000, - 0x37980000, - 0x37988000, - 0x37990000, - 0x37998000, - 0x379a0000, - 0x379a8000, - 0x379b0000, - 0x379b8000, - 0x379c0000, - 0x379c8000, - 0x379d0000, - 0x379d8000, - 0x379e0000, - 0x379e8000, - 0x379f0000, - 0x379f8000, - 0x37a00000, - 0x37a08000, - 0x37a10000, - 0x37a18000, - 0x37a20000, - 0x37a28000, - 0x37a30000, - 0x37a38000, - 0x37a40000, - 0x37a48000, - 0x37a50000, - 0x37a58000, - 0x37a60000, - 0x37a68000, - 0x37a70000, - 0x37a78000, - 0x37a80000, - 0x37a88000, - 0x37a90000, - 0x37a98000, - 0x37aa0000, - 0x37aa8000, - 0x37ab0000, - 0x37ab8000, - 0x37ac0000, - 0x37ac8000, - 0x37ad0000, - 0x37ad8000, - 0x37ae0000, - 0x37ae8000, - 0x37af0000, - 0x37af8000, - 0x37b00000, - 0x37b08000, - 0x37b10000, - 0x37b18000, - 0x37b20000, - 0x37b28000, - 0x37b30000, - 0x37b38000, - 0x37b40000, - 0x37b48000, - 0x37b50000, - 0x37b58000, - 0x37b60000, - 0x37b68000, - 0x37b70000, - 0x37b78000, - 0x37b80000, - 0x37b88000, - 0x37b90000, - 0x37b98000, - 0x37ba0000, - 0x37ba8000, - 0x37bb0000, - 0x37bb8000, - 0x37bc0000, - 0x37bc8000, - 0x37bd0000, - 0x37bd8000, - 0x37be0000, - 0x37be8000, - 0x37bf0000, - 0x37bf8000, - 0x37c00000, - 0x37c08000, - 0x37c10000, - 0x37c18000, - 0x37c20000, - 0x37c28000, - 0x37c30000, - 0x37c38000, - 0x37c40000, - 0x37c48000, - 0x37c50000, - 0x37c58000, - 0x37c60000, - 0x37c68000, - 0x37c70000, - 0x37c78000, - 0x37c80000, - 0x37c88000, - 0x37c90000, - 0x37c98000, - 0x37ca0000, - 0x37ca8000, - 0x37cb0000, - 0x37cb8000, - 0x37cc0000, - 0x37cc8000, - 0x37cd0000, - 0x37cd8000, - 0x37ce0000, - 0x37ce8000, - 0x37cf0000, - 0x37cf8000, - 0x37d00000, - 0x37d08000, - 0x37d10000, - 0x37d18000, - 0x37d20000, - 0x37d28000, - 0x37d30000, - 0x37d38000, - 0x37d40000, - 0x37d48000, - 0x37d50000, - 0x37d58000, - 0x37d60000, - 0x37d68000, - 0x37d70000, - 0x37d78000, - 0x37d80000, - 0x37d88000, - 0x37d90000, - 0x37d98000, - 0x37da0000, - 0x37da8000, - 0x37db0000, - 0x37db8000, - 0x37dc0000, - 0x37dc8000, - 0x37dd0000, - 0x37dd8000, - 0x37de0000, - 0x37de8000, - 0x37df0000, - 0x37df8000, - 0x37e00000, - 0x37e08000, - 0x37e10000, - 0x37e18000, - 0x37e20000, - 0x37e28000, - 0x37e30000, - 0x37e38000, - 0x37e40000, - 0x37e48000, - 0x37e50000, - 0x37e58000, - 0x37e60000, - 0x37e68000, - 0x37e70000, - 0x37e78000, - 0x37e80000, - 0x37e88000, - 0x37e90000, - 0x37e98000, - 0x37ea0000, - 0x37ea8000, - 0x37eb0000, - 0x37eb8000, - 0x37ec0000, - 0x37ec8000, - 0x37ed0000, - 0x37ed8000, - 0x37ee0000, - 0x37ee8000, - 0x37ef0000, - 0x37ef8000, - 0x37f00000, - 0x37f08000, - 0x37f10000, - 0x37f18000, - 0x37f20000, - 0x37f28000, - 0x37f30000, - 0x37f38000, - 0x37f40000, - 0x37f48000, - 0x37f50000, - 0x37f58000, - 0x37f60000, - 0x37f68000, - 0x37f70000, - 0x37f78000, - 0x37f80000, - 0x37f88000, - 0x37f90000, - 0x37f98000, - 0x37fa0000, - 0x37fa8000, - 0x37fb0000, - 0x37fb8000, - 0x37fc0000, - 0x37fc8000, - 0x37fd0000, - 0x37fd8000, - 0x37fe0000, - 0x37fe8000, - 0x37ff0000, - 0x37ff8000, - 0x38000000, - 0x38004000, - 0x38008000, - 0x3800c000, - 0x38010000, - 0x38014000, - 0x38018000, - 0x3801c000, - 0x38020000, - 0x38024000, - 0x38028000, - 0x3802c000, - 0x38030000, - 0x38034000, - 0x38038000, - 0x3803c000, - 0x38040000, - 0x38044000, - 0x38048000, - 0x3804c000, - 0x38050000, - 0x38054000, - 0x38058000, - 0x3805c000, - 0x38060000, - 0x38064000, - 0x38068000, - 0x3806c000, - 0x38070000, - 0x38074000, - 0x38078000, - 0x3807c000, - 0x38080000, - 0x38084000, - 0x38088000, - 0x3808c000, - 0x38090000, - 0x38094000, - 0x38098000, - 0x3809c000, - 0x380a0000, - 0x380a4000, - 0x380a8000, - 0x380ac000, - 0x380b0000, - 0x380b4000, - 0x380b8000, - 0x380bc000, - 0x380c0000, - 0x380c4000, - 0x380c8000, - 0x380cc000, - 0x380d0000, - 0x380d4000, - 0x380d8000, - 0x380dc000, - 0x380e0000, - 0x380e4000, - 0x380e8000, - 0x380ec000, - 0x380f0000, - 0x380f4000, - 0x380f8000, - 0x380fc000, - 0x38100000, - 0x38104000, - 0x38108000, - 0x3810c000, - 0x38110000, - 0x38114000, - 0x38118000, - 0x3811c000, - 0x38120000, - 0x38124000, - 0x38128000, - 0x3812c000, - 0x38130000, - 0x38134000, - 0x38138000, - 0x3813c000, - 0x38140000, - 0x38144000, - 0x38148000, - 0x3814c000, - 0x38150000, - 0x38154000, - 0x38158000, - 0x3815c000, - 0x38160000, - 0x38164000, - 0x38168000, - 0x3816c000, - 0x38170000, - 0x38174000, - 0x38178000, - 0x3817c000, - 0x38180000, - 0x38184000, - 0x38188000, - 0x3818c000, - 0x38190000, - 0x38194000, - 0x38198000, - 0x3819c000, - 0x381a0000, - 0x381a4000, - 0x381a8000, - 0x381ac000, - 0x381b0000, - 0x381b4000, - 0x381b8000, - 0x381bc000, - 0x381c0000, - 0x381c4000, - 0x381c8000, - 0x381cc000, - 0x381d0000, - 0x381d4000, - 0x381d8000, - 0x381dc000, - 0x381e0000, - 0x381e4000, - 0x381e8000, - 0x381ec000, - 0x381f0000, - 0x381f4000, - 0x381f8000, - 0x381fc000, - 0x38200000, - 0x38204000, - 0x38208000, - 0x3820c000, - 0x38210000, - 0x38214000, - 0x38218000, - 0x3821c000, - 0x38220000, - 0x38224000, - 0x38228000, - 0x3822c000, - 0x38230000, - 0x38234000, - 0x38238000, - 0x3823c000, - 0x38240000, - 0x38244000, - 0x38248000, - 0x3824c000, - 0x38250000, - 0x38254000, - 0x38258000, - 0x3825c000, - 0x38260000, - 0x38264000, - 0x38268000, - 0x3826c000, - 0x38270000, - 0x38274000, - 0x38278000, - 0x3827c000, - 0x38280000, - 0x38284000, - 0x38288000, - 0x3828c000, - 0x38290000, - 0x38294000, - 0x38298000, - 0x3829c000, - 0x382a0000, - 0x382a4000, - 0x382a8000, - 0x382ac000, - 0x382b0000, - 0x382b4000, - 0x382b8000, - 0x382bc000, - 0x382c0000, - 0x382c4000, - 0x382c8000, - 0x382cc000, - 0x382d0000, - 0x382d4000, - 0x382d8000, - 0x382dc000, - 0x382e0000, - 0x382e4000, - 0x382e8000, - 0x382ec000, - 0x382f0000, - 0x382f4000, - 0x382f8000, - 0x382fc000, - 0x38300000, - 0x38304000, - 0x38308000, - 0x3830c000, - 0x38310000, - 0x38314000, - 0x38318000, - 0x3831c000, - 0x38320000, - 0x38324000, - 0x38328000, - 0x3832c000, - 0x38330000, - 0x38334000, - 0x38338000, - 0x3833c000, - 0x38340000, - 0x38344000, - 0x38348000, - 0x3834c000, - 0x38350000, - 0x38354000, - 0x38358000, - 0x3835c000, - 0x38360000, - 0x38364000, - 0x38368000, - 0x3836c000, - 0x38370000, - 0x38374000, - 0x38378000, - 0x3837c000, - 0x38380000, - 0x38384000, - 0x38388000, - 0x3838c000, - 0x38390000, - 0x38394000, - 0x38398000, - 0x3839c000, - 0x383a0000, - 0x383a4000, - 0x383a8000, - 0x383ac000, - 0x383b0000, - 0x383b4000, - 0x383b8000, - 0x383bc000, - 0x383c0000, - 0x383c4000, - 0x383c8000, - 0x383cc000, - 0x383d0000, - 0x383d4000, - 0x383d8000, - 0x383dc000, - 0x383e0000, - 0x383e4000, - 0x383e8000, - 0x383ec000, - 0x383f0000, - 0x383f4000, - 0x383f8000, - 0x383fc000, - 0x38400000, - 0x38404000, - 0x38408000, - 0x3840c000, - 0x38410000, - 0x38414000, - 0x38418000, - 0x3841c000, - 0x38420000, - 0x38424000, - 0x38428000, - 0x3842c000, - 0x38430000, - 0x38434000, - 0x38438000, - 0x3843c000, - 0x38440000, - 0x38444000, - 0x38448000, - 0x3844c000, - 0x38450000, - 0x38454000, - 0x38458000, - 0x3845c000, - 0x38460000, - 0x38464000, - 0x38468000, - 0x3846c000, - 0x38470000, - 0x38474000, - 0x38478000, - 0x3847c000, - 0x38480000, - 0x38484000, - 0x38488000, - 0x3848c000, - 0x38490000, - 0x38494000, - 0x38498000, - 0x3849c000, - 0x384a0000, - 0x384a4000, - 0x384a8000, - 0x384ac000, - 0x384b0000, - 0x384b4000, - 0x384b8000, - 0x384bc000, - 0x384c0000, - 0x384c4000, - 0x384c8000, - 0x384cc000, - 0x384d0000, - 0x384d4000, - 0x384d8000, - 0x384dc000, - 0x384e0000, - 0x384e4000, - 0x384e8000, - 0x384ec000, - 0x384f0000, - 0x384f4000, - 0x384f8000, - 0x384fc000, - 0x38500000, - 0x38504000, - 0x38508000, - 0x3850c000, - 0x38510000, - 0x38514000, - 0x38518000, - 0x3851c000, - 0x38520000, - 0x38524000, - 0x38528000, - 0x3852c000, - 0x38530000, - 0x38534000, - 0x38538000, - 0x3853c000, - 0x38540000, - 0x38544000, - 0x38548000, - 0x3854c000, - 0x38550000, - 0x38554000, - 0x38558000, - 0x3855c000, - 0x38560000, - 0x38564000, - 0x38568000, - 0x3856c000, - 0x38570000, - 0x38574000, - 0x38578000, - 0x3857c000, - 0x38580000, - 0x38584000, - 0x38588000, - 0x3858c000, - 0x38590000, - 0x38594000, - 0x38598000, - 0x3859c000, - 0x385a0000, - 0x385a4000, - 0x385a8000, - 0x385ac000, - 0x385b0000, - 0x385b4000, - 0x385b8000, - 0x385bc000, - 0x385c0000, - 0x385c4000, - 0x385c8000, - 0x385cc000, - 0x385d0000, - 0x385d4000, - 0x385d8000, - 0x385dc000, - 0x385e0000, - 0x385e4000, - 0x385e8000, - 0x385ec000, - 0x385f0000, - 0x385f4000, - 0x385f8000, - 0x385fc000, - 0x38600000, - 0x38604000, - 0x38608000, - 0x3860c000, - 0x38610000, - 0x38614000, - 0x38618000, - 0x3861c000, - 0x38620000, - 0x38624000, - 0x38628000, - 0x3862c000, - 0x38630000, - 0x38634000, - 0x38638000, - 0x3863c000, - 0x38640000, - 0x38644000, - 0x38648000, - 0x3864c000, - 0x38650000, - 0x38654000, - 0x38658000, - 0x3865c000, - 0x38660000, - 0x38664000, - 0x38668000, - 0x3866c000, - 0x38670000, - 0x38674000, - 0x38678000, - 0x3867c000, - 0x38680000, - 0x38684000, - 0x38688000, - 0x3868c000, - 0x38690000, - 0x38694000, - 0x38698000, - 0x3869c000, - 0x386a0000, - 0x386a4000, - 0x386a8000, - 0x386ac000, - 0x386b0000, - 0x386b4000, - 0x386b8000, - 0x386bc000, - 0x386c0000, - 0x386c4000, - 0x386c8000, - 0x386cc000, - 0x386d0000, - 0x386d4000, - 0x386d8000, - 0x386dc000, - 0x386e0000, - 0x386e4000, - 0x386e8000, - 0x386ec000, - 0x386f0000, - 0x386f4000, - 0x386f8000, - 0x386fc000, - 0x38700000, - 0x38704000, - 0x38708000, - 0x3870c000, - 0x38710000, - 0x38714000, - 0x38718000, - 0x3871c000, - 0x38720000, - 0x38724000, - 0x38728000, - 0x3872c000, - 0x38730000, - 0x38734000, - 0x38738000, - 0x3873c000, - 0x38740000, - 0x38744000, - 0x38748000, - 0x3874c000, - 0x38750000, - 0x38754000, - 0x38758000, - 0x3875c000, - 0x38760000, - 0x38764000, - 0x38768000, - 0x3876c000, - 0x38770000, - 0x38774000, - 0x38778000, - 0x3877c000, - 0x38780000, - 0x38784000, - 0x38788000, - 0x3878c000, - 0x38790000, - 0x38794000, - 0x38798000, - 0x3879c000, - 0x387a0000, - 0x387a4000, - 0x387a8000, - 0x387ac000, - 0x387b0000, - 0x387b4000, - 0x387b8000, - 0x387bc000, - 0x387c0000, - 0x387c4000, - 0x387c8000, - 0x387cc000, - 0x387d0000, - 0x387d4000, - 0x387d8000, - 0x387dc000, - 0x387e0000, - 0x387e4000, - 0x387e8000, - 0x387ec000, - 0x387f0000, - 0x387f4000, - 0x387f8000, - 0x387fc000, - 0x38000000, - 0x38002000, - 0x38004000, - 0x38006000, - 0x38008000, - 0x3800a000, - 0x3800c000, - 0x3800e000, - 0x38010000, - 0x38012000, - 0x38014000, - 0x38016000, - 0x38018000, - 0x3801a000, - 0x3801c000, - 0x3801e000, - 0x38020000, - 0x38022000, - 0x38024000, - 0x38026000, - 0x38028000, - 0x3802a000, - 0x3802c000, - 0x3802e000, - 0x38030000, - 0x38032000, - 0x38034000, - 0x38036000, - 0x38038000, - 0x3803a000, - 0x3803c000, - 0x3803e000, - 0x38040000, - 0x38042000, - 0x38044000, - 0x38046000, - 0x38048000, - 0x3804a000, - 0x3804c000, - 0x3804e000, - 0x38050000, - 0x38052000, - 0x38054000, - 0x38056000, - 0x38058000, - 0x3805a000, - 0x3805c000, - 0x3805e000, - 0x38060000, - 0x38062000, - 0x38064000, - 0x38066000, - 0x38068000, - 0x3806a000, - 0x3806c000, - 0x3806e000, - 0x38070000, - 0x38072000, - 0x38074000, - 0x38076000, - 0x38078000, - 0x3807a000, - 0x3807c000, - 0x3807e000, - 0x38080000, - 0x38082000, - 0x38084000, - 0x38086000, - 0x38088000, - 0x3808a000, - 0x3808c000, - 0x3808e000, - 0x38090000, - 0x38092000, - 0x38094000, - 0x38096000, - 0x38098000, - 0x3809a000, - 0x3809c000, - 0x3809e000, - 0x380a0000, - 0x380a2000, - 0x380a4000, - 0x380a6000, - 0x380a8000, - 0x380aa000, - 0x380ac000, - 0x380ae000, - 0x380b0000, - 0x380b2000, - 0x380b4000, - 0x380b6000, - 0x380b8000, - 0x380ba000, - 0x380bc000, - 0x380be000, - 0x380c0000, - 0x380c2000, - 0x380c4000, - 0x380c6000, - 0x380c8000, - 0x380ca000, - 0x380cc000, - 0x380ce000, - 0x380d0000, - 0x380d2000, - 0x380d4000, - 0x380d6000, - 0x380d8000, - 0x380da000, - 0x380dc000, - 0x380de000, - 0x380e0000, - 0x380e2000, - 0x380e4000, - 0x380e6000, - 0x380e8000, - 0x380ea000, - 0x380ec000, - 0x380ee000, - 0x380f0000, - 0x380f2000, - 0x380f4000, - 0x380f6000, - 0x380f8000, - 0x380fa000, - 0x380fc000, - 0x380fe000, - 0x38100000, - 0x38102000, - 0x38104000, - 0x38106000, - 0x38108000, - 0x3810a000, - 0x3810c000, - 0x3810e000, - 0x38110000, - 0x38112000, - 0x38114000, - 0x38116000, - 0x38118000, - 0x3811a000, - 0x3811c000, - 0x3811e000, - 0x38120000, - 0x38122000, - 0x38124000, - 0x38126000, - 0x38128000, - 0x3812a000, - 0x3812c000, - 0x3812e000, - 0x38130000, - 0x38132000, - 0x38134000, - 0x38136000, - 0x38138000, - 0x3813a000, - 0x3813c000, - 0x3813e000, - 0x38140000, - 0x38142000, - 0x38144000, - 0x38146000, - 0x38148000, - 0x3814a000, - 0x3814c000, - 0x3814e000, - 0x38150000, - 0x38152000, - 0x38154000, - 0x38156000, - 0x38158000, - 0x3815a000, - 0x3815c000, - 0x3815e000, - 0x38160000, - 0x38162000, - 0x38164000, - 0x38166000, - 0x38168000, - 0x3816a000, - 0x3816c000, - 0x3816e000, - 0x38170000, - 0x38172000, - 0x38174000, - 0x38176000, - 0x38178000, - 0x3817a000, - 0x3817c000, - 0x3817e000, - 0x38180000, - 0x38182000, - 0x38184000, - 0x38186000, - 0x38188000, - 0x3818a000, - 0x3818c000, - 0x3818e000, - 0x38190000, - 0x38192000, - 0x38194000, - 0x38196000, - 0x38198000, - 0x3819a000, - 0x3819c000, - 0x3819e000, - 0x381a0000, - 0x381a2000, - 0x381a4000, - 0x381a6000, - 0x381a8000, - 0x381aa000, - 0x381ac000, - 0x381ae000, - 0x381b0000, - 0x381b2000, - 0x381b4000, - 0x381b6000, - 0x381b8000, - 0x381ba000, - 0x381bc000, - 0x381be000, - 0x381c0000, - 0x381c2000, - 0x381c4000, - 0x381c6000, - 0x381c8000, - 0x381ca000, - 0x381cc000, - 0x381ce000, - 0x381d0000, - 0x381d2000, - 0x381d4000, - 0x381d6000, - 0x381d8000, - 0x381da000, - 0x381dc000, - 0x381de000, - 0x381e0000, - 0x381e2000, - 0x381e4000, - 0x381e6000, - 0x381e8000, - 0x381ea000, - 0x381ec000, - 0x381ee000, - 0x381f0000, - 0x381f2000, - 0x381f4000, - 0x381f6000, - 0x381f8000, - 0x381fa000, - 0x381fc000, - 0x381fe000, - 0x38200000, - 0x38202000, - 0x38204000, - 0x38206000, - 0x38208000, - 0x3820a000, - 0x3820c000, - 0x3820e000, - 0x38210000, - 0x38212000, - 0x38214000, - 0x38216000, - 0x38218000, - 0x3821a000, - 0x3821c000, - 0x3821e000, - 0x38220000, - 0x38222000, - 0x38224000, - 0x38226000, - 0x38228000, - 0x3822a000, - 0x3822c000, - 0x3822e000, - 0x38230000, - 0x38232000, - 0x38234000, - 0x38236000, - 0x38238000, - 0x3823a000, - 0x3823c000, - 0x3823e000, - 0x38240000, - 0x38242000, - 0x38244000, - 0x38246000, - 0x38248000, - 0x3824a000, - 0x3824c000, - 0x3824e000, - 0x38250000, - 0x38252000, - 0x38254000, - 0x38256000, - 0x38258000, - 0x3825a000, - 0x3825c000, - 0x3825e000, - 0x38260000, - 0x38262000, - 0x38264000, - 0x38266000, - 0x38268000, - 0x3826a000, - 0x3826c000, - 0x3826e000, - 0x38270000, - 0x38272000, - 0x38274000, - 0x38276000, - 0x38278000, - 0x3827a000, - 0x3827c000, - 0x3827e000, - 0x38280000, - 0x38282000, - 0x38284000, - 0x38286000, - 0x38288000, - 0x3828a000, - 0x3828c000, - 0x3828e000, - 0x38290000, - 0x38292000, - 0x38294000, - 0x38296000, - 0x38298000, - 0x3829a000, - 0x3829c000, - 0x3829e000, - 0x382a0000, - 0x382a2000, - 0x382a4000, - 0x382a6000, - 0x382a8000, - 0x382aa000, - 0x382ac000, - 0x382ae000, - 0x382b0000, - 0x382b2000, - 0x382b4000, - 0x382b6000, - 0x382b8000, - 0x382ba000, - 0x382bc000, - 0x382be000, - 0x382c0000, - 0x382c2000, - 0x382c4000, - 0x382c6000, - 0x382c8000, - 0x382ca000, - 0x382cc000, - 0x382ce000, - 0x382d0000, - 0x382d2000, - 0x382d4000, - 0x382d6000, - 0x382d8000, - 0x382da000, - 0x382dc000, - 0x382de000, - 0x382e0000, - 0x382e2000, - 0x382e4000, - 0x382e6000, - 0x382e8000, - 0x382ea000, - 0x382ec000, - 0x382ee000, - 0x382f0000, - 0x382f2000, - 0x382f4000, - 0x382f6000, - 0x382f8000, - 0x382fa000, - 0x382fc000, - 0x382fe000, - 0x38300000, - 0x38302000, - 0x38304000, - 0x38306000, - 0x38308000, - 0x3830a000, - 0x3830c000, - 0x3830e000, - 0x38310000, - 0x38312000, - 0x38314000, - 0x38316000, - 0x38318000, - 0x3831a000, - 0x3831c000, - 0x3831e000, - 0x38320000, - 0x38322000, - 0x38324000, - 0x38326000, - 0x38328000, - 0x3832a000, - 0x3832c000, - 0x3832e000, - 0x38330000, - 0x38332000, - 0x38334000, - 0x38336000, - 0x38338000, - 0x3833a000, - 0x3833c000, - 0x3833e000, - 0x38340000, - 0x38342000, - 0x38344000, - 0x38346000, - 0x38348000, - 0x3834a000, - 0x3834c000, - 0x3834e000, - 0x38350000, - 0x38352000, - 0x38354000, - 0x38356000, - 0x38358000, - 0x3835a000, - 0x3835c000, - 0x3835e000, - 0x38360000, - 0x38362000, - 0x38364000, - 0x38366000, - 0x38368000, - 0x3836a000, - 0x3836c000, - 0x3836e000, - 0x38370000, - 0x38372000, - 0x38374000, - 0x38376000, - 0x38378000, - 0x3837a000, - 0x3837c000, - 0x3837e000, - 0x38380000, - 0x38382000, - 0x38384000, - 0x38386000, - 0x38388000, - 0x3838a000, - 0x3838c000, - 0x3838e000, - 0x38390000, - 0x38392000, - 0x38394000, - 0x38396000, - 0x38398000, - 0x3839a000, - 0x3839c000, - 0x3839e000, - 0x383a0000, - 0x383a2000, - 0x383a4000, - 0x383a6000, - 0x383a8000, - 0x383aa000, - 0x383ac000, - 0x383ae000, - 0x383b0000, - 0x383b2000, - 0x383b4000, - 0x383b6000, - 0x383b8000, - 0x383ba000, - 0x383bc000, - 0x383be000, - 0x383c0000, - 0x383c2000, - 0x383c4000, - 0x383c6000, - 0x383c8000, - 0x383ca000, - 0x383cc000, - 0x383ce000, - 0x383d0000, - 0x383d2000, - 0x383d4000, - 0x383d6000, - 0x383d8000, - 0x383da000, - 0x383dc000, - 0x383de000, - 0x383e0000, - 0x383e2000, - 0x383e4000, - 0x383e6000, - 0x383e8000, - 0x383ea000, - 0x383ec000, - 0x383ee000, - 0x383f0000, - 0x383f2000, - 0x383f4000, - 0x383f6000, - 0x383f8000, - 0x383fa000, - 0x383fc000, - 0x383fe000, - 0x38400000, - 0x38402000, - 0x38404000, - 0x38406000, - 0x38408000, - 0x3840a000, - 0x3840c000, - 0x3840e000, - 0x38410000, - 0x38412000, - 0x38414000, - 0x38416000, - 0x38418000, - 0x3841a000, - 0x3841c000, - 0x3841e000, - 0x38420000, - 0x38422000, - 0x38424000, - 0x38426000, - 0x38428000, - 0x3842a000, - 0x3842c000, - 0x3842e000, - 0x38430000, - 0x38432000, - 0x38434000, - 0x38436000, - 0x38438000, - 0x3843a000, - 0x3843c000, - 0x3843e000, - 0x38440000, - 0x38442000, - 0x38444000, - 0x38446000, - 0x38448000, - 0x3844a000, - 0x3844c000, - 0x3844e000, - 0x38450000, - 0x38452000, - 0x38454000, - 0x38456000, - 0x38458000, - 0x3845a000, - 0x3845c000, - 0x3845e000, - 0x38460000, - 0x38462000, - 0x38464000, - 0x38466000, - 0x38468000, - 0x3846a000, - 0x3846c000, - 0x3846e000, - 0x38470000, - 0x38472000, - 0x38474000, - 0x38476000, - 0x38478000, - 0x3847a000, - 0x3847c000, - 0x3847e000, - 0x38480000, - 0x38482000, - 0x38484000, - 0x38486000, - 0x38488000, - 0x3848a000, - 0x3848c000, - 0x3848e000, - 0x38490000, - 0x38492000, - 0x38494000, - 0x38496000, - 0x38498000, - 0x3849a000, - 0x3849c000, - 0x3849e000, - 0x384a0000, - 0x384a2000, - 0x384a4000, - 0x384a6000, - 0x384a8000, - 0x384aa000, - 0x384ac000, - 0x384ae000, - 0x384b0000, - 0x384b2000, - 0x384b4000, - 0x384b6000, - 0x384b8000, - 0x384ba000, - 0x384bc000, - 0x384be000, - 0x384c0000, - 0x384c2000, - 0x384c4000, - 0x384c6000, - 0x384c8000, - 0x384ca000, - 0x384cc000, - 0x384ce000, - 0x384d0000, - 0x384d2000, - 0x384d4000, - 0x384d6000, - 0x384d8000, - 0x384da000, - 0x384dc000, - 0x384de000, - 0x384e0000, - 0x384e2000, - 0x384e4000, - 0x384e6000, - 0x384e8000, - 0x384ea000, - 0x384ec000, - 0x384ee000, - 0x384f0000, - 0x384f2000, - 0x384f4000, - 0x384f6000, - 0x384f8000, - 0x384fa000, - 0x384fc000, - 0x384fe000, - 0x38500000, - 0x38502000, - 0x38504000, - 0x38506000, - 0x38508000, - 0x3850a000, - 0x3850c000, - 0x3850e000, - 0x38510000, - 0x38512000, - 0x38514000, - 0x38516000, - 0x38518000, - 0x3851a000, - 0x3851c000, - 0x3851e000, - 0x38520000, - 0x38522000, - 0x38524000, - 0x38526000, - 0x38528000, - 0x3852a000, - 0x3852c000, - 0x3852e000, - 0x38530000, - 0x38532000, - 0x38534000, - 0x38536000, - 0x38538000, - 0x3853a000, - 0x3853c000, - 0x3853e000, - 0x38540000, - 0x38542000, - 0x38544000, - 0x38546000, - 0x38548000, - 0x3854a000, - 0x3854c000, - 0x3854e000, - 0x38550000, - 0x38552000, - 0x38554000, - 0x38556000, - 0x38558000, - 0x3855a000, - 0x3855c000, - 0x3855e000, - 0x38560000, - 0x38562000, - 0x38564000, - 0x38566000, - 0x38568000, - 0x3856a000, - 0x3856c000, - 0x3856e000, - 0x38570000, - 0x38572000, - 0x38574000, - 0x38576000, - 0x38578000, - 0x3857a000, - 0x3857c000, - 0x3857e000, - 0x38580000, - 0x38582000, - 0x38584000, - 0x38586000, - 0x38588000, - 0x3858a000, - 0x3858c000, - 0x3858e000, - 0x38590000, - 0x38592000, - 0x38594000, - 0x38596000, - 0x38598000, - 0x3859a000, - 0x3859c000, - 0x3859e000, - 0x385a0000, - 0x385a2000, - 0x385a4000, - 0x385a6000, - 0x385a8000, - 0x385aa000, - 0x385ac000, - 0x385ae000, - 0x385b0000, - 0x385b2000, - 0x385b4000, - 0x385b6000, - 0x385b8000, - 0x385ba000, - 0x385bc000, - 0x385be000, - 0x385c0000, - 0x385c2000, - 0x385c4000, - 0x385c6000, - 0x385c8000, - 0x385ca000, - 0x385cc000, - 0x385ce000, - 0x385d0000, - 0x385d2000, - 0x385d4000, - 0x385d6000, - 0x385d8000, - 0x385da000, - 0x385dc000, - 0x385de000, - 0x385e0000, - 0x385e2000, - 0x385e4000, - 0x385e6000, - 0x385e8000, - 0x385ea000, - 0x385ec000, - 0x385ee000, - 0x385f0000, - 0x385f2000, - 0x385f4000, - 0x385f6000, - 0x385f8000, - 0x385fa000, - 0x385fc000, - 0x385fe000, - 0x38600000, - 0x38602000, - 0x38604000, - 0x38606000, - 0x38608000, - 0x3860a000, - 0x3860c000, - 0x3860e000, - 0x38610000, - 0x38612000, - 0x38614000, - 0x38616000, - 0x38618000, - 0x3861a000, - 0x3861c000, - 0x3861e000, - 0x38620000, - 0x38622000, - 0x38624000, - 0x38626000, - 0x38628000, - 0x3862a000, - 0x3862c000, - 0x3862e000, - 0x38630000, - 0x38632000, - 0x38634000, - 0x38636000, - 0x38638000, - 0x3863a000, - 0x3863c000, - 0x3863e000, - 0x38640000, - 0x38642000, - 0x38644000, - 0x38646000, - 0x38648000, - 0x3864a000, - 0x3864c000, - 0x3864e000, - 0x38650000, - 0x38652000, - 0x38654000, - 0x38656000, - 0x38658000, - 0x3865a000, - 0x3865c000, - 0x3865e000, - 0x38660000, - 0x38662000, - 0x38664000, - 0x38666000, - 0x38668000, - 0x3866a000, - 0x3866c000, - 0x3866e000, - 0x38670000, - 0x38672000, - 0x38674000, - 0x38676000, - 0x38678000, - 0x3867a000, - 0x3867c000, - 0x3867e000, - 0x38680000, - 0x38682000, - 0x38684000, - 0x38686000, - 0x38688000, - 0x3868a000, - 0x3868c000, - 0x3868e000, - 0x38690000, - 0x38692000, - 0x38694000, - 0x38696000, - 0x38698000, - 0x3869a000, - 0x3869c000, - 0x3869e000, - 0x386a0000, - 0x386a2000, - 0x386a4000, - 0x386a6000, - 0x386a8000, - 0x386aa000, - 0x386ac000, - 0x386ae000, - 0x386b0000, - 0x386b2000, - 0x386b4000, - 0x386b6000, - 0x386b8000, - 0x386ba000, - 0x386bc000, - 0x386be000, - 0x386c0000, - 0x386c2000, - 0x386c4000, - 0x386c6000, - 0x386c8000, - 0x386ca000, - 0x386cc000, - 0x386ce000, - 0x386d0000, - 0x386d2000, - 0x386d4000, - 0x386d6000, - 0x386d8000, - 0x386da000, - 0x386dc000, - 0x386de000, - 0x386e0000, - 0x386e2000, - 0x386e4000, - 0x386e6000, - 0x386e8000, - 0x386ea000, - 0x386ec000, - 0x386ee000, - 0x386f0000, - 0x386f2000, - 0x386f4000, - 0x386f6000, - 0x386f8000, - 0x386fa000, - 0x386fc000, - 0x386fe000, - 0x38700000, - 0x38702000, - 0x38704000, - 0x38706000, - 0x38708000, - 0x3870a000, - 0x3870c000, - 0x3870e000, - 0x38710000, - 0x38712000, - 0x38714000, - 0x38716000, - 0x38718000, - 0x3871a000, - 0x3871c000, - 0x3871e000, - 0x38720000, - 0x38722000, - 0x38724000, - 0x38726000, - 0x38728000, - 0x3872a000, - 0x3872c000, - 0x3872e000, - 0x38730000, - 0x38732000, - 0x38734000, - 0x38736000, - 0x38738000, - 0x3873a000, - 0x3873c000, - 0x3873e000, - 0x38740000, - 0x38742000, - 0x38744000, - 0x38746000, - 0x38748000, - 0x3874a000, - 0x3874c000, - 0x3874e000, - 0x38750000, - 0x38752000, - 0x38754000, - 0x38756000, - 0x38758000, - 0x3875a000, - 0x3875c000, - 0x3875e000, - 0x38760000, - 0x38762000, - 0x38764000, - 0x38766000, - 0x38768000, - 0x3876a000, - 0x3876c000, - 0x3876e000, - 0x38770000, - 0x38772000, - 0x38774000, - 0x38776000, - 0x38778000, - 0x3877a000, - 0x3877c000, - 0x3877e000, - 0x38780000, - 0x38782000, - 0x38784000, - 0x38786000, - 0x38788000, - 0x3878a000, - 0x3878c000, - 0x3878e000, - 0x38790000, - 0x38792000, - 0x38794000, - 0x38796000, - 0x38798000, - 0x3879a000, - 0x3879c000, - 0x3879e000, - 0x387a0000, - 0x387a2000, - 0x387a4000, - 0x387a6000, - 0x387a8000, - 0x387aa000, - 0x387ac000, - 0x387ae000, - 0x387b0000, - 0x387b2000, - 0x387b4000, - 0x387b6000, - 0x387b8000, - 0x387ba000, - 0x387bc000, - 0x387be000, - 0x387c0000, - 0x387c2000, - 0x387c4000, - 0x387c6000, - 0x387c8000, - 0x387ca000, - 0x387cc000, - 0x387ce000, - 0x387d0000, - 0x387d2000, - 0x387d4000, - 0x387d6000, - 0x387d8000, - 0x387da000, - 0x387dc000, - 0x387de000, - 0x387e0000, - 0x387e2000, - 0x387e4000, - 0x387e6000, - 0x387e8000, - 0x387ea000, - 0x387ec000, - 0x387ee000, - 0x387f0000, - 0x387f2000, - 0x387f4000, - 0x387f6000, - 0x387f8000, - 0x387fa000, - 0x387fc000, - 0x387fe000, -}; - -const static unsigned g_exponent[64] = { - 0x00000000, - 0x00800000, - 0x01000000, - 0x01800000, - 0x02000000, - 0x02800000, - 0x03000000, - 0x03800000, - 0x04000000, - 0x04800000, - 0x05000000, - 0x05800000, - 0x06000000, - 0x06800000, - 0x07000000, - 0x07800000, - 0x08000000, - 0x08800000, - 0x09000000, - 0x09800000, - 0x0a000000, - 0x0a800000, - 0x0b000000, - 0x0b800000, - 0x0c000000, - 0x0c800000, - 0x0d000000, - 0x0d800000, - 0x0e000000, - 0x0e800000, - 0x0f000000, - 0x47800000, - 0x80000000, - 0x80800000, - 0x81000000, - 0x81800000, - 0x82000000, - 0x82800000, - 0x83000000, - 0x83800000, - 0x84000000, - 0x84800000, - 0x85000000, - 0x85800000, - 0x86000000, - 0x86800000, - 0x87000000, - 0x87800000, - 0x88000000, - 0x88800000, - 0x89000000, - 0x89800000, - 0x8a000000, - 0x8a800000, - 0x8b000000, - 0x8b800000, - 0x8c000000, - 0x8c800000, - 0x8d000000, - 0x8d800000, - 0x8e000000, - 0x8e800000, - 0x8f000000, - 0xc7800000, -}; - -const static unsigned g_offset[64] = { - 0x00000000, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000000, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, - 0x00000400, -}; - -float float16ToFloat32(unsigned short h) -{ - unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10]; - return *(float*) &i32; -} -} - diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp index b1dd4a1b0f..3def57b87e 100644 --- a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp @@ -9,6 +9,7 @@ #include "libANGLE/Framebuffer.h" +#include "common/Optional.h" #include "common/utilities.h" #include "libANGLE/Config.h" #include "libANGLE/Context.h" @@ -20,81 +21,164 @@ #include "libANGLE/renderer/FramebufferImpl.h" #include "libANGLE/renderer/ImplFactory.h" #include "libANGLE/renderer/RenderbufferImpl.h" -#include "libANGLE/renderer/Workarounds.h" +#include "libANGLE/renderer/SurfaceImpl.h" namespace gl { namespace { -void DeleteMatchingAttachment(FramebufferAttachment *&attachment, GLenum matchType, GLuint matchId) +void DetachMatchingAttachment(FramebufferAttachment *attachment, GLenum matchType, GLuint matchId) { - if (attachment && attachment->type() == matchType && attachment->id() == matchId) + if (attachment->isAttached() && + attachment->type() == matchType && + attachment->id() == matchId) { - SafeDelete(attachment); + attachment->detach(); } } } +Framebuffer::Data::Data() + : mLabel(), + mColorAttachments(1), + mDrawBufferStates(1, GL_NONE), + mReadBufferState(GL_COLOR_ATTACHMENT0_EXT) +{ + mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; +} + Framebuffer::Data::Data(const Caps &caps) - : mColorAttachments(caps.maxColorAttachments, nullptr), - mDepthAttachment(nullptr), - mStencilAttachment(nullptr), + : mLabel(), + mColorAttachments(caps.maxColorAttachments), mDrawBufferStates(caps.maxDrawBuffers, GL_NONE), mReadBufferState(GL_COLOR_ATTACHMENT0_EXT) { + ASSERT(mDrawBufferStates.size() > 0); mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; } Framebuffer::Data::~Data() { - for (auto it = mColorAttachments.begin(); it != mColorAttachments.end(); ++it) - { - SafeDelete(*it); - } - SafeDelete(mDepthAttachment); - SafeDelete(mStencilAttachment); } -FramebufferAttachment *Framebuffer::Data::getReadAttachment() const +const std::string &Framebuffer::Data::getLabel() +{ + return mLabel; +} + +const FramebufferAttachment *Framebuffer::Data::getReadAttachment() const { ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15)); size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast(mReadBufferState - GL_COLOR_ATTACHMENT0)); ASSERT(readIndex < mColorAttachments.size()); - return mColorAttachments[readIndex]; + return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr; } -FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const +const FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const { - for (auto it = mColorAttachments.cbegin(); it != mColorAttachments.cend(); ++it) + for (const FramebufferAttachment &colorAttachment : mColorAttachments) { - if (*it != nullptr) + if (colorAttachment.isAttached()) { - return *it; + return &colorAttachment; } } return nullptr; } -FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const +const FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const { - return (mDepthAttachment != nullptr ? mDepthAttachment : mStencilAttachment); + if (mDepthAttachment.isAttached()) + { + return &mDepthAttachment; + } + if (mStencilAttachment.isAttached()) + { + return &mStencilAttachment; + } + return nullptr; } -Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id) - : mData(caps), - mImpl(nullptr), - mId(id) +const FramebufferAttachment *Framebuffer::Data::getColorAttachment(size_t colorAttachment) const { - if (mId == 0) + ASSERT(colorAttachment < mColorAttachments.size()); + return mColorAttachments[colorAttachment].isAttached() ? + &mColorAttachments[colorAttachment] : + nullptr; +} + +const FramebufferAttachment *Framebuffer::Data::getDepthAttachment() const +{ + return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr; +} + +const FramebufferAttachment *Framebuffer::Data::getStencilAttachment() const +{ + return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr; +} + +const FramebufferAttachment *Framebuffer::Data::getDepthStencilAttachment() const +{ + // A valid depth-stencil attachment has the same resource bound to both the + // depth and stencil attachment points. + if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() && + mDepthAttachment.type() == mStencilAttachment.type() && + mDepthAttachment.id() == mStencilAttachment.id()) { - mImpl = factory->createDefaultFramebuffer(mData); + return &mDepthAttachment; } - else + + return nullptr; +} + +bool Framebuffer::Data::attachmentsHaveSameDimensions() const +{ + Optional attachmentSize; + + auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) + { + if (!attachment.isAttached()) + { + return false; + } + + if (!attachmentSize.valid()) + { + attachmentSize = attachment.getSize(); + return false; + } + + return (attachment.getSize() != attachmentSize.value()); + }; + + for (const auto &attachment : mColorAttachments) + { + if (hasMismatchedSize(attachment)) + { + return false; + } + } + + if (hasMismatchedSize(mDepthAttachment)) { - mImpl = factory->createFramebuffer(mData); + return false; } + + return !hasMismatchedSize(mStencilAttachment); +} + +Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id) + : mData(caps), mImpl(factory->createFramebuffer(mData)), mId(id) +{ + ASSERT(mId != 0); + ASSERT(mImpl != nullptr); +} + +Framebuffer::Framebuffer(rx::SurfaceImpl *surface) + : mData(), mImpl(surface->createDefaultFramebuffer(mData)), mId(0) +{ ASSERT(mImpl != nullptr); } @@ -103,6 +187,16 @@ Framebuffer::~Framebuffer() SafeDelete(mImpl); } +void Framebuffer::setLabel(const std::string &label) +{ + mData.mLabel = label; +} + +const std::string &Framebuffer::getLabel() const +{ + return mData.mLabel; +} + void Framebuffer::detachTexture(GLuint textureId) { detachResourceById(GL_TEXTURE, textureId); @@ -115,62 +209,61 @@ void Framebuffer::detachRenderbuffer(GLuint renderbufferId) void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId) { - for (auto it = mData.mColorAttachments.begin(); it != mData.mColorAttachments.end(); ++it) + for (auto &colorAttachment : mData.mColorAttachments) { - DeleteMatchingAttachment(*it, resourceType, resourceId); + DetachMatchingAttachment(&colorAttachment, resourceType, resourceId); } - DeleteMatchingAttachment(mData.mDepthAttachment, resourceType, resourceId); - DeleteMatchingAttachment(mData.mStencilAttachment, resourceType, resourceId); + DetachMatchingAttachment(&mData.mDepthAttachment, resourceType, resourceId); + DetachMatchingAttachment(&mData.mStencilAttachment, resourceType, resourceId); } -FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const +const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const { - ASSERT(colorAttachment < mData.mColorAttachments.size()); - return mData.mColorAttachments[colorAttachment]; + return mData.getColorAttachment(colorAttachment); } -FramebufferAttachment *Framebuffer::getDepthbuffer() const +const FramebufferAttachment *Framebuffer::getDepthbuffer() const { - return mData.mDepthAttachment; + return mData.getDepthAttachment(); } -FramebufferAttachment *Framebuffer::getStencilbuffer() const +const FramebufferAttachment *Framebuffer::getStencilbuffer() const { - return mData.mStencilAttachment; + return mData.getStencilAttachment(); } -FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const +const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const { - return (hasValidDepthStencil() ? mData.mDepthAttachment : NULL); + return mData.getDepthStencilAttachment(); } -FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const +const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const { return mData.getDepthOrStencilAttachment(); } -FramebufferAttachment *Framebuffer::getReadColorbuffer() const +const FramebufferAttachment *Framebuffer::getReadColorbuffer() const { return mData.getReadAttachment(); } GLenum Framebuffer::getReadColorbufferType() const { - FramebufferAttachment *readAttachment = mData.getReadAttachment(); - return (readAttachment ? readAttachment->type() : GL_NONE); + const FramebufferAttachment *readAttachment = mData.getReadAttachment(); + return (readAttachment != nullptr ? readAttachment->type() : GL_NONE); } -FramebufferAttachment *Framebuffer::getFirstColorbuffer() const +const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const { return mData.getFirstColorAttachment(); } -FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const +const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const { if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) { - return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0); + return mData.getColorAttachment(attachment - GL_COLOR_ATTACHMENT0); } else { @@ -178,27 +271,32 @@ FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const { case GL_COLOR: case GL_BACK: - return getColorbuffer(0); + return mData.getColorAttachment(0); case GL_DEPTH: case GL_DEPTH_ATTACHMENT: - return getDepthbuffer(); + return mData.getDepthAttachment(); case GL_STENCIL: case GL_STENCIL_ATTACHMENT: - return getStencilbuffer(); + return mData.getStencilAttachment(); case GL_DEPTH_STENCIL: case GL_DEPTH_STENCIL_ATTACHMENT: return getDepthStencilBuffer(); default: UNREACHABLE(); - return NULL; + return nullptr; } } } -GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const +size_t Framebuffer::getDrawbufferStateCount() const { - ASSERT(colorAttachment < mData.mDrawBufferStates.size()); - return mData.mDrawBufferStates[colorAttachment]; + return mData.mDrawBufferStates.size(); +} + +GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const +{ + ASSERT(drawBuffer < mData.mDrawBufferStates.size()); + return mData.mDrawBufferStates[drawBuffer]; } void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers) @@ -208,7 +306,37 @@ void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers) ASSERT(count <= drawStates.size()); std::copy(buffers, buffers + count, drawStates.begin()); std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE); - mImpl->setDrawBuffers(count, buffers); + mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS); +} + +const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const +{ + ASSERT(drawBuffer < mData.mDrawBufferStates.size()); + if (mData.mDrawBufferStates[drawBuffer] != GL_NONE) + { + // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs + // must be COLOR_ATTACHMENTi or NONE" + ASSERT(mData.mDrawBufferStates[drawBuffer] == GL_COLOR_ATTACHMENT0 + drawBuffer || + (drawBuffer == 0 && mData.mDrawBufferStates[drawBuffer] == GL_BACK)); + return getAttachment(mData.mDrawBufferStates[drawBuffer]); + } + else + { + return nullptr; + } +} + +bool Framebuffer::hasEnabledDrawBuffer() const +{ + for (size_t drawbufferIdx = 0; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx) + { + if (getDrawBuffer(drawbufferIdx) != nullptr) + { + return true; + } + } + + return false; } GLenum Framebuffer::getReadBufferState() const @@ -222,39 +350,29 @@ void Framebuffer::setReadBuffer(GLenum buffer) (buffer >= GL_COLOR_ATTACHMENT0 && (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size())); mData.mReadBufferState = buffer; - mImpl->setReadBuffer(buffer); + mDirtyBits.set(DIRTY_BIT_READ_BUFFER); } -bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const +size_t Framebuffer::getNumColorBuffers() const { - ASSERT(colorAttachment < mData.mColorAttachments.size()); - return (mData.mColorAttachments[colorAttachment] && - mData.mDrawBufferStates[colorAttachment] != GL_NONE); + return mData.mColorAttachments.size(); } -bool Framebuffer::hasEnabledColorAttachment() const +bool Framebuffer::hasDepth() const { - for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment) - { - if (isEnabledColorAttachment(colorAttachment)) - { - return true; - } - } - - return false; + return (mData.mDepthAttachment.isAttached() && mData.mDepthAttachment.getDepthSize() > 0); } bool Framebuffer::hasStencil() const { - return (mData.mStencilAttachment && mData.mStencilAttachment->getStencilSize() > 0); + return (mData.mStencilAttachment.isAttached() && mData.mStencilAttachment.getStencilSize() > 0); } bool Framebuffer::usingExtendedDrawBuffers() const { - for (size_t colorAttachment = 1; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment) + for (size_t drawbufferIdx = 1; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx) { - if (isEnabledColorAttachment(colorAttachment)) + if (getDrawBuffer(drawbufferIdx) != nullptr) { return true; } @@ -272,38 +390,52 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const return GL_FRAMEBUFFER_COMPLETE; } - int width = 0; - int height = 0; unsigned int colorbufferSize = 0; int samples = -1; bool missingAttachment = true; - for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments) { - const auto &colorAttachment = *it; - if (colorAttachment != nullptr) + if (colorAttachment.isAttached()) { - if (colorAttachment->getWidth() == 0 || colorAttachment->getHeight() == 0) + const Extents &size = colorAttachment.getSize(); + if (size.width == 0 || size.height == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - GLenum internalformat = colorAttachment->getInternalFormat(); + GLenum internalformat = colorAttachment.getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (colorAttachment->type() == GL_TEXTURE) + if (colorAttachment.type() == GL_TEXTURE) { if (!formatCaps.renderable) { - return GL_FRAMEBUFFER_UNSUPPORTED; + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } + + if (colorAttachment.layer() >= size.depth) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } + + // ES3 specifies that cube map texture attachments must be cube complete. + // This language is missing from the ES2 spec, but we enforce it here because some + // desktop OpenGL drivers also enforce this validation. + // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness. + const Texture *texture = colorAttachment.getTexture(); + ASSERT(texture); + if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete()) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } } - else if (colorAttachment->type() == GL_RENDERBUFFER) + else if (colorAttachment.type() == GL_RENDERBUFFER) { if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { @@ -313,15 +445,9 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const if (!missingAttachment) { - // all color attachments must have the same width and height - if (colorAttachment->getWidth() != width || colorAttachment->getHeight() != height) - { - return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - } - // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that // all color attachments have the same number of samples for the FBO to be complete. - if (colorAttachment->getSamples() != samples) + if (colorAttachment.getSamples() != samples) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; } @@ -338,27 +464,26 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const } else { - width = colorAttachment->getWidth(); - height = colorAttachment->getHeight(); - samples = colorAttachment->getSamples(); + samples = colorAttachment.getSamples(); colorbufferSize = formatInfo.pixelBytes; missingAttachment = false; } } } - const FramebufferAttachment *depthAttachment = mData.mDepthAttachment; - if (depthAttachment != nullptr) + const FramebufferAttachment &depthAttachment = mData.mDepthAttachment; + if (depthAttachment.isAttached()) { - if (depthAttachment->getWidth() == 0 || depthAttachment->getHeight() == 0) + const Extents &size = depthAttachment.getSize(); + if (size.width == 0 || size.height == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - GLenum internalformat = depthAttachment->getInternalFormat(); + GLenum internalformat = depthAttachment.getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (depthAttachment->type() == GL_TEXTURE) + if (depthAttachment.type() == GL_TEXTURE) { // depth texture attachments require OES/ANGLE_depth_texture if (!data.extensions->depthTextures) @@ -368,7 +493,7 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const if (!formatCaps.renderable) { - return GL_FRAMEBUFFER_UNSUPPORTED; + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (formatInfo.depthBits == 0) @@ -376,7 +501,7 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } - else if (depthAttachment->type() == GL_RENDERBUFFER) + else if (depthAttachment.type() == GL_RENDERBUFFER) { if (!formatCaps.renderable || formatInfo.depthBits == 0) { @@ -386,33 +511,28 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const if (missingAttachment) { - width = depthAttachment->getWidth(); - height = depthAttachment->getHeight(); - samples = depthAttachment->getSamples(); + samples = depthAttachment.getSamples(); missingAttachment = false; } - else if (width != depthAttachment->getWidth() || height != depthAttachment->getHeight()) - { - return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - } - else if (samples != depthAttachment->getSamples()) + else if (samples != depthAttachment.getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } } - const FramebufferAttachment *stencilAttachment = mData.mStencilAttachment; - if (stencilAttachment) + const FramebufferAttachment &stencilAttachment = mData.mStencilAttachment; + if (stencilAttachment.isAttached()) { - if (stencilAttachment->getWidth() == 0 || stencilAttachment->getHeight() == 0) + const Extents &size = stencilAttachment.getSize(); + if (size.width == 0 || size.height == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - GLenum internalformat = stencilAttachment->getInternalFormat(); + GLenum internalformat = stencilAttachment.getInternalFormat(); const TextureCaps &formatCaps = data.textureCaps->get(internalformat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); - if (stencilAttachment->type() == GL_TEXTURE) + if (stencilAttachment.type() == GL_TEXTURE) { // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture @@ -423,7 +543,7 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const if (!formatCaps.renderable) { - return GL_FRAMEBUFFER_UNSUPPORTED; + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } if (formatInfo.stencilBits == 0) @@ -431,7 +551,7 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } - else if (stencilAttachment->type() == GL_RENDERBUFFER) + else if (stencilAttachment.type() == GL_RENDERBUFFER) { if (!formatCaps.renderable || formatInfo.stencilBits == 0) { @@ -441,35 +561,40 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const if (missingAttachment) { - width = stencilAttachment->getWidth(); - height = stencilAttachment->getHeight(); - samples = stencilAttachment->getSamples(); + samples = stencilAttachment.getSamples(); missingAttachment = false; } - else if (width != stencilAttachment->getWidth() || height != stencilAttachment->getHeight()) - { - return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; - } - else if (samples != stencilAttachment->getSamples()) + else if (samples != stencilAttachment.getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } } - // if we have both a depth and stencil buffer, they must refer to the same object - // since we only support packed_depth_stencil and not separate depth and stencil - if (depthAttachment && stencilAttachment && !hasValidDepthStencil()) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - // we need to have at least one attachment to be complete if (missingAttachment) { return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; } - return mImpl->checkStatus(); + // In ES 2.0, all color attachments must have the same width and height. + // In ES 3.0, there is no such restriction. + if (data.clientVersion < 3 && !mData.attachmentsHaveSameDimensions()) + { + return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + } + + syncState(); + if (!mImpl->checkStatus()) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } + + return GL_FRAMEBUFFER_COMPLETE; +} + +Error Framebuffer::discard(size_t count, const GLenum *attachments) +{ + return mImpl->discard(count, attachments); } Error Framebuffer::invalidate(size_t count, const GLenum *attachments) @@ -484,27 +609,65 @@ Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const Error Framebuffer::clear(const gl::Data &data, GLbitfield mask) { + if (data.state->isRasterizerDiscardEnabled()) + { + return gl::Error(GL_NO_ERROR); + } + return mImpl->clear(data, mask); } -Error Framebuffer::clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) +Error Framebuffer::clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) { - return mImpl->clearBufferfv(state, buffer, drawbuffer, values); + if (data.state->isRasterizerDiscardEnabled()) + { + return gl::Error(GL_NO_ERROR); + } + + return mImpl->clearBufferfv(data, buffer, drawbuffer, values); } -Error Framebuffer::clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) +Error Framebuffer::clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) { - return mImpl->clearBufferuiv(state, buffer, drawbuffer, values); + if (data.state->isRasterizerDiscardEnabled()) + { + return gl::Error(GL_NO_ERROR); + } + + return mImpl->clearBufferuiv(data, buffer, drawbuffer, values); } -Error Framebuffer::clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values) +Error Framebuffer::clearBufferiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLint *values) { - return mImpl->clearBufferiv(state, buffer, drawbuffer, values); + if (data.state->isRasterizerDiscardEnabled()) + { + return gl::Error(GL_NO_ERROR); + } + + return mImpl->clearBufferiv(data, buffer, drawbuffer, values); } -Error Framebuffer::clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +Error Framebuffer::clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) { - return mImpl->clearBufferfi(state, buffer, drawbuffer, depth, stencil); + if (data.state->isRasterizerDiscardEnabled()) + { + return gl::Error(GL_NO_ERROR); + } + + return mImpl->clearBufferfi(data, buffer, drawbuffer, depth, stencil); } GLenum Framebuffer::getImplementationColorReadFormat() const @@ -517,13 +680,33 @@ GLenum Framebuffer::getImplementationColorReadType() const return mImpl->getImplementationColorReadType(); } -Error Framebuffer::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const +Error Framebuffer::readPixels(const State &state, + const Rectangle &area, + GLenum format, + GLenum type, + GLvoid *pixels) const { - return mImpl->readPixels(state, area, format, type, pixels); + Error error = mImpl->readPixels(state, area, format, type, pixels); + if (error.isError()) + { + return error; + } + + Buffer *unpackBuffer = state.getUnpackState().pixelBuffer.get(); + if (unpackBuffer) + { + unpackBuffer->onPixelUnpack(); + } + + return Error(GL_NO_ERROR); } -Error Framebuffer::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, - GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) +Error Framebuffer::blit(const State &state, + const Rectangle &sourceArea, + const Rectangle &destArea, + GLbitfield mask, + GLenum filter, + const Framebuffer *sourceFramebuffer) { return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer); } @@ -534,11 +717,11 @@ int Framebuffer::getSamples(const gl::Data &data) const { // for a complete framebuffer, all attachments must have the same sample count // in this case return the first nonzero sample size - for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments) { - if (*it != nullptr) + if (colorAttachment.isAttached()) { - return (*it)->getSamples(); + return colorAttachment.getSamples(); } } } @@ -548,111 +731,77 @@ int Framebuffer::getSamples(const gl::Data &data) const bool Framebuffer::hasValidDepthStencil() const { - // A valid depth-stencil attachment has the same resource bound to both the - // depth and stencil attachment points. - return (mData.mDepthAttachment && mData.mStencilAttachment && - mData.mDepthAttachment->type() == mData.mStencilAttachment->type() && - mData.mDepthAttachment->id() == mData.mStencilAttachment->id()); -} - -void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex) -{ - setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex)); + return mData.getDepthStencilAttachment() != nullptr; } -void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer) +void Framebuffer::setAttachment(GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource) { - setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer)); -} - -void Framebuffer::setNULLAttachment(GLenum attachment) -{ - setAttachment(attachment, NULL); -} - -void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj) -{ - if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + mData.mColorAttachments.size())) - { - size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0; - SafeDelete(mData.mColorAttachments[colorAttachment]); - mData.mColorAttachments[colorAttachment] = attachmentObj; - mImpl->setColorAttachment(colorAttachment, attachmentObj); - } - else if (attachment == GL_BACK) - { - SafeDelete(mData.mColorAttachments[0]); - mData.mColorAttachments[0] = attachmentObj; - mImpl->setColorAttachment(0, attachmentObj); - } - else if (attachment == GL_DEPTH_ATTACHMENT || attachment == GL_DEPTH) - { - SafeDelete(mData.mDepthAttachment); - mData.mDepthAttachment = attachmentObj; - mImpl->setDepthAttachment(attachmentObj); - } - else if (attachment == GL_STENCIL_ATTACHMENT || attachment == GL_STENCIL) + if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT) { - SafeDelete(mData.mStencilAttachment); - mData.mStencilAttachment = attachmentObj; - mImpl->setStencilAttachment(attachmentObj); - } - else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT || attachment == GL_DEPTH_STENCIL) - { - SafeDelete(mData.mDepthAttachment); - SafeDelete(mData.mStencilAttachment); - // ensure this is a legitimate depth+stencil format - if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0) + FramebufferAttachmentObject *attachmentObj = resource; + if (resource) { - mData.mDepthAttachment = attachmentObj; - mImpl->setDepthAttachment(attachmentObj); - - // Make a new attachment object to ensure we do not double-delete - // See angle issue 686 - if (attachmentObj->type() == GL_TEXTURE) - { - mData.mStencilAttachment = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(), - *attachmentObj->getTextureImageIndex()); - mImpl->setStencilAttachment(mData.mStencilAttachment); - } - else if (attachmentObj->type() == GL_RENDERBUFFER) + FramebufferAttachment::Target target(binding, textureIndex); + GLenum internalFormat = resource->getAttachmentInternalFormat(target); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat); + if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0) { - mData.mStencilAttachment = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer()); - mImpl->setStencilAttachment(mData.mStencilAttachment); - } - else - { - UNREACHABLE(); + // Attaching nullptr detaches the current attachment. + attachmentObj = nullptr; } } + + mData.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj); + mData.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj); + mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT); + mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT); } else { - UNREACHABLE(); + switch (binding) + { + case GL_DEPTH: + case GL_DEPTH_ATTACHMENT: + mData.mDepthAttachment.attach(type, binding, textureIndex, resource); + mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT); + break; + case GL_STENCIL: + case GL_STENCIL_ATTACHMENT: + mData.mStencilAttachment.attach(type, binding, textureIndex, resource); + mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT); + break; + case GL_BACK: + mData.mColorAttachments[0].attach(type, binding, textureIndex, resource); + mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0); + break; + default: + { + size_t colorIndex = binding - GL_COLOR_ATTACHMENT0; + ASSERT(colorIndex < mData.mColorAttachments.size()); + mData.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource); + mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex); + } + break; + } } } -DefaultFramebuffer::DefaultFramebuffer(const Caps &caps, rx::ImplFactory *factory, egl::Surface *surface) - : Framebuffer(caps, factory, 0) +void Framebuffer::resetAttachment(GLenum binding) { - const egl::Config *config = surface->getConfig(); - - setAttachment(GL_BACK, new DefaultAttachment(GL_BACK, surface)); + setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr); +} - if (config->depthSize > 0) - { - setAttachment(GL_DEPTH, new DefaultAttachment(GL_DEPTH, surface)); - } - if (config->stencilSize > 0) +void Framebuffer::syncState() const +{ + if (mDirtyBits.any()) { - setAttachment(GL_STENCIL, new DefaultAttachment(GL_STENCIL, surface)); + mImpl->syncState(mDirtyBits); + mDirtyBits.reset(); } - - GLenum drawBufferState = GL_BACK; - setDrawBuffers(1, &drawBufferState); - - setReadBuffer(GL_BACK); } -} +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.h b/src/3rdparty/angle/src/libANGLE/Framebuffer.h index 8b24cf984e..b07b59ac90 100644 --- a/src/3rdparty/angle/src/libANGLE/Framebuffer.h +++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.h @@ -14,7 +14,9 @@ #include "common/angleutils.h" #include "libANGLE/Constants.h" +#include "libANGLE/Debug.h" #include "libANGLE/Error.h" +#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/RefCountObject.h" namespace rx @@ -22,7 +24,7 @@ namespace rx class ImplFactory; class FramebufferImpl; class RenderbufferImpl; -struct Workarounds; +class SurfaceImpl; } namespace egl @@ -32,7 +34,7 @@ class Surface; namespace gl { -class FramebufferAttachment; +class Context; class Renderbuffer; class State; class Texture; @@ -43,64 +45,89 @@ struct Extensions; struct ImageIndex; struct Rectangle; -typedef std::vector AttachmentList; - -class Framebuffer +class Framebuffer final : public LabeledObject { public: class Data final : angle::NonCopyable { public: + explicit Data(); explicit Data(const Caps &caps); ~Data(); - FramebufferAttachment *getReadAttachment() const; - FramebufferAttachment *getFirstColorAttachment() const; - FramebufferAttachment *getDepthOrStencilAttachment() const; + const std::string &getLabel(); + + const FramebufferAttachment *getReadAttachment() const; + const FramebufferAttachment *getFirstColorAttachment() const; + const FramebufferAttachment *getDepthOrStencilAttachment() const; + const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const; + const FramebufferAttachment *getDepthAttachment() const; + const FramebufferAttachment *getStencilAttachment() const; + const FramebufferAttachment *getDepthStencilAttachment() const; + + const std::vector &getDrawBufferStates() const { return mDrawBufferStates; } + GLenum getReadBufferState() const { return mReadBufferState; } + const std::vector &getColorAttachments() const { return mColorAttachments; } + + bool attachmentsHaveSameDimensions() const; - AttachmentList mColorAttachments; - FramebufferAttachment *mDepthAttachment; - FramebufferAttachment *mStencilAttachment; + private: + friend class Framebuffer; + + std::string mLabel; + + std::vector mColorAttachments; + FramebufferAttachment mDepthAttachment; + FramebufferAttachment mStencilAttachment; std::vector mDrawBufferStates; GLenum mReadBufferState; }; Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id); + Framebuffer(rx::SurfaceImpl *surface); virtual ~Framebuffer(); + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + const rx::FramebufferImpl *getImplementation() const { return mImpl; } rx::FramebufferImpl *getImplementation() { return mImpl; } GLuint id() const { return mId; } - void setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex); - void setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer); - void setNULLAttachment(GLenum attachment); + void setAttachment(GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource); + void resetAttachment(GLenum binding); void detachTexture(GLuint texture); void detachRenderbuffer(GLuint renderbuffer); - FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const; - FramebufferAttachment *getDepthbuffer() const; - FramebufferAttachment *getStencilbuffer() const; - FramebufferAttachment *getDepthStencilBuffer() const; - FramebufferAttachment *getDepthOrStencilbuffer() const; - FramebufferAttachment *getReadColorbuffer() const; + const FramebufferAttachment *getColorbuffer(size_t colorAttachment) const; + const FramebufferAttachment *getDepthbuffer() const; + const FramebufferAttachment *getStencilbuffer() const; + const FramebufferAttachment *getDepthStencilBuffer() const; + const FramebufferAttachment *getDepthOrStencilbuffer() const; + const FramebufferAttachment *getReadColorbuffer() const; GLenum getReadColorbufferType() const; - FramebufferAttachment *getFirstColorbuffer() const; + const FramebufferAttachment *getFirstColorbuffer() const; - FramebufferAttachment *getAttachment(GLenum attachment) const; + const FramebufferAttachment *getAttachment(GLenum attachment) const; - GLenum getDrawBufferState(unsigned int colorAttachment) const; + size_t getDrawbufferStateCount() const; + GLenum getDrawBufferState(size_t drawBuffer) const; void setDrawBuffers(size_t count, const GLenum *buffers); + const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const; + bool hasEnabledDrawBuffer() const; GLenum getReadBufferState() const; void setReadBuffer(GLenum buffer); - bool isEnabledColorAttachment(unsigned int colorAttachment) const; - bool hasEnabledColorAttachment() const; + size_t getNumColorBuffers() const; + bool hasDepth() const; bool hasStencil() const; int getSamples(const gl::Data &data) const; bool usingExtendedDrawBuffers() const; @@ -108,35 +135,68 @@ class Framebuffer GLenum checkStatus(const gl::Data &data) const; bool hasValidDepthStencil() const; + Error discard(size_t count, const GLenum *attachments); Error invalidate(size_t count, const GLenum *attachments); Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area); Error clear(const gl::Data &data, GLbitfield mask); - Error clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values); - Error clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values); - Error clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values); - Error clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + Error clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values); + Error clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values); + Error clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values); + Error clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil); GLenum getImplementationColorReadFormat() const; GLenum getImplementationColorReadType() const; - Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const; + Error readPixels(const gl::State &state, + const gl::Rectangle &area, + GLenum format, + GLenum type, + GLvoid *pixels) const; + + Error blit(const State &state, + const Rectangle &sourceArea, + const Rectangle &destArea, + GLbitfield mask, + GLenum filter, + const Framebuffer *sourceFramebuffer); + + enum DirtyBitType + { + DIRTY_BIT_COLOR_ATTACHMENT_0, + DIRTY_BIT_COLOR_ATTACHMENT_MAX = + DIRTY_BIT_COLOR_ATTACHMENT_0 + gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS, + DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX, + DIRTY_BIT_STENCIL_ATTACHMENT, + DIRTY_BIT_DRAW_BUFFERS, + DIRTY_BIT_READ_BUFFER, + DIRTY_BIT_UNKNOWN, + DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN, + }; + + typedef std::bitset DirtyBits; + bool hasAnyDirtyBit() const { return mDirtyBits.any(); } - Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, - GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer); + void syncState() const; protected: - void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj); void detachResourceById(GLenum resourceType, GLuint resourceId); Data mData; rx::FramebufferImpl *mImpl; GLuint mId; -}; -class DefaultFramebuffer : public Framebuffer -{ - public: - DefaultFramebuffer(const gl::Caps &caps, rx::ImplFactory *factory, egl::Surface *surface); + // TODO(jmadill): See if we can make this non-mutable. + mutable DirtyBits mDirtyBits; }; } diff --git a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp index e56fc750ad..352a326c23 100644 --- a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp +++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp @@ -20,283 +20,189 @@ namespace gl { -////// FramebufferAttachment Implementation ////// +////// FramebufferAttachment::Target Implementation ////// -FramebufferAttachment::FramebufferAttachment(GLenum binding) - : mBinding(binding) +FramebufferAttachment::Target::Target() + : mBinding(GL_NONE), + mTextureIndex(ImageIndex::MakeInvalid()) { } -FramebufferAttachment::~FramebufferAttachment() +FramebufferAttachment::Target::Target(GLenum binding, const ImageIndex &imageIndex) + : mBinding(binding), + mTextureIndex(imageIndex) { } -GLuint FramebufferAttachment::getRedSize() const +FramebufferAttachment::Target::Target(const Target &other) + : mBinding(other.mBinding), + mTextureIndex(other.mTextureIndex) { - return GetInternalFormatInfo(getInternalFormat()).redBits; } -GLuint FramebufferAttachment::getGreenSize() const +FramebufferAttachment::Target &FramebufferAttachment::Target::operator=(const Target &other) { - return GetInternalFormatInfo(getInternalFormat()).greenBits; + this->mBinding = other.mBinding; + this->mTextureIndex = other.mTextureIndex; + return *this; } -GLuint FramebufferAttachment::getBlueSize() const -{ - return GetInternalFormatInfo(getInternalFormat()).blueBits; -} - -GLuint FramebufferAttachment::getAlphaSize() const -{ - return GetInternalFormatInfo(getInternalFormat()).alphaBits; -} - -GLuint FramebufferAttachment::getDepthSize() const -{ - return GetInternalFormatInfo(getInternalFormat()).depthBits; -} - -GLuint FramebufferAttachment::getStencilSize() const -{ - return GetInternalFormatInfo(getInternalFormat()).stencilBits; -} - -GLenum FramebufferAttachment::getComponentType() const -{ - return GetInternalFormatInfo(getInternalFormat()).componentType; -} - -GLenum FramebufferAttachment::getColorEncoding() const -{ - return GetInternalFormatInfo(getInternalFormat()).colorEncoding; -} - -///// TextureAttachment Implementation //////// - -TextureAttachment::TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index) - : FramebufferAttachment(binding), - mIndex(index) -{ - mTexture.set(texture); -} - -TextureAttachment::~TextureAttachment() -{ - mTexture.set(NULL); -} - -GLsizei TextureAttachment::getSamples() const -{ - return 0; -} - -GLuint TextureAttachment::id() const -{ - return mTexture->id(); -} - -GLsizei TextureAttachment::getWidth() const -{ - return mTexture->getWidth(mIndex.type, mIndex.mipIndex); -} - -GLsizei TextureAttachment::getHeight() const -{ - return mTexture->getHeight(mIndex.type, mIndex.mipIndex); -} - -GLenum TextureAttachment::getInternalFormat() const -{ - return mTexture->getInternalFormat(mIndex.type, mIndex.mipIndex); -} - -GLenum TextureAttachment::type() const -{ - return GL_TEXTURE; -} - -GLint TextureAttachment::mipLevel() const -{ - return mIndex.mipIndex; -} - -GLenum TextureAttachment::cubeMapFace() const -{ - return IsCubeMapTextureTarget(mIndex.type) ? mIndex.type : GL_NONE; -} - -GLint TextureAttachment::layer() const -{ - return mIndex.layerIndex; -} - -Texture *TextureAttachment::getTexture() const -{ - return mTexture.get(); -} - -const ImageIndex *TextureAttachment::getTextureImageIndex() const -{ - return &mIndex; -} - -Renderbuffer *TextureAttachment::getRenderbuffer() const -{ - UNREACHABLE(); - return NULL; -} - -////// RenderbufferAttachment Implementation ////// +////// FramebufferAttachment Implementation ////// -RenderbufferAttachment::RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer) - : FramebufferAttachment(binding) +FramebufferAttachment::FramebufferAttachment() + : mType(GL_NONE), mResource(nullptr) { - ASSERT(renderbuffer); - mRenderbuffer.set(renderbuffer); } -RenderbufferAttachment::~RenderbufferAttachment() +FramebufferAttachment::FramebufferAttachment(GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource) + : mResource(nullptr) { - mRenderbuffer.set(NULL); + attach(type, binding, textureIndex, resource); } -GLsizei RenderbufferAttachment::getWidth() const +FramebufferAttachment::FramebufferAttachment(const FramebufferAttachment &other) + : mResource(nullptr) { - return mRenderbuffer->getWidth(); + attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource); } -GLsizei RenderbufferAttachment::getHeight() const +FramebufferAttachment &FramebufferAttachment::operator=(const FramebufferAttachment &other) { - return mRenderbuffer->getHeight(); + attach(other.mType, other.mTarget.binding(), other.mTarget.textureIndex(), other.mResource); + return *this; } -GLenum RenderbufferAttachment::getInternalFormat() const +FramebufferAttachment::~FramebufferAttachment() { - return mRenderbuffer->getInternalFormat(); + detach(); } -GLsizei RenderbufferAttachment::getSamples() const +void FramebufferAttachment::detach() { - return mRenderbuffer->getSamples(); -} + mType = GL_NONE; + if (mResource != nullptr) + { + mResource->onDetach(); + mResource = nullptr; + } -GLuint RenderbufferAttachment::id() const -{ - return mRenderbuffer->id(); + // not technically necessary, could omit for performance + mTarget = Target(); } -GLenum RenderbufferAttachment::type() const +void FramebufferAttachment::attach(GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource) { - return GL_RENDERBUFFER; -} + mType = type; + mTarget = Target(binding, textureIndex); -GLint RenderbufferAttachment::mipLevel() const -{ - return 0; + if (resource) + { + resource->onAttach(); + } + if (mResource != nullptr) + { + mResource->onDetach(); + } + mResource = resource; } -GLenum RenderbufferAttachment::cubeMapFace() const +GLuint FramebufferAttachment::getRedSize() const { - return GL_NONE; + return GetInternalFormatInfo(getInternalFormat()).redBits; } -GLint RenderbufferAttachment::layer() const +GLuint FramebufferAttachment::getGreenSize() const { - return 0; + return GetInternalFormatInfo(getInternalFormat()).greenBits; } -Texture *RenderbufferAttachment::getTexture() const +GLuint FramebufferAttachment::getBlueSize() const { - UNREACHABLE(); - return NULL; + return GetInternalFormatInfo(getInternalFormat()).blueBits; } -const ImageIndex *RenderbufferAttachment::getTextureImageIndex() const +GLuint FramebufferAttachment::getAlphaSize() const { - UNREACHABLE(); - return NULL; + return GetInternalFormatInfo(getInternalFormat()).alphaBits; } -Renderbuffer *RenderbufferAttachment::getRenderbuffer() const +GLuint FramebufferAttachment::getDepthSize() const { - return mRenderbuffer.get(); + return GetInternalFormatInfo(getInternalFormat()).depthBits; } - -DefaultAttachment::DefaultAttachment(GLenum binding, egl::Surface *surface) - : FramebufferAttachment(binding) +GLuint FramebufferAttachment::getStencilSize() const { - mSurface.set(surface); + return GetInternalFormatInfo(getInternalFormat()).stencilBits; } -DefaultAttachment::~DefaultAttachment() +GLenum FramebufferAttachment::getComponentType() const { - mSurface.set(nullptr); + return GetInternalFormatInfo(getInternalFormat()).componentType; } -GLsizei DefaultAttachment::getWidth() const +GLenum FramebufferAttachment::getColorEncoding() const { - return mSurface->getWidth(); + return GetInternalFormatInfo(getInternalFormat()).colorEncoding; } -GLsizei DefaultAttachment::getHeight() const +GLuint FramebufferAttachment::id() const { - return mSurface->getHeight(); + return mResource->getId(); } -GLenum DefaultAttachment::getInternalFormat() const +const ImageIndex &FramebufferAttachment::getTextureImageIndex() const { - const egl::Config *config = mSurface->getConfig(); - return (getBinding() == GL_BACK ? config->renderTargetFormat : config->depthStencilFormat); + ASSERT(type() == GL_TEXTURE); + return mTarget.textureIndex(); } -GLsizei DefaultAttachment::getSamples() const +GLenum FramebufferAttachment::cubeMapFace() const { - const egl::Config *config = mSurface->getConfig(); - return config->samples; -} + ASSERT(mType == GL_TEXTURE); -GLuint DefaultAttachment::id() const -{ - return 0; + const auto &index = mTarget.textureIndex(); + return IsCubeMapTextureTarget(index.type) ? index.type : GL_NONE; } -GLenum DefaultAttachment::type() const +GLint FramebufferAttachment::mipLevel() const { - return GL_FRAMEBUFFER_DEFAULT; + ASSERT(type() == GL_TEXTURE); + return mTarget.textureIndex().mipIndex; } -GLint DefaultAttachment::mipLevel() const +GLint FramebufferAttachment::layer() const { - return 0; -} + ASSERT(mType == GL_TEXTURE); -GLenum DefaultAttachment::cubeMapFace() const -{ - return GL_NONE; -} + const auto &index = mTarget.textureIndex(); -GLint DefaultAttachment::layer() const -{ + if (index.type == GL_TEXTURE_2D_ARRAY || index.type == GL_TEXTURE_3D) + { + return index.layerIndex; + } return 0; } -Texture *DefaultAttachment::getTexture() const +Texture *FramebufferAttachment::getTexture() const { - UNREACHABLE(); - return NULL; + return rx::GetAs(mResource); } -const ImageIndex *DefaultAttachment::getTextureImageIndex() const +Renderbuffer *FramebufferAttachment::getRenderbuffer() const { - UNREACHABLE(); - return NULL; + return rx::GetAs(mResource); } -Renderbuffer *DefaultAttachment::getRenderbuffer() const +const egl::Surface *FramebufferAttachment::getSurface() const { - UNREACHABLE(); - return NULL; + return rx::GetAs(mResource); } } diff --git a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h index 0662130931..33196f5c61 100644 --- a/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h +++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h @@ -10,16 +10,36 @@ #ifndef LIBANGLE_FRAMEBUFFERATTACHMENT_H_ #define LIBANGLE_FRAMEBUFFERATTACHMENT_H_ -#include "libANGLE/Texture.h" -#include "libANGLE/RefCountObject.h" - +#include "angle_gl.h" #include "common/angleutils.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Error.h" +#include "libANGLE/ImageIndex.h" -#include "angle_gl.h" +namespace egl +{ +class Surface; +} + +namespace rx +{ +// An implementation-specific object associated with an attachment. + +class FramebufferAttachmentRenderTarget : angle::NonCopyable +{ + public: + FramebufferAttachmentRenderTarget() {} + virtual ~FramebufferAttachmentRenderTarget() {} +}; + +class FramebufferAttachmentObjectImpl; +} namespace gl { +class FramebufferAttachmentObject; class Renderbuffer; +class Texture; // FramebufferAttachment implements a GL framebuffer attachment. // Attachments are "light" containers, which store pointers to ref-counted GL objects. @@ -27,11 +47,48 @@ class Renderbuffer; // Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for // framebuffer attachments, which confused their usage. -class FramebufferAttachment : angle::NonCopyable +class FramebufferAttachment final { public: - explicit FramebufferAttachment(GLenum binding); - virtual ~FramebufferAttachment(); + FramebufferAttachment(); + + FramebufferAttachment(GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource); + + FramebufferAttachment(const FramebufferAttachment &other); + FramebufferAttachment &operator=(const FramebufferAttachment &other); + + ~FramebufferAttachment(); + + // A framebuffer attachment points to one of three types of resources: Renderbuffers, + // Textures and egl::Surface. The "Target" struct indicates which part of the + // object an attachment references. For the three types: + // - a Renderbuffer has a unique renderable target, and needs no target index + // - a Texture has targets for every image and uses an ImageIndex + // - a Surface has targets for Color and Depth/Stencil, and uses the attachment binding + class Target + { + public: + Target(); + Target(GLenum binding, const ImageIndex &imageIndex); + Target(const Target &other); + Target &operator=(const Target &other); + + GLenum binding() const { return mBinding; } + const ImageIndex &textureIndex() const { return mTextureIndex; } + + private: + GLenum mBinding; + ImageIndex mTextureIndex; + }; + + void detach(); + void attach(GLenum type, + GLenum binding, + const ImageIndex &textureIndex, + FramebufferAttachmentObject *resource); // Helper methods GLuint getRedSize() const; @@ -43,111 +100,118 @@ class FramebufferAttachment : angle::NonCopyable GLenum getComponentType() const; GLenum getColorEncoding() const; - bool isTextureWithId(GLuint textureId) const { return type() == GL_TEXTURE && id() == textureId; } - bool isRenderbufferWithId(GLuint renderbufferId) const { return type() == GL_RENDERBUFFER && id() == renderbufferId; } - - GLenum getBinding() const { return mBinding; } - - // Child class interface - virtual GLsizei getWidth() const = 0; - virtual GLsizei getHeight() const = 0; - virtual GLenum getInternalFormat() const = 0; - virtual GLsizei getSamples() const = 0; - - virtual GLuint id() const = 0; - virtual GLenum type() const = 0; - virtual GLint mipLevel() const = 0; - virtual GLenum cubeMapFace() const = 0; - virtual GLint layer() const = 0; - - virtual Texture *getTexture() const = 0; - virtual const ImageIndex *getTextureImageIndex() const = 0; - virtual Renderbuffer *getRenderbuffer() const = 0; + bool isTextureWithId(GLuint textureId) const { return mType == GL_TEXTURE && id() == textureId; } + bool isRenderbufferWithId(GLuint renderbufferId) const { return mType == GL_RENDERBUFFER && id() == renderbufferId; } + + GLenum getBinding() const { return mTarget.binding(); } + GLuint id() const; + + // These methods are only legal to call on Texture attachments + const ImageIndex &getTextureImageIndex() const; + GLenum cubeMapFace() const; + GLint mipLevel() const; + GLint layer() const; + + // The size of the underlying resource the attachment points to. The 'depth' value will + // correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and + // Renderbuffers, it will always be 1. + Extents getSize() const; + GLenum getInternalFormat() const; + GLsizei getSamples() const; + GLenum type() const { return mType; } + bool isAttached() const { return mType != GL_NONE; } + + Renderbuffer *getRenderbuffer() const; + Texture *getTexture() const; + const egl::Surface *getSurface() const; + + // "T" must be static_castable from FramebufferAttachmentRenderTarget + template + gl::Error getRenderTarget(T **rtOut) const + { + // Cast through the pointer-to-pointer type + rx::FramebufferAttachmentRenderTarget *rtPtr = nullptr; + gl::Error error = getRenderTarget(&rtPtr); + *rtOut = static_cast(rtPtr); + return error; + } private: - GLenum mBinding; + gl::Error getRenderTarget(rx::FramebufferAttachmentRenderTarget **rtOut) const; + + GLenum mType; + Target mTarget; + FramebufferAttachmentObject *mResource; }; -class TextureAttachment : public FramebufferAttachment +// A base class for objects that FBO Attachments may point to. +class FramebufferAttachmentObject { public: - TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index); - virtual ~TextureAttachment(); + FramebufferAttachmentObject() {} + virtual ~FramebufferAttachmentObject() {} - virtual GLsizei getSamples() const; - virtual GLuint id() const; + virtual Extents getAttachmentSize(const FramebufferAttachment::Target &target) const = 0; + virtual GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &target) const = 0; + virtual GLsizei getAttachmentSamples(const FramebufferAttachment::Target &target) const = 0; - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; + virtual void onAttach() = 0; + virtual void onDetach() = 0; + virtual GLuint getId() const = 0; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLenum cubeMapFace() const; - virtual GLint layer() const; + Error getAttachmentRenderTarget(const FramebufferAttachment::Target &target, + rx::FramebufferAttachmentRenderTarget **rtOut) const; - virtual Texture *getTexture() const; - virtual const ImageIndex *getTextureImageIndex() const; - virtual Renderbuffer *getRenderbuffer() const; - - private: - BindingPointer mTexture; - ImageIndex mIndex; + protected: + virtual rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const = 0; }; -class RenderbufferAttachment : public FramebufferAttachment +inline Extents FramebufferAttachment::getSize() const { - public: - RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer); + return mResource->getAttachmentSize(mTarget); +} - virtual ~RenderbufferAttachment(); +inline GLenum FramebufferAttachment::getInternalFormat() const +{ + return mResource->getAttachmentInternalFormat(mTarget); +} - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLsizei getSamples() const; +inline GLsizei FramebufferAttachment::getSamples() const +{ + return mResource->getAttachmentSamples(mTarget); +} - virtual GLuint id() const; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLenum cubeMapFace() const; - virtual GLint layer() const; +inline gl::Error FramebufferAttachment::getRenderTarget(rx::FramebufferAttachmentRenderTarget **rtOut) const +{ + return mResource->getAttachmentRenderTarget(mTarget, rtOut); +} - virtual Texture *getTexture() const; - virtual const ImageIndex *getTextureImageIndex() const; - virtual Renderbuffer *getRenderbuffer() const; +} // namespace gl - private: - BindingPointer mRenderbuffer; -}; +namespace rx +{ -class DefaultAttachment : public FramebufferAttachment +class FramebufferAttachmentObjectImpl : angle::NonCopyable { public: - DefaultAttachment(GLenum binding, egl::Surface *surface); - - virtual ~DefaultAttachment(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLsizei getSamples() const; + FramebufferAttachmentObjectImpl() {} + virtual ~FramebufferAttachmentObjectImpl() {} - virtual GLuint id() const; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLenum cubeMapFace() const; - virtual GLint layer() const; + virtual gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) = 0; +}; - virtual Texture *getTexture() const; - virtual const ImageIndex *getTextureImageIndex() const; - virtual Renderbuffer *getRenderbuffer() const; +} // namespace rx - const egl::Surface *getSurface() const { return mSurface.get(); } +namespace gl +{ - private: - BindingPointer mSurface; -}; +inline Error FramebufferAttachmentObject::getAttachmentRenderTarget( + const FramebufferAttachment::Target &target, + rx::FramebufferAttachmentRenderTarget **rtOut) const +{ + return getAttachmentImpl()->getAttachmentRenderTarget(target, rtOut); +} } diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp index 59d3966758..4815855d5a 100644 --- a/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp +++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp @@ -20,13 +20,13 @@ struct HandleAllocator::HandleRangeComparator { bool operator()(const HandleRange &range, GLuint handle) const { - return (handle < range.begin); + return (range.end < handle); } }; HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1) { - mUnallocatedList.push_back(HandleRange(1, std::numeric_limits::max() - 1)); + mUnallocatedList.push_back(HandleRange(1, std::numeric_limits::max())); } HandleAllocator::HandleAllocator(GLuint maximumHandleValue) : mBaseValue(1), mNextValue(1) @@ -120,14 +120,15 @@ void HandleAllocator::reserve(GLuint handle) // need to split the range auto placementIt = mUnallocatedList.erase(boundIt); - if (begin != handle) + if (handle + 1 != end) { - placementIt = mUnallocatedList.insert(placementIt, HandleRange(begin, handle)); + placementIt = mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end)); } - if (handle + 1 != end) + if (begin != handle) { - mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end)); + ASSERT(begin < handle); + mUnallocatedList.insert(placementIt, HandleRange(begin, handle)); } } -} +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.h b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h index c22f2ba61a..1888d57cfa 100644 --- a/src/3rdparty/angle/src/libANGLE/HandleAllocator.h +++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h @@ -58,6 +58,6 @@ class HandleAllocator final : angle::NonCopyable std::vector mReleasedList; }; -} +} // namespace gl #endif // LIBANGLE_HANDLEALLOCATOR_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Image.cpp b/src/3rdparty/angle/src/libANGLE/Image.cpp new file mode 100644 index 0000000000..a9448e3f6c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Image.cpp @@ -0,0 +1,192 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image.cpp: Implements the egl::Image class representing the EGLimage object. + +#include "libANGLE/Image.h" + +#include "common/debug.h" +#include "common/utilities.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/Texture.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/renderer/ImageImpl.h" + +namespace egl +{ +ImageSibling::ImageSibling(GLuint id) : RefCountObject(id), mSourcesOf(), mTargetOf() +{ +} + +ImageSibling::~ImageSibling() +{ + // EGL images should hold a ref to their targets and siblings, a Texture should not be deletable + // while it is attached to an EGL image. + ASSERT(mSourcesOf.empty()); + orphanImages(); +} + +void ImageSibling::setTargetImage(egl::Image *imageTarget) +{ + ASSERT(imageTarget != nullptr); + mTargetOf.set(imageTarget); + imageTarget->addTargetSibling(this); +} + +gl::Error ImageSibling::orphanImages() +{ + if (mTargetOf.get() != nullptr) + { + // Can't be a target and have sources. + ASSERT(mSourcesOf.empty()); + + gl::Error error = mTargetOf->orphanSibling(this); + if (error.isError()) + { + return error; + } + + mTargetOf.set(nullptr); + } + else + { + for (auto &sourceImage : mSourcesOf) + { + gl::Error error = sourceImage->orphanSibling(this); + if (error.isError()) + { + return error; + } + } + mSourcesOf.clear(); + } + + return gl::Error(GL_NO_ERROR); +} + +void ImageSibling::addImageSource(egl::Image *imageSource) +{ + ASSERT(imageSource != nullptr); + mSourcesOf.insert(imageSource); +} + +void ImageSibling::removeImageSource(egl::Image *imageSource) +{ + ASSERT(mSourcesOf.find(imageSource) != mSourcesOf.end()); + mSourcesOf.erase(imageSource); +} + +Image::Image(rx::ImageImpl *impl, EGLenum target, ImageSibling *buffer, const AttributeMap &attribs) + : RefCountObject(0), + mImplementation(impl), + mInternalFormat(GL_NONE), + mWidth(0), + mHeight(0), + mSamples(0), + mSource(), + mTargets() +{ + ASSERT(mImplementation != nullptr); + ASSERT(buffer != nullptr); + + mSource.set(buffer); + mSource->addImageSource(this); + + if (IsTextureTarget(target)) + { + gl::Texture *texture = rx::GetAs(mSource.get()); + GLenum textureTarget = egl_gl::EGLImageTargetToGLTextureTarget(target); + size_t level = attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0); + mInternalFormat = texture->getInternalFormat(textureTarget, level); + mWidth = texture->getWidth(textureTarget, level); + mHeight = texture->getHeight(textureTarget, level); + mSamples = 0; + } + else if (IsRenderbufferTarget(target)) + { + gl::Renderbuffer *renderbuffer = rx::GetAs(mSource.get()); + mInternalFormat = renderbuffer->getInternalFormat(); + mWidth = renderbuffer->getWidth(); + mHeight = renderbuffer->getHeight(); + mSamples = renderbuffer->getSamples(); + } + else + { + UNREACHABLE(); + } +} + +Image::~Image() +{ + SafeDelete(mImplementation); + + // All targets should hold a ref to the egl image and it should not be deleted until there are + // no siblings left. + ASSERT(mTargets.empty()); + + // Tell the source that it is no longer used by this image + if (mSource.get() != nullptr) + { + mSource->removeImageSource(this); + mSource.set(nullptr); + } +} + +void Image::addTargetSibling(ImageSibling *sibling) +{ + mTargets.insert(sibling); +} + +gl::Error Image::orphanSibling(ImageSibling *sibling) +{ + // notify impl + gl::Error error = mImplementation->orphan(sibling); + + if (mSource.get() == sibling) + { + // If the sibling is the source, it cannot be a target. + ASSERT(mTargets.find(sibling) == mTargets.end()); + + mSource.set(nullptr); + } + else + { + mTargets.erase(sibling); + } + + return error; +} + +GLenum Image::getInternalFormat() const +{ + return mInternalFormat; +} + +size_t Image::getWidth() const +{ + return mWidth; +} + +size_t Image::getHeight() const +{ + return mHeight; +} + +size_t Image::getSamples() const +{ + return mSamples; +} + +rx::ImageImpl *Image::getImplementation() +{ + return mImplementation; +} + +const rx::ImageImpl *Image::getImplementation() const +{ + return mImplementation; +} +} diff --git a/src/3rdparty/angle/src/libANGLE/Image.h b/src/3rdparty/angle/src/libANGLE/Image.h new file mode 100644 index 0000000000..26c9df914c --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Image.h @@ -0,0 +1,91 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image.h: Defines the egl::Image class representing the EGLimage object. + +#ifndef LIBANGLE_IMAGE_H_ +#define LIBANGLE_IMAGE_H_ + +#include "common/angleutils.h" +#include "libANGLE/AttributeMap.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" + +#include + +namespace rx +{ +class ImageImpl; +} + +namespace egl +{ +class Image; + +class ImageSibling : public RefCountObject +{ + public: + ImageSibling(GLuint id); + virtual ~ImageSibling(); + + protected: + // Set the image target of this sibling + void setTargetImage(egl::Image *imageTarget); + + // Orphan all EGL image sources and targets + gl::Error orphanImages(); + + private: + friend class Image; + + // Called from Image only to add a new source image + void addImageSource(egl::Image *imageSource); + + // Called from Image only to remove a source image when the Image is being deleted + void removeImageSource(egl::Image *imageSource); + + std::set mSourcesOf; + BindingPointer mTargetOf; +}; + +class Image final : public RefCountObject +{ + public: + Image(rx::ImageImpl *impl, EGLenum target, ImageSibling *buffer, const AttributeMap &attribs); + ~Image(); + + GLenum getInternalFormat() const; + size_t getWidth() const; + size_t getHeight() const; + size_t getSamples() const; + + rx::ImageImpl *getImplementation(); + const rx::ImageImpl *getImplementation() const; + + private: + friend class ImageSibling; + + // Called from ImageSibling only notify the image that a new target sibling exists for state + // tracking. + void addTargetSibling(ImageSibling *sibling); + + // Called from ImageSibling only to notify the image that a sibling (source or target) has + // been respecified and state tracking should be updated. + gl::Error orphanSibling(ImageSibling *sibling); + + rx::ImageImpl *mImplementation; + + GLenum mInternalFormat; + size_t mWidth; + size_t mHeight; + size_t mSamples; + + BindingPointer mSource; + std::set mTargets; +}; +} + +#endif // LIBANGLE_IMAGE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp index ac7302d121..c84e7c5d65 100644 --- a/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp +++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp @@ -35,7 +35,8 @@ ImageIndex ImageIndex::Make2D(GLint mipIndex) ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex) { ASSERT(gl::IsCubeMapTextureTarget(target)); - return ImageIndex(target, mipIndex, CubeMapTextureTargetToLayerIndex(target)); + return ImageIndex(target, mipIndex, + static_cast(CubeMapTextureTargetToLayerIndex(target))); } ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex) @@ -50,7 +51,9 @@ ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex) ImageIndex ImageIndex::MakeGeneric(GLenum target, GLint mipIndex) { - GLint layerIndex = IsCubeMapTextureTarget(target) ? CubeMapTextureTargetToLayerIndex(target) : ENTIRE_LEVEL; + GLint layerIndex = IsCubeMapTextureTarget(target) + ? static_cast(CubeMapTextureTargetToLayerIndex(target)) + : ENTIRE_LEVEL; return ImageIndex(target, mipIndex, layerIndex); } @@ -83,30 +86,30 @@ ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn) ImageIndexIterator ImageIndexIterator::Make2D(GLint minMip, GLint maxMip) { - return ImageIndexIterator(GL_TEXTURE_2D, rx::Range(minMip, maxMip), - rx::Range(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL); + return ImageIndexIterator(GL_TEXTURE_2D, Range(minMip, maxMip), + Range(ImageIndex::ENTIRE_LEVEL, ImageIndex::ENTIRE_LEVEL), NULL); } ImageIndexIterator ImageIndexIterator::MakeCube(GLint minMip, GLint maxMip) { - return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, rx::Range(minMip, maxMip), rx::Range(0, 6), NULL); + return ImageIndexIterator(GL_TEXTURE_CUBE_MAP, Range(minMip, maxMip), Range(0, 6), NULL); } ImageIndexIterator ImageIndexIterator::Make3D(GLint minMip, GLint maxMip, GLint minLayer, GLint maxLayer) { - return ImageIndexIterator(GL_TEXTURE_3D, rx::Range(minMip, maxMip), rx::Range(minLayer, maxLayer), NULL); + return ImageIndexIterator(GL_TEXTURE_3D, Range(minMip, maxMip), Range(minLayer, maxLayer), NULL); } ImageIndexIterator ImageIndexIterator::Make2DArray(GLint minMip, GLint maxMip, const GLsizei *layerCounts) { - return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, rx::Range(minMip, maxMip), - rx::Range(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts); + return ImageIndexIterator(GL_TEXTURE_2D_ARRAY, Range(minMip, maxMip), + Range(0, IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS), layerCounts); } -ImageIndexIterator::ImageIndexIterator(GLenum type, const rx::Range &mipRange, - const rx::Range &layerRange, const GLsizei *layerCounts) +ImageIndexIterator::ImageIndexIterator(GLenum type, const Range &mipRange, + const Range &layerRange, const GLsizei *layerCounts) : mType(type), mMipRange(mipRange), mLayerRange(layerRange), diff --git a/src/3rdparty/angle/src/libANGLE/ImageIndex.h b/src/3rdparty/angle/src/libANGLE/ImageIndex.h index 820c650f20..b527c7c8ab 100644 --- a/src/3rdparty/angle/src/libANGLE/ImageIndex.h +++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.h @@ -61,14 +61,14 @@ class ImageIndexIterator private: - ImageIndexIterator(GLenum type, const rx::Range &mipRange, - const rx::Range &layerRange, const GLsizei *layerCounts); + ImageIndexIterator(GLenum type, const Range &mipRange, + const Range &layerRange, const GLsizei *layerCounts); GLint maxLayer() const; GLenum mType; - rx::Range mMipRange; - rx::Range mLayerRange; + Range mMipRange; + Range mLayerRange; const GLsizei *mLayerCounts; GLint mCurrentMip; GLint mCurrentLayer; diff --git a/src/3rdparty/angle/src/libANGLE/IndexRangeCache.cpp b/src/3rdparty/angle/src/libANGLE/IndexRangeCache.cpp new file mode 100644 index 0000000000..4f165c1b28 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/IndexRangeCache.cpp @@ -0,0 +1,113 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexRangeCache.cpp: Defines the gl::IndexRangeCache class which stores information about +// ranges of indices. + +#include "libANGLE/IndexRangeCache.h" + +#include "common/debug.h" +#include "libANGLE/formatutils.h" + +namespace gl +{ + +void IndexRangeCache::addRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + const IndexRange &range) +{ + mIndexRangeCache[IndexRangeKey(type, offset, count, primitiveRestartEnabled)] = range; +} + +bool IndexRangeCache::findRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + IndexRange *outRange) const +{ + auto i = mIndexRangeCache.find(IndexRangeKey(type, offset, count, primitiveRestartEnabled)); + if (i != mIndexRangeCache.end()) + { + if (outRange) + { + *outRange = i->second; + } + return true; + } + else + { + if (outRange) + { + *outRange = IndexRange(); + } + return false; + } +} + +void IndexRangeCache::invalidateRange(size_t offset, size_t size) +{ + size_t invalidateStart = offset; + size_t invalidateEnd = offset + size; + + auto i = mIndexRangeCache.begin(); + while (i != mIndexRangeCache.end()) + { + size_t rangeStart = i->first.offset; + size_t rangeEnd = i->first.offset + (GetTypeInfo(i->first.type).bytes * i->first.count); + + if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) + { + ++i; + } + else + { + mIndexRangeCache.erase(i++); + } + } +} + +void IndexRangeCache::clear() +{ + mIndexRangeCache.clear(); +} + +IndexRangeCache::IndexRangeKey::IndexRangeKey() + : IndexRangeCache::IndexRangeKey(GL_NONE, 0, 0, false) +{ +} + +IndexRangeCache::IndexRangeKey::IndexRangeKey(GLenum type_, + size_t offset_, + size_t count_, + bool primitiveRestartEnabled_) + : type(type_), offset(offset_), count(count_), primitiveRestartEnabled(primitiveRestartEnabled_) +{ +} + +bool IndexRangeCache::IndexRangeKey::operator<(const IndexRangeKey &rhs) const +{ + if (type != rhs.type) + { + return type < rhs.type; + } + if (offset != rhs.offset) + { + return offset < rhs.offset; + } + if (count != rhs.count) + { + return count < rhs.count; + } + if (primitiveRestartEnabled != rhs.primitiveRestartEnabled) + { + return primitiveRestartEnabled; + } + return false; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/IndexRangeCache.h b/src/3rdparty/angle/src/libANGLE/IndexRangeCache.h new file mode 100644 index 0000000000..69de421c13 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/IndexRangeCache.h @@ -0,0 +1,60 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexRangeCache.h: Defines the gl::IndexRangeCache class which stores information about +// ranges of indices. + +#ifndef LIBANGLE_INDEXRANGECACHE_H_ +#define LIBANGLE_INDEXRANGECACHE_H_ + +#include "common/angleutils.h" +#include "common/mathutil.h" + +#include "angle_gl.h" + +#include + +namespace gl +{ + +class IndexRangeCache +{ + public: + void addRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + const IndexRange &range); + bool findRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + IndexRange *outRange) const; + + void invalidateRange(size_t offset, size_t size); + void clear(); + + private: + struct IndexRangeKey + { + IndexRangeKey(); + IndexRangeKey(GLenum type, size_t offset, size_t count, bool primitiveRestart); + + bool operator<(const IndexRangeKey &rhs) const; + + GLenum type; + size_t offset; + size_t count; + bool primitiveRestartEnabled; + }; + + typedef std::map IndexRangeMap; + IndexRangeMap mIndexRangeCache; +}; + +} + +#endif // LIBANGLE_INDEXRANGECACHE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Platform.cpp b/src/3rdparty/angle/src/libANGLE/Platform.cpp index ab75bbba5a..bfcdb1494e 100644 --- a/src/3rdparty/angle/src/libANGLE/Platform.cpp +++ b/src/3rdparty/angle/src/libANGLE/Platform.cpp @@ -16,20 +16,20 @@ angle::Platform *currentPlatform = nullptr; } // static -ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent() +angle::Platform *ANGLE_APIENTRY ANGLEPlatformCurrent() { return currentPlatform; } // static -ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform *platformImpl) +void ANGLE_APIENTRY ANGLEPlatformInitialize(angle::Platform *platformImpl) { ASSERT(platformImpl != nullptr); currentPlatform = platformImpl; } // static -ANGLE_EXPORT void ANGLEPlatformShutdown() +void ANGLE_APIENTRY ANGLEPlatformShutdown() { currentPlatform = nullptr; } diff --git a/src/3rdparty/angle/src/libANGLE/Program.cpp b/src/3rdparty/angle/src/libANGLE/Program.cpp index daf0a403f0..748ceae030 100644 --- a/src/3rdparty/angle/src/libANGLE/Program.cpp +++ b/src/3rdparty/angle/src/libANGLE/Program.cpp @@ -11,6 +11,7 @@ #include +#include "common/BitSetIterator.h" #include "common/debug.h" #include "common/platform.h" #include "common/utilities.h" @@ -21,72 +22,156 @@ #include "libANGLE/features.h" #include "libANGLE/renderer/Renderer.h" #include "libANGLE/renderer/ProgramImpl.h" +#include "libANGLE/queryconversions.h" namespace gl { -const char * const g_fakepath = "C:\\fakepath"; namespace { -unsigned int ParseAndStripArrayIndex(std::string* name) +void WriteShaderVar(BinaryOutputStream *stream, const sh::ShaderVariable &var) { - unsigned int subscript = GL_INVALID_INDEX; + stream->writeInt(var.type); + stream->writeInt(var.precision); + stream->writeString(var.name); + stream->writeString(var.mappedName); + stream->writeInt(var.arraySize); + stream->writeInt(var.staticUse); + stream->writeString(var.structName); + ASSERT(var.fields.empty()); +} - // Strip any trailing array operator and retrieve the subscript - size_t open = name->find_last_of('['); - size_t close = name->find_last_of(']'); - if (open != std::string::npos && close == name->length() - 1) - { - subscript = atoi(name->substr(open + 1).c_str()); - name->erase(open); - } +void LoadShaderVar(BinaryInputStream *stream, sh::ShaderVariable *var) +{ + var->type = stream->readInt(); + var->precision = stream->readInt(); + var->name = stream->readString(); + var->mappedName = stream->readString(); + var->arraySize = stream->readInt(); + var->staticUse = stream->readBool(); + var->structName = stream->readString(); +} + +// This simplified cast function doesn't need to worry about advanced concepts like +// depth range values, or casting to bool. +template +DestT UniformStateQueryCast(SrcT value); + +// From-Float-To-Integer Casts +template <> +GLint UniformStateQueryCast(GLfloat value) +{ + return clampCast(roundf(value)); +} - return subscript; +template <> +GLuint UniformStateQueryCast(GLfloat value) +{ + return clampCast(roundf(value)); } +// From-Integer-to-Integer Casts +template <> +GLint UniformStateQueryCast(GLuint value) +{ + return clampCast(value); } -AttributeBindings::AttributeBindings() +template <> +GLuint UniformStateQueryCast(GLint value) { + return clampCast(value); } -AttributeBindings::~AttributeBindings() +// From-Boolean-to-Anything Casts +template <> +GLfloat UniformStateQueryCast(GLboolean value) { + return (value == GL_TRUE ? 1.0f : 0.0f); } -InfoLog::InfoLog() : mInfoLog(NULL) +template <> +GLint UniformStateQueryCast(GLboolean value) { + return (value == GL_TRUE ? 1 : 0); } -InfoLog::~InfoLog() +template <> +GLuint UniformStateQueryCast(GLboolean value) { - delete[] mInfoLog; + return (value == GL_TRUE ? 1u : 0u); } +// Default to static_cast +template +DestT UniformStateQueryCast(SrcT value) +{ + return static_cast(value); +} -int InfoLog::getLength() const +template +void UniformStateQueryCastLoop(DestT *dataOut, const uint8_t *srcPointer, int components) { - if (!mInfoLog) + for (int comp = 0; comp < components; ++comp) { - return 0; + // We only work with strides of 4 bytes for uniform components. (GLfloat/GLint) + // Don't use SrcT stride directly since GLboolean has a stride of 1 byte. + size_t offset = comp * 4; + const SrcT *typedSrcPointer = reinterpret_cast(&srcPointer[offset]); + dataOut[comp] = UniformStateQueryCast(*typedSrcPointer); } - else +} + +bool UniformInList(const std::vector &list, const std::string &name) +{ + for (const LinkedUniform &uniform : list) { - return strlen(mInfoLog) + 1; + if (uniform.name == name) + return true; } + + return false; +} + +} // anonymous namespace + +const char *const g_fakepath = "C:\\fakepath"; + +AttributeBindings::AttributeBindings() +{ +} + +AttributeBindings::~AttributeBindings() +{ } -void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) +InfoLog::InfoLog() { - int index = 0; +} + +InfoLog::~InfoLog() +{ +} + +size_t InfoLog::getLength() const +{ + const std::string &logString = mStream.str(); + return logString.empty() ? 0 : logString.length() + 1; +} + +void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const +{ + size_t index = 0; if (bufSize > 0) { - if (mInfoLog) + const std::string str(mStream.str()); + + if (!str.empty()) { - index = std::min(bufSize - 1, (int)strlen(mInfoLog)); - memcpy(infoLog, mInfoLog, index); + index = std::min(static_cast(bufSize) - 1, str.length()); + memcpy(infoLog, str.c_str(), index); } infoLog[index] = '\0'; @@ -94,7 +179,7 @@ void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog) if (length) { - *length = index; + *length = static_cast(index); } } @@ -116,89 +201,125 @@ void InfoLog::appendSanitized(const char *message) } while (found != std::string::npos); - append("%s", msg.c_str()); + mStream << message << std::endl; } -void InfoLog::append(const char *format, ...) +void InfoLog::reset() { - if (!format) - { - return; - } +} - va_list vararg; - va_start(vararg, format); - size_t infoLength = vsnprintf(NULL, 0, format, vararg); - va_end(vararg); +VariableLocation::VariableLocation() + : name(), + element(0), + index(0) +{ +} + +VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) + : name(name), + element(element), + index(index) +{ +} - char *logPointer = NULL; +Program::Data::Data() + : mLabel(), + mAttachedFragmentShader(nullptr), + mAttachedVertexShader(nullptr), + mTransformFeedbackBufferMode(GL_INTERLEAVED_ATTRIBS), + mBinaryRetrieveableHint(false) +{ +} - if (!mInfoLog) +Program::Data::~Data() +{ + if (mAttachedVertexShader != nullptr) { - mInfoLog = new char[infoLength + 2]; - logPointer = mInfoLog; + mAttachedVertexShader->release(); } - else - { - size_t currentlogLength = strlen(mInfoLog); - char *newLog = new char[currentlogLength + infoLength + 2]; - strcpy(newLog, mInfoLog); - delete[] mInfoLog; - mInfoLog = newLog; - - logPointer = mInfoLog + currentlogLength; + if (mAttachedFragmentShader != nullptr) + { + mAttachedFragmentShader->release(); } +} - va_start(vararg, format); - vsnprintf(logPointer, infoLength, format, vararg); - va_end(vararg); - - logPointer[infoLength] = 0; - strcpy(logPointer + infoLength, "\n"); +const std::string &Program::Data::getLabel() +{ + return mLabel; } -void InfoLog::reset() +const LinkedUniform *Program::Data::getUniformByName(const std::string &name) const { - if (mInfoLog) + for (const LinkedUniform &linkedUniform : mUniforms) { - delete [] mInfoLog; - mInfoLog = NULL; + if (linkedUniform.name == name) + { + return &linkedUniform; + } } -} -VariableLocation::VariableLocation() - : name(), element(0), index(0) -{ + return nullptr; } -VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) - : name(name), element(element), index(index) +GLint Program::Data::getUniformLocation(const std::string &name) const { -} + size_t subscript = GL_INVALID_INDEX; + std::string baseName = gl::ParseUniformName(name, &subscript); -LinkedVarying::LinkedVarying() -{ + for (size_t location = 0; location < mUniformLocations.size(); ++location) + { + const VariableLocation &uniformLocation = mUniformLocations[location]; + const LinkedUniform &uniform = mUniforms[uniformLocation.index]; + + if (uniform.name == baseName) + { + if ((uniform.isArray() && uniformLocation.element == subscript) || + (subscript == GL_INVALID_INDEX)) + { + return static_cast(location); + } + } + } + + return -1; } -LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, - unsigned int semanticIndex, unsigned int semanticIndexCount) - : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount) +GLuint Program::Data::getUniformIndex(const std::string &name) const { + size_t subscript = GL_INVALID_INDEX; + std::string baseName = gl::ParseUniformName(name, &subscript); + + // The app is not allowed to specify array indices other than 0 for arrays of basic types + if (subscript != 0 && subscript != GL_INVALID_INDEX) + { + return GL_INVALID_INDEX; + } + + for (size_t index = 0; index < mUniforms.size(); index++) + { + const LinkedUniform &uniform = mUniforms[index]; + if (uniform.name == baseName) + { + if (uniform.isArray() || subscript == GL_INVALID_INDEX) + { + return static_cast(index); + } + } + } + + return GL_INVALID_INDEX; } -Program::Program(rx::ProgramImpl *impl, ResourceManager *manager, GLuint handle) - : mProgram(impl), +Program::Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle) + : mProgram(factory->createProgram(mData)), mValidated(false), - mTransformFeedbackVaryings(), - mTransformFeedbackBufferMode(GL_NONE), - mFragmentShader(NULL), - mVertexShader(NULL), mLinked(false), mDeleteStatus(false), mRefCount(0), mResourceManager(manager), - mHandle(handle) + mHandle(handle), + mSamplerUniformRange(0, 0) { ASSERT(mProgram); @@ -210,40 +331,40 @@ Program::~Program() { unlink(true); - if (mVertexShader != NULL) - { - mVertexShader->release(); - } + SafeDelete(mProgram); +} - if (mFragmentShader != NULL) - { - mFragmentShader->release(); - } +void Program::setLabel(const std::string &label) +{ + mData.mLabel = label; +} - SafeDelete(mProgram); +const std::string &Program::getLabel() const +{ + return mData.mLabel; } bool Program::attachShader(Shader *shader) { if (shader->getType() == GL_VERTEX_SHADER) { - if (mVertexShader) + if (mData.mAttachedVertexShader) { return false; } - mVertexShader = shader; - mVertexShader->addRef(); + mData.mAttachedVertexShader = shader; + mData.mAttachedVertexShader->addRef(); } else if (shader->getType() == GL_FRAGMENT_SHADER) { - if (mFragmentShader) + if (mData.mAttachedFragmentShader) { return false; } - mFragmentShader = shader; - mFragmentShader->addRef(); + mData.mAttachedFragmentShader = shader; + mData.mAttachedFragmentShader->addRef(); } else UNREACHABLE(); @@ -254,23 +375,23 @@ bool Program::detachShader(Shader *shader) { if (shader->getType() == GL_VERTEX_SHADER) { - if (mVertexShader != shader) + if (mData.mAttachedVertexShader != shader) { return false; } - mVertexShader->release(); - mVertexShader = NULL; + shader->release(); + mData.mAttachedVertexShader = nullptr; } else if (shader->getType() == GL_FRAGMENT_SHADER) { - if (mFragmentShader != shader) + if (mData.mAttachedFragmentShader != shader) { return false; } - mFragmentShader->release(); - mFragmentShader = NULL; + shader->release(); + mData.mAttachedFragmentShader = nullptr; } else UNREACHABLE(); @@ -279,7 +400,7 @@ bool Program::detachShader(Shader *shader) int Program::getAttachedShadersCount() const { - return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0); + return (mData.mAttachedVertexShader ? 1 : 0) + (mData.mAttachedFragmentShader ? 1 : 0); } void AttributeBindings::bindAttributeLocation(GLuint index, const char *name) @@ -303,65 +424,63 @@ void Program::bindAttributeLocation(GLuint index, const char *name) // Links the HLSL code of the vertex and pixel shader by matching up their varyings, // compiling them into binaries, determining the attribute mappings, and collecting // a list of uniforms -Error Program::link(const Data &data) +Error Program::link(const gl::Data &data) { unlink(false); mInfoLog.reset(); resetUniformBlockBindings(); - if (!mFragmentShader || !mFragmentShader->isCompiled()) + if (!mData.mAttachedFragmentShader || !mData.mAttachedFragmentShader->isCompiled()) { return Error(GL_NO_ERROR); } - ASSERT(mFragmentShader->getType() == GL_FRAGMENT_SHADER); + ASSERT(mData.mAttachedFragmentShader->getType() == GL_FRAGMENT_SHADER); - if (!mVertexShader || !mVertexShader->isCompiled()) + if (!mData.mAttachedVertexShader || !mData.mAttachedVertexShader->isCompiled()) { return Error(GL_NO_ERROR); } - ASSERT(mVertexShader->getType() == GL_VERTEX_SHADER); + ASSERT(mData.mAttachedVertexShader->getType() == GL_VERTEX_SHADER); - if (!linkAttributes(mInfoLog, mAttributeBindings, mVertexShader)) + if (!linkAttributes(data, mInfoLog, mAttributeBindings, mData.mAttachedVertexShader)) { return Error(GL_NO_ERROR); } - int registers; - std::vector linkedVaryings; - rx::LinkResult result = mProgram->link(data, mInfoLog, mFragmentShader, mVertexShader, mTransformFeedbackVaryings, mTransformFeedbackBufferMode, - ®isters, &linkedVaryings, &mOutputVariables); - if (result.error.isError() || !result.linkSuccess) + if (!linkVaryings(mInfoLog, mData.mAttachedVertexShader, mData.mAttachedFragmentShader)) { - return result.error; + return Error(GL_NO_ERROR); } - if (!mProgram->linkUniforms(mInfoLog, *mVertexShader, *mFragmentShader, *data.caps)) + if (!linkUniforms(mInfoLog, *data.caps)) { return Error(GL_NO_ERROR); } - if (!linkUniformBlocks(mInfoLog, *mVertexShader, *mFragmentShader, *data.caps)) + if (!linkUniformBlocks(mInfoLog, *data.caps)) { return Error(GL_NO_ERROR); } - if (!gatherTransformFeedbackLinkedVaryings(mInfoLog, linkedVaryings, mTransformFeedbackVaryings, - mTransformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps)) + const auto &mergedVaryings = getMergedVaryings(); + + if (!linkValidateTransformFeedback(mInfoLog, mergedVaryings, *data.caps)) { return Error(GL_NO_ERROR); } - // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called, - // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling. - result = mProgram->compileProgramExecutables(mInfoLog, mFragmentShader, mVertexShader, registers); + linkOutputVariables(); + + rx::LinkResult result = mProgram->link(data, mInfoLog); if (result.error.isError() || !result.linkSuccess) { - mInfoLog.append("Failed to create D3D shaders."); - unlink(false); return result.error; } + gatherTransformFeedbackVaryings(mergedVaryings); + gatherInterfaceBlockInfo(); + mLinked = true; return gl::Error(GL_NO_ERROR); } @@ -384,30 +503,33 @@ void Program::unlink(bool destroy) { if (destroy) // Object being destructed { - if (mFragmentShader) + if (mData.mAttachedFragmentShader) { - mFragmentShader->release(); - mFragmentShader = NULL; + mData.mAttachedFragmentShader->release(); + mData.mAttachedFragmentShader = nullptr; } - if (mVertexShader) + if (mData.mAttachedVertexShader) { - mVertexShader->release(); - mVertexShader = NULL; + mData.mAttachedVertexShader->release(); + mData.mAttachedVertexShader = nullptr; } } - std::fill(mLinkedAttribute, mLinkedAttribute + ArraySize(mLinkedAttribute), sh::Attribute()); - mOutputVariables.clear(); - - mProgram->reset(); + mData.mAttributes.clear(); + mData.mActiveAttribLocationsMask.reset(); + mData.mTransformFeedbackVaryingVars.clear(); + mData.mUniforms.clear(); + mData.mUniformLocations.clear(); + mData.mUniformBlocks.clear(); + mData.mOutputVariables.clear(); mValidated = false; mLinked = false; } -bool Program::isLinked() +bool Program::isLinked() const { return mLinked; } @@ -419,22 +541,20 @@ Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei lengt #if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED return Error(GL_NO_ERROR); #else - ASSERT(binaryFormat == mProgram->getBinaryFormat()); - - BinaryInputStream stream(binary, length); - - GLenum format = stream.readInt(); - if (format != mProgram->getBinaryFormat()) + ASSERT(binaryFormat == GL_PROGRAM_BINARY_ANGLE); + if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) { - mInfoLog.append("Invalid program binary format."); + mInfoLog << "Invalid program binary format."; return Error(GL_NO_ERROR); } + BinaryInputStream stream(binary, length); + int majorVersion = stream.readInt(); int minorVersion = stream.readInt(); if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) { - mInfoLog.append("Invalid program binary version."); + mInfoLog << "Invalid program binary version."; return Error(GL_NO_ERROR); } @@ -442,19 +562,105 @@ Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei lengt stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE); if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) { - mInfoLog.append("Invalid program binary version."); + mInfoLog << "Invalid program binary version."; return Error(GL_NO_ERROR); } - for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) + static_assert(MAX_VERTEX_ATTRIBS <= sizeof(unsigned long) * 8, + "Too many vertex attribs for mask"); + mData.mActiveAttribLocationsMask = stream.readInt(); + + unsigned int attribCount = stream.readInt(); + ASSERT(mData.mAttributes.empty()); + for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex) + { + sh::Attribute attrib; + LoadShaderVar(&stream, &attrib); + attrib.location = stream.readInt(); + mData.mAttributes.push_back(attrib); + } + + unsigned int uniformCount = stream.readInt(); + ASSERT(mData.mUniforms.empty()); + for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; ++uniformIndex) + { + LinkedUniform uniform; + LoadShaderVar(&stream, &uniform); + + uniform.blockIndex = stream.readInt(); + uniform.blockInfo.offset = stream.readInt(); + uniform.blockInfo.arrayStride = stream.readInt(); + uniform.blockInfo.matrixStride = stream.readInt(); + uniform.blockInfo.isRowMajorMatrix = stream.readBool(); + + mData.mUniforms.push_back(uniform); + } + + const unsigned int uniformIndexCount = stream.readInt(); + ASSERT(mData.mUniformLocations.empty()); + for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; + uniformIndexIndex++) + { + VariableLocation variable; + stream.readString(&variable.name); + stream.readInt(&variable.element); + stream.readInt(&variable.index); + + mData.mUniformLocations.push_back(variable); + } + + unsigned int uniformBlockCount = stream.readInt(); + ASSERT(mData.mUniformBlocks.empty()); + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; + ++uniformBlockIndex) + { + UniformBlock uniformBlock; + stream.readString(&uniformBlock.name); + stream.readBool(&uniformBlock.isArray); + stream.readInt(&uniformBlock.arrayElement); + stream.readInt(&uniformBlock.dataSize); + stream.readBool(&uniformBlock.vertexStaticUse); + stream.readBool(&uniformBlock.fragmentStaticUse); + + unsigned int numMembers = stream.readInt(); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++) + { + uniformBlock.memberUniformIndexes.push_back(stream.readInt()); + } + + mData.mUniformBlocks.push_back(uniformBlock); + } + + unsigned int transformFeedbackVaryingCount = stream.readInt(); + ASSERT(mData.mTransformFeedbackVaryingVars.empty()); + for (unsigned int transformFeedbackVaryingIndex = 0; + transformFeedbackVaryingIndex < transformFeedbackVaryingCount; + ++transformFeedbackVaryingIndex) { - stream.readInt(&mLinkedAttribute[i].type); - stream.readString(&mLinkedAttribute[i].name); - stream.readInt(&mProgram->getShaderAttributes()[i].type); - stream.readString(&mProgram->getShaderAttributes()[i].name); - stream.readInt(&mProgram->getSemanticIndexes()[i]); + sh::Varying varying; + stream.readInt(&varying.arraySize); + stream.readInt(&varying.type); + stream.readString(&varying.name); + + mData.mTransformFeedbackVaryingVars.push_back(varying); + } + + stream.readInt(&mData.mTransformFeedbackBufferMode); + + unsigned int outputVarCount = stream.readInt(); + for (unsigned int outputIndex = 0; outputIndex < outputVarCount; ++outputIndex) + { + int locationIndex = stream.readInt(); + VariableLocation locationData; + stream.readInt(&locationData.element); + stream.readInt(&locationData.index); + stream.readString(&locationData.name); + mData.mOutputVariables[locationIndex] = locationData; } + stream.readInt(&mSamplerUniformRange.start); + stream.readInt(&mSamplerUniformRange.end); + rx::LinkResult result = mProgram->load(mInfoLog, &stream); if (result.error.isError() || !result.linkSuccess) { @@ -470,32 +676,93 @@ Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, G { if (binaryFormat) { - *binaryFormat = mProgram->getBinaryFormat(); + *binaryFormat = GL_PROGRAM_BINARY_ANGLE; } BinaryOutputStream stream; - stream.writeInt(mProgram->getBinaryFormat()); stream.writeInt(ANGLE_MAJOR_VERSION); stream.writeInt(ANGLE_MINOR_VERSION); stream.writeBytes(reinterpret_cast(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE); - for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) + stream.writeInt(mData.mActiveAttribLocationsMask.to_ulong()); + + stream.writeInt(mData.mAttributes.size()); + for (const sh::Attribute &attrib : mData.mAttributes) + { + WriteShaderVar(&stream, attrib); + stream.writeInt(attrib.location); + } + + stream.writeInt(mData.mUniforms.size()); + for (const gl::LinkedUniform &uniform : mData.mUniforms) + { + WriteShaderVar(&stream, uniform); + + // FIXME: referenced + + stream.writeInt(uniform.blockIndex); + stream.writeInt(uniform.blockInfo.offset); + stream.writeInt(uniform.blockInfo.arrayStride); + stream.writeInt(uniform.blockInfo.matrixStride); + stream.writeInt(uniform.blockInfo.isRowMajorMatrix); + } + + stream.writeInt(mData.mUniformLocations.size()); + for (const auto &variable : mData.mUniformLocations) + { + stream.writeString(variable.name); + stream.writeInt(variable.element); + stream.writeInt(variable.index); + } + + stream.writeInt(mData.mUniformBlocks.size()); + for (const UniformBlock &uniformBlock : mData.mUniformBlocks) + { + stream.writeString(uniformBlock.name); + stream.writeInt(uniformBlock.isArray); + stream.writeInt(uniformBlock.arrayElement); + stream.writeInt(uniformBlock.dataSize); + + stream.writeInt(uniformBlock.vertexStaticUse); + stream.writeInt(uniformBlock.fragmentStaticUse); + + stream.writeInt(uniformBlock.memberUniformIndexes.size()); + for (unsigned int memberUniformIndex : uniformBlock.memberUniformIndexes) + { + stream.writeInt(memberUniformIndex); + } + } + + stream.writeInt(mData.mTransformFeedbackVaryingVars.size()); + for (const sh::Varying &varying : mData.mTransformFeedbackVaryingVars) + { + stream.writeInt(varying.arraySize); + stream.writeInt(varying.type); + stream.writeString(varying.name); + } + + stream.writeInt(mData.mTransformFeedbackBufferMode); + + stream.writeInt(mData.mOutputVariables.size()); + for (const auto &outputPair : mData.mOutputVariables) { - stream.writeInt(mLinkedAttribute[i].type); - stream.writeString(mLinkedAttribute[i].name); - stream.writeInt(mProgram->getShaderAttributes()[i].type); - stream.writeString(mProgram->getShaderAttributes()[i].name); - stream.writeInt(mProgram->getSemanticIndexes()[i]); + stream.writeInt(outputPair.first); + stream.writeInt(outputPair.second.element); + stream.writeInt(outputPair.second.index); + stream.writeString(outputPair.second.name); } + stream.writeInt(mSamplerUniformRange.start); + stream.writeInt(mSamplerUniformRange.end); + gl::Error error = mProgram->save(&stream); if (error.isError()) { return error; } - GLsizei streamLength = stream.length(); + GLsizei streamLength = static_cast(stream.length()); const void *streamData = stream.data(); if (streamLength > bufSize) @@ -532,7 +799,7 @@ Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, G GLint Program::getBinaryLength() const { GLint length; - Error error = saveBinary(NULL, NULL, std::numeric_limits::max(), &length); + Error error = saveBinary(nullptr, nullptr, std::numeric_limits::max(), &length); if (error.isError()) { return 0; @@ -541,6 +808,18 @@ GLint Program::getBinaryLength() const return length; } +void Program::setBinaryRetrievableHint(bool retrievable) +{ + // TODO(jmadill) : replace with dirty bits + mProgram->setBinaryRetrievableHint(retrievable); + mData.mBinaryRetrieveableHint = retrievable; +} + +bool Program::getBinaryRetrievableHint() const +{ + return mData.mBinaryRetrieveableHint; +} + void Program::release() { mRefCount--; @@ -563,33 +842,33 @@ unsigned int Program::getRefCount() const int Program::getInfoLogLength() const { - return mInfoLog.getLength(); + return static_cast(mInfoLog.getLength()); } -void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) +void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const { return mInfoLog.getLog(bufSize, length, infoLog); } -void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) +void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const { int total = 0; - if (mVertexShader) + if (mData.mAttachedVertexShader) { if (total < maxCount) { - shaders[total] = mVertexShader->getHandle(); + shaders[total] = mData.mAttachedVertexShader->getHandle(); } total++; } - if (mFragmentShader) + if (mData.mAttachedFragmentShader) { if (total < maxCount) { - shaders[total] = mFragmentShader->getHandle(); + shaders[total] = mData.mAttachedFragmentShader->getHandle(); } total++; @@ -601,66 +880,28 @@ void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shade } } -GLuint Program::getAttributeLocation(const std::string &name) +GLuint Program::getAttributeLocation(const std::string &name) const { - for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) + for (const sh::Attribute &attribute : mData.mAttributes) { - if (mLinkedAttribute[index].name == name) + if (attribute.name == name && attribute.staticUse) { - return index; + return attribute.location; } } return static_cast(-1); } -int Program::getSemanticIndex(int attributeIndex) +bool Program::isAttribLocationActive(size_t attribLocation) const { - ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); - - return mProgram->getSemanticIndexes()[attributeIndex]; + ASSERT(attribLocation < mData.mActiveAttribLocationsMask.size()); + return mData.mActiveAttribLocationsMask[attribLocation]; } void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) { - if (mLinked) - { - // Skip over inactive attributes - unsigned int activeAttribute = 0; - unsigned int attribute; - for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) - { - if (mLinkedAttribute[attribute].name.empty()) - { - continue; - } - - if (activeAttribute == index) - { - break; - } - - activeAttribute++; - } - - if (bufsize > 0) - { - const char *string = mLinkedAttribute[attribute].name.c_str(); - - strncpy(name, string, bufsize); - name[bufsize - 1] = '\0'; - - if (length) - { - *length = strlen(name); - } - } - - *size = 1; // Always a single 'type' instance - - *type = mLinkedAttribute[attribute].type; - } - else + if (!mLinked) { if (bufsize > 0) { @@ -674,92 +915,114 @@ void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, *type = GL_NONE; *size = 1; + return; } -} -GLint Program::getActiveAttributeCount() -{ - int count = 0; + size_t attributeIndex = 0; - if (mLinked) + for (const sh::Attribute &attribute : mData.mAttributes) { - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + // Skip over inactive attributes + if (attribute.staticUse) { - if (!mLinkedAttribute[attributeIndex].name.empty()) + if (static_cast(index) == attributeIndex) { - count++; + break; } + attributeIndex++; } } - return count; -} - -GLint Program::getActiveAttributeMaxLength() -{ - int maxLength = 0; + ASSERT(index == attributeIndex && attributeIndex < mData.mAttributes.size()); + const sh::Attribute &attrib = mData.mAttributes[attributeIndex]; - if (mLinked) + if (bufsize > 0) { - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + const char *string = attrib.name.c_str(); + + strncpy(name, string, bufsize); + name[bufsize - 1] = '\0'; + + if (length) { - if (!mLinkedAttribute[attributeIndex].name.empty()) - { - maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength); - } + *length = static_cast(strlen(name)); } } - return maxLength; + // Always a single 'type' instance + *size = 1; + *type = attrib.type; } -// Returns one more than the highest sampler index used. -GLint Program::getUsedSamplerRange(SamplerType type) +GLint Program::getActiveAttributeCount() const { - return mProgram->getUsedSamplerRange(type); -} + if (!mLinked) + { + return 0; + } -bool Program::usesPointSize() const -{ - return mProgram->usesPointSize(); -} + GLint count = 0; -GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) -{ - return mProgram->getSamplerMapping(type, samplerIndex, caps); + for (const sh::Attribute &attrib : mData.mAttributes) + { + count += (attrib.staticUse ? 1 : 0); + } + + return count; } -GLenum Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) +GLint Program::getActiveAttributeMaxLength() const { - return mProgram->getSamplerTextureType(type, samplerIndex); + if (!mLinked) + { + return 0; + } + + size_t maxLength = 0; + + for (const sh::Attribute &attrib : mData.mAttributes) + { + if (attrib.staticUse) + { + maxLength = std::max(attrib.name.length() + 1, maxLength); + } + } + + return static_cast(maxLength); } GLint Program::getFragDataLocation(const std::string &name) const { std::string baseName(name); unsigned int arrayIndex = ParseAndStripArrayIndex(&baseName); - for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++) + for (auto outputPair : mData.mOutputVariables) { - const VariableLocation &outputVariable = locationIt->second; + const VariableLocation &outputVariable = outputPair.second; if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element)) { - return static_cast(locationIt->first); + return static_cast(outputPair.first); } } return -1; } -void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) +void Program::getActiveUniform(GLuint index, + GLsizei bufsize, + GLsizei *length, + GLint *size, + GLenum *type, + GLchar *name) const { if (mLinked) { - ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount() - LinkedUniform *uniform = mProgram->getUniforms()[index]; + // index must be smaller than getActiveUniformCount() + ASSERT(index < mData.mUniforms.size()); + const LinkedUniform &uniform = mData.mUniforms[index]; if (bufsize > 0) { - std::string string = uniform->name; - if (uniform->isArray()) + std::string string = uniform.name; + if (uniform.isArray()) { string += "[0]"; } @@ -769,12 +1032,12 @@ void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, G if (length) { - *length = strlen(name); + *length = static_cast(strlen(name)); } } - *size = uniform->elementCount(); - *type = uniform->type; + *size = uniform.elementCount(); + *type = uniform.type; } else { @@ -793,11 +1056,11 @@ void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, G } } -GLint Program::getActiveUniformCount() +GLint Program::getActiveUniformCount() const { if (mLinked) { - return mProgram->getUniforms().size(); + return static_cast(mData.mUniforms.size()); } else { @@ -805,19 +1068,18 @@ GLint Program::getActiveUniformCount() } } -GLint Program::getActiveUniformMaxLength() +GLint Program::getActiveUniformMaxLength() const { - int maxLength = 0; + size_t maxLength = 0; if (mLinked) { - unsigned int numUniforms = mProgram->getUniforms().size(); - for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++) + for (const LinkedUniform &uniform : mData.mUniforms) { - if (!mProgram->getUniforms()[uniformIndex]->name.empty()) + if (!uniform.name.empty()) { - int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1); - if (mProgram->getUniforms()[uniformIndex]->isArray()) + size_t length = uniform.name.length() + 1u; + if (uniform.isArray()) { length += 3; // Counting in "[0]". } @@ -826,12 +1088,13 @@ GLint Program::getActiveUniformMaxLength() } } - return maxLength; + return static_cast(maxLength); } GLint Program::getActiveUniformi(GLuint index, GLenum pname) const { - const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index]; + ASSERT(static_cast(index) < mData.mUniforms.size()); + const gl::LinkedUniform &uniform = mData.mUniforms[index]; switch (pname) { case GL_UNIFORM_TYPE: return static_cast(uniform.type); @@ -851,159 +1114,165 @@ GLint Program::getActiveUniformi(GLuint index, GLenum pname) const bool Program::isValidUniformLocation(GLint location) const { - ASSERT(rx::IsIntegerCastSafe(mProgram->getUniformIndices().size())); - return (location >= 0 && location < static_cast(mProgram->getUniformIndices().size())); -} - -LinkedUniform *Program::getUniformByLocation(GLint location) const -{ - return mProgram->getUniformByLocation(location); + ASSERT(rx::IsIntegerCastSafe(mData.mUniformLocations.size())); + return (location >= 0 && static_cast(location) < mData.mUniformLocations.size()); } -LinkedUniform *Program::getUniformByName(const std::string &name) const +const LinkedUniform &Program::getUniformByLocation(GLint location) const { - return mProgram->getUniformByName(name); + ASSERT(location >= 0 && static_cast(location) < mData.mUniformLocations.size()); + return mData.mUniforms[mData.mUniformLocations[location].index]; } -GLint Program::getUniformLocation(const std::string &name) +GLint Program::getUniformLocation(const std::string &name) const { - return mProgram->getUniformLocation(name); + return mData.getUniformLocation(name); } -GLuint Program::getUniformIndex(const std::string &name) +GLuint Program::getUniformIndex(const std::string &name) const { - return mProgram->getUniformIndex(name); + return mData.getUniformIndex(name); } void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) { + setUniformInternal(location, count * 1, v); mProgram->setUniform1fv(location, count, v); } void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) { + setUniformInternal(location, count * 2, v); mProgram->setUniform2fv(location, count, v); } void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) { + setUniformInternal(location, count * 3, v); mProgram->setUniform3fv(location, count, v); } void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) { + setUniformInternal(location, count * 4, v); mProgram->setUniform4fv(location, count, v); } void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v) { + setUniformInternal(location, count * 1, v); mProgram->setUniform1iv(location, count, v); } void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v) { + setUniformInternal(location, count * 2, v); mProgram->setUniform2iv(location, count, v); } void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v) { + setUniformInternal(location, count * 3, v); mProgram->setUniform3iv(location, count, v); } void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v) { + setUniformInternal(location, count * 4, v); mProgram->setUniform4iv(location, count, v); } void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) { + setUniformInternal(location, count * 1, v); mProgram->setUniform1uiv(location, count, v); } void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) { + setUniformInternal(location, count * 2, v); mProgram->setUniform2uiv(location, count, v); } void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) { + setUniformInternal(location, count * 3, v); mProgram->setUniform3uiv(location, count, v); } void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) { + setUniformInternal(location, count * 4, v); mProgram->setUniform4uiv(location, count, v); } void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + setMatrixUniformInternal<2, 2>(location, count, transpose, v); mProgram->setUniformMatrix2fv(location, count, transpose, v); } void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + setMatrixUniformInternal<3, 3>(location, count, transpose, v); mProgram->setUniformMatrix3fv(location, count, transpose, v); } void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + setMatrixUniformInternal<4, 4>(location, count, transpose, v); mProgram->setUniformMatrix4fv(location, count, transpose, v); } void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + setMatrixUniformInternal<2, 3>(location, count, transpose, v); mProgram->setUniformMatrix2x3fv(location, count, transpose, v); } void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + setMatrixUniformInternal<2, 4>(location, count, transpose, v); mProgram->setUniformMatrix2x4fv(location, count, transpose, v); } void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + setMatrixUniformInternal<3, 2>(location, count, transpose, v); mProgram->setUniformMatrix3x2fv(location, count, transpose, v); } void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + setMatrixUniformInternal<3, 4>(location, count, transpose, v); mProgram->setUniformMatrix3x4fv(location, count, transpose, v); } void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + setMatrixUniformInternal<4, 2>(location, count, transpose, v); mProgram->setUniformMatrix4x2fv(location, count, transpose, v); } void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) { + setMatrixUniformInternal<4, 3>(location, count, transpose, v); mProgram->setUniformMatrix4x3fv(location, count, transpose, v); } -void Program::getUniformfv(GLint location, GLfloat *v) -{ - mProgram->getUniformfv(location, v); -} - -void Program::getUniformiv(GLint location, GLint *v) -{ - mProgram->getUniformiv(location, v); -} - -void Program::getUniformuiv(GLint location, GLuint *v) +void Program::getUniformfv(GLint location, GLfloat *v) const { - mProgram->getUniformuiv(location, v); + getUniformInternal(location, v); } -// Applies all the uniforms set for this program object to the renderer -Error Program::applyUniforms() +void Program::getUniformiv(GLint location, GLint *v) const { - return mProgram->applyUniforms(); + getUniformInternal(location, v); } -Error Program::applyUniformBuffers(const gl::Data &data) +void Program::getUniformuiv(GLint location, GLuint *v) const { - return mProgram->applyUniformBuffers(data, mUniformBlockBindings); + getUniformInternal(location, v); } void Program::flagForDeletion() @@ -1019,52 +1288,117 @@ bool Program::isFlaggedForDeletion() const void Program::validate(const Caps &caps) { mInfoLog.reset(); - mValidated = false; if (mLinked) { - applyUniforms(); - mValidated = mProgram->validateSamplers(&mInfoLog, caps); + mValidated = (mProgram->validate(caps, &mInfoLog) == GL_TRUE); } else { - mInfoLog.append("Program has not been successfully linked."); + mInfoLog << "Program has not been successfully linked."; } } bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps) { - return mProgram->validateSamplers(infoLog, caps); -} + // Skip cache if we're using an infolog, so we get the full error. + // Also skip the cache if the sample mapping has changed, or if we haven't ever validated. + if (infoLog == nullptr && mCachedValidateSamplersResult.valid()) + { + return mCachedValidateSamplersResult.value(); + } -bool Program::isValidated() const -{ - return mValidated; + if (mTextureUnitTypesCache.empty()) + { + mTextureUnitTypesCache.resize(caps.maxCombinedTextureImageUnits, GL_NONE); + } + else + { + std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE); + } + + // if any two active samplers in a program are of different types, but refer to the same + // texture image unit, and this is the current program, then ValidateProgram will fail, and + // DrawArrays and DrawElements will issue the INVALID_OPERATION error. + for (unsigned int samplerIndex = mSamplerUniformRange.start; + samplerIndex < mSamplerUniformRange.end; ++samplerIndex) + { + const LinkedUniform &uniform = mData.mUniforms[samplerIndex]; + ASSERT(uniform.isSampler()); + + if (!uniform.staticUse) + continue; + + const GLuint *dataPtr = reinterpret_cast(uniform.getDataPtrToElement(0)); + GLenum textureType = SamplerTypeToTextureType(uniform.type); + + for (unsigned int arrayElement = 0; arrayElement < uniform.elementCount(); ++arrayElement) + { + GLuint textureUnit = dataPtr[arrayElement]; + + if (textureUnit >= caps.maxCombinedTextureImageUnits) + { + if (infoLog) + { + (*infoLog) << "Sampler uniform (" << textureUnit + << ") exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (" + << caps.maxCombinedTextureImageUnits << ")"; + } + + mCachedValidateSamplersResult = false; + return false; + } + + if (mTextureUnitTypesCache[textureUnit] != GL_NONE) + { + if (textureType != mTextureUnitTypesCache[textureUnit]) + { + if (infoLog) + { + (*infoLog) << "Samplers of conflicting types refer to the same texture " + "image unit (" + << textureUnit << ")."; + } + + mCachedValidateSamplersResult = false; + return false; + } + } + else + { + mTextureUnitTypesCache[textureUnit] = textureType; + } + } + } + + mCachedValidateSamplersResult = true; + return true; } -void Program::updateSamplerMapping() +bool Program::isValidated() const { - return mProgram->updateSamplerMapping(); + return mValidated; } -GLuint Program::getActiveUniformBlockCount() +GLuint Program::getActiveUniformBlockCount() const { - return mProgram->getUniformBlocks().size(); + return static_cast(mData.mUniformBlocks.size()); } void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const { - ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() + ASSERT(uniformBlockIndex < + mData.mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() - const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; + const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex]; if (bufSize > 0) { std::string string = uniformBlock.name; - if (uniformBlock.isArrayElement()) + if (uniformBlock.isArray) { - string += ArrayString(uniformBlock.elementIndex); + string += ArrayString(uniformBlock.arrayElement); } strncpy(uniformBlockName, string.c_str(), bufSize); @@ -1072,16 +1406,17 @@ void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSiz if (length) { - *length = strlen(uniformBlockName); + *length = static_cast(strlen(uniformBlockName)); } } } void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const { - ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount() + ASSERT(uniformBlockIndex < + mData.mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() - const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; + const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex]; switch (pname) { @@ -1089,7 +1424,8 @@ void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GL *params = static_cast(uniformBlock.dataSize); break; case GL_UNIFORM_BLOCK_NAME_LENGTH: - *params = static_cast(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0)); + *params = + static_cast(uniformBlock.name.size() + 1 + (uniformBlock.isArray ? 3 : 0)); break; case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: *params = static_cast(uniformBlock.memberUniformIndexes.size()); @@ -1103,31 +1439,31 @@ void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GL } break; case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: - *params = static_cast(uniformBlock.isReferencedByVertexShader()); + *params = static_cast(uniformBlock.vertexStaticUse); break; case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: - *params = static_cast(uniformBlock.isReferencedByFragmentShader()); + *params = static_cast(uniformBlock.fragmentStaticUse); break; default: UNREACHABLE(); } } -GLint Program::getActiveUniformBlockMaxLength() +GLint Program::getActiveUniformBlockMaxLength() const { int maxLength = 0; if (mLinked) { - unsigned int numUniformBlocks = mProgram->getUniformBlocks().size(); + unsigned int numUniformBlocks = static_cast(mData.mUniformBlocks.size()); for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) { - const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex]; + const UniformBlock &uniformBlock = mData.mUniformBlocks[uniformBlockIndex]; if (!uniformBlock.name.empty()) { - const int length = uniformBlock.name.length() + 1; + const int length = static_cast(uniformBlock.name.length()) + 1; // Counting in "[0]". - const int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0); + const int arrayLength = (uniformBlock.isArray ? 3 : 0); maxLength = std::max(length + arrayLength, maxLength); } @@ -1137,51 +1473,73 @@ GLint Program::getActiveUniformBlockMaxLength() return maxLength; } -GLuint Program::getUniformBlockIndex(const std::string &name) +GLuint Program::getUniformBlockIndex(const std::string &name) const { - return mProgram->getUniformBlockIndex(name); + size_t subscript = GL_INVALID_INDEX; + std::string baseName = gl::ParseUniformName(name, &subscript); + + unsigned int numUniformBlocks = static_cast(mData.mUniformBlocks.size()); + for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++) + { + const gl::UniformBlock &uniformBlock = mData.mUniformBlocks[blockIndex]; + if (uniformBlock.name == baseName) + { + const bool arrayElementZero = + (subscript == GL_INVALID_INDEX && + (!uniformBlock.isArray || uniformBlock.arrayElement == 0)); + if (subscript == uniformBlock.arrayElement || arrayElementZero) + { + return blockIndex; + } + } + } + + return GL_INVALID_INDEX; } -const UniformBlock *Program::getUniformBlockByIndex(GLuint index) const +const UniformBlock &Program::getUniformBlockByIndex(GLuint index) const { - return mProgram->getUniformBlockByIndex(index); + ASSERT(index < static_cast(mData.mUniformBlocks.size())); + return mData.mUniformBlocks[index]; } void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding) { - mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding; + mData.mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding; + mProgram->setUniformBlockBinding(uniformBlockIndex, uniformBlockBinding); } GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const { - return mUniformBlockBindings[uniformBlockIndex]; + return mData.getUniformBlockBinding(uniformBlockIndex); } void Program::resetUniformBlockBindings() { for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++) { - mUniformBlockBindings[blockId] = 0; + mData.mUniformBlockBindings[blockId] = 0; } + mData.mActiveUniformBlockBindings.reset(); } void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode) { - mTransformFeedbackVaryings.resize(count); + mData.mTransformFeedbackVaryingNames.resize(count); for (GLsizei i = 0; i < count; i++) { - mTransformFeedbackVaryings[i] = varyings[i]; + mData.mTransformFeedbackVaryingNames[i] = varyings[i]; } - mTransformFeedbackBufferMode = bufferMode; + mData.mTransformFeedbackBufferMode = bufferMode; } void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const { if (mLinked) { - ASSERT(index < mProgram->getTransformFeedbackLinkedVaryings().size()); - const LinkedVarying &varying = mProgram->getTransformFeedbackLinkedVaryings()[index]; + ASSERT(index < mData.mTransformFeedbackVaryingVars.size()); + const sh::Varying &varying = mData.mTransformFeedbackVaryingVars[index]; GLsizei lastNameIdx = std::min(bufSize - 1, static_cast(varying.name.length())); if (length) { @@ -1189,7 +1547,7 @@ void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei } if (size) { - *size = varying.size; + *size = varying.elementCount(); } if (type) { @@ -1207,7 +1565,7 @@ GLsizei Program::getTransformFeedbackVaryingCount() const { if (mLinked) { - return static_cast(mProgram->getTransformFeedbackLinkedVaryings().size()); + return static_cast(mData.mTransformFeedbackVaryingVars.size()); } else { @@ -1220,9 +1578,8 @@ GLsizei Program::getTransformFeedbackVaryingMaxLength() const if (mLinked) { GLsizei maxSize = 0; - for (size_t i = 0; i < mProgram->getTransformFeedbackLinkedVaryings().size(); i++) + for (const sh::Varying &varying : mData.mTransformFeedbackVaryingVars) { - const LinkedVarying &varying = mProgram->getTransformFeedbackLinkedVaryings()[i]; maxSize = std::max(maxSize, static_cast(varying.name.length() + 1)); } @@ -1236,64 +1593,123 @@ GLsizei Program::getTransformFeedbackVaryingMaxLength() const GLenum Program::getTransformFeedbackBufferMode() const { - return mTransformFeedbackBufferMode; + return mData.mTransformFeedbackBufferMode; } -bool Program::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) +// static +bool Program::linkVaryings(InfoLog &infoLog, + const Shader *vertexShader, + const Shader *fragmentShader) { - std::vector &fragmentVaryings = fragmentShader->getVaryings(); - std::vector &vertexVaryings = vertexShader->getVaryings(); + const std::vector &vertexVaryings = vertexShader->getVaryings(); + const std::vector &fragmentVaryings = fragmentShader->getVaryings(); - for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++) + for (const sh::Varying &output : fragmentVaryings) { - PackedVarying *input = &fragmentVaryings[fragVaryingIndex]; bool matched = false; // Built-in varyings obey special rules - if (input->isBuiltIn()) + if (output.isBuiltIn()) { continue; } - for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) + for (const sh::Varying &input : vertexVaryings) { - PackedVarying *output = &vertexVaryings[vertVaryingIndex]; - if (output->name == input->name) + if (output.name == input.name) { - if (!linkValidateVaryings(infoLog, output->name, *input, *output)) + ASSERT(!input.isBuiltIn()); + if (!linkValidateVaryings(infoLog, output.name, input, output)) { return false; } - output->registerIndex = input->registerIndex; - output->columnIndex = input->columnIndex; - matched = true; break; } } // We permit unmatched, unreferenced varyings - if (!matched && input->staticUse) + if (!matched && output.staticUse) { - infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str()); + infoLog << "Fragment varying " << output.name << " does not match any vertex varying"; return false; } } + // TODO(jmadill): verify no unmatched vertex varyings? + + return true; +} + +bool Program::linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps) +{ + const std::vector &vertexUniforms = mData.mAttachedVertexShader->getUniforms(); + const std::vector &fragmentUniforms = mData.mAttachedFragmentShader->getUniforms(); + + // Check that uniforms defined in the vertex and fragment shaders are identical + std::map linkedUniforms; + + for (const sh::Uniform &vertexUniform : vertexUniforms) + { + linkedUniforms[vertexUniform.name] = LinkedUniform(vertexUniform); + } + + for (const sh::Uniform &fragmentUniform : fragmentUniforms) + { + auto entry = linkedUniforms.find(fragmentUniform.name); + if (entry != linkedUniforms.end()) + { + LinkedUniform *vertexUniform = &entry->second; + const std::string &uniformName = "uniform '" + vertexUniform->name + "'"; + if (!linkValidateUniforms(infoLog, uniformName, *vertexUniform, fragmentUniform)) + { + return false; + } + } + } + + // Flatten the uniforms list (nested fields) into a simple list (no nesting). + // Also check the maximum uniform vector and sampler counts. + if (!flattenUniformsAndCheckCaps(caps, infoLog)) + { + return false; + } + + indexUniforms(); + return true; } +void Program::indexUniforms() +{ + for (size_t uniformIndex = 0; uniformIndex < mData.mUniforms.size(); uniformIndex++) + { + const gl::LinkedUniform &uniform = mData.mUniforms[uniformIndex]; + + for (unsigned int arrayIndex = 0; arrayIndex < uniform.elementCount(); arrayIndex++) + { + if (!uniform.isBuiltIn()) + { + // Assign in-order uniform locations + mData.mUniformLocations.push_back(gl::VariableLocation( + uniform.name, arrayIndex, static_cast(uniformIndex))); + } + } + } +} + bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) { - if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) + // We don't validate precision on UBO fields. See resolution of Khronos bug 10287. + if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, false)) { return false; } if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout) { - infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); + infoLog << "Matrix packings for " << uniformName << " differ between vertex and fragment shaders"; return false; } @@ -1301,143 +1717,168 @@ bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::stri } // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices -bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader) +bool Program::linkAttributes(const gl::Data &data, + InfoLog &infoLog, + const AttributeBindings &attributeBindings, + const Shader *vertexShader) { unsigned int usedLocations = 0; - const std::vector &shaderAttributes = vertexShader->getActiveAttributes(); + mData.mAttributes = vertexShader->getActiveAttributes(); + GLuint maxAttribs = data.caps->maxVertexAttributes; - // Link attributes that have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) + // TODO(jmadill): handle aliasing robustly + if (mData.mAttributes.size() > maxAttribs) { - const sh::Attribute &attribute = shaderAttributes[attributeIndex]; + infoLog << "Too many vertex attributes."; + return false; + } - ASSERT(attribute.staticUse); + std::vector usedAttribMap(data.caps->maxVertexAttributes, nullptr); - const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; + // Link attributes that have a binding location + for (sh::Attribute &attribute : mData.mAttributes) + { + // TODO(jmadill): do staticUse filtering step here, or not at all + ASSERT(attribute.staticUse); - mProgram->getShaderAttributes()[attributeIndex] = attribute; + int bindingLocation = attributeBindings.getAttributeBinding(attribute.name); + if (attribute.location == -1 && bindingLocation != -1) + { + attribute.location = bindingLocation; + } - if (location != -1) // Set by glBindAttribLocation or by location layout qualifier + if (attribute.location != -1) { - const int rows = VariableRegisterCount(attribute.type); + // Location is set by glBindAttribLocation or by location layout qualifier + const int regs = VariableRegisterCount(attribute.type); - if (rows + location > MAX_VERTEX_ATTRIBS) + if (static_cast(regs + attribute.location) > maxAttribs) { - infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location); + infoLog << "Active attribute (" << attribute.name << ") at location " + << attribute.location << " is too big to fit"; return false; } - for (int row = 0; row < rows; row++) + for (int reg = 0; reg < regs; reg++) { - const int rowLocation = location + row; - sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation]; + const int regLocation = attribute.location + reg; + sh::ShaderVariable *linkedAttribute = usedAttribMap[regLocation]; // In GLSL 3.00, attribute aliasing produces a link error - // In GLSL 1.00, attribute aliasing is allowed - if (mProgram->getShaderVersion() >= 300) + // In GLSL 1.00, attribute aliasing is allowed, but ANGLE currently has a bug + if (linkedAttribute) { - if (!linkedAttribute.name.empty()) + // TODO(jmadill): fix aliasing on ES2 + // if (mProgram->getShaderVersion() >= 300) { - infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation); + infoLog << "Attribute '" << attribute.name << "' aliases attribute '" + << linkedAttribute->name << "' at location " << regLocation; return false; } } + else + { + usedAttribMap[regLocation] = &attribute; + } - linkedAttribute = attribute; - usedLocations |= 1 << rowLocation; + usedLocations |= 1 << regLocation; } } } // Link attributes that don't have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) + for (sh::Attribute &attribute : mData.mAttributes) { - const sh::Attribute &attribute = shaderAttributes[attributeIndex]; - ASSERT(attribute.staticUse); - const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; - - if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier + // Not set by glBindAttribLocation or by location layout qualifier + if (attribute.location == -1) { - int rows = VariableRegisterCount(attribute.type); - int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS); + int regs = VariableRegisterCount(attribute.type); + int availableIndex = AllocateFirstFreeBits(&usedLocations, regs, maxAttribs); - if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS) + if (availableIndex == -1 || static_cast(availableIndex + regs) > maxAttribs) { - infoLog.append("Too many active attributes (%s)", attribute.name.c_str()); - - return false; // Fail to link + infoLog << "Too many active attributes (" << attribute.name << ")"; + return false; } - mLinkedAttribute[availableIndex] = attribute; + attribute.location = availableIndex; } } - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) + for (const sh::Attribute &attribute : mData.mAttributes) { - int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); - int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); + ASSERT(attribute.staticUse); + ASSERT(attribute.location != -1); + int regs = VariableRegisterCount(attribute.type); - for (int r = 0; r < rows; r++) + for (int r = 0; r < regs; r++) { - mProgram->getSemanticIndexes()[attributeIndex++] = index++; + mData.mActiveAttribLocationsMask.set(attribute.location + r); } } return true; } -bool Program::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) +bool Program::linkUniformBlocks(InfoLog &infoLog, const Caps &caps) { + const Shader &vertexShader = *mData.mAttachedVertexShader; + const Shader &fragmentShader = *mData.mAttachedFragmentShader; + const std::vector &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); const std::vector &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); + // Check that interface blocks defined in the vertex and fragment shaders are identical typedef std::map UniformBlockMap; UniformBlockMap linkedUniformBlocks; - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) + + GLuint vertexBlockCount = 0; + for (const sh::InterfaceBlock &vertexInterfaceBlock : vertexInterfaceBlocks) { - const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; - } - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; - UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); - if (entry != linkedUniformBlocks.end()) + + // Note: shared and std140 layouts are always considered active + if (vertexInterfaceBlock.staticUse || vertexInterfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) { - const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; - if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) + if (++vertexBlockCount > caps.maxVertexUniformBlocks) { + infoLog << "Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (" + << caps.maxVertexUniformBlocks << ")"; return false; } } } - for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) + + GLuint fragmentBlockCount = 0; + for (const sh::InterfaceBlock &fragmentInterfaceBlock : fragmentInterfaceBlocks) { - const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; - // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) + auto entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); + if (entry != linkedUniformBlocks.end()) { - if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) + const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; + if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) { return false; } } - } - for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; + // Note: shared and std140 layouts are always considered active - if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) + if (fragmentInterfaceBlock.staticUse || + fragmentInterfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) { - if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) + if (++fragmentBlockCount > caps.maxFragmentUniformBlocks) { + infoLog + << "Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (" + << caps.maxFragmentUniformBlocks << ")"; return false; } } } + return true; } @@ -1448,28 +1889,34 @@ bool Program::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::Interfa // validate blocks for the same member types if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size()) { - infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName); + infoLog << "Types for interface block '" << blockName + << "' differ between vertex and fragment shaders"; return false; } if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize) { - infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName); + infoLog << "Array sizes differ for interface block '" << blockName + << "' between vertex and fragment shaders"; return false; } if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout) { - infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName); + infoLog << "Layout qualifiers differ for interface block '" << blockName + << "' between vertex and fragment shaders"; return false; } - const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); + const unsigned int numBlockMembers = + static_cast(vertexInterfaceBlock.fields.size()); for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) { const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; if (vertexMember.name != fragmentMember.name) { - infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')", - blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str()); + infoLog << "Name mismatch for field " << blockMemberIndex + << " of interface block '" << blockName + << "': (in vertex: '" << vertexMember.name + << "', in fragment: '" << fragmentMember.name << "')"; return false; } std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; @@ -1486,26 +1933,26 @@ bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &var { if (vertexVariable.type != fragmentVariable.type) { - infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str()); + infoLog << "Types for " << variableName << " differ between vertex and fragment shaders"; return false; } if (vertexVariable.arraySize != fragmentVariable.arraySize) { - infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str()); + infoLog << "Array sizes for " << variableName << " differ between vertex and fragment shaders"; return false; } if (validatePrecision && vertexVariable.precision != fragmentVariable.precision) { - infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str()); + infoLog << "Precisions for " << variableName << " differ between vertex and fragment shaders"; return false; } if (vertexVariable.fields.size() != fragmentVariable.fields.size()) { - infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str()); + infoLog << "Structure lengths for " << variableName << " differ between vertex and fragment shaders"; return false; } - const unsigned int numMembers = vertexVariable.fields.size(); + const unsigned int numMembers = static_cast(vertexVariable.fields.size()); for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++) { const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex]; @@ -1513,9 +1960,10 @@ bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &var if (vertexMember.name != fragmentMember.name) { - infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')", - memberIndex, variableName.c_str(), - vertexMember.name.c_str(), fragmentMember.name.c_str()); + infoLog << "Name mismatch for field '" << memberIndex + << "' of " << variableName + << ": (in vertex: '" << vertexMember.name + << "', in fragment: '" << fragmentMember.name << "')"; return false; } @@ -1533,7 +1981,13 @@ bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &var bool Program::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) { - if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) +#if ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION == ANGLE_ENABLED + const bool validatePrecision = true; +#else + const bool validatePrecision = false; +#endif + + if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, validatePrecision)) { return false; } @@ -1550,68 +2004,530 @@ bool Program::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingN if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation)) { - infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str()); + infoLog << "Interpolation types for " << varyingName << " differ between vertex and fragment shaders"; return false; } return true; } -bool Program::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, - const std::vector &transformFeedbackVaryingNames, - GLenum transformFeedbackBufferMode, - std::vector *outTransformFeedbackLinkedVaryings, - const Caps &caps) const +bool Program::linkValidateTransformFeedback(InfoLog &infoLog, + const std::vector &varyings, + const Caps &caps) const { size_t totalComponents = 0; - // Gather the linked varyings that are used for transform feedback, they should all exist. - outTransformFeedbackLinkedVaryings->clear(); - for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++) + std::set uniqueNames; + + for (const std::string &tfVaryingName : mData.mTransformFeedbackVaryingNames) { bool found = false; - for (size_t j = 0; j < linkedVaryings.size(); j++) + for (const sh::Varying *varying : varyings) { - if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name) + if (tfVaryingName == varying->name) { - for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++) + if (uniqueNames.count(tfVaryingName) > 0) { - if (outTransformFeedbackLinkedVaryings->at(k).name == linkedVaryings[j].name) - { - infoLog.append("Two transform feedback varyings specify the same output variable (%s).", linkedVaryings[j].name.c_str()); - return false; - } + infoLog << "Two transform feedback varyings specify the same output variable (" + << tfVaryingName << ")."; + return false; + } + uniqueNames.insert(tfVaryingName); + + if (varying->isArray()) + { + infoLog << "Capture of arrays is undefined and not supported."; + return false; } - size_t componentCount = linkedVaryings[j].semanticIndexCount * 4; - if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && + // TODO(jmadill): Investigate implementation limits on D3D11 + size_t componentCount = gl::VariableComponentCount(varying->type); + if (mData.mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && componentCount > caps.maxTransformFeedbackSeparateComponents) { - infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).", - linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents); + infoLog << "Transform feedback varying's " << varying->name << " components (" + << componentCount << ") exceed the maximum separate components (" + << caps.maxTransformFeedbackSeparateComponents << ")."; return false; } totalComponents += componentCount; - - outTransformFeedbackLinkedVaryings->push_back(linkedVaryings[j]); found = true; break; } } + if (tfVaryingName.find('[') != std::string::npos) + { + infoLog << "Capture of array elements is undefined and not supported."; + return false; + } + // All transform feedback varyings are expected to exist since packVaryings checks for them. ASSERT(found); + UNUSED_ASSERTION_VARIABLE(found); } - if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents) + if (mData.mTransformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && + totalComponents > caps.maxTransformFeedbackInterleavedComponents) { - infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).", - totalComponents, caps.maxTransformFeedbackInterleavedComponents); + infoLog << "Transform feedback varying total components (" << totalComponents + << ") exceed the maximum interleaved components (" + << caps.maxTransformFeedbackInterleavedComponents << ")."; return false; } return true; } +void Program::gatherTransformFeedbackVaryings(const std::vector &varyings) +{ + // Gather the linked varyings that are used for transform feedback, they should all exist. + mData.mTransformFeedbackVaryingVars.clear(); + for (const std::string &tfVaryingName : mData.mTransformFeedbackVaryingNames) + { + for (const sh::Varying *varying : varyings) + { + if (tfVaryingName == varying->name) + { + mData.mTransformFeedbackVaryingVars.push_back(*varying); + break; + } + } + } +} + +std::vector Program::getMergedVaryings() const +{ + std::set uniqueNames; + std::vector varyings; + + for (const sh::Varying &varying : mData.mAttachedVertexShader->getVaryings()) + { + if (uniqueNames.count(varying.name) == 0) + { + uniqueNames.insert(varying.name); + varyings.push_back(&varying); + } + } + + for (const sh::Varying &varying : mData.mAttachedFragmentShader->getVaryings()) + { + if (uniqueNames.count(varying.name) == 0) + { + uniqueNames.insert(varying.name); + varyings.push_back(&varying); + } + } + + return varyings; +} + +void Program::linkOutputVariables() +{ + const Shader *fragmentShader = mData.mAttachedFragmentShader; + ASSERT(fragmentShader != nullptr); + + // Skip this step for GLES2 shaders. + if (fragmentShader->getShaderVersion() == 100) + return; + + const auto &shaderOutputVars = fragmentShader->getActiveOutputVariables(); + + // TODO(jmadill): any caps validation here? + + for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); + outputVariableIndex++) + { + const sh::OutputVariable &outputVariable = shaderOutputVars[outputVariableIndex]; + + // Don't store outputs for gl_FragDepth, gl_FragColor, etc. + if (outputVariable.isBuiltIn()) + continue; + + // Since multiple output locations must be specified, use 0 for non-specified locations. + int baseLocation = (outputVariable.location == -1 ? 0 : outputVariable.location); + + ASSERT(outputVariable.staticUse); + + for (unsigned int elementIndex = 0; elementIndex < outputVariable.elementCount(); + elementIndex++) + { + const int location = baseLocation + elementIndex; + ASSERT(mData.mOutputVariables.count(location) == 0); + unsigned int element = outputVariable.isArray() ? elementIndex : GL_INVALID_INDEX; + mData.mOutputVariables[location] = + VariableLocation(outputVariable.name, element, outputVariableIndex); + } + } +} + +bool Program::flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog) +{ + const gl::Shader *vertexShader = mData.getAttachedVertexShader(); + VectorAndSamplerCount vsCounts; + + std::vector samplerUniforms; + + for (const sh::Uniform &uniform : vertexShader->getUniforms()) + { + if (uniform.staticUse) + { + vsCounts += flattenUniform(uniform, uniform.name, &samplerUniforms); + } + } + + if (vsCounts.vectorCount > caps.maxVertexUniformVectors) + { + infoLog << "Vertex shader active uniforms exceed MAX_VERTEX_UNIFORM_VECTORS (" + << caps.maxVertexUniformVectors << ")."; + return false; + } + + if (vsCounts.samplerCount > caps.maxVertexTextureImageUnits) + { + infoLog << "Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (" + << caps.maxVertexTextureImageUnits << ")."; + return false; + } + + const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); + VectorAndSamplerCount fsCounts; + + for (const sh::Uniform &uniform : fragmentShader->getUniforms()) + { + if (uniform.staticUse) + { + fsCounts += flattenUniform(uniform, uniform.name, &samplerUniforms); + } + } + + if (fsCounts.vectorCount > caps.maxFragmentUniformVectors) + { + infoLog << "Fragment shader active uniforms exceed MAX_FRAGMENT_UNIFORM_VECTORS (" + << caps.maxFragmentUniformVectors << ")."; + return false; + } + + if (fsCounts.samplerCount > caps.maxTextureImageUnits) + { + infoLog << "Fragment shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (" + << caps.maxTextureImageUnits << ")."; + return false; + } + + mSamplerUniformRange.start = static_cast(mData.mUniforms.size()); + mSamplerUniformRange.end = + mSamplerUniformRange.start + static_cast(samplerUniforms.size()); + + mData.mUniforms.insert(mData.mUniforms.end(), samplerUniforms.begin(), samplerUniforms.end()); + + return true; +} + +Program::VectorAndSamplerCount Program::flattenUniform(const sh::ShaderVariable &uniform, + const std::string &fullName, + std::vector *samplerUniforms) +{ + VectorAndSamplerCount vectorAndSamplerCount; + + if (uniform.isStruct()) + { + for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) + { + const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); + + for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) + { + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; + const std::string &fieldFullName = (fullName + elementString + "." + field.name); + + vectorAndSamplerCount += flattenUniform(field, fieldFullName, samplerUniforms); + } + } + + return vectorAndSamplerCount; + } + + // Not a struct + bool isSampler = IsSamplerType(uniform.type); + if (!UniformInList(mData.getUniforms(), fullName) && !UniformInList(*samplerUniforms, fullName)) + { + gl::LinkedUniform linkedUniform(uniform.type, uniform.precision, fullName, + uniform.arraySize, -1, + sh::BlockMemberInfo::getDefaultBlockInfo()); + linkedUniform.staticUse = true; + + // Store sampler uniforms separately, so we'll append them to the end of the list. + if (isSampler) + { + samplerUniforms->push_back(linkedUniform); + } + else + { + mData.mUniforms.push_back(linkedUniform); + } + } + + unsigned int elementCount = uniform.elementCount(); + + // Samplers aren't "real" uniforms, so they don't count towards register usage. + // Likewise, don't count "real" uniforms towards sampler count. + vectorAndSamplerCount.vectorCount = + (isSampler ? 0 : (VariableRegisterCount(uniform.type) * elementCount)); + vectorAndSamplerCount.samplerCount = (isSampler ? elementCount : 0); + + return vectorAndSamplerCount; +} + +void Program::gatherInterfaceBlockInfo() +{ + std::set visitedList; + + const gl::Shader *vertexShader = mData.getAttachedVertexShader(); + + ASSERT(mData.mUniformBlocks.empty()); + for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks()) + { + // Only 'packed' blocks are allowed to be considered inacive. + if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED) + continue; + + if (visitedList.count(vertexBlock.name) > 0) + continue; + + defineUniformBlock(vertexBlock, GL_VERTEX_SHADER); + visitedList.insert(vertexBlock.name); + } + + const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); + + for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks()) + { + // Only 'packed' blocks are allowed to be considered inacive. + if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED) + continue; + + if (visitedList.count(fragmentBlock.name) > 0) + { + for (gl::UniformBlock &block : mData.mUniformBlocks) + { + if (block.name == fragmentBlock.name) + { + block.fragmentStaticUse = fragmentBlock.staticUse; + } + } + + continue; + } + + defineUniformBlock(fragmentBlock, GL_FRAGMENT_SHADER); + visitedList.insert(fragmentBlock.name); + } +} + +template +void Program::defineUniformBlockMembers(const std::vector &fields, + const std::string &prefix, + int blockIndex) +{ + for (const VarT &field : fields) + { + const std::string &fullName = (prefix.empty() ? field.name : prefix + "." + field.name); + + if (field.isStruct()) + { + for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) + { + const std::string uniformElementName = + fullName + (field.isArray() ? ArrayString(arrayElement) : ""); + defineUniformBlockMembers(field.fields, uniformElementName, blockIndex); + } + } + else + { + // If getBlockMemberInfo returns false, the uniform is optimized out. + sh::BlockMemberInfo memberInfo; + if (!mProgram->getUniformBlockMemberInfo(fullName, &memberInfo)) + { + continue; + } + + LinkedUniform newUniform(field.type, field.precision, fullName, field.arraySize, + blockIndex, memberInfo); + + // Since block uniforms have no location, we don't need to store them in the uniform + // locations list. + mData.mUniforms.push_back(newUniform); + } + } +} + +void Program::defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType) +{ + int blockIndex = static_cast(mData.mUniformBlocks.size()); + size_t blockSize = 0; + + // Don't define this block at all if it's not active in the implementation. + if (!mProgram->getUniformBlockSize(interfaceBlock.name, &blockSize)) + { + return; + } + + // Track the first and last uniform index to determine the range of active uniforms in the + // block. + size_t firstBlockUniformIndex = mData.mUniforms.size(); + defineUniformBlockMembers(interfaceBlock.fields, interfaceBlock.fieldPrefix(), blockIndex); + size_t lastBlockUniformIndex = mData.mUniforms.size(); + + std::vector blockUniformIndexes; + for (size_t blockUniformIndex = firstBlockUniformIndex; + blockUniformIndex < lastBlockUniformIndex; ++blockUniformIndex) + { + blockUniformIndexes.push_back(static_cast(blockUniformIndex)); + } + + if (interfaceBlock.arraySize > 0) + { + for (unsigned int arrayElement = 0; arrayElement < interfaceBlock.arraySize; ++arrayElement) + { + UniformBlock block(interfaceBlock.name, true, arrayElement); + block.memberUniformIndexes = blockUniformIndexes; + + if (shaderType == GL_VERTEX_SHADER) + { + block.vertexStaticUse = interfaceBlock.staticUse; + } + else + { + ASSERT(shaderType == GL_FRAGMENT_SHADER); + block.fragmentStaticUse = interfaceBlock.staticUse; + } + + // TODO(jmadill): Determine if we can ever have an inactive array element block. + size_t blockElementSize = 0; + if (!mProgram->getUniformBlockSize(block.nameWithArrayIndex(), &blockElementSize)) + { + continue; + } + + ASSERT(blockElementSize == blockSize); + block.dataSize = static_cast(blockElementSize); + mData.mUniformBlocks.push_back(block); + } + } + else + { + UniformBlock block(interfaceBlock.name, false, 0); + block.memberUniformIndexes = blockUniformIndexes; + + if (shaderType == GL_VERTEX_SHADER) + { + block.vertexStaticUse = interfaceBlock.staticUse; + } + else + { + ASSERT(shaderType == GL_FRAGMENT_SHADER); + block.fragmentStaticUse = interfaceBlock.staticUse; + } + + block.dataSize = static_cast(blockSize); + mData.mUniformBlocks.push_back(block); + } +} + +template +void Program::setUniformInternal(GLint location, GLsizei count, const T *v) +{ + const VariableLocation &locationInfo = mData.mUniformLocations[location]; + LinkedUniform *linkedUniform = &mData.mUniforms[locationInfo.index]; + uint8_t *destPointer = linkedUniform->getDataPtrToElement(locationInfo.element); + + if (VariableComponentType(linkedUniform->type) == GL_BOOL) + { + // Do a cast conversion for boolean types. From the spec: + // "The uniform is set to FALSE if the input value is 0 or 0.0f, and set to TRUE otherwise." + GLint *destAsInt = reinterpret_cast(destPointer); + for (GLsizei component = 0; component < count; ++component) + { + destAsInt[component] = (v[component] != static_cast(0) ? GL_TRUE : GL_FALSE); + } + } + else + { + // Invalide the validation cache if we modify the sampler data. + if (linkedUniform->isSampler() && memcmp(destPointer, v, sizeof(T) * count) != 0) + { + mCachedValidateSamplersResult.reset(); + } + + memcpy(destPointer, v, sizeof(T) * count); + } +} + +template +void Program::setMatrixUniformInternal(GLint location, + GLsizei count, + GLboolean transpose, + const T *v) +{ + if (!transpose) + { + setUniformInternal(location, count * cols * rows, v); + return; + } + + // Perform a transposing copy. + const VariableLocation &locationInfo = mData.mUniformLocations[location]; + LinkedUniform *linkedUniform = &mData.mUniforms[locationInfo.index]; + T *destPtr = reinterpret_cast(linkedUniform->getDataPtrToElement(locationInfo.element)); + for (GLsizei element = 0; element < count; ++element) + { + size_t elementOffset = element * rows * cols; + + for (size_t row = 0; row < rows; ++row) + { + for (size_t col = 0; col < cols; ++col) + { + destPtr[col * rows + row + elementOffset] = v[row * cols + col + elementOffset]; + } + } + } +} + +template +void Program::getUniformInternal(GLint location, DestT *dataOut) const +{ + const VariableLocation &locationInfo = mData.mUniformLocations[location]; + const LinkedUniform &uniform = mData.mUniforms[locationInfo.index]; + + const uint8_t *srcPointer = uniform.getDataPtrToElement(locationInfo.element); + + GLenum componentType = VariableComponentType(uniform.type); + if (componentType == GLTypeToGLenum::value) + { + memcpy(dataOut, srcPointer, uniform.getElementSize()); + return; + } + + int components = VariableComponentCount(uniform.type) * uniform.elementCount(); + + switch (componentType) + { + case GL_INT: + UniformStateQueryCastLoop(dataOut, srcPointer, components); + break; + case GL_UNSIGNED_INT: + UniformStateQueryCastLoop(dataOut, srcPointer, components); + break; + case GL_BOOL: + UniformStateQueryCastLoop(dataOut, srcPointer, components); + break; + case GL_FLOAT: + UniformStateQueryCastLoop(dataOut, srcPointer, components); + break; + default: + UNREACHABLE(); + } +} } diff --git a/src/3rdparty/angle/src/libANGLE/Program.h b/src/3rdparty/angle/src/libANGLE/Program.h index 38fc83d29d..f885ad1694 100644 --- a/src/3rdparty/angle/src/libANGLE/Program.h +++ b/src/3rdparty/angle/src/libANGLE/Program.h @@ -10,26 +10,29 @@ #ifndef LIBANGLE_PROGRAM_H_ #define LIBANGLE_PROGRAM_H_ -#include "libANGLE/angletypes.h" -#include "libANGLE/Constants.h" -#include "libANGLE/Error.h" -#include "libANGLE/RefCountObject.h" - -#include "common/angleutils.h" - #include #include -#include -#include #include +#include +#include +#include + +#include "common/angleutils.h" +#include "common/mathutil.h" +#include "common/Optional.h" + +#include "libANGLE/angletypes.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Debug.h" +#include "libANGLE/Error.h" +#include "libANGLE/RefCountObject.h" namespace rx { -class Renderer; -class Renderer; -struct TranslatedAttribute; +class ImplFactory; class ProgramImpl; +struct TranslatedAttribute; } namespace gl @@ -66,14 +69,68 @@ class InfoLog : angle::NonCopyable InfoLog(); ~InfoLog(); - int getLength() const; - void getLog(GLsizei bufSize, GLsizei *length, char *infoLog); + size_t getLength() const; + void getLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; void appendSanitized(const char *message); - void append(const char *info, ...); void reset(); + + // This helper class ensures we append a newline after writing a line. + class StreamHelper : angle::NonCopyable + { + public: + StreamHelper(StreamHelper &&rhs) + : mStream(rhs.mStream) + { + rhs.mStream = nullptr; + } + + StreamHelper &operator=(StreamHelper &&rhs) + { + std::swap(mStream, rhs.mStream); + return *this; + } + + ~StreamHelper() + { + // Write newline when destroyed on the stack + if (mStream) + { + (*mStream) << std::endl; + } + } + + template + StreamHelper &operator<<(const T &value) + { + (*mStream) << value; + return *this; + } + + private: + friend class InfoLog; + + StreamHelper(std::stringstream *stream) + : mStream(stream) + { + ASSERT(stream); + } + + std::stringstream *mStream; + }; + + template + StreamHelper operator<<(const T &value) + { + StreamHelper helper(&mStream); + helper << value; + return helper; + } + + std::string str() const { return mStream.str(); } + private: - char *mInfoLog; + std::stringstream mStream; }; // Struct used for correlating uniforms/elements of uniform arrays to handles @@ -87,32 +144,94 @@ struct VariableLocation unsigned int index; }; -struct LinkedVarying -{ - LinkedVarying(); - LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, - unsigned int semanticIndex, unsigned int semanticIndexCount); - - // Original GL name - std::string name; - - GLenum type; - GLsizei size; - - // DirectX semantic information - std::string semanticName; - unsigned int semanticIndex; - unsigned int semanticIndexCount; -}; - -class Program : angle::NonCopyable +class Program final : angle::NonCopyable, public LabeledObject { public: - Program(rx::ProgramImpl *impl, ResourceManager *manager, GLuint handle); + class Data final : angle::NonCopyable + { + public: + Data(); + ~Data(); + + const std::string &getLabel(); + + const Shader *getAttachedVertexShader() const { return mAttachedVertexShader; } + const Shader *getAttachedFragmentShader() const { return mAttachedFragmentShader; } + const std::vector &getTransformFeedbackVaryingNames() const + { + return mTransformFeedbackVaryingNames; + } + GLint getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } + GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const + { + ASSERT(uniformBlockIndex < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + return mUniformBlockBindings[uniformBlockIndex]; + } + const UniformBlockBindingMask &getActiveUniformBlockBindingsMask() const + { + return mActiveUniformBlockBindings; + } + const std::vector &getAttributes() const { return mAttributes; } + const AttributesMask &getActiveAttribLocationsMask() const + { + return mActiveAttribLocationsMask; + } + const std::map &getOutputVariables() const + { + return mOutputVariables; + } + const std::vector &getUniforms() const { return mUniforms; } + const std::vector &getUniformLocations() const + { + return mUniformLocations; + } + const std::vector &getUniformBlocks() const { return mUniformBlocks; } + + const LinkedUniform *getUniformByName(const std::string &name) const; + GLint getUniformLocation(const std::string &name) const; + GLuint getUniformIndex(const std::string &name) const; + + private: + friend class Program; + + std::string mLabel; + + Shader *mAttachedFragmentShader; + Shader *mAttachedVertexShader; + + std::vector mTransformFeedbackVaryingNames; + std::vector mTransformFeedbackVaryingVars; + GLenum mTransformFeedbackBufferMode; + + GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + UniformBlockBindingMask mActiveUniformBlockBindings; + + std::vector mAttributes; + std::bitset mActiveAttribLocationsMask; + + // Uniforms are sorted in order: + // 1. Non-sampler uniforms + // 2. Sampler uniforms + // 3. Uniform block uniforms + // This makes sampler validation easier, since we don't need a separate list. + std::vector mUniforms; + std::vector mUniformLocations; + std::vector mUniformBlocks; + + // TODO(jmadill): use unordered/hash map when available + std::map mOutputVariables; + + bool mBinaryRetrieveableHint; + }; + + Program(rx::ImplFactory *factory, ResourceManager *manager, GLuint handle); ~Program(); GLuint id() const { return mHandle; } + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + rx::ProgramImpl *getImplementation() { return mProgram; } const rx::ProgramImpl *getImplementation() const { return mProgram; } @@ -122,41 +241,43 @@ class Program : angle::NonCopyable void bindAttributeLocation(GLuint index, const char *name); - Error link(const Data &data); - bool isLinked(); + Error link(const gl::Data &data); + bool isLinked() const; Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length); Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const; GLint getBinaryLength() const; + void setBinaryRetrievableHint(bool retrievable); + bool getBinaryRetrievableHint() const; int getInfoLogLength() const; - void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); - void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); + void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; + void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders) const; - GLuint getAttributeLocation(const std::string &name); - int getSemanticIndex(int attributeIndex); + GLuint getAttributeLocation(const std::string &name) const; + bool isAttribLocationActive(size_t attribLocation) const; void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveAttributeCount(); - GLint getActiveAttributeMaxLength(); - - GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps); - GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex); - GLint getUsedSamplerRange(SamplerType type); - bool usesPointSize() const; + GLint getActiveAttributeCount() const; + GLint getActiveAttributeMaxLength() const; + const std::vector &getAttributes() const { return mData.mAttributes; } GLint getFragDataLocation(const std::string &name) const; - void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); - GLint getActiveUniformCount(); - GLint getActiveUniformMaxLength(); + void getActiveUniform(GLuint index, + GLsizei bufsize, + GLsizei *length, + GLint *size, + GLenum *type, + GLchar *name) const; + GLint getActiveUniformCount() const; + GLint getActiveUniformMaxLength() const; GLint getActiveUniformi(GLuint index, GLenum pname) const; bool isValidUniformLocation(GLint location) const; - LinkedUniform *getUniformByLocation(GLint location) const; - LinkedUniform *getUniformByName(const std::string &name) const; + const LinkedUniform &getUniformByLocation(GLint location) const; - GLint getUniformLocation(const std::string &name); - GLuint getUniformIndex(const std::string &name); + GLint getUniformLocation(const std::string &name) const; + GLuint getUniformIndex(const std::string &name) const; void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); @@ -179,24 +300,21 @@ class Program : angle::NonCopyable void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void getUniformfv(GLint location, GLfloat *params); - void getUniformiv(GLint location, GLint *params); - void getUniformuiv(GLint location, GLuint *params); - - Error applyUniforms(); - Error applyUniformBuffers(const gl::Data &data); + void getUniformfv(GLint location, GLfloat *params) const; + void getUniformiv(GLint location, GLint *params) const; + void getUniformuiv(GLint location, GLuint *params) const; void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const; void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; - GLuint getActiveUniformBlockCount(); - GLint getActiveUniformBlockMaxLength(); + GLuint getActiveUniformBlockCount() const; + GLint getActiveUniformBlockMaxLength() const; - GLuint getUniformBlockIndex(const std::string &name); + GLuint getUniformBlockIndex(const std::string &name) const; void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; - const UniformBlock *getUniformBlockByIndex(GLuint index) const; + const UniformBlock &getUniformBlockByIndex(GLuint index) const; void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; @@ -204,7 +322,6 @@ class Program : angle::NonCopyable GLsizei getTransformFeedbackVaryingMaxLength() const; GLenum getTransformFeedbackBufferMode() const; - static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader); static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); @@ -217,14 +334,26 @@ class Program : angle::NonCopyable void validate(const Caps &caps); bool validateSamplers(InfoLog *infoLog, const Caps &caps); bool isValidated() const; - void updateSamplerMapping(); + + const AttributesMask &getActiveAttribLocationsMask() const + { + return mData.mActiveAttribLocationsMask; + } private: void unlink(bool destroy = false); void resetUniformBlockBindings(); - bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader); - bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); + bool linkAttributes(const gl::Data &data, + InfoLog &infoLog, + const AttributeBindings &attributeBindings, + const Shader *vertexShader); + bool linkUniformBlocks(InfoLog &infoLog, const Caps &caps); + static bool linkVaryings(InfoLog &infoLog, + const Shader *vertexShader, + const Shader *fragmentShader); + bool linkUniforms(gl::InfoLog &infoLog, const gl::Caps &caps); + void indexUniforms(); bool areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock); @@ -235,31 +364,63 @@ class Program : angle::NonCopyable bool validatePrecision); static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); - bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, - const std::vector &transformFeedbackVaryingNames, - GLenum transformFeedbackBufferMode, - std::vector *outTransformFeedbackLinkedVaryings, - const Caps &caps) const; + bool linkValidateTransformFeedback(InfoLog &infoLog, + const std::vector &linkedVaryings, + const Caps &caps) const; + + void gatherTransformFeedbackVaryings(const std::vector &varyings); bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps); void defineOutputVariables(Shader *fragmentShader); - rx::ProgramImpl *mProgram; + std::vector getMergedVaryings() const; + void linkOutputVariables(); - sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; + bool flattenUniformsAndCheckCaps(const Caps &caps, InfoLog &infoLog); - std::map mOutputVariables; + struct VectorAndSamplerCount + { + VectorAndSamplerCount() : vectorCount(0), samplerCount(0) {} + VectorAndSamplerCount(const VectorAndSamplerCount &other) = default; + VectorAndSamplerCount &operator=(const VectorAndSamplerCount &other) = default; - bool mValidated; + VectorAndSamplerCount &operator+=(const VectorAndSamplerCount &other) + { + vectorCount += other.vectorCount; + samplerCount += other.samplerCount; + return *this; + } - Shader *mFragmentShader; - Shader *mVertexShader; + unsigned int vectorCount; + unsigned int samplerCount; + }; - AttributeBindings mAttributeBindings; + VectorAndSamplerCount flattenUniform(const sh::ShaderVariable &uniform, + const std::string &fullName, + std::vector *samplerUniforms); + + void gatherInterfaceBlockInfo(); + template + void defineUniformBlockMembers(const std::vector &fields, + const std::string &prefix, + int blockIndex); + + void defineUniformBlock(const sh::InterfaceBlock &interfaceBlock, GLenum shaderType); - GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + template + void setUniformInternal(GLint location, GLsizei count, const T *v); - std::vector mTransformFeedbackVaryings; - GLenum mTransformFeedbackBufferMode; + template + void setMatrixUniformInternal(GLint location, GLsizei count, GLboolean transpose, const T *v); + + template + void getUniformInternal(GLint location, DestT *dataOut) const; + + Data mData; + rx::ProgramImpl *mProgram; + + bool mValidated; + + AttributeBindings mAttributeBindings; bool mLinked; bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use @@ -270,6 +431,11 @@ class Program : angle::NonCopyable const GLuint mHandle; InfoLog mInfoLog; + + // Cache for sampler validation + Optional mCachedValidateSamplersResult; + std::vector mTextureUnitTypesCache; + RangeUI mSamplerUniformRange; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Query.cpp b/src/3rdparty/angle/src/libANGLE/Query.cpp index a402b732bf..cd1fb5f4bc 100644 --- a/src/3rdparty/angle/src/libANGLE/Query.cpp +++ b/src/3rdparty/angle/src/libANGLE/Query.cpp @@ -11,9 +11,7 @@ namespace gl { -Query::Query(rx::QueryImpl *impl, GLuint id) - : RefCountObject(id), - mQuery(impl) +Query::Query(rx::QueryImpl *impl, GLuint id) : RefCountObject(id), mQuery(impl), mLabel() { } @@ -22,6 +20,16 @@ Query::~Query() SafeDelete(mQuery); } +void Query::setLabel(const std::string &label) +{ + mLabel = label; +} + +const std::string &Query::getLabel() const +{ + return mLabel; +} + Error Query::begin() { return mQuery->begin(); @@ -32,12 +40,32 @@ Error Query::end() return mQuery->end(); } +Error Query::queryCounter() +{ + return mQuery->queryCounter(); +} + +Error Query::getResult(GLint *params) +{ + return mQuery->getResult(params); +} + Error Query::getResult(GLuint *params) { return mQuery->getResult(params); } -Error Query::isResultAvailable(GLuint *available) +Error Query::getResult(GLint64 *params) +{ + return mQuery->getResult(params); +} + +Error Query::getResult(GLuint64 *params) +{ + return mQuery->getResult(params); +} + +Error Query::isResultAvailable(bool *available) { return mQuery->isResultAvailable(available); } @@ -47,4 +75,13 @@ GLenum Query::getType() const return mQuery->getType(); } +rx::QueryImpl *Query::getImplementation() +{ + return mQuery; +} + +const rx::QueryImpl *Query::getImplementation() const +{ + return mQuery; +} } diff --git a/src/3rdparty/angle/src/libANGLE/Query.h b/src/3rdparty/angle/src/libANGLE/Query.h index 8585fde0e2..5486f983e7 100644 --- a/src/3rdparty/angle/src/libANGLE/Query.h +++ b/src/3rdparty/angle/src/libANGLE/Query.h @@ -9,6 +9,7 @@ #ifndef LIBANGLE_QUERY_H_ #define LIBANGLE_QUERY_H_ +#include "libANGLE/Debug.h" #include "libANGLE/Error.h" #include "libANGLE/RefCountObject.h" @@ -24,22 +25,33 @@ class QueryImpl; namespace gl { -class Query : public RefCountObject +class Query final : public RefCountObject, public LabeledObject { public: Query(rx::QueryImpl *impl, GLuint id); virtual ~Query(); + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + Error begin(); Error end(); - + Error queryCounter(); + Error getResult(GLint *params); Error getResult(GLuint *params); - Error isResultAvailable(GLuint *available); + Error getResult(GLint64 *params); + Error getResult(GLuint64 *params); + Error isResultAvailable(bool *available); GLenum getType() const; + rx::QueryImpl *getImplementation(); + const rx::QueryImpl *getImplementation() const; + private: rx::QueryImpl *mQuery; + + std::string mLabel; }; } diff --git a/src/3rdparty/angle/src/libANGLE/RefCountObject.h b/src/3rdparty/angle/src/libANGLE/RefCountObject.h index 48c0338c3f..86e6d788b5 100644 --- a/src/3rdparty/angle/src/libANGLE/RefCountObject.h +++ b/src/3rdparty/angle/src/libANGLE/RefCountObject.h @@ -21,14 +21,27 @@ class RefCountObject : angle::NonCopyable { public: - explicit RefCountObject(GLuint id); - virtual ~RefCountObject(); + explicit RefCountObject(GLuint id) : mId(id), mRefCount(0) {} - virtual void addRef() const; - virtual void release() const; + void addRef() const { ++mRefCount; } + + void release() const + { + ASSERT(mRefCount > 0); + + if (--mRefCount == 0) + { + delete this; + } + } GLuint id() const { return mId; } + size_t getRefCount() const { return mRefCount; } + + protected: + virtual ~RefCountObject() { ASSERT(mRefCount == 0); } + private: GLuint mId; @@ -38,7 +51,7 @@ class RefCountObject : angle::NonCopyable template class BindingPointer { -public: + public: BindingPointer() : mObject(nullptr) { @@ -73,7 +86,13 @@ public: ObjectType *operator->() const { return mObject; } GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; } - bool operator!() const { return (mObject == nullptr); } + + bool operator==(const BindingPointer &other) const + { + return mObject == other.mObject; + } + + bool operator!=(const BindingPointer &other) const { return !(*this == other); } private: ObjectType *mObject; @@ -102,6 +121,16 @@ class OffsetBindingPointer : public BindingPointer GLintptr getOffset() const { return mOffset; } GLsizeiptr getSize() const { return mSize; } + bool operator==(const OffsetBindingPointer &other) const + { + return this->get() == other.get() && mOffset == other.mOffset && mSize == other.mSize; + } + + bool operator!=(const OffsetBindingPointer &other) const + { + return !(*this == other); + } + private: GLintptr mOffset; GLsizeiptr mSize; diff --git a/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp index 6a0cde812b..161fbea797 100644 --- a/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp @@ -12,20 +12,21 @@ #include "common/utilities.h" #include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Image.h" #include "libANGLE/Texture.h" #include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/RenderTargetD3D.h" -#include "libANGLE/renderer/RenderbufferImpl.h" namespace gl { Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id) - : RefCountObject(id), - mRenderbuffer(impl), - mWidth(0), - mHeight(0), - mInternalFormat(GL_RGBA4), - mSamples(0) + : egl::ImageSibling(id), + mRenderbuffer(impl), + mLabel(), + mWidth(0), + mHeight(0), + mInternalFormat(GL_RGBA4), + mSamples(0) { } @@ -34,16 +35,28 @@ Renderbuffer::~Renderbuffer() SafeDelete(mRenderbuffer); } +void Renderbuffer::setLabel(const std::string &label) +{ + mLabel = label; +} + +const std::string &Renderbuffer::getLabel() const +{ + return mLabel; +} + Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t height) { + orphanImages(); + Error error = mRenderbuffer->setStorage(internalformat, width, height); if (error.isError()) { return error; } - mWidth = width; - mHeight = height; + mWidth = static_cast(width); + mHeight = static_cast(height); mInternalFormat = internalformat; mSamples = 0; @@ -52,16 +65,38 @@ Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t heigh Error Renderbuffer::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) { + orphanImages(); + Error error = mRenderbuffer->setStorageMultisample(samples, internalformat, width, height); if (error.isError()) { return error; } - mWidth = width; - mHeight = height; + mWidth = static_cast(width); + mHeight = static_cast(height); mInternalFormat = internalformat; - mSamples = samples; + mSamples = static_cast(samples); + + return Error(GL_NO_ERROR); +} + +Error Renderbuffer::setStorageEGLImageTarget(egl::Image *image) +{ + orphanImages(); + + Error error = mRenderbuffer->setStorageEGLImageTarget(image); + if (error.isError()) + { + return error; + } + + setTargetImage(image); + + mWidth = static_cast(image->getWidth()); + mHeight = static_cast(image->getHeight()); + mInternalFormat = image->getInternalFormat(); + mSamples = 0; return Error(GL_NO_ERROR); } @@ -127,4 +162,23 @@ GLuint Renderbuffer::getStencilSize() const return GetInternalFormatInfo(mInternalFormat).stencilBits; } +void Renderbuffer::onAttach() +{ + addRef(); +} + +void Renderbuffer::onDetach() +{ + release(); +} + +GLuint Renderbuffer::getId() const +{ + return id(); +} + +Extents Renderbuffer::getAttachmentSize(const FramebufferAttachment::Target & /*target*/) const +{ + return Extents(mWidth, mHeight, 1); +} } diff --git a/src/3rdparty/angle/src/libANGLE/Renderbuffer.h b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h index 98c7eb0f10..04af03e879 100644 --- a/src/3rdparty/angle/src/libANGLE/Renderbuffer.h +++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h @@ -12,34 +12,34 @@ #define LIBANGLE_RENDERBUFFER_H_ #include "angle_gl.h" - -#include "libANGLE/Error.h" -#include "libANGLE/RefCountObject.h" - #include "common/angleutils.h" - -namespace rx -{ -class RenderbufferImpl; -} +#include "libANGLE/Debug.h" +#include "libANGLE/Error.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Image.h" +#include "libANGLE/renderer/RenderbufferImpl.h" namespace gl { -class FramebufferAttachment; - // A GL renderbuffer object is usually used as a depth or stencil buffer attachment // for a framebuffer object. The renderbuffer itself is a distinct GL object, see // FramebufferAttachment and Framebuffer for how they are applied to an FBO via an // attachment point. -class Renderbuffer : public RefCountObject +class Renderbuffer final : public egl::ImageSibling, + public gl::FramebufferAttachmentObject, + public LabeledObject { public: Renderbuffer(rx::RenderbufferImpl *impl, GLuint id); virtual ~Renderbuffer(); + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + Error setStorage(GLenum internalformat, size_t width, size_t height); Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height); + Error setStorageEGLImageTarget(egl::Image *imageTarget); rx::RenderbufferImpl *getImplementation(); const rx::RenderbufferImpl *getImplementation() const; @@ -55,9 +55,22 @@ class Renderbuffer : public RefCountObject GLuint getDepthSize() const; GLuint getStencilSize() const; + // FramebufferAttachmentObject Impl + Extents getAttachmentSize(const FramebufferAttachment::Target &target) const override; + GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &/*target*/) const override { return getInternalFormat(); } + GLsizei getAttachmentSamples(const FramebufferAttachment::Target &/*target*/) const override { return getSamples(); } + + void onAttach() override; + void onDetach() override; + GLuint getId() const override; + private: + rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mRenderbuffer; } + rx::RenderbufferImpl *mRenderbuffer; + std::string mLabel; + GLsizei mWidth; GLsizei mHeight; GLenum mInternalFormat; diff --git a/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp index aaf144cfa9..dc9dad1e9f 100644 --- a/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp @@ -88,13 +88,13 @@ GLuint ResourceManager::createBuffer() } // Returns an unused shader/program name -GLuint ResourceManager::createShader(const gl::Data &data, GLenum type) +GLuint ResourceManager::createShader(const gl::Limitations &rendererLimitations, GLenum type) { GLuint handle = mProgramShaderHandleAllocator.allocate(); if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) { - mShaderMap[handle] = new Shader(this, mFactory->createShader(type), type, handle); + mShaderMap[handle] = new Shader(this, mFactory, rendererLimitations, type, handle); } else UNREACHABLE(); @@ -106,7 +106,7 @@ GLuint ResourceManager::createProgram() { GLuint handle = mProgramShaderHandleAllocator.allocate(); - mProgramMap[handle] = new Program(mFactory->createProgram(), this, handle); + mProgramMap[handle] = new Program(mFactory, this, handle); return handle; } @@ -441,7 +441,7 @@ void ResourceManager::checkSamplerAllocation(GLuint sampler) { if (sampler != 0 && !getSampler(sampler)) { - Sampler *samplerObject = new Sampler(sampler); + Sampler *samplerObject = new Sampler(mFactory, sampler); mSamplerMap[sampler] = samplerObject; samplerObject->addRef(); // Samplers cannot be created via Bind diff --git a/src/3rdparty/angle/src/libANGLE/ResourceManager.h b/src/3rdparty/angle/src/libANGLE/ResourceManager.h index 8e95e8840a..2073e9d728 100644 --- a/src/3rdparty/angle/src/libANGLE/ResourceManager.h +++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.h @@ -25,13 +25,14 @@ class ImplFactory; namespace gl { class Buffer; -class Shader; +struct Data; +class FenceSync; +struct Limitations; class Program; -class Texture; class Renderbuffer; class Sampler; -class FenceSync; -struct Data; +class Shader; +class Texture; class ResourceManager : angle::NonCopyable { @@ -43,7 +44,7 @@ class ResourceManager : angle::NonCopyable void release(); GLuint createBuffer(); - GLuint createShader(const gl::Data &data, GLenum type); + GLuint createShader(const gl::Limitations &rendererLimitations, GLenum type); GLuint createProgram(); GLuint createTexture(); GLuint createRenderbuffer(); diff --git a/src/3rdparty/angle/src/libANGLE/Sampler.cpp b/src/3rdparty/angle/src/libANGLE/Sampler.cpp index d58bd5a862..d8d606a46f 100644 --- a/src/3rdparty/angle/src/libANGLE/Sampler.cpp +++ b/src/3rdparty/angle/src/libANGLE/Sampler.cpp @@ -9,35 +9,144 @@ #include "libANGLE/Sampler.h" #include "libANGLE/angletypes.h" +#include "libANGLE/renderer/ImplFactory.h" +#include "libANGLE/renderer/SamplerImpl.h" namespace gl { -Sampler::Sampler(GLuint id) - : RefCountObject(id), - mMinFilter(GL_NEAREST_MIPMAP_LINEAR), - mMagFilter(GL_LINEAR), - mWrapS(GL_REPEAT), - mWrapT(GL_REPEAT), - mWrapR(GL_REPEAT), - mMinLod(-1000.0f), - mMaxLod(1000.0f), - mComparisonMode(GL_NONE), - mComparisonFunc(GL_LEQUAL) +Sampler::Sampler(rx::ImplFactory *factory, GLuint id) + : RefCountObject(id), mImpl(factory->createSampler()), mLabel(), mSamplerState() { } -void Sampler::getState(SamplerState *samplerState) const +Sampler::~Sampler() { - samplerState->minFilter = mMinFilter; - samplerState->magFilter = mMagFilter; - samplerState->wrapS = mWrapS; - samplerState->wrapT = mWrapT; - samplerState->wrapR = mWrapR; - samplerState->minLod = mMinLod; - samplerState->maxLod = mMaxLod; - samplerState->compareMode = mComparisonMode; - samplerState->compareFunc = mComparisonFunc; + SafeDelete(mImpl); } +void Sampler::setLabel(const std::string &label) +{ + mLabel = label; +} + +const std::string &Sampler::getLabel() const +{ + return mLabel; +} + +void Sampler::setMinFilter(GLenum minFilter) +{ + mSamplerState.minFilter = minFilter; +} + +GLenum Sampler::getMinFilter() const +{ + return mSamplerState.minFilter; +} + +void Sampler::setMagFilter(GLenum magFilter) +{ + mSamplerState.magFilter = magFilter; +} + +GLenum Sampler::getMagFilter() const +{ + return mSamplerState.magFilter; +} + +void Sampler::setWrapS(GLenum wrapS) +{ + mSamplerState.wrapS = wrapS; +} + +GLenum Sampler::getWrapS() const +{ + return mSamplerState.wrapS; +} + +void Sampler::setWrapT(GLenum wrapT) +{ + mSamplerState.wrapT = wrapT; +} + +GLenum Sampler::getWrapT() const +{ + return mSamplerState.wrapT; +} + +void Sampler::setWrapR(GLenum wrapR) +{ + mSamplerState.wrapR = wrapR; +} + +GLenum Sampler::getWrapR() const +{ + return mSamplerState.wrapR; +} + +void Sampler::setMaxAnisotropy(float maxAnisotropy) +{ + mSamplerState.maxAnisotropy = maxAnisotropy; +} + +float Sampler::getMaxAnisotropy() const +{ + return mSamplerState.maxAnisotropy; +} + +void Sampler::setMinLod(GLfloat minLod) +{ + mSamplerState.minLod = minLod; +} + +GLfloat Sampler::getMinLod() const +{ + return mSamplerState.minLod; +} + +void Sampler::setMaxLod(GLfloat maxLod) +{ + mSamplerState.maxLod = maxLod; +} + +GLfloat Sampler::getMaxLod() const +{ + return mSamplerState.maxLod; +} + +void Sampler::setCompareMode(GLenum compareMode) +{ + mSamplerState.compareMode = compareMode; +} + +GLenum Sampler::getCompareMode() const +{ + return mSamplerState.compareMode; +} + +void Sampler::setCompareFunc(GLenum compareFunc) +{ + mSamplerState.compareFunc = compareFunc; +} + +GLenum Sampler::getCompareFunc() const +{ + return mSamplerState.compareFunc; +} + +const SamplerState &Sampler::getSamplerState() const +{ + return mSamplerState; +} + +const rx::SamplerImpl *Sampler::getImplementation() const +{ + return mImpl; +} + +rx::SamplerImpl *Sampler::getImplementation() +{ + return mImpl; +} } diff --git a/src/3rdparty/angle/src/libANGLE/Sampler.h b/src/3rdparty/angle/src/libANGLE/Sampler.h index d33798ff15..a40b1655fc 100644 --- a/src/3rdparty/angle/src/libANGLE/Sampler.h +++ b/src/3rdparty/angle/src/libANGLE/Sampler.h @@ -10,49 +10,69 @@ #ifndef LIBANGLE_SAMPLER_H_ #define LIBANGLE_SAMPLER_H_ +#include "libANGLE/angletypes.h" +#include "libANGLE/Debug.h" #include "libANGLE/RefCountObject.h" +namespace rx +{ +class ImplFactory; +class SamplerImpl; +} + namespace gl { -struct SamplerState; -class Sampler : public RefCountObject +class Sampler final : public RefCountObject, public LabeledObject { public: - Sampler(GLuint id); - - void setMinFilter(GLenum minFilter) { mMinFilter = minFilter; } - void setMagFilter(GLenum magFilter) { mMagFilter = magFilter; } - void setWrapS(GLenum wrapS) { mWrapS = wrapS; } - void setWrapT(GLenum wrapT) { mWrapT = wrapT; } - void setWrapR(GLenum wrapR) { mWrapR = wrapR; } - void setMinLod(GLfloat minLod) { mMinLod = minLod; } - void setMaxLod(GLfloat maxLod) { mMaxLod = maxLod; } - void setComparisonMode(GLenum comparisonMode) { mComparisonMode = comparisonMode; } - void setComparisonFunc(GLenum comparisonFunc) { mComparisonFunc = comparisonFunc; } - - GLenum getMinFilter() const { return mMinFilter; } - GLenum getMagFilter() const { return mMagFilter; } - GLenum getWrapS() const { return mWrapS; } - GLenum getWrapT() const { return mWrapT; } - GLenum getWrapR() const { return mWrapR; } - GLfloat getMinLod() const { return mMinLod; } - GLfloat getMaxLod() const { return mMaxLod; } - GLenum getComparisonMode() const { return mComparisonMode; } - GLenum getComparisonFunc() const { return mComparisonFunc; } - - void getState(SamplerState *samplerState) const; + Sampler(rx::ImplFactory *factory, GLuint id); + ~Sampler() override; + + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + + void setMinFilter(GLenum minFilter); + GLenum getMinFilter() const; + + void setMagFilter(GLenum magFilter); + GLenum getMagFilter() const; + + void setWrapS(GLenum wrapS); + GLenum getWrapS() const; + + void setWrapT(GLenum wrapT); + GLenum getWrapT() const; + + void setWrapR(GLenum wrapR); + GLenum getWrapR() const; + + void setMaxAnisotropy(float maxAnisotropy); + float getMaxAnisotropy() const; + + void setMinLod(GLfloat minLod); + GLfloat getMinLod() const; + + void setMaxLod(GLfloat maxLod); + GLfloat getMaxLod() const; + + void setCompareMode(GLenum compareMode); + GLenum getCompareMode() const; + + void setCompareFunc(GLenum compareFunc); + GLenum getCompareFunc() const; + + const SamplerState &getSamplerState() const; + + const rx::SamplerImpl *getImplementation() const; + rx::SamplerImpl *getImplementation(); private: - GLenum mMinFilter; - GLenum mMagFilter; - GLenum mWrapS; - GLenum mWrapT; - GLenum mWrapR; - GLfloat mMinLod; - GLfloat mMaxLod; - GLenum mComparisonMode; - GLenum mComparisonFunc; + rx::SamplerImpl *mImpl; + + std::string mLabel; + + SamplerState mSamplerState; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Shader.cpp b/src/3rdparty/angle/src/libANGLE/Shader.cpp index 7af4ff358d..bbe9077fc9 100644 --- a/src/3rdparty/angle/src/libANGLE/Shader.cpp +++ b/src/3rdparty/angle/src/libANGLE/Shader.cpp @@ -9,35 +9,108 @@ // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. #include "libANGLE/Shader.h" + +#include + +#include "common/utilities.h" +#include "GLSLANG/ShaderLang.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/Constants.h" #include "libANGLE/renderer/Renderer.h" #include "libANGLE/renderer/ShaderImpl.h" -#include "libANGLE/Constants.h" #include "libANGLE/ResourceManager.h" -#include "common/utilities.h" +namespace gl +{ -#include "GLSLANG/ShaderLang.h" +namespace +{ +template +std::vector GetActiveShaderVariables(const std::vector *variableList) +{ + ASSERT(variableList); + std::vector result; + for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++) + { + const VarT &var = variableList->at(varIndex); + if (var.staticUse) + { + result.push_back(var); + } + } + return result; +} -#include +template +const std::vector &GetShaderVariables(const std::vector *variableList) +{ + ASSERT(variableList); + return *variableList; +} -namespace gl +} // anonymous namespace + +// true if varying x has a higher priority in packing than y +bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y) { + if (x.type == y.type) + { + return x.arraySize > y.arraySize; + } -Shader::Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle) - : mShader(impl), - mType(type), + // Special case for handling structs: we sort these to the end of the list + if (x.type == GL_STRUCT_ANGLEX) + { + return false; + } + + if (y.type == GL_STRUCT_ANGLEX) + { + return true; + } + + return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type); +} + +Shader::Data::Data(GLenum shaderType) : mLabel(), mShaderType(shaderType), mShaderVersion(100) +{ +} + +Shader::Data::~Data() +{ +} + +Shader::Shader(ResourceManager *manager, + rx::ImplFactory *implFactory, + const gl::Limitations &rendererLimitations, + GLenum type, + GLuint handle) + : mData(type), + mImplementation(implFactory->createShader(mData)), + mRendererLimitations(rendererLimitations), mHandle(handle), - mResourceManager(manager), + mType(type), mRefCount(0), mDeleteStatus(false), - mCompiled(false) + mCompiled(false), + mResourceManager(manager) { - ASSERT(impl); + ASSERT(mImplementation); } Shader::~Shader() { - SafeDelete(mShader); + SafeDelete(mImplementation); +} + +void Shader::setLabel(const std::string &label) +{ + mData.mLabel = label; +} + +const std::string &Shader::getLabel() const +{ + return mData.mLabel; } GLuint Shader::getHandle() const @@ -61,12 +134,17 @@ void Shader::setSource(GLsizei count, const char *const *string, const GLint *le } } - mSource = stream.str(); + mData.mSource = stream.str(); } int Shader::getInfoLogLength() const { - return mShader->getInfoLog().empty() ? 0 : (mShader->getInfoLog().length() + 1); + if (mInfoLog.empty()) + { + return 0; + } + + return (static_cast(mInfoLog.length()) + 1); } void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const @@ -75,8 +153,8 @@ void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const if (bufSize > 0) { - index = std::min(bufSize - 1, static_cast(mShader->getInfoLog().length())); - memcpy(infoLog, mShader->getInfoLog().c_str(), index); + index = std::min(bufSize - 1, static_cast(mInfoLog.length())); + memcpy(infoLog, mInfoLog.c_str(), index); infoLog[index] = '\0'; } @@ -89,12 +167,28 @@ void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const int Shader::getSourceLength() const { - return mSource.empty() ? 0 : (mSource.length() + 1); + return mData.mSource.empty() ? 0 : (static_cast(mData.mSource.length()) + 1); } int Shader::getTranslatedSourceLength() const { - return mShader->getTranslatedSource().empty() ? 0 : (mShader->getTranslatedSource().length() + 1); + if (mData.mTranslatedSource.empty()) + { + return 0; + } + + return (static_cast(mData.mTranslatedSource.length()) + 1); +} + +int Shader::getTranslatedSourceWithDebugInfoLength() const +{ + const std::string &debugInfo = mImplementation->getDebugInfo(); + if (debugInfo.empty()) + { + return 0; + } + + return (static_cast(debugInfo.length()) + 1); } void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) @@ -117,23 +211,117 @@ void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei * void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const { - getSourceImpl(mSource, bufSize, length, buffer); + getSourceImpl(mData.mSource, bufSize, length, buffer); } void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const { - getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer); + getSourceImpl(mData.mTranslatedSource, bufSize, length, buffer); } void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const { - std::string debugInfo(mShader->getDebugInfo()); + const std::string &debugInfo = mImplementation->getDebugInfo(); getSourceImpl(debugInfo, bufSize, length, buffer); } void Shader::compile(Compiler *compiler) { - mCompiled = mShader->compile(compiler, mSource); + mData.mTranslatedSource.clear(); + mInfoLog.clear(); + mData.mShaderVersion = 100; + mData.mVaryings.clear(); + mData.mUniforms.clear(); + mData.mInterfaceBlocks.clear(); + mData.mActiveAttributes.clear(); + mData.mActiveOutputVariables.clear(); + + ShHandle compilerHandle = compiler->getCompilerHandle(mData.mShaderType); + + std::stringstream sourceStream; + + std::string sourcePath; + int additionalOptions = + mImplementation->prepareSourceAndReturnOptions(&sourceStream, &sourcePath); + int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES | additionalOptions); + + // Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop indexes + // in fragment shaders. Shader compilation will fail. To provide a better error message we can + // instruct the compiler to pre-validate. + if (mRendererLimitations.shadersRequireIndexedLoopValidation) + { + compileOptions |= SH_VALIDATE_LOOP_INDEXING; + } + + std::string sourceString = sourceStream.str(); + std::vector sourceCStrings; + + if (!sourcePath.empty()) + { + sourceCStrings.push_back(sourcePath.c_str()); + } + + sourceCStrings.push_back(sourceString.c_str()); + + bool result = + ShCompile(compilerHandle, &sourceCStrings[0], sourceCStrings.size(), compileOptions); + + if (!result) + { + mInfoLog = ShGetInfoLog(compilerHandle); + TRACE("\n%s", mInfoLog.c_str()); + mCompiled = false; + return; + } + + mData.mTranslatedSource = ShGetObjectCode(compilerHandle); + +#ifndef NDEBUG + // Prefix translated shader with commented out un-translated shader. + // Useful in diagnostics tools which capture the shader source. + std::ostringstream shaderStream; + shaderStream << "// GLSL\n"; + shaderStream << "//\n"; + + size_t curPos = 0; + while (curPos != std::string::npos) + { + size_t nextLine = mData.mSource.find("\n", curPos); + size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); + + shaderStream << "// " << mData.mSource.substr(curPos, len); + + curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); + } + shaderStream << "\n\n"; + shaderStream << mData.mTranslatedSource; + mData.mTranslatedSource = shaderStream.str(); +#endif + + // Gather the shader information + mData.mShaderVersion = ShGetShaderVersion(compilerHandle); + + mData.mVaryings = GetShaderVariables(ShGetVaryings(compilerHandle)); + mData.mUniforms = GetShaderVariables(ShGetUniforms(compilerHandle)); + mData.mInterfaceBlocks = GetShaderVariables(ShGetInterfaceBlocks(compilerHandle)); + + if (mData.mShaderType == GL_VERTEX_SHADER) + { + mData.mActiveAttributes = GetActiveShaderVariables(ShGetAttributes(compilerHandle)); + } + else + { + ASSERT(mData.mShaderType == GL_FRAGMENT_SHADER); + + // TODO(jmadill): Figure out why we only sort in the FS, and if we need to. + std::sort(mData.mVaryings.begin(), mData.mVaryings.end(), CompareShaderVar); + mData.mActiveOutputVariables = + GetActiveShaderVariables(ShGetOutputVariables(compilerHandle)); + } + + ASSERT(!mData.mTranslatedSource.empty()); + + mCompiled = mImplementation->postTranslateCompile(compiler, &mInfoLog); } void Shader::addRef() @@ -166,62 +354,41 @@ void Shader::flagForDeletion() mDeleteStatus = true; } -const std::vector &Shader::getVaryings() const -{ - return mShader->getVaryings(); -} - -const std::vector &Shader::getUniforms() const -{ - return mShader->getUniforms(); -} - -const std::vector &Shader::getInterfaceBlocks() const +int Shader::getShaderVersion() const { - return mShader->getInterfaceBlocks(); + return mData.mShaderVersion; } -const std::vector &Shader::getActiveAttributes() const +const std::vector &Shader::getVaryings() const { - return mShader->getActiveAttributes(); + return mData.getVaryings(); } -const std::vector &Shader::getActiveOutputVariables() const -{ - return mShader->getActiveOutputVariables(); -} - -std::vector &Shader::getVaryings() -{ - return mShader->getVaryings(); -} - -std::vector &Shader::getUniforms() +const std::vector &Shader::getUniforms() const { - return mShader->getUniforms(); + return mData.getUniforms(); } -std::vector &Shader::getInterfaceBlocks() +const std::vector &Shader::getInterfaceBlocks() const { - return mShader->getInterfaceBlocks(); + return mData.getInterfaceBlocks(); } -std::vector &Shader::getActiveAttributes() +const std::vector &Shader::getActiveAttributes() const { - return mShader->getActiveAttributes(); + return mData.getActiveAttributes(); } -std::vector &Shader::getActiveOutputVariables() +const std::vector &Shader::getActiveOutputVariables() const { - return mShader->getActiveOutputVariables(); + return mData.getActiveOutputVariables(); } - int Shader::getSemanticIndex(const std::string &attributeName) const { if (!attributeName.empty()) { - const auto &activeAttributes = mShader->getActiveAttributes(); + const auto &activeAttributes = mData.getActiveAttributes(); int semanticIndex = 0; for (size_t attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) diff --git a/src/3rdparty/angle/src/libANGLE/Shader.h b/src/3rdparty/angle/src/libANGLE/Shader.h index 10e79c7499..997977c87b 100644 --- a/src/3rdparty/angle/src/libANGLE/Shader.h +++ b/src/3rdparty/angle/src/libANGLE/Shader.h @@ -21,50 +21,83 @@ #include "common/angleutils.h" #include "libANGLE/angletypes.h" +#include "libANGLE/Debug.h" namespace rx { +class ImplFactory; class ShaderImpl; +class ShaderSh; } namespace gl { class Compiler; +struct Limitations; class ResourceManager; struct Data; -struct PackedVarying : public sh::Varying -{ - unsigned int registerIndex; // Assigned during link - unsigned int columnIndex; // Assigned during link, defaults to 0 - - PackedVarying(const sh::Varying &varying) - : sh::Varying(varying), - registerIndex(GL_INVALID_INDEX), - columnIndex(0) - {} - - bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; } - bool isBuiltIn() const { return name.compare(0, 3, "gl_") == 0; } - - void resetRegisterAssignment() - { - registerIndex = GL_INVALID_INDEX; - } -}; - -class Shader : angle::NonCopyable +class Shader final : angle::NonCopyable, public LabeledObject { public: - Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle); + class Data final : angle::NonCopyable + { + public: + Data(GLenum shaderType); + ~Data(); + + const std::string &getLabel() const { return mLabel; } + + const std::string &getSource() const { return mSource; } + const std::string &getTranslatedSource() const { return mTranslatedSource; } + + GLenum getShaderType() const { return mShaderType; } + int getShaderVersion() const { return mShaderVersion; } + + const std::vector &getVaryings() const { return mVaryings; } + const std::vector &getUniforms() const { return mUniforms; } + const std::vector &getInterfaceBlocks() const + { + return mInterfaceBlocks; + } + const std::vector &getActiveAttributes() const { return mActiveAttributes; } + const std::vector &getActiveOutputVariables() const + { + return mActiveOutputVariables; + } + + private: + friend class Shader; + + std::string mLabel; + + GLenum mShaderType; + int mShaderVersion; + std::string mTranslatedSource; + std::string mSource; + + std::vector mVaryings; + std::vector mUniforms; + std::vector mInterfaceBlocks; + std::vector mActiveAttributes; + std::vector mActiveOutputVariables; + }; + + Shader(ResourceManager *manager, + rx::ImplFactory *implFactory, + const gl::Limitations &rendererLimitations, + GLenum type, + GLuint handle); virtual ~Shader(); + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + GLenum getType() const { return mType; } GLuint getHandle() const; - rx::ShaderImpl *getImplementation() { return mShader; } - const rx::ShaderImpl *getImplementation() const { return mShader; } + const rx::ShaderImpl *getImplementation() const { return mImplementation; } void deleteSource(); void setSource(GLsizei count, const char *const *string, const GLint *length); @@ -73,6 +106,8 @@ class Shader : angle::NonCopyable int getSourceLength() const; void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const; int getTranslatedSourceLength() const; + int getTranslatedSourceWithDebugInfoLength() const; + const std::string &getTranslatedSource() const { return mData.getTranslatedSource(); } void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const; void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const; @@ -85,34 +120,33 @@ class Shader : angle::NonCopyable bool isFlaggedForDeletion() const; void flagForDeletion(); - const std::vector &getVaryings() const; + int getShaderVersion() const; + + const std::vector &getVaryings() const; const std::vector &getUniforms() const; const std::vector &getInterfaceBlocks() const; const std::vector &getActiveAttributes() const; - const std::vector &getActiveOutputVariables() const; - - std::vector &getVaryings(); - std::vector &getUniforms(); - std::vector &getInterfaceBlocks(); - std::vector &getActiveAttributes(); - std::vector &getActiveOutputVariables(); + const std::vector &getActiveOutputVariables() const; int getSemanticIndex(const std::string &attributeName) const; private: static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer); - rx::ShaderImpl *mShader; + Data mData; + rx::ShaderImpl *mImplementation; + const gl::Limitations &mRendererLimitations; const GLuint mHandle; const GLenum mType; - std::string mSource; unsigned int mRefCount; // Number of program objects this shader is attached to bool mDeleteStatus; // Flag to indicate that the shader can be deleted when no longer in use bool mCompiled; // Indicates if this shader has been successfully compiled + std::string mInfoLog; ResourceManager *mResourceManager; }; +bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y); } #endif // LIBANGLE_SHADER_H_ diff --git a/src/3rdparty/angle/src/libANGLE/State.cpp b/src/3rdparty/angle/src/libANGLE/State.cpp index 4c044d2950..a1437b838b 100644 --- a/src/3rdparty/angle/src/libANGLE/State.cpp +++ b/src/3rdparty/angle/src/libANGLE/State.cpp @@ -8,8 +8,10 @@ #include "libANGLE/State.h" +#include "common/BitSetIterator.h" #include "libANGLE/Context.h" #include "libANGLE/Caps.h" +#include "libANGLE/Debug.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/Query.h" @@ -20,9 +22,57 @@ namespace gl { State::State() -{ - mMaxDrawBuffers = 0; - mMaxCombinedTextureImageUnits = 0; + : mMaxDrawBuffers(0), + mMaxCombinedTextureImageUnits(0), + mDepthClearValue(0), + mStencilClearValue(0), + mScissorTest(false), + mSampleCoverage(false), + mSampleCoverageValue(0), + mSampleCoverageInvert(false), + mStencilRef(0), + mStencilBackRef(0), + mLineWidth(0), + mGenerateMipmapHint(GL_NONE), + mFragmentShaderDerivativeHint(GL_NONE), + mNearZ(0), + mFarZ(0), + mReadFramebuffer(nullptr), + mDrawFramebuffer(nullptr), + mProgram(nullptr), + mVertexArray(nullptr), + mActiveSampler(0), + mPrimitiveRestart(false) +{ + // Initialize dirty bit masks + // TODO(jmadill): additional ES3 state + mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ALIGNMENT); + mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ROW_LENGTH); + mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT); + mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_IMAGES); + mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_ROWS); + mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_PIXELS); + + mPackStateBitMask.set(DIRTY_BIT_PACK_ALIGNMENT); + mPackStateBitMask.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER); + mPackStateBitMask.set(DIRTY_BIT_PACK_ROW_LENGTH); + mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_ROWS); + mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_PIXELS); + + mClearStateBitMask.set(DIRTY_BIT_RASTERIZER_DISCARD_ENABLED); + mClearStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED); + mClearStateBitMask.set(DIRTY_BIT_SCISSOR); + mClearStateBitMask.set(DIRTY_BIT_VIEWPORT); + mClearStateBitMask.set(DIRTY_BIT_CLEAR_COLOR); + mClearStateBitMask.set(DIRTY_BIT_CLEAR_DEPTH); + mClearStateBitMask.set(DIRTY_BIT_CLEAR_STENCIL); + mClearStateBitMask.set(DIRTY_BIT_COLOR_MASK); + mClearStateBitMask.set(DIRTY_BIT_DEPTH_MASK); + mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + + mBlitStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED); + mBlitStateBitMask.set(DIRTY_BIT_SCISSOR); } State::~State() @@ -30,7 +80,10 @@ State::~State() reset(); } -void State::initialize(const Caps& caps, GLuint clientVersion) +void State::initialize(const Caps &caps, + const Extensions &extensions, + GLuint clientVersion, + bool debug) { mMaxDrawBuffers = caps.maxDrawBuffers; mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; @@ -112,15 +165,9 @@ void State::initialize(const Caps& caps, GLuint clientVersion) mActiveSampler = 0; - const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; mVertexAttribCurrentValues.resize(caps.maxVertexAttributes); - for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); ++attribIndex) - { - mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); - } mUniformBuffers.resize(caps.maxCombinedUniformBlocks); - mTransformFeedbackBuffers.resize(caps.maxTransformFeedbackSeparateAttributes); mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits); mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits); @@ -133,16 +180,20 @@ void State::initialize(const Caps& caps, GLuint clientVersion) mSamplers.resize(caps.maxCombinedTextureImageUnits); - mActiveQueries[GL_ANY_SAMPLES_PASSED].set(NULL); - mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL); - mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL); + mActiveQueries[GL_ANY_SAMPLES_PASSED].set(nullptr); + mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(nullptr); + mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(nullptr); + mActiveQueries[GL_TIME_ELAPSED_EXT].set(nullptr); - mProgram = NULL; + mProgram = nullptr; - mReadFramebuffer = NULL; - mDrawFramebuffer = NULL; + mReadFramebuffer = nullptr; + mDrawFramebuffer = nullptr; mPrimitiveRestart = false; + + mDebug.setOutputEnabled(debug); + mDebug.setMaxLoggedMessages(extensions.maxDebugLoggedMessages); } void State::reset() @@ -177,17 +228,11 @@ void State::reset() } mGenericUniformBuffer.set(NULL); - mGenericTransformFeedbackBuffer.set(NULL); for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr) { bufItr->set(NULL); } - for (BufferVector::iterator bufItr = mTransformFeedbackBuffers.begin(); bufItr != mTransformFeedbackBuffers.end(); ++bufItr) - { - bufItr->set(NULL); - } - mCopyReadBuffer.set(NULL); mCopyWriteBuffer.set(NULL); @@ -195,6 +240,9 @@ void State::reset() mUnpack.pixelBuffer.set(NULL); mProgram = NULL; + + // TODO(jmadill): Is this necessary? + setAllDirtyBits(); } const RasterizerState &State::getRasterizerState() const @@ -218,16 +266,19 @@ void State::setColorClearValue(float red, float green, float blue, float alpha) mColorClearValue.green = green; mColorClearValue.blue = blue; mColorClearValue.alpha = alpha; + mDirtyBits.set(DIRTY_BIT_CLEAR_COLOR); } void State::setDepthClearValue(float depth) { mDepthClearValue = depth; + mDirtyBits.set(DIRTY_BIT_CLEAR_DEPTH); } void State::setStencilClearValue(int stencil) { mStencilClearValue = stencil; + mDirtyBits.set(DIRTY_BIT_CLEAR_STENCIL); } void State::setColorMask(bool red, bool green, bool blue, bool alpha) @@ -236,11 +287,13 @@ void State::setColorMask(bool red, bool green, bool blue, bool alpha) mBlend.colorMaskGreen = green; mBlend.colorMaskBlue = blue; mBlend.colorMaskAlpha = alpha; + mDirtyBits.set(DIRTY_BIT_COLOR_MASK); } void State::setDepthMask(bool mask) { mDepthStencil.depthMask = mask; + mDirtyBits.set(DIRTY_BIT_DEPTH_MASK); } bool State::isRasterizerDiscardEnabled() const @@ -251,6 +304,7 @@ bool State::isRasterizerDiscardEnabled() const void State::setRasterizerDiscard(bool enabled) { mRasterizer.rasterizerDiscard = enabled; + mDirtyBits.set(DIRTY_BIT_RASTERIZER_DISCARD_ENABLED); } bool State::isCullFaceEnabled() const @@ -261,16 +315,19 @@ bool State::isCullFaceEnabled() const void State::setCullFace(bool enabled) { mRasterizer.cullFace = enabled; + mDirtyBits.set(DIRTY_BIT_CULL_FACE_ENABLED); } void State::setCullMode(GLenum mode) { mRasterizer.cullMode = mode; + mDirtyBits.set(DIRTY_BIT_CULL_FACE); } void State::setFrontFace(GLenum front) { mRasterizer.frontFace = front; + mDirtyBits.set(DIRTY_BIT_FRONT_FACE); } bool State::isDepthTestEnabled() const @@ -281,23 +338,30 @@ bool State::isDepthTestEnabled() const void State::setDepthTest(bool enabled) { mDepthStencil.depthTest = enabled; + mDirtyBits.set(DIRTY_BIT_DEPTH_TEST_ENABLED); } void State::setDepthFunc(GLenum depthFunc) { mDepthStencil.depthFunc = depthFunc; + mDirtyBits.set(DIRTY_BIT_DEPTH_FUNC); } void State::setDepthRange(float zNear, float zFar) { mNearZ = zNear; mFarZ = zFar; + mDirtyBits.set(DIRTY_BIT_DEPTH_RANGE); +} + +float State::getNearPlane() const +{ + return mNearZ; } -void State::getDepthRange(float *zNear, float *zFar) const +float State::getFarPlane() const { - *zNear = mNearZ; - *zFar = mFarZ; + return mFarZ; } bool State::isBlendEnabled() const @@ -308,6 +372,7 @@ bool State::isBlendEnabled() const void State::setBlend(bool enabled) { mBlend.blend = enabled; + mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); } void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) @@ -316,6 +381,7 @@ void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha mBlend.destBlendRGB = destRGB; mBlend.sourceBlendAlpha = sourceAlpha; mBlend.destBlendAlpha = destAlpha; + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS); } void State::setBlendColor(float red, float green, float blue, float alpha) @@ -324,12 +390,14 @@ void State::setBlendColor(float red, float green, float blue, float alpha) mBlendColor.green = green; mBlendColor.blue = blue; mBlendColor.alpha = alpha; + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); } void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) { mBlend.blendEquationRGB = rgbEquation; mBlend.blendEquationAlpha = alphaEquation; + mDirtyBits.set(DIRTY_BIT_BLEND_EQUATIONS); } const ColorF &State::getBlendColor() const @@ -345,6 +413,7 @@ bool State::isStencilTestEnabled() const void State::setStencilTest(bool enabled) { mDepthStencil.stencilTest = enabled; + mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); } void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) @@ -352,6 +421,7 @@ void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stenci mDepthStencil.stencilFunc = stencilFunc; mStencilRef = (stencilRef > 0) ? stencilRef : 0; mDepthStencil.stencilMask = stencilMask; + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); } void State::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) @@ -359,16 +429,19 @@ void State::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, G mDepthStencil.stencilBackFunc = stencilBackFunc; mStencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; mDepthStencil.stencilBackMask = stencilBackMask; + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); } void State::setStencilWritemask(GLuint stencilWritemask) { mDepthStencil.stencilWritemask = stencilWritemask; + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); } void State::setStencilBackWritemask(GLuint stencilBackWritemask) { mDepthStencil.stencilBackWritemask = stencilBackWritemask; + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); } void State::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) @@ -376,6 +449,7 @@ void State::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail mDepthStencil.stencilFail = stencilFail; mDepthStencil.stencilPassDepthFail = stencilPassDepthFail; mDepthStencil.stencilPassDepthPass = stencilPassDepthPass; + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); } void State::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) @@ -383,6 +457,7 @@ void State::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackP mDepthStencil.stencilBackFail = stencilBackFail; mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); } GLint State::getStencilRef() const @@ -402,7 +477,8 @@ bool State::isPolygonOffsetFillEnabled() const void State::setPolygonOffsetFill(bool enabled) { - mRasterizer.polygonOffsetFill = enabled; + mRasterizer.polygonOffsetFill = enabled; + mDirtyBits.set(DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED); } void State::setPolygonOffsetParams(GLfloat factor, GLfloat units) @@ -410,6 +486,7 @@ void State::setPolygonOffsetParams(GLfloat factor, GLfloat units) // An application can pass NaN values here, so handle this gracefully mRasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor; mRasterizer.polygonOffsetUnits = units != units ? 0.0f : units; + mDirtyBits.set(DIRTY_BIT_POLYGON_OFFSET); } bool State::isSampleAlphaToCoverageEnabled() const @@ -420,6 +497,7 @@ bool State::isSampleAlphaToCoverageEnabled() const void State::setSampleAlphaToCoverage(bool enabled) { mBlend.sampleAlphaToCoverage = enabled; + mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED); } bool State::isSampleCoverageEnabled() const @@ -430,20 +508,24 @@ bool State::isSampleCoverageEnabled() const void State::setSampleCoverage(bool enabled) { mSampleCoverage = enabled; + mDirtyBits.set(DIRTY_BIT_SAMPLE_COVERAGE_ENABLED); } void State::setSampleCoverageParams(GLclampf value, bool invert) { mSampleCoverageValue = value; mSampleCoverageInvert = invert; + mDirtyBits.set(DIRTY_BIT_SAMPLE_COVERAGE); } -void State::getSampleCoverageParams(GLclampf *value, bool *invert) const +GLclampf State::getSampleCoverageValue() const { - ASSERT(value != NULL && invert != NULL); + return mSampleCoverageValue; +} - *value = mSampleCoverageValue; - *invert = mSampleCoverageInvert; +bool State::getSampleCoverageInvert() const +{ + return mSampleCoverageInvert; } bool State::isScissorTestEnabled() const @@ -454,6 +536,7 @@ bool State::isScissorTestEnabled() const void State::setScissorTest(bool enabled) { mScissorTest = enabled; + mDirtyBits.set(DIRTY_BIT_SCISSOR_TEST_ENABLED); } void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) @@ -462,6 +545,7 @@ void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) mScissor.y = y; mScissor.width = width; mScissor.height = height; + mDirtyBits.set(DIRTY_BIT_SCISSOR); } const Rectangle &State::getScissor() const @@ -477,6 +561,7 @@ bool State::isDitherEnabled() const void State::setDither(bool enabled) { mBlend.dither = enabled; + mDirtyBits.set(DIRTY_BIT_DITHER_ENABLED); } bool State::isPrimitiveRestartEnabled() const @@ -487,6 +572,7 @@ bool State::isPrimitiveRestartEnabled() const void State::setPrimitiveRestart(bool enabled) { mPrimitiveRestart = enabled; + mDirtyBits.set(DIRTY_BIT_PRIMITIVE_RESTART_ENABLED); } void State::setEnableFeature(GLenum feature, bool enabled) @@ -504,6 +590,12 @@ void State::setEnableFeature(GLenum feature, bool enabled) case GL_DITHER: setDither(enabled); break; case GL_PRIMITIVE_RESTART_FIXED_INDEX: setPrimitiveRestart(enabled); break; case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break; + case GL_DEBUG_OUTPUT_SYNCHRONOUS: + mDebug.setOutputSynchronous(enabled); + break; + case GL_DEBUG_OUTPUT: + mDebug.setOutputEnabled(enabled); + break; default: UNREACHABLE(); } } @@ -523,6 +615,10 @@ bool State::getEnableFeature(GLenum feature) case GL_DITHER: return isDitherEnabled(); case GL_PRIMITIVE_RESTART_FIXED_INDEX: return isPrimitiveRestartEnabled(); case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled(); + case GL_DEBUG_OUTPUT_SYNCHRONOUS: + return mDebug.isOutputSynchronous(); + case GL_DEBUG_OUTPUT: + return mDebug.isOutputEnabled(); default: UNREACHABLE(); return false; } } @@ -530,16 +626,24 @@ bool State::getEnableFeature(GLenum feature) void State::setLineWidth(GLfloat width) { mLineWidth = width; + mDirtyBits.set(DIRTY_BIT_LINE_WIDTH); +} + +float State::getLineWidth() const +{ + return mLineWidth; } void State::setGenerateMipmapHint(GLenum hint) { mGenerateMipmapHint = hint; + mDirtyBits.set(DIRTY_BIT_GENERATE_MIPMAP_HINT); } void State::setFragmentShaderDerivativeHint(GLenum hint) { mFragmentShaderDerivativeHint = hint; + mDirtyBits.set(DIRTY_BIT_SHADER_DERIVATIVE_HINT); // TODO: Propagate the hint to shader translator so we can write // ddx, ddx_coarse, or ddx_fine depending on the hint. // Ignore for now. It is valid for implementations to ignore hint. @@ -551,6 +655,7 @@ void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) mViewport.y = y; mViewport.width = width; mViewport.height = height; + mDirtyBits.set(DIRTY_BIT_VIEWPORT); } const Rectangle &State::getViewport() const @@ -565,7 +670,7 @@ void State::setActiveSampler(unsigned int active) unsigned int State::getActiveSampler() const { - return mActiveSampler; + return static_cast(mActiveSampler); } void State::setSamplerTexture(GLenum type, Texture *texture) @@ -573,10 +678,16 @@ void State::setSamplerTexture(GLenum type, Texture *texture) mSamplerTextures[type][mActiveSampler].set(texture); } +Texture *State::getTargetTexture(GLenum target) const +{ + return getSamplerTexture(static_cast(mActiveSampler), target); +} + Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const { const auto it = mSamplerTextures.find(type); ASSERT(it != mSamplerTextures.end()); + ASSERT(sampler < it->second.size()); return it->second[sampler].get(); } @@ -584,6 +695,7 @@ GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const { const auto it = mSamplerTextures.find(type); ASSERT(it != mSamplerTextures.end()); + ASSERT(sampler < it->second.size()); return it->second[sampler].id(); } @@ -633,9 +745,8 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) void State::initializeZeroTextures(const TextureMap &zeroTextures) { - for (auto it = zeroTextures.cbegin(); it != zeroTextures.cend(); ++it) + for (const auto &zeroTexture : zeroTextures) { - const auto &zeroTexture = *it; auto &samplerTextureArray = mSamplerTextures[zeroTexture.first]; for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) @@ -725,22 +836,44 @@ void State::detachRenderbuffer(GLuint renderbuffer) void State::setReadFramebufferBinding(Framebuffer *framebuffer) { + if (mReadFramebuffer == framebuffer) + return; + mReadFramebuffer = framebuffer; + mDirtyBits.set(DIRTY_BIT_READ_FRAMEBUFFER_BINDING); + + if (mReadFramebuffer && mReadFramebuffer->hasAnyDirtyBit()) + { + mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER); + } } void State::setDrawFramebufferBinding(Framebuffer *framebuffer) { + if (mDrawFramebuffer == framebuffer) + return; + mDrawFramebuffer = framebuffer; + mDirtyBits.set(DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING); + + if (mDrawFramebuffer && mDrawFramebuffer->hasAnyDirtyBit()) + { + mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); + } } Framebuffer *State::getTargetFramebuffer(GLenum target) const { switch (target) { - case GL_READ_FRAMEBUFFER_ANGLE: return mReadFramebuffer; - case GL_DRAW_FRAMEBUFFER_ANGLE: - case GL_FRAMEBUFFER: return mDrawFramebuffer; - default: UNREACHABLE(); return NULL; + case GL_READ_FRAMEBUFFER_ANGLE: + return mReadFramebuffer; + case GL_DRAW_FRAMEBUFFER_ANGLE: + case GL_FRAMEBUFFER: + return mDrawFramebuffer; + default: + UNREACHABLE(); + return NULL; } } @@ -766,9 +899,10 @@ const Framebuffer *State::getDrawFramebuffer() const bool State::removeReadFramebufferBinding(GLuint framebuffer) { - if (mReadFramebuffer->id() == framebuffer) + if (mReadFramebuffer != nullptr && + mReadFramebuffer->id() == framebuffer) { - mReadFramebuffer = NULL; + setReadFramebufferBinding(nullptr); return true; } @@ -777,9 +911,10 @@ bool State::removeReadFramebufferBinding(GLuint framebuffer) bool State::removeDrawFramebufferBinding(GLuint framebuffer) { - if (mDrawFramebuffer->id() == framebuffer) + if (mReadFramebuffer != nullptr && + mDrawFramebuffer->id() == framebuffer) { - mDrawFramebuffer = NULL; + setDrawFramebufferBinding(nullptr); return true; } @@ -789,6 +924,12 @@ bool State::removeDrawFramebufferBinding(GLuint framebuffer) void State::setVertexArrayBinding(VertexArray *vertexArray) { mVertexArray = vertexArray; + mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING); + + if (mVertexArray && mVertexArray->hasAnyDirtyBit()) + { + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); + } } GLuint State::getVertexArrayId() const @@ -808,6 +949,8 @@ bool State::removeVertexArrayBinding(GLuint vertexArray) if (mVertexArray->id() == vertexArray) { mVertexArray = NULL; + mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); return true; } @@ -850,7 +993,7 @@ TransformFeedback *State::getCurrentTransformFeedback() const bool State::isTransformFeedbackActiveUnpaused() const { gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback(); - return curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused(); + return curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused(); } void State::detachTransformFeedback(GLuint transformFeedback) @@ -863,10 +1006,22 @@ void State::detachTransformFeedback(GLuint transformFeedback) bool State::isQueryActive() const { - for (State::ActiveQueryMap::const_iterator i = mActiveQueries.begin(); - i != mActiveQueries.end(); i++) + for (auto &iter : mActiveQueries) { - if (i->second.get() != NULL) + if (iter.second.get() != NULL) + { + return true; + } + } + + return false; +} + +bool State::isQueryActive(Query *query) const +{ + for (auto &iter : mActiveQueries) + { + if (iter.second.get() == query) { return true; } @@ -906,17 +1061,6 @@ GLuint State::getArrayBufferId() const return mArrayBuffer.id(); } -bool State::removeArrayBufferBinding(GLuint buffer) -{ - if (mArrayBuffer.id() == buffer) - { - mArrayBuffer.set(NULL); - return true; - } - - return false; -} - void State::setGenericUniformBufferBinding(Buffer *buffer) { mGenericUniformBuffer.set(buffer); @@ -927,68 +1071,10 @@ void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintpt mUniformBuffers[index].set(buffer, offset, size); } -GLuint State::getIndexedUniformBufferId(GLuint index) const -{ - ASSERT(static_cast(index) < mUniformBuffers.size()); - - return mUniformBuffers[index].id(); -} - -Buffer *State::getIndexedUniformBuffer(GLuint index) const +const OffsetBindingPointer &State::getIndexedUniformBuffer(size_t index) const { ASSERT(static_cast(index) < mUniformBuffers.size()); - - return mUniformBuffers[index].get(); -} - -GLintptr State::getIndexedUniformBufferOffset(GLuint index) const -{ - ASSERT(static_cast(index) < mUniformBuffers.size()); - - return mUniformBuffers[index].getOffset(); -} - -GLsizeiptr State::getIndexedUniformBufferSize(GLuint index) const -{ - ASSERT(static_cast(index) < mUniformBuffers.size()); - - return mUniformBuffers[index].getSize(); -} - -void State::setGenericTransformFeedbackBufferBinding(Buffer *buffer) -{ - mGenericTransformFeedbackBuffer.set(buffer); -} - -void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) -{ - mTransformFeedbackBuffers[index].set(buffer, offset, size); -} - -GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const -{ - ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); - - return mTransformFeedbackBuffers[index].id(); -} - -Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const -{ - ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); - - return mTransformFeedbackBuffers[index].get(); -} - -GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const -{ - ASSERT(static_cast(index) < mTransformFeedbackBuffers.size()); - - return mTransformFeedbackBuffers[index].getOffset(); -} - -size_t State::getTransformFeedbackBufferIndexRange() const -{ - return mTransformFeedbackBuffers.size(); + return mUniformBuffers[index]; } void State::setCopyReadBufferBinding(Buffer *buffer) @@ -1018,42 +1104,81 @@ Buffer *State::getTargetBuffer(GLenum target) const case GL_ARRAY_BUFFER: return mArrayBuffer.get(); case GL_COPY_READ_BUFFER: return mCopyReadBuffer.get(); case GL_COPY_WRITE_BUFFER: return mCopyWriteBuffer.get(); - case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer(); + case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer().get(); case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get(); case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get(); - case GL_TRANSFORM_FEEDBACK_BUFFER: return mGenericTransformFeedbackBuffer.get(); + case GL_TRANSFORM_FEEDBACK_BUFFER: return mTransformFeedback->getGenericBuffer().get(); case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get(); default: UNREACHABLE(); return NULL; } } +void State::detachBuffer(GLuint bufferName) +{ + BindingPointer *buffers[] = {&mArrayBuffer, &mCopyReadBuffer, + &mCopyWriteBuffer, &mPack.pixelBuffer, + &mUnpack.pixelBuffer, &mGenericUniformBuffer}; + for (auto buffer : buffers) + { + if (buffer->id() == bufferName) + { + buffer->set(nullptr); + } + } + + TransformFeedback *curTransformFeedback = getCurrentTransformFeedback(); + if (curTransformFeedback) + { + curTransformFeedback->detachBuffer(bufferName); + } + + getVertexArray()->detachBuffer(bufferName); +} + void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) { getVertexArray()->enableAttribute(attribNum, enabled); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); } void State::setVertexAttribf(GLuint index, const GLfloat values[4]) { ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setFloatValues(values); + mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index); } void State::setVertexAttribu(GLuint index, const GLuint values[4]) { ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setUnsignedIntValues(values); + mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index); } void State::setVertexAttribi(GLuint index, const GLint values[4]) { ASSERT(static_cast(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setIntValues(values); + mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index); } -void State::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, - bool pureInteger, GLsizei stride, const void *pointer) +void State::setVertexAttribState(unsigned int attribNum, + Buffer *boundBuffer, + GLint size, + GLenum type, + bool normalized, + bool pureInteger, + GLsizei stride, + const void *pointer) { getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); +} + +void State::setVertexAttribDivisor(GLuint index, GLuint divisor) +{ + getVertexArray()->setVertexAttribDivisor(index, divisor); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); } const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const @@ -1070,6 +1195,7 @@ const void *State::getVertexAttribPointer(unsigned int attribNum) const void State::setPackAlignment(GLint alignment) { mPack.alignment = alignment; + mDirtyBits.set(DIRTY_BIT_PACK_ALIGNMENT); } GLint State::getPackAlignment() const @@ -1080,6 +1206,7 @@ GLint State::getPackAlignment() const void State::setPackReverseRowOrder(bool reverseRowOrder) { mPack.reverseRowOrder = reverseRowOrder; + mDirtyBits.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER); } bool State::getPackReverseRowOrder() const @@ -1087,6 +1214,39 @@ bool State::getPackReverseRowOrder() const return mPack.reverseRowOrder; } +void State::setPackRowLength(GLint rowLength) +{ + mPack.rowLength = rowLength; + mDirtyBits.set(DIRTY_BIT_PACK_ROW_LENGTH); +} + +GLint State::getPackRowLength() const +{ + return mPack.rowLength; +} + +void State::setPackSkipRows(GLint skipRows) +{ + mPack.skipRows = skipRows; + mDirtyBits.set(DIRTY_BIT_PACK_SKIP_ROWS); +} + +GLint State::getPackSkipRows() const +{ + return mPack.skipRows; +} + +void State::setPackSkipPixels(GLint skipPixels) +{ + mPack.skipPixels = skipPixels; + mDirtyBits.set(DIRTY_BIT_PACK_SKIP_PIXELS); +} + +GLint State::getPackSkipPixels() const +{ + return mPack.skipPixels; +} + const PixelPackState &State::getPackState() const { return mPack; @@ -1100,6 +1260,7 @@ PixelPackState &State::getPackState() void State::setUnpackAlignment(GLint alignment) { mUnpack.alignment = alignment; + mDirtyBits.set(DIRTY_BIT_UNPACK_ALIGNMENT); } GLint State::getUnpackAlignment() const @@ -1110,6 +1271,7 @@ GLint State::getUnpackAlignment() const void State::setUnpackRowLength(GLint rowLength) { mUnpack.rowLength = rowLength; + mDirtyBits.set(DIRTY_BIT_UNPACK_ROW_LENGTH); } GLint State::getUnpackRowLength() const @@ -1117,6 +1279,50 @@ GLint State::getUnpackRowLength() const return mUnpack.rowLength; } +void State::setUnpackImageHeight(GLint imageHeight) +{ + mUnpack.imageHeight = imageHeight; + mDirtyBits.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT); +} + +GLint State::getUnpackImageHeight() const +{ + return mUnpack.imageHeight; +} + +void State::setUnpackSkipImages(GLint skipImages) +{ + mUnpack.skipImages = skipImages; + mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_IMAGES); +} + +GLint State::getUnpackSkipImages() const +{ + return mUnpack.skipImages; +} + +void State::setUnpackSkipRows(GLint skipRows) +{ + mUnpack.skipRows = skipRows; + mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_ROWS); +} + +GLint State::getUnpackSkipRows() const +{ + return mUnpack.skipRows; +} + +void State::setUnpackSkipPixels(GLint skipPixels) +{ + mUnpack.skipPixels = skipPixels; + mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_PIXELS); +} + +GLint State::getUnpackSkipPixels() const +{ + return mUnpack.skipPixels; +} + const PixelUnpackState &State::getUnpackState() const { return mUnpack; @@ -1127,6 +1333,16 @@ PixelUnpackState &State::getUnpackState() return mUnpack; } +const Debug &State::getDebug() const +{ + return mDebug; +} + +Debug &State::getDebug() +{ + return mDebug; +} + void State::getBooleanv(GLenum pname, GLboolean *params) { switch (pname) @@ -1148,8 +1364,20 @@ void State::getBooleanv(GLenum pname, GLboolean *params) case GL_DEPTH_TEST: *params = mDepthStencil.depthTest; break; case GL_BLEND: *params = mBlend.blend; break; case GL_DITHER: *params = mBlend.dither; break; - case GL_TRANSFORM_FEEDBACK_ACTIVE: *params = getCurrentTransformFeedback()->isStarted(); break; - case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused(); break; + case GL_TRANSFORM_FEEDBACK_ACTIVE: *params = getCurrentTransformFeedback()->isActive() ? GL_TRUE : GL_FALSE; break; + case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused() ? GL_TRUE : GL_FALSE; break; + case GL_PRIMITIVE_RESTART_FIXED_INDEX: + *params = mPrimitiveRestart; + break; + case GL_RASTERIZER_DISCARD: + *params = isRasterizerDiscardEnabled() ? GL_TRUE : GL_FALSE; + break; + case GL_DEBUG_OUTPUT_SYNCHRONOUS: + *params = mDebug.isOutputSynchronous() ? GL_TRUE : GL_FALSE; + break; + case GL_DEBUG_OUTPUT: + *params = mDebug.isOutputEnabled() ? GL_TRUE : GL_FALSE; + break; default: UNREACHABLE(); break; @@ -1210,7 +1438,7 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) switch (pname) { case GL_ARRAY_BUFFER_BINDING: *params = mArrayBuffer.id(); break; - case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBufferId(); break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBuffer().id(); break; //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mDrawFramebuffer->id(); break; case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break; @@ -1219,11 +1447,34 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) case GL_CURRENT_PROGRAM: *params = mProgram ? mProgram->id() : 0; break; case GL_PACK_ALIGNMENT: *params = mPack.alignment; break; case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mPack.reverseRowOrder; break; + case GL_PACK_ROW_LENGTH: + *params = mPack.rowLength; + break; + case GL_PACK_SKIP_ROWS: + *params = mPack.skipRows; + break; + case GL_PACK_SKIP_PIXELS: + *params = mPack.skipPixels; + break; case GL_UNPACK_ALIGNMENT: *params = mUnpack.alignment; break; case GL_UNPACK_ROW_LENGTH: *params = mUnpack.rowLength; break; + case GL_UNPACK_IMAGE_HEIGHT: + *params = mUnpack.imageHeight; + break; + case GL_UNPACK_SKIP_IMAGES: + *params = mUnpack.skipImages; + break; + case GL_UNPACK_SKIP_ROWS: + *params = mUnpack.skipRows; + break; + case GL_UNPACK_SKIP_PIXELS: + *params = mUnpack.skipPixels; + break; case GL_GENERATE_MIPMAP_HINT: *params = mGenerateMipmapHint; break; case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mFragmentShaderDerivativeHint; break; - case GL_ACTIVE_TEXTURE: *params = (mActiveSampler + GL_TEXTURE0); break; + case GL_ACTIVE_TEXTURE: + *params = (static_cast(mActiveSampler) + GL_TEXTURE0); + break; case GL_STENCIL_FUNC: *params = mDepthStencil.stencilFunc; break; case GL_STENCIL_REF: *params = mStencilRef; break; case GL_STENCIL_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilMask); break; @@ -1297,7 +1548,7 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) case GL_ALPHA_BITS: { gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer(); + const gl::FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer(); if (colorbuffer) { @@ -1317,8 +1568,8 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) break; case GL_DEPTH_BITS: { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer(); + const gl::Framebuffer *framebuffer = getDrawFramebuffer(); + const gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer(); if (depthbuffer) { @@ -1332,8 +1583,8 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) break; case GL_STENCIL_BITS: { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer(); + const gl::Framebuffer *framebuffer = getDrawFramebuffer(); + const gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer(); if (stencilbuffer) { @@ -1347,25 +1598,30 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) break; case GL_TEXTURE_BINDING_2D: ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_2D) ; + *params = getSamplerTextureId(static_cast(mActiveSampler), GL_TEXTURE_2D); break; case GL_TEXTURE_BINDING_CUBE_MAP: ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_CUBE_MAP); + *params = + getSamplerTextureId(static_cast(mActiveSampler), GL_TEXTURE_CUBE_MAP); break; case GL_TEXTURE_BINDING_3D: ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_3D); + *params = getSamplerTextureId(static_cast(mActiveSampler), GL_TEXTURE_3D); break; case GL_TEXTURE_BINDING_2D_ARRAY: ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); - *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_2D_ARRAY); + *params = + getSamplerTextureId(static_cast(mActiveSampler), GL_TEXTURE_2D_ARRAY); break; case GL_UNIFORM_BUFFER_BINDING: *params = mGenericUniformBuffer.id(); break; + case GL_TRANSFORM_FEEDBACK_BINDING: + *params = mTransformFeedback.id(); + break; case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - *params = mGenericTransformFeedbackBuffer.id(); + *params = mTransformFeedback->getGenericBuffer().id(); break; case GL_COPY_READ_BUFFER_BINDING: *params = mCopyReadBuffer.id(); @@ -1379,20 +1635,45 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) case GL_PIXEL_UNPACK_BUFFER_BINDING: *params = mUnpack.pixelBuffer.id(); break; + case GL_DEBUG_LOGGED_MESSAGES: + *params = static_cast(mDebug.getMessageCount()); + break; + case GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH: + *params = static_cast(mDebug.getNextMessageLength()); + break; + case GL_DEBUG_GROUP_STACK_DEPTH: + *params = static_cast(mDebug.getGroupStackDepth()); + break; default: UNREACHABLE(); break; } } +void State::getPointerv(GLenum pname, void **params) const +{ + switch (pname) + { + case GL_DEBUG_CALLBACK_FUNCTION: + *params = reinterpret_cast(mDebug.getCallback()); + break; + case GL_DEBUG_CALLBACK_USER_PARAM: + *params = const_cast(mDebug.getUserParam()); + break; + default: + UNREACHABLE(); + break; + } +} + bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) { switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (static_cast(index) < mTransformFeedbackBuffers.size()) + if (static_cast(index) < mTransformFeedback->getIndexedBufferCount()) { - *data = mTransformFeedbackBuffers[index].id(); + *data = mTransformFeedback->getIndexedBuffer(index).id(); } break; case GL_UNIFORM_BUFFER_BINDING: @@ -1413,15 +1694,15 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER_START: - if (static_cast(index) < mTransformFeedbackBuffers.size()) + if (static_cast(index) < mTransformFeedback->getIndexedBufferCount()) { - *data = mTransformFeedbackBuffers[index].getOffset(); + *data = mTransformFeedback->getIndexedBuffer(index).getOffset(); } break; case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - if (static_cast(index) < mTransformFeedbackBuffers.size()) + if (static_cast(index) < mTransformFeedback->getIndexedBufferCount()) { - *data = mTransformFeedbackBuffers[index].getSize(); + *data = mTransformFeedback->getIndexedBuffer(index).getSize(); } break; case GL_UNIFORM_BUFFER_START: @@ -1448,9 +1729,11 @@ bool State::hasMappedBuffer(GLenum target) const if (target == GL_ARRAY_BUFFER) { const VertexArray *vao = getVertexArray(); - for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++) + const auto &vertexAttribs = vao->getVertexAttributes(); + size_t maxEnabledAttrib = vao->getMaxEnabledAttribute(); + for (size_t attribIndex = 0; attribIndex < maxEnabledAttrib; attribIndex++) { - const gl::VertexAttribute &vertexAttrib = vao->getVertexAttribute(attribIndex); + const gl::VertexAttribute &vertexAttrib = vertexAttribs[attribIndex]; gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) { @@ -1467,4 +1750,92 @@ bool State::hasMappedBuffer(GLenum target) const } } +void State::syncDirtyObjects() +{ + if (!mDirtyObjects.any()) + return; + + syncDirtyObjects(mDirtyObjects); +} + +void State::syncDirtyObjects(const DirtyObjects &bitset) +{ + for (auto dirtyObject : angle::IterateBitSet(bitset)) + { + switch (dirtyObject) + { + case DIRTY_OBJECT_READ_FRAMEBUFFER: + ASSERT(mReadFramebuffer); + mReadFramebuffer->syncState(); + break; + case DIRTY_OBJECT_DRAW_FRAMEBUFFER: + ASSERT(mDrawFramebuffer); + mDrawFramebuffer->syncState(); + break; + case DIRTY_OBJECT_VERTEX_ARRAY: + ASSERT(mVertexArray); + mVertexArray->syncImplState(); + break; + case DIRTY_OBJECT_PROGRAM: + // TODO(jmadill): implement this + break; + default: + UNREACHABLE(); + break; + } + } + + mDirtyObjects &= ~bitset; +} + +void State::syncDirtyObject(GLenum target) +{ + DirtyObjects localSet; + + switch (target) + { + case GL_READ_FRAMEBUFFER: + localSet.set(DIRTY_OBJECT_READ_FRAMEBUFFER); + break; + case GL_DRAW_FRAMEBUFFER: + localSet.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); + break; + case GL_FRAMEBUFFER: + localSet.set(DIRTY_OBJECT_READ_FRAMEBUFFER); + localSet.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); + break; + case GL_VERTEX_ARRAY: + localSet.set(DIRTY_OBJECT_VERTEX_ARRAY); + break; + case GL_PROGRAM: + localSet.set(DIRTY_OBJECT_PROGRAM); + break; + } + + syncDirtyObjects(localSet); } + +void State::setObjectDirty(GLenum target) +{ + switch (target) + { + case GL_READ_FRAMEBUFFER: + mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER); + break; + case GL_DRAW_FRAMEBUFFER: + mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); + break; + case GL_FRAMEBUFFER: + mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER); + mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); + break; + case GL_VERTEX_ARRAY: + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); + break; + case GL_PROGRAM: + mDirtyObjects.set(DIRTY_OBJECT_PROGRAM); + break; + } +} + +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/State.h b/src/3rdparty/angle/src/libANGLE/State.h index 4370a2f16f..e822d7e679 100644 --- a/src/3rdparty/angle/src/libANGLE/State.h +++ b/src/3rdparty/angle/src/libANGLE/State.h @@ -9,15 +9,19 @@ #ifndef LIBANGLE_STATE_H_ #define LIBANGLE_STATE_H_ +#include +#include + #include "common/angleutils.h" +#include "libANGLE/Debug.h" +#include "libANGLE/Program.h" #include "libANGLE/RefCountObject.h" -#include "libANGLE/angletypes.h" -#include "libANGLE/VertexAttribute.h" #include "libANGLE/Renderbuffer.h" +#include "libANGLE/Sampler.h" #include "libANGLE/Texture.h" #include "libANGLE/TransformFeedback.h" -#include "libANGLE/Program.h" -#include "libANGLE/Sampler.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/angletypes.h" namespace gl { @@ -27,7 +31,7 @@ class Context; struct Caps; struct Data; -typedef std::map< GLenum, BindingPointer > TextureMap; +typedef std::map> TextureMap; class State : angle::NonCopyable { @@ -35,7 +39,10 @@ class State : angle::NonCopyable State(); ~State(); - void initialize(const Caps& caps, GLuint clientVersion); + void initialize(const Caps &caps, + const Extensions &extensions, + GLuint clientVersion, + bool debug); void reset(); // State chunk getters @@ -75,7 +82,8 @@ class State : angle::NonCopyable void setDepthTest(bool enabled); void setDepthFunc(GLenum depthFunc); void setDepthRange(float zNear, float zFar); - void getDepthRange(float *zNear, float *zFar) const; + float getNearPlane() const; + float getFarPlane() const; // Blend state manipulation bool isBlendEnabled() const; @@ -108,7 +116,8 @@ class State : angle::NonCopyable bool isSampleCoverageEnabled() const; void setSampleCoverage(bool enabled); void setSampleCoverageParams(GLclampf value, bool invert); - void getSampleCoverageParams(GLclampf *value, bool *invert) const; + GLclampf getSampleCoverageValue() const; + bool getSampleCoverageInvert() const; // Scissor test state toggle & query bool isScissorTestEnabled() const; @@ -126,6 +135,7 @@ class State : angle::NonCopyable // Line width state setter void setLineWidth(GLfloat width); + float getLineWidth() const; // Hint setters void setGenerateMipmapHint(GLenum hint); @@ -139,6 +149,7 @@ class State : angle::NonCopyable void setActiveSampler(unsigned int active); unsigned int getActiveSampler() const; void setSamplerTexture(GLenum type, Texture *texture); + Texture *getTargetTexture(GLenum target) const; Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; GLuint getSamplerTextureId(unsigned int sampler, GLenum type) const; void detachTexture(const TextureMap &zeroTextures, GLuint texture); @@ -185,6 +196,7 @@ class State : angle::NonCopyable // Query binding manipulation bool isQueryActive() const; + bool isQueryActive(Query *query) const; void setActiveQuery(GLenum target, Query *query); GLuint getActiveQueryId(GLenum target) const; Query *getActiveQuery(GLenum target) const; @@ -193,23 +205,11 @@ class State : angle::NonCopyable // GL_ARRAY_BUFFER void setArrayBufferBinding(Buffer *buffer); GLuint getArrayBufferId() const; - bool removeArrayBufferBinding(GLuint buffer); // GL_UNIFORM_BUFFER - Both indexed and generic targets void setGenericUniformBufferBinding(Buffer *buffer); void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); - GLuint getIndexedUniformBufferId(GLuint index) const; - Buffer *getIndexedUniformBuffer(GLuint index) const; - GLintptr getIndexedUniformBufferOffset(GLuint index) const; - GLsizeiptr getIndexedUniformBufferSize(GLuint index) const; - - // GL_TRANSFORM_FEEDBACK_BUFFER - Both indexed and generic targets - void setGenericTransformFeedbackBufferBinding(Buffer *buffer); - void setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); - GLuint getIndexedTransformFeedbackBufferId(GLuint index) const; - Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const; - GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const; - size_t getTransformFeedbackBufferIndexRange() const; + const OffsetBindingPointer &getIndexedUniformBuffer(size_t index) const; // GL_COPY_[READ/WRITE]_BUFFER void setCopyReadBufferBinding(Buffer *buffer); @@ -221,6 +221,8 @@ class State : angle::NonCopyable // Retrieve typed buffer by target (non-indexed) Buffer *getTargetBuffer(GLenum target) const; + // Detach a buffer from all bindings + void detachBuffer(GLuint bufferName); // Vertex attrib manipulation void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); @@ -229,6 +231,7 @@ class State : angle::NonCopyable void setVertexAttribi(GLuint index, const GLint values[4]); void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, bool pureInteger, GLsizei stride, const void *pointer); + void setVertexAttribDivisor(GLuint index, GLuint divisor); const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; const void *getVertexAttribPointer(unsigned int attribNum) const; @@ -237,6 +240,12 @@ class State : angle::NonCopyable GLint getPackAlignment() const; void setPackReverseRowOrder(bool reverseRowOrder); bool getPackReverseRowOrder() const; + void setPackRowLength(GLint rowLength); + GLint getPackRowLength() const; + void setPackSkipRows(GLint skipRows); + GLint getPackSkipRows() const; + void setPackSkipPixels(GLint skipPixels); + GLint getPackSkipPixels() const; const PixelPackState &getPackState() const; PixelPackState &getPackState(); @@ -245,18 +254,122 @@ class State : angle::NonCopyable GLint getUnpackAlignment() const; void setUnpackRowLength(GLint rowLength); GLint getUnpackRowLength() const; + void setUnpackImageHeight(GLint imageHeight); + GLint getUnpackImageHeight() const; + void setUnpackSkipImages(GLint skipImages); + GLint getUnpackSkipImages() const; + void setUnpackSkipRows(GLint skipRows); + GLint getUnpackSkipRows() const; + void setUnpackSkipPixels(GLint skipPixels); + GLint getUnpackSkipPixels() const; const PixelUnpackState &getUnpackState() const; PixelUnpackState &getUnpackState(); + // Debug state + const Debug &getDebug() const; + Debug &getDebug(); + // State query functions void getBooleanv(GLenum pname, GLboolean *params); void getFloatv(GLenum pname, GLfloat *params); void getIntegerv(const gl::Data &data, GLenum pname, GLint *params); + void getPointerv(GLenum pname, void **params) const; bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); bool hasMappedBuffer(GLenum target) const; + enum DirtyBitType + { + DIRTY_BIT_SCISSOR_TEST_ENABLED, + DIRTY_BIT_SCISSOR, + DIRTY_BIT_VIEWPORT, + DIRTY_BIT_DEPTH_RANGE, + DIRTY_BIT_BLEND_ENABLED, + DIRTY_BIT_BLEND_COLOR, + DIRTY_BIT_BLEND_FUNCS, + DIRTY_BIT_BLEND_EQUATIONS, + DIRTY_BIT_COLOR_MASK, + DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED, + DIRTY_BIT_SAMPLE_COVERAGE_ENABLED, + DIRTY_BIT_SAMPLE_COVERAGE, + DIRTY_BIT_DEPTH_TEST_ENABLED, + DIRTY_BIT_DEPTH_FUNC, + DIRTY_BIT_DEPTH_MASK, + DIRTY_BIT_STENCIL_TEST_ENABLED, + DIRTY_BIT_STENCIL_FUNCS_FRONT, + DIRTY_BIT_STENCIL_FUNCS_BACK, + DIRTY_BIT_STENCIL_OPS_FRONT, + DIRTY_BIT_STENCIL_OPS_BACK, + DIRTY_BIT_STENCIL_WRITEMASK_FRONT, + DIRTY_BIT_STENCIL_WRITEMASK_BACK, + DIRTY_BIT_CULL_FACE_ENABLED, + DIRTY_BIT_CULL_FACE, + DIRTY_BIT_FRONT_FACE, + DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED, + DIRTY_BIT_POLYGON_OFFSET, + DIRTY_BIT_RASTERIZER_DISCARD_ENABLED, + DIRTY_BIT_LINE_WIDTH, + DIRTY_BIT_PRIMITIVE_RESTART_ENABLED, + DIRTY_BIT_CLEAR_COLOR, + DIRTY_BIT_CLEAR_DEPTH, + DIRTY_BIT_CLEAR_STENCIL, + DIRTY_BIT_UNPACK_ALIGNMENT, + DIRTY_BIT_UNPACK_ROW_LENGTH, + DIRTY_BIT_UNPACK_IMAGE_HEIGHT, + DIRTY_BIT_UNPACK_SKIP_IMAGES, + DIRTY_BIT_UNPACK_SKIP_ROWS, + DIRTY_BIT_UNPACK_SKIP_PIXELS, + DIRTY_BIT_PACK_ALIGNMENT, + DIRTY_BIT_PACK_REVERSE_ROW_ORDER, + DIRTY_BIT_PACK_ROW_LENGTH, + DIRTY_BIT_PACK_SKIP_ROWS, + DIRTY_BIT_PACK_SKIP_PIXELS, + DIRTY_BIT_DITHER_ENABLED, + DIRTY_BIT_GENERATE_MIPMAP_HINT, + DIRTY_BIT_SHADER_DERIVATIVE_HINT, + DIRTY_BIT_READ_FRAMEBUFFER_BINDING, + DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING, + DIRTY_BIT_RENDERBUFFER_BINDING, + DIRTY_BIT_VERTEX_ARRAY_BINDING, + DIRTY_BIT_PROGRAM_BINDING, + DIRTY_BIT_CURRENT_VALUE_0, + DIRTY_BIT_CURRENT_VALUE_MAX = DIRTY_BIT_CURRENT_VALUE_0 + MAX_VERTEX_ATTRIBS, + DIRTY_BIT_INVALID = DIRTY_BIT_CURRENT_VALUE_MAX, + DIRTY_BIT_MAX = DIRTY_BIT_INVALID, + }; + + // TODO(jmadill): Consider storing dirty objects in a list instead of by binding. + enum DirtyObjectType + { + DIRTY_OBJECT_READ_FRAMEBUFFER, + DIRTY_OBJECT_DRAW_FRAMEBUFFER, + DIRTY_OBJECT_VERTEX_ARRAY, + DIRTY_OBJECT_PROGRAM, + DIRTY_OBJECT_UNKNOWN, + DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN, + }; + + typedef std::bitset DirtyBits; + const DirtyBits &getDirtyBits() const { return mDirtyBits; } + void clearDirtyBits() { mDirtyBits.reset(); } + void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; } + void setAllDirtyBits() { mDirtyBits.set(); } + + typedef std::bitset DirtyObjects; + void clearDirtyObjects() { mDirtyObjects.reset(); } + void setAllDirtyObjects() { mDirtyObjects.set(); } + void syncDirtyObjects(); + void syncDirtyObjects(const DirtyObjects &bitset); + void syncDirtyObject(GLenum target); + void setObjectDirty(GLenum target); + + // Dirty bit masks + const DirtyBits &unpackStateBitMask() const { return mUnpackStateBitMask; } + const DirtyBits &packStateBitMask() const { return mPackStateBitMask; } + const DirtyBits &clearStateBitMask() const { return mClearStateBitMask; } + const DirtyBits &blitStateBitMask() const { return mBlitStateBitMask; } + private: // Cached values from Context's caps GLuint mMaxDrawBuffers; @@ -302,23 +415,21 @@ class State : angle::NonCopyable // Texture and sampler bindings size_t mActiveSampler; // Active texture unit selector - GL_TEXTURE0 - typedef std::vector< BindingPointer > TextureBindingVector; + typedef std::vector> TextureBindingVector; typedef std::map TextureBindingMap; TextureBindingMap mSamplerTextures; - typedef std::vector< BindingPointer > SamplerBindingVector; + typedef std::vector> SamplerBindingVector; SamplerBindingVector mSamplers; - typedef std::map< GLenum, BindingPointer > ActiveQueryMap; + typedef std::map> ActiveQueryMap; ActiveQueryMap mActiveQueries; BindingPointer mGenericUniformBuffer; - typedef std::vector< OffsetBindingPointer > BufferVector; + typedef std::vector> BufferVector; BufferVector mUniformBuffers; BindingPointer mTransformFeedback; - BindingPointer mGenericTransformFeedbackBuffer; - BufferVector mTransformFeedbackBuffers; BindingPointer mCopyReadBuffer; BindingPointer mCopyWriteBuffer; @@ -327,6 +438,16 @@ class State : angle::NonCopyable PixelPackState mPack; bool mPrimitiveRestart; + + Debug mDebug; + + DirtyBits mDirtyBits; + DirtyBits mUnpackStateBitMask; + DirtyBits mPackStateBitMask; + DirtyBits mClearStateBitMask; + DirtyBits mBlitStateBitMask; + + DirtyObjects mDirtyObjects; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Surface.cpp b/src/3rdparty/angle/src/libANGLE/Surface.cpp index ac455f3905..b5ed0ff5a6 100644 --- a/src/3rdparty/angle/src/libANGLE/Surface.cpp +++ b/src/3rdparty/angle/src/libANGLE/Surface.cpp @@ -11,17 +11,25 @@ #include "libANGLE/Surface.h" #include "libANGLE/Config.h" +#include "libANGLE/Framebuffer.h" #include "libANGLE/Texture.h" -#include "libANGLE/renderer/SurfaceImpl.h" #include +#include + namespace egl { -Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes) - : RefCountObject(0), // id unused +Surface::Surface(rx::SurfaceImpl *impl, + EGLint surfaceType, + const egl::Config *config, + const AttributeMap &attributes) + : FramebufferAttachmentObject(), mImplementation(impl), + mDefaultFramebuffer(nullptr), + mCurrentCount(0), + mDestroyed(false), mType(surfaceType), mConfig(config), mPostSubBufferRequested(false), @@ -33,12 +41,15 @@ Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *c // FIXME: Determine actual pixel aspect ratio mPixelAspectRatio(static_cast(1.0 * EGL_DISPLAY_SCALING)), mRenderBuffer(EGL_BACK_BUFFER), - mSwapBehavior(EGL_BUFFER_PRESERVED), - mTexture(NULL) + mSwapBehavior(impl->getSwapBehavior()), + mOrientation(0), + mTexture() { - addRef(); - mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE); + mFlexibleSurfaceCompatibilityRequested = + (attributes.get(EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_FALSE) == EGL_TRUE); + + mDirectComposition = (attributes.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE); mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE); if (mFixedSize) @@ -52,23 +63,55 @@ Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *c mTextureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE); mTextureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE); } + + mOrientation = attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0); + + mDefaultFramebuffer = createDefaultFramebuffer(); + ASSERT(mDefaultFramebuffer != nullptr); } Surface::~Surface() { - if (mTexture) + if (mTexture.get()) { if (mImplementation) { - mImplementation->releaseTexImage(mTexture->id()); + mImplementation->releaseTexImage(EGL_BACK_BUFFER); } - mTexture->releaseTexImage(); - mTexture = NULL; + mTexture->releaseTexImageFromSurface(); + mTexture.set(nullptr); } + SafeDelete(mDefaultFramebuffer); SafeDelete(mImplementation); } +void Surface::setIsCurrent(bool isCurrent) +{ + if (isCurrent) + { + mCurrentCount++; + } + else + { + ASSERT(mCurrentCount > 0); + mCurrentCount--; + if (mCurrentCount == 0 && mDestroyed) + { + delete this; + } + } +} + +void Surface::onDestroy() +{ + mDestroyed = true; + if (mCurrentCount == 0) + { + delete this; + } +} + EGLint Surface::getType() const { return mType; @@ -136,31 +179,83 @@ EGLint Surface::isFixedSize() const EGLint Surface::getWidth() const { - return mFixedSize ? mFixedWidth : mImplementation->getWidth(); + return mFixedSize ? static_cast(mFixedWidth) : mImplementation->getWidth(); } EGLint Surface::getHeight() const { - return mFixedSize ? mFixedHeight : mImplementation->getHeight(); + return mFixedSize ? static_cast(mFixedHeight) : mImplementation->getHeight(); } Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer) { - ASSERT(!mTexture); + ASSERT(!mTexture.get()); - texture->bindTexImage(this); - mTexture = texture; - return mImplementation->bindTexImage(buffer); + texture->bindTexImageFromSurface(this); + mTexture.set(texture); + return mImplementation->bindTexImage(texture, buffer); } Error Surface::releaseTexImage(EGLint buffer) { - ASSERT(mTexture); - gl::Texture *boundTexture = mTexture; - mTexture = NULL; + ASSERT(mTexture.get()); + mTexture->releaseTexImageFromSurface(); + mTexture.set(nullptr); - boundTexture->releaseTexImage(); return mImplementation->releaseTexImage(buffer); } +void Surface::releaseTexImageFromTexture() +{ + ASSERT(mTexture.get()); + mTexture.set(nullptr); +} + +gl::Extents Surface::getAttachmentSize(const gl::FramebufferAttachment::Target & /*target*/) const +{ + return gl::Extents(getWidth(), getHeight(), 1); +} + +GLenum Surface::getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const +{ + const egl::Config *config = getConfig(); + return (target.binding() == GL_BACK ? config->renderTargetFormat : config->depthStencilFormat); +} + +GLsizei Surface::getAttachmentSamples(const gl::FramebufferAttachment::Target &target) const +{ + return getConfig()->samples; +} + +GLuint Surface::getId() const +{ + UNREACHABLE(); + return 0; +} + +gl::Framebuffer *Surface::createDefaultFramebuffer() +{ + gl::Framebuffer *framebuffer = new gl::Framebuffer(mImplementation); + + GLenum drawBufferState = GL_BACK; + framebuffer->setDrawBuffers(1, &drawBufferState); + framebuffer->setReadBuffer(GL_BACK); + + framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(), + this); + + if (mConfig->depthSize > 0) + { + framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), + this); + } + + if (mConfig->stencilSize > 0) + { + framebuffer->setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, + gl::ImageIndex::MakeInvalid(), this); + } + + return framebuffer; +} } diff --git a/src/3rdparty/angle/src/libANGLE/Surface.h b/src/3rdparty/angle/src/libANGLE/Surface.h index 430bf0195d..e110f5da7b 100644 --- a/src/3rdparty/angle/src/libANGLE/Surface.h +++ b/src/3rdparty/angle/src/libANGLE/Surface.h @@ -15,25 +15,23 @@ #include "common/angleutils.h" #include "libANGLE/Error.h" +#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/RefCountObject.h" +#include "libANGLE/renderer/SurfaceImpl.h" namespace gl { +class Framebuffer; class Texture; } -namespace rx -{ -class SurfaceImpl; -} - namespace egl { class AttributeMap; class Display; struct Config; -class Surface final : public RefCountObject +class Surface final : public gl::FramebufferAttachmentObject { public: Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes); @@ -52,6 +50,8 @@ class Surface final : public RefCountObject EGLint isPostSubBufferSupported() const; void setSwapInterval(EGLint interval); + void setIsCurrent(bool isCurrent); + void onDestroy(); const Config *getConfig() const; @@ -64,25 +64,56 @@ class Surface final : public RefCountObject EGLenum getTextureFormat() const; EGLenum getTextureTarget() const; - gl::Texture *getBoundTexture() const { return mTexture; } + gl::Texture *getBoundTexture() const { return mTexture.get(); } + gl::Framebuffer *getDefaultFramebuffer() { return mDefaultFramebuffer; } EGLint isFixedSize() const; + // FramebufferAttachmentObject implementation + gl::Extents getAttachmentSize(const gl::FramebufferAttachment::Target &target) const override; + GLenum getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const override; + GLsizei getAttachmentSamples(const gl::FramebufferAttachment::Target &target) const override; + + void onAttach() override {} + void onDetach() override {} + GLuint getId() const override; + + bool flexibleSurfaceCompatibilityRequested() const + { + return mFlexibleSurfaceCompatibilityRequested; + } + EGLint getOrientation() const { return mOrientation; } + + bool directComposition() const { return mDirectComposition; } + private: virtual ~Surface(); + rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mImplementation; } + + gl::Framebuffer *createDefaultFramebuffer(); + + // ANGLE-only method, used internally + friend class gl::Texture; + void releaseTexImageFromTexture(); rx::SurfaceImpl *mImplementation; + gl::Framebuffer *mDefaultFramebuffer; + int mCurrentCount; + bool mDestroyed; EGLint mType; const egl::Config *mConfig; bool mPostSubBufferRequested; + bool mFlexibleSurfaceCompatibilityRequested; bool mFixedSize; size_t mFixedWidth; size_t mFixedHeight; + bool mDirectComposition; + EGLenum mTextureFormat; EGLenum mTextureTarget; @@ -90,7 +121,9 @@ class Surface final : public RefCountObject EGLenum mRenderBuffer; // Render buffer EGLenum mSwapBehavior; // Buffer swap behavior - gl::Texture *mTexture; + EGLint mOrientation; + + BindingPointer mTexture; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Texture.cpp b/src/3rdparty/angle/src/libANGLE/Texture.cpp index cd4584f694..5ef6762d3d 100644 --- a/src/3rdparty/angle/src/libANGLE/Texture.cpp +++ b/src/3rdparty/angle/src/libANGLE/Texture.cpp @@ -7,14 +7,15 @@ // Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63. #include "libANGLE/Texture.h" -#include "libANGLE/Data.h" -#include "libANGLE/formatutils.h" - -#include "libANGLE/Config.h" -#include "libANGLE/Surface.h" #include "common/mathutil.h" #include "common/utilities.h" +#include "libANGLE/Config.h" +#include "libANGLE/Context.h" +#include "libANGLE/Data.h" +#include "libANGLE/Image.h" +#include "libANGLE/Surface.h" +#include "libANGLE/formatutils.h" namespace gl { @@ -46,14 +47,11 @@ static size_t GetImageDescIndex(GLenum target, size_t level) return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target)) : level; } -unsigned int Texture::mCurrentTextureSerial = 1; - Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target) - : RefCountObject(id), + : egl::ImageSibling(id), mTexture(impl), - mTextureSerial(issueTextureSerial()), - mUsage(GL_NONE), - mImmutableLevelCount(0), + mLabel(), + mTextureState(), mTarget(target), mImageDescs(IMPLEMENTATION_MAX_TEXTURE_LEVELS * (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)), mCompletenessCache(), @@ -71,20 +69,210 @@ Texture::~Texture() SafeDelete(mTexture); } +void Texture::setLabel(const std::string &label) +{ + mLabel = label; +} + +const std::string &Texture::getLabel() const +{ + return mLabel; +} + GLenum Texture::getTarget() const { return mTarget; } +void Texture::setSwizzleRed(GLenum swizzleRed) +{ + mTextureState.swizzleRed = swizzleRed; +} + +GLenum Texture::getSwizzleRed() const +{ + return mTextureState.swizzleRed; +} + +void Texture::setSwizzleGreen(GLenum swizzleGreen) +{ + mTextureState.swizzleGreen = swizzleGreen; +} + +GLenum Texture::getSwizzleGreen() const +{ + return mTextureState.swizzleGreen; +} + +void Texture::setSwizzleBlue(GLenum swizzleBlue) +{ + mTextureState.swizzleBlue = swizzleBlue; +} + +GLenum Texture::getSwizzleBlue() const +{ + return mTextureState.swizzleBlue; +} + +void Texture::setSwizzleAlpha(GLenum swizzleAlpha) +{ + mTextureState.swizzleAlpha = swizzleAlpha; +} + +GLenum Texture::getSwizzleAlpha() const +{ + return mTextureState.swizzleAlpha; +} + +void Texture::setMinFilter(GLenum minFilter) +{ + mTextureState.samplerState.minFilter = minFilter; +} + +GLenum Texture::getMinFilter() const +{ + return mTextureState.samplerState.minFilter; +} + +void Texture::setMagFilter(GLenum magFilter) +{ + mTextureState.samplerState.magFilter = magFilter; +} + +GLenum Texture::getMagFilter() const +{ + return mTextureState.samplerState.magFilter; +} + +void Texture::setWrapS(GLenum wrapS) +{ + mTextureState.samplerState.wrapS = wrapS; +} + +GLenum Texture::getWrapS() const +{ + return mTextureState.samplerState.wrapS; +} + +void Texture::setWrapT(GLenum wrapT) +{ + mTextureState.samplerState.wrapT = wrapT; +} + +GLenum Texture::getWrapT() const +{ + return mTextureState.samplerState.wrapT; +} + +void Texture::setWrapR(GLenum wrapR) +{ + mTextureState.samplerState.wrapR = wrapR; +} + +GLenum Texture::getWrapR() const +{ + return mTextureState.samplerState.wrapR; +} + +void Texture::setMaxAnisotropy(float maxAnisotropy) +{ + mTextureState.samplerState.maxAnisotropy = maxAnisotropy; +} + +float Texture::getMaxAnisotropy() const +{ + return mTextureState.samplerState.maxAnisotropy; +} + +void Texture::setMinLod(GLfloat minLod) +{ + mTextureState.samplerState.minLod = minLod; +} + +GLfloat Texture::getMinLod() const +{ + return mTextureState.samplerState.minLod; +} + +void Texture::setMaxLod(GLfloat maxLod) +{ + mTextureState.samplerState.maxLod = maxLod; +} + +GLfloat Texture::getMaxLod() const +{ + return mTextureState.samplerState.maxLod; +} + +void Texture::setCompareMode(GLenum compareMode) +{ + mTextureState.samplerState.compareMode = compareMode; +} + +GLenum Texture::getCompareMode() const +{ + return mTextureState.samplerState.compareMode; +} + +void Texture::setCompareFunc(GLenum compareFunc) +{ + mTextureState.samplerState.compareFunc = compareFunc; +} + +GLenum Texture::getCompareFunc() const +{ + return mTextureState.samplerState.compareFunc; +} + +const SamplerState &Texture::getSamplerState() const +{ + return mTextureState.samplerState; +} + +void Texture::setBaseLevel(GLuint baseLevel) +{ + mTextureState.baseLevel = baseLevel; +} + +GLuint Texture::getBaseLevel() const +{ + return mTextureState.baseLevel; +} + +void Texture::setMaxLevel(GLuint maxLevel) +{ + mTextureState.maxLevel = maxLevel; +} + +GLuint Texture::getMaxLevel() const +{ + return mTextureState.maxLevel; +} + +bool Texture::getImmutableFormat() const +{ + return mTextureState.immutableFormat; +} + +GLuint Texture::getImmutableLevels() const +{ + return mTextureState.immutableLevels; +} + void Texture::setUsage(GLenum usage) { - mUsage = usage; + mTextureState.usage = usage; getImplementation()->setUsage(usage); } GLenum Texture::getUsage() const { - return mUsage; + return mTextureState.usage; +} + +const TextureState &Texture::getTextureState() const +{ + return mTextureState; } size_t Texture::getWidth(GLenum target, size_t level) const @@ -113,7 +301,7 @@ GLenum Texture::getInternalFormat(GLenum target, size_t level) const bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const { - const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), mTextureState.baseLevel); const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat); if (!mCompletenessCache.cacheValid || mCompletenessCache.samplerState != samplerState || @@ -131,6 +319,11 @@ bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &da return mCompletenessCache.samplerComplete; } +bool Texture::isMipmapComplete() const +{ + return computeMipmapCompleteness(); +} + // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. bool Texture::isCubeComplete() const { @@ -156,76 +349,122 @@ bool Texture::isCubeComplete() const return true; } -unsigned int Texture::getTextureSerial() const +size_t Texture::getMipCompleteLevels() const { - return mTextureSerial; + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0); + if (mTarget == GL_TEXTURE_3D) + { + const int maxDim = std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height), + baseImageDesc.size.depth); + return log2(maxDim) + 1; + } + else + { + return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1; + } } -unsigned int Texture::issueTextureSerial() +egl::Surface *Texture::getBoundSurface() const { - return mCurrentTextureSerial++; + return mBoundSurface; } -bool Texture::isImmutable() const +Error Texture::setImage(Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + const Extents &size, + GLenum format, + GLenum type, + const uint8_t *pixels) { - return (mImmutableLevelCount > 0); -} + ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); -int Texture::immutableLevelCount() -{ - return mImmutableLevelCount; -} + // Release from previous calls to eglBindTexImage, to avoid calling the Impl after + releaseTexImageInternal(); + orphanImages(); -Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type, - const PixelUnpackState &unpack, const uint8_t *pixels) -{ - ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + // Hack: allow nullptr for testing + if (context != nullptr) + { + // Sync the unpack state + context->syncRendererState(context->getState().unpackStateBitMask()); + } + const PixelUnpackState defaultUnpack; + const PixelUnpackState &unpack = context ? context->getState().getUnpackState() : defaultUnpack; Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels); if (error.isError()) { return error; } - releaseTexImage(); - setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type))); return Error(GL_NO_ERROR); } -Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type, - const PixelUnpackState &unpack, const uint8_t *pixels) +Error Texture::setSubImage(Context *context, + GLenum target, + size_t level, + const Box &area, + GLenum format, + GLenum type, + const uint8_t *pixels) { ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + // Sync the unpack state + context->syncRendererState(context->getState().unpackStateBitMask()); + + const PixelUnpackState &unpack = context->getState().getUnpackState(); return mTexture->setSubImage(target, level, area, format, type, unpack, pixels); } -Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, - const PixelUnpackState &unpack, const uint8_t *pixels) +Error Texture::setCompressedImage(Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + const Extents &size, + size_t imageSize, + const uint8_t *pixels) { ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); - Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels); + // Release from previous calls to eglBindTexImage, to avoid calling the Impl after + releaseTexImageInternal(); + orphanImages(); + + // Sync the unpack state + context->syncRendererState(context->getState().unpackStateBitMask()); + + const PixelUnpackState &unpack = context->getState().getUnpackState(); + Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, imageSize, pixels); if (error.isError()) { return error; } - releaseTexImage(); - setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE))); return Error(GL_NO_ERROR); } -Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format, - const PixelUnpackState &unpack, const uint8_t *pixels) +Error Texture::setCompressedSubImage(Context *context, + GLenum target, + size_t level, + const Box &area, + GLenum format, + size_t imageSize, + const uint8_t *pixels) { ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); - return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels); + // Sync the unpack state + context->syncRendererState(context->getState().unpackStateBitMask()); + + const PixelUnpackState &unpack = context->getState().getUnpackState(); + return mTexture->setCompressedSubImage(target, level, area, format, unpack, imageSize, pixels); } Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat, @@ -233,14 +472,16 @@ Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceAre { ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target))); + // Release from previous calls to eglBindTexImage, to avoid calling the Impl after + releaseTexImageInternal(); + orphanImages(); + Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source); if (error.isError()) { return error; } - releaseTexImage(); - setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1), GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE))); @@ -259,32 +500,42 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c { ASSERT(target == mTarget); + // Release from previous calls to eglBindTexImage, to avoid calling the Impl after + releaseTexImageInternal(); + orphanImages(); + Error error = mTexture->setStorage(target, levels, internalFormat, size); if (error.isError()) { return error; } - releaseTexImage(); - - mImmutableLevelCount = levels; + mTextureState.immutableFormat = true; + mTextureState.immutableLevels = static_cast(levels); clearImageDescs(); setImageDescChain(levels, size, internalFormat); return Error(GL_NO_ERROR); } - Error Texture::generateMipmaps() { - Error error = mTexture->generateMipmaps(); + // Release from previous calls to eglBindTexImage, to avoid calling the Impl after + releaseTexImageInternal(); + + // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture + // is not mip complete. + if (!isMipmapComplete()) + { + orphanImages(); + } + + Error error = mTexture->generateMipmaps(mTextureState); if (error.isError()) { return error; } - releaseTexImage(); - const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0); size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1; setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat); @@ -294,16 +545,17 @@ Error Texture::generateMipmaps() void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat) { - for (size_t level = 0; level < levels; level++) + for (int level = 0; level < static_cast(levels); level++) { - Extents levelSize(std::max(baseSize.width >> level, 1), - std::max(baseSize.height >> level, 1), - (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth : std::max(baseSize.depth >> level, 1)); + Extents levelSize( + std::max(baseSize.width >> level, 1), std::max(baseSize.height >> level, 1), + (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth + : std::max(baseSize.depth >> level, 1)); ImageDesc levelInfo(levelSize, sizedInternalFormat); if (mTarget == GL_TEXTURE_CUBE_MAP) { - for (size_t face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++) + for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++) { setImageDesc(face, level, levelInfo); } @@ -316,7 +568,7 @@ void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInt } Texture::ImageDesc::ImageDesc() - : size(0, 0, 0), internalFormat(GL_NONE) + : ImageDesc(Extents(0, 0, 0), GL_NONE) { } @@ -355,11 +607,15 @@ void Texture::clearImageDescs() mCompletenessCache.cacheValid = false; } -void Texture::bindTexImage(egl::Surface *surface) +void Texture::bindTexImageFromSurface(egl::Surface *surface) { ASSERT(surface); - releaseTexImage(); + if (mBoundSurface) + { + releaseTexImageFromSurface(); + } + mTexture->bindTexImage(surface); mBoundSurface = surface; @@ -370,40 +626,65 @@ void Texture::bindTexImage(egl::Surface *surface) setImageDesc(mTarget, 0, desc); } -void Texture::releaseTexImage() +void Texture::releaseTexImageFromSurface() +{ + ASSERT(mBoundSurface); + mBoundSurface = nullptr; + mTexture->releaseTexImage(); + + // Erase the image info for level 0 + ASSERT(mTarget == GL_TEXTURE_2D); + clearImageDesc(mTarget, 0); +} + +void Texture::releaseTexImageInternal() { if (mBoundSurface) { - mBoundSurface = NULL; - mTexture->releaseTexImage(); + // Notify the surface + mBoundSurface->releaseTexImageFromTexture(); - // Erase the image info for level 0 - ASSERT(mTarget == GL_TEXTURE_2D); - clearImageDesc(mTarget, 0); + // Then, call the same method as from the surface + releaseTexImageFromSurface(); } } -GLenum Texture::getBaseImageTarget() const +Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget) { - return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget; -} + ASSERT(target == mTarget); + ASSERT(target == GL_TEXTURE_2D); -size_t Texture::getExpectedMipLevels() const -{ - const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0); - if (mTarget == GL_TEXTURE_3D) - { - return log2(std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height), baseImageDesc.size.depth)) + 1; - } - else + // Release from previous calls to eglBindTexImage, to avoid calling the Impl after + releaseTexImageInternal(); + orphanImages(); + + Error error = mTexture->setEGLImageTarget(target, imageTarget); + if (error.isError()) { - return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1; + return error; } + + setTargetImage(imageTarget); + + Extents size(static_cast(imageTarget->getWidth()), + static_cast(imageTarget->getHeight()), 1); + GLenum internalFormat = imageTarget->getInternalFormat(); + GLenum type = GetInternalFormatInfo(internalFormat).type; + + clearImageDescs(); + setImageDesc(target, 0, ImageDesc(size, GetSizedInternalFormat(internalFormat, type))); + + return Error(GL_NO_ERROR); +} + +GLenum Texture::getBaseImageTarget() const +{ + return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget; } bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const { - const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), mTextureState.baseLevel); if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0) { return false; @@ -440,7 +721,7 @@ bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const } } - if (!computeMipmapCompleteness(samplerState)) + if (!computeMipmapCompleteness()) { return false; } @@ -474,19 +755,19 @@ bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const return true; } -bool Texture::computeMipmapCompleteness(const gl::SamplerState &samplerState) const +bool Texture::computeMipmapCompleteness() const { - size_t expectedMipLevels = getExpectedMipLevels(); + size_t expectedMipLevels = getMipCompleteLevels(); - size_t maxLevel = std::min(expectedMipLevels, samplerState.maxLevel + 1); + size_t maxLevel = std::min(expectedMipLevels, mTextureState.maxLevel + 1); - for (size_t level = samplerState.baseLevel; level < maxLevel; level++) + for (size_t level = mTextureState.baseLevel; level < maxLevel; level++) { if (mTarget == GL_TEXTURE_CUBE_MAP) { for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++) { - if (!computeLevelCompleteness(face, level, samplerState)) + if (!computeLevelCompleteness(face, level)) { return false; } @@ -494,7 +775,7 @@ bool Texture::computeMipmapCompleteness(const gl::SamplerState &samplerState) co } else { - if (!computeLevelCompleteness(mTarget, level, samplerState)) + if (!computeLevelCompleteness(mTarget, level)) { return false; } @@ -504,47 +785,48 @@ bool Texture::computeMipmapCompleteness(const gl::SamplerState &samplerState) co return true; } - -bool Texture::computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const +bool Texture::computeLevelCompleteness(GLenum target, size_t level) const { ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS); - if (isImmutable()) + if (mTextureState.immutableFormat) { return true; } - const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel); + const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), mTextureState.baseLevel); if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0) { return false; } - // The base image level is complete if the width and height are positive - if (level == 0) + const ImageDesc &levelImageDesc = getImageDesc(target, level); + if (levelImageDesc.size.width == 0 || levelImageDesc.size.height == 0 || + levelImageDesc.size.depth == 0) { - return true; + return false; } - const ImageDesc &levelImageDesc = getImageDesc(target, level); if (levelImageDesc.internalFormat != baseImageDesc.internalFormat) { return false; } - if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> level)) + ASSERT(level >= mTextureState.baseLevel); + const size_t relativeLevel = level - mTextureState.baseLevel; + if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> relativeLevel)) { return false; } - if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> level)) + if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> relativeLevel)) { return false; } if (mTarget == GL_TEXTURE_3D) { - if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> level)) + if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> relativeLevel)) { return false; } @@ -570,4 +852,34 @@ Texture::SamplerCompletenessCache::SamplerCompletenessCache() { } +Extents Texture::getAttachmentSize(const gl::FramebufferAttachment::Target &target) const +{ + return getImageDesc(target.textureIndex().type, target.textureIndex().mipIndex).size; +} + +GLenum Texture::getAttachmentInternalFormat(const gl::FramebufferAttachment::Target &target) const +{ + return getInternalFormat(target.textureIndex().type, target.textureIndex().mipIndex); +} + +GLsizei Texture::getAttachmentSamples(const gl::FramebufferAttachment::Target &/*target*/) const +{ + // Multisample textures not currently supported + return 0; +} + +void Texture::onAttach() +{ + addRef(); +} + +void Texture::onDetach() +{ + release(); +} + +GLuint Texture::getId() const +{ + return id(); +} } diff --git a/src/3rdparty/angle/src/libANGLE/Texture.h b/src/3rdparty/angle/src/libANGLE/Texture.h index b5a0717713..7ca8a456fc 100644 --- a/src/3rdparty/angle/src/libANGLE/Texture.h +++ b/src/3rdparty/angle/src/libANGLE/Texture.h @@ -9,17 +9,19 @@ #ifndef LIBANGLE_TEXTURE_H_ #define LIBANGLE_TEXTURE_H_ +#include +#include + +#include "angle_gl.h" #include "common/debug.h" -#include "libANGLE/RefCountObject.h" -#include "libANGLE/angletypes.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Debug.h" #include "libANGLE/Constants.h" +#include "libANGLE/Error.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Image.h" +#include "libANGLE/angletypes.h" #include "libANGLE/renderer/TextureImpl.h" -#include "libANGLE/Caps.h" - -#include "angle_gl.h" - -#include -#include namespace egl { @@ -28,81 +30,172 @@ class Surface; namespace gl { +class Context; class Framebuffer; struct Data; -bool IsMipmapFiltered(const gl::SamplerState &samplerState); +bool IsMipmapFiltered(const SamplerState &samplerState); -class Texture final : public RefCountObject +class Texture final : public egl::ImageSibling, + public FramebufferAttachmentObject, + public LabeledObject { public: Texture(rx::TextureImpl *impl, GLuint id, GLenum target); + ~Texture() override; - virtual ~Texture(); + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; GLenum getTarget() const; - const SamplerState &getSamplerState() const { return mSamplerState; } - SamplerState &getSamplerState() { return mSamplerState; } + void setSwizzleRed(GLenum swizzleRed); + GLenum getSwizzleRed() const; - void setUsage(GLenum usage); - GLenum getUsage() const; + void setSwizzleGreen(GLenum swizzleGreen); + GLenum getSwizzleGreen() const; - size_t getWidth(GLenum target, size_t level) const; - size_t getHeight(GLenum target, size_t level) const; - size_t getDepth(GLenum target, size_t level) const; - GLenum getInternalFormat(GLenum target, size_t level) const; + void setSwizzleBlue(GLenum swizzleBlue); + GLenum getSwizzleBlue() const; - bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const; - bool isCubeComplete() const; + void setSwizzleAlpha(GLenum swizzleAlpha); + GLenum getSwizzleAlpha() const; + + void setMinFilter(GLenum minFilter); + GLenum getMinFilter() const; - virtual Error setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type, - const PixelUnpackState &unpack, const uint8_t *pixels); - virtual Error setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type, - const PixelUnpackState &unpack, const uint8_t *pixels); + void setMagFilter(GLenum magFilter); + GLenum getMagFilter() const; - virtual Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, - const PixelUnpackState &unpack, const uint8_t *pixels); - virtual Error setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format, - const PixelUnpackState &unpack, const uint8_t *pixels); + void setWrapS(GLenum wrapS); + GLenum getWrapS() const; - virtual Error copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat, - const Framebuffer *source); - virtual Error copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea, - const Framebuffer *source); + void setWrapT(GLenum wrapT); + GLenum getWrapT() const; - virtual Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size); + void setWrapR(GLenum wrapR); + GLenum getWrapR() const; - virtual Error generateMipmaps(); + void setMaxAnisotropy(float maxAnisotropy); + float getMaxAnisotropy() const; - // Texture serials provide a unique way of identifying a Texture that isn't a raw pointer. - // "id" is not good enough, as Textures can be deleted, then re-allocated with the same id. - unsigned int getTextureSerial() const; + void setMinLod(GLfloat minLod); + GLfloat getMinLod() const; - bool isImmutable() const; - GLsizei immutableLevelCount(); + void setMaxLod(GLfloat maxLod); + GLfloat getMaxLod() const; - void bindTexImage(egl::Surface *surface); - void releaseTexImage(); + void setCompareMode(GLenum compareMode); + GLenum getCompareMode() const; + + void setCompareFunc(GLenum compareFunc); + GLenum getCompareFunc() const; + + const SamplerState &getSamplerState() const; + + void setBaseLevel(GLuint baseLevel); + GLuint getBaseLevel() const; + + void setMaxLevel(GLuint maxLevel); + GLuint getMaxLevel() const; + + bool getImmutableFormat() const; + + GLuint getImmutableLevels() const; + + void setUsage(GLenum usage); + GLenum getUsage() const; + + const TextureState &getTextureState() const; + + size_t getWidth(GLenum target, size_t level) const; + size_t getHeight(GLenum target, size_t level) const; + size_t getDepth(GLenum target, size_t level) const; + GLenum getInternalFormat(GLenum target, size_t level) const; + + bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const; + bool isMipmapComplete() const; + bool isCubeComplete() const; + size_t getMipCompleteLevels() const; + + Error setImage(Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + const Extents &size, + GLenum format, + GLenum type, + const uint8_t *pixels); + Error setSubImage(Context *context, + GLenum target, + size_t level, + const Box &area, + GLenum format, + GLenum type, + const uint8_t *pixels); + + Error setCompressedImage(Context *context, + GLenum target, + size_t level, + GLenum internalFormat, + const Extents &size, + size_t imageSize, + const uint8_t *pixels); + Error setCompressedSubImage(Context *context, + GLenum target, + size_t level, + const Box &area, + GLenum format, + size_t imageSize, + const uint8_t *pixels); + + Error copyImage(GLenum target, + size_t level, + const Rectangle &sourceArea, + GLenum internalFormat, + const Framebuffer *source); + Error copySubImage(GLenum target, + size_t level, + const Offset &destOffset, + const Rectangle &sourceArea, + const Framebuffer *source); + + Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size); + + Error setEGLImageTarget(GLenum target, egl::Image *imageTarget); + + Error generateMipmaps(); + + egl::Surface *getBoundSurface() const; rx::TextureImpl *getImplementation() { return mTexture; } const rx::TextureImpl *getImplementation() const { return mTexture; } - static const GLuint INCOMPLETE_TEXTURE_ID = static_cast(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager. + // FramebufferAttachmentObject implementation + Extents getAttachmentSize(const FramebufferAttachment::Target &target) const override; + GLenum getAttachmentInternalFormat(const FramebufferAttachment::Target &target) const override; + GLsizei getAttachmentSamples(const FramebufferAttachment::Target &target) const override; + + void onAttach() override; + void onDetach() override; + GLuint getId() const override; private: - static unsigned int issueTextureSerial(); + rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override { return mTexture; } + + // ANGLE-only method, used internally + friend class egl::Surface; + void bindTexImageFromSurface(egl::Surface *surface); + void releaseTexImageFromSurface(); rx::TextureImpl *mTexture; - SamplerState mSamplerState; - GLenum mUsage; + std::string mLabel; - GLsizei mImmutableLevelCount; + TextureState mTextureState; GLenum mTarget; - struct ImageDesc { Extents size; @@ -112,21 +205,18 @@ class Texture final : public RefCountObject ImageDesc(const Extents &size, GLenum internalFormat); }; - const unsigned int mTextureSerial; - static unsigned int mCurrentTextureSerial; - GLenum getBaseImageTarget() const; - size_t getExpectedMipLevels() const; bool computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const; - bool computeMipmapCompleteness(const gl::SamplerState &samplerState) const; - bool computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const; + bool computeMipmapCompleteness() const; + bool computeLevelCompleteness(GLenum target, size_t level) const; const ImageDesc &getImageDesc(GLenum target, size_t level) const; void setImageDesc(GLenum target, size_t level, const ImageDesc &desc); void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat); void clearImageDesc(GLenum target, size_t level); void clearImageDescs(); + void releaseTexImageInternal(); std::vector mImageDescs; diff --git a/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp index 6effaca976..b7961971d0 100644 --- a/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp +++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp @@ -5,67 +5,146 @@ // #include "libANGLE/TransformFeedback.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/Caps.h" #include "libANGLE/renderer/TransformFeedbackImpl.h" namespace gl { -TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id) +TransformFeedback::TransformFeedback(rx::TransformFeedbackImpl *impl, GLuint id, const Caps &caps) : RefCountObject(id), - mTransformFeedback(impl), - mStarted(GL_FALSE), + mImplementation(impl), + mLabel(), + mActive(false), mPrimitiveMode(GL_NONE), - mPaused(GL_FALSE) + mPaused(false), + mGenericBuffer(), + mIndexedBuffers(caps.maxTransformFeedbackSeparateAttributes) { ASSERT(impl != NULL); } TransformFeedback::~TransformFeedback() { - SafeDelete(mTransformFeedback); + mGenericBuffer.set(nullptr); + for (size_t i = 0; i < mIndexedBuffers.size(); i++) + { + mIndexedBuffers[i].set(nullptr); + } + + SafeDelete(mImplementation); } -void TransformFeedback::start(GLenum primitiveMode) +void TransformFeedback::setLabel(const std::string &label) { - mStarted = GL_TRUE; - mPrimitiveMode = primitiveMode; - mPaused = GL_FALSE; - mTransformFeedback->begin(primitiveMode); + mLabel = label; } -void TransformFeedback::stop() +const std::string &TransformFeedback::getLabel() const { - mStarted = GL_FALSE; - mPrimitiveMode = GL_NONE; - mPaused = GL_FALSE; - mTransformFeedback->end(); + return mLabel; } -GLboolean TransformFeedback::isStarted() const +void TransformFeedback::begin(GLenum primitiveMode) { - return mStarted; + mActive = true; + mPrimitiveMode = primitiveMode; + mPaused = false; + mImplementation->begin(primitiveMode); } -GLenum TransformFeedback::getDrawMode() const +void TransformFeedback::end() { - return mPrimitiveMode; + mActive = false; + mPrimitiveMode = GL_NONE; + mPaused = false; + mImplementation->end(); } void TransformFeedback::pause() { - mPaused = GL_TRUE; - mTransformFeedback->pause(); + mPaused = true; + mImplementation->pause(); } void TransformFeedback::resume() { - mPaused = GL_FALSE; - mTransformFeedback->resume(); + mPaused = false; + mImplementation->resume(); +} + +bool TransformFeedback::isActive() const +{ + return mActive; } -GLboolean TransformFeedback::isPaused() const +bool TransformFeedback::isPaused() const { return mPaused; } +GLenum TransformFeedback::getPrimitiveMode() const +{ + return mPrimitiveMode; +} + +void TransformFeedback::bindGenericBuffer(Buffer *buffer) +{ + mGenericBuffer.set(buffer); + mImplementation->bindGenericBuffer(mGenericBuffer); +} + +void TransformFeedback::detachBuffer(GLuint bufferName) +{ + for (size_t index = 0; index < mIndexedBuffers.size(); index++) + { + if (mIndexedBuffers[index].id() == bufferName) + { + mIndexedBuffers[index].set(nullptr); + mImplementation->bindIndexedBuffer(index, mIndexedBuffers[index]); + } + } + + if (mGenericBuffer.id() == bufferName) + { + mGenericBuffer.set(nullptr); + mImplementation->bindGenericBuffer(mGenericBuffer); + } +} + +const BindingPointer &TransformFeedback::getGenericBuffer() const +{ + return mGenericBuffer; +} + +void TransformFeedback::bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size) +{ + ASSERT(index < mIndexedBuffers.size()); + mIndexedBuffers[index].set(buffer, offset, size); + mImplementation->bindIndexedBuffer(index, mIndexedBuffers[index]); +} + +const OffsetBindingPointer &TransformFeedback::getIndexedBuffer(size_t index) const +{ + ASSERT(index < mIndexedBuffers.size()); + return mIndexedBuffers[index]; +} + +size_t TransformFeedback::getIndexedBufferCount() const +{ + return mIndexedBuffers.size(); +} + +rx::TransformFeedbackImpl *TransformFeedback::getImplementation() +{ + return mImplementation; +} + +const rx::TransformFeedbackImpl *TransformFeedback::getImplementation() const +{ + return mImplementation; +} + } diff --git a/src/3rdparty/angle/src/libANGLE/TransformFeedback.h b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h index 7673db93ff..098e4ea4d6 100644 --- a/src/3rdparty/angle/src/libANGLE/TransformFeedback.h +++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h @@ -10,6 +10,7 @@ #include "libANGLE/RefCountObject.h" #include "common/angleutils.h" +#include "libANGLE/Debug.h" #include "angle_gl.h" @@ -20,29 +21,50 @@ class TransformFeedbackImpl; namespace gl { +class Buffer; +struct Caps; -class TransformFeedback : public RefCountObject +class TransformFeedback final : public RefCountObject, public LabeledObject { public: - TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id); + TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id, const Caps &caps); virtual ~TransformFeedback(); - void start(GLenum primitiveMode); - void stop(); - GLboolean isStarted() const; - - GLenum getDrawMode() const; + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + void begin(GLenum primitiveMode); + void end(); void pause(); void resume(); - GLboolean isPaused() const; + + bool isActive() const; + bool isPaused() const; + GLenum getPrimitiveMode() const; + + void bindGenericBuffer(Buffer *buffer); + const BindingPointer &getGenericBuffer() const; + + void bindIndexedBuffer(size_t index, Buffer *buffer, size_t offset, size_t size); + const OffsetBindingPointer &getIndexedBuffer(size_t index) const; + size_t getIndexedBufferCount() const; + + void detachBuffer(GLuint bufferName); + + rx::TransformFeedbackImpl *getImplementation(); + const rx::TransformFeedbackImpl *getImplementation() const; private: - rx::TransformFeedbackImpl* mTransformFeedback; + rx::TransformFeedbackImpl* mImplementation; - GLboolean mStarted; + std::string mLabel; + + bool mActive; GLenum mPrimitiveMode; - GLboolean mPaused; + bool mPaused; + + BindingPointer mGenericBuffer; + std::vector> mIndexedBuffers; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Uniform.cpp b/src/3rdparty/angle/src/libANGLE/Uniform.cpp index f161b9d6bd..bfae3c014f 100644 --- a/src/3rdparty/angle/src/libANGLE/Uniform.cpp +++ b/src/3rdparty/angle/src/libANGLE/Uniform.cpp @@ -13,55 +13,51 @@ namespace gl { -LinkedUniform::LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, - const int blockIndex, const sh::BlockMemberInfo &blockInfo) - : type(type), - precision(precision), - name(name), - arraySize(arraySize), - blockIndex(blockIndex), - blockInfo(blockInfo), - data(NULL), - dirty(true), - psRegisterIndex(GL_INVALID_INDEX), - vsRegisterIndex(GL_INVALID_INDEX), - registerCount(0), - registerElement(0) -{ - // We use data storage for default block uniforms to cache values that are sent to D3D during rendering - // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only) - if (isInDefaultBlock()) - { - size_t bytes = dataSize(); - data = new unsigned char[bytes]; - memset(data, 0, bytes); - registerCount = VariableRowCount(type) * elementCount(); - } +LinkedUniform::LinkedUniform() + : blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo()) +{ } -LinkedUniform::~LinkedUniform() +LinkedUniform::LinkedUniform(GLenum typeIn, + GLenum precisionIn, + const std::string &nameIn, + unsigned int arraySizeIn, + const int blockIndexIn, + const sh::BlockMemberInfo &blockInfoIn) + : blockIndex(blockIndexIn), blockInfo(blockInfoIn) { - delete[] data; + type = typeIn; + precision = precisionIn; + name = nameIn; + arraySize = arraySizeIn; } -bool LinkedUniform::isArray() const +LinkedUniform::LinkedUniform(const sh::Uniform &uniform) + : sh::Uniform(uniform), blockIndex(-1), blockInfo(sh::BlockMemberInfo::getDefaultBlockInfo()) { - return arraySize > 0; } -unsigned int LinkedUniform::elementCount() const +LinkedUniform::LinkedUniform(const LinkedUniform &uniform) + : sh::Uniform(uniform), blockIndex(uniform.blockIndex), blockInfo(uniform.blockInfo) { - return arraySize > 0 ? arraySize : 1; + // This function is not intended to be called during runtime. + ASSERT(uniform.mLazyData.empty()); } -bool LinkedUniform::isReferencedByVertexShader() const +LinkedUniform &LinkedUniform::operator=(const LinkedUniform &uniform) { - return vsRegisterIndex != GL_INVALID_INDEX; + // This function is not intended to be called during runtime. + ASSERT(uniform.mLazyData.empty()); + + sh::Uniform::operator=(uniform); + blockIndex = uniform.blockIndex; + blockInfo = uniform.blockInfo; + + return *this; } -bool LinkedUniform::isReferencedByFragmentShader() const +LinkedUniform::~LinkedUniform() { - return psRegisterIndex != GL_INVALID_INDEX; } bool LinkedUniform::isInDefaultBlock() const @@ -72,7 +68,30 @@ bool LinkedUniform::isInDefaultBlock() const size_t LinkedUniform::dataSize() const { ASSERT(type != GL_STRUCT_ANGLEX); - return VariableInternalSize(type) * elementCount(); + if (mLazyData.empty()) + { + mLazyData.resize(VariableExternalSize(type) * elementCount()); + ASSERT(!mLazyData.empty()); + } + + return mLazyData.size(); +} + +uint8_t *LinkedUniform::data() +{ + if (mLazyData.empty()) + { + // dataSize() will init the data store. + size_t size = dataSize(); + memset(mLazyData.data(), 0, size); + } + + return mLazyData.data(); +} + +const uint8_t *LinkedUniform::data() const +{ + return const_cast(this)->data(); } bool LinkedUniform::isSampler() const @@ -80,28 +99,51 @@ bool LinkedUniform::isSampler() const return IsSamplerType(type); } -UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize) - : name(name), - elementIndex(elementIndex), - dataSize(dataSize), - psRegisterIndex(GL_INVALID_INDEX), - vsRegisterIndex(GL_INVALID_INDEX) +bool LinkedUniform::isField() const { + return name.find('.') != std::string::npos; } -bool UniformBlock::isArrayElement() const +size_t LinkedUniform::getElementSize() const { - return elementIndex != GL_INVALID_INDEX; + return VariableExternalSize(type); } -bool UniformBlock::isReferencedByVertexShader() const +uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex) { - return vsRegisterIndex != GL_INVALID_INDEX; + ASSERT((!isArray() && elementIndex == 0) || (isArray() && elementIndex < arraySize)); + return data() + getElementSize() * elementIndex; } -bool UniformBlock::isReferencedByFragmentShader() const +const uint8_t *LinkedUniform::getDataPtrToElement(size_t elementIndex) const { - return psRegisterIndex != GL_INVALID_INDEX; + return const_cast(this)->getDataPtrToElement(elementIndex); } +UniformBlock::UniformBlock() + : isArray(false), arrayElement(0), dataSize(0), vertexStaticUse(false), fragmentStaticUse(false) +{ +} + +UniformBlock::UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn) + : name(nameIn), + isArray(isArrayIn), + arrayElement(arrayElementIn), + dataSize(0), + vertexStaticUse(false), + fragmentStaticUse(false) +{ +} + +std::string UniformBlock::nameWithArrayIndex() const +{ + std::stringstream fullNameStr; + fullNameStr << name; + if (isArray) + { + fullNameStr << "[" << arrayElement << "]"; + } + + return fullNameStr.str(); +} } diff --git a/src/3rdparty/angle/src/libANGLE/Uniform.h b/src/3rdparty/angle/src/libANGLE/Uniform.h index dcf30f23cc..e62a583f3d 100644 --- a/src/3rdparty/angle/src/libANGLE/Uniform.h +++ b/src/3rdparty/angle/src/libANGLE/Uniform.h @@ -12,6 +12,7 @@ #include "angle_gl.h" #include "common/debug.h" +#include "common/MemoryBuffer.h" #include "compiler/translator/blocklayout.h" #include "libANGLE/angletypes.h" @@ -19,57 +20,51 @@ namespace gl { // Helper struct representing a single shader uniform -struct LinkedUniform : angle::NonCopyable +struct LinkedUniform : public sh::Uniform { + LinkedUniform(); LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo); - + LinkedUniform(const sh::Uniform &uniform); + LinkedUniform(const LinkedUniform &uniform); + LinkedUniform &operator=(const LinkedUniform &uniform); ~LinkedUniform(); - bool isArray() const; - unsigned int elementCount() const; - bool isReferencedByVertexShader() const; - bool isReferencedByFragmentShader() const; - bool isInDefaultBlock() const; size_t dataSize() const; + uint8_t *data(); + const uint8_t *data() const; bool isSampler() const; + bool isInDefaultBlock() const; + bool isField() const; + size_t getElementSize() const; + uint8_t *getDataPtrToElement(size_t elementIndex); + const uint8_t *getDataPtrToElement(size_t elementIndex) const; - const GLenum type; - const GLenum precision; - const std::string name; - const unsigned int arraySize; - const int blockIndex; - const sh::BlockMemberInfo blockInfo; - - unsigned char *data; - bool dirty; - - unsigned int psRegisterIndex; - unsigned int vsRegisterIndex; - unsigned int registerCount; + int blockIndex; + sh::BlockMemberInfo blockInfo; - // Register "elements" are used for uniform structs in ES3, to appropriately identify single uniforms - // inside aggregate types, which are packed according C-like structure rules. - unsigned int registerElement; + private: + mutable rx::MemoryBuffer mLazyData; }; // Helper struct representing a single shader uniform block -struct UniformBlock : angle::NonCopyable +struct UniformBlock { - // use GL_INVALID_INDEX for non-array elements - UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize); + UniformBlock(); + UniformBlock(const std::string &nameIn, bool isArrayIn, unsigned int arrayElementIn); + UniformBlock(const UniformBlock &other) = default; + UniformBlock &operator=(const UniformBlock &other) = default; - bool isArrayElement() const; - bool isReferencedByVertexShader() const; - bool isReferencedByFragmentShader() const; + std::string nameWithArrayIndex() const; - const std::string name; - const unsigned int elementIndex; - const unsigned int dataSize; + std::string name; + bool isArray; + unsigned int arrayElement; + unsigned int dataSize; - std::vector memberUniformIndexes; + bool vertexStaticUse; + bool fragmentStaticUse; - unsigned int psRegisterIndex; - unsigned int vsRegisterIndex; + std::vector memberUniformIndexes; }; } diff --git a/src/3rdparty/angle/src/libANGLE/Version.h b/src/3rdparty/angle/src/libANGLE/Version.h new file mode 100644 index 0000000000..72dfbb6b8d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Version.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Version.h: Encapsulation of a GL version. + +#ifndef LIBANGLE_VERSION_H_ +#define LIBANGLE_VERSION_H_ + +#include + +namespace gl +{ + +struct Version +{ + Version(); + Version(GLuint major, GLuint minor); + + GLuint major; + GLuint minor; +}; + +bool operator>=(const Version &a, const Version &b); +bool operator<(const Version &a, const Version &b); + +} + +#include "Version.inl" + +#endif // LIBANGLE_VERSION_H_ diff --git a/src/3rdparty/angle/src/libANGLE/Version.inl b/src/3rdparty/angle/src/libANGLE/Version.inl new file mode 100644 index 0000000000..f64f7cae77 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/Version.inl @@ -0,0 +1,33 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Version.inl: Encapsulation of a GL version. + +namespace gl +{ + +inline Version::Version() + : Version(0, 0) +{ +} + +inline Version::Version(GLuint major_, GLuint minor_) +{ + major = major_; + minor = minor_; +} + +inline bool operator>=(const Version &a, const Version &b) +{ + return a.major > b.major || (a.major == b.major && a.minor >= b.minor); +} + +inline bool operator<(const Version &a, const Version &b) +{ + return !(a >= b); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/VertexArray.cpp b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp index f0aded905d..8d51e9b469 100644 --- a/src/3rdparty/angle/src/libANGLE/VertexArray.cpp +++ b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp @@ -8,28 +8,36 @@ #include "libANGLE/VertexArray.h" #include "libANGLE/Buffer.h" +#include "libANGLE/renderer/ImplFactory.h" #include "libANGLE/renderer/VertexArrayImpl.h" namespace gl { -VertexArray::VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs) - : mId(id), - mVertexArray(impl), - mVertexAttributes(maxAttribs) +VertexArray::Data::Data(size_t maxAttribs) + : mLabel(), mVertexAttributes(maxAttribs), mMaxEnabledAttribute(0) { - ASSERT(impl != NULL); } -VertexArray::~VertexArray() +VertexArray::Data::~Data() { - SafeDelete(mVertexArray); - for (size_t i = 0; i < getMaxAttribs(); i++) { - mVertexAttributes[i].buffer.set(NULL); + mVertexAttributes[i].buffer.set(nullptr); } - mElementArrayBuffer.set(NULL); + mElementArrayBuffer.set(nullptr); +} + +VertexArray::VertexArray(rx::ImplFactory *factory, GLuint id, size_t maxAttribs) + : mId(id), + mVertexArray(factory->createVertexArray(mData)), + mData(maxAttribs) +{ +} + +VertexArray::~VertexArray() +{ + SafeDelete(mVertexArray); } GLuint VertexArray::id() const @@ -37,65 +45,96 @@ GLuint VertexArray::id() const return mId; } +void VertexArray::setLabel(const std::string &label) +{ + mData.mLabel = label; +} + +const std::string &VertexArray::getLabel() const +{ + return mData.mLabel; +} + void VertexArray::detachBuffer(GLuint bufferName) { for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++) { - if (mVertexAttributes[attribute].buffer.id() == bufferName) + if (mData.mVertexAttributes[attribute].buffer.id() == bufferName) { - mVertexAttributes[attribute].buffer.set(NULL); + mData.mVertexAttributes[attribute].buffer.set(nullptr); } } - if (mElementArrayBuffer.id() == bufferName) + if (mData.mElementArrayBuffer.id() == bufferName) { - mElementArrayBuffer.set(NULL); + mData.mElementArrayBuffer.set(nullptr); } } -const VertexAttribute& VertexArray::getVertexAttribute(size_t attributeIndex) const +const VertexAttribute &VertexArray::getVertexAttribute(size_t attributeIndex) const { ASSERT(attributeIndex < getMaxAttribs()); - return mVertexAttributes[attributeIndex]; + return mData.mVertexAttributes[attributeIndex]; } -const std::vector &VertexArray::getVertexAttributes() const -{ - return mVertexAttributes; -} - -void VertexArray::setVertexAttribDivisor(GLuint index, GLuint divisor) +void VertexArray::setVertexAttribDivisor(size_t index, GLuint divisor) { ASSERT(index < getMaxAttribs()); - mVertexAttributes[index].divisor = divisor; - mVertexArray->setAttributeDivisor(index, divisor); + mData.mVertexAttributes[index].divisor = divisor; + mDirtyBits.set(DIRTY_BIT_ATTRIB_0_DIVISOR + index); } -void VertexArray::enableAttribute(unsigned int attributeIndex, bool enabledState) +void VertexArray::enableAttribute(size_t attributeIndex, bool enabledState) { ASSERT(attributeIndex < getMaxAttribs()); - mVertexAttributes[attributeIndex].enabled = enabledState; - mVertexArray->enableAttribute(attributeIndex, enabledState); + mData.mVertexAttributes[attributeIndex].enabled = enabledState; + mDirtyBits.set(DIRTY_BIT_ATTRIB_0_ENABLED + attributeIndex); + + // Update state cache + if (enabledState) + { + mData.mMaxEnabledAttribute = std::max(attributeIndex + 1, mData.mMaxEnabledAttribute); + } + else if (mData.mMaxEnabledAttribute == attributeIndex + 1) + { + while (mData.mMaxEnabledAttribute > 0 && + !mData.mVertexAttributes[mData.mMaxEnabledAttribute - 1].enabled) + { + --mData.mMaxEnabledAttribute; + } + } } -void VertexArray::setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, +void VertexArray::setAttributeState(size_t attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, bool normalized, bool pureInteger, GLsizei stride, const void *pointer) { ASSERT(attributeIndex < getMaxAttribs()); - mVertexAttributes[attributeIndex].buffer.set(boundBuffer); - mVertexAttributes[attributeIndex].size = size; - mVertexAttributes[attributeIndex].type = type; - mVertexAttributes[attributeIndex].normalized = normalized; - mVertexAttributes[attributeIndex].pureInteger = pureInteger; - mVertexAttributes[attributeIndex].stride = stride; - mVertexAttributes[attributeIndex].pointer = pointer; - mVertexArray->setAttribute(attributeIndex, mVertexAttributes[attributeIndex]); + + VertexAttribute *attrib = &mData.mVertexAttributes[attributeIndex]; + + attrib->buffer.set(boundBuffer); + attrib->size = size; + attrib->type = type; + attrib->normalized = normalized; + attrib->pureInteger = pureInteger; + attrib->stride = stride; + attrib->pointer = pointer; + mDirtyBits.set(DIRTY_BIT_ATTRIB_0_POINTER + attributeIndex); } void VertexArray::setElementArrayBuffer(Buffer *buffer) { - mElementArrayBuffer.set(buffer); - mVertexArray->setElementArrayBuffer(buffer); + mData.mElementArrayBuffer.set(buffer); + mDirtyBits.set(DIRTY_BIT_ELEMENT_ARRAY_BUFFER); +} + +void VertexArray::syncImplState() +{ + if (mDirtyBits.any()) + { + mVertexArray->syncState(mDirtyBits); + mDirtyBits.reset(); + } } } diff --git a/src/3rdparty/angle/src/libANGLE/VertexArray.h b/src/3rdparty/angle/src/libANGLE/VertexArray.h index 5c79b9953d..6bc267d399 100644 --- a/src/3rdparty/angle/src/libANGLE/VertexArray.h +++ b/src/3rdparty/angle/src/libANGLE/VertexArray.h @@ -15,12 +15,15 @@ #include "libANGLE/RefCountObject.h" #include "libANGLE/Constants.h" +#include "libANGLE/Debug.h" +#include "libANGLE/State.h" #include "libANGLE/VertexAttribute.h" #include namespace rx { +class ImplFactory; class VertexArrayImpl; } @@ -28,37 +31,93 @@ namespace gl { class Buffer; -class VertexArray +class VertexArray final : public LabeledObject { public: - VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs); + VertexArray(rx::ImplFactory *factory, GLuint id, size_t maxAttribs); ~VertexArray(); GLuint id() const; - const VertexAttribute& getVertexAttribute(size_t attributeIndex) const; - const std::vector &getVertexAttributes() const; + void setLabel(const std::string &label) override; + const std::string &getLabel() const override; + + const VertexAttribute &getVertexAttribute(size_t attributeIndex) const; void detachBuffer(GLuint bufferName); - void setVertexAttribDivisor(GLuint index, GLuint divisor); - void enableAttribute(unsigned int attributeIndex, bool enabledState); - void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, + void setVertexAttribDivisor(size_t index, GLuint divisor); + void enableAttribute(size_t attributeIndex, bool enabledState); + void setAttributeState(size_t attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, bool normalized, bool pureInteger, GLsizei stride, const void *pointer); - Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); } void setElementArrayBuffer(Buffer *buffer); - GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); } - size_t getMaxAttribs() const { return mVertexAttributes.size(); } + + const BindingPointer &getElementArrayBuffer() const { return mData.getElementArrayBuffer(); } + size_t getMaxAttribs() const { return mData.getVertexAttributes().size(); } + const std::vector &getVertexAttributes() const { return mData.getVertexAttributes(); } rx::VertexArrayImpl *getImplementation() { return mVertexArray; } const rx::VertexArrayImpl *getImplementation() const { return mVertexArray; } + size_t getMaxEnabledAttribute() const { return mData.getMaxEnabledAttribute(); } + + class Data final : public angle::NonCopyable + { + public: + explicit Data(size_t maxAttribs); + ~Data(); + + const std::string &getLabel() const { return mLabel; } + + const BindingPointer &getElementArrayBuffer() const { return mElementArrayBuffer; } + size_t getMaxAttribs() const { return mVertexAttributes.size(); } + size_t getMaxEnabledAttribute() const { return mMaxEnabledAttribute; } + const std::vector &getVertexAttributes() const { return mVertexAttributes; } + const VertexAttribute &getVertexAttribute(size_t index) const + { + return mVertexAttributes[index]; + } + + private: + friend class VertexArray; + std::string mLabel; + std::vector mVertexAttributes; + BindingPointer mElementArrayBuffer; + size_t mMaxEnabledAttribute; + }; + + enum DirtyBitType + { + DIRTY_BIT_ELEMENT_ARRAY_BUFFER, + + // Reserve bits for enabled flags + DIRTY_BIT_ATTRIB_0_ENABLED, + DIRTY_BIT_ATTRIB_MAX_ENABLED = DIRTY_BIT_ATTRIB_0_ENABLED + gl::MAX_VERTEX_ATTRIBS, + + // Reserve bits for attrib pointers + DIRTY_BIT_ATTRIB_0_POINTER = DIRTY_BIT_ATTRIB_MAX_ENABLED, + DIRTY_BIT_ATTRIB_MAX_POINTER = DIRTY_BIT_ATTRIB_0_POINTER + gl::MAX_VERTEX_ATTRIBS, + + // Reserve bits for divisors + DIRTY_BIT_ATTRIB_0_DIVISOR = DIRTY_BIT_ATTRIB_MAX_POINTER, + DIRTY_BIT_ATTRIB_MAX_DIVISOR = DIRTY_BIT_ATTRIB_0_DIVISOR + gl::MAX_VERTEX_ATTRIBS, + + DIRTY_BIT_UNKNOWN = DIRTY_BIT_ATTRIB_MAX_DIVISOR, + DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN, + }; + + typedef std::bitset DirtyBits; + + void syncImplState(); + bool hasAnyDirtyBit() const { return mDirtyBits.any(); } + private: GLuint mId; rx::VertexArrayImpl *mVertexArray; - std::vector mVertexAttributes; - BindingPointer mElementArrayBuffer; + + Data mData; + DirtyBits mDirtyBits; }; } diff --git a/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp index 19934e7fac..13d78fd13c 100644 --- a/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp +++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp @@ -23,24 +23,6 @@ VertexAttribute::VertexAttribute() { } -bool operator==(const VertexAttribute &a, const VertexAttribute &b) -{ - return a.enabled == b.enabled && - a.type == b.type && - a.size == b.size && - a.normalized == b.normalized && - a.pureInteger == b.pureInteger && - a.stride == b.stride && - a.pointer == b.pointer && - a.buffer.get() == b.buffer.get() && - a.divisor == b.divisor; -} - -bool operator!=(const VertexAttribute &a, const VertexAttribute &b) -{ - return !(a == b); -} - size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib) { GLuint size = attrib.size; @@ -70,4 +52,23 @@ size_t ComputeVertexAttributeStride(const VertexAttribute& attrib) return attrib.stride ? attrib.stride : ComputeVertexAttributeTypeSize(attrib); } +size_t ComputeVertexAttributeElementCount(const VertexAttribute &attrib, + size_t drawCount, + size_t instanceCount) +{ + // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. + // + // A vertex attribute with a positive divisor loads one instanced vertex for every set of + // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" + // instances. + if (instanceCount > 0 && attrib.divisor > 0) + { + // When instanceDrawCount is not a multiple attrib.divisor, the division must round up. + // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced + // vertices. + return (instanceCount + attrib.divisor - 1u) / attrib.divisor; + } + + return drawCount; +} } diff --git a/src/3rdparty/angle/src/libANGLE/VertexAttribute.h b/src/3rdparty/angle/src/libANGLE/VertexAttribute.h index bdffe97466..d1ee1b47a2 100644 --- a/src/3rdparty/angle/src/libANGLE/VertexAttribute.h +++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.h @@ -40,34 +40,13 @@ bool operator==(const VertexAttribute &a, const VertexAttribute &b); bool operator!=(const VertexAttribute &a, const VertexAttribute &b); template -T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname) -{ - switch (pname) - { - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - return static_cast(attrib.enabled ? GL_TRUE : GL_FALSE); - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - return static_cast(attrib.size); - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - return static_cast(attrib.stride); - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - return static_cast(attrib.type); - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - return static_cast(attrib.normalized ? GL_TRUE : GL_FALSE); - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - return static_cast(attrib.buffer.id()); - case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: - return static_cast(attrib.divisor); - case GL_VERTEX_ATTRIB_ARRAY_INTEGER: - return static_cast(attrib.pureInteger ? GL_TRUE : GL_FALSE); - default: - UNREACHABLE(); - return static_cast(0); - } -} +T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname); size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib); size_t ComputeVertexAttributeStride(const VertexAttribute& attrib); +size_t ComputeVertexAttributeElementCount(const VertexAttribute &attrib, + size_t drawCount, + size_t instanceCount); struct VertexAttribCurrentValueData { @@ -79,44 +58,18 @@ struct VertexAttribCurrentValueData }; GLenum Type; - void setFloatValues(const GLfloat floatValues[4]) - { - for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) - { - FloatValues[valueIndex] = floatValues[valueIndex]; - } - Type = GL_FLOAT; - } - - void setIntValues(const GLint intValues[4]) - { - for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) - { - IntValues[valueIndex] = intValues[valueIndex]; - } - Type = GL_INT; - } - - void setUnsignedIntValues(const GLuint unsignedIntValues[4]) - { - for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) - { - UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex]; - } - Type = GL_UNSIGNED_INT; - } - - bool operator==(const VertexAttribCurrentValueData &other) - { - return (Type == other.Type && memcmp(FloatValues, other.FloatValues, sizeof(float) * 4) == 0); - } + VertexAttribCurrentValueData(); - bool operator!=(const VertexAttribCurrentValueData &other) - { - return !(*this == other); - } + void setFloatValues(const GLfloat floatValues[4]); + void setIntValues(const GLint intValues[4]); + void setUnsignedIntValues(const GLuint unsignedIntValues[4]); }; +bool operator==(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b); +bool operator!=(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b); + } +#include "VertexAttribute.inl" + #endif // LIBANGLE_VERTEXATTRIBUTE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/VertexAttribute.inl b/src/3rdparty/angle/src/libANGLE/VertexAttribute.inl new file mode 100644 index 0000000000..0cd31f6762 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.inl @@ -0,0 +1,103 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// VertexAttribute.inl: Inline vertex attribute methods +// + +namespace gl +{ + +inline bool operator==(const VertexAttribute &a, const VertexAttribute &b) +{ + return a.enabled == b.enabled && + a.type == b.type && + a.size == b.size && + a.normalized == b.normalized && + a.pureInteger == b.pureInteger && + a.stride == b.stride && + a.pointer == b.pointer && + a.buffer.get() == b.buffer.get() && + a.divisor == b.divisor; +} + +inline bool operator!=(const VertexAttribute &a, const VertexAttribute &b) +{ + return !(a == b); +} + +template +T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname) +{ + switch (pname) + { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + return static_cast(attrib.enabled ? GL_TRUE : GL_FALSE); + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + return static_cast(attrib.size); + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + return static_cast(attrib.stride); + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + return static_cast(attrib.type); + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + return static_cast(attrib.normalized ? GL_TRUE : GL_FALSE); + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + return static_cast(attrib.buffer.id()); + case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: + return static_cast(attrib.divisor); + case GL_VERTEX_ATTRIB_ARRAY_INTEGER: + return static_cast(attrib.pureInteger ? GL_TRUE : GL_FALSE); + default: + UNREACHABLE(); + return static_cast(0); + } +} + +inline VertexAttribCurrentValueData::VertexAttribCurrentValueData() + : Type(GL_FLOAT) +{ + FloatValues[0] = 0.0f; + FloatValues[1] = 0.0f; + FloatValues[2] = 0.0f; + FloatValues[3] = 1.0f; +} + +inline void VertexAttribCurrentValueData::setFloatValues(const GLfloat floatValues[4]) +{ + for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) + { + FloatValues[valueIndex] = floatValues[valueIndex]; + } + Type = GL_FLOAT; +} + +inline void VertexAttribCurrentValueData::setIntValues(const GLint intValues[4]) +{ + for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) + { + IntValues[valueIndex] = intValues[valueIndex]; + } + Type = GL_INT; +} + +inline void VertexAttribCurrentValueData::setUnsignedIntValues(const GLuint unsignedIntValues[4]) +{ + for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) + { + UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex]; + } + Type = GL_UNSIGNED_INT; +} + +inline bool operator==(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b) +{ + return (a.Type == b.Type && memcmp(a.FloatValues, b.FloatValues, sizeof(float) * 4) == 0); +} + +inline bool operator!=(const VertexAttribCurrentValueData &a, const VertexAttribCurrentValueData &b) +{ + return !(a == b); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.cpp b/src/3rdparty/angle/src/libANGLE/angletypes.cpp index 16879f8041..fa5b157906 100644 --- a/src/3rdparty/angle/src/libANGLE/angletypes.cpp +++ b/src/3rdparty/angle/src/libANGLE/angletypes.cpp @@ -15,17 +15,28 @@ namespace gl { -bool operator==(const Rectangle &a, const Rectangle &b) +PrimitiveType GetPrimitiveType(GLenum drawMode) { - return a.x == b.x && - a.y == b.y && - a.width == b.width && - a.height == b.height; -} - -bool operator!=(const Rectangle &a, const Rectangle &b) -{ - return !(a == b); + switch (drawMode) + { + case GL_POINTS: + return PRIMITIVE_POINTS; + case GL_LINES: + return PRIMITIVE_LINES; + case GL_LINE_STRIP: + return PRIMITIVE_LINE_STRIP; + case GL_LINE_LOOP: + return PRIMITIVE_LINE_LOOP; + case GL_TRIANGLES: + return PRIMITIVE_TRIANGLES; + case GL_TRIANGLE_STRIP: + return PRIMITIVE_TRIANGLE_STRIP; + case GL_TRIANGLE_FAN: + return PRIMITIVE_TRIANGLE_FAN; + default: + UNREACHABLE(); + return PRIMITIVE_TYPE_MAX; + } } SamplerState::SamplerState() @@ -35,47 +46,30 @@ SamplerState::SamplerState() wrapT(GL_REPEAT), wrapR(GL_REPEAT), maxAnisotropy(1.0f), - baseLevel(0), - maxLevel(1000), minLod(-1000.0f), maxLod(1000.0f), compareMode(GL_NONE), - compareFunc(GL_LEQUAL), - swizzleRed(GL_RED), - swizzleGreen(GL_GREEN), - swizzleBlue(GL_BLUE), - swizzleAlpha(GL_ALPHA) -{} - -bool SamplerState::swizzleRequired() const + compareFunc(GL_LEQUAL) { - return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || - swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA; } -bool SamplerState::operator==(const SamplerState &other) const +TextureState::TextureState() + : swizzleRed(GL_RED), + swizzleGreen(GL_GREEN), + swizzleBlue(GL_BLUE), + swizzleAlpha(GL_ALPHA), + samplerState(), + baseLevel(0), + maxLevel(1000), + immutableFormat(false), + immutableLevels(0) { - return minFilter == other.minFilter && - magFilter == other.magFilter && - wrapS == other.wrapS && - wrapT == other.wrapT && - wrapR == other.wrapR && - maxAnisotropy == other.maxAnisotropy && - baseLevel == other.baseLevel && - maxLevel == other.maxLevel && - minLod == other.minLod && - maxLod == other.maxLod && - compareMode == other.compareMode && - compareFunc == other.compareFunc && - swizzleRed == other.swizzleRed && - swizzleGreen == other.swizzleGreen && - swizzleBlue == other.swizzleBlue && - swizzleAlpha == other.swizzleAlpha; } -bool SamplerState::operator!=(const SamplerState &other) const +bool TextureState::swizzleRequired() const { - return !(*this == other); + return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || + swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA; } static void MinMax(int a, int b, int *minimum, int *maximum) @@ -128,119 +122,24 @@ bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *in } } -VertexFormat::VertexFormat() - : mType(GL_NONE), - mNormalized(GL_FALSE), - mComponents(0), - mPureInteger(false) -{} - -VertexFormat::VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger) - : mType(type), - mNormalized(normalized), - mComponents(components), - mPureInteger(pureInteger) -{ - // Float data can not be normalized, so ignore the user setting - if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) - { - mNormalized = GL_FALSE; - } -} - -VertexFormat::VertexFormat(const VertexAttribute &attrib) - : mType(attrib.type), - mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), - mComponents(attrib.size), - mPureInteger(attrib.pureInteger) -{ - // Ensure we aren't initializing a vertex format which should be using - // the current-value type - ASSERT(attrib.enabled); - - // Float data can not be normalized, so ignore the user setting - if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) - { - mNormalized = GL_FALSE; - } -} - -VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueType) - : mType(attrib.type), - mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), - mComponents(attrib.size), - mPureInteger(attrib.pureInteger) -{ - if (!attrib.enabled) - { - mType = currentValueType; - mNormalized = GL_FALSE; - mComponents = 4; - mPureInteger = (currentValueType != GL_FLOAT); - } - - // Float data can not be normalized, so ignore the user setting - if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) - { - mNormalized = GL_FALSE; - } -} - -void VertexFormat::GetInputLayout(VertexFormat *inputLayout, - Program *program, - const State &state) -{ - const std::vector &vertexAttributes = state.getVertexArray()->getVertexAttributes(); - for (unsigned int attributeIndex = 0; attributeIndex < vertexAttributes.size(); attributeIndex++) - { - int semanticIndex = program->getSemanticIndex(attributeIndex); - - if (semanticIndex != -1) - { - inputLayout[semanticIndex] = VertexFormat(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex).Type); - } - } -} - -bool VertexFormat::operator==(const VertexFormat &other) const +bool Box::operator==(const Box &other) const { - return (mType == other.mType && - mComponents == other.mComponents && - mNormalized == other.mNormalized && - mPureInteger == other.mPureInteger ); + return (x == other.x && y == other.y && z == other.z && + width == other.width && height == other.height && depth == other.depth); } -bool VertexFormat::operator!=(const VertexFormat &other) const +bool Box::operator!=(const Box &other) const { return !(*this == other); } -bool VertexFormat::operator<(const VertexFormat& other) const -{ - if (mType != other.mType) - { - return mType < other.mType; - } - if (mNormalized != other.mNormalized) - { - return mNormalized < other.mNormalized; - } - if (mComponents != other.mComponents) - { - return mComponents < other.mComponents; - } - return mPureInteger < other.mPureInteger; -} - -bool Box::operator==(const Box &other) const +bool operator==(const Extents &lhs, const Extents &rhs) { - return (x == other.x && y == other.y && z == other.z && - width == other.width && height == other.height && depth == other.depth); + return lhs.width == rhs.width && lhs.height == rhs.height && lhs.depth == rhs.depth; } -bool Box::operator!=(const Box &other) const +bool operator!=(const Extents &lhs, const Extents &rhs) { - return !(*this == other); + return !(lhs == rhs); } - } diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.h b/src/3rdparty/angle/src/libANGLE/angletypes.h index e4e08b5512..c29ad06bd2 100644 --- a/src/3rdparty/angle/src/libANGLE/angletypes.h +++ b/src/3rdparty/angle/src/libANGLE/angletypes.h @@ -13,7 +13,8 @@ #include "libANGLE/RefCountObject.h" #include -#include + +#include namespace gl { @@ -23,6 +24,20 @@ class Program; struct VertexAttribute; struct VertexAttribCurrentValueData; +enum PrimitiveType +{ + PRIMITIVE_POINTS, + PRIMITIVE_LINES, + PRIMITIVE_LINE_STRIP, + PRIMITIVE_LINE_LOOP, + PRIMITIVE_TRIANGLES, + PRIMITIVE_TRIANGLE_STRIP, + PRIMITIVE_TRIANGLE_FAN, + PRIMITIVE_TYPE_MAX, +}; + +PrimitiveType GetPrimitiveType(GLenum drawMode); + enum SamplerType { SAMPLER_PIXEL, @@ -42,19 +57,10 @@ struct Color }; template -bool operator==(const Color &a, const Color &b) -{ - return a.red == b.red && - a.green == b.green && - a.blue == b.blue && - a.alpha == b.alpha; -} +bool operator==(const Color &a, const Color &b); template -bool operator!=(const Color &a, const Color &b) -{ - return !(a == b); -} +bool operator!=(const Color &a, const Color &b); typedef Color ColorF; typedef Color ColorI; @@ -62,13 +68,21 @@ typedef Color ColorUI; struct Rectangle { + Rectangle() : x(0), y(0), width(0), height(0) {} + Rectangle(int x_in, int y_in, int width_in, int height_in) + : x(x_in), y(y_in), width(width_in), height(height_in) + { + } + + int x0() const { return x; } + int y0() const { return y; } + int x1() const { return x + width; } + int y1() const { return y + height; } + int x; int y; int width; int height; - - Rectangle() : x(0), y(0), width(0), height(0) { } - Rectangle(int x_in, int y_in, int width_in, int height_in) : x(x_in), y(y_in), width(width_in), height(height_in) { } }; bool operator==(const Rectangle &a, const Rectangle &b); @@ -98,6 +112,9 @@ struct Extents bool empty() const { return (width * height * depth) == 0; } }; +bool operator==(const Extents &lhs, const Extents &rhs); +bool operator!=(const Extents &lhs, const Extents &rhs); + struct Box { int x; @@ -172,36 +189,58 @@ struct DepthStencilState GLuint stencilBackWritemask; }; +// State from Table 6.10 (state per sampler object) struct SamplerState { SamplerState(); GLenum minFilter; GLenum magFilter; + GLenum wrapS; GLenum wrapT; GLenum wrapR; + + // From EXT_texture_filter_anisotropic float maxAnisotropy; - GLint baseLevel; - GLint maxLevel; GLfloat minLod; GLfloat maxLod; GLenum compareMode; GLenum compareFunc; +}; + +bool operator==(const SamplerState &a, const SamplerState &b); +bool operator!=(const SamplerState &a, const SamplerState &b); + +// State from Table 6.9 (state per texture object) in the OpenGL ES 3.0.2 spec. +struct TextureState +{ + TextureState(); GLenum swizzleRed; GLenum swizzleGreen; GLenum swizzleBlue; GLenum swizzleAlpha; - bool swizzleRequired() const; + SamplerState samplerState; + + GLuint baseLevel; + GLuint maxLevel; - bool operator==(const SamplerState &other) const; - bool operator!=(const SamplerState &other) const; + bool immutableFormat; + GLuint immutableLevels; + + // From GL_ANGLE_texture_usage + GLenum usage; + + bool swizzleRequired() const; }; +bool operator==(const TextureState &a, const TextureState &b); +bool operator!=(const TextureState &a, const TextureState &b); + struct PixelUnpackState { BindingPointer pixelBuffer; @@ -257,54 +296,56 @@ struct PixelPackState {} }; -struct VertexFormat -{ - GLenum mType; - GLboolean mNormalized; - GLuint mComponents; - bool mPureInteger; - - VertexFormat(); - VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger); - explicit VertexFormat(const VertexAttribute &attribute); - VertexFormat(const VertexAttribute &attribute, GLenum currentValueType); - - static void GetInputLayout(VertexFormat *inputLayout, - Program *program, - const State& currentValues); - - bool operator==(const VertexFormat &other) const; - bool operator!=(const VertexFormat &other) const; - bool operator<(const VertexFormat& other) const; -}; +// Used in Program and VertexArray. +typedef std::bitset AttributesMask; +// Use in Program +typedef std::bitset UniformBlockBindingMask; } namespace rx { - enum VendorID : uint32_t { - VENDOR_ID_AMD = 0x1002, - VENDOR_ID_INTEL = 0x8086, - VENDOR_ID_NVIDIA = 0x10DE, + VENDOR_ID_UNKNOWN = 0x0, + VENDOR_ID_AMD = 0x1002, + VENDOR_ID_INTEL = 0x8086, + VENDOR_ID_NVIDIA = 0x10DE, }; +// A macro that determines whether an object has a given runtime type. +#if defined(__clang__) +#if __has_feature(cxx_rtti) +#define ANGLE_HAS_DYNAMIC_CAST 1 +#endif +#elif !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || defined(__GXX_RTTI)) +#define ANGLE_HAS_DYNAMIC_CAST 1 +#endif + +#ifdef ANGLE_HAS_DYNAMIC_CAST +#define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast(obj) != nullptr) +#undef ANGLE_HAS_DYNAMIC_CAST +#else +#define ANGLE_HAS_DYNAMIC_TYPE(type, obj) (obj != nullptr) +#endif + // Downcast a base implementation object (EG TextureImpl to TextureD3D) template inline DestT *GetAs(SrcT *src) { - ASSERT(HAS_DYNAMIC_TYPE(DestT*, src)); + ASSERT(ANGLE_HAS_DYNAMIC_TYPE(DestT*, src)); return static_cast(src); } template inline const DestT *GetAs(const SrcT *src) { - ASSERT(HAS_DYNAMIC_TYPE(const DestT*, src)); + ASSERT(ANGLE_HAS_DYNAMIC_TYPE(const DestT*, src)); return static_cast(src); } +#undef ANGLE_HAS_DYNAMIC_TYPE + // Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D) template inline DestT *GetImplAs(SrcT *src) @@ -320,4 +361,52 @@ inline const DestT *GetImplAs(const SrcT *src) } +#include "angletypes.inl" + +namespace angle +{ +// Zero-based for better array indexing +enum FramebufferBinding +{ + FramebufferBindingRead = 0, + FramebufferBindingDraw, + FramebufferBindingSingletonMax, + FramebufferBindingBoth = FramebufferBindingSingletonMax, + FramebufferBindingMax, + FramebufferBindingUnknown = FramebufferBindingMax, +}; + +inline FramebufferBinding EnumToFramebufferBinding(GLenum enumValue) +{ + switch (enumValue) + { + case GL_READ_FRAMEBUFFER: + return FramebufferBindingRead; + case GL_DRAW_FRAMEBUFFER: + return FramebufferBindingDraw; + case GL_FRAMEBUFFER: + return FramebufferBindingBoth; + default: + UNREACHABLE(); + return FramebufferBindingUnknown; + } +} + +inline GLenum FramebufferBindingToEnum(FramebufferBinding binding) +{ + switch (binding) + { + case FramebufferBindingRead: + return GL_READ_FRAMEBUFFER; + case FramebufferBindingDraw: + return GL_DRAW_FRAMEBUFFER; + case FramebufferBindingBoth: + return GL_FRAMEBUFFER; + default: + UNREACHABLE(); + return GL_NONE; + } +} +} + #endif // LIBANGLE_ANGLETYPES_H_ diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.inl b/src/3rdparty/angle/src/libANGLE/angletypes.inl new file mode 100644 index 0000000000..d51bcaaa78 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/angletypes.inl @@ -0,0 +1,78 @@ +// +// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// angletypes.inl : Inline definitions of some functions from angletypes.h + +namespace gl +{ + +template +bool operator==(const Color &a, const Color &b) +{ + return a.red == b.red && + a.green == b.green && + a.blue == b.blue && + a.alpha == b.alpha; +} + +template +bool operator!=(const Color &a, const Color &b) +{ + return !(a == b); +} + +inline bool operator==(const Rectangle &a, const Rectangle &b) +{ + return a.x == b.x && + a.y == b.y && + a.width == b.width && + a.height == b.height; +} + +inline bool operator!=(const Rectangle &a, const Rectangle &b) +{ + return !(a == b); +} + +inline bool operator==(const SamplerState &a, const SamplerState &b) +{ + return a.minFilter == b.minFilter && + a.magFilter == b.magFilter && + a.wrapS == b.wrapS && + a.wrapT == b.wrapT && + a.wrapR == b.wrapR && + a.maxAnisotropy == b.maxAnisotropy && + a.minLod == b.minLod && + a.maxLod == b.maxLod && + a.compareMode == b.compareMode && + a.compareFunc == b.compareFunc; +} + +inline bool operator!=(const SamplerState &a, const SamplerState &b) +{ + return !(a == b); +} + +inline bool operator==(const TextureState &a, const TextureState &b) +{ + return a.swizzleRed == b.swizzleRed && + a.swizzleGreen == b.swizzleGreen && + a.swizzleBlue == b.swizzleBlue && + a.swizzleAlpha == b.swizzleAlpha && + a.samplerState == b.samplerState && + a.baseLevel == b.baseLevel && + a.maxLevel == b.maxLevel && + a.immutableFormat == b.immutableFormat && + a.immutableLevels == b.immutableLevels && + a.usage == b.usage; +} + +inline bool operator!=(const TextureState &a, const TextureState &b) +{ + return !(a == b); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/features.h b/src/3rdparty/angle/src/libANGLE/features.h index fbe013f47d..ecf486dcf7 100644 --- a/src/3rdparty/angle/src/libANGLE/features.h +++ b/src/3rdparty/angle/src/libANGLE/features.h @@ -32,9 +32,22 @@ #define ANGLE_PROGRAM_BINARY_LOAD ANGLE_ENABLED #endif -// Shader debug info -#if !defined(ANGLE_SHADER_DEBUG_INFO) -#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED +// Append HLSL assembly to shader debug info. Defaults to enabled in Debug and off in Release. +#if !defined(ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO) +#if !defined(NDEBUG) +#define ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO ANGLE_ENABLED +#else +#define ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO ANGLE_DISABLED +#endif // !defined(NDEBUG) +#endif // !defined(ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO) + +// Program link validation of precisions for uniforms. This feature was +// requested by developers to allow non-conformant shaders to be used which +// contain mismatched precisions. +// ENABLED validate that precision for uniforms match between vertex and fragment shaders +// DISABLED allow precision for uniforms to differ between vertex and fragment shaders +#if !defined(ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION) +#define ANGLE_PROGRAM_LINK_VALIDATE_UNIFORM_PRECISION ANGLE_ENABLED #endif #endif // LIBANGLE_FEATURES_H_ diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.cpp b/src/3rdparty/angle/src/libANGLE/formatutils.cpp index 51e6a5a65d..3a4df126c5 100644 --- a/src/3rdparty/angle/src/libANGLE/formatutils.cpp +++ b/src/3rdparty/angle/src/libANGLE/formatutils.cpp @@ -163,11 +163,6 @@ static bool AlwaysSupported(GLuint, const Extensions &) return true; } -static bool UnimplementedSupport(GLuint, const Extensions &) -{ - return false; -} - static bool NeverSupported(GLuint, const Extensions &) { return false; @@ -217,6 +212,61 @@ static bool RequireExtAndExt(GLuint, const Extensions &extensions) return extensions.*bool1 && extensions.*bool2; } +// Check support for either of two extensions +template +static bool RequireExtOrExt(GLuint, const Extensions &extensions) +{ + return extensions.*bool1 || extensions.*bool2; +} + +// Special function for half float formats with three or four channels. +static bool HalfFloatSupport(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= 3 || extensions.textureHalfFloat; +} + +static bool HalfFloatRenderableSupport(GLuint clientVersion, const Extensions &extensions) +{ + return HalfFloatSupport(clientVersion, extensions) && extensions.colorBufferHalfFloat; +} + +// Special function for half float formats with one or two channels. +static bool HalfFloatSupportRG(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= 3 || (extensions.textureHalfFloat && extensions.textureRG); +} + +static bool HalfFloatRenderableSupportRG(GLuint clientVersion, const Extensions &extensions) +{ + return HalfFloatSupportRG(clientVersion, extensions) && extensions.colorBufferHalfFloat; +} + +// Special function for float formats with three or four channels. +static bool FloatSupport(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= 3 || extensions.textureFloat; +} + +static bool FloatRenderableSupport(GLuint clientVersion, const Extensions &extensions) +{ + // We don't expose colorBufferFloat in ES2, but we silently support rendering to float. + return FloatSupport(clientVersion, extensions) && + (extensions.colorBufferFloat || clientVersion == 2); +} + +// Special function for float formats with one or two channels. +static bool FloatSupportRG(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= 3 || (extensions.textureFloat && extensions.textureRG); +} + +static bool FloatRenderableSupportRG(GLuint clientVersion, const Extensions &extensions) +{ + // We don't expose colorBufferFloat in ES2, but we silently support rendering to float. + return FloatSupportRG(clientVersion, extensions) && + (extensions.colorBufferFloat || clientVersion == 2); +} + InternalFormat::InternalFormat() : redBits(0), greenBits(0), @@ -228,13 +278,13 @@ InternalFormat::InternalFormat() stencilBits(0), pixelBytes(0), componentCount(0), + compressed(false), compressedBlockWidth(0), compressedBlockHeight(0), format(GL_NONE), type(GL_NONE), componentType(GL_NONE), colorEncoding(GL_NONE), - compressed(false), textureSupport(NeverSupported), renderSupport(NeverSupported), filterSupport(NeverSupported) @@ -346,6 +396,7 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() { InternalFormatInfoMap map; + // clang-format off // From ES 3.0.1 spec, table 3.12 map.insert(InternalFormatInfoPair(GL_NONE, InternalFormat())); @@ -362,7 +413,7 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() map.insert(InternalFormatInfoPair(GL_RGBA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESOrExt<3, &Extensions::rgb8rgba8>, RequireESOrExt<3, &Extensions::rgb8rgba8>, AlwaysSupported))); map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireES<3>, NeverSupported, AlwaysSupported))); map.insert(InternalFormatInfoPair(GL_RGB10_A2, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireES<3>, RequireES<3>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB10_A2UI, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3>, NeverSupported, NeverSupported))); + map.insert(InternalFormatInfoPair(GL_RGB10_A2UI, RGBAFormat(10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireES<3>, RequireES<3>, NeverSupported))); map.insert(InternalFormatInfoPair(GL_SRGB8, RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported))); map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8, RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &Extensions::sRGB>, AlwaysSupported))); map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F, RGBAFormat(11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireES<3>, RequireExt<&Extensions::colorBufferFloat>, AlwaysSupported))); @@ -397,23 +448,23 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX, RGBAFormat( 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported))); // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float - // | Internal format | | D |S | Format | Type | Comp | SRGB | Texture supported | Renderable | Filterable | - // | | | | | | | type | | | | | - map.insert(InternalFormatInfoPair(GL_R16F, RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_RG16F, RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_RGB16F, RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireExt<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_RGBA16F, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireESOrExt<3, &Extensions::textureHalfFloat>, RequireExt<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_R32F, RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureFloatLinear> ))); - map.insert(InternalFormatInfoPair(GL_RG32F, RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireESOrExtAndExt<3, &Extensions::textureFloat, &Extensions::textureRG>, RequireExt<&Extensions::textureFloatLinear> ))); - map.insert(InternalFormatInfoPair(GL_RGB32F, RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>, RequireESOrExt<3, &Extensions::textureFloat>, RequireExt<&Extensions::textureFloatLinear> ))); - map.insert(InternalFormatInfoPair(GL_RGBA32F, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, RequireESOrExt<3, &Extensions::textureFloat>, RequireESOrExt<3, &Extensions::textureFloat>, RequireExt<&Extensions::textureFloatLinear> ))); + // | Internal format | | D |S | Format | Type | Comp | SRGB | Texture supported | Renderable | Filterable | + // | | | | | | | type | | | | | + map.insert(InternalFormatInfoPair(GL_R16F, RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupportRG, HalfFloatRenderableSupportRG, RequireExt<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_RG16F, RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupportRG, HalfFloatRenderableSupportRG, RequireExt<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_RGB16F, RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupport, HalfFloatRenderableSupport, RequireExt<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_RGBA16F, RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, HalfFloatSupport, HalfFloatRenderableSupport, RequireExt<&Extensions::textureHalfFloatLinear>))); + map.insert(InternalFormatInfoPair(GL_R32F, RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, FloatSupportRG, FloatRenderableSupportRG, RequireExt<&Extensions::textureFloatLinear> ))); + map.insert(InternalFormatInfoPair(GL_RG32F, RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, FloatSupportRG, FloatRenderableSupportRG, RequireExt<&Extensions::textureFloatLinear> ))); + map.insert(InternalFormatInfoPair(GL_RGB32F, RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, FloatSupport, FloatRenderableSupport, RequireExt<&Extensions::textureFloatLinear> ))); + map.insert(InternalFormatInfoPair(GL_RGBA32F, RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, FloatSupport, FloatRenderableSupport, RequireExt<&Extensions::textureFloatLinear> ))); // Depth stencil formats // | Internal format | | D |S | X | Format | Type | Component type | Supported | Renderable | Filterable | map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, RequireESOrExt<3, &Extensions::depthTextures>))); map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24, DepthStencilFormat(24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>))); map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireES<3>, RequireES<3>, RequireESOrExt<3, &Extensions::depthTextures>))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::depthTextures>, RequireExt<&Extensions::depthTextures>, AlwaysSupported ))); + map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, RequireExtOrExt<&Extensions::depthTextures, &Extensions::depth32>, AlwaysSupported ))); map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, &Extensions::depthTextures>, RequireESOrExtOrExt<3, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported ))); map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3>, RequireES<3>, AlwaysSupported ))); // STENCIL_INDEX8 is special-cased, see around the bottom of the list. @@ -450,28 +501,63 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT, UnsizedFormat(GL_RGBA, RequireESOrExt<3, &Extensions::sRGB>, RequireESOrExt<3, &Extensions::sRGB>, AlwaysSupported))); // Compressed formats, From ES 3.0.1 spec, table 3.16 - // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | - map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_COMPRESSED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, true, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, true, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, false, RequireES<3>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, RequireES<3>, NeverSupported, AlwaysSupported))); // From GL_EXT_texture_compression_dxt1 - // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported))); + // | Internal format | |W |H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported))); // From GL_ANGLE_texture_compression_dxt3 - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported))); // From GL_ANGLE_texture_compression_dxt5 - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported))); + + // From GL_OES_compressed_ETC1_RGB8_texture + map.insert(InternalFormatInfoPair(GL_ETC1_RGB8_OES, CompressedFormat(4, 4, 64, 3, GL_ETC1_RGB8_OES, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::compressedETC1RGB8Texture>, NeverSupported, AlwaysSupported))); + + // From KHR_texture_compression_astc_hdr + // | Internal format | | W | H | BS |CC| Format | Type | SRGB | Supported | Renderable | Filterable | + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_4x4_KHR, CompressedFormat( 4, 4, 128, 4, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_5x4_KHR, CompressedFormat( 5, 4, 128, 4, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_5x5_KHR, CompressedFormat( 5, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_6x5_KHR, CompressedFormat( 6, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_6x6_KHR, CompressedFormat( 6, 6, 128, 4, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_8x5_KHR, CompressedFormat( 8, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_8x6_KHR, CompressedFormat( 8, 6, 128, 4, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_8x8_KHR, CompressedFormat( 8, 8, 128, 4, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x5_KHR, CompressedFormat(10, 5, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x6_KHR, CompressedFormat(10, 6, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x8_KHR, CompressedFormat(10, 8, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_10x10_KHR, CompressedFormat(10, 10, 128, 4, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_12x10_KHR, CompressedFormat(12, 10, 128, 4, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_ASTC_12x12_KHR, CompressedFormat(12, 12, 128, 4, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, false, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, CompressedFormat( 4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, CompressedFormat( 5, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, CompressedFormat( 5, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, CompressedFormat( 6, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, CompressedFormat( 6, 6, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, CompressedFormat( 8, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, CompressedFormat( 8, 6, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, CompressedFormat( 8, 8, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, CompressedFormat(10, 5, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, CompressedFormat(10, 6, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, CompressedFormat(10, 8, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, CompressedFormat(10, 10, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, CompressedFormat(12, 10, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); + map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, CompressedFormat(12, 12, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_UNSIGNED_BYTE, true, RequireExtOrExt<&Extensions::textureCompressionASTCHDR, &Extensions::textureCompressionASTCLDR>, NeverSupported, AlwaysSupported))); // For STENCIL_INDEX8 we chose a normalized component type for the following reasons: // - Multisampled buffer are disallowed for non-normalized integer component types and we want to support it for STENCIL_INDEX8 @@ -480,6 +566,11 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() // | Internal format | |D |S |X | Format | Type | Component type | Supported | Renderable | Filterable | map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat(0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, NeverSupported))); + // From GL_ANGLE_lossy_etc_decode + map.insert(InternalFormatInfoPair(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, CompressedFormat(4, 4, 64, 3, GL_ETC1_RGB8_OES, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::lossyETCDecode>, NeverSupported, AlwaysSupported))); + + // clang-format on + return map; } @@ -592,9 +683,23 @@ GLuint InternalFormat::computeRowPitch(GLenum formatType, GLsizei width, GLint a return rx::roundUp(rowBytes, static_cast(alignment)); } -GLuint InternalFormat::computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const +GLuint InternalFormat::computeDepthPitch(GLenum formatType, + GLsizei width, + GLsizei height, + GLint alignment, + GLint rowLength, + GLint imageHeight) const { - return computeRowPitch(formatType, width, alignment, rowLength) * height; + GLuint rows; + if (imageHeight > 0) + { + rows = imageHeight; + } + else + { + rows = height; + } + return computeRowPitch(formatType, width, alignment, rowLength) * rows; } GLuint InternalFormat::computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const @@ -619,6 +724,15 @@ GLuint InternalFormat::computeBlockSize(GLenum formatType, GLsizei width, GLsize } } +GLuint InternalFormat::computeSkipPixels(GLint rowPitch, + GLint depthPitch, + GLint skipImages, + GLint skipRows, + GLint skipPixels) const +{ + return skipImages * depthPitch + skipRows * rowPitch + skipPixels * pixelBytes; +} + GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type) { const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat); @@ -647,4 +761,796 @@ const FormatSet &GetAllSizedInternalFormats() return formatSet; } +AttributeType GetAttributeType(GLenum enumValue) +{ + switch (enumValue) + { + case GL_FLOAT: + return ATTRIBUTE_FLOAT; + case GL_FLOAT_VEC2: + return ATTRIBUTE_VEC2; + case GL_FLOAT_VEC3: + return ATTRIBUTE_VEC3; + case GL_FLOAT_VEC4: + return ATTRIBUTE_VEC4; + case GL_INT: + return ATTRIBUTE_INT; + case GL_INT_VEC2: + return ATTRIBUTE_IVEC2; + case GL_INT_VEC3: + return ATTRIBUTE_IVEC3; + case GL_INT_VEC4: + return ATTRIBUTE_IVEC4; + case GL_UNSIGNED_INT: + return ATTRIBUTE_UINT; + case GL_UNSIGNED_INT_VEC2: + return ATTRIBUTE_UVEC2; + case GL_UNSIGNED_INT_VEC3: + return ATTRIBUTE_UVEC3; + case GL_UNSIGNED_INT_VEC4: + return ATTRIBUTE_UVEC4; + case GL_FLOAT_MAT2: + return ATTRIBUTE_MAT2; + case GL_FLOAT_MAT3: + return ATTRIBUTE_MAT3; + case GL_FLOAT_MAT4: + return ATTRIBUTE_MAT4; + case GL_FLOAT_MAT2x3: + return ATTRIBUTE_MAT2x3; + case GL_FLOAT_MAT2x4: + return ATTRIBUTE_MAT2x4; + case GL_FLOAT_MAT3x2: + return ATTRIBUTE_MAT3x2; + case GL_FLOAT_MAT3x4: + return ATTRIBUTE_MAT3x4; + case GL_FLOAT_MAT4x2: + return ATTRIBUTE_MAT4x2; + case GL_FLOAT_MAT4x3: + return ATTRIBUTE_MAT4x3; + default: + UNREACHABLE(); + return ATTRIBUTE_FLOAT; + } +} + +VertexFormatType GetVertexFormatType(GLenum type, GLboolean normalized, GLuint components, bool pureInteger) +{ + switch (type) + { + case GL_BYTE: + switch (components) + { + case 1: + if (pureInteger) + return VERTEX_FORMAT_SBYTE1_INT; + if (normalized) + return VERTEX_FORMAT_SBYTE1_NORM; + return VERTEX_FORMAT_SBYTE1; + case 2: + if (pureInteger) + return VERTEX_FORMAT_SBYTE2_INT; + if (normalized) + return VERTEX_FORMAT_SBYTE2_NORM; + return VERTEX_FORMAT_SBYTE2; + case 3: + if (pureInteger) + return VERTEX_FORMAT_SBYTE3_INT; + if (normalized) + return VERTEX_FORMAT_SBYTE3_NORM; + return VERTEX_FORMAT_SBYTE3; + case 4: + if (pureInteger) + return VERTEX_FORMAT_SBYTE4_INT; + if (normalized) + return VERTEX_FORMAT_SBYTE4_NORM; + return VERTEX_FORMAT_SBYTE4; + default: + UNREACHABLE(); + break; + } + case GL_UNSIGNED_BYTE: + switch (components) + { + case 1: + if (pureInteger) + return VERTEX_FORMAT_UBYTE1_INT; + if (normalized) + return VERTEX_FORMAT_UBYTE1_NORM; + return VERTEX_FORMAT_UBYTE1; + case 2: + if (pureInteger) + return VERTEX_FORMAT_UBYTE2_INT; + if (normalized) + return VERTEX_FORMAT_UBYTE2_NORM; + return VERTEX_FORMAT_UBYTE2; + case 3: + if (pureInteger) + return VERTEX_FORMAT_UBYTE3_INT; + if (normalized) + return VERTEX_FORMAT_UBYTE3_NORM; + return VERTEX_FORMAT_UBYTE3; + case 4: + if (pureInteger) + return VERTEX_FORMAT_UBYTE4_INT; + if (normalized) + return VERTEX_FORMAT_UBYTE4_NORM; + return VERTEX_FORMAT_UBYTE4; + default: + UNREACHABLE(); + break; + } + case GL_SHORT: + switch (components) + { + case 1: + if (pureInteger) + return VERTEX_FORMAT_SSHORT1_INT; + if (normalized) + return VERTEX_FORMAT_SSHORT1_NORM; + return VERTEX_FORMAT_SSHORT1; + case 2: + if (pureInteger) + return VERTEX_FORMAT_SSHORT2_INT; + if (normalized) + return VERTEX_FORMAT_SSHORT2_NORM; + return VERTEX_FORMAT_SSHORT2; + case 3: + if (pureInteger) + return VERTEX_FORMAT_SSHORT3_INT; + if (normalized) + return VERTEX_FORMAT_SSHORT3_NORM; + return VERTEX_FORMAT_SSHORT3; + case 4: + if (pureInteger) + return VERTEX_FORMAT_SSHORT4_INT; + if (normalized) + return VERTEX_FORMAT_SSHORT4_NORM; + return VERTEX_FORMAT_SSHORT4; + default: + UNREACHABLE(); + break; + } + case GL_UNSIGNED_SHORT: + switch (components) + { + case 1: + if (pureInteger) + return VERTEX_FORMAT_USHORT1_INT; + if (normalized) + return VERTEX_FORMAT_USHORT1_NORM; + return VERTEX_FORMAT_USHORT1; + case 2: + if (pureInteger) + return VERTEX_FORMAT_USHORT2_INT; + if (normalized) + return VERTEX_FORMAT_USHORT2_NORM; + return VERTEX_FORMAT_USHORT2; + case 3: + if (pureInteger) + return VERTEX_FORMAT_USHORT3_INT; + if (normalized) + return VERTEX_FORMAT_USHORT3_NORM; + return VERTEX_FORMAT_USHORT3; + case 4: + if (pureInteger) + return VERTEX_FORMAT_USHORT4_INT; + if (normalized) + return VERTEX_FORMAT_USHORT4_NORM; + return VERTEX_FORMAT_USHORT4; + default: + UNREACHABLE(); + break; + } + case GL_INT: + switch (components) + { + case 1: + if (pureInteger) + return VERTEX_FORMAT_SINT1_INT; + if (normalized) + return VERTEX_FORMAT_SINT1_NORM; + return VERTEX_FORMAT_SINT1; + case 2: + if (pureInteger) + return VERTEX_FORMAT_SINT2_INT; + if (normalized) + return VERTEX_FORMAT_SINT2_NORM; + return VERTEX_FORMAT_SINT2; + case 3: + if (pureInteger) + return VERTEX_FORMAT_SINT3_INT; + if (normalized) + return VERTEX_FORMAT_SINT3_NORM; + return VERTEX_FORMAT_SINT3; + case 4: + if (pureInteger) + return VERTEX_FORMAT_SINT4_INT; + if (normalized) + return VERTEX_FORMAT_SINT4_NORM; + return VERTEX_FORMAT_SINT4; + default: + UNREACHABLE(); + break; + } + case GL_UNSIGNED_INT: + switch (components) + { + case 1: + if (pureInteger) + return VERTEX_FORMAT_UINT1_INT; + if (normalized) + return VERTEX_FORMAT_UINT1_NORM; + return VERTEX_FORMAT_UINT1; + case 2: + if (pureInteger) + return VERTEX_FORMAT_UINT2_INT; + if (normalized) + return VERTEX_FORMAT_UINT2_NORM; + return VERTEX_FORMAT_UINT2; + case 3: + if (pureInteger) + return VERTEX_FORMAT_UINT3_INT; + if (normalized) + return VERTEX_FORMAT_UINT3_NORM; + return VERTEX_FORMAT_UINT3; + case 4: + if (pureInteger) + return VERTEX_FORMAT_UINT4_INT; + if (normalized) + return VERTEX_FORMAT_UINT4_NORM; + return VERTEX_FORMAT_UINT4; + default: + UNREACHABLE(); + break; + } + case GL_FLOAT: + switch (components) + { + case 1: + return VERTEX_FORMAT_FLOAT1; + case 2: + return VERTEX_FORMAT_FLOAT2; + case 3: + return VERTEX_FORMAT_FLOAT3; + case 4: + return VERTEX_FORMAT_FLOAT4; + default: + UNREACHABLE(); + break; + } + case GL_HALF_FLOAT: + switch (components) + { + case 1: + return VERTEX_FORMAT_HALF1; + case 2: + return VERTEX_FORMAT_HALF2; + case 3: + return VERTEX_FORMAT_HALF3; + case 4: + return VERTEX_FORMAT_HALF4; + default: + UNREACHABLE(); + break; + } + case GL_FIXED: + switch (components) + { + case 1: + return VERTEX_FORMAT_FIXED1; + case 2: + return VERTEX_FORMAT_FIXED2; + case 3: + return VERTEX_FORMAT_FIXED3; + case 4: + return VERTEX_FORMAT_FIXED4; + default: + UNREACHABLE(); + break; + } + case GL_INT_2_10_10_10_REV: + if (pureInteger) + return VERTEX_FORMAT_SINT210_INT; + if (normalized) + return VERTEX_FORMAT_SINT210_NORM; + return VERTEX_FORMAT_SINT210; + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (pureInteger) + return VERTEX_FORMAT_UINT210_INT; + if (normalized) + return VERTEX_FORMAT_UINT210_NORM; + return VERTEX_FORMAT_UINT210; + default: + UNREACHABLE(); + break; + } + return VERTEX_FORMAT_UBYTE1; +} + +VertexFormatType GetVertexFormatType(const VertexAttribute &attrib) +{ + return GetVertexFormatType(attrib.type, attrib.normalized, attrib.size, attrib.pureInteger); +} + +VertexFormatType GetVertexFormatType(const VertexAttribute &attrib, GLenum currentValueType) +{ + if (!attrib.enabled) + { + return GetVertexFormatType(currentValueType, GL_FALSE, 4, (currentValueType != GL_FLOAT)); + } + return GetVertexFormatType(attrib); +} + +const VertexFormat &GetVertexFormatFromType(VertexFormatType vertexFormatType) +{ + switch (vertexFormatType) + { + case VERTEX_FORMAT_SBYTE1: + { + static const VertexFormat format(GL_BYTE, GL_FALSE, 1, false); + return format; + } + case VERTEX_FORMAT_SBYTE1_NORM: + { + static const VertexFormat format(GL_BYTE, GL_TRUE, 1, false); + return format; + } + case VERTEX_FORMAT_SBYTE2: + { + static const VertexFormat format(GL_BYTE, GL_FALSE, 2, false); + return format; + } + case VERTEX_FORMAT_SBYTE2_NORM: + { + static const VertexFormat format(GL_BYTE, GL_TRUE, 2, false); + return format; + } + case VERTEX_FORMAT_SBYTE3: + { + static const VertexFormat format(GL_BYTE, GL_FALSE, 3, false); + return format; + } + case VERTEX_FORMAT_SBYTE3_NORM: + { + static const VertexFormat format(GL_BYTE, GL_TRUE, 3, false); + return format; + } + case VERTEX_FORMAT_SBYTE4: + { + static const VertexFormat format(GL_BYTE, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_SBYTE4_NORM: + { + static const VertexFormat format(GL_BYTE, GL_TRUE, 4, false); + return format; + } + case VERTEX_FORMAT_UBYTE1: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 1, false); + return format; + } + case VERTEX_FORMAT_UBYTE1_NORM: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 1, false); + return format; + } + case VERTEX_FORMAT_UBYTE2: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 2, false); + return format; + } + case VERTEX_FORMAT_UBYTE2_NORM: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 2, false); + return format; + } + case VERTEX_FORMAT_UBYTE3: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 3, false); + return format; + } + case VERTEX_FORMAT_UBYTE3_NORM: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 3, false); + return format; + } + case VERTEX_FORMAT_UBYTE4: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_UBYTE4_NORM: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_TRUE, 4, false); + return format; + } + case VERTEX_FORMAT_SSHORT1: + { + static const VertexFormat format(GL_SHORT, GL_FALSE, 1, false); + return format; + } + case VERTEX_FORMAT_SSHORT1_NORM: + { + static const VertexFormat format(GL_SHORT, GL_TRUE, 1, false); + return format; + } + case VERTEX_FORMAT_SSHORT2: + { + static const VertexFormat format(GL_SHORT, GL_FALSE, 2, false); + return format; + } + case VERTEX_FORMAT_SSHORT2_NORM: + { + static const VertexFormat format(GL_SHORT, GL_TRUE, 2, false); + return format; + } + case VERTEX_FORMAT_SSHORT3: + { + static const VertexFormat format(GL_SHORT, GL_FALSE, 3, false); + return format; + } + case VERTEX_FORMAT_SSHORT3_NORM: + { + static const VertexFormat format(GL_SHORT, GL_TRUE, 3, false); + return format; + } + case VERTEX_FORMAT_SSHORT4: + { + static const VertexFormat format(GL_SHORT, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_SSHORT4_NORM: + { + static const VertexFormat format(GL_SHORT, GL_TRUE, 4, false); + return format; + } + case VERTEX_FORMAT_USHORT1: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 1, false); + return format; + } + case VERTEX_FORMAT_USHORT1_NORM: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 1, false); + return format; + } + case VERTEX_FORMAT_USHORT2: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 2, false); + return format; + } + case VERTEX_FORMAT_USHORT2_NORM: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 2, false); + return format; + } + case VERTEX_FORMAT_USHORT3: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 3, false); + return format; + } + case VERTEX_FORMAT_USHORT3_NORM: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 3, false); + return format; + } + case VERTEX_FORMAT_USHORT4: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_USHORT4_NORM: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_TRUE, 4, false); + return format; + } + case VERTEX_FORMAT_SINT1: + { + static const VertexFormat format(GL_INT, GL_FALSE, 1, false); + return format; + } + case VERTEX_FORMAT_SINT1_NORM: + { + static const VertexFormat format(GL_INT, GL_TRUE, 1, false); + return format; + } + case VERTEX_FORMAT_SINT2: + { + static const VertexFormat format(GL_INT, GL_FALSE, 2, false); + return format; + } + case VERTEX_FORMAT_SINT2_NORM: + { + static const VertexFormat format(GL_INT, GL_TRUE, 2, false); + return format; + } + case VERTEX_FORMAT_SINT3: + { + static const VertexFormat format(GL_INT, GL_FALSE, 3, false); + return format; + } + case VERTEX_FORMAT_SINT3_NORM: + { + static const VertexFormat format(GL_INT, GL_TRUE, 3, false); + return format; + } + case VERTEX_FORMAT_SINT4: + { + static const VertexFormat format(GL_INT, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_SINT4_NORM: + { + static const VertexFormat format(GL_INT, GL_TRUE, 4, false); + return format; + } + case VERTEX_FORMAT_UINT1: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 1, false); + return format; + } + case VERTEX_FORMAT_UINT1_NORM: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 1, false); + return format; + } + case VERTEX_FORMAT_UINT2: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 2, false); + return format; + } + case VERTEX_FORMAT_UINT2_NORM: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 2, false); + return format; + } + case VERTEX_FORMAT_UINT3: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 3, false); + return format; + } + case VERTEX_FORMAT_UINT3_NORM: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 3, false); + return format; + } + case VERTEX_FORMAT_UINT4: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_UINT4_NORM: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_TRUE, 4, false); + return format; + } + case VERTEX_FORMAT_SBYTE1_INT: + { + static const VertexFormat format(GL_BYTE, GL_FALSE, 1, true); + return format; + } + case VERTEX_FORMAT_SBYTE2_INT: + { + static const VertexFormat format(GL_BYTE, GL_FALSE, 2, true); + return format; + } + case VERTEX_FORMAT_SBYTE3_INT: + { + static const VertexFormat format(GL_BYTE, GL_FALSE, 3, true); + return format; + } + case VERTEX_FORMAT_SBYTE4_INT: + { + static const VertexFormat format(GL_BYTE, GL_FALSE, 4, true); + return format; + } + case VERTEX_FORMAT_UBYTE1_INT: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 1, true); + return format; + } + case VERTEX_FORMAT_UBYTE2_INT: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 2, true); + return format; + } + case VERTEX_FORMAT_UBYTE3_INT: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 3, true); + return format; + } + case VERTEX_FORMAT_UBYTE4_INT: + { + static const VertexFormat format(GL_UNSIGNED_BYTE, GL_FALSE, 4, true); + return format; + } + case VERTEX_FORMAT_SSHORT1_INT: + { + static const VertexFormat format(GL_SHORT, GL_FALSE, 1, true); + return format; + } + case VERTEX_FORMAT_SSHORT2_INT: + { + static const VertexFormat format(GL_SHORT, GL_FALSE, 2, true); + return format; + } + case VERTEX_FORMAT_SSHORT3_INT: + { + static const VertexFormat format(GL_SHORT, GL_FALSE, 3, true); + return format; + } + case VERTEX_FORMAT_SSHORT4_INT: + { + static const VertexFormat format(GL_SHORT, GL_FALSE, 4, true); + return format; + } + case VERTEX_FORMAT_USHORT1_INT: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 1, true); + return format; + } + case VERTEX_FORMAT_USHORT2_INT: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 2, true); + return format; + } + case VERTEX_FORMAT_USHORT3_INT: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 3, true); + return format; + } + case VERTEX_FORMAT_USHORT4_INT: + { + static const VertexFormat format(GL_UNSIGNED_SHORT, GL_FALSE, 4, true); + return format; + } + case VERTEX_FORMAT_SINT1_INT: + { + static const VertexFormat format(GL_INT, GL_FALSE, 1, true); + return format; + } + case VERTEX_FORMAT_SINT2_INT: + { + static const VertexFormat format(GL_INT, GL_FALSE, 2, true); + return format; + } + case VERTEX_FORMAT_SINT3_INT: + { + static const VertexFormat format(GL_INT, GL_FALSE, 3, true); + return format; + } + case VERTEX_FORMAT_SINT4_INT: + { + static const VertexFormat format(GL_INT, GL_FALSE, 4, true); + return format; + } + case VERTEX_FORMAT_UINT1_INT: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 1, true); + return format; + } + case VERTEX_FORMAT_UINT2_INT: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 2, true); + return format; + } + case VERTEX_FORMAT_UINT3_INT: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 3, true); + return format; + } + case VERTEX_FORMAT_UINT4_INT: + { + static const VertexFormat format(GL_UNSIGNED_INT, GL_FALSE, 4, true); + return format; + } + case VERTEX_FORMAT_FIXED1: + { + static const VertexFormat format(GL_FIXED, GL_FALSE, 1, false); + return format; + } + case VERTEX_FORMAT_FIXED2: + { + static const VertexFormat format(GL_FIXED, GL_FALSE, 2, false); + return format; + } + case VERTEX_FORMAT_FIXED3: + { + static const VertexFormat format(GL_FIXED, GL_FALSE, 3, false); + return format; + } + case VERTEX_FORMAT_FIXED4: + { + static const VertexFormat format(GL_FIXED, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_HALF1: + { + static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 1, false); + return format; + } + case VERTEX_FORMAT_HALF2: + { + static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 2, false); + return format; + } + case VERTEX_FORMAT_HALF3: + { + static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 3, false); + return format; + } + case VERTEX_FORMAT_HALF4: + { + static const VertexFormat format(GL_HALF_FLOAT, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_FLOAT1: + { + static const VertexFormat format(GL_FLOAT, GL_FALSE, 1, false); + return format; + } + case VERTEX_FORMAT_FLOAT2: + { + static const VertexFormat format(GL_FLOAT, GL_FALSE, 2, false); + return format; + } + case VERTEX_FORMAT_FLOAT3: + { + static const VertexFormat format(GL_FLOAT, GL_FALSE, 3, false); + return format; + } + case VERTEX_FORMAT_FLOAT4: + { + static const VertexFormat format(GL_FLOAT, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_SINT210: + { + static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_UINT210: + { + static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, false); + return format; + } + case VERTEX_FORMAT_SINT210_NORM: + { + static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_TRUE, 4, false); + return format; + } + case VERTEX_FORMAT_UINT210_NORM: + { + static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, false); + return format; + } + case VERTEX_FORMAT_SINT210_INT: + { + static const VertexFormat format(GL_INT_2_10_10_10_REV, GL_FALSE, 4, true); + return format; + } + case VERTEX_FORMAT_UINT210_INT: + { + static const VertexFormat format(GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, true); + return format; + } + default: + { + static const VertexFormat format(GL_NONE, GL_FALSE, 0, false); + return format; + } + } +} + +VertexFormat::VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn) + : type(typeIn), + normalized(normalizedIn), + components(componentsIn), + pureInteger(pureIntegerIn) +{ + // float -> !normalized + ASSERT(!(type == GL_FLOAT || type == GL_HALF_FLOAT || type == GL_FIXED) || normalized == GL_FALSE); +} + } diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.h b/src/3rdparty/angle/src/libANGLE/formatutils.h index 37d4a8f8ef..6863e4ddc4 100644 --- a/src/3rdparty/angle/src/libANGLE/formatutils.h +++ b/src/3rdparty/angle/src/libANGLE/formatutils.h @@ -66,8 +66,18 @@ struct InternalFormat SupportCheckFunction filterSupport; GLuint computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const; - GLuint computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const; + GLuint computeDepthPitch(GLenum formatType, + GLsizei width, + GLsizei height, + GLint alignment, + GLint rowLength, + GLint imageHeight) const; GLuint computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const; + GLuint computeSkipPixels(GLint rowPitch, + GLint depthPitch, + GLint skipImages, + GLint skipRows, + GLint skipPixels) const; }; const InternalFormat &GetInternalFormatInfo(GLenum internalFormat); @@ -76,6 +86,149 @@ GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type); typedef std::set FormatSet; const FormatSet &GetAllSizedInternalFormats(); -} +// From the ESSL 3.00.4 spec: +// Vertex shader inputs can only be float, floating-point vectors, matrices, signed and unsigned +// integers and integer vectors. Vertex shader inputs cannot be arrays or structures. + +enum AttributeType +{ + ATTRIBUTE_FLOAT, + ATTRIBUTE_VEC2, + ATTRIBUTE_VEC3, + ATTRIBUTE_VEC4, + ATTRIBUTE_INT, + ATTRIBUTE_IVEC2, + ATTRIBUTE_IVEC3, + ATTRIBUTE_IVEC4, + ATTRIBUTE_UINT, + ATTRIBUTE_UVEC2, + ATTRIBUTE_UVEC3, + ATTRIBUTE_UVEC4, + ATTRIBUTE_MAT2, + ATTRIBUTE_MAT3, + ATTRIBUTE_MAT4, + ATTRIBUTE_MAT2x3, + ATTRIBUTE_MAT2x4, + ATTRIBUTE_MAT3x2, + ATTRIBUTE_MAT3x4, + ATTRIBUTE_MAT4x2, + ATTRIBUTE_MAT4x3, +}; + +AttributeType GetAttributeType(GLenum enumValue); + +enum VertexFormatType +{ + VERTEX_FORMAT_INVALID, + VERTEX_FORMAT_SBYTE1, + VERTEX_FORMAT_SBYTE1_NORM, + VERTEX_FORMAT_SBYTE2, + VERTEX_FORMAT_SBYTE2_NORM, + VERTEX_FORMAT_SBYTE3, + VERTEX_FORMAT_SBYTE3_NORM, + VERTEX_FORMAT_SBYTE4, + VERTEX_FORMAT_SBYTE4_NORM, + VERTEX_FORMAT_UBYTE1, + VERTEX_FORMAT_UBYTE1_NORM, + VERTEX_FORMAT_UBYTE2, + VERTEX_FORMAT_UBYTE2_NORM, + VERTEX_FORMAT_UBYTE3, + VERTEX_FORMAT_UBYTE3_NORM, + VERTEX_FORMAT_UBYTE4, + VERTEX_FORMAT_UBYTE4_NORM, + VERTEX_FORMAT_SSHORT1, + VERTEX_FORMAT_SSHORT1_NORM, + VERTEX_FORMAT_SSHORT2, + VERTEX_FORMAT_SSHORT2_NORM, + VERTEX_FORMAT_SSHORT3, + VERTEX_FORMAT_SSHORT3_NORM, + VERTEX_FORMAT_SSHORT4, + VERTEX_FORMAT_SSHORT4_NORM, + VERTEX_FORMAT_USHORT1, + VERTEX_FORMAT_USHORT1_NORM, + VERTEX_FORMAT_USHORT2, + VERTEX_FORMAT_USHORT2_NORM, + VERTEX_FORMAT_USHORT3, + VERTEX_FORMAT_USHORT3_NORM, + VERTEX_FORMAT_USHORT4, + VERTEX_FORMAT_USHORT4_NORM, + VERTEX_FORMAT_SINT1, + VERTEX_FORMAT_SINT1_NORM, + VERTEX_FORMAT_SINT2, + VERTEX_FORMAT_SINT2_NORM, + VERTEX_FORMAT_SINT3, + VERTEX_FORMAT_SINT3_NORM, + VERTEX_FORMAT_SINT4, + VERTEX_FORMAT_SINT4_NORM, + VERTEX_FORMAT_UINT1, + VERTEX_FORMAT_UINT1_NORM, + VERTEX_FORMAT_UINT2, + VERTEX_FORMAT_UINT2_NORM, + VERTEX_FORMAT_UINT3, + VERTEX_FORMAT_UINT3_NORM, + VERTEX_FORMAT_UINT4, + VERTEX_FORMAT_UINT4_NORM, + VERTEX_FORMAT_SBYTE1_INT, + VERTEX_FORMAT_SBYTE2_INT, + VERTEX_FORMAT_SBYTE3_INT, + VERTEX_FORMAT_SBYTE4_INT, + VERTEX_FORMAT_UBYTE1_INT, + VERTEX_FORMAT_UBYTE2_INT, + VERTEX_FORMAT_UBYTE3_INT, + VERTEX_FORMAT_UBYTE4_INT, + VERTEX_FORMAT_SSHORT1_INT, + VERTEX_FORMAT_SSHORT2_INT, + VERTEX_FORMAT_SSHORT3_INT, + VERTEX_FORMAT_SSHORT4_INT, + VERTEX_FORMAT_USHORT1_INT, + VERTEX_FORMAT_USHORT2_INT, + VERTEX_FORMAT_USHORT3_INT, + VERTEX_FORMAT_USHORT4_INT, + VERTEX_FORMAT_SINT1_INT, + VERTEX_FORMAT_SINT2_INT, + VERTEX_FORMAT_SINT3_INT, + VERTEX_FORMAT_SINT4_INT, + VERTEX_FORMAT_UINT1_INT, + VERTEX_FORMAT_UINT2_INT, + VERTEX_FORMAT_UINT3_INT, + VERTEX_FORMAT_UINT4_INT, + VERTEX_FORMAT_FIXED1, + VERTEX_FORMAT_FIXED2, + VERTEX_FORMAT_FIXED3, + VERTEX_FORMAT_FIXED4, + VERTEX_FORMAT_HALF1, + VERTEX_FORMAT_HALF2, + VERTEX_FORMAT_HALF3, + VERTEX_FORMAT_HALF4, + VERTEX_FORMAT_FLOAT1, + VERTEX_FORMAT_FLOAT2, + VERTEX_FORMAT_FLOAT3, + VERTEX_FORMAT_FLOAT4, + VERTEX_FORMAT_SINT210, + VERTEX_FORMAT_UINT210, + VERTEX_FORMAT_SINT210_NORM, + VERTEX_FORMAT_UINT210_NORM, + VERTEX_FORMAT_SINT210_INT, + VERTEX_FORMAT_UINT210_INT, +}; + +typedef std::vector InputLayout; + +struct VertexFormat : angle::NonCopyable +{ + VertexFormat(GLenum typeIn, GLboolean normalizedIn, GLuint componentsIn, bool pureIntegerIn); + + GLenum type; + GLboolean normalized; + GLuint components; + bool pureInteger; +}; + +VertexFormatType GetVertexFormatType(GLenum type, GLboolean normalized, GLuint components, bool pureInteger); +VertexFormatType GetVertexFormatType(const VertexAttribute &attrib); +VertexFormatType GetVertexFormatType(const VertexAttribute &attrib, GLenum currentValueType); +const VertexFormat &GetVertexFormatFromType(VertexFormatType vertexFormatType); + +} // namespace gl #endif // LIBANGLE_FORMATUTILS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/histogram_macros.h b/src/3rdparty/angle/src/libANGLE/histogram_macros.h new file mode 100644 index 0000000000..d1c952a6bd --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/histogram_macros.h @@ -0,0 +1,107 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// histogram_macros.h: +// Helpers for making histograms, to keep consistency with Chromium's +// histogram_macros.h. + +#ifndef LIBANGLE_HISTOGRAM_MACROS_H_ +#define LIBANGLE_HISTOGRAM_MACROS_H_ + +#include + +#define ANGLE_HISTOGRAM_TIMES(name, sample) ANGLE_HISTOGRAM_CUSTOM_TIMES( \ + name, sample, 1, 10000, 50) + +#define ANGLE_HISTOGRAM_MEDIUM_TIMES(name, sample) ANGLE_HISTOGRAM_CUSTOM_TIMES( \ + name, sample, 10, 180000, 50) + +// Use this macro when times can routinely be much longer than 10 seconds. +#define ANGLE_HISTOGRAM_LONG_TIMES(name, sample) ANGLE_HISTOGRAM_CUSTOM_TIMES( \ + name, sample, 1, 3600000, 50) + +// Use this macro when times can routinely be much longer than 10 seconds and +// you want 100 buckets. +#define ANGLE_HISTOGRAM_LONG_TIMES_100(name, sample) ANGLE_HISTOGRAM_CUSTOM_TIMES( \ + name, sample, 1, 3600000, 100) + +// For folks that need real specific times, use this to select a precise range +// of times you want plotted, and the number of buckets you want used. +#define ANGLE_HISTOGRAM_CUSTOM_TIMES(name, sample, min, max, bucket_count) \ + ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) + +#define ANGLE_HISTOGRAM_COUNTS(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \ + name, sample, 1, 1000000, 50) + +#define ANGLE_HISTOGRAM_COUNTS_100(name, sample) \ + ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 100, 50) + +#define ANGLE_HISTOGRAM_COUNTS_10000(name, sample) \ + ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 10000, 50) + +#define ANGLE_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, bucket_count) \ + ANGLEPlatformCurrent()->histogramCustomCounts(\ + name, sample, min, max, bucket_count) + +#define ANGLE_HISTOGRAM_PERCENTAGE(name, under_one_hundred) \ + ANGLE_HISTOGRAM_ENUMERATION(name, under_one_hundred, 101) + +#define ANGLE_HISTOGRAM_BOOLEAN(name, sample) \ + ANGLEPlatformCurrent()->histogramBoolean(name, sample) + +#define ANGLE_HISTOGRAM_ENUMERATION(name, sample, boundary_value) \ + ANGLEPlatformCurrent()->histogramEnumeration(name, sample, boundary_value) + +#define ANGLE_HISTOGRAM_MEMORY_KB(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \ + name, sample, 1000, 500000, 50) + +#define ANGLE_HISTOGRAM_MEMORY_MB(name, sample) ANGLE_HISTOGRAM_CUSTOM_COUNTS( \ + name, sample, 1, 1000, 50) + +#define ANGLE_HISTOGRAM_SPARSE_SLOWLY(name, sample) \ + ANGLEPlatformCurrent()->histogramSparse(name, sample) + +// Scoped class which logs its time on this earth as a UMA statistic. This is +// recommended for when you want a histogram which measures the time it takes +// for a method to execute. This measures up to 10 seconds. +#define SCOPED_ANGLE_HISTOGRAM_TIMER(name) \ + SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, false, __COUNTER__) + +// Similar scoped histogram timer, but this uses ANGLE_HISTOGRAM_LONG_TIMES_100, +// which measures up to an hour, and uses 100 buckets. This is more expensive +// to store, so only use if this often takes >10 seconds. +#define SCOPED_ANGLE_HISTOGRAM_LONG_TIMER(name) \ + SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, true, __COUNTER__) + +// This nested macro is necessary to expand __COUNTER__ to an actual value. +#define SCOPED_ANGLE_HISTOGRAM_TIMER_EXPANDER(name, is_long, key) \ + SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) + +#define SCOPED_ANGLE_HISTOGRAM_TIMER_UNIQUE(name, is_long, key) \ + class ScopedHistogramTimer##key \ + { \ + public: \ + ScopedHistogramTimer##key() : constructed_(ANGLEPlatformCurrent()->currentTime()) {} \ + ~ScopedHistogramTimer##key() \ + { \ + if (constructed_ == 0) \ + return; \ + double elapsed = ANGLEPlatformCurrent()->currentTime() - constructed_; \ + int elapsedMS = static_cast(elapsed * 1000.0); \ + if (is_long) \ + { \ + ANGLE_HISTOGRAM_LONG_TIMES_100(name, elapsedMS); \ + } \ + else \ + { \ + ANGLE_HISTOGRAM_TIMES(name, elapsedMS); \ + } \ + } \ + \ + private: \ + double constructed_; \ + } scoped_histogram_timer_##key + +#endif // BASE_METRICS_HISTOGRAM_MACROS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/queryconversions.cpp b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp index 460e346eac..3a6059a89c 100644 --- a/src/3rdparty/angle/src/libANGLE/queryconversions.cpp +++ b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp @@ -6,41 +6,48 @@ // queryconversions.cpp: Implementation of state query cast conversions +#include "libANGLE/queryconversions.h" + +#include + #include "libANGLE/Context.h" #include "common/utilities.h" namespace gl { -// Helper class for converting a GL type to a GLenum: -// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap. -// We restrict our use to CastStateValue, where it eliminates duplicate parameters. +namespace +{ -template -struct CastStateValueEnum { static GLenum mEnumForType; }; +GLint64 ExpandFloatToInteger(GLfloat value) +{ + return static_cast((static_cast(0xFFFFFFFFULL) * value - 1.0) / 2.0); +} -template <> GLenum CastStateValueEnum::mEnumForType = GL_INT; -template <> GLenum CastStateValueEnum::mEnumForType = GL_UNSIGNED_INT; -template <> GLenum CastStateValueEnum::mEnumForType = GL_BOOL; -template <> GLenum CastStateValueEnum::mEnumForType = GL_INT_64_ANGLEX; -template <> GLenum CastStateValueEnum::mEnumForType = GL_FLOAT; +template +QueryT ClampToQueryRange(GLint64 value) +{ + const GLint64 min = static_cast(std::numeric_limits::min()); + const GLint64 max = static_cast(std::numeric_limits::max()); + return static_cast(clamp(value, min, max)); +} template QueryT CastStateValueToInt(GLenum pname, NativeT value) { - GLenum queryType = CastStateValueEnum::mEnumForType; - GLenum nativeType = CastStateValueEnum::mEnumForType; + GLenum queryType = GLTypeToGLenum::value; + GLenum nativeType = GLTypeToGLenum::value; if (nativeType == GL_FLOAT) { // RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from Table 4.5 if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR) { - return static_cast((static_cast(0xFFFFFFFF) * value - 1.0f) / 2.0f); + return ClampToQueryRange(ExpandFloatToInteger(static_cast(value))); } else { - return gl::iround(value); + return gl::iround(static_cast(value)); } } @@ -59,77 +66,80 @@ QueryT CastStateValueToInt(GLenum pname, NativeT value) template QueryT CastStateValue(GLenum pname, NativeT value) { - GLenum queryType = CastStateValueEnum::mEnumForType; + GLenum queryType = GLTypeToGLenum::value; switch (queryType) { - case GL_INT: return CastStateValueToInt(pname, value); - case GL_INT_64_ANGLEX: return CastStateValueToInt(pname, value); - case GL_FLOAT: return static_cast(value); - case GL_BOOL: return (value == static_cast(0) ? GL_FALSE : GL_TRUE); - default: UNREACHABLE(); return 0; + case GL_INT: + return CastStateValueToInt(pname, value); + case GL_INT_64_ANGLEX: + return CastStateValueToInt(pname, value); + case GL_FLOAT: + return static_cast(value); + case GL_BOOL: + return static_cast(value == static_cast(0) ? GL_FALSE : GL_TRUE); + default: + UNREACHABLE(); + return 0; } } +} // anonymous namespace + +template <> +GLenum GLTypeToGLenum::value = GL_INT; +template <> +GLenum GLTypeToGLenum::value = GL_UNSIGNED_INT; +template <> +GLenum GLTypeToGLenum::value = GL_BOOL; +template <> +GLenum GLTypeToGLenum::value = GL_INT_64_ANGLEX; +template <> +GLenum GLTypeToGLenum::value = GL_FLOAT; + template void CastStateValues(Context *context, GLenum nativeType, GLenum pname, unsigned int numParams, QueryT *outParams) { if (nativeType == GL_INT) { - GLint *intParams = NULL; - intParams = new GLint[numParams]; - - context->getIntegerv(pname, intParams); + std::vector intParams(numParams, 0); + context->getIntegerv(pname, intParams.data()); for (unsigned int i = 0; i < numParams; ++i) { outParams[i] = CastStateValue(pname, intParams[i]); } - - delete [] intParams; } else if (nativeType == GL_BOOL) { - GLboolean *boolParams = NULL; - boolParams = new GLboolean[numParams]; - - context->getBooleanv(pname, boolParams); + std::vector boolParams(numParams, GL_FALSE); + context->getBooleanv(pname, boolParams.data()); for (unsigned int i = 0; i < numParams; ++i) { outParams[i] = (boolParams[i] == GL_FALSE ? static_cast(0) : static_cast(1)); } - - delete [] boolParams; } else if (nativeType == GL_FLOAT) { - GLfloat *floatParams = NULL; - floatParams = new GLfloat[numParams]; - - context->getFloatv(pname, floatParams); + std::vector floatParams(numParams, 0.0f); + context->getFloatv(pname, floatParams.data()); for (unsigned int i = 0; i < numParams; ++i) { outParams[i] = CastStateValue(pname, floatParams[i]); } - - delete [] floatParams; } else if (nativeType == GL_INT_64_ANGLEX) { - GLint64 *int64Params = NULL; - int64Params = new GLint64[numParams]; - - context->getInteger64v(pname, int64Params); + std::vector int64Params(numParams, 0); + context->getInteger64v(pname, int64Params.data()); for (unsigned int i = 0; i < numParams; ++i) { outParams[i] = CastStateValue(pname, int64Params[i]); } - - delete [] int64Params; } else UNREACHABLE(); } diff --git a/src/3rdparty/angle/src/libANGLE/queryconversions.h b/src/3rdparty/angle/src/libANGLE/queryconversions.h index da7047f730..e0fdbe17e0 100644 --- a/src/3rdparty/angle/src/libANGLE/queryconversions.h +++ b/src/3rdparty/angle/src/libANGLE/queryconversions.h @@ -6,8 +6,25 @@ // queryconversions.h: Declaration of state query cast conversions +#ifndef LIBANGLE_QUERY_CONVERSIONS_H_ +#define LIBANGLE_QUERY_CONVERSIONS_H_ + +#include "angle_gl.h" +#include "common/angleutils.h" + namespace gl { +class Context; + +// Helper class for converting a GL type to a GLenum: +// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap. +// We restrict our use to CastStateValue, where it eliminates duplicate parameters. + +template +struct GLTypeToGLenum +{ + static GLenum value; +}; // The GL state query API types are: bool, int, uint, float, int64 template @@ -15,3 +32,5 @@ void CastStateValues(Context *context, GLenum nativeType, GLenum pname, unsigned int numParams, QueryT *outParams); } + +#endif // LIBANGLE_QUERY_CONVERSIONS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h index 9bc5eaff58..d77f06cf09 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h @@ -10,7 +10,8 @@ #define LIBANGLE_RENDERER_BUFFERIMPL_H_ #include "common/angleutils.h" -#include "libANGLE/Buffer.h" +#include "common/mathutil.h" +#include "libANGLE/Error.h" #include @@ -25,12 +26,15 @@ class BufferImpl : angle::NonCopyable virtual gl::Error setData(const void* data, size_t size, GLenum usage) = 0; virtual gl::Error setSubData(const void* data, size_t size, size_t offset) = 0; virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0; - virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0; - virtual gl::Error unmap() = 0; - - // This method may not have a corresponding GL-backed function. It is necessary - // for validation, for certain indexed draw calls. - virtual gl::Error getData(const uint8_t **outData) = 0; + virtual gl::Error map(GLenum access, GLvoid **mapPtr) = 0; + virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0; + virtual gl::Error unmap(GLboolean *result) = 0; + + virtual gl::Error getIndexRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + gl::IndexRange *outRange) = 0; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl_mock.h new file mode 100644 index 0000000000..a6387661ce --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl_mock.h @@ -0,0 +1,38 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferImpl_mock.h: Defines a mock of the BufferImpl class. + +#ifndef LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_ +#define LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_ + +#include "gmock/gmock.h" + +#include "libANGLE/renderer/BufferImpl.h" + +namespace rx +{ + +class MockBufferImpl : public BufferImpl +{ + public: + ~MockBufferImpl() { destructor(); } + + MOCK_METHOD3(setData, gl::Error(const void*, size_t, GLenum)); + MOCK_METHOD3(setSubData, gl::Error(const void*, size_t, size_t)); + MOCK_METHOD4(copySubData, gl::Error(BufferImpl *, GLintptr, GLintptr, GLsizeiptr)); + MOCK_METHOD2(map, gl::Error(GLenum, GLvoid **)); + MOCK_METHOD4(mapRange, gl::Error(size_t, size_t, GLbitfield, GLvoid **)); + MOCK_METHOD1(unmap, gl::Error(GLboolean *result)); + + MOCK_METHOD5(getIndexRange, gl::Error(GLenum, size_t, size_t, bool, gl::IndexRange *)); + + MOCK_METHOD0(destructor, void()); +}; + +} + +#endif // LIBANGLE_RENDERER_BUFFERIMPLMOCK_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h index ccc78d8c2a..82f1ffe0d3 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h @@ -8,6 +8,7 @@ // for the gl::Compiler object. #include "common/angleutils.h" +#include "GLSLANG/ShaderLang.h" #include "libANGLE/Error.h" #ifndef LIBANGLE_RENDERER_COMPILERIMPL_H_ @@ -23,6 +24,9 @@ class CompilerImpl : angle::NonCopyable virtual ~CompilerImpl() {} virtual gl::Error release() = 0; + + // TODO(jmadill): Expose translator built-in resources init method. + virtual ShShaderOutput getTranslatorOutputType() const = 0; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DeviceImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/DeviceImpl.cpp new file mode 100644 index 0000000000..6a166236d0 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/DeviceImpl.cpp @@ -0,0 +1,22 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DeviceImpl.cpp: Implementation methods of egl::Device + +#include "libANGLE/renderer/DeviceImpl.h" + +namespace rx +{ + +DeviceImpl::DeviceImpl() +{ +} + +DeviceImpl::~DeviceImpl() +{ +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DeviceImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/DeviceImpl.h new file mode 100644 index 0000000000..550bc1e2d9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/DeviceImpl.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DeviceImpl.h: Implementation methods of egl::Device + +#ifndef LIBANGLE_RENDERER_DEVICEIMPL_H_ +#define LIBANGLE_RENDERER_DEVICEIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" +#include "libANGLE/Caps.h" + +namespace egl +{ +class Device; +} + +namespace rx +{ +class DeviceImpl : angle::NonCopyable +{ + public: + DeviceImpl(); + virtual ~DeviceImpl(); + + virtual egl::Error getDevice(void **outValue) = 0; + virtual EGLint getType() = 0; + virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0; + virtual bool deviceExternallySourced() = 0; +}; + +} + +#endif // LIBANGLE_RENDERER_DEVICEIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp index 7713ee2d6d..8061189f0a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp @@ -21,16 +21,13 @@ DisplayImpl::DisplayImpl() DisplayImpl::~DisplayImpl() { - while (!mSurfaceSet.empty()) - { - destroySurface(*mSurfaceSet.begin()); - } + ASSERT(mSurfaceSet.empty()); } void DisplayImpl::destroySurface(egl::Surface *surface) { mSurfaceSet.erase(surface); - surface->release(); + surface->onDestroy(); } const egl::DisplayExtensions &DisplayImpl::getExtensions() const diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h index 381fa67f71..9e38f63370 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h @@ -24,6 +24,7 @@ class AttributeMap; class Display; struct Config; class Surface; +class ImageSibling; } namespace gl @@ -34,7 +35,9 @@ class Context; namespace rx { class SurfaceImpl; +class ImageImpl; struct ConfigDesc; +class DeviceImpl; class DisplayImpl : angle::NonCopyable { @@ -45,16 +48,25 @@ class DisplayImpl : angle::NonCopyable virtual egl::Error initialize(egl::Display *display) = 0; virtual void terminate() = 0; - virtual egl::Error createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, const egl::AttributeMap &attribs, - SurfaceImpl **outSurface) = 0; - virtual egl::Error createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs, - SurfaceImpl **outSurface) = 0; - virtual egl::Error createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle, - const egl::AttributeMap &attribs, SurfaceImpl **outSurface) = 0; - virtual egl::Error createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap, - const egl::AttributeMap &attribs, SurfaceImpl **outSurface) = 0; - virtual egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, - gl::Context **outContext) = 0; + virtual SurfaceImpl *createWindowSurface(const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) = 0; + virtual SurfaceImpl *createPbufferSurface(const egl::Config *configuration, + const egl::AttributeMap &attribs) = 0; + virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::Config *configuration, + EGLClientBuffer shareHandle, + const egl::AttributeMap &attribs) = 0; + virtual SurfaceImpl *createPixmapSurface(const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) = 0; + + virtual ImageImpl *createImage(EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) = 0; + + virtual gl::Context *createContext(const egl::Config *config, + const gl::Context *shareContext, + const egl::AttributeMap &attribs) = 0; virtual egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) = 0; @@ -68,6 +80,13 @@ class DisplayImpl : angle::NonCopyable virtual std::string getVendorString() const = 0; + virtual egl::Error getDevice(DeviceImpl **device) = 0; + + virtual egl::Error waitClient() const = 0; + virtual egl::Error waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const = 0; + const egl::Caps &getCaps() const; typedef std::set SurfaceSet; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h index 3463921d6e..a534914970 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h @@ -24,9 +24,9 @@ class FenceNVImpl : angle::NonCopyable FenceNVImpl() { }; virtual ~FenceNVImpl() { }; - virtual gl::Error set() = 0; - virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0; - virtual gl::Error finishFence(GLboolean *outFinished) = 0; + virtual gl::Error set(GLenum condition) = 0; + virtual gl::Error test(GLboolean *outFinished) = 0; + virtual gl::Error finish() = 0; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h index 321964113f..6b78e69d47 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h @@ -24,7 +24,7 @@ class FenceSyncImpl : angle::NonCopyable FenceSyncImpl() { }; virtual ~FenceSyncImpl() { }; - virtual gl::Error set() = 0; + virtual gl::Error set(GLenum condition, GLbitfield flags) = 0; virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0; virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0; virtual gl::Error getStatus(GLint *outResult) = 0; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h index 728f949a0f..680122d0ed 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h @@ -31,22 +31,28 @@ class FramebufferImpl : angle::NonCopyable explicit FramebufferImpl(const gl::Framebuffer::Data &data) : mData(data) { } virtual ~FramebufferImpl() { } - virtual void setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment) = 0; - virtual void setDepthAttachment(const gl::FramebufferAttachment *attachment) = 0; - virtual void setStencilAttachment(const gl::FramebufferAttachment *attachment) = 0; - virtual void setDepthStencilAttachment(const gl::FramebufferAttachment *attachment) = 0; - - virtual void setDrawBuffers(size_t count, const GLenum *buffers) = 0; - virtual void setReadBuffer(GLenum buffer) = 0; - + virtual gl::Error discard(size_t count, const GLenum *attachments) = 0; virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0; virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0; virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0; - virtual gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0; - virtual gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0; - virtual gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) = 0; - virtual gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0; + virtual gl::Error clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) = 0; + virtual gl::Error clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) = 0; + virtual gl::Error clearBufferiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLint *values) = 0; + virtual gl::Error clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) = 0; virtual GLenum getImplementationColorReadFormat() const = 0; virtual GLenum getImplementationColorReadType() const = 0; @@ -55,7 +61,9 @@ class FramebufferImpl : angle::NonCopyable virtual gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) = 0; - virtual GLenum checkStatus() const = 0; + virtual bool checkStatus() const = 0; + + virtual void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) = 0; const gl::Framebuffer::Data &getData() const { return mData; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl_mock.h new file mode 100644 index 0000000000..57c95342d7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl_mock.h @@ -0,0 +1,72 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// FramebufferImpl_mock.h: +// Defines a mock of the FramebufferImpl class. +// + +#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_ +#define LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_ + +#include "gmock/gmock.h" + +#include "libANGLE/renderer/FramebufferImpl.h" + +namespace rx +{ + +class MockFramebufferImpl : public rx::FramebufferImpl +{ + public: + MockFramebufferImpl() : rx::FramebufferImpl(gl::Framebuffer::Data()) {} + virtual ~MockFramebufferImpl() { destroy(); } + + MOCK_METHOD2(discard, gl::Error(size_t, const GLenum *)); + MOCK_METHOD2(invalidate, gl::Error(size_t, const GLenum *)); + MOCK_METHOD3(invalidateSub, gl::Error(size_t, const GLenum *, const gl::Rectangle &)); + + MOCK_METHOD2(clear, gl::Error(const gl::Data &, GLbitfield)); + MOCK_METHOD4(clearBufferfv, gl::Error(const gl::Data &, GLenum, GLint, const GLfloat *)); + MOCK_METHOD4(clearBufferuiv, gl::Error(const gl::Data &, GLenum, GLint, const GLuint *)); + MOCK_METHOD4(clearBufferiv, gl::Error(const gl::Data &, GLenum, GLint, const GLint *)); + MOCK_METHOD5(clearBufferfi, gl::Error(const gl::Data &, GLenum, GLint, GLfloat, GLint)); + + MOCK_CONST_METHOD0(getImplementationColorReadFormat, GLenum()); + MOCK_CONST_METHOD0(getImplementationColorReadType, GLenum()); + MOCK_CONST_METHOD5( + readPixels, + gl::Error(const gl::State &, const gl::Rectangle &, GLenum, GLenum, GLvoid *)); + + MOCK_METHOD6(blit, + gl::Error(const gl::State &, + const gl::Rectangle &, + const gl::Rectangle &, + GLbitfield, + GLenum, + const gl::Framebuffer *)); + + MOCK_CONST_METHOD0(checkStatus, bool()); + + MOCK_METHOD1(syncState, void(const gl::Framebuffer::DirtyBits &)); + + MOCK_METHOD0(destroy, void()); +}; + +inline ::testing::NiceMock *MakeFramebufferMock() +{ + ::testing::NiceMock *framebufferImpl = + new ::testing::NiceMock(); + // TODO(jmadill): add ON_CALLS for other returning methods + ON_CALL(*framebufferImpl, checkStatus()).WillByDefault(::testing::Return(true)); + + // We must mock the destructor since NiceMock doesn't work for destructors. + EXPECT_CALL(*framebufferImpl, destroy()).Times(1).RetiresOnSaturation(); + + return framebufferImpl; +} + +} // namespace rx + +#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPLMOCK_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl.h new file mode 100644 index 0000000000..e48f1946a8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ImageImpl.h: Defines the rx::ImageImpl class representing the EGLimage object. + +#ifndef LIBANGLE_RENDERER_IMAGEIMPL_H_ +#define LIBANGLE_RENDERER_IMAGEIMPL_H_ + +#include "common/angleutils.h" +#include "libANGLE/Error.h" + +namespace egl +{ +class ImageSibling; +} + +namespace rx +{ +class ImageImpl : angle::NonCopyable +{ + public: + virtual ~ImageImpl() {} + virtual egl::Error initialize() = 0; + + virtual gl::Error orphan(egl::ImageSibling *sibling) = 0; +}; +} + +#endif // LIBANGLE_RENDERER_IMAGEIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl_mock.h new file mode 100644 index 0000000000..27fe6a3947 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/ImageImpl_mock.h @@ -0,0 +1,28 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ImageImpl_mock.h: Defines a mock of the ImageImpl class. + +#ifndef LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_ +#define LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_ + +#include "gmock/gmock.h" + +#include "libANGLE/renderer/ImageImpl.h" + +namespace rx +{ +class MockImageImpl : public ImageImpl +{ + public: + virtual ~MockImageImpl() { destructor(); } + MOCK_METHOD0(initialize, egl::Error(void)); + MOCK_METHOD1(orphan, gl::Error(egl::ImageSibling *)); + MOCK_METHOD0(destructor, void()); +}; +} + +#endif // LIBANGLE_RENDERER_IMAGEIMPLMOCK_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h b/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h index d77e59f7df..b988fcf97f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h @@ -11,6 +11,9 @@ #define LIBANGLE_RENDERER_IMPLFACTORY_H_ #include "libANGLE/Framebuffer.h" +#include "libANGLE/Program.h" +#include "libANGLE/Shader.h" +#include "libANGLE/VertexArray.h" namespace rx { @@ -22,6 +25,7 @@ class FramebufferImpl; class ProgramImpl; class QueryImpl; class RenderbufferImpl; +class SamplerImpl; class ShaderImpl; class TextureImpl; class TransformFeedbackImpl; @@ -34,12 +38,11 @@ class ImplFactory : angle::NonCopyable virtual ~ImplFactory() {} // Shader creation - virtual CompilerImpl *createCompiler(const gl::Data &data) = 0; - virtual ShaderImpl *createShader(GLenum type) = 0; - virtual ProgramImpl *createProgram() = 0; + virtual CompilerImpl *createCompiler() = 0; + virtual ShaderImpl *createShader(const gl::Shader::Data &data) = 0; + virtual ProgramImpl *createProgram(const gl::Program::Data &data) = 0; // Framebuffer creation - virtual FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) = 0; virtual FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) = 0; // Texture creation @@ -52,7 +55,7 @@ class ImplFactory : angle::NonCopyable virtual BufferImpl *createBuffer() = 0; // Vertex Array creation - virtual VertexArrayImpl *createVertexArray() = 0; + virtual VertexArrayImpl *createVertexArray(const gl::VertexArray::Data &data) = 0; // Query and Fence creation virtual QueryImpl *createQuery(GLenum type) = 0; @@ -61,6 +64,9 @@ class ImplFactory : angle::NonCopyable // Transform Feedback creation virtual TransformFeedbackImpl *createTransformFeedback() = 0; + + // Sampler object creation + virtual SamplerImpl *createSampler() = 0; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp deleted file mode 100644 index 4a71cf4b45..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about -// ranges of indices. - -#include "libANGLE/renderer/IndexRangeCache.h" -#include "libANGLE/formatutils.h" - -#include "common/debug.h" - -namespace rx -{ - -template -static RangeUI ComputeTypedRange(const IndexType *indices, GLsizei count) -{ - unsigned int minIndex = indices[0]; - unsigned int maxIndex = indices[0]; - - for (GLsizei i = 1; i < count; i++) - { - if (minIndex > indices[i]) minIndex = indices[i]; - if (maxIndex < indices[i]) maxIndex = indices[i]; - } - - return RangeUI(minIndex, maxIndex); -} - -RangeUI IndexRangeCache::ComputeRange(GLenum type, const GLvoid *indices, GLsizei count) -{ - switch (type) - { - case GL_UNSIGNED_BYTE: - return ComputeTypedRange(static_cast(indices), count); - case GL_UNSIGNED_INT: - return ComputeTypedRange(static_cast(indices), count); - case GL_UNSIGNED_SHORT: - return ComputeTypedRange(static_cast(indices), count); - default: - UNREACHABLE(); - return RangeUI(); - } -} - -void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range) -{ - mIndexRangeCache[IndexRange(type, offset, count)] = range; -} - -void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) -{ - unsigned int invalidateStart = offset; - unsigned int invalidateEnd = offset + size; - - IndexRangeMap::iterator i = mIndexRangeCache.begin(); - while (i != mIndexRangeCache.end()) - { - unsigned int rangeStart = i->first.offset; - unsigned int rangeEnd = i->first.offset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count); - - if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) - { - ++i; - } - else - { - mIndexRangeCache.erase(i++); - } - } -} - -bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, - RangeUI *outRange) const -{ - IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count)); - if (i != mIndexRangeCache.end()) - { - if (outRange) *outRange = i->second; - return true; - } - else - { - if (outRange) *outRange = RangeUI(0, 0); - return false; - } -} - -void IndexRangeCache::clear() -{ - mIndexRangeCache.clear(); -} - -IndexRangeCache::IndexRange::IndexRange() - : type(GL_NONE), offset(0), count(0) -{ -} - -IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c) - : type(typ), offset(off), count(c) -{ -} - -bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const -{ - if (type != rhs.type) return type < rhs.type; - if (offset != rhs.offset) return offset < rhs.offset; - return count < rhs.count; -} - -} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h deleted file mode 100644 index 77249f5ff6..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexRangeCache.h: Defines the rx::IndexRangeCache class which stores information about -// ranges of indices. - -#ifndef LIBANGLE_RENDERER_INDEXRANGECACHE_H_ -#define LIBANGLE_RENDERER_INDEXRANGECACHE_H_ - -#include "common/angleutils.h" -#include "common/mathutil.h" - -#include "angle_gl.h" - -#include - -namespace rx -{ - -class IndexRangeCache -{ - public: - void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range); - bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut) const; - - void invalidateRange(unsigned int offset, unsigned int size); - void clear(); - - static RangeUI ComputeRange(GLenum type, const GLvoid *indices, GLsizei count); - - private: - struct IndexRange - { - GLenum type; - unsigned int offset; - GLsizei count; - - IndexRange(); - IndexRange(GLenum type, intptr_t offset, GLsizei count); - - bool operator<(const IndexRange& rhs) const; - }; - - typedef std::map IndexRangeMap; - IndexRangeMap mIndexRangeCache; -}; - -} - -#endif // LIBANGLE_RENDERER_INDEXRANGECACHE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h index 1128ab6741..1e688045a1 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h @@ -23,33 +23,24 @@ namespace rx struct LinkResult { + LinkResult(bool linkSuccess, const gl::Error &error) : linkSuccess(linkSuccess), error(error) {} + bool linkSuccess; gl::Error error; - LinkResult(bool linkSuccess, const gl::Error &error); }; class ProgramImpl : angle::NonCopyable { public: - typedef int SemanticIndexArray[gl::MAX_VERTEX_ATTRIBS]; - - ProgramImpl() { } - virtual ~ProgramImpl(); - - virtual bool usesPointSize() const = 0; - virtual int getShaderVersion() const = 0; - virtual GLenum getTransformFeedbackBufferMode() const = 0; + ProgramImpl(const gl::Program::Data &data) : mData(data) {} + virtual ~ProgramImpl() {} - virtual GLenum getBinaryFormat() = 0; virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; virtual gl::Error save(gl::BinaryOutputStream *stream) = 0; + virtual void setBinaryRetrievableHint(bool retrievable) = 0; - virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, - gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode, - int *registers, std::vector *linkedVaryings, - std::map *outputVariables) = 0; + virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) = 0; + virtual GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) = 0; virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0; virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0; @@ -73,63 +64,20 @@ class ProgramImpl : angle::NonCopyable virtual void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; virtual void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) = 0; - virtual void getUniformfv(GLint location, GLfloat *params) = 0; - virtual void getUniformiv(GLint location, GLint *params) = 0; - virtual void getUniformuiv(GLint location, GLuint *params) = 0; - - // TODO: The following functions are possibly only applicable to D3D backends. The should be carefully evaluated to - // determine if they can be removed from this interface. - virtual GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const = 0; - virtual GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const = 0; - virtual GLint getUsedSamplerRange(gl::SamplerType type) const = 0; - virtual void updateSamplerMapping() = 0; - virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0; - - virtual LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - int registers) = 0; - - virtual bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, - const gl::Caps &caps) = 0; - virtual bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, - const gl::Caps &caps) = 0; - - virtual gl::Error applyUniforms() = 0; - virtual gl::Error applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) = 0; - virtual bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, - unsigned int registerIndex, const gl::Caps &caps) = 0; - - const std::vector &getUniforms() const { return mUniforms; } - const std::vector &getUniformIndices() const { return mUniformIndex; } - const std::vector &getUniformBlocks() const { return mUniformBlocks; } - const std::vector &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; } - const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; } - const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndex; } - - std::vector &getUniforms() { return mUniforms; } - std::vector &getUniformIndices() { return mUniformIndex; } - std::vector &getUniformBlocks() { return mUniformBlocks; } - std::vector &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; } - sh::Attribute *getShaderAttributes() { return mShaderAttributes; } - SemanticIndexArray &getSemanticIndexes() { return mSemanticIndex; } - - gl::LinkedUniform *getUniformByLocation(GLint location) const; - gl::LinkedUniform *getUniformByName(const std::string &name) const; - gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const; - - GLint getUniformLocation(std::string name); - GLuint getUniformIndex(std::string name); - GLuint getUniformBlockIndex(std::string name) const; - - virtual void reset(); + // TODO: synchronize in syncState when dirty bits exist. + virtual void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0; - protected: - std::vector mUniforms; - std::vector mUniformIndex; - std::vector mUniformBlocks; - std::vector mTransformFeedbackLinkedVaryings; + // May only be called after a successful link operation. + // Return false for inactive blocks. + virtual bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const = 0; + + // May only be called after a successful link operation. + // Returns false for inactive members. + virtual bool getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const = 0; - SemanticIndexArray mSemanticIndex; - sh::Attribute mShaderAttributes[gl::MAX_VERTEX_ATTRIBS]; + protected: + const gl::Program::Data &mData; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl_mock.h new file mode 100644 index 0000000000..d6aa238f64 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl_mock.h @@ -0,0 +1,75 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// ProgramImpl_mock.h: +// Defines a mock of the ProgramImpl class. +// + +#ifndef LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_ +#define LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_ + +#include "gmock/gmock.h" + +#include "libANGLE/renderer/ProgramImpl.h" + +namespace rx +{ + +class MockProgramImpl : public rx::ProgramImpl +{ + public: + MockProgramImpl() : ProgramImpl(gl::Program::Data()) {} + virtual ~MockProgramImpl() { destroy(); } + + MOCK_METHOD2(load, LinkResult(gl::InfoLog &, gl::BinaryInputStream *)); + MOCK_METHOD1(save, gl::Error(gl::BinaryOutputStream *)); + MOCK_METHOD1(setBinaryRetrievableHint, void(bool)); + + MOCK_METHOD2(link, LinkResult(const gl::Data &, gl::InfoLog &)); + MOCK_METHOD2(validate, GLboolean(const gl::Caps &, gl::InfoLog *)); + + MOCK_METHOD3(setUniform1fv, void(GLint, GLsizei, const GLfloat *)); + MOCK_METHOD3(setUniform2fv, void(GLint, GLsizei, const GLfloat *)); + MOCK_METHOD3(setUniform3fv, void(GLint, GLsizei, const GLfloat *)); + MOCK_METHOD3(setUniform4fv, void(GLint, GLsizei, const GLfloat *)); + MOCK_METHOD3(setUniform1iv, void(GLint, GLsizei, const GLint *)); + MOCK_METHOD3(setUniform2iv, void(GLint, GLsizei, const GLint *)); + MOCK_METHOD3(setUniform3iv, void(GLint, GLsizei, const GLint *)); + MOCK_METHOD3(setUniform4iv, void(GLint, GLsizei, const GLint *)); + MOCK_METHOD3(setUniform1uiv, void(GLint, GLsizei, const GLuint *)); + MOCK_METHOD3(setUniform2uiv, void(GLint, GLsizei, const GLuint *)); + MOCK_METHOD3(setUniform3uiv, void(GLint, GLsizei, const GLuint *)); + MOCK_METHOD3(setUniform4uiv, void(GLint, GLsizei, const GLuint *)); + + MOCK_METHOD4(setUniformMatrix2fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix3fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix4fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix2x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix3x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix2x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix4x2fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix3x4fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + MOCK_METHOD4(setUniformMatrix4x3fv, void(GLint, GLsizei, GLboolean, const GLfloat *)); + + MOCK_METHOD2(setUniformBlockBinding, void(GLuint, GLuint)); + MOCK_CONST_METHOD2(getUniformBlockSize, bool(const std::string &, size_t *)); + MOCK_CONST_METHOD2(getUniformBlockMemberInfo, bool(const std::string &, sh::BlockMemberInfo *)); + + MOCK_METHOD0(destroy, void()); +}; + +inline ::testing::NiceMock *MakeProgramMock() +{ + ::testing::NiceMock *programImpl = new ::testing::NiceMock(); + // TODO(jmadill): add ON_CALLS for returning methods + // We must mock the destructor since NiceMock doesn't work for destructors. + EXPECT_CALL(*programImpl, destroy()).Times(1).RetiresOnSaturation(); + + return programImpl; +} + +} // namespace rx + +#endif // LIBANGLE_RENDERER_PROGRAMIMPLMOCK_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h index bed63ea1b0..d738eb4ffc 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h @@ -26,8 +26,12 @@ class QueryImpl : angle::NonCopyable virtual gl::Error begin() = 0; virtual gl::Error end() = 0; + virtual gl::Error queryCounter() = 0; + virtual gl::Error getResult(GLint *params) = 0; virtual gl::Error getResult(GLuint *params) = 0; - virtual gl::Error isResultAvailable(GLuint *available) = 0; + virtual gl::Error getResult(GLint64 *params) = 0; + virtual gl::Error getResult(GLuint64 *params) = 0; + virtual gl::Error isResultAvailable(bool *available) = 0; GLenum getType() const { return mType; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h index 8ce257c833..75b4cdcfee 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h @@ -10,22 +10,27 @@ #define LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_ #include "angle_gl.h" - +#include "common/angleutils.h" #include "libANGLE/Error.h" +#include "libANGLE/FramebufferAttachment.h" -#include "common/angleutils.h" +namespace egl +{ +class Image; +} namespace rx { -class RenderbufferImpl : angle::NonCopyable +class RenderbufferImpl : public FramebufferAttachmentObjectImpl { public: - RenderbufferImpl(); - virtual ~RenderbufferImpl() = 0; + RenderbufferImpl() {} + virtual ~RenderbufferImpl() {} virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) = 0; virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) = 0; + virtual gl::Error setStorageEGLImageTarget(egl::Image *image) = 0; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h new file mode 100644 index 0000000000..c2c67cc76a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl_mock.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderbufferImpl_mock.h: Defines a mock of the RenderbufferImpl class. + +#ifndef LIBANGLE_RENDERER_RENDERBUFFERIMPLMOCK_H_ +#define LIBANGLE_RENDERER_RENDERBUFFERIMPLMOCK_H_ + +#include "gmock/gmock.h" + +#include "libANGLE/Image.h" +#include "libANGLE/renderer/RenderbufferImpl.h" + +namespace rx +{ + +class MockRenderbufferImpl : public RenderbufferImpl +{ + public: + virtual ~MockRenderbufferImpl() { destructor(); } + MOCK_METHOD3(setStorage, gl::Error(GLenum, size_t, size_t)); + MOCK_METHOD4(setStorageMultisample, gl::Error(size_t, GLenum, size_t, size_t)); + MOCK_METHOD1(setStorageEGLImageTarget, gl::Error(egl::Image *)); + + MOCK_METHOD2(getAttachmentRenderTarget, gl::Error(const gl::FramebufferAttachment::Target &, FramebufferAttachmentRenderTarget **)); + + MOCK_METHOD0(destructor, void()); +}; + +} + +#endif // LIBANGLE_RENDERER_RENDERBUFFERIMPLMOCK_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp index fbc2ad5d1c..f3f7f55bb9 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp @@ -14,10 +14,7 @@ namespace rx { - -Renderer::Renderer() - : mCapsInitialized(false), - mWorkaroundsInitialized(false) +Renderer::Renderer() : mCapsInitialized(false) { } @@ -25,48 +22,41 @@ Renderer::~Renderer() { } -const gl::Caps &Renderer::getRendererCaps() const +void Renderer::ensureCapsInitialized() const { if (!mCapsInitialized) { - generateCaps(&mCaps, &mTextureCaps, &mExtensions); + generateCaps(&mCaps, &mTextureCaps, &mExtensions, &mLimitations); mCapsInitialized = true; } +} + +const gl::Caps &Renderer::getRendererCaps() const +{ + ensureCapsInitialized(); return mCaps; } const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const { - if (!mCapsInitialized) - { - generateCaps(&mCaps, &mTextureCaps, &mExtensions); - mCapsInitialized = true; - } + ensureCapsInitialized(); return mTextureCaps; } const gl::Extensions &Renderer::getRendererExtensions() const { - if (!mCapsInitialized) - { - generateCaps(&mCaps, &mTextureCaps, &mExtensions); - mCapsInitialized = true; - } + ensureCapsInitialized(); return mExtensions; } -const Workarounds &Renderer::getWorkarounds() const +const gl::Limitations &Renderer::getRendererLimitations() const { - if (!mWorkaroundsInitialized) - { - mWorkarounds = generateWorkarounds(); - mWorkaroundsInitialized = true; - } + ensureCapsInitialized(); - return mWorkarounds; + return mLimitations; } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h index b607fe5613..d0da2b140c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h @@ -13,10 +13,10 @@ #include "libANGLE/Caps.h" #include "libANGLE/Error.h" #include "libANGLE/Framebuffer.h" +#include "libANGLE/State.h" #include "libANGLE/Uniform.h" #include "libANGLE/angletypes.h" #include "libANGLE/renderer/ImplFactory.h" -#include "libANGLE/renderer/Workarounds.h" #include "common/mathutil.h" #include @@ -30,16 +30,11 @@ class Display; class Surface; } -namespace gl -{ -class Buffer; -struct Data; -} - namespace rx { struct TranslatedIndexData; -struct Workarounds; +struct SourceIndexData; +struct WorkaroundsD3D; class DisplayImpl; class Renderer : public ImplFactory @@ -51,11 +46,34 @@ class Renderer : public ImplFactory virtual gl::Error flush() = 0; virtual gl::Error finish() = 0; - virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, - GLint first, GLsizei count, GLsizei instances) = 0; - virtual gl::Error drawElements(const gl::Data &data, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const RangeUI &indexRange) = 0; + virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count) = 0; + virtual gl::Error drawArraysInstanced(const gl::Data &data, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) = 0; + + virtual gl::Error drawElements(const gl::Data &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) = 0; + virtual gl::Error drawElementsInstanced(const gl::Data &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) = 0; + virtual gl::Error drawRangeElements(const gl::Data &data, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) = 0; // lost device //TODO(jmadill): investigate if this stuff is necessary in GL @@ -64,27 +82,39 @@ class Renderer : public ImplFactory virtual bool testDeviceLost() = 0; virtual bool testDeviceResettable() = 0; - virtual VendorID getVendorId() const = 0; virtual std::string getVendorString() const = 0; virtual std::string getRendererDescription() const = 0; + virtual void insertEventMarker(GLsizei length, const char *marker) = 0; + virtual void pushGroupMarker(GLsizei length, const char *marker) = 0; + virtual void popGroupMarker() = 0; + + virtual void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) = 0; + + // Disjoint timer queries + virtual GLint getGPUDisjoint() = 0; + virtual GLint64 getTimestamp() = 0; + + // Context switching + virtual void onMakeCurrent(const gl::Data &data) = 0; + // Renderer capabilities const gl::Caps &getRendererCaps() const; const gl::TextureCapsMap &getRendererTextureCaps() const; const gl::Extensions &getRendererExtensions() const; - const Workarounds &getWorkarounds() const; + const gl::Limitations &getRendererLimitations() const; private: - virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; - virtual Workarounds generateWorkarounds() const = 0; + void ensureCapsInitialized() const; + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const = 0; mutable bool mCapsInitialized; mutable gl::Caps mCaps; mutable gl::TextureCapsMap mTextureCaps; mutable gl::Extensions mExtensions; - - mutable bool mWorkaroundsInitialized; - mutable Workarounds mWorkarounds; + mutable gl::Limitations mLimitations; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SamplerImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/SamplerImpl.h new file mode 100644 index 0000000000..85383cf8e5 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/SamplerImpl.h @@ -0,0 +1,25 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SamplerImpl.h: Defines the abstract rx::SamplerImpl class. + +#ifndef LIBANGLE_RENDERER_SAMPLERIMPL_H_ +#define LIBANGLE_RENDERER_SAMPLERIMPL_H_ + +#include "common/angleutils.h" + +namespace rx +{ + +class SamplerImpl : public angle::NonCopyable +{ + public: + SamplerImpl() {} + virtual ~SamplerImpl() {} +}; +} + +#endif // LIBANGLE_RENDERER_SAMPLERIMPL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h index 3011bc57f8..5a466377a5 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h @@ -9,8 +9,6 @@ #ifndef LIBANGLE_RENDERER_SHADERIMPL_H_ #define LIBANGLE_RENDERER_SHADERIMPL_H_ -#include - #include "common/angleutils.h" #include "libANGLE/Shader.h" @@ -20,36 +18,21 @@ namespace rx class ShaderImpl : angle::NonCopyable { public: - ShaderImpl() { } + ShaderImpl(const gl::Shader::Data &data) : mData(data) {} virtual ~ShaderImpl() { } - virtual bool compile(gl::Compiler *compiler, const std::string &source) = 0; - virtual std::string getDebugInfo() const = 0; - - virtual const std::string &getInfoLog() const { return mInfoLog; } - virtual const std::string &getTranslatedSource() const { return mTranslatedSource; } + // Returns additional ShCompile options. + virtual int prepareSourceAndReturnOptions(std::stringstream *sourceStream, + std::string *sourcePath) = 0; + // Returns success for compiling on the driver. Returns success. + virtual bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) = 0; - const std::vector &getVaryings() const { return mVaryings; } - const std::vector &getUniforms() const { return mUniforms; } - const std::vector &getInterfaceBlocks() const { return mInterfaceBlocks; } - const std::vector &getActiveAttributes() const { return mActiveAttributes; } - const std::vector &getActiveOutputVariables() const { return mActiveOutputVariables; } + virtual std::string getDebugInfo() const = 0; - std::vector &getVaryings() { return mVaryings; } - std::vector &getUniforms() { return mUniforms; } - std::vector &getInterfaceBlocks() { return mInterfaceBlocks; } - std::vector &getActiveAttributes() { return mActiveAttributes; } - std::vector &getActiveOutputVariables() { return mActiveOutputVariables; } + const gl::Shader::Data &getData() const { return mData; } protected: - std::string mInfoLog; - std::string mTranslatedSource; - - std::vector mVaryings; - std::vector mUniforms; - std::vector mInterfaceBlocks; - std::vector mActiveAttributes; - std::vector mActiveOutputVariables; + const gl::Shader::Data &mData; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h index ca04a42bd1..32125d542c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h @@ -11,6 +11,8 @@ #include "common/angleutils.h" #include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" namespace egl { @@ -21,17 +23,20 @@ struct Config; namespace rx { -class SurfaceImpl : angle::NonCopyable +class FramebufferImpl; + +class SurfaceImpl : public FramebufferAttachmentObjectImpl { public: SurfaceImpl(); virtual ~SurfaceImpl(); virtual egl::Error initialize() = 0; + virtual FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) = 0; virtual egl::Error swap() = 0; virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0; virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0; - virtual egl::Error bindTexImage(EGLint buffer) = 0; + virtual egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) = 0; virtual egl::Error releaseTexImage(EGLint buffer) = 0; virtual void setSwapInterval(EGLint interval) = 0; @@ -40,6 +45,7 @@ class SurfaceImpl : angle::NonCopyable virtual EGLint getHeight() const = 0; virtual EGLint isPostSubBufferSupported() const = 0; + virtual EGLint getSwapBehavior() const = 0; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h index d628906116..ad4ec8d830 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h @@ -9,18 +9,18 @@ #ifndef LIBANGLE_RENDERER_TEXTUREIMPL_H_ #define LIBANGLE_RENDERER_TEXTUREIMPL_H_ -#include "libANGLE/Error.h" -#include "libANGLE/ImageIndex.h" - -#include "common/angleutils.h" +#include #include "angle_gl.h" - -#include +#include "common/angleutils.h" +#include "libANGLE/Error.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/ImageIndex.h" namespace egl { class Surface; +class Image; } namespace gl @@ -31,16 +31,17 @@ struct Offset; struct Rectangle; class Framebuffer; struct PixelUnpackState; -struct SamplerState; +struct TextureState; } namespace rx { -class TextureImpl : angle::NonCopyable +class TextureImpl : public FramebufferAttachmentObjectImpl { public: - virtual ~TextureImpl() {}; + TextureImpl() {} + virtual ~TextureImpl() {} virtual void setUsage(GLenum usage) = 0; @@ -50,9 +51,9 @@ class TextureImpl : angle::NonCopyable const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; virtual gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) = 0; virtual gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) = 0; virtual gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, const gl::Framebuffer *source) = 0; @@ -61,7 +62,9 @@ class TextureImpl : angle::NonCopyable virtual gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) = 0; - virtual gl::Error generateMipmaps() = 0; + virtual gl::Error setEGLImageTarget(GLenum target, egl::Image *image) = 0; + + virtual gl::Error generateMipmaps(const gl::TextureState &textureState) = 0; virtual void bindTexImage(egl::Surface *surface) = 0; virtual void releaseTexImage() = 0; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl_mock.h new file mode 100644 index 0000000000..3eb43f0033 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl_mock.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureImpl_mock.h: Defines a mock of the TextureImpl class. + +#ifndef LIBANGLE_RENDERER_TEXTUREIMPLMOCK_H_ +#define LIBANGLE_RENDERER_TEXTUREIMPLMOCK_H_ + +#include "gmock/gmock.h" + +#include "libANGLE/renderer/TextureImpl.h" + +namespace rx +{ + +class MockTextureImpl : public TextureImpl +{ + public: + virtual ~MockTextureImpl() { destructor(); } + MOCK_METHOD1(setUsage, void(GLenum)); + MOCK_METHOD8(setImage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &, GLenum, GLenum, const gl::PixelUnpackState &, const uint8_t *)); + MOCK_METHOD7(setSubImage, gl::Error(GLenum, size_t, const gl::Box &, GLenum, GLenum, const gl::PixelUnpackState &, const uint8_t *)); + MOCK_METHOD7(setCompressedImage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &, const gl::PixelUnpackState &, size_t, const uint8_t *)); + MOCK_METHOD7(setCompressedSubImage, gl::Error(GLenum, size_t, const gl::Box &, GLenum, const gl::PixelUnpackState &, size_t, const uint8_t *)); + MOCK_METHOD5(copyImage, gl::Error(GLenum, size_t, const gl::Rectangle &, GLenum, const gl::Framebuffer *)); + MOCK_METHOD5(copySubImage, gl::Error(GLenum, size_t, const gl::Offset &, const gl::Rectangle &, const gl::Framebuffer *)); + MOCK_METHOD4(setStorage, gl::Error(GLenum, size_t, GLenum, const gl::Extents &)); + MOCK_METHOD2(setEGLImageTarget, gl::Error(GLenum, egl::Image *)); + MOCK_METHOD1(generateMipmaps, gl::Error(const gl::TextureState &)); + MOCK_METHOD1(bindTexImage, void(egl::Surface *)); + MOCK_METHOD0(releaseTexImage, void(void)); + + MOCK_METHOD2(getAttachmentRenderTarget, gl::Error(const gl::FramebufferAttachment::Target &, FramebufferAttachmentRenderTarget **)); + + MOCK_METHOD0(destructor, void()); +}; + +} + +#endif // LIBANGLE_RENDERER_TEXTUREIMPLMOCK_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h index 8f9133cfe5..5df7cad87b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h @@ -24,6 +24,9 @@ class TransformFeedbackImpl : angle::NonCopyable virtual void end() = 0; virtual void pause() = 0; virtual void resume() = 0; + + virtual void bindGenericBuffer(const BindingPointer &binding) = 0; + virtual void bindIndexedBuffer(size_t index, const OffsetBindingPointer &binding) = 0; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h new file mode 100644 index 0000000000..c7d2fc620d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl_mock.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TransformFeedbackImpl_mock.h: Defines a mock of the TransformFeedbackImpl class. + +#ifndef LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_ +#define LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_ + +#include "gmock/gmock.h" + +#include "libANGLE/renderer/TransformFeedbackImpl.h" + +namespace rx +{ + +class MockTransformFeedbackImpl : public TransformFeedbackImpl +{ + public: + ~MockTransformFeedbackImpl() { destructor(); } + + MOCK_METHOD1(begin, void(GLenum primitiveMode)); + MOCK_METHOD0(end, void()); + MOCK_METHOD0(pause, void()); + MOCK_METHOD0(resume, void()); + + MOCK_METHOD1(bindGenericBuffer, void(const BindingPointer &)); + MOCK_METHOD2(bindIndexedBuffer, void(size_t, const OffsetBindingPointer &)); + + MOCK_METHOD0(destructor, void()); +}; + +} + +#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPLMOCK_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h index 0e25f952c2..13617c7ecb 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h @@ -11,7 +11,7 @@ #include "common/angleutils.h" #include "libANGLE/Buffer.h" -#include "libANGLE/VertexAttribute.h" +#include "libANGLE/VertexArray.h" namespace rx { @@ -19,12 +19,11 @@ namespace rx class VertexArrayImpl : angle::NonCopyable { public: + VertexArrayImpl(const gl::VertexArray::Data &data) : mData(data) { } virtual ~VertexArrayImpl() { } - - virtual void setElementArrayBuffer(const gl::Buffer *buffer) = 0; - virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) = 0; - virtual void setAttributeDivisor(size_t idx, GLuint divisor) = 0; - virtual void enableAttribute(size_t idx, bool enabledState) = 0; + virtual void syncState(const gl::VertexArray::DirtyBits &dirtyBits) {} + protected: + const gl::VertexArray::Data &mData; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp index 1af8794356..ffca99c3ac 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp @@ -8,6 +8,8 @@ #include "libANGLE/renderer/d3d/BufferD3D.h" +#include "common/mathutil.h" +#include "common/utilities.h" #include "libANGLE/renderer/d3d/IndexBuffer.h" #include "libANGLE/renderer/d3d/VertexBuffer.h" @@ -21,7 +23,11 @@ BufferD3D::BufferD3D(BufferFactoryD3D *factory) mFactory(factory), mStaticVertexBuffer(nullptr), mStaticIndexBuffer(nullptr), - mUnmodifiedDataUse(0) + mStaticBufferCache(nullptr), + mStaticBufferCacheTotalSize(0), + mStaticVertexBufferOutOfDate(false), + mUnmodifiedDataUse(0), + mUsage(D3D_BUFFER_USAGE_STATIC) { updateSerial(); } @@ -30,6 +36,19 @@ BufferD3D::~BufferD3D() { SafeDelete(mStaticVertexBuffer); SafeDelete(mStaticIndexBuffer); + + emptyStaticBufferCache(); +} + +void BufferD3D::emptyStaticBufferCache() +{ + if (mStaticBufferCache != nullptr) + { + SafeDeleteContainer(*mStaticBufferCache); + SafeDelete(mStaticBufferCache); + } + + mStaticBufferCacheTotalSize = 0; } void BufferD3D::updateSerial() @@ -37,6 +56,30 @@ void BufferD3D::updateSerial() mSerial = mNextSerial++; } +void BufferD3D::updateD3DBufferUsage(GLenum usage) +{ + switch (usage) + { + case GL_STATIC_DRAW: + case GL_STATIC_READ: + case GL_STATIC_COPY: + mUsage = D3D_BUFFER_USAGE_STATIC; + initializeStaticData(); + break; + + case GL_STREAM_DRAW: + case GL_STREAM_READ: + case GL_STREAM_COPY: + case GL_DYNAMIC_READ: + case GL_DYNAMIC_COPY: + case GL_DYNAMIC_DRAW: + mUsage = D3D_BUFFER_USAGE_DYNAMIC; + break; + default: + UNREACHABLE(); + } +} + void BufferD3D::initializeStaticData() { if (!mStaticVertexBuffer) @@ -49,15 +92,135 @@ void BufferD3D::initializeStaticData() } } -void BufferD3D::invalidateStaticData() +StaticIndexBufferInterface *BufferD3D::getStaticIndexBuffer() { + return mStaticIndexBuffer; +} + +StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer( + const gl::VertexAttribute &attribute, + D3DStaticBufferCreationType creationType) +{ + if (!mStaticVertexBuffer) + { + // Early out if there aren't any static buffers at all + ASSERT(mStaticBufferCache == nullptr); + return nullptr; + } + + if (mStaticBufferCache == nullptr && !mStaticVertexBuffer->isCommitted()) + { + // Early out, the attribute can be added to mStaticVertexBuffer or is already in there + return mStaticVertexBuffer; + } + + // At this point, see if any of the existing static buffers contains the attribute data + + // If the default static vertex buffer contains the attribute, then return it + if (mStaticVertexBuffer->lookupAttribute(attribute, nullptr)) + { + return mStaticVertexBuffer; + } + + if (mStaticBufferCache != nullptr) + { + // If there is a cached static buffer that already contains the attribute, then return it + for (StaticVertexBufferInterface *staticBuffer : *mStaticBufferCache) + { + if (staticBuffer->lookupAttribute(attribute, nullptr)) + { + return staticBuffer; + } + } + } + + if (!mStaticVertexBuffer->isCommitted()) + { + // None of the existing static buffers contain the attribute data and we are able to add + // the data to mStaticVertexBuffer, so we should just do so + return mStaticVertexBuffer; + } + + // At this point, we must create a new static buffer for the attribute data + if (creationType != D3D_BUFFER_CREATE_IF_NECESSARY) + { + return nullptr; + } + + ASSERT(mStaticVertexBuffer); + ASSERT(mStaticVertexBuffer->isCommitted()); + unsigned int staticVertexBufferSize = mStaticVertexBuffer->getBufferSize(); + if (IsUnsignedAdditionSafe(staticVertexBufferSize, mStaticBufferCacheTotalSize)) + { + // Ensure that the total size of the static buffer cache remains less than 4x the + // size of the original buffer + unsigned int maxStaticCacheSize = + IsUnsignedMultiplicationSafe(static_cast(getSize()), 4u) + ? 4u * static_cast(getSize()) + : std::numeric_limits::max(); + + // We can't reuse the default static vertex buffer, so we add it to the cache + if (staticVertexBufferSize + mStaticBufferCacheTotalSize <= maxStaticCacheSize) + { + if (mStaticBufferCache == nullptr) + { + mStaticBufferCache = new std::vector(); + } + + mStaticBufferCacheTotalSize += staticVertexBufferSize; + (*mStaticBufferCache).push_back(mStaticVertexBuffer); + mStaticVertexBuffer = nullptr; + + // Then reinitialize the static buffers to create a new static vertex buffer + initializeStaticData(); + + // Return the default static vertex buffer + return mStaticVertexBuffer; + } + } + + // At this point: + // - mStaticVertexBuffer is committed and can't be altered + // - mStaticBufferCache is full (or nearly overflowing) + // The inputted attribute should be put in some static buffer at some point, but it can't + // go in one right now, since mStaticBufferCache is full and we can't delete mStaticVertexBuffer + // in case another attribute is relying upon it for the current draw. + // We therefore mark mStaticVertexBuffer for deletion at the next possible time. + mStaticVertexBufferOutOfDate = true; + return nullptr; +} + +void BufferD3D::reinitOutOfDateStaticData() +{ + if (mStaticVertexBufferOutOfDate) + { + // During the last draw the caller tried to use some attribute with static data, but neither + // the static buffer cache nor mStaticVertexBuffer contained that data. + // Therefore, invalidate mStaticVertexBuffer so that if the caller tries to use that + // attribute in the next draw, it'll successfully get put into mStaticVertexBuffer. + invalidateStaticData(D3D_BUFFER_INVALIDATE_DEFAULT_BUFFER_ONLY); + mStaticVertexBufferOutOfDate = false; + } +} + +void BufferD3D::invalidateStaticData(D3DBufferInvalidationType invalidationType) +{ + if (invalidationType == D3D_BUFFER_INVALIDATE_WHOLE_CACHE && mStaticBufferCache != nullptr) + { + emptyStaticBufferCache(); + } + if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) { SafeDelete(mStaticVertexBuffer); SafeDelete(mStaticIndexBuffer); - // Re-init static data to track that we're in a static buffer - initializeStaticData(); + // If the buffer was created with a static usage then we recreate the static + // buffers so that they are populated the next time we use this buffer. + if (mUsage == D3D_BUFFER_USAGE_STATIC) + { + initializeStaticData(); + } } mUnmodifiedDataUse = 0; @@ -68,6 +231,10 @@ void BufferD3D::promoteStaticUsage(int dataSize) { if (!mStaticVertexBuffer && !mStaticIndexBuffer) { + // There isn't any scenario that involves promoting static usage and the static buffer cache + // being non-empty + ASSERT(mStaticBufferCache == nullptr); + mUnmodifiedDataUse += dataSize; if (mUnmodifiedDataUse > 3 * getSize()) @@ -77,4 +244,21 @@ void BufferD3D::promoteStaticUsage(int dataSize) } } -} \ No newline at end of file +gl::Error BufferD3D::getIndexRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + gl::IndexRange *outRange) +{ + const uint8_t *data = nullptr; + gl::Error error = getData(&data); + if (error.isError()) + { + return error; + } + + *outRange = gl::ComputeIndexRange(type, data + offset, count, primitiveRestartEnabled); + return gl::Error(GL_NO_ERROR); +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h index a46398f911..a27ca9857a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h @@ -9,10 +9,11 @@ #ifndef LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ #define LIBANGLE_RENDERER_D3D_BUFFERD3D_H_ -#include "libANGLE/renderer/BufferImpl.h" #include "libANGLE/angletypes.h" +#include "libANGLE/renderer/BufferImpl.h" #include +#include namespace rx { @@ -20,6 +21,24 @@ class BufferFactoryD3D; class StaticIndexBufferInterface; class StaticVertexBufferInterface; +enum D3DBufferUsage +{ + D3D_BUFFER_USAGE_STATIC, + D3D_BUFFER_USAGE_DYNAMIC, +}; + +enum D3DBufferInvalidationType +{ + D3D_BUFFER_INVALIDATE_WHOLE_CACHE, + D3D_BUFFER_INVALIDATE_DEFAULT_BUFFER_ONLY, +}; + +enum D3DStaticBufferCreationType +{ + D3D_BUFFER_CREATE_IF_NECESSARY, + D3D_BUFFER_DO_NOT_CREATE, +}; + class BufferD3D : public BufferImpl { public: @@ -31,16 +50,28 @@ class BufferD3D : public BufferImpl virtual size_t getSize() const = 0; virtual bool supportsDirectBinding() const = 0; virtual void markTransformFeedbackUsage() = 0; + virtual gl::Error getData(const uint8_t **outData) = 0; - StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } - StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } + StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute, + D3DStaticBufferCreationType creationType); + StaticIndexBufferInterface *getStaticIndexBuffer(); void initializeStaticData(); - void invalidateStaticData(); + void invalidateStaticData(D3DBufferInvalidationType invalidationType); + void reinitOutOfDateStaticData(); + void promoteStaticUsage(int dataSize); + gl::Error getIndexRange(GLenum type, + size_t offset, + size_t count, + bool primitiveRestartEnabled, + gl::IndexRange *outRange) override; + protected: void updateSerial(); + void updateD3DBufferUsage(GLenum usage); + void emptyStaticBufferCache(); BufferFactoryD3D *mFactory; unsigned int mSerial; @@ -48,7 +79,11 @@ class BufferD3D : public BufferImpl StaticVertexBufferInterface *mStaticVertexBuffer; StaticIndexBufferInterface *mStaticIndexBuffer; + std::vector *mStaticBufferCache; + unsigned int mStaticBufferCacheTotalSize; + unsigned int mStaticVertexBufferOutOfDate; unsigned int mUnmodifiedDataUse; + D3DBufferUsage mUsage; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp index a22757cf9f..6f8d1717cd 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp @@ -1,128 +1,20 @@ // -// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Copyright 2015 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // - -// CompilerD3D.cpp: Implementation of the rx::CompilerD3D class. +// CompilerD3D: +// Implementation of the D3D compiler methods. +// #include "libANGLE/renderer/d3d/CompilerD3D.h" -#include "libANGLE/Caps.h" -#include "libANGLE/Data.h" - -#include "common/debug.h" - namespace rx { -// Global count of active shader compiler handles. Needed to know when to call ShInitialize and ShFinalize. -static size_t activeCompilerHandles = 0; - -CompilerD3D::CompilerD3D(const gl::Data &data, ShShaderOutput outputType) - : mSpec(data.clientVersion > 2 ? SH_GLES3_SPEC : SH_GLES2_SPEC), - mOutputType(outputType), - mResources(), - mFragmentCompiler(NULL), - mVertexCompiler(NULL) -{ - ASSERT(data.clientVersion == 2 || data.clientVersion == 3); - - const gl::Caps &caps = *data.caps; - const gl::Extensions &extensions = *data.extensions; - - ShInitBuiltInResources(&mResources); - mResources.MaxVertexAttribs = caps.maxVertexAttributes; - mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors; - mResources.MaxVaryingVectors = caps.maxVaryingVectors; - mResources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits; - mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; - mResources.MaxTextureImageUnits = caps.maxTextureImageUnits; - mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors; - mResources.MaxDrawBuffers = caps.maxDrawBuffers; - mResources.OES_standard_derivatives = extensions.standardDerivatives; - mResources.EXT_draw_buffers = extensions.drawBuffers; - mResources.EXT_shader_texture_lod = 1; - // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported. - mResources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp - mResources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output - - // GLSL ES 3.0 constants - mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4; - mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4; - mResources.MinProgramTexelOffset = caps.minProgramTexelOffset; - mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset; -} - -CompilerD3D::~CompilerD3D() -{ - release(); -} - -CompilerD3D *CompilerD3D::makeCompilerD3D(CompilerImpl *compiler) +CompilerD3D::CompilerD3D(ShShaderOutput translatorOutputType) + : mTranslatorOutputType(translatorOutputType) { - ASSERT(HAS_DYNAMIC_TYPE(CompilerD3D*, compiler)); - return static_cast(compiler); } -gl::Error CompilerD3D::release() -{ - if (mFragmentCompiler) - { - ShDestruct(mFragmentCompiler); - mFragmentCompiler = NULL; - - ASSERT(activeCompilerHandles > 0); - activeCompilerHandles--; - } - - if (mVertexCompiler) - { - ShDestruct(mVertexCompiler); - mVertexCompiler = NULL; - - ASSERT(activeCompilerHandles > 0); - activeCompilerHandles--; - } - - if (activeCompilerHandles == 0) - { - ShFinalize(); - } - - return gl::Error(GL_NO_ERROR); -} - -ShHandle CompilerD3D::getCompilerHandle(GLenum type) -{ - ShHandle *compiler = NULL; - switch (type) - { - case GL_VERTEX_SHADER: - compiler = &mVertexCompiler; - break; - - case GL_FRAGMENT_SHADER: - compiler = &mFragmentCompiler; - break; - - default: - UNREACHABLE(); - return NULL; - } - - if (!(*compiler)) - { - if (activeCompilerHandles == 0) - { - ShInitialize(); - } - - *compiler = ShConstructCompiler(type, mSpec, mOutputType, &mResources); - activeCompilerHandles++; - } - - return *compiler; -} - -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h index 0f83e4f8c8..8f4334963d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h @@ -10,14 +10,7 @@ #define LIBANGLE_RENDERER_COMPILERD3D_H_ #include "libANGLE/renderer/CompilerImpl.h" -#include "libANGLE/Caps.h" - -#include "GLSLANG/ShaderLang.h" - -namespace gl -{ -struct Data; -} +#include "libANGLE/renderer/d3d/RendererD3D.h" namespace rx { @@ -25,22 +18,14 @@ namespace rx class CompilerD3D : public CompilerImpl { public: - CompilerD3D(const gl::Data &data, ShShaderOutput outputType); - virtual ~CompilerD3D(); + CompilerD3D(ShShaderOutput translatorOutputType); + ~CompilerD3D() override {} - static CompilerD3D *makeCompilerD3D(CompilerImpl *compiler); - - gl::Error release() override; - - ShHandle getCompilerHandle(GLenum type); + gl::Error release() override { return gl::Error(GL_NO_ERROR); } + ShShaderOutput getTranslatorOutputType() const override { return mTranslatorOutputType; } private: - ShShaderSpec mSpec; - ShShaderOutput mOutputType; - ShBuiltInResources mResources; - - ShHandle mFragmentCompiler; - ShHandle mVertexCompiler; + ShShaderOutput mTranslatorOutputType; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp new file mode 100644 index 0000000000..f40e6e6cab --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.cpp @@ -0,0 +1,102 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DeviceD3D.cpp: D3D implementation of egl::Device + +#include "libANGLE/renderer/d3d/DeviceD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +#include "libANGLE/Device.h" +#include "libANGLE/Display.h" + +#include + +namespace rx +{ + +DeviceD3D::DeviceD3D() + : mDevice(0), mDeviceType(0), mDeviceExternallySourced(false), mIsInitialized(false) +{ +} + +DeviceD3D::~DeviceD3D() +{ +#if defined(ANGLE_ENABLE_D3D11) + if (mDeviceType == EGL_D3D11_DEVICE_ANGLE) + { + // DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it. + ID3D11Device *device = reinterpret_cast(mDevice); + device->Release(); + } +#endif +} + +egl::Error DeviceD3D::getDevice(void **outValue) +{ + if (!mIsInitialized) + { + *outValue = nullptr; + return egl::Error(EGL_BAD_DEVICE_EXT); + } + + *outValue = mDevice; + return egl::Error(EGL_SUCCESS); +} + +egl::Error DeviceD3D::initialize(void *device, + EGLint deviceType, + EGLBoolean deviceExternallySourced) +{ + ASSERT(!mIsInitialized); + if (mIsInitialized) + { + return egl::Error(EGL_BAD_DEVICE_EXT); + } + + mDevice = device; + mDeviceType = deviceType; + mDeviceExternallySourced = !!deviceExternallySourced; + +#if defined(ANGLE_ENABLE_D3D11) + if (mDeviceType == EGL_D3D11_DEVICE_ANGLE) + { + // Validate the device + IUnknown *iunknown = reinterpret_cast(device); + + ID3D11Device *d3dDevice = nullptr; + HRESULT hr = + iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast(&d3dDevice)); + if (FAILED(hr)) + { + return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid D3D device passed into EGLDeviceEXT"); + } + + // The QI to ID3D11Device adds a ref to the D3D11 device. + // Deliberately don't release the ref here, so that the DeviceD3D holds a ref to the + // D3D11 device. + } + else +#endif + { + ASSERT(!mDeviceExternallySourced); + } + + mIsInitialized = true; + + return egl::Error(EGL_SUCCESS); +} + +EGLint DeviceD3D::getType() +{ + return mDeviceType; +} + +void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const +{ + outExtensions->deviceD3D = true; +} + +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h new file mode 100644 index 0000000000..1dd9979708 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DeviceD3D.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// DeviceD3D.h: D3D implementation of egl::Device + +#ifndef LIBANGLE_RENDERER_D3D_DEVICED3D_H_ +#define LIBANGLE_RENDERER_D3D_DEVICED3D_H_ + +#include "libANGLE/Device.h" +#include "libANGLE/renderer/DeviceImpl.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ +class DeviceD3D : public DeviceImpl +{ + public: + DeviceD3D(); + ~DeviceD3D() override; + + egl::Error initialize(void *device, EGLint deviceType, EGLBoolean external); + egl::Error getDevice(void **outValue) override; + EGLint getType() override; + void generateExtensions(egl::DeviceExtensions *outExtensions) const override; + bool deviceExternallySourced() override { return mDeviceExternallySourced; } + + private: + void *mDevice; + EGLint mDeviceType; + bool mDeviceExternallySourced; + bool mIsInitialized; +}; + +} + +#endif // LIBANGLE_RENDERER_D3D_DEVICED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp index add5d62fae..d4dc702582 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp @@ -12,10 +12,12 @@ #include "libANGLE/Config.h" #include "libANGLE/Display.h" #include "libANGLE/Surface.h" +#include "libANGLE/histogram_macros.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/SurfaceD3D.h" #include "libANGLE/renderer/d3d/SwapChainD3D.h" -#include "platform/Platform.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" #include @@ -33,7 +35,7 @@ #if !defined(ANGLE_DEFAULT_D3D11) // Enables use of the Direct3D 11 API for a default display, when available -# define ANGLE_DEFAULT_D3D11 0 +# define ANGLE_DEFAULT_D3D11 1 #endif namespace rx @@ -53,10 +55,13 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) std::vector rendererCreationFunctions; - const auto &attribMap = display->getAttributeMap(); - EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId(); + if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE) + { + const auto &attribMap = display->getAttributeMap(); + EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId(); - EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); + EGLint requestedDisplayType = + attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); # if defined(ANGLE_ENABLE_D3D11) if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || @@ -75,27 +80,41 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) } # endif - if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && - nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && - requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) - { + if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && + nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) + { // The default display is requested, try the D3D9 and D3D11 renderers, order them using // the definition of ANGLE_DEFAULT_D3D11 # if ANGLE_DEFAULT_D3D11 # if defined(ANGLE_ENABLE_D3D11) - rendererCreationFunctions.push_back(CreateTypedRendererD3D); + rendererCreationFunctions.push_back(CreateTypedRendererD3D); # endif # if defined(ANGLE_ENABLE_D3D9) - rendererCreationFunctions.push_back(CreateTypedRendererD3D); + rendererCreationFunctions.push_back(CreateTypedRendererD3D); # endif # else # if defined(ANGLE_ENABLE_D3D9) - rendererCreationFunctions.push_back(CreateTypedRendererD3D); + rendererCreationFunctions.push_back(CreateTypedRendererD3D); # endif # if defined(ANGLE_ENABLE_D3D11) - rendererCreationFunctions.push_back(CreateTypedRendererD3D); + rendererCreationFunctions.push_back(CreateTypedRendererD3D); # endif # endif + } + } + else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) + { +#if defined(ANGLE_ENABLE_D3D11) + if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE) + { + rendererCreationFunctions.push_back(CreateTypedRendererD3D); + } +#endif + } + else + { + UNIMPLEMENTED(); } egl::Error result(EGL_NOT_INITIALIZED, "No available renderers."); @@ -108,10 +127,9 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) if (renderer->getRendererClass() == RENDERER_D3D11) { ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS); - - angle::Platform *platform = ANGLEPlatformCurrent(); - platform->histogramEnumeration("GPU.ANGLE.D3D11InitializeResult", - result.getID(), NUM_D3D11_INIT_ERRORS); + ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11InitializeResult", + result.getID(), + NUM_D3D11_INIT_ERRORS); } # endif @@ -119,10 +137,9 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) if (renderer->getRendererClass() == RENDERER_D3D9) { ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS); - - angle::Platform *platform = ANGLEPlatformCurrent(); - platform->histogramEnumeration("GPU.ANGLE.D3D9InitializeResult", - result.getID(), NUM_D3D9_INIT_ERRORS); + ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D9InitializeResult", + result.getID(), + NUM_D3D9_INIT_ERRORS); } # endif @@ -141,19 +158,22 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer) return result; } -DisplayD3D::DisplayD3D() - : mRenderer(nullptr) +DisplayD3D::DisplayD3D() : mRenderer(nullptr) { } -egl::Error DisplayD3D::createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, - const egl::AttributeMap &attribs, SurfaceImpl **outSurface) + +SurfaceImpl *DisplayD3D::createWindowSurface(const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) { ASSERT(mRenderer != nullptr); EGLint width = attribs.get(EGL_WIDTH, 0); EGLint height = attribs.get(EGL_HEIGHT, 0); EGLint fixedSize = attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE); + EGLint orientation = attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0); + EGLint directComposition = attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE); if (!fixedSize) { @@ -161,81 +181,60 @@ egl::Error DisplayD3D::createWindowSurface(const egl::Config *configuration, EGL height = -1; } - SurfaceD3D *surface = SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize, - width, height); - egl::Error error = surface->initialize(); - if (error.isError()) - { - SafeDelete(surface); - return error; - } - - *outSurface = surface; - return egl::Error(EGL_SUCCESS); + return SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize, + directComposition, width, height, orientation); } -egl::Error DisplayD3D::createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs, - SurfaceImpl **outSurface) +SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::Config *configuration, + const egl::AttributeMap &attribs) { ASSERT(mRenderer != nullptr); EGLint width = attribs.get(EGL_WIDTH, 0); EGLint height = attribs.get(EGL_HEIGHT, 0); - SurfaceD3D *surface = SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, NULL, width, height); - egl::Error error = surface->initialize(); - if (error.isError()) - { - SafeDelete(surface); - return error; - } - - *outSurface = surface; - return egl::Error(EGL_SUCCESS); + return SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, nullptr, width, height); } -egl::Error DisplayD3D::createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle, - const egl::AttributeMap &attribs, SurfaceImpl **outSurface) +SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::Config *configuration, + EGLClientBuffer shareHandle, + const egl::AttributeMap &attribs) { ASSERT(mRenderer != nullptr); EGLint width = attribs.get(EGL_WIDTH, 0); EGLint height = attribs.get(EGL_HEIGHT, 0); - SurfaceD3D *surface = SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, shareHandle, - width, height); - egl::Error error = surface->initialize(); - if (error.isError()) - { - SafeDelete(surface); - return error; - } - - *outSurface = surface; - return egl::Error(EGL_SUCCESS); + return SurfaceD3D::createOffscreen( + mRenderer, mDisplay, configuration, shareHandle, width, height); } -egl::Error DisplayD3D::createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap, - const egl::AttributeMap &attribs, SurfaceImpl **outSurface) +SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) { - ASSERT(mRenderer != nullptr); - UNIMPLEMENTED(); - *outSurface = nullptr; - return egl::Error(EGL_BAD_DISPLAY); + return nullptr; } -egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, - gl::Context **outContext) +ImageImpl *DisplayD3D::createImage(EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) { - ASSERT(mRenderer != nullptr); + return new EGLImageD3D(mRenderer, target, buffer, attribs); +} - EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1); - bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT); - bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE); +egl::Error DisplayD3D::getDevice(DeviceImpl **device) +{ + return mRenderer->getEGLDevice(device); +} - *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, robustAccess); - return egl::Error(EGL_SUCCESS); +gl::Context *DisplayD3D::createContext(const egl::Config *config, + const gl::Context *shareContext, + const egl::AttributeMap &attribs) +{ + ASSERT(mRenderer != nullptr); + return new gl::Context(config, shareContext, mRenderer, attribs); } egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) @@ -247,7 +246,13 @@ egl::Error DisplayD3D::initialize(egl::Display *display) { ASSERT(mRenderer == nullptr && display != nullptr); mDisplay = display; - return CreateRendererD3D(display, &mRenderer); + egl::Error error = CreateRendererD3D(display, &mRenderer); + if (error.isError()) + { + return error; + } + + return egl::Error(EGL_SUCCESS); } void DisplayD3D::terminate() @@ -276,9 +281,8 @@ bool DisplayD3D::testDeviceLost() egl::Error DisplayD3D::restoreLostDevice() { // Release surface resources to make the Reset() succeed - for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it) + for (auto &surface : mSurfaceSet) { - const auto &surface = *it; if (surface->getBoundTexture()) { surface->releaseTexImage(EGL_BACK_BUFFER); @@ -293,9 +297,8 @@ egl::Error DisplayD3D::restoreLostDevice() } // Restore any surfaces that may have been lost - for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it) + for (const auto &surface : mSurfaceSet) { - const auto &surface = *it; SurfaceD3D *surfaceD3D = GetImplAs(surface); egl::Error error = surfaceD3D->resetSwapChain(); @@ -315,24 +318,7 @@ bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const { - outExtensions->createContextRobustness = true; - - // ANGLE-specific extensions - if (mRenderer->getShareHandleSupport()) - { - outExtensions->d3dShareHandleClientBuffer = true; - outExtensions->surfaceD3DTexture2DShareHandle = true; - } - - outExtensions->querySurfacePointer = true; - outExtensions->windowFixedSize = true; - - if (mRenderer->getPostSubBufferSupport()) - { - outExtensions->postSubBuffer = true; - } - - outExtensions->createContext = true; + mRenderer->generateDisplayExtensions(outExtensions); } std::string DisplayD3D::getVendorString() const @@ -354,4 +340,17 @@ void DisplayD3D::generateCaps(egl::Caps *outCaps) const outCaps->textureNPOT = mRenderer->getRendererExtensions().textureNPOT; } +egl::Error DisplayD3D::waitClient() const +{ + // Unimplemented as it is a noop on D3D + return egl::Error(EGL_SUCCESS); +} + +egl::Error DisplayD3D::waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const +{ + // Unimplemented as it is a noop on D3D + return egl::Error(EGL_SUCCESS); +} } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h index f007ba9a19..0ce196dea2 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h @@ -10,6 +10,7 @@ #define LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_ #include "libANGLE/renderer/DisplayImpl.h" +#include "libANGLE/Device.h" namespace rx { @@ -23,17 +24,26 @@ class DisplayD3D : public DisplayImpl egl::Error initialize(egl::Display *display) override; virtual void terminate() override; - egl::Error createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, const egl::AttributeMap &attribs, - SurfaceImpl **outSurface) override; - egl::Error createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs, - SurfaceImpl **outSurface) override; - egl::Error createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle, - const egl::AttributeMap &attribs, SurfaceImpl **outSurface) override; - egl::Error createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap, - const egl::AttributeMap &attribs, SurfaceImpl **outSurface) override; - - egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs, - gl::Context **outContext) override; + // Surface creation + SurfaceImpl *createWindowSurface(const egl::Config *configuration, + EGLNativeWindowType window, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferSurface(const egl::Config *configuration, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPbufferFromClientBuffer(const egl::Config *configuration, + EGLClientBuffer shareHandle, + const egl::AttributeMap &attribs) override; + SurfaceImpl *createPixmapSurface(const egl::Config *configuration, + NativePixmapType nativePixmap, + const egl::AttributeMap &attribs) override; + + ImageImpl *createImage(EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) override; + + gl::Context *createContext(const egl::Config *config, + const gl::Context *shareContext, + const egl::AttributeMap &attribs) override; egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override; @@ -45,8 +55,15 @@ class DisplayD3D : public DisplayImpl bool isValidNativeWindow(EGLNativeWindowType window) const override; + egl::Error getDevice(DeviceImpl **device) override; + std::string getVendorString() const override; + egl::Error waitClient() const override; + egl::Error waitNative(EGLint engine, + egl::Surface *drawSurface, + egl::Surface *readSurface) const override; + private: void generateExtensions(egl::DisplayExtensions *outExtensions) const override; void generateCaps(egl::Caps *outCaps) const override; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp index 0dbc30ae36..42a534f573 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp @@ -10,14 +10,13 @@ #include "common/utilities.h" #include "compiler/translator/blocklayoutHLSL.h" -#include "libANGLE/renderer/d3d/ShaderD3D.h" -#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/Program.h" #include "libANGLE/Shader.h" #include "libANGLE/formatutils.h" - -// For use with ArrayString, see angleutils.h -static_assert(GL_INVALID_INDEX == UINT_MAX, "GL_INVALID_INDEX must be equal to the max unsigned int."); +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/VaryingPacking.h" using namespace gl; @@ -31,12 +30,17 @@ std::string HLSLComponentTypeString(GLenum componentType) { switch (componentType) { - case GL_UNSIGNED_INT: return "uint"; - case GL_INT: return "int"; - case GL_UNSIGNED_NORMALIZED: - case GL_SIGNED_NORMALIZED: - case GL_FLOAT: return "float"; - default: UNREACHABLE(); return "not-component-type"; + case GL_UNSIGNED_INT: + return "uint"; + case GL_INT: + return "int"; + case GL_UNSIGNED_NORMALIZED: + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + return "float"; + default: + UNREACHABLE(); + return "not-component-type"; } } @@ -49,16 +53,27 @@ std::string HLSLMatrixTypeString(GLenum type) { switch (type) { - case GL_FLOAT_MAT2: return "float2x2"; - case GL_FLOAT_MAT3: return "float3x3"; - case GL_FLOAT_MAT4: return "float4x4"; - case GL_FLOAT_MAT2x3: return "float2x3"; - case GL_FLOAT_MAT3x2: return "float3x2"; - case GL_FLOAT_MAT2x4: return "float2x4"; - case GL_FLOAT_MAT4x2: return "float4x2"; - case GL_FLOAT_MAT3x4: return "float3x4"; - case GL_FLOAT_MAT4x3: return "float4x3"; - default: UNREACHABLE(); return "not-matrix-type"; + case GL_FLOAT_MAT2: + return "float2x2"; + case GL_FLOAT_MAT3: + return "float3x3"; + case GL_FLOAT_MAT4: + return "float4x4"; + case GL_FLOAT_MAT2x3: + return "float2x3"; + case GL_FLOAT_MAT3x2: + return "float3x2"; + case GL_FLOAT_MAT2x4: + return "float2x4"; + case GL_FLOAT_MAT4x2: + return "float4x2"; + case GL_FLOAT_MAT3x4: + return "float3x4"; + case GL_FLOAT_MAT4x3: + return "float4x3"; + default: + UNREACHABLE(); + return "not-matrix-type"; } } @@ -69,11 +84,13 @@ std::string HLSLTypeString(GLenum type) return HLSLMatrixTypeString(type); } - return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type)); + return HLSLComponentTypeString(gl::VariableComponentType(type), + gl::VariableComponentCount(type)); } -const PixelShaderOutputVariable *FindOutputAtLocation(const std::vector &outputVariables, - unsigned int location) +const PixelShaderOutputVariable *FindOutputAtLocation( + const std::vector &outputVariables, + unsigned int location) { for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex) { @@ -83,314 +100,102 @@ const PixelShaderOutputVariable *FindOutputAtLocation(const std::vectorisStruct()) - { - registers = HLSLVariableRegisterCount(*varying, true) * varying->elementCount(); - elements = 4; - } - else + static_assert(GL_INVALID_INDEX == UINT_MAX, + "GL_INVALID_INDEX must be equal to the max unsigned int."); + if (i == UINT_MAX) { - GLenum transposedType = TransposeMatrixType(varying->type); - registers = VariableRowCount(transposedType) * varying->elementCount(); - elements = VariableColumnCount(transposedType); + return; } - if (elements >= 2 && elements <= 4) - { - for (int r = 0; r <= maxVaryingVectors - registers; r++) - { - bool available = true; - - for (int y = 0; y < registers && available; y++) - { - for (int x = 0; x < elements && available; x++) - { - if (packing[r + y][x]) - { - available = false; - } - } - } - - if (available) - { - varying->registerIndex = r; - varying->columnIndex = 0; - - for (int y = 0; y < registers; y++) - { - for (int x = 0; x < elements; x++) - { - packing[r + y][x] = &*varying; - } - } - - return true; - } - } - - if (elements == 2) - { - for (int r = maxVaryingVectors - registers; r >= 0; r--) - { - bool available = true; - - for (int y = 0; y < registers && available; y++) - { - for (int x = 2; x < 4 && available; x++) - { - if (packing[r + y][x]) - { - available = false; - } - } - } - - if (available) - { - varying->registerIndex = r; - varying->columnIndex = 2; - - for (int y = 0; y < registers; y++) - { - for (int x = 2; x < 4; x++) - { - packing[r + y][x] = &*varying; - } - } - - return true; - } - } - } - } - else if (elements == 1) - { - int space[4] = { 0 }; - - for (int y = 0; y < maxVaryingVectors; y++) - { - for (int x = 0; x < 4; x++) - { - space[x] += packing[y][x] ? 0 : 1; - } - } - - int column = 0; - - for (int x = 0; x < 4; x++) - { - if (space[x] >= registers && (space[column] < registers || space[x] < space[column])) - { - column = x; - } - } + strstr << "["; + strstr << i; + strstr << "]"; +} - if (space[column] >= registers) - { - for (int r = 0; r < maxVaryingVectors; r++) - { - if (!packing[r][column]) - { - varying->registerIndex = r; - varying->columnIndex = column; +const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; +const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; +} // anonymous namespace - for (int y = r; y < r + registers; y++) - { - packing[y][column] = &*varying; - } +std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize) +{ + // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) + // In D3D11 we manually compute gl_PointCoord in the GS. + return ((programUsesPointSize && majorShaderModel < 4) ? "COLOR" : "TEXCOORD"); +} - break; - } - } +// DynamicHLSL implementation - return true; - } - } - else UNREACHABLE(); - - return false; +DynamicHLSL::DynamicHLSL(RendererD3D *const renderer) : mRenderer(renderer) +{ } -// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111 -// Returns the number of used varying registers, or -1 if unsuccesful -int DynamicHLSL::packVaryings(InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader, - ShaderD3D *vertexShader, const std::vector &transformFeedbackVaryings) +void DynamicHLSL::generateVaryingHLSL(const VaryingPacking &varyingPacking, + std::stringstream &hlslStream) const { - // TODO (geofflang): Use context's caps - const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors; - - vertexShader->resetVaryingsRegisterAssignment(); - fragmentShader->resetVaryingsRegisterAssignment(); + std::string varyingSemantic = + GetVaryingSemantic(mRenderer->getMajorShaderModel(), varyingPacking.usesPointSize()); - std::set packedVaryings; - - std::vector &fragmentVaryings = fragmentShader->getVaryings(); - std::vector &vertexVaryings = vertexShader->getVaryings(); - for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++) + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) { - PackedVarying *varying = &fragmentVaryings[varyingIndex]; - - // Do not assign registers to built-in or unreferenced varyings - if (varying->isBuiltIn() || !varying->staticUse) - { - continue; - } - - if (packVarying(varying, maxVaryingVectors, packing)) - { - packedVaryings.insert(varying->name); - } - else - { - infoLog.append("Could not pack varying %s", varying->name.c_str()); - return -1; - } - } + const auto &varying = *registerInfo.packedVarying->varying; + ASSERT(!varying.isStruct()); - for (unsigned int feedbackVaryingIndex = 0; feedbackVaryingIndex < transformFeedbackVaryings.size(); feedbackVaryingIndex++) - { - const std::string &transformFeedbackVarying = transformFeedbackVaryings[feedbackVaryingIndex]; + // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many + // registers being used. + // For example, if there are N registers, and we have N vec3 varyings and 1 float + // varying, then D3D will pack them into N registers. + // If the float varying has the 'nointerpolation' modifier on it then we would need + // N + 1 registers, and D3D compilation will fail. - if (transformFeedbackVarying == "gl_Position" || transformFeedbackVarying == "gl_PointSize") + switch (registerInfo.packedVarying->interpolation) { - // do not pack builtin XFB varyings - continue; + case sh::INTERPOLATION_SMOOTH: + hlslStream << " "; + break; + case sh::INTERPOLATION_FLAT: + hlslStream << " nointerpolation "; + break; + case sh::INTERPOLATION_CENTROID: + hlslStream << " centroid "; + break; + default: + UNREACHABLE(); } - if (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end()) - { - bool found = false; - for (unsigned int varyingIndex = 0; varyingIndex < vertexVaryings.size(); varyingIndex++) - { - PackedVarying *varying = &vertexVaryings[varyingIndex]; - if (transformFeedbackVarying == varying->name) - { - if (!packVarying(varying, maxVaryingVectors, packing)) - { - infoLog.append("Could not pack varying %s", varying->name.c_str()); - return -1; - } - - found = true; - break; - } - } - - if (!found) - { - infoLog.append("Transform feedback varying %s does not exist in the vertex shader.", transformFeedbackVarying.c_str()); - return -1; - } - } - } - - // Return the number of used registers - int registers = 0; - - for (int r = 0; r < maxVaryingVectors; r++) - { - if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3]) - { - registers++; - } + GLenum transposedType = gl::TransposeMatrixType(varying.type); + GLenum componentType = gl::VariableComponentType(transposedType); + int columnCount = gl::VariableColumnCount(transposedType); + hlslStream << HLSLComponentTypeString(componentType, columnCount); + unsigned int semanticIndex = registerInfo.semanticIndex; + hlslStream << " v" << semanticIndex << " : " << varyingSemantic << semanticIndex << ";\n"; } - - return registers; } -std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const +std::string DynamicHLSL::generateVertexShaderForInputLayout( + const std::string &sourceShader, + const InputLayout &inputLayout, + const std::vector &shaderAttributes) const { - std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize); - std::string varyingHLSL; - - const std::vector &varyings = shader->getVaryings(); + std::stringstream structStream; + std::stringstream initStream; - for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++) - { - const PackedVarying &varying = varyings[varyingIndex]; - if (varying.registerAssigned()) - { - ASSERT(!varying.isBuiltIn()); - GLenum transposedType = TransposeMatrixType(varying.type); - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); - - for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) - { - for (int row = 0; row < variableRows; row++) - { - // TODO: Add checks to ensure D3D interpolation modifiers don't result in too many registers being used. - // For example, if there are N registers, and we have N vec3 varyings and 1 float varying, then D3D will pack them into N registers. - // If the float varying has the 'nointerpolation' modifier on it then we would need N + 1 registers, and D3D compilation will fail. - - switch (varying.interpolation) - { - case sh::INTERPOLATION_SMOOTH: varyingHLSL += " "; break; - case sh::INTERPOLATION_FLAT: varyingHLSL += " nointerpolation "; break; - case sh::INTERPOLATION_CENTROID: varyingHLSL += " centroid "; break; - default: UNREACHABLE(); - } - - unsigned int semanticIndex = elementIndex * variableRows + - varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + - varying.registerIndex + row; - std::string n = Str(semanticIndex); - - std::string typeString; - - if (varying.isStruct()) - { - // TODO(jmadill): pass back translated name from the shader translator - typeString = decorateVariable(varying.structName); - } - else - { - GLenum componentType = VariableComponentType(transposedType); - int columnCount = VariableColumnCount(transposedType); - typeString = HLSLComponentTypeString(componentType, columnCount); - } - varyingHLSL += typeString + " v" + n + " : " + varyingSemantic + n + ";\n"; - } - } - } - } - - return varyingHLSL; -} + structStream << "struct VS_INPUT\n" + << "{\n"; -std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &sourceShader, - const VertexFormat inputLayout[], - const sh::Attribute shaderAttributes[]) const -{ - std::string structHLSL, initHLSL; - - int semanticIndex = 0; + int semanticIndex = 0; unsigned int inputIndex = 0; // If gl_PointSize is used in the shader then pointsprites rendering is expected. // If the renderer does not support Geometry shaders then Instanced PointSprite emulation // must be used. bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos; - bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; + bool useInstancedPointSpriteEmulation = + usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; // Instanced PointSprite emulation requires additional entries in the // VS_INPUT structure to support the vertices that make up the quad vertices. @@ -402,102 +207,109 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s // before per instance data in the shader. if (useInstancedPointSpriteEmulation) { - structHLSL += " float3 spriteVertexPos : SPRITEPOSITION0;\n"; - structHLSL += " float2 spriteTexCoord : SPRITETEXCOORD0;\n"; + structStream << " float3 spriteVertexPos : SPRITEPOSITION0;\n" + << " float2 spriteTexCoord : SPRITETEXCOORD0;\n"; } - for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); ++attributeIndex) { const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex]; if (!shaderAttribute.name.empty()) { ASSERT(inputIndex < MAX_VERTEX_ATTRIBS); - const VertexFormat &vertexFormat = inputLayout[inputIndex]; + VertexFormatType vertexFormatType = + inputIndex < inputLayout.size() ? inputLayout[inputIndex] : VERTEX_FORMAT_INVALID; // HLSL code for input structure if (IsMatrixType(shaderAttribute.type)) { // Matrix types are always transposed - structHLSL += " " + HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type)); + structStream << " " + << HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type)); } else { - GLenum componentType = mRenderer->getVertexComponentType(vertexFormat); + GLenum componentType = mRenderer->getVertexComponentType(vertexFormatType); if (shaderAttribute.name == "gl_InstanceID") { - // The input type of the instance ID in HLSL (uint) differs from the one in ESSL (int). - structHLSL += " uint"; + // The input type of the instance ID in HLSL (uint) differs from the one in ESSL + // (int). + structStream << " uint"; } else { - structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type)); + structStream << " " << HLSLComponentTypeString( + componentType, + VariableComponentCount(shaderAttribute.type)); } } - structHLSL += " " + decorateVariable(shaderAttribute.name) + " : "; + structStream << " " << decorateVariable(shaderAttribute.name) << " : "; if (shaderAttribute.name == "gl_InstanceID") { - structHLSL += "SV_InstanceID"; + structStream << "SV_InstanceID"; } else { - structHLSL += "TEXCOORD" + Str(semanticIndex); + structStream << "TEXCOORD" << semanticIndex; semanticIndex += VariableRegisterCount(shaderAttribute.type); } - structHLSL += ";\n"; + structStream << ";\n"; // HLSL code for initialization - initHLSL += " " + decorateVariable(shaderAttribute.name) + " = "; + initStream << " " << decorateVariable(shaderAttribute.name) << " = "; // Mismatched vertex attribute to vertex input may result in an undefined // data reinterpretation (eg for pure integer->float, float->pure integer) // TODO: issue warning with gl debug info extension, when supported if (IsMatrixType(shaderAttribute.type) || - (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0) + (mRenderer->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_GPU) != 0) { - initHLSL += generateAttributeConversionHLSL(vertexFormat, shaderAttribute); + initStream << generateAttributeConversionHLSL(vertexFormatType, shaderAttribute); } else { - initHLSL += "input." + decorateVariable(shaderAttribute.name); + initStream << "input." << decorateVariable(shaderAttribute.name); } - initHLSL += ";\n"; + initStream << ";\n"; inputIndex += VariableRowCount(TransposeMatrixType(shaderAttribute.type)); } } - std::string replacementHLSL = "struct VS_INPUT\n" - "{\n" + - structHLSL + - "};\n" - "\n" - "void initAttributes(VS_INPUT input)\n" - "{\n" + - initHLSL + - "}\n"; + structStream << "};\n" + "\n" + "void initAttributes(VS_INPUT input)\n" + "{\n" + << initStream.str() << "}\n"; std::string vertexHLSL(sourceShader); size_t copyInsertionPos = vertexHLSL.find(VERTEX_ATTRIBUTE_STUB_STRING); - vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), replacementHLSL); + vertexHLSL.replace(copyInsertionPos, VERTEX_ATTRIBUTE_STUB_STRING.length(), structStream.str()); return vertexHLSL; } -std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector &outputVariables, - bool usesFragDepth, const std::vector &outputLayout) const +std::string DynamicHLSL::generatePixelShaderForOutputSignature( + const std::string &sourceShader, + const std::vector &outputVariables, + bool usesFragDepth, + const std::vector &outputLayout) const { - const int shaderModel = mRenderer->getMajorShaderModel(); + const int shaderModel = mRenderer->getMajorShaderModel(); std::string targetSemantic = (shaderModel >= 4) ? "SV_TARGET" : "COLOR"; - std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; + std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; + + std::stringstream declarationStream; + std::stringstream copyStream; - std::string declarationHLSL; - std::string copyHLSL; + declarationStream << "struct PS_OUTPUT\n" + "{\n"; for (size_t layoutIndex = 0; layoutIndex < outputLayout.size(); ++layoutIndex) { @@ -507,703 +319,680 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string { unsigned int location = (binding - GL_COLOR_ATTACHMENT0); - const PixelShaderOutputVariable *outputVariable = FindOutputAtLocation(outputVariables, location); + const PixelShaderOutputVariable *outputVariable = + FindOutputAtLocation(outputVariables, location); // OpenGL ES 3.0 spec $4.2.1 - // If [...] not all user-defined output variables are written, the values of fragment colors + // If [...] not all user-defined output variables are written, the values of fragment + // colors // corresponding to unwritten variables are similarly undefined. if (outputVariable) { - declarationHLSL += " " + HLSLTypeString(outputVariable->type) + " " + outputVariable->name + - " : " + targetSemantic + Str(layoutIndex) + ";\n"; + declarationStream << " " + HLSLTypeString(outputVariable->type) << " " + << outputVariable->name << " : " << targetSemantic + << static_cast(layoutIndex) << ";\n"; - copyHLSL += " output." + outputVariable->name + " = " + outputVariable->source + ";\n"; + copyStream << " output." << outputVariable->name << " = " + << outputVariable->source << ";\n"; } } } if (usesFragDepth) { - declarationHLSL += " float gl_Depth : " + depthSemantic + ";\n"; - copyHLSL += " output.gl_Depth = gl_Depth; \n"; + declarationStream << " float gl_Depth : " << depthSemantic << ";\n"; + copyStream << " output.gl_Depth = gl_Depth; \n"; } - std::string replacementHLSL = "struct PS_OUTPUT\n" - "{\n" + - declarationHLSL + - "};\n" - "\n" - "PS_OUTPUT generateOutput()\n" - "{\n" - " PS_OUTPUT output;\n" + - copyHLSL + - " return output;\n" - "}\n"; + declarationStream << "};\n" + "\n" + "PS_OUTPUT generateOutput()\n" + "{\n" + " PS_OUTPUT output;\n" + << copyStream.str() << " return output;\n" + "}\n"; std::string pixelHLSL(sourceShader); size_t outputInsertionPos = pixelHLSL.find(PIXEL_OUTPUT_STUB_STRING); - pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), replacementHLSL); + pixelHLSL.replace(outputInsertionPos, PIXEL_OUTPUT_STUB_STRING.length(), + declarationStream.str()); return pixelHLSL; } -std::string DynamicHLSL::getVaryingSemantic(bool pointSize) const -{ - // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) - // In D3D11 we manually compute gl_PointCoord in the GS. - int shaderModel = mRenderer->getMajorShaderModel(); - return ((pointSize && shaderModel < 4) ? "COLOR" : "TEXCOORD"); -} - -struct DynamicHLSL::SemanticInfo -{ - struct BuiltinInfo - { - BuiltinInfo() - : enabled(false), - index(0), - systemValue(false) - {} - - bool enabled; - std::string semantic; - unsigned int index; - bool systemValue; - - std::string str() const - { - return (systemValue ? semantic : (semantic + Str(index))); - } - - void enableSystem(const std::string &systemValueSemantic) - { - enabled = true; - semantic = systemValueSemantic; - systemValue = true; - } - - void enable(const std::string &semanticVal, unsigned int indexVal) - { - enabled = true; - semantic = semanticVal; - index = indexVal; - } - }; - - BuiltinInfo dxPosition; - BuiltinInfo glPosition; - BuiltinInfo glFragCoord; - BuiltinInfo glPointCoord; - BuiltinInfo glPointSize; -}; - -DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool position, bool fragCoord, - bool pointCoord, bool pointSize, bool pixelShader) const +void DynamicHLSL::generateVaryingLinkHLSL(ShaderType shaderType, + const VaryingPacking &varyingPacking, + std::stringstream &linkStream) const { - SemanticInfo info; - bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4); - const std::string &varyingSemantic = getVaryingSemantic(pointSize); - - int reservedRegisterIndex = startRegisters; + const auto &builtins = varyingPacking.builtins(shaderType); + ASSERT(builtins.dxPosition.enabled); + linkStream << "{\n" + << " float4 dx_Position : " << builtins.dxPosition.str() << ";\n"; - if (hlsl4) + if (builtins.glPosition.enabled) { - info.dxPosition.enableSystem("SV_Position"); - } - else if (pixelShader) - { - info.dxPosition.enableSystem("VPOS"); - } - else - { - info.dxPosition.enableSystem("POSITION"); - } - - if (position) - { - info.glPosition.enable(varyingSemantic, reservedRegisterIndex++); - } - - if (fragCoord) - { - info.glFragCoord.enable(varyingSemantic, reservedRegisterIndex++); - } - - if (pointCoord) - { - // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) - // In D3D11 we manually compute gl_PointCoord in the GS. - if (hlsl4) - { - info.glPointCoord.enable(varyingSemantic, reservedRegisterIndex++); - } - else - { - info.glPointCoord.enable("TEXCOORD", 0); - } - } - - // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders - if (pointSize && (!pixelShader || hlsl4)) - { - info.glPointSize.enableSystem("PSIZE"); + linkStream << " float4 gl_Position : " << builtins.glPosition.str() << ";\n"; } - return info; -} - -std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const -{ - std::string linkHLSL = "{\n"; - - ASSERT(info.dxPosition.enabled); - linkHLSL += " float4 dx_Position : " + info.dxPosition.str() + ";\n"; - - if (info.glPosition.enabled) - { - linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n"; - } - - if (info.glFragCoord.enabled) - { - linkHLSL += " float4 gl_FragCoord : " + info.glFragCoord.str() + ";\n"; - } - - if (info.glPointCoord.enabled) - { - linkHLSL += " float2 gl_PointCoord : " + info.glPointCoord.str() + ";\n"; - } - - if (info.glPointSize.enabled) - { - linkHLSL += " float gl_PointSize : " + info.glPointSize.str() + ";\n"; - } - - // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the same register. - linkHLSL += varyingHLSL; - - linkHLSL += "};\n"; - - return linkHLSL; -} - -void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info, - std::vector *linkedVaryings) const -{ - if (info.glPosition.enabled) + if (builtins.glFragCoord.enabled) { - linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic, - info.glPosition.index, 1)); + linkStream << " float4 gl_FragCoord : " << builtins.glFragCoord.str() << ";\n"; } - if (info.glFragCoord.enabled) + if (builtins.glPointCoord.enabled) { - linkedVaryings->push_back(LinkedVarying("gl_FragCoord", GL_FLOAT_VEC4, 1, info.glFragCoord.semantic, - info.glFragCoord.index, 1)); + linkStream << " float2 gl_PointCoord : " << builtins.glPointCoord.str() << ";\n"; } - if (info.glPointSize.enabled) + if (builtins.glPointSize.enabled) { - linkedVaryings->push_back(LinkedVarying("gl_PointSize", GL_FLOAT, 1, "PSIZE", 0, 1)); + linkStream << " float gl_PointSize : " << builtins.glPointSize.str() << ";\n"; } -} - -void DynamicHLSL::storeUserLinkedVaryings(const ShaderD3D *vertexShader, - std::vector *linkedVaryings) const -{ - const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize); - const std::vector &varyings = vertexShader->getVaryings(); - for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++) - { - const PackedVarying &varying = varyings[varyingIndex]; - - if (varying.registerAssigned()) - { - ASSERT(!varying.isBuiltIn()); - GLenum transposedType = TransposeMatrixType(varying.type); - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); + // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the + // same register. + generateVaryingHLSL(varyingPacking, linkStream); - linkedVaryings->push_back(LinkedVarying(varying.name, varying.type, varying.elementCount(), - varyingSemantic, varying.registerIndex, - variableRows * varying.elementCount())); - } - } + linkStream << "};\n"; } -bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog, int registers, - const VaryingPacking packing, - std::string &pixelHLSL, std::string &vertexHLSL, - ShaderD3D *fragmentShader, ShaderD3D *vertexShader, - const std::vector &transformFeedbackVaryings, - std::vector *linkedVaryings, - std::map *programOutputVars, - std::vector *outPixelShaderKey, - bool *outUsesFragDepth) const +bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, + const gl::Program::Data &programData, + const ProgramD3DMetadata &programMetadata, + const VaryingPacking &varyingPacking, + std::string *pixelHLSL, + std::string *vertexHLSL) const { - if (pixelHLSL.empty() || vertexHLSL.empty()) - { - return false; - } + ASSERT(pixelHLSL->empty() && vertexHLSL->empty()); - bool usesMRT = fragmentShader->mUsesMultipleRenderTargets; - bool usesFragColor = fragmentShader->mUsesFragColor; - bool usesFragData = fragmentShader->mUsesFragData; - bool usesFragCoord = fragmentShader->mUsesFragCoord; - bool usesPointCoord = fragmentShader->mUsesPointCoord; - bool usesPointSize = vertexShader->mUsesPointSize; - bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; + const gl::Shader *vertexShaderGL = programData.getAttachedVertexShader(); + const ShaderD3D *vertexShader = GetImplAs(vertexShaderGL); + const gl::Shader *fragmentShaderGL = programData.getAttachedFragmentShader(); + const ShaderD3D *fragmentShader = GetImplAs(fragmentShaderGL); + const int shaderModel = mRenderer->getMajorShaderModel(); - if (usesFragColor && usesFragData) - { - infoLog.append("Cannot use both gl_FragColor and gl_FragData in the same fragment shader."); - return false; - } - - // Write the HLSL input/output declarations - const int shaderModel = mRenderer->getMajorShaderModel(); - const int registersNeeded = registers + (usesFragCoord ? 1 : 0) + (usesPointCoord ? 1 : 0); - - // Two cases when writing to gl_FragColor and using ESSL 1.0: - // - with a 3.0 context, the output color is copied to channel 0 - // - with a 2.0 context, the output color is broadcast to all channels - const bool broadcast = (fragmentShader->mUsesFragColor && data.clientVersion < 3); - const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1); - - // gl_Position only needs to be outputted from the vertex shader if transform feedback is active. - // This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from the vertex shader in this case. - // This saves us 1 output vector. - bool outputPositionFromVS = !(shaderModel >= 4 && mRenderer->getShaderModelSuffix() != ""); - - int shaderVersion = vertexShader->getShaderVersion(); - - if (static_cast(registersNeeded) > data.caps->maxVaryingVectors) - { - infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord"); - return false; - } + // usesViewScale() isn't supported in the D3D9 renderer + ASSERT(shaderModel >= 4 || !programMetadata.usesViewScale()); - const std::string &varyingHLSL = generateVaryingHLSL(vertexShader); + bool useInstancedPointSpriteEmulation = + programMetadata.usesPointSize() && + mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; - // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader VS_OUTPUT - // structure to ensure compatibility with the generated PS_INPUT of the pixel shader. - // GeometryShader PointSprite emulation does not require this additional entry because the - // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the PS_INPUT of the - // generated pixel shader. - // The Geometry Shader point sprite implementation needs gl_PointSize to be in VS_OUTPUT and GS_INPUT. - // Instanced point sprites doesn't need gl_PointSize in VS_OUTPUT. - const SemanticInfo &vertexSemantics = getSemanticInfo(registers, outputPositionFromVS, - usesFragCoord, (useInstancedPointSpriteEmulation && usesPointCoord), - (!useInstancedPointSpriteEmulation && usesPointSize), false); + // Validation done in the compiler + ASSERT(!fragmentShader->usesFragColor() || !fragmentShader->usesFragData()); - storeUserLinkedVaryings(vertexShader, linkedVaryings); - storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings); + std::stringstream vertexStream; + vertexStream << vertexShaderGL->getTranslatedSource(); // Instanced PointSprite emulation requires additional entries originally generated in the - // GeometryShader HLSL. These include pointsize clamp values. + // GeometryShader HLSL. These include pointsize clamp values. if (useInstancedPointSpriteEmulation) { - vertexHLSL += "static float minPointSize = " + Str((int)mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" - "static float maxPointSize = " + Str((int)mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n"; + vertexStream << "static float minPointSize = " + << static_cast(data.caps->minAliasedPointSize) << ".0f;\n" + << "static float maxPointSize = " + << static_cast(data.caps->maxAliasedPointSize) << ".0f;\n"; } // Add stub string to be replaced when shader is dynamically defined by its layout - vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n" - "struct VS_OUTPUT\n" + generateVaryingLinkHLSL(vertexSemantics, varyingHLSL) + "\n" - "VS_OUTPUT main(VS_INPUT input)\n" - "{\n" - " initAttributes(input);\n"; + vertexStream << "\n" << VERTEX_ATTRIBUTE_STUB_STRING + "\n"; + + // Write the HLSL input/output declarations + vertexStream << "struct VS_OUTPUT\n"; + generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, vertexStream); + vertexStream << "\n" + << "VS_OUTPUT main(VS_INPUT input)\n" + << "{\n" + << " initAttributes(input);\n"; if (vertexShader->usesDeferredInit()) { - vertexHLSL += "\n" - " initializeDeferredGlobals();\n"; + vertexStream << "\n" + << " initializeDeferredGlobals();\n"; } - vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n"; + vertexStream << "\n" + << " gl_main();\n" + << "\n" + << " VS_OUTPUT output;\n"; + + const auto &vertexBuiltins = varyingPacking.builtins(SHADER_VERTEX); - if (outputPositionFromVS) + if (vertexBuiltins.glPosition.enabled) { - vertexHLSL += " output.gl_Position = gl_Position;\n"; + vertexStream << " output.gl_Position = gl_Position;\n"; } // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust. - if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") { - vertexHLSL += " output.dx_Position.x = gl_Position.x;\n" - " output.dx_Position.y = -gl_Position.y;\n" - " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.dx_Position.w = gl_Position.w;\n"; + vertexStream << " output.dx_Position.x = gl_Position.x;\n"; + + if (programMetadata.usesViewScale()) + { + // This code assumes that dx_ViewScale.y = -1.0f when rendering to texture, and +1.0f + // when rendering to the default framebuffer. No other values are valid. + vertexStream << " output.dx_Position.y = dx_ViewScale.y * gl_Position.y;\n"; + } + else + { + vertexStream << " output.dx_Position.y = - gl_Position.y;\n"; + } + + vertexStream << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + << " output.dx_Position.w = gl_Position.w;\n"; } else { - vertexHLSL += " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" - " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" - " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.dx_Position.w = gl_Position.w;\n"; + vertexStream << " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + " + "dx_ViewAdjust.x * gl_Position.w;\n"; + + // If usesViewScale() is true and we're using the D3D11 renderer via Feature Level 9_*, + // then we need to multiply the gl_Position.y by the viewScale. + // usesViewScale() isn't supported when using the D3D9 renderer. + if (programMetadata.usesViewScale() && + (shaderModel >= 4 && mRenderer->getShaderModelSuffix() != "")) + { + vertexStream << " output.dx_Position.y = dx_ViewScale.y * (gl_Position.y * " + "dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"; + } + else + { + vertexStream << " output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + " + "dx_ViewAdjust.y * gl_Position.w);\n"; + } + + vertexStream << " output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" + << " output.dx_Position.w = gl_Position.w;\n"; } // We don't need to output gl_PointSize if we use are emulating point sprites via instancing. - if (usesPointSize && shaderModel >= 3 && !useInstancedPointSpriteEmulation) + if (vertexBuiltins.glPointSize.enabled) { - vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; + vertexStream << " output.gl_PointSize = gl_PointSize;\n"; } - if (usesFragCoord) + if (vertexBuiltins.glFragCoord.enabled) { - vertexHLSL += " output.gl_FragCoord = gl_Position;\n"; + vertexStream << " output.gl_FragCoord = gl_Position;\n"; } - const std::vector &vertexVaryings = vertexShader->getVaryings(); - for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) { - const PackedVarying &varying = vertexVaryings[vertVaryingIndex]; - if (varying.registerAssigned()) - { - for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) - { - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(TransposeMatrixType(varying.type))); + const auto &packedVarying = *registerInfo.packedVarying; + const auto &varying = *packedVarying.varying; + ASSERT(!varying.isStruct()); - for (int row = 0; row < variableRows; row++) - { - int r = varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row; - vertexHLSL += " output.v" + Str(r); + vertexStream << " output.v" << registerInfo.semanticIndex << " = "; - vertexHLSL += " = _" + varying.name; + if (packedVarying.isStructField()) + { + vertexStream << decorateVariable(packedVarying.parentStructName) << "."; + } - if (varying.isArray()) - { - vertexHLSL += ArrayString(elementIndex); - } + vertexStream << decorateVariable(varying.name); - if (variableRows > 1) - { - vertexHLSL += ArrayString(row); - } + if (varying.isArray()) + { + WriteArrayString(vertexStream, registerInfo.varyingArrayIndex); + } - vertexHLSL += ";\n"; - } - } + if (VariableRowCount(varying.type) > 1) + { + WriteArrayString(vertexStream, registerInfo.varyingRowIndex); } + + vertexStream << ";\n"; } // Instanced PointSprite emulation requires additional entries to calculate // the final output vertex positions of the quad that represents each sprite. if (useInstancedPointSpriteEmulation) { - vertexHLSL += "\n" - " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n" - " output.dx_Position.xyz += float3(input.spriteVertexPos.x * gl_PointSize / (dx_ViewCoords.x*2), input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2), input.spriteVertexPos.z) * output.dx_Position.w;\n"; + vertexStream << "\n" + << " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n"; + + vertexStream << " output.dx_Position.x += (input.spriteVertexPos.x * gl_PointSize / " + "(dx_ViewCoords.x*2)) * output.dx_Position.w;"; - if (usesPointCoord) + if (programMetadata.usesViewScale()) { - vertexHLSL += "\n" - " output.gl_PointCoord = input.spriteTexCoord;\n"; + // Multiply by ViewScale to invert the rendering when appropriate + vertexStream << " output.dx_Position.y += (-dx_ViewScale.y * " + "input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2)) * " + "output.dx_Position.w;"; } - } - - vertexHLSL += "\n" - " return output;\n" - "}\n"; - - const SemanticInfo &pixelSemantics = getSemanticInfo(registers, outputPositionFromVS, usesFragCoord, usesPointCoord, - (!useInstancedPointSpriteEmulation && usesPointSize), true); - - pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n"; - - if (shaderVersion < 300) - { - for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) + else { - PixelShaderOutputVariable outputKeyVariable; - outputKeyVariable.type = GL_FLOAT_VEC4; - outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex); - outputKeyVariable.source = broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]"; - outputKeyVariable.outputIndex = renderTargetIndex; - - outPixelShaderKey->push_back(outputKeyVariable); + vertexStream << " output.dx_Position.y += (input.spriteVertexPos.y * gl_PointSize / " + "(dx_ViewCoords.y*2)) * output.dx_Position.w;"; } - *outUsesFragDepth = fragmentShader->mUsesFragDepth; - } - else - { - defineOutputVariables(fragmentShader, programOutputVars); + vertexStream + << " output.dx_Position.z += input.spriteVertexPos.z * output.dx_Position.w;\n"; - const std::vector &shaderOutputVars = fragmentShader->getActiveOutputVariables(); - for (auto locationIt = programOutputVars->begin(); locationIt != programOutputVars->end(); locationIt++) + if (programMetadata.usesPointCoord()) { - const VariableLocation &outputLocation = locationIt->second; - const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; - const std::string &variableName = "out_" + outputLocation.name; - const std::string &elementString = (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); - - ASSERT(outputVariable.staticUse); - - PixelShaderOutputVariable outputKeyVariable; - outputKeyVariable.type = outputVariable.type; - outputKeyVariable.name = variableName + elementString; - outputKeyVariable.source = variableName + ArrayString(outputLocation.element); - outputKeyVariable.outputIndex = locationIt->first; - - outPixelShaderKey->push_back(outputKeyVariable); + vertexStream << "\n" + << " output.gl_PointCoord = input.spriteTexCoord;\n"; } + } - *outUsesFragDepth = false; + // Renderers that enable instanced pointsprite emulation require the vertex shader output member + // gl_PointCoord to be set to a default value if used without gl_PointSize. 0.5,0.5 is the same + // default value used in the generated pixel shader. + if (programMetadata.usesInsertedPointCoordValue()) + { + ASSERT(!useInstancedPointSpriteEmulation); + vertexStream << "\n" + << " output.gl_PointCoord = float2(0.5, 0.5);\n"; } - pixelHLSL += PIXEL_OUTPUT_STUB_STRING + "\n"; + vertexStream << "\n" + << " return output;\n" + << "}\n"; + + std::stringstream pixelStream; + pixelStream << fragmentShaderGL->getTranslatedSource(); + pixelStream << "struct PS_INPUT\n"; + generateVaryingLinkHLSL(SHADER_PIXEL, varyingPacking, pixelStream); + pixelStream << "\n"; + + pixelStream << PIXEL_OUTPUT_STUB_STRING + "\n"; - if (fragmentShader->mUsesFrontFacing) + if (fragmentShader->usesFrontFacing()) { if (shaderModel >= 4) { - pixelHLSL += "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n" - "{\n"; + pixelStream << "PS_OUTPUT main(PS_INPUT input, bool isFrontFace : SV_IsFrontFace)\n" + << "{\n"; } else { - pixelHLSL += "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n" - "{\n"; + pixelStream << "PS_OUTPUT main(PS_INPUT input, float vFace : VFACE)\n" + << "{\n"; } } else { - pixelHLSL += "PS_OUTPUT main(PS_INPUT input)\n" - "{\n"; + pixelStream << "PS_OUTPUT main(PS_INPUT input)\n" + << "{\n"; } - if (usesFragCoord) + const auto &pixelBuiltins = varyingPacking.builtins(SHADER_PIXEL); + + if (pixelBuiltins.glFragCoord.enabled) { - pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; + pixelStream << " float rhw = 1.0 / input.gl_FragCoord.w;\n"; // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader. - // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using dx_ViewCoords. + // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using + // dx_ViewCoords. if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") { - pixelHLSL += " gl_FragCoord.x = input.dx_Position.x;\n" - " gl_FragCoord.y = input.dx_Position.y;\n"; + pixelStream << " gl_FragCoord.x = input.dx_Position.x;\n" + << " gl_FragCoord.y = input.dx_Position.y;\n"; } else if (shaderModel == 3) { - pixelHLSL += " gl_FragCoord.x = input.dx_Position.x + 0.5;\n" - " gl_FragCoord.y = input.dx_Position.y + 0.5;\n"; + pixelStream << " gl_FragCoord.x = input.dx_Position.x + 0.5;\n" + << " gl_FragCoord.y = input.dx_Position.y + 0.5;\n"; } else { - // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See Renderer::setViewport() - pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + dx_ViewCoords.z;\n" - " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + dx_ViewCoords.w;\n"; + // dx_ViewCoords contains the viewport width/2, height/2, center.x and center.y. See + // Renderer::setViewport() + pixelStream << " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_ViewCoords.x + " + "dx_ViewCoords.z;\n" + << " gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_ViewCoords.y + " + "dx_ViewCoords.w;\n"; } - pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n" - " gl_FragCoord.w = rhw;\n"; + if (programMetadata.usesViewScale()) + { + // For Feature Level 9_3 and below, we need to correct gl_FragCoord.y to account + // for dx_ViewScale. On Feature Level 10_0+, gl_FragCoord.y is calculated above using + // dx_ViewCoords and is always correct irrespective of dx_ViewScale's value. + // NOTE: usesViewScale() can only be true on D3D11 (i.e. Shader Model 4.0+). + if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "") + { + // Some assumptions: + // - dx_ViewScale.y = -1.0f when rendering to texture + // - dx_ViewScale.y = +1.0f when rendering to the default framebuffer + // - gl_FragCoord.y has been set correctly above. + // + // When rendering to the backbuffer, the code inverts gl_FragCoord's y coordinate. + // This involves subtracting the y coordinate from the height of the area being + // rendered to. + // + // First we calculate the height of the area being rendered to: + // render_area_height = (2.0f / (1.0f - input.gl_FragCoord.y * rhw)) * + // gl_FragCoord.y + // + // Note that when we're rendering to default FB, we want our output to be + // equivalent to: + // "gl_FragCoord.y = render_area_height - gl_FragCoord.y" + // + // When we're rendering to a texture, we want our output to be equivalent to: + // "gl_FragCoord.y = gl_FragCoord.y;" + // + // If we set scale_factor = ((1.0f + dx_ViewScale.y) / 2.0f), then notice that + // - When rendering to default FB: scale_factor = 1.0f + // - When rendering to texture: scale_factor = 0.0f + // + // Therefore, we can get our desired output by setting: + // "gl_FragCoord.y = scale_factor * render_area_height - dx_ViewScale.y * + // gl_FragCoord.y" + // + // Simplifying, this becomes: + pixelStream + << " gl_FragCoord.y = (1.0f + dx_ViewScale.y) * gl_FragCoord.y /" + "(1.0f - input.gl_FragCoord.y * rhw) - dx_ViewScale.y * gl_FragCoord.y;\n"; + } + } + + pixelStream << " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + " + "dx_DepthFront.y;\n" + << " gl_FragCoord.w = rhw;\n"; } - if (usesPointCoord && shaderModel >= 3) + if (pixelBuiltins.glPointCoord.enabled && shaderModel >= 3) { - pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n"; - pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; + pixelStream << " gl_PointCoord.x = input.gl_PointCoord.x;\n" + << " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; } - if (fragmentShader->mUsesFrontFacing) + if (fragmentShader->usesFrontFacing()) { if (shaderModel <= 3) { - pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; + pixelStream << " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; } else { - pixelHLSL += " gl_FrontFacing = isFrontFace;\n"; + pixelStream << " gl_FrontFacing = isFrontFace;\n"; } } - const std::vector &fragmentVaryings = fragmentShader->getVaryings(); - for (unsigned int varyingIndex = 0; varyingIndex < fragmentVaryings.size(); varyingIndex++) + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) { - const PackedVarying &varying = fragmentVaryings[varyingIndex]; - if (varying.registerAssigned()) + const auto &packedVarying = *registerInfo.packedVarying; + const auto &varying = *packedVarying.varying; + ASSERT(!varying.isBuiltIn() && !varying.isStruct()); + + // Don't reference VS-only transform feedback varyings in the PS. + if (registerInfo.packedVarying->vertexOnly) + continue; + + pixelStream << " "; + + if (packedVarying.isStructField()) { - ASSERT(!varying.isBuiltIn()); - for (unsigned int elementIndex = 0; elementIndex < varying.elementCount(); elementIndex++) - { - GLenum transposedType = TransposeMatrixType(varying.type); - int variableRows = (varying.isStruct() ? 1 : VariableRowCount(transposedType)); - for (int row = 0; row < variableRows; row++) - { - std::string n = Str(varying.registerIndex + varying.columnIndex * data.caps->maxVaryingVectors + elementIndex * variableRows + row); - pixelHLSL += " _" + varying.name; - - if (varying.isArray()) - { - pixelHLSL += ArrayString(elementIndex); - } - - if (variableRows > 1) - { - pixelHLSL += ArrayString(row); - } - - if (varying.isStruct()) - { - pixelHLSL += " = input.v" + n + ";\n"; break; - } - else - { - switch (VariableColumnCount(transposedType)) - { - case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break; - case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break; - case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break; - case 4: pixelHLSL += " = input.v" + n + ";\n"; break; - default: UNREACHABLE(); - } - } - } - } + pixelStream << decorateVariable(packedVarying.parentStructName) << "."; } - else + + pixelStream << decorateVariable(varying.name); + + if (varying.isArray()) + { + WriteArrayString(pixelStream, registerInfo.varyingArrayIndex); + } + + GLenum transposedType = TransposeMatrixType(varying.type); + if (VariableRowCount(transposedType) > 1) { - ASSERT(varying.isBuiltIn() || !varying.staticUse); + WriteArrayString(pixelStream, registerInfo.varyingRowIndex); } + + pixelStream << " = input.v" << registerInfo.semanticIndex; + + switch (VariableColumnCount(transposedType)) + { + case 1: + pixelStream << ".x"; + break; + case 2: + pixelStream << ".xy"; + break; + case 3: + pixelStream << ".xyz"; + break; + case 4: + break; + default: + UNREACHABLE(); + } + pixelStream << ";\n"; } if (fragmentShader->usesDeferredInit()) { - pixelHLSL += "\n" - " initializeDeferredGlobals();\n"; + pixelStream << "\n" + << " initializeDeferredGlobals();\n"; } - pixelHLSL += "\n" - " gl_main();\n" - "\n" - " return generateOutput();\n" - "}\n"; + pixelStream << "\n" + << " gl_main();\n" + << "\n" + << " return generateOutput();\n" + << "}\n"; + + *vertexHLSL = vertexStream.str(); + *pixelHLSL = pixelStream.str(); return true; } -void DynamicHLSL::defineOutputVariables(ShaderD3D *fragmentShader, std::map *programOutputVars) const +std::string DynamicHLSL::generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const { - const std::vector &shaderOutputVars = fragmentShader->getActiveOutputVariables(); + ASSERT(mRenderer->getMajorShaderModel() >= 4); - for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++) - { - const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex]; - const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location; + std::stringstream preambleStream; - ASSERT(outputVariable.staticUse); + const auto &builtins = varyingPacking.builtins(SHADER_VERTEX); - if (outputVariable.arraySize > 0) - { - for (unsigned int elementIndex = 0; elementIndex < outputVariable.arraySize; elementIndex++) - { - const int location = baseLocation + elementIndex; - ASSERT(programOutputVars->count(location) == 0); - (*programOutputVars)[location] = VariableLocation(outputVariable.name, elementIndex, outputVariableIndex); - } - } - else + preambleStream << "struct GS_INPUT\n"; + generateVaryingLinkHLSL(SHADER_VERTEX, varyingPacking, preambleStream); + preambleStream << "\n" + << "struct GS_OUTPUT\n"; + generateVaryingLinkHLSL(SHADER_GEOMETRY, varyingPacking, preambleStream); + preambleStream + << "\n" + << "void copyVertex(inout GS_OUTPUT output, GS_INPUT input, GS_INPUT flatinput)\n" + << "{\n" + << " output.gl_Position = input.gl_Position;\n"; + + if (builtins.glPointSize.enabled) + { + preambleStream << " output.gl_PointSize = input.gl_PointSize;\n"; + } + + for (const PackedVaryingRegister &varyingRegister : varyingPacking.getRegisterList()) + { + preambleStream << " output.v" << varyingRegister.semanticIndex << " = "; + if (varyingRegister.packedVarying->interpolation == sh::INTERPOLATION_FLAT) { - ASSERT(programOutputVars->count(baseLocation) == 0); - (*programOutputVars)[baseLocation] = VariableLocation(outputVariable.name, GL_INVALID_INDEX, outputVariableIndex); + preambleStream << "flat"; } + preambleStream << "input.v" << varyingRegister.semanticIndex << "; \n"; } -} -std::string DynamicHLSL::generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const -{ - // for now we only handle point sprite emulation - ASSERT(vertexShader->mUsesPointSize && mRenderer->getMajorShaderModel() >= 4); - return generatePointSpriteHLSL(registers, fragmentShader, vertexShader); + if (builtins.glFragCoord.enabled) + { + preambleStream << " output.gl_FragCoord = input.gl_FragCoord;\n"; + } + + // Only write the dx_Position if we aren't using point sprites + preambleStream << "#ifndef ANGLE_POINT_SPRITE_SHADER\n" + << " output.dx_Position = input.dx_Position;\n" + << "#endif // ANGLE_POINT_SPRITE_SHADER\n" + << "}\n"; + + return preambleStream.str(); } -std::string DynamicHLSL::generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const +std::string DynamicHLSL::generateGeometryShaderHLSL(gl::PrimitiveType primitiveType, + const gl::Data &data, + const gl::Program::Data &programData, + const bool useViewScale, + const std::string &preambleString) const { - ASSERT(registers >= 0); - ASSERT(vertexShader->mUsesPointSize); ASSERT(mRenderer->getMajorShaderModel() >= 4); - std::string geomHLSL; - - const SemanticInfo &inSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord, - false, true, false); - const SemanticInfo &outSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord, - fragmentShader->mUsesPointCoord, true, false); - - std::string varyingHLSL = generateVaryingHLSL(vertexShader); - std::string inLinkHLSL = generateVaryingLinkHLSL(inSemantics, varyingHLSL); - std::string outLinkHLSL = generateVaryingLinkHLSL(outSemantics, varyingHLSL); - - // TODO(geofflang): use context's caps - geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n" - "\n" - "struct GS_INPUT\n" + inLinkHLSL + "\n" + - "struct GS_OUTPUT\n" + outLinkHLSL + "\n" + - "\n" - "static float2 pointSpriteCorners[] = \n" - "{\n" - " float2( 0.5f, -0.5f),\n" - " float2( 0.5f, 0.5f),\n" - " float2(-0.5f, -0.5f),\n" - " float2(-0.5f, 0.5f)\n" - "};\n" - "\n" - "static float2 pointSpriteTexcoords[] = \n" - "{\n" - " float2(1.0f, 1.0f),\n" - " float2(1.0f, 0.0f),\n" - " float2(0.0f, 1.0f),\n" - " float2(0.0f, 0.0f)\n" - "};\n" - "\n" - "static float minPointSize = " + Str(mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n" - "static float maxPointSize = " + Str(mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n" - "\n" - "[maxvertexcount(4)]\n" - "void main(point GS_INPUT input[1], inout TriangleStream outStream)\n" - "{\n" - " GS_OUTPUT output = (GS_OUTPUT)0;\n" - " output.gl_Position = input[0].gl_Position;\n" - " output.gl_PointSize = input[0].gl_PointSize;\n"; - - for (int r = 0; r < registers; r++) + std::stringstream shaderStream; + + const bool pointSprites = (primitiveType == PRIMITIVE_POINTS); + const bool usesPointCoord = preambleString.find("gl_PointCoord") != std::string::npos; + + const char *inputPT = nullptr; + const char *outputPT = nullptr; + int inputSize = 0; + int maxVertexOutput = 0; + + switch (primitiveType) { - geomHLSL += " output.v" + Str(r) + " = input[0].v" + Str(r) + ";\n"; + case PRIMITIVE_POINTS: + inputPT = "point"; + outputPT = "Triangle"; + inputSize = 1; + maxVertexOutput = 4; + break; + + case PRIMITIVE_LINES: + case PRIMITIVE_LINE_STRIP: + case PRIMITIVE_LINE_LOOP: + inputPT = "line"; + outputPT = "Line"; + inputSize = 2; + maxVertexOutput = 2; + break; + + case PRIMITIVE_TRIANGLES: + case PRIMITIVE_TRIANGLE_STRIP: + case PRIMITIVE_TRIANGLE_FAN: + inputPT = "triangle"; + outputPT = "Triangle"; + inputSize = 3; + maxVertexOutput = 3; + break; + + default: + UNREACHABLE(); + break; } - if (fragmentShader->mUsesFragCoord) + if (pointSprites) { - geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n"; + shaderStream << "#define ANGLE_POINT_SPRITE_SHADER\n" + "\n" + "uniform float4 dx_ViewCoords : register(c1);\n"; + + if (useViewScale) + { + shaderStream << "uniform float2 dx_ViewScale : register(c3);\n"; + } + + shaderStream << "\n" + "static float2 pointSpriteCorners[] = \n" + "{\n" + " float2( 0.5f, -0.5f),\n" + " float2( 0.5f, 0.5f),\n" + " float2(-0.5f, -0.5f),\n" + " float2(-0.5f, 0.5f)\n" + "};\n" + "\n" + "static float2 pointSpriteTexcoords[] = \n" + "{\n" + " float2(1.0f, 1.0f),\n" + " float2(1.0f, 0.0f),\n" + " float2(0.0f, 1.0f),\n" + " float2(0.0f, 0.0f)\n" + "};\n" + "\n" + "static float minPointSize = " + << static_cast(data.caps->minAliasedPointSize) + << ".0f;\n" + "static float maxPointSize = " + << static_cast(data.caps->maxAliasedPointSize) << ".0f;\n" + << "\n"; } - geomHLSL += " \n" - " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n" - " float4 dx_Position = input[0].dx_Position;\n" - " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * dx_Position.w;\n"; + shaderStream << preambleString << "\n" + << "[maxvertexcount(" << maxVertexOutput << ")]\n" + << "void main(" << inputPT << " GS_INPUT input[" << inputSize << "], "; - for (int corner = 0; corner < 4; corner++) + if (primitiveType == PRIMITIVE_TRIANGLE_STRIP) { - geomHLSL += " \n" - " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + Str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; + shaderStream << "uint primitiveID : SV_PrimitiveID, "; + } + + shaderStream << " inout " << outputPT << "Stream outStream)\n" + << "{\n" + << " GS_OUTPUT output = (GS_OUTPUT)0;\n"; - if (fragmentShader->mUsesPointCoord) + if (primitiveType == PRIMITIVE_TRIANGLE_STRIP) + { + shaderStream << " uint lastVertexIndex = (primitiveID % 2 == 0 ? 2 : 1);\n"; + } + else + { + shaderStream << " uint lastVertexIndex = " << (inputSize - 1) << ";\n"; + } + + for (int vertexIndex = 0; vertexIndex < inputSize; ++vertexIndex) + { + shaderStream << " copyVertex(output, input[" << vertexIndex + << "], input[lastVertexIndex]);\n"; + + if (!pointSprites) { - geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + Str(corner) + "];\n"; + ASSERT(inputSize == maxVertexOutput); + shaderStream << " outStream.Append(output);\n"; } + } + + if (pointSprites) + { + shaderStream << "\n" + " float4 dx_Position = input[0].dx_Position;\n" + " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, " + "maxPointSize);\n" + " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / " + "dx_ViewCoords.y) * dx_Position.w;\n"; + + for (int corner = 0; corner < 4; corner++) + { + if (useViewScale) + { + shaderStream << " \n" + " output.dx_Position = dx_Position + float4(1.0f, " + "-dx_ViewScale.y, 1.0f, 1.0f)" + " * float4(pointSpriteCorners[" + << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; + } + else + { + shaderStream << "\n" + " output.dx_Position = dx_Position + float4(pointSpriteCorners[" + << corner << "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; + } - geomHLSL += " outStream.Append(output);\n"; + if (usesPointCoord) + { + shaderStream << " output.gl_PointCoord = pointSpriteTexcoords[" << corner + << "];\n"; + } + + shaderStream << " outStream.Append(output);\n"; + } } - geomHLSL += " \n" - " outStream.RestartStrip();\n" - "}\n"; + shaderStream << " \n" + " outStream.RestartStrip();\n" + "}\n"; - return geomHLSL; + return shaderStream.str(); } // This method needs to match OutputHLSL::decorate @@ -1217,9 +1006,12 @@ std::string DynamicHLSL::decorateVariable(const std::string &name) return name; } -std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const +std::string DynamicHLSL::generateAttributeConversionHLSL( + gl::VertexFormatType vertexFormatType, + const sh::ShaderVariable &shaderAttrib) const { - std::string attribString = "input." + decorateVariable(shaderAttrib.name); + const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType); + std::string attribString = "input." + decorateVariable(shaderAttrib.name); // Matrix if (IsMatrixType(shaderAttrib.type)) @@ -1228,15 +1020,16 @@ std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &ver } GLenum shaderComponentType = VariableComponentType(shaderAttrib.type); - int shaderComponentCount = VariableComponentCount(shaderAttrib.type); + int shaderComponentCount = VariableComponentCount(shaderAttrib.type); // Perform integer to float conversion (if necessary) - bool requiresTypeConversion = (shaderComponentType == GL_FLOAT && vertexFormat.mType != GL_FLOAT); + bool requiresTypeConversion = + (shaderComponentType == GL_FLOAT && vertexFormat.type != GL_FLOAT); if (requiresTypeConversion) { // TODO: normalization for 32-bit integer formats - ASSERT(!vertexFormat.mNormalized && !vertexFormat.mPureInteger); + ASSERT(!vertexFormat.normalized && !vertexFormat.pureInteger); return "float" + Str(shaderComponentCount) + "(" + attribString + ")"; } @@ -1244,22 +1037,57 @@ std::string DynamicHLSL::generateAttributeConversionHLSL(const VertexFormat &ver return attribString; } -void DynamicHLSL::getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const +void DynamicHLSL::getPixelShaderOutputKey(const gl::Data &data, + const gl::Program::Data &programData, + const ProgramD3DMetadata &metadata, + std::vector *outPixelShaderKey) { - for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++) - { - const VertexFormat &vertexFormat = inputLayout[inputIndex]; + // Two cases when writing to gl_FragColor and using ESSL 1.0: + // - with a 3.0 context, the output color is copied to channel 0 + // - with a 2.0 context, the output color is broadcast to all channels + bool broadcast = metadata.usesBroadcast(data); + const unsigned int numRenderTargets = + (broadcast || metadata.usesMultipleFragmentOuts() ? data.caps->maxDrawBuffers : 1); - if (vertexFormat.mType == GL_NONE) + if (metadata.getMajorShaderVersion() < 300) + { + for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; + renderTargetIndex++) { - signature[inputIndex] = GL_NONE; + PixelShaderOutputVariable outputKeyVariable; + outputKeyVariable.type = GL_FLOAT_VEC4; + outputKeyVariable.name = "gl_Color" + Str(renderTargetIndex); + outputKeyVariable.source = + broadcast ? "gl_Color[0]" : "gl_Color[" + Str(renderTargetIndex) + "]"; + outputKeyVariable.outputIndex = renderTargetIndex; + + outPixelShaderKey->push_back(outputKeyVariable); } - else + } + else + { + const auto &shaderOutputVars = + metadata.getFragmentShader()->getData().getActiveOutputVariables(); + + for (auto outputPair : programData.getOutputVariables()) { - bool gpuConverted = ((mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_GPU) != 0); - signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE); + const VariableLocation &outputLocation = outputPair.second; + const sh::ShaderVariable &outputVariable = shaderOutputVars[outputLocation.index]; + const std::string &variableName = "out_" + outputLocation.name; + const std::string &elementString = + (outputLocation.element == GL_INVALID_INDEX ? "" : Str(outputLocation.element)); + + ASSERT(outputVariable.staticUse); + + PixelShaderOutputVariable outputKeyVariable; + outputKeyVariable.type = outputVariable.type; + outputKeyVariable.name = variableName + elementString; + outputKeyVariable.source = variableName + ArrayString(outputLocation.element); + outputKeyVariable.outputIndex = outputPair.first; + + outPixelShaderKey->push_back(outputKeyVariable); } } } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h index 26ae13b342..69d941c06a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h @@ -9,13 +9,15 @@ #ifndef LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ #define LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ -#include "common/angleutils.h" -#include "libANGLE/Constants.h" +#include +#include #include "angle_gl.h" - -#include -#include +#include "common/angleutils.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Program.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" namespace sh { @@ -27,19 +29,16 @@ namespace gl { class InfoLog; struct VariableLocation; -struct LinkedVarying; struct VertexAttribute; -struct VertexFormat; -struct PackedVarying; struct Data; } namespace rx { -class RendererD3D; +struct PackedVarying; +class ProgramD3DMetadata; class ShaderD3D; - -typedef const gl::PackedVarying *VaryingPacking[gl::IMPLEMENTATION_MAX_VARYING_VECTORS][4]; +class VaryingPacking; struct PixelShaderOutputVariable { @@ -54,46 +53,52 @@ class DynamicHLSL : angle::NonCopyable public: explicit DynamicHLSL(RendererD3D *const renderer); - int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, ShaderD3D *fragmentShader, - ShaderD3D *vertexShader, const std::vector& transformFeedbackVaryings); - std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const gl::VertexFormat inputLayout[], - const sh::Attribute shaderAttributes[]) const; - std::string generatePixelShaderForOutputSignature(const std::string &sourceShader, const std::vector &outputVariables, - bool usesFragDepth, const std::vector &outputLayout) const; - bool generateShaderLinkHLSL(const gl::Data &data, gl::InfoLog &infoLog, int registers, - const VaryingPacking packing, - std::string &pixelHLSL, std::string &vertexHLSL, - ShaderD3D *fragmentShader, ShaderD3D *vertexShader, - const std::vector &transformFeedbackVaryings, - std::vector *linkedVaryings, - std::map *programOutputVars, - std::vector *outPixelShaderKey, - bool *outUsesFragDepth) const; - - std::string generateGeometryShaderHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const; - void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; + std::string generateVertexShaderForInputLayout( + const std::string &sourceShader, + const gl::InputLayout &inputLayout, + const std::vector &shaderAttributes) const; + std::string generatePixelShaderForOutputSignature( + const std::string &sourceShader, + const std::vector &outputVariables, + bool usesFragDepth, + const std::vector &outputLayout) const; + bool generateShaderLinkHLSL(const gl::Data &data, + const gl::Program::Data &programData, + const ProgramD3DMetadata &programMetadata, + const VaryingPacking &varyingPacking, + std::string *pixelHLSL, + std::string *vertexHLSL) const; + + std::string generateGeometryShaderPreamble(const VaryingPacking &varyingPacking) const; + + std::string generateGeometryShaderHLSL(gl::PrimitiveType primitiveType, + const gl::Data &data, + const gl::Program::Data &programData, + const bool useViewScale, + const std::string &preambleString) const; + + void getPixelShaderOutputKey(const gl::Data &data, + const gl::Program::Data &programData, + const ProgramD3DMetadata &metadata, + std::vector *outPixelShaderKey); private: RendererD3D *const mRenderer; - struct SemanticInfo; - - std::string getVaryingSemantic(bool pointSize) const; - SemanticInfo getSemanticInfo(int startRegisters, bool position, bool fragCoord, bool pointCoord, - bool pointSize, bool pixelShader) const; - std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const; - std::string generateVaryingHLSL(const ShaderD3D *shader) const; - void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector *linkedVaryings) const; - void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector *linkedVaryings) const; - void defineOutputVariables(ShaderD3D *fragmentShader, std::map *programOutputVars) const; - std::string generatePointSpriteHLSL(int registers, ShaderD3D *fragmentShader, ShaderD3D *vertexShader) const; + void generateVaryingLinkHLSL(ShaderType shaderType, + const VaryingPacking &varyingPacking, + std::stringstream &linkStream) const; + void generateVaryingHLSL(const VaryingPacking &varyingPacking, + std::stringstream &hlslStream) const; // Prepend an underscore static std::string decorateVariable(const std::string &name); - std::string generateAttributeConversionHLSL(const gl::VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const; + std::string generateAttributeConversionHLSL(gl::VertexFormatType vertexFormatType, + const sh::ShaderVariable &shaderAttrib) const; }; +std::string GetVaryingSemantic(int majorShaderModel, bool programUsesPointSize); } -#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ +#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp new file mode 100644 index 0000000000..ca4b16987f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.cpp @@ -0,0 +1,132 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// EGLImageD3D.cpp: Implements the rx::EGLImageD3D class, the D3D implementation of EGL images + +#include "libANGLE/renderer/d3d/EGLImageD3D.h" + +#include "common/debug.h" +#include "common/utilities.h" +#include "libANGLE/AttributeMap.h" +#include "libANGLE/Texture.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/TextureStorage.h" + +#include + +namespace rx +{ +static gl::ImageIndex GetImageIndex(GLenum target, size_t mip, size_t layer) +{ + if (target == GL_TEXTURE_3D) + { + return gl::ImageIndex::Make3D(static_cast(mip), static_cast(layer)); + } + else + { + ASSERT(layer == 0); + return gl::ImageIndex::MakeGeneric(target, static_cast(mip)); + } +} + +EGLImageD3D::EGLImageD3D(RendererD3D *renderer, + EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs) + : mRenderer(renderer), mBuffer(buffer), mAttachmentBuffer(nullptr), mRenderTarget(nullptr) +{ + ASSERT(renderer != nullptr); + ASSERT(buffer != nullptr); + + if (egl::IsTextureTarget(target)) + { + mAttachmentBuffer = GetImplAs(GetAs(buffer)); + mAttachmentTarget = gl::FramebufferAttachment::Target( + GL_NONE, GetImageIndex(egl_gl::EGLImageTargetToGLTextureTarget(target), + attribs.get(EGL_GL_TEXTURE_LEVEL_KHR, 0), + attribs.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0))); + } + else if (egl::IsRenderbufferTarget(target)) + { + mAttachmentBuffer = GetImplAs(GetAs(buffer)); + mAttachmentTarget = + gl::FramebufferAttachment::Target(GL_NONE, gl::ImageIndex::MakeInvalid()); + } + else + { + UNREACHABLE(); + } +} + +EGLImageD3D::~EGLImageD3D() +{ + SafeDelete(mRenderTarget); +} + +egl::Error EGLImageD3D::initialize() +{ + return egl::Error(EGL_SUCCESS); +} + +gl::Error EGLImageD3D::orphan(egl::ImageSibling *sibling) +{ + if (sibling == mBuffer) + { + gl::Error error = copyToLocalRendertarget(); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error EGLImageD3D::getRenderTarget(RenderTargetD3D **outRT) const +{ + if (mAttachmentBuffer) + { + FramebufferAttachmentRenderTarget *rt = nullptr; + gl::Error error = mAttachmentBuffer->getAttachmentRenderTarget(mAttachmentTarget, &rt); + if (error.isError()) + { + return error; + } + + *outRT = static_cast(rt); + return gl::Error(GL_NO_ERROR); + } + else + { + ASSERT(mRenderTarget); + *outRT = mRenderTarget; + return gl::Error(GL_NO_ERROR); + } +} + +gl::Error EGLImageD3D::copyToLocalRendertarget() +{ + ASSERT(mBuffer != nullptr); + ASSERT(mAttachmentBuffer != nullptr); + ASSERT(mRenderTarget == nullptr); + + RenderTargetD3D *curRenderTarget = nullptr; + gl::Error error = getRenderTarget(&curRenderTarget); + if (error.isError()) + { + return error; + } + + // Clear the source image buffers + mBuffer = nullptr; + mAttachmentBuffer = nullptr; + + return mRenderer->createRenderTargetCopy(curRenderTarget, &mRenderTarget); +} +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h new file mode 100644 index 0000000000..6ec33e08f2 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/EGLImageD3D.h @@ -0,0 +1,56 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// EGLImageD3D.h: Defines the rx::EGLImageD3D class, the D3D implementation of EGL images + +#ifndef LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_ +#define LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_ + +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/ImageImpl.h" + +namespace egl +{ +class AttributeMap; +} + +namespace rx +{ +class TextureD3D; +class RenderbufferD3D; +class RendererD3D; +class RenderTargetD3D; + +class EGLImageD3D final : public ImageImpl +{ + public: + EGLImageD3D(RendererD3D *renderer, + EGLenum target, + egl::ImageSibling *buffer, + const egl::AttributeMap &attribs); + ~EGLImageD3D() override; + + egl::Error initialize() override; + + gl::Error orphan(egl::ImageSibling *sibling) override; + + gl::Error getRenderTarget(RenderTargetD3D **outRT) const; + + private: + gl::Error copyToLocalRendertarget(); + + RendererD3D *mRenderer; + + egl::ImageSibling *mBuffer; + + gl::FramebufferAttachment::Target mAttachmentTarget; + FramebufferAttachmentObjectImpl *mAttachmentBuffer; + + RenderTargetD3D *mRenderTarget; +}; +} + +#endif // LIBANGLE_RENDERER_D3D_EGLIMAGED3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp index 1a4734b269..82967aced0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp @@ -8,6 +8,7 @@ #include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "common/BitSetIterator.h" #include "libANGLE/formatutils.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" @@ -53,7 +54,7 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer(); if (mask & GL_COLOR_BUFFER_BIT) { - if (framebufferObject->hasEnabledColorAttachment()) + if (framebufferObject->hasEnabledDrawBuffer()) { for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { @@ -85,67 +86,28 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) } FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer) - : FramebufferImpl(data), - mRenderer(renderer), - mColorAttachmentsForRender(mData.mColorAttachments.size(), nullptr), - mInvalidateColorAttachmentCache(true) + : FramebufferImpl(data), mRenderer(renderer) { - ASSERT(mRenderer != nullptr); } FramebufferD3D::~FramebufferD3D() { } -void FramebufferD3D::setColorAttachment(size_t, const gl::FramebufferAttachment *) -{ - mInvalidateColorAttachmentCache = true; -} - -void FramebufferD3D::setDepthAttachment(const gl::FramebufferAttachment *) -{ -} - -void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *) -{ -} - -void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *) -{ -} - -void FramebufferD3D::setDrawBuffers(size_t, const GLenum *) -{ - mInvalidateColorAttachmentCache = true; -} - -void FramebufferD3D::setReadBuffer(GLenum) -{ -} - -gl::Error FramebufferD3D::invalidate(size_t, const GLenum *) -{ - // No-op in D3D - return gl::Error(GL_NO_ERROR); -} - -gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) -{ - // No-op in D3D - return gl::Error(GL_NO_ERROR); -} - gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask) { const gl::State &state = *data.state; ClearParameters clearParams = GetClearParameters(state, mask); - return clear(state, clearParams); + return clear(data, clearParams); } -gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) +gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) { // glClearBufferfv can be called to clear the color buffer or depth buffer - ClearParameters clearParams = GetClearParameters(state, 0); + ClearParameters clearParams = GetClearParameters(*data.state, 0); if (buffer == GL_COLOR) { @@ -163,13 +125,16 @@ gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, G clearParams.depthClearValue = values[0]; } - return clear(state, clearParams); + return clear(data, clearParams); } -gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) +gl::Error FramebufferD3D::clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) { // glClearBufferuiv can only be called to clear a color buffer - ClearParameters clearParams = GetClearParameters(state, 0); + ClearParameters clearParams = GetClearParameters(*data.state, 0); for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { clearParams.clearColor[i] = (drawbuffer == static_cast(i)); @@ -177,13 +142,16 @@ gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_UNSIGNED_INT; - return clear(state, clearParams); + return clear(data, clearParams); } -gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) +gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLint *values) { // glClearBufferiv can be called to clear the color buffer or stencil buffer - ClearParameters clearParams = GetClearParameters(state, 0); + ClearParameters clearParams = GetClearParameters(*data.state, 0); if (buffer == GL_COLOR) { @@ -201,19 +169,23 @@ gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, G clearParams.stencilClearValue = values[1]; } - return clear(state, clearParams); + return clear(data, clearParams); } -gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +gl::Error FramebufferD3D::clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) { // glClearBufferfi can only be called to clear a depth stencil buffer - ClearParameters clearParams = GetClearParameters(state, 0); + ClearParameters clearParams = GetClearParameters(*data.state, 0); clearParams.clearDepth = true; clearParams.depthClearValue = depth; clearParams.clearStencil = true; clearParams.stencilClearValue = stencil; - return clear(state, clearParams); + return clear(data, clearParams); } GLenum FramebufferD3D::getImplementationColorReadFormat() const @@ -226,7 +198,7 @@ GLenum FramebufferD3D::getImplementationColorReadFormat() const } RenderTargetD3D *attachmentRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget); + gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget); if (error.isError()) { return GL_NONE; @@ -248,7 +220,7 @@ GLenum FramebufferD3D::getImplementationColorReadType() const } RenderTargetD3D *attachmentRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget); + gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget); if (error.isError()) { return GL_NONE; @@ -264,17 +236,15 @@ gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle { const gl::PixelPackState &packState = state.getPackState(); - if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels"); - } - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0); + GLuint outputPitch = + sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength); + GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels( + outputPitch, 0, 0, packState.skipRows, packState.skipPixels); - return readPixels(area, format, type, outputPitch, packState, reinterpret_cast(pixels)); + return readPixelsImpl(area, format, type, outputPitch, packState, + reinterpret_cast(pixels) + outputSkipBytes); } gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, @@ -291,7 +261,7 @@ gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sour bool blitStencil = false; if ((mask & GL_STENCIL_BUFFER_BIT) && sourceFramebuffer->getStencilbuffer() != nullptr && - mData.mStencilAttachment != nullptr) + mData.getStencilAttachment() != nullptr) { blitStencil = true; } @@ -299,7 +269,7 @@ gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sour bool blitDepth = false; if ((mask & GL_DEPTH_BUFFER_BIT) && sourceFramebuffer->getDepthbuffer() != nullptr && - mData.mDepthAttachment != nullptr) + mData.getDepthAttachment() != nullptr) { blitDepth = true; } @@ -318,146 +288,99 @@ gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sour return gl::Error(GL_NO_ERROR); } -GLenum FramebufferD3D::checkStatus() const +bool FramebufferD3D::checkStatus() const { + // if we have both a depth and stencil buffer, they must refer to the same object + // since we only support packed_depth_stencil and not separate depth and stencil + if (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr && + mData.getDepthStencilAttachment() == nullptr) + { + return false; + } + // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness - for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++) + const auto &colorAttachments = mData.getColorAttachments(); + for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) { - const gl::FramebufferAttachment *attachment = mData.mColorAttachments[colorAttachment]; - if (attachment != nullptr) + const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachment]; + if (attachment.isAttached()) { for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++) { - const gl::FramebufferAttachment *prevAttachment = mData.mColorAttachments[prevColorAttachment]; - if (prevAttachment != nullptr && - (attachment->id() == prevAttachment->id() && - attachment->type() == prevAttachment->type())) + const gl::FramebufferAttachment &prevAttachment = colorAttachments[prevColorAttachment]; + if (prevAttachment.isAttached() && + (attachment.id() == prevAttachment.id() && + attachment.type() == prevAttachment.type())) { - return GL_FRAMEBUFFER_UNSUPPORTED; + return false; } } } } - return GL_FRAMEBUFFER_COMPLETE; + // D3D requires all render targets to have the same dimensions. + if (!mData.attachmentsHaveSameDimensions()) + { + return false; + } + + return true; } -const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const +void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) { - if (!workarounds.mrtPerfWorkaround) - { - return mData.mColorAttachments; - } + bool invalidateColorAttachmentCache = false; - if (!mInvalidateColorAttachmentCache) + if (!mColorAttachmentsForRender.valid()) { - return mColorAttachmentsForRender; + invalidateColorAttachmentCache = true; } - // Does not actually free memory - mColorAttachmentsForRender.clear(); - - for (size_t attachmentIndex = 0; attachmentIndex < mData.mColorAttachments.size(); ++attachmentIndex) + for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) { - GLenum drawBufferState = mData.mDrawBufferStates[attachmentIndex]; - gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[attachmentIndex]; - - if (colorAttachment != nullptr && drawBufferState != GL_NONE) + if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 && + dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) || + dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS) { - ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex)); - mColorAttachmentsForRender.push_back(colorAttachment); + invalidateColorAttachmentCache = true; } } - mInvalidateColorAttachmentCache = false; - return mColorAttachmentsForRender; -} - -gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT) -{ - if (attachment->type() == GL_TEXTURE) - { - gl::Texture *texture = attachment->getTexture(); - ASSERT(texture); - TextureD3D *textureD3D = GetImplAs(texture); - const gl::ImageIndex *index = attachment->getTextureImageIndex(); - ASSERT(index); - return textureD3D->getRenderTarget(*index, outRT); - } - else if (attachment->type() == GL_RENDERBUFFER) + if (!invalidateColorAttachmentCache) { - gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); - ASSERT(renderbuffer); - RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); - *outRT = renderbufferD3D->getRenderTarget(); - return gl::Error(GL_NO_ERROR); + return; } - else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) - { - const gl::DefaultAttachment *defaultAttachment = static_cast(attachment); - const egl::Surface *surface = defaultAttachment->getSurface(); - ASSERT(surface); - const SurfaceD3D *surfaceD3D = GetImplAs(surface); - ASSERT(surfaceD3D); - if (defaultAttachment->getBinding() == GL_BACK) - { - *outRT = surfaceD3D->getSwapChain()->getColorRenderTarget(); - } - else - { - *outRT = surfaceD3D->getSwapChain()->getDepthStencilRenderTarget(); - } - return gl::Error(GL_NO_ERROR); - } - else - { - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); - } -} + // Does not actually free memory + gl::AttachmentList colorAttachmentsForRender; -// Note: RenderTarget serials should ideally be in the RenderTargets themselves. -unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment) -{ - if (attachment->type() == GL_TEXTURE) - { - gl::Texture *texture = attachment->getTexture(); - ASSERT(texture); - TextureD3D *textureD3D = GetImplAs(texture); - const gl::ImageIndex *index = attachment->getTextureImageIndex(); - ASSERT(index); - return textureD3D->getRenderTargetSerial(*index); - } - else if (attachment->type() == GL_RENDERBUFFER) - { - gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); - ASSERT(renderbuffer); - RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation()); - return renderbufferD3D->getRenderTargetSerial(); - } - else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) + const auto &colorAttachments = mData.getColorAttachments(); + const auto &drawBufferStates = mData.getDrawBufferStates(); + const auto &workarounds = mRenderer->getWorkarounds(); + + for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex) { - const gl::DefaultAttachment *defaultAttachment = static_cast(attachment); - const egl::Surface *surface = defaultAttachment->getSurface(); - ASSERT(surface); - const SurfaceD3D *surfaceD3D = GetImplAs(surface); - ASSERT(surfaceD3D); + GLenum drawBufferState = drawBufferStates[attachmentIndex]; + const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex]; - if (defaultAttachment->getBinding() == GL_BACK) + if (colorAttachment.isAttached() && drawBufferState != GL_NONE) { - return surfaceD3D->getSwapChain()->getColorRenderTarget()->getSerial(); + ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex)); + colorAttachmentsForRender.push_back(&colorAttachment); } - else + else if (!workarounds.mrtPerfWorkaround) { - return surfaceD3D->getSwapChain()->getDepthStencilRenderTarget()->getSerial(); + colorAttachmentsForRender.push_back(nullptr); } } - else - { - UNREACHABLE(); - return 0; - } + + mColorAttachmentsForRender = std::move(colorAttachmentsForRender); } +const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const +{ + ASSERT(mColorAttachmentsForRender.valid()); + return mColorAttachmentsForRender.value(); } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h index d5d2dae8bd..eb839c4364 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h @@ -12,6 +12,7 @@ #include #include +#include "common/Optional.h" #include "libANGLE/angletypes.h" #include "libANGLE/renderer/FramebufferImpl.h" @@ -19,12 +20,16 @@ namespace gl { class FramebufferAttachment; struct PixelPackState; + +typedef std::vector AttachmentList; + } namespace rx { -class RenderTargetD3D; class RendererD3D; +class RenderTargetD3D; +struct WorkaroundsD3D; struct ClearParameters { @@ -55,22 +60,24 @@ class FramebufferD3D : public FramebufferImpl FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer); virtual ~FramebufferD3D(); - void setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment) override; - void setDepthAttachment(const gl::FramebufferAttachment *attachment) override; - void setStencilAttachment(const gl::FramebufferAttachment *attachment) override; - void setDepthStencilAttachment(const gl::FramebufferAttachment *attachment) override; - - void setDrawBuffers(size_t count, const GLenum *buffers) override; - void setReadBuffer(GLenum buffer) override; - - gl::Error invalidate(size_t count, const GLenum *attachments) override; - gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; - gl::Error clear(const gl::Data &data, GLbitfield mask) override; - gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override; - gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override; - gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override; - gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override; + gl::Error clearBufferfv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLfloat *values) override; + gl::Error clearBufferuiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLuint *values) override; + gl::Error clearBufferiv(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + const GLint *values) override; + gl::Error clearBufferfi(const gl::Data &data, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) override; GLenum getImplementationColorReadFormat() const override; GLenum getImplementationColorReadType() const override; @@ -79,32 +86,31 @@ class FramebufferD3D : public FramebufferImpl gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override; - GLenum checkStatus() const override; + bool checkStatus() const override; - const gl::AttachmentList &getColorAttachmentsForRender(const Workarounds &workarounds) const; + void syncState(const gl::Framebuffer::DirtyBits &dirtyBits) override; - protected: - // Cache variable - mutable gl::AttachmentList mColorAttachmentsForRender; - mutable bool mInvalidateColorAttachmentCache; + const gl::AttachmentList &getColorAttachmentsForRender() const; private: - RendererD3D *const mRenderer; - - virtual gl::Error clear(const gl::State &state, const ClearParameters &clearParams) = 0; + virtual gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) = 0; - virtual gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, - const gl::PixelPackState &pack, uint8_t *pixels) const = 0; + virtual gl::Error readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const = 0; virtual gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, const gl::Framebuffer *sourceFramebuffer) = 0; virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0; -}; -gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT); -unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment); + RendererD3D *mRenderer; + Optional mColorAttachmentsForRender; +}; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp index 8961a36ec5..df0257e370 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp @@ -5,21 +5,20 @@ // #include "libANGLE/renderer/d3d/HLSLCompiler.h" -#include "libANGLE/Program.h" -#include "libANGLE/features.h" #include "common/utilities.h" - +#include "libANGLE/Program.h" +#include "libANGLE/features.h" +#include "libANGLE/histogram_macros.h" #include "third_party/trace_event/trace_event.h" #ifndef QT_D3DCOMPILER_DLL #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL #endif -// Definitions local to the translation unit +#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED namespace { - #ifdef CREATE_COMPILER_FLAG_INFO #undef CREATE_COMPILER_FLAG_INFO #endif @@ -89,19 +88,8 @@ bool IsCompilerFlagSet(UINT mask, UINT flag) return isFlagSet; } } - -const char *GetCompilerFlagName(UINT mask, size_t flagIx) -{ - const CompilerFlagInfo &flagInfo = CompilerFlagInfos[flagIx]; - if (IsCompilerFlagSet(mask, flagInfo.mFlag)) - { - return flagInfo.mName; - } - - return nullptr; -} - -} +} // anonymous namespace +#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED namespace rx { @@ -119,9 +107,10 @@ CompileConfig::CompileConfig(UINT flags, const std::string &name) } HLSLCompiler::HLSLCompiler() - : mD3DCompilerModule(NULL), - mD3DCompileFunc(NULL), - mD3DDisassembleFunc(NULL) + : mInitialized(false), + mD3DCompilerModule(nullptr), + mD3DCompileFunc(nullptr), + mD3DDisassembleFunc(nullptr) { } @@ -130,9 +119,14 @@ HLSLCompiler::~HLSLCompiler() release(); } -bool HLSLCompiler::initialize() +gl::Error HLSLCompiler::initialize() { - TRACE_EVENT0("gpu", "initializeCompiler"); + if (mInitialized) + { + return gl::Error(GL_NO_ERROR); + } + + TRACE_EVENT0("gpu.angle", "HLSLCompiler::initialize"); #if !defined(ANGLE_ENABLE_WINDOWS_STORE) #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. @@ -168,6 +162,7 @@ bool HLSLCompiler::initialize() break; } + if (!mD3DCompilerModule) { // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. @@ -176,8 +171,7 @@ bool HLSLCompiler::initialize() if (!mD3DCompilerModule) { - ERR("No D3D compiler module found - aborting!\n"); - return false; + return gl::Error(GL_INVALID_OPERATION, "No D3D compiler module found - aborting!\n"); } mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DCompile")); @@ -189,29 +183,42 @@ bool HLSLCompiler::initialize() #else // D3D Shader compiler is linked already into this module, so the export // can be directly assigned. - mD3DCompilerModule = NULL; + mD3DCompilerModule = nullptr; mD3DCompileFunc = reinterpret_cast(D3DCompile); mD3DDisassembleFunc = reinterpret_cast(D3DDisassemble); #endif - return mD3DCompileFunc != NULL; + if (mD3DCompileFunc == nullptr) + { + return gl::Error(GL_INVALID_OPERATION, "Error finding D3DCompile entry point"); + } + + mInitialized = true; + return gl::Error(GL_NO_ERROR); } void HLSLCompiler::release() { - if (mD3DCompilerModule) + if (mInitialized) { FreeLibrary(mD3DCompilerModule); - mD3DCompilerModule = NULL; - mD3DCompileFunc = NULL; - mD3DDisassembleFunc = NULL; + mD3DCompilerModule = nullptr; + mD3DCompileFunc = nullptr; + mD3DDisassembleFunc = nullptr; + mInitialized = false; } } gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, const std::vector &configs, const D3D_SHADER_MACRO *overrideMacros, - ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const + ID3DBlob **outCompiledBlob, std::string *outDebugInfo) { + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + #if !defined(ANGLE_ENABLE_WINDOWS_STORE) ASSERT(mD3DCompilerModule); #endif @@ -226,15 +233,21 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string } #endif - const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : NULL; + const D3D_SHADER_MACRO *macros = overrideMacros ? overrideMacros : nullptr; for (size_t i = 0; i < configs.size(); ++i) { - ID3DBlob *errorMessage = NULL; - ID3DBlob *binary = NULL; + ID3DBlob *errorMessage = nullptr; + ID3DBlob *binary = nullptr; + HRESULT result = S_OK; - HRESULT result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, NULL, "main", profile.c_str(), - configs[i].flags, 0, &binary, &errorMessage); + { + TRACE_EVENT0("gpu.angle", "D3DCompile"); + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3DCompileMS"); + result = mD3DCompileFunc(hlsl.c_str(), hlsl.length(), gl::g_fakepath, macros, nullptr, + "main", profile.c_str(), configs[i].flags, 0, &binary, + &errorMessage); + } if (errorMessage) { @@ -245,13 +258,14 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string TRACE("\n%s", hlsl.c_str()); TRACE("\n%s", message.c_str()); - if (message.find("error X3531:") != std::string::npos || // "can't unroll loops marked with loop attribute" - message.find("error X4014:") != std::string::npos) // "cannot have gradient operations inside loops with divergent flow control", - // even though it is counter-intuitive to disable unrolling for this error, - // some very long shaders have trouble deciding which loops to unroll and - // turning off forced unrolls allows them to compile properly. + if ((message.find("error X3531:") != std::string::npos || // "can't unroll loops marked with loop attribute" + message.find("error X4014:") != std::string::npos) && // "cannot have gradient operations inside loops with divergent flow control", + // even though it is counter-intuitive to disable unrolling for this error, + // some very long shaders have trouble deciding which loops to unroll and + // turning off forced unrolls allows them to compile properly. + macros != nullptr) { - macros = NULL; // Disable [loop] and [flatten] + macros = nullptr; // Disable [loop] and [flatten] // Retry without changing compiler flags i--; @@ -263,16 +277,16 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string { *outCompiledBlob = binary; -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED (*outDebugInfo) += "// COMPILER INPUT HLSL BEGIN\n\n" + hlsl + "\n// COMPILER INPUT HLSL END\n"; + +#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED (*outDebugInfo) += "\n\n// ASSEMBLY BEGIN\n\n"; (*outDebugInfo) += "// Compiler configuration: " + configs[i].name + "\n// Flags:\n"; for (size_t fIx = 0; fIx < ArraySize(CompilerFlagInfos); ++fIx) { - const char *flagName = GetCompilerFlagName(configs[i].flags, fIx); - if (flagName != nullptr) + if (IsCompilerFlagSet(configs[i].flags, CompilerFlagInfos[fIx].mFlag)) { - (*outDebugInfo) += std::string("// ") + flagName + "\n"; + (*outDebugInfo) += std::string("// ") + CompilerFlagInfos[fIx].mName + "\n"; } } @@ -289,52 +303,65 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string } } - (*outDebugInfo) += "\n" + disassembleBinary(binary) + "\n// ASSEMBLY END\n"; -#endif - + std::string disassembly; + error = disassembleBinary(binary, &disassembly); + if (error.isError()) + { + return error; + } + (*outDebugInfo) += "\n" + disassembly + "\n// ASSEMBLY END\n"; +#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED return gl::Error(GL_NO_ERROR); } - else + + if (result == E_OUTOFMEMORY) { - if (result == E_OUTOFMEMORY) - { - *outCompiledBlob = NULL; - return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result); - } + *outCompiledBlob = nullptr; + return gl::Error(GL_OUT_OF_MEMORY, "HLSL compiler had an unexpected failure, result: 0x%X.", result); + } - infoLog.append("Warning: D3D shader compilation failed with %s flags.", configs[i].name.c_str()); + infoLog << "Warning: D3D shader compilation failed with " << configs[i].name << " flags. (" + << profile << ")"; - if (i + 1 < configs.size()) - { - infoLog.append(" Retrying with %s.\n", configs[i + 1].name.c_str()); - } + if (i + 1 < configs.size()) + { + infoLog << " Retrying with " << configs[i + 1].name; } } // None of the configurations succeeded in compiling this shader but the compiler is still intact - *outCompiledBlob = NULL; + *outCompiledBlob = nullptr; return gl::Error(GL_NO_ERROR); } -std::string HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary) const +gl::Error HLSLCompiler::disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut) { + gl::Error error = initialize(); + if (error.isError()) + { + return error; + } + // Retrieve disassembly UINT flags = D3D_DISASM_ENABLE_DEFAULT_VALUE_PRINTS | D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING; - ID3DBlob *disassembly = NULL; + ID3DBlob *disassembly = nullptr; pD3DDisassemble disassembleFunc = reinterpret_cast(mD3DDisassembleFunc); LPCVOID buffer = shaderBinary->GetBufferPointer(); SIZE_T bufSize = shaderBinary->GetBufferSize(); HRESULT result = disassembleFunc(buffer, bufSize, flags, "", &disassembly); - std::string asmSrc; if (SUCCEEDED(result)) { - asmSrc = reinterpret_cast(disassembly->GetBufferPointer()); + *disassemblyOut = std::string(reinterpret_cast(disassembly->GetBufferPointer())); + } + else + { + *disassemblyOut = ""; } SafeRelease(disassembly); - return asmSrc; + return gl::Error(GL_NO_ERROR); } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h index a824952553..3c0d2adcac 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h @@ -32,18 +32,20 @@ class HLSLCompiler : angle::NonCopyable HLSLCompiler(); ~HLSLCompiler(); - bool initialize(); void release(); // Attempt to compile a HLSL shader using the supplied configurations, may output a NULL compiled blob // even if no GL errors are returned. gl::Error compileToBinary(gl::InfoLog &infoLog, const std::string &hlsl, const std::string &profile, const std::vector &configs, const D3D_SHADER_MACRO *overrideMacros, - ID3DBlob **outCompiledBlob, std::string *outDebugInfo) const; + ID3DBlob **outCompiledBlob, std::string *outDebugInfo); - std::string disassembleBinary(ID3DBlob* shaderBinary) const; + gl::Error disassembleBinary(ID3DBlob *shaderBinary, std::string *disassemblyOut); private: + gl::Error initialize(); + + bool mInitialized; HMODULE mD3DCompilerModule; pD3DCompile mD3DCompileFunc; pD3DDisassemble mD3DDisassembleFunc; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp index 4e6f61150a..ead5db6453 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp @@ -13,6 +13,7 @@ #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" namespace rx { @@ -22,26 +23,10 @@ ImageD3D::ImageD3D() mHeight(0), mDepth(0), mInternalFormat(GL_NONE), - mTarget(GL_NONE), mRenderable(false), + mTarget(GL_NONE), mDirty(false) { } -gl::Error ImageD3D::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) -{ - gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); - ASSERT(colorbuffer); - - RenderTargetD3D *renderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) - { - return error; - } - - ASSERT(renderTarget); - return copy(destOffset, sourceArea, renderTarget); -} - -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h index 0fe88a8f59..2afe1cfabf 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h @@ -60,10 +60,11 @@ class ImageD3D : angle::NonCopyable virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); }; virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) = 0; - virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, - const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0; - - gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source); + virtual gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, + TextureStorage *source) = 0; + virtual gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) = 0; protected: GLsizei mWidth; @@ -74,9 +75,6 @@ class ImageD3D : angle::NonCopyable GLenum mTarget; bool mDirty; - - private: - virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) = 0; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h index 36262f1d09..0b7b28ddf0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h @@ -12,7 +12,6 @@ #include "common/angleutils.h" #include "libANGLE/Error.h" -#include "libANGLE/renderer/IndexRangeCache.h" namespace rx { diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp index 7dad269435..f1ba3d3db0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp @@ -8,6 +8,8 @@ // runs the Buffer translation process for index buffers. #include "libANGLE/renderer/d3d/IndexDataManager.h" + +#include "common/utilities.h" #include "libANGLE/renderer/d3d/BufferD3D.h" #include "libANGLE/renderer/d3d/IndexBuffer.h" #include "libANGLE/Buffer.h" @@ -16,45 +18,111 @@ namespace rx { -static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output) +namespace { - if (sourceType == GL_UNSIGNED_BYTE) - { - ASSERT(destinationType == GL_UNSIGNED_SHORT); - const GLubyte *in = static_cast(input); - GLushort *out = static_cast(output); +template +void ConvertIndexArray(const void *input, + GLenum sourceType, + void *output, + GLenum destinationType, + GLsizei count, + bool usePrimitiveRestartFixedIndex) +{ + const InputT *in = static_cast(input); + DestT *out = static_cast(output); + + if (usePrimitiveRestartFixedIndex) + { + InputT srcRestartIndex = static_cast(gl::GetPrimitiveRestartIndex(sourceType)); + DestT destRestartIndex = static_cast(gl::GetPrimitiveRestartIndex(destinationType)); for (GLsizei i = 0; i < count; i++) { - out[i] = in[i]; + out[i] = (in[i] == srcRestartIndex ? destRestartIndex : static_cast(in[i])); } } - else if (sourceType == GL_UNSIGNED_INT) - { - ASSERT(destinationType == GL_UNSIGNED_INT); - memcpy(output, input, count * sizeof(GLuint)); - } - else if (sourceType == GL_UNSIGNED_SHORT) + else { - if (destinationType == GL_UNSIGNED_SHORT) + for (GLsizei i = 0; i < count; i++) { - memcpy(output, input, count * sizeof(GLushort)); + out[i] = static_cast(in[i]); } - else if (destinationType == GL_UNSIGNED_INT) - { - const GLushort *in = static_cast(input); - GLuint *out = static_cast(output); + } +} - for (GLsizei i = 0; i < count; i++) - { - out[i] = in[i]; - } - } - else UNREACHABLE(); +void ConvertIndices(GLenum sourceType, + GLenum destinationType, + const void *input, + GLsizei count, + void *output, + bool usePrimitiveRestartFixedIndex) +{ + if (sourceType == destinationType) + { + const gl::Type &typeInfo = gl::GetTypeInfo(destinationType); + memcpy(output, input, count * typeInfo.bytes); + return; + } + + if (sourceType == GL_UNSIGNED_BYTE) + { + ASSERT(destinationType == GL_UNSIGNED_SHORT); + ConvertIndexArray(input, sourceType, output, destinationType, count, + usePrimitiveRestartFixedIndex); + } + else if (sourceType == GL_UNSIGNED_SHORT) + { + ASSERT(destinationType == GL_UNSIGNED_INT); + ConvertIndexArray(input, sourceType, output, destinationType, count, + usePrimitiveRestartFixedIndex); } else UNREACHABLE(); } +gl::Error StreamInIndexBuffer(IndexBufferInterface *buffer, + const GLvoid *data, + unsigned int count, + GLenum srcType, + GLenum dstType, + bool usePrimitiveRestartFixedIndex, + unsigned int *offset) +{ + const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); + + if (count > (std::numeric_limits::max() >> dstTypeInfo.bytesShift)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Reserving %u indices of %u bytes each exceeds the maximum buffer size.", + count, dstTypeInfo.bytes); + } + + unsigned int bufferSizeRequired = count << dstTypeInfo.bytesShift; + gl::Error error = buffer->reserveBufferSpace(bufferSizeRequired, dstType); + if (error.isError()) + { + return error; + } + + void *output = nullptr; + error = buffer->mapBuffer(bufferSizeRequired, &output, offset); + if (error.isError()) + { + return error; + } + + ConvertIndices(srcType, dstType, data, count, output, usePrimitiveRestartFixedIndex); + + error = buffer->unmapBuffer(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +} // anonymous namespace + IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass) : mFactory(factory), mRendererClass(rendererClass), @@ -69,163 +137,180 @@ IndexDataManager::~IndexDataManager() SafeDelete(mStreamingBufferInt); } -gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) +// This function translates a GL-style indices into DX-style indices, with their description +// returned in translated. +// GL can specify vertex data in immediate mode (pointer to CPU array of indices), which is not +// possible in DX and requires streaming (Case 1). If the GL indices are specified with a buffer +// (Case 2), in a format supported by DX (subcase a) then all is good. +// When we have a buffer with an unsupported format (subcase b) then we need to do some translation: +// we will start by falling back to streaming, and after a while will start using a static translated +// copy of the index buffer. +gl::Error IndexDataManager::prepareIndexData(GLenum srcType, + GLsizei count, + gl::Buffer *glBuffer, + const GLvoid *indices, + TranslatedIndexData *translated, + bool primitiveRestartFixedIndexEnabled) { - const gl::Type &typeInfo = gl::GetTypeInfo(type); - - GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; - - unsigned int offset = 0; - bool alignedOffset = false; - - BufferD3D *storage = NULL; - - if (buffer != NULL) + // Avoid D3D11's primitive restart index value + // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx + bool hasPrimitiveRestartIndex = + translated->indexRange.vertexIndexCount < static_cast(count) || + translated->indexRange.end == gl::GetPrimitiveRestartIndex(srcType); + bool primitiveRestartWorkaround = mRendererClass == RENDERER_D3D11 && + !primitiveRestartFixedIndexEnabled && + hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_SHORT; + + // We should never have to deal with MAX_UINT indices, since we restrict it via + // MAX_ELEMENT_INDEX. + ASSERT(!(mRendererClass == RENDERER_D3D11 && !primitiveRestartFixedIndexEnabled && + hasPrimitiveRestartIndex && srcType == GL_UNSIGNED_INT)); + + const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) ? + GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + + const gl::Type &srcTypeInfo = gl::GetTypeInfo(srcType); + const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); + + BufferD3D *buffer = glBuffer ? GetImplAs(glBuffer) : nullptr; + + translated->indexType = dstType; + translated->srcIndexData.srcBuffer = buffer; + translated->srcIndexData.srcIndices = indices; + translated->srcIndexData.srcIndexType = srcType; + translated->srcIndexData.srcCount = count; + + // Case 1: the indices are passed by pointer, which forces the streaming of index data + if (glBuffer == nullptr) { - offset = static_cast(reinterpret_cast(indices)); - - storage = GetImplAs(buffer); - - // We'll trust that the compiler will optimize the % below: - // the operands are unsigned and the divisor is a constant. - switch (type) - { - case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; - case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break; - case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break; - default: UNREACHABLE(); alignedOffset = false; - } - - ASSERT(typeInfo.bytes * static_cast(count) + offset <= storage->getSize()); - - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) - { - return error; - } - - indices = bufferData + offset; + translated->storage = nullptr; + return streamIndexData(indices, count, srcType, dstType, primitiveRestartFixedIndexEnabled, + translated); } - StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; - IndexBufferInterface *indexBuffer = NULL; - bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && - destinationIndexType == type; - unsigned int streamOffset = 0; + // Case 2: the indices are already in a buffer + unsigned int offset = static_cast(reinterpret_cast(indices)); + ASSERT(srcTypeInfo.bytes * static_cast(count) + offset <= buffer->getSize()); - if (directStorage) + bool offsetAligned; + switch (srcType) { - streamOffset = offset; + case GL_UNSIGNED_BYTE: offsetAligned = (offset % sizeof(GLubyte) == 0); break; + case GL_UNSIGNED_SHORT: offsetAligned = (offset % sizeof(GLushort) == 0); break; + case GL_UNSIGNED_INT: offsetAligned = (offset % sizeof(GLuint) == 0); break; + default: UNREACHABLE(); offsetAligned = false; } - else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset) - { - indexBuffer = staticBuffer; - // Using bit-shift here is faster than using division. - streamOffset = (offset >> typeInfo.bytesShift) << gl::GetTypeInfo(destinationIndexType).bytesShift; - } - - // Avoid D3D11's primitive restart index value - // see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx - if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRendererClass == RENDERER_D3D11) + // Case 2a: the buffer can be used directly + if (offsetAligned && buffer->supportsDirectBinding() && + dstType == srcType && !primitiveRestartWorkaround) { - destinationIndexType = GL_UNSIGNED_INT; - directStorage = false; - indexBuffer = NULL; + translated->storage = buffer; + translated->indexBuffer = nullptr; + translated->serial = buffer->getSerial(); + translated->startIndex = (offset >> srcTypeInfo.bytesShift); + translated->startOffset = offset; + buffer->promoteStaticUsage(count << srcTypeInfo.bytesShift); + return gl::Error(GL_NO_ERROR); } - - const gl::Type &destTypeInfo = gl::GetTypeInfo(destinationIndexType); - - if (!directStorage && !indexBuffer) + else { - gl::Error error = getStreamingIndexBuffer(destinationIndexType, &indexBuffer); - if (error.isError()) - { - return error; - } - - unsigned int convertCount = count; + translated->storage = nullptr; + } - if (staticBuffer) - { - if (staticBuffer->getBufferSize() == 0 && alignedOffset) - { - indexBuffer = staticBuffer; - // Using bit-shift here is faster than using division. - convertCount = storage->getSize() >> typeInfo.bytesShift; - } - else - { - storage->invalidateStaticData(); - staticBuffer = NULL; - } - } + // Case 2b: use a static translated copy or fall back to streaming + StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer(); - ASSERT(indexBuffer); + bool staticBufferInitialized = staticBuffer && staticBuffer->getBufferSize() != 0; + bool staticBufferUsable = staticBuffer && + offsetAligned && staticBuffer->getIndexType() == dstType; - // Using bit-shift here is faster than using division. - if (convertCount > (std::numeric_limits::max() >> destTypeInfo.bytesShift)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Reserving %u indices of %u bytes each exceeds the maximum buffer size.", - convertCount, destTypeInfo.bytes); - } + if (staticBufferInitialized && !staticBufferUsable) + { + buffer->invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + staticBuffer = nullptr; + } - unsigned int bufferSizeRequired = convertCount << destTypeInfo.bytesShift; - error = indexBuffer->reserveBufferSpace(bufferSizeRequired, type); + if (staticBuffer == nullptr || !offsetAligned) + { + const uint8_t *bufferData = nullptr; + gl::Error error = buffer->getData(&bufferData); if (error.isError()) { return error; } + ASSERT(bufferData != nullptr); - void* output = NULL; - error = indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset); + error = streamIndexData(bufferData + offset, count, srcType, dstType, + primitiveRestartFixedIndexEnabled, translated); if (error.isError()) { return error; } - - const uint8_t *dataPointer = reinterpret_cast(indices); - if (staticBuffer) + } + else + { + if (!staticBufferInitialized) { - error = storage->getData(&dataPointer); + const uint8_t *bufferData = nullptr; + gl::Error error = buffer->getData(&bufferData); if (error.isError()) { return error; } - } - ConvertIndices(type, destinationIndexType, dataPointer, convertCount, output); + ASSERT(bufferData != nullptr); - error = indexBuffer->unmapBuffer(); - if (error.isError()) - { - return error; + unsigned int convertCount = + static_cast(buffer->getSize()) >> srcTypeInfo.bytesShift; + error = StreamInIndexBuffer(staticBuffer, bufferData, convertCount, srcType, dstType, + primitiveRestartFixedIndexEnabled, nullptr); + if (error.isError()) + { + return error; + } } + ASSERT(offsetAligned && staticBuffer->getIndexType() == dstType); - if (staticBuffer) - { - // Using bit-shift here is faster than using division. - streamOffset = (offset >> typeInfo.bytesShift) << destTypeInfo.bytesShift; - } + translated->indexBuffer = staticBuffer->getIndexBuffer(); + translated->serial = staticBuffer->getSerial(); + translated->startIndex = (offset >> srcTypeInfo.bytesShift); + translated->startOffset = (offset >> srcTypeInfo.bytesShift) << dstTypeInfo.bytesShift; } - translated->storage = directStorage ? storage : NULL; - translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL; - translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); - // Using bit-shift here is faster than using division. - translated->startIndex = (streamOffset >> destTypeInfo.bytesShift); - translated->startOffset = streamOffset; - translated->indexType = destinationIndexType; + return gl::Error(GL_NO_ERROR); +} - if (storage) +gl::Error IndexDataManager::streamIndexData(const GLvoid *data, + unsigned int count, + GLenum srcType, + GLenum dstType, + bool usePrimitiveRestartFixedIndex, + TranslatedIndexData *translated) +{ + const gl::Type &dstTypeInfo = gl::GetTypeInfo(dstType); + + IndexBufferInterface *indexBuffer = nullptr; + gl::Error error = getStreamingIndexBuffer(dstType, &indexBuffer); + if (error.isError()) { - storage->promoteStaticUsage(count << typeInfo.bytesShift); + return error; } + ASSERT(indexBuffer != nullptr); + + unsigned int offset; + StreamInIndexBuffer(indexBuffer, data, count, srcType, dstType, usePrimitiveRestartFixedIndex, + &offset); + + translated->indexBuffer = indexBuffer->getIndexBuffer(); + translated->serial = indexBuffer->getSerial(); + translated->startIndex = (offset >> dstTypeInfo.bytesShift); + translated->startOffset = offset; return gl::Error(GL_NO_ERROR); } -gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer) +gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, + IndexBufferInterface **outBuffer) { ASSERT(outBuffer); if (destinationIndexType == GL_UNSIGNED_INT) @@ -233,7 +318,8 @@ gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, if (!mStreamingBufferInt) { mStreamingBufferInt = new StreamingIndexBufferInterface(mFactory); - gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, + GL_UNSIGNED_INT); if (error.isError()) { SafeDelete(mStreamingBufferInt); @@ -251,7 +337,8 @@ gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, if (!mStreamingBufferShort) { mStreamingBufferShort = new StreamingIndexBufferInterface(mFactory); - gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); + gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, + GL_UNSIGNED_SHORT); if (error.isError()) { SafeDelete(mStreamingBufferShort); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h index 275b3720c5..44eb68c071 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h @@ -36,9 +36,18 @@ class IndexBuffer; class BufferD3D; class RendererD3D; +struct SourceIndexData +{ + BufferD3D *srcBuffer; + const GLvoid *srcIndices; + unsigned int srcCount; + GLenum srcIndexType; + bool srcIndicesChanged; +}; + struct TranslatedIndexData { - RangeUI indexRange; + gl::IndexRange indexRange; unsigned int startIndex; unsigned int startOffset; // In bytes @@ -46,6 +55,8 @@ struct TranslatedIndexData BufferD3D *storage; GLenum indexType; unsigned int serial; + + SourceIndexData srcIndexData; }; class IndexDataManager : angle::NonCopyable @@ -54,10 +65,22 @@ class IndexDataManager : angle::NonCopyable explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass); virtual ~IndexDataManager(); - gl::Error prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); + gl::Error prepareIndexData(GLenum srcType, + GLsizei count, + gl::Buffer *glBuffer, + const GLvoid *indices, + TranslatedIndexData *translated, + bool primitiveRestartFixedIndexEnabled); private: - gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer); + gl::Error streamIndexData(const GLvoid *data, + unsigned int count, + GLenum srcType, + GLenum dstType, + bool usePrimitiveRestartFixedIndex, + TranslatedIndexData *translated); + gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, + IndexBufferInterface **outBuffer); BufferFactoryD3D *const mFactory; RendererClass mRendererClass; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp index 9ce9a27cd3..72c6f1a1a9 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp @@ -8,16 +8,19 @@ #include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "common/BitSetIterator.h" #include "common/utilities.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/Program.h" +#include "libANGLE/VertexArray.h" #include "libANGLE/features.h" #include "libANGLE/renderer/d3d/DynamicHLSL.h" #include "libANGLE/renderer/d3d/FramebufferD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/ShaderD3D.h" #include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" +#include "libANGLE/renderer/d3d/VaryingPacking.h" #include "libANGLE/renderer/d3d/VertexDataManager.h" namespace rx @@ -26,69 +29,41 @@ namespace rx namespace { -GLenum GetTextureType(GLenum samplerType) -{ - switch (samplerType) - { - case GL_SAMPLER_2D: - case GL_INT_SAMPLER_2D: - case GL_UNSIGNED_INT_SAMPLER_2D: - case GL_SAMPLER_2D_SHADOW: - return GL_TEXTURE_2D; - case GL_SAMPLER_3D: - case GL_INT_SAMPLER_3D: - case GL_UNSIGNED_INT_SAMPLER_3D: - return GL_TEXTURE_3D; - case GL_SAMPLER_CUBE: - case GL_SAMPLER_CUBE_SHADOW: - return GL_TEXTURE_CUBE_MAP; - case GL_INT_SAMPLER_CUBE: - case GL_UNSIGNED_INT_SAMPLER_CUBE: - return GL_TEXTURE_CUBE_MAP; - case GL_SAMPLER_2D_ARRAY: - case GL_INT_SAMPLER_2D_ARRAY: - case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: - case GL_SAMPLER_2D_ARRAY_SHADOW: - return GL_TEXTURE_2D_ARRAY; - default: UNREACHABLE(); - } - - return GL_TEXTURE_2D; -} - -void GetDefaultInputLayoutFromShader(const std::vector &shaderAttributes, gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) +gl::InputLayout GetDefaultInputLayoutFromShader(const gl::Shader *vertexShader) { - size_t layoutIndex = 0; - for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) + gl::InputLayout defaultLayout; + for (const sh::Attribute &shaderAttr : vertexShader->getActiveAttributes()) { - ASSERT(layoutIndex < gl::MAX_VERTEX_ATTRIBS); - - const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex]; - if (shaderAttr.type != GL_NONE) { GLenum transposedType = gl::TransposeMatrixType(shaderAttr.type); - for (size_t rowIndex = 0; static_cast(rowIndex) < gl::VariableRowCount(transposedType); rowIndex++, layoutIndex++) + for (size_t rowIndex = 0; + static_cast(rowIndex) < gl::VariableRowCount(transposedType); ++rowIndex) { - gl::VertexFormat *defaultFormat = &inputLayout[layoutIndex]; + GLenum componentType = gl::VariableComponentType(transposedType); + GLuint components = static_cast(gl::VariableColumnCount(transposedType)); + bool pureInt = (componentType != GL_FLOAT); + gl::VertexFormatType defaultType = + gl::GetVertexFormatType(componentType, GL_FALSE, components, pureInt); - defaultFormat->mType = gl::VariableComponentType(transposedType); - defaultFormat->mNormalized = false; - defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool - defaultFormat->mComponents = gl::VariableColumnCount(transposedType); + defaultLayout.push_back(defaultType); } } } + + return defaultLayout; } -std::vector GetDefaultOutputLayoutFromShader(const std::vector &shaderOutputVars) +std::vector GetDefaultOutputLayoutFromShader( + const std::vector &shaderOutputVars) { std::vector defaultPixelOutput; if (!shaderOutputVars.empty()) { - defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex); + defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 + + static_cast(shaderOutputVars[0].outputIndex)); } return defaultPixelOutput; @@ -106,7 +81,7 @@ bool IsRowMajorLayout(const sh::ShaderVariable &var) struct AttributeSorter { - AttributeSorter(const ProgramImpl::SemanticIndexArray &semanticIndices) + AttributeSorter(const ProgramD3D::SemanticIndexArray &semanticIndices) : originalIndices(&semanticIndices) { } @@ -116,49 +91,463 @@ struct AttributeSorter int indexA = (*originalIndices)[a]; int indexB = (*originalIndices)[b]; - if (indexA == -1) return false; - if (indexB == -1) return true; + if (indexA == -1) + return false; + if (indexB == -1) + return true; return (indexA < indexB); } - const ProgramImpl::SemanticIndexArray *originalIndices; + const ProgramD3D::SemanticIndexArray *originalIndices; }; +// true if varying x has a higher priority in packing than y +bool ComparePackedVarying(const PackedVarying &x, const PackedVarying &y) +{ + return gl::CompareShaderVar(*x.varying, *y.varying); } -ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[], - const GLenum signature[], - ShaderExecutableD3D *shaderExecutable) - : mShaderExecutable(shaderExecutable) +std::vector MergeVaryings(const gl::Shader &vertexShader, + const gl::Shader &fragmentShader, + const std::vector &tfVaryings) +{ + std::vector packedVaryings; + + for (const sh::Varying &output : vertexShader.getVaryings()) + { + bool packed = false; + + // Built-in varyings obey special rules + if (output.isBuiltIn()) + { + continue; + } + + for (const sh::Varying &input : fragmentShader.getVaryings()) + { + if (output.name == input.name) + { + if (output.isStruct()) + { + ASSERT(!output.isArray()); + for (const auto &field : output.fields) + { + ASSERT(!field.isStruct() && !field.isArray()); + packedVaryings.push_back( + PackedVarying(field, input.interpolation, input.name)); + } + } + else + { + packedVaryings.push_back(PackedVarying(input, input.interpolation)); + } + packed = true; + break; + } + } + + // Keep Transform FB varyings in the merged list always. + if (!packed) + { + for (const std::string &tfVarying : tfVaryings) + { + if (tfVarying == output.name) + { + // Transform feedback for varying structs is underspecified. + // See Khronos bug 9856. + // TODO(jmadill): Figure out how to be spec-compliant here. + if (!output.isStruct()) + { + packedVaryings.push_back(PackedVarying(output, output.interpolation)); + packedVaryings.back().vertexOnly = true; + } + break; + } + } + } + } + + std::sort(packedVaryings.begin(), packedVaryings.end(), ComparePackedVarying); + + return packedVaryings; +} + +template +void GetUniformBlockInfo(const std::vector &fields, + const std::string &prefix, + sh::BlockLayoutEncoder *encoder, + bool inRowMajorLayout, + std::map *blockInfoOut) +{ + for (const VarT &field : fields) + { + const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); + + if (field.isStruct()) + { + bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); + + for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) + { + encoder->enterAggregateType(); + + const std::string uniformElementName = + fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); + GetUniformBlockInfo(field.fields, uniformElementName, encoder, rowMajorLayout, + blockInfoOut); + + encoder->exitAggregateType(); + } + } + else + { + bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); + (*blockInfoOut)[fieldName] = + encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); + } + } +} + +template +static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag) +{ + ASSERT(dest != NULL); + ASSERT(dirtyFlag != NULL); + + *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); + *dest = source; +} + +template +bool TransposeMatrix(T *target, + const GLfloat *value, + int targetWidth, + int targetHeight, + int srcWidth, + int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetHeight, srcWidth); + int copyHeight = std::min(targetWidth, srcHeight); + + for (int x = 0; x < copyWidth; x++) + { + for (int y = 0; y < copyHeight; y++) + { + SetIfDirty(target + (x * targetWidth + y), static_cast(value[y * srcWidth + x]), + &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyWidth; y++) + { + for (int x = copyHeight; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyWidth; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + + return dirty; +} + +template +bool ExpandMatrix(T *target, + const GLfloat *value, + int targetWidth, + int targetHeight, + int srcWidth, + int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetWidth, srcWidth); + int copyHeight = std::min(targetHeight, srcHeight); + + for (int y = 0; y < copyHeight; y++) + { + for (int x = 0; x < copyWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(value[y * srcWidth + x]), + &dirty); + } + } + // clear unfilled right side + for (int y = 0; y < copyHeight; y++) + { + for (int x = copyWidth; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + // clear unfilled bottom. + for (int y = copyHeight; y < targetHeight; y++) + { + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } + } + + return dirty; +} + +gl::PrimitiveType GetGeometryShaderTypeFromDrawMode(GLenum drawMode) +{ + switch (drawMode) + { + // Uses the point sprite geometry shader. + case GL_POINTS: + return gl::PRIMITIVE_POINTS; + + // All line drawing uses the same geometry shader. + case GL_LINES: + case GL_LINE_STRIP: + case GL_LINE_LOOP: + return gl::PRIMITIVE_LINES; + + // The triangle fan primitive is emulated with strips in D3D11. + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + return gl::PRIMITIVE_TRIANGLES; + + // Special case for triangle strips. + case GL_TRIANGLE_STRIP: + return gl::PRIMITIVE_TRIANGLE_STRIP; + + default: + UNREACHABLE(); + return gl::PRIMITIVE_TYPE_MAX; + } +} + +} // anonymous namespace + +// D3DUniform Implementation + +D3DUniform::D3DUniform(GLenum typeIn, + const std::string &nameIn, + unsigned int arraySizeIn, + bool defaultBlock) + : type(typeIn), + name(nameIn), + arraySize(arraySizeIn), + data(nullptr), + dirty(true), + vsRegisterIndex(GL_INVALID_INDEX), + psRegisterIndex(GL_INVALID_INDEX), + registerCount(0), + registerElement(0) { - for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + // We use data storage for default block uniforms to cache values that are sent to D3D during + // rendering + // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only) + if (defaultBlock) { - mInputs[attributeIndex] = inputLayout[attributeIndex]; - mSignature[attributeIndex] = signature[attributeIndex]; + size_t bytes = gl::VariableInternalSize(type) * elementCount(); + data = new uint8_t[bytes]; + memset(data, 0, bytes); + + // TODO(jmadill): is this correct with non-square matrices? + registerCount = gl::VariableRowCount(type) * elementCount(); } } +D3DUniform::~D3DUniform() +{ + SafeDeleteArray(data); +} + +bool D3DUniform::isSampler() const +{ + return gl::IsSamplerType(type); +} + +bool D3DUniform::isReferencedByVertexShader() const +{ + return vsRegisterIndex != GL_INVALID_INDEX; +} + +bool D3DUniform::isReferencedByFragmentShader() const +{ + return psRegisterIndex != GL_INVALID_INDEX; +} + +// D3DVarying Implementation + +D3DVarying::D3DVarying() : semanticIndex(0), componentCount(0), outputSlot(0) +{ +} + +D3DVarying::D3DVarying(const std::string &semanticNameIn, + unsigned int semanticIndexIn, + unsigned int componentCountIn, + unsigned int outputSlotIn) + : semanticName(semanticNameIn), + semanticIndex(semanticIndexIn), + componentCount(componentCountIn), + outputSlot(outputSlotIn) +{ +} + +// ProgramD3DMetadata Implementation + +ProgramD3DMetadata::ProgramD3DMetadata(int rendererMajorShaderModel, + const std::string &shaderModelSuffix, + bool usesInstancedPointSpriteEmulation, + bool usesViewScale, + const ShaderD3D *vertexShader, + const ShaderD3D *fragmentShader) + : mRendererMajorShaderModel(rendererMajorShaderModel), + mShaderModelSuffix(shaderModelSuffix), + mUsesInstancedPointSpriteEmulation(usesInstancedPointSpriteEmulation), + mUsesViewScale(usesViewScale), + mVertexShader(vertexShader), + mFragmentShader(fragmentShader) +{ +} + +int ProgramD3DMetadata::getRendererMajorShaderModel() const +{ + return mRendererMajorShaderModel; +} + +bool ProgramD3DMetadata::usesBroadcast(const gl::Data &data) const +{ + return (mFragmentShader->usesFragColor() && data.clientVersion < 3); +} + +bool ProgramD3DMetadata::usesFragDepth(const gl::Program::Data &programData) const +{ + return mFragmentShader->usesFragDepth(); +} + +bool ProgramD3DMetadata::usesPointCoord() const +{ + return mFragmentShader->usesPointCoord(); +} + +bool ProgramD3DMetadata::usesFragCoord() const +{ + return mFragmentShader->usesFragCoord(); +} + +bool ProgramD3DMetadata::usesPointSize() const +{ + return mVertexShader->usesPointSize(); +} + +bool ProgramD3DMetadata::usesInsertedPointCoordValue() const +{ + return !usesPointSize() && usesPointCoord() && mRendererMajorShaderModel >= 4; +} + +bool ProgramD3DMetadata::usesViewScale() const +{ + return mUsesViewScale; +} + +bool ProgramD3DMetadata::addsPointCoordToVertexShader() const +{ + // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader + // VS_OUTPUT structure to ensure compatibility with the generated PS_INPUT of the pixel shader. + // GeometryShader PointSprite emulation does not require this additional entry because the + // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the + // PS_INPUT of the generated pixel shader. The Geometry Shader point sprite implementation needs + // gl_PointSize to be in VS_OUTPUT and GS_INPUT. Instanced point sprites doesn't need + // gl_PointSize in VS_OUTPUT. + return (mUsesInstancedPointSpriteEmulation && usesPointCoord()) || + usesInsertedPointCoordValue(); +} + +bool ProgramD3DMetadata::usesTransformFeedbackGLPosition() const +{ + // gl_Position only needs to be outputted from the vertex shader if transform feedback is + // active. This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from + // the vertex shader in this case. This saves us 1 output vector. + return !(mRendererMajorShaderModel >= 4 && mShaderModelSuffix != ""); +} + +bool ProgramD3DMetadata::usesSystemValuePointSize() const +{ + return !mUsesInstancedPointSpriteEmulation && usesPointSize(); +} + +bool ProgramD3DMetadata::usesMultipleFragmentOuts() const +{ + return mFragmentShader->usesMultipleRenderTargets(); +} + +GLint ProgramD3DMetadata::getMajorShaderVersion() const +{ + return mVertexShader->getData().getShaderVersion(); +} + +const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const +{ + return mFragmentShader; +} + +// ProgramD3D Implementation + +ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout, + const Signature &signature, + ShaderExecutableD3D *shaderExecutable) + : mInputs(inputLayout), mSignature(signature), mShaderExecutable(shaderExecutable) +{ +} + ProgramD3D::VertexExecutable::~VertexExecutable() { SafeDelete(mShaderExecutable); } -bool ProgramD3D::VertexExecutable::matchesSignature(const GLenum signature[]) const +// static +void ProgramD3D::VertexExecutable::getSignature(RendererD3D *renderer, + const gl::InputLayout &inputLayout, + Signature *signatureOut) { - for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + signatureOut->resize(inputLayout.size()); + + for (size_t index = 0; index < inputLayout.size(); ++index) { - if (mSignature[attributeIndex] != signature[attributeIndex]) + gl::VertexFormatType vertexFormatType = inputLayout[index]; + bool converted = false; + if (vertexFormatType != gl::VERTEX_FORMAT_INVALID) { - return false; + VertexConversionType conversionType = + renderer->getVertexConversionType(vertexFormatType); + converted = ((conversionType & VERTEX_CONVERT_GPU) != 0); } + + (*signatureOut)[index] = converted; + } +} + +bool ProgramD3D::VertexExecutable::matchesSignature(const Signature &signature) const +{ + size_t limit = std::max(mSignature.size(), signature.size()); + for (size_t index = 0; index < limit; ++index) + { + // treat undefined indexes as 'not converted' + bool a = index < signature.size() ? signature[index] : false; + bool b = index < mSignature.size() ? mSignature[index] : false; + if (a != b) + return false; } return true; } -ProgramD3D::PixelExecutable::PixelExecutable(const std::vector &outputSignature, ShaderExecutableD3D *shaderExecutable) - : mOutputSignature(outputSignature), - mShaderExecutable(shaderExecutable) +ProgramD3D::PixelExecutable::PixelExecutable(const std::vector &outputSignature, + ShaderExecutableD3D *shaderExecutable) + : mOutputSignature(outputSignature), mShaderExecutable(shaderExecutable) { } @@ -173,19 +562,18 @@ ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureTy unsigned int ProgramD3D::mCurrentSerial = 1; -ProgramD3D::ProgramD3D(RendererD3D *renderer) - : ProgramImpl(), +ProgramD3D::ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer) + : ProgramImpl(data), mRenderer(renderer), mDynamicHLSL(NULL), - mGeometryExecutable(NULL), + mGeometryExecutables(gl::PRIMITIVE_TYPE_MAX, nullptr), mUsesPointSize(false), + mUsesFlatInterpolation(false), mVertexUniformStorage(NULL), mFragmentUniformStorage(NULL), mUsedVertexSamplerRange(0), mUsedPixelSamplerRange(0), mDirtySamplerMapping(true), - mTextureUnitTypesCache(renderer->getRendererCaps().maxCombinedTextureImageUnits), - mShaderVersion(100), mSerial(issueSerial()) { mDynamicHLSL = new DynamicHLSL(renderer); @@ -202,8 +590,13 @@ bool ProgramD3D::usesPointSpriteEmulation() const return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; } -bool ProgramD3D::usesGeometryShader() const +bool ProgramD3D::usesGeometryShader(GLenum drawMode) const { + if (drawMode != GL_POINTS) + { + return mUsesFlatInterpolation; + } + return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation(); } @@ -212,30 +605,34 @@ bool ProgramD3D::usesInstancedPointSpriteEmulation() const return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation; } -GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const +GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, + unsigned int samplerIndex, + const gl::Caps &caps) const { GLint logicalTextureUnit = -1; switch (type) { - case gl::SAMPLER_PIXEL: - ASSERT(samplerIndex < caps.maxTextureImageUnits); - if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) - { - logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; - } - break; - case gl::SAMPLER_VERTEX: - ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); - if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) - { - logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; - } - break; - default: UNREACHABLE(); + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < caps.maxTextureImageUnits); + if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) + { + logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; + } + break; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); + if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) + { + logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; + } + break; + default: + UNREACHABLE(); } - if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast(caps.maxCombinedTextureImageUnits)) + if (logicalTextureUnit >= 0 && + logicalTextureUnit < static_cast(caps.maxCombinedTextureImageUnits)) { return logicalTextureUnit; } @@ -249,15 +646,16 @@ GLenum ProgramD3D::getSamplerTextureType(gl::SamplerType type, unsigned int samp { switch (type) { - case gl::SAMPLER_PIXEL: - ASSERT(samplerIndex < mSamplersPS.size()); - ASSERT(mSamplersPS[samplerIndex].active); - return mSamplersPS[samplerIndex].textureType; - case gl::SAMPLER_VERTEX: - ASSERT(samplerIndex < mSamplersVS.size()); - ASSERT(mSamplersVS[samplerIndex].active); - return mSamplersVS[samplerIndex].textureType; - default: UNREACHABLE(); + case gl::SAMPLER_PIXEL: + ASSERT(samplerIndex < mSamplersPS.size()); + ASSERT(mSamplersPS[samplerIndex].active); + return mSamplersPS[samplerIndex].textureType; + case gl::SAMPLER_VERTEX: + ASSERT(samplerIndex < mSamplersVS.size()); + ASSERT(mSamplersVS[samplerIndex].active); + return mSamplersVS[samplerIndex].textureType; + default: + UNREACHABLE(); } return GL_TEXTURE_2D; @@ -267,13 +665,13 @@ GLint ProgramD3D::getUsedSamplerRange(gl::SamplerType type) const { switch (type) { - case gl::SAMPLER_PIXEL: - return mUsedPixelSamplerRange; - case gl::SAMPLER_VERTEX: - return mUsedVertexSamplerRange; - default: - UNREACHABLE(); - return 0; + case gl::SAMPLER_PIXEL: + return mUsedPixelSamplerRange; + case gl::SAMPLER_VERTEX: + return mUsedVertexSamplerRange; + default: + UNREACHABLE(); + return 0; } } @@ -287,145 +685,78 @@ void ProgramD3D::updateSamplerMapping() mDirtySamplerMapping = false; // Retrieve sampler uniform values - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + for (const D3DUniform *d3dUniform : mD3DUniforms) { - gl::LinkedUniform *targetUniform = mUniforms[uniformIndex]; + if (!d3dUniform->dirty) + continue; + + if (!d3dUniform->isSampler()) + continue; + + int count = d3dUniform->elementCount(); + const GLint(*v)[4] = reinterpret_cast(d3dUniform->data); - if (targetUniform->dirty) + if (d3dUniform->isReferencedByFragmentShader()) { - if (gl::IsSamplerType(targetUniform->type)) + unsigned int firstIndex = d3dUniform->psRegisterIndex; + + for (int i = 0; i < count; i++) { - int count = targetUniform->elementCount(); - GLint (*v)[4] = reinterpret_cast(targetUniform->data); + unsigned int samplerIndex = firstIndex + i; - if (targetUniform->isReferencedByFragmentShader()) + if (samplerIndex < mSamplersPS.size()) { - unsigned int firstIndex = targetUniform->psRegisterIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < mSamplersPS.size()) - { - ASSERT(mSamplersPS[samplerIndex].active); - mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; - } - } + ASSERT(mSamplersPS[samplerIndex].active); + mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; } + } + } - if (targetUniform->isReferencedByVertexShader()) - { - unsigned int firstIndex = targetUniform->vsRegisterIndex; - - for (int i = 0; i < count; i++) - { - unsigned int samplerIndex = firstIndex + i; - - if (samplerIndex < mSamplersVS.size()) - { - ASSERT(mSamplersVS[samplerIndex].active); - mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; - } - } - } - } - } - } -} - -bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) -{ - // if any two active samplers in a program are of different types, but refer to the same - // texture image unit, and this is the current program, then ValidateProgram will fail, and - // DrawArrays and DrawElements will issue the INVALID_OPERATION error. - updateSamplerMapping(); - - std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE); - - for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) - { - if (mSamplersPS[i].active) + if (d3dUniform->isReferencedByVertexShader()) { - unsigned int unit = mSamplersPS[i].logicalTextureUnit; + unsigned int firstIndex = d3dUniform->vsRegisterIndex; - if (unit >= caps.maxCombinedTextureImageUnits) + for (int i = 0; i < count; i++) { - if (infoLog) - { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, caps.maxCombinedTextureImageUnits); - } + unsigned int samplerIndex = firstIndex + i; - return false; - } - - if (mTextureUnitTypesCache[unit] != GL_NONE) - { - if (mSamplersPS[i].textureType != mTextureUnitTypesCache[unit]) + if (samplerIndex < mSamplersVS.size()) { - if (infoLog) - { - infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); - } - - return false; + ASSERT(mSamplersVS[samplerIndex].active); + mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; } } - else - { - mTextureUnitTypesCache[unit] = mSamplersPS[i].textureType; - } } } +} - for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i) - { - if (mSamplersVS[i].active) - { - unsigned int unit = mSamplersVS[i].logicalTextureUnit; - - if (unit >= caps.maxCombinedTextureImageUnits) - { - if (infoLog) - { - infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, caps.maxCombinedTextureImageUnits); - } - - return false; - } +LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) +{ + reset(); - if (mTextureUnitTypesCache[unit] != GL_NONE) - { - if (mSamplersVS[i].textureType != mTextureUnitTypesCache[unit]) - { - if (infoLog) - { - infoLog->append("Samplers of conflicting types refer to the same texture image unit (%d).", unit); - } + DeviceIdentifier binaryDeviceIdentifier = {0}; + stream->readBytes(reinterpret_cast(&binaryDeviceIdentifier), + sizeof(DeviceIdentifier)); - return false; - } - } - else - { - mTextureUnitTypesCache[unit] = mSamplersVS[i].textureType; - } - } + DeviceIdentifier identifier = mRenderer->getAdapterIdentifier(); + if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0) + { + infoLog << "Invalid program binary, device configuration has changed."; + return LinkResult(false, gl::Error(GL_NO_ERROR)); } - return true; -} - -LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) -{ int compileFlags = stream->readInt(); if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) { - infoLog.append("Mismatched compilation flags."); + infoLog << "Mismatched compilation flags."; return LinkResult(false, gl::Error(GL_NO_ERROR)); } - stream->readInt(&mShaderVersion); + // TODO(jmadill): replace MAX_VERTEX_ATTRIBS + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i) + { + stream->readInt(&mSemanticIndexes[i]); + } const unsigned int psSamplerCount = stream->readInt(); for (unsigned int i = 0; i < psSamplerCount; ++i) @@ -452,105 +783,69 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) const unsigned int uniformCount = stream->readInt(); if (stream->error()) { - infoLog.append("Invalid program binary."); + infoLog << "Invalid program binary."; return LinkResult(false, gl::Error(GL_NO_ERROR)); } - mUniforms.resize(uniformCount); + const auto &linkedUniforms = mData.getUniforms(); + ASSERT(mD3DUniforms.empty()); for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) { - GLenum type = stream->readInt(); - GLenum precision = stream->readInt(); - std::string name = stream->readString(); - unsigned int arraySize = stream->readInt(); - int blockIndex = stream->readInt(); - - int offset = stream->readInt(); - int arrayStride = stream->readInt(); - int matrixStride = stream->readInt(); - bool isRowMajorMatrix = stream->readBool(); - - const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix); + const gl::LinkedUniform &linkedUniform = linkedUniforms[uniformIndex]; - gl::LinkedUniform *uniform = new gl::LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo); - - stream->readInt(&uniform->psRegisterIndex); - stream->readInt(&uniform->vsRegisterIndex); - stream->readInt(&uniform->registerCount); - stream->readInt(&uniform->registerElement); - - mUniforms[uniformIndex] = uniform; - } - - const unsigned int uniformIndexCount = stream->readInt(); - if (stream->error()) - { - infoLog.append("Invalid program binary."); - return LinkResult(false, gl::Error(GL_NO_ERROR)); - } + D3DUniform *d3dUniform = + new D3DUniform(linkedUniform.type, linkedUniform.name, linkedUniform.arraySize, + linkedUniform.isInDefaultBlock()); + stream->readInt(&d3dUniform->psRegisterIndex); + stream->readInt(&d3dUniform->vsRegisterIndex); + stream->readInt(&d3dUniform->registerCount); + stream->readInt(&d3dUniform->registerElement); - mUniformIndex.resize(uniformIndexCount); - for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++) - { - stream->readString(&mUniformIndex[uniformIndexIndex].name); - stream->readInt(&mUniformIndex[uniformIndexIndex].element); - stream->readInt(&mUniformIndex[uniformIndexIndex].index); + mD3DUniforms.push_back(d3dUniform); } - unsigned int uniformBlockCount = stream->readInt(); + const unsigned int blockCount = stream->readInt(); if (stream->error()) { - infoLog.append("Invalid program binary."); + infoLog << "Invalid program binary."; return LinkResult(false, gl::Error(GL_NO_ERROR)); } - mUniformBlocks.resize(uniformBlockCount); - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex) + ASSERT(mD3DUniformBlocks.empty()); + for (unsigned int blockIndex = 0; blockIndex < blockCount; ++blockIndex) { - std::string name = stream->readString(); - unsigned int elementIndex = stream->readInt(); - unsigned int dataSize = stream->readInt(); - - gl::UniformBlock *uniformBlock = new gl::UniformBlock(name, elementIndex, dataSize); - - stream->readInt(&uniformBlock->psRegisterIndex); - stream->readInt(&uniformBlock->vsRegisterIndex); - - unsigned int numMembers = stream->readInt(); - uniformBlock->memberUniformIndexes.resize(numMembers); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++) - { - stream->readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]); - } - - mUniformBlocks[uniformBlockIndex] = uniformBlock; + D3DUniformBlock uniformBlock; + stream->readInt(&uniformBlock.psRegisterIndex); + stream->readInt(&uniformBlock.vsRegisterIndex); + mD3DUniformBlocks.push_back(uniformBlock); } - stream->readInt(&mTransformFeedbackBufferMode); - const unsigned int transformFeedbackVaryingCount = stream->readInt(); - mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount); - for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++) + const unsigned int streamOutVaryingCount = stream->readInt(); + mStreamOutVaryings.resize(streamOutVaryingCount); + for (unsigned int varyingIndex = 0; varyingIndex < streamOutVaryingCount; ++varyingIndex) { - gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex]; + D3DVarying *varying = &mStreamOutVaryings[varyingIndex]; - stream->readString(&varying.name); - stream->readInt(&varying.type); - stream->readInt(&varying.size); - stream->readString(&varying.semanticName); - stream->readInt(&varying.semanticIndex); - stream->readInt(&varying.semanticIndexCount); + stream->readString(&varying->semanticName); + stream->readInt(&varying->semanticIndex); + stream->readInt(&varying->componentCount); + stream->readInt(&varying->outputSlot); } stream->readString(&mVertexHLSL); - stream->readBytes(reinterpret_cast(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->readBytes(reinterpret_cast(&mVertexWorkarounds), + sizeof(D3DCompilerWorkarounds)); stream->readString(&mPixelHLSL); - stream->readBytes(reinterpret_cast(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->readBytes(reinterpret_cast(&mPixelWorkarounds), + sizeof(D3DCompilerWorkarounds)); stream->readBool(&mUsesFragDepth); stream->readBool(&mUsesPointSize); + stream->readBool(&mUsesFlatInterpolation); const size_t pixelShaderKeySize = stream->readInt(); mPixelShaderKey.resize(pixelShaderKeySize); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++) + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; + pixelShaderKeyIndex++) { stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); stream->readString(&mPixelShaderKey[pixelShaderKeyIndex].name); @@ -558,31 +853,30 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) stream->readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); } - const unsigned char* binary = reinterpret_cast(stream->data()); + stream->readString(&mGeometryShaderPreamble); + + const unsigned char *binary = reinterpret_cast(stream->data()); const unsigned int vertexShaderCount = stream->readInt(); - for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) + for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; + vertexShaderIndex++) { - gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; + size_t inputLayoutSize = stream->readInt(); + gl::InputLayout inputLayout(inputLayoutSize, gl::VERTEX_FORMAT_INVALID); - for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) + for (size_t inputIndex = 0; inputIndex < inputLayoutSize; inputIndex++) { - gl::VertexFormat *vertexInput = &inputLayout[inputIndex]; - stream->readInt(&vertexInput->mType); - stream->readInt(&vertexInput->mNormalized); - stream->readInt(&vertexInput->mComponents); - stream->readBool(&vertexInput->mPureInteger); + inputLayout[inputIndex] = stream->readInt(); } - unsigned int vertexShaderSize = stream->readInt(); + unsigned int vertexShaderSize = stream->readInt(); const unsigned char *vertexShaderFunction = binary + stream->offset(); - ShaderExecutableD3D *shaderExecutable = NULL; - gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize, - SHADER_VERTEX, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - &shaderExecutable); + ShaderExecutableD3D *shaderExecutable = nullptr; + + gl::Error error = mRenderer->loadExecutable( + vertexShaderFunction, vertexShaderSize, SHADER_VERTEX, mStreamOutVaryings, + (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable); if (error.isError()) { return LinkResult(false, error); @@ -590,16 +884,17 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) if (!shaderExecutable) { - infoLog.append("Could not create vertex shader."); + infoLog << "Could not create vertex shader."; return LinkResult(false, gl::Error(GL_NO_ERROR)); } // generated converted input layout - GLenum signature[gl::MAX_VERTEX_ATTRIBS]; - getInputLayoutSignature(inputLayout, signature); + VertexExecutable::Signature signature; + VertexExecutable::getSignature(mRenderer, inputLayout, &signature); // add new binary - mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); + mVertexExecutables.push_back( + new VertexExecutable(inputLayout, signature, shaderExecutable)); stream->skip(vertexShaderSize); } @@ -614,13 +909,13 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) stream->readInt(&outputs[outputIndex]); } - const size_t pixelShaderSize = stream->readInt(); + const size_t pixelShaderSize = stream->readInt(); const unsigned char *pixelShaderFunction = binary + stream->offset(); - ShaderExecutableD3D *shaderExecutable = NULL; - gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - &shaderExecutable); + ShaderExecutableD3D *shaderExecutable = nullptr; + + gl::Error error = mRenderer->loadExecutable( + pixelShaderFunction, pixelShaderSize, SHADER_PIXEL, mStreamOutVaryings, + (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), &shaderExecutable); if (error.isError()) { return LinkResult(false, error); @@ -628,7 +923,7 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) if (!shaderExecutable) { - infoLog.append("Could not create pixel shader."); + infoLog << "Could not create pixel shader."; return LinkResult(false, gl::Error(GL_NO_ERROR)); } @@ -638,38 +933,35 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) stream->skip(pixelShaderSize); } - unsigned int geometryShaderSize = stream->readInt(); - - if (geometryShaderSize > 0) + for (unsigned int geometryExeIndex = 0; geometryExeIndex < gl::PRIMITIVE_TYPE_MAX; + ++geometryExeIndex) { + unsigned int geometryShaderSize = stream->readInt(); + if (geometryShaderSize == 0) + { + mGeometryExecutables[geometryExeIndex] = nullptr; + continue; + } + const unsigned char *geometryShaderFunction = binary + stream->offset(); - gl::Error error = mRenderer->loadExecutable(geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - &mGeometryExecutable); + bool splitAttribs = (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS); + + gl::Error error = mRenderer->loadExecutable( + geometryShaderFunction, geometryShaderSize, SHADER_GEOMETRY, mStreamOutVaryings, + splitAttribs, &mGeometryExecutables[geometryExeIndex]); if (error.isError()) { return LinkResult(false, error); } - if (!mGeometryExecutable) + if (!mGeometryExecutables[geometryExeIndex]) { - infoLog.append("Could not create geometry shader."); + infoLog << "Could not create geometry shader."; return LinkResult(false, gl::Error(GL_NO_ERROR)); } stream->skip(geometryShaderSize); } - GUID binaryIdentifier = {0}; - stream->readBytes(reinterpret_cast(&binaryIdentifier), sizeof(GUID)); - - GUID identifier = mRenderer->getAdapterIdentifier(); - if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0) - { - infoLog.append("Invalid program binary."); - return LinkResult(false, gl::Error(GL_NO_ERROR)); - } - initializeUniformStorage(); initAttributesByLayout(); @@ -678,9 +970,20 @@ LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) { + // Output the DeviceIdentifier before we output any shader code + // When we load the binary again later, we can validate the device identifier before trying to + // compile any HLSL + DeviceIdentifier binaryIdentifier = mRenderer->getAdapterIdentifier(); + stream->writeBytes(reinterpret_cast(&binaryIdentifier), + sizeof(DeviceIdentifier)); + stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); - stream->writeInt(mShaderVersion); + // TODO(jmadill): replace MAX_VERTEX_ATTRIBS + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i) + { + stream->writeInt(mSemanticIndexes[i]); + } stream->writeInt(mSamplersPS.size()); for (unsigned int i = 0; i < mSamplersPS.size(); ++i) @@ -701,79 +1004,46 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeInt(mUsedVertexSamplerRange); stream->writeInt(mUsedPixelSamplerRange); - stream->writeInt(mUniforms.size()); - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) + stream->writeInt(mD3DUniforms.size()); + for (const D3DUniform *uniform : mD3DUniforms) { - const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; - - stream->writeInt(uniform.type); - stream->writeInt(uniform.precision); - stream->writeString(uniform.name); - stream->writeInt(uniform.arraySize); - stream->writeInt(uniform.blockIndex); - - stream->writeInt(uniform.blockInfo.offset); - stream->writeInt(uniform.blockInfo.arrayStride); - stream->writeInt(uniform.blockInfo.matrixStride); - stream->writeInt(uniform.blockInfo.isRowMajorMatrix); - - stream->writeInt(uniform.psRegisterIndex); - stream->writeInt(uniform.vsRegisterIndex); - stream->writeInt(uniform.registerCount); - stream->writeInt(uniform.registerElement); - } - - stream->writeInt(mUniformIndex.size()); - for (size_t i = 0; i < mUniformIndex.size(); ++i) - { - stream->writeString(mUniformIndex[i].name); - stream->writeInt(mUniformIndex[i].element); - stream->writeInt(mUniformIndex[i].index); + // Type, name and arraySize are redundant, so aren't stored in the binary. + stream->writeInt(uniform->psRegisterIndex); + stream->writeInt(uniform->vsRegisterIndex); + stream->writeInt(uniform->registerCount); + stream->writeInt(uniform->registerElement); } - stream->writeInt(mUniformBlocks.size()); - for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex) + stream->writeInt(mD3DUniformBlocks.size()); + for (const D3DUniformBlock &uniformBlock : mD3DUniformBlocks) { - const gl::UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex]; - - stream->writeString(uniformBlock.name); - stream->writeInt(uniformBlock.elementIndex); - stream->writeInt(uniformBlock.dataSize); - - stream->writeInt(uniformBlock.memberUniformIndexes.size()); - for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) - { - stream->writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]); - } - stream->writeInt(uniformBlock.psRegisterIndex); stream->writeInt(uniformBlock.vsRegisterIndex); } - stream->writeInt(mTransformFeedbackBufferMode); - stream->writeInt(mTransformFeedbackLinkedVaryings.size()); - for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++) + stream->writeInt(mStreamOutVaryings.size()); + for (const auto &varying : mStreamOutVaryings) { - const gl::LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i]; - - stream->writeString(varying.name); - stream->writeInt(varying.type); - stream->writeInt(varying.size); stream->writeString(varying.semanticName); stream->writeInt(varying.semanticIndex); - stream->writeInt(varying.semanticIndexCount); + stream->writeInt(varying.componentCount); + stream->writeInt(varying.outputSlot); } stream->writeString(mVertexHLSL); - stream->writeBytes(reinterpret_cast(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->writeBytes(reinterpret_cast(&mVertexWorkarounds), + sizeof(D3DCompilerWorkarounds)); stream->writeString(mPixelHLSL); - stream->writeBytes(reinterpret_cast(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds)); + stream->writeBytes(reinterpret_cast(&mPixelWorkarounds), + sizeof(D3DCompilerWorkarounds)); stream->writeInt(mUsesFragDepth); stream->writeInt(mUsesPointSize); + stream->writeInt(mUsesFlatInterpolation); const std::vector &pixelShaderKey = mPixelShaderKey; stream->writeInt(pixelShaderKey.size()); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++) + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); + pixelShaderKeyIndex++) { const PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex]; stream->writeInt(variable.type); @@ -782,18 +1052,20 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeInt(variable.outputIndex); } + stream->writeString(mGeometryShaderPreamble); + stream->writeInt(mVertexExecutables.size()); - for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) + for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); + vertexExecutableIndex++) { VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; - for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) + const auto &inputLayout = vertexExecutable->inputs(); + stream->writeInt(inputLayout.size()); + + for (size_t inputIndex = 0; inputIndex < inputLayout.size(); inputIndex++) { - const gl::VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex]; - stream->writeInt(vertexInput.mType); - stream->writeInt(vertexInput.mNormalized); - stream->writeInt(vertexInput.mComponents); - stream->writeInt(vertexInput.mPureInteger); + stream->writeInt(inputLayout[inputIndex]); } size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); @@ -804,7 +1076,8 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) } stream->writeInt(mPixelExecutables.size()); - for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) + for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); + pixelExecutableIndex++) { PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; @@ -822,27 +1095,33 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream) stream->writeBytes(pixelBlob, pixelShaderSize); } - size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; - stream->writeInt(geometryShaderSize); - - if (mGeometryExecutable != NULL && geometryShaderSize > 0) + for (const ShaderExecutableD3D *geometryExe : mGeometryExecutables) { - const uint8_t *geometryBlob = mGeometryExecutable->getFunction(); - stream->writeBytes(geometryBlob, geometryShaderSize); - } + if (geometryExe == nullptr) + { + stream->writeInt(0); + continue; + } - GUID binaryIdentifier = mRenderer->getAdapterIdentifier(); - stream->writeBytes(reinterpret_cast(&binaryIdentifier), sizeof(GUID)); + size_t geometryShaderSize = geometryExe->getLength(); + stream->writeInt(geometryShaderSize); + stream->writeBytes(geometryExe->getFunction(), geometryShaderSize); + } return gl::Error(GL_NO_ERROR); } -gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable) +void ProgramD3D::setBinaryRetrievableHint(bool /* retrievable */) +{ +} + +gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, + ShaderExecutableD3D **outExecutable) { mPixelShaderOutputFormatCache.clear(); const FramebufferD3D *fboD3D = GetImplAs(fbo); - const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds()); + const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(); for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { @@ -850,7 +1129,9 @@ gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fb if (colorbuffer) { - mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); + mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK + ? GL_COLOR_ATTACHMENT0 + : colorbuffer->getBinding()); } else { @@ -874,8 +1155,8 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vectorgeneratePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, - outputSignature); + std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature( + mPixelHLSL, mPixelShaderKey, mUsesFragDepth, outputSignature); // Generate new pixel executable ShaderExecutableD3D *pixelExecutable = NULL; @@ -883,10 +1164,10 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vectorcompileToExecutable(*currentInfoLog, finalPixelHLSL, SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mPixelWorkarounds, &pixelExecutable); + gl::Error error = mRenderer->compileToExecutable( + *currentInfoLog, finalPixelHLSL, SHADER_PIXEL, mStreamOutVaryings, + (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mPixelWorkarounds, + &pixelExecutable); if (error.isError()) { return error; @@ -899,7 +1180,7 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector tempCharBuffer(tempInfoLog.getLength() + 3); - tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); + tempInfoLog.getLog(static_cast(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]); ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]); } @@ -907,16 +1188,15 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vectormatchesSignature(signature)) + if (mVertexExecutables[executableIndex]->matchesSignature(mCachedVertexSignature)) { *outExectuable = mVertexExecutables[executableIndex]->shaderExecutable(); return gl::Error(GL_NO_ERROR); @@ -924,7 +1204,8 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i } // Generate new dynamic layout with attribute conversions - std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); + std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout( + mVertexHLSL, inputLayout, mData.getAttributes()); // Generate new vertex executable ShaderExecutableD3D *vertexExecutable = NULL; @@ -932,10 +1213,10 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i gl::InfoLog tempInfoLog; gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; - gl::Error error = mRenderer->compileToExecutable(*currentInfoLog, finalVertexHLSL, SHADER_VERTEX, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mVertexWorkarounds, &vertexExecutable); + gl::Error error = mRenderer->compileToExecutable( + *currentInfoLog, finalVertexHLSL, SHADER_VERTEX, mStreamOutVaryings, + (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), mVertexWorkarounds, + &vertexExecutable); if (error.isError()) { return error; @@ -943,12 +1224,13 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i if (vertexExecutable) { - mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); + mVertexExecutables.push_back( + new VertexExecutable(inputLayout, mCachedVertexSignature, vertexExecutable)); } else if (!infoLog) { std::vector tempCharBuffer(tempInfoLog.getLength() + 3); - tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); + tempInfoLog.getLog(static_cast(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]); ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]); } @@ -956,50 +1238,96 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i return gl::Error(GL_NO_ERROR); } -LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - int registers) +gl::Error ProgramD3D::getGeometryExecutableForPrimitiveType(const gl::Data &data, + GLenum drawMode, + ShaderExecutableD3D **outExecutable, + gl::InfoLog *infoLog) { - ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); - ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); + if (outExecutable) + { + *outExecutable = nullptr; + } + + // Return a null shader if the current rendering doesn't use a geometry shader + if (!usesGeometryShader(drawMode)) + { + return gl::Error(GL_NO_ERROR); + } + + gl::PrimitiveType geometryShaderType = GetGeometryShaderTypeFromDrawMode(drawMode); + + if (mGeometryExecutables[geometryShaderType] != nullptr) + { + if (outExecutable) + { + *outExecutable = mGeometryExecutables[geometryShaderType]; + } + return gl::Error(GL_NO_ERROR); + } + + std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL( + geometryShaderType, data, mData, mRenderer->presentPathFastEnabled(), + mGeometryShaderPreamble); + + gl::InfoLog tempInfoLog; + gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog; + + gl::Error error = mRenderer->compileToExecutable( + *currentInfoLog, geometryHLSL, SHADER_GEOMETRY, mStreamOutVaryings, + (mData.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS), D3DCompilerWorkarounds(), + &mGeometryExecutables[geometryShaderType]); + + if (!infoLog && error.isError()) + { + std::vector tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(static_cast(tempInfoLog.getLength()), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic geometry executable:\n%s\n", &tempCharBuffer[0]); + } + + if (outExecutable) + { + *outExecutable = mGeometryExecutables[geometryShaderType]; + } + return error; +} - gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS]; - GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); +LinkResult ProgramD3D::compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog) +{ + const gl::InputLayout &defaultInputLayout = + GetDefaultInputLayoutFromShader(mData.getAttachedVertexShader()); ShaderExecutableD3D *defaultVertexExecutable = NULL; - gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog); + gl::Error error = + getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog); if (error.isError()) { return LinkResult(false, error); } - std::vector defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); + std::vector defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey()); ShaderExecutableD3D *defaultPixelExecutable = NULL; - error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog); + error = + getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog); if (error.isError()) { return LinkResult(false, error); } - if (usesGeometryShader()) + // Auto-generate the geometry shader here, if we expect to be using point rendering in D3D11. + ShaderExecutableD3D *pointGS = nullptr; + if (usesGeometryShader(GL_POINTS)) { - std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); - - - error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - D3DCompilerWorkarounds(), &mGeometryExecutable); - if (error.isError()) - { - return LinkResult(false, error); - } + getGeometryExecutableForPrimitiveType(data, GL_POINTS, &pointGS, &infoLog); } -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED - if (usesGeometryShader() && mGeometryExecutable) + const ShaderD3D *vertexShaderD3D = GetImplAs(mData.getAttachedVertexShader()); + + if (usesGeometryShader(GL_POINTS) && pointGS) { - // Geometry shaders are currently only used internally, so there is no corresponding shader object at the interface level - // For now the geometry shader debug info is pre-pended to the vertex shader, this is a bit of a clutch + // Geometry shaders are currently only used internally, so there is no corresponding shader + // object at the interface level. For now the geometry shader debug info is prepended to + // the vertex shader. vertexShaderD3D->appendDebugInfo("// GEOMETRY SHADER BEGIN\n\n"); - vertexShaderD3D->appendDebugInfo(mGeometryExecutable->getDebugInfo()); + vertexShaderD3D->appendDebugInfo(pointGS->getDebugInfo()); vertexShaderD3D->appendDebugInfo("\nGEOMETRY SHADER END\n\n\n"); } @@ -1010,200 +1338,316 @@ LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shade if (defaultPixelExecutable) { + const ShaderD3D *fragmentShaderD3D = + GetImplAs(mData.getAttachedFragmentShader()); fragmentShaderD3D->appendDebugInfo(defaultPixelExecutable->getDebugInfo()); } -#endif - bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable)); + bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && + (!usesGeometryShader(GL_POINTS) || pointGS)); return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR)); } -LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog, - gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode, - int *registers, std::vector *linkedVaryings, - std::map *outputVariables) +LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog) { - ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); - ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); + reset(); - mSamplersPS.resize(data.caps->maxTextureImageUnits); - mSamplersVS.resize(data.caps->maxVertexTextureImageUnits); + // TODO(jmadill): structures containing samplers + for (const gl::LinkedUniform &linkedUniform : mData.getUniforms()) + { + if (linkedUniform.isSampler() && linkedUniform.isField()) + { + infoLog << "Structures containing samplers not currently supported in D3D."; + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + } - mTransformFeedbackBufferMode = transformFeedbackBufferMode; + const gl::Shader *vertexShader = mData.getAttachedVertexShader(); + const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); - mPixelHLSL = fragmentShaderD3D->getTranslatedSource(); - fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds); + const ShaderD3D *vertexShaderD3D = GetImplAs(vertexShader); + const ShaderD3D *fragmentShaderD3D = GetImplAs(fragmentShader); + + mSamplersVS.resize(data.caps->maxVertexTextureImageUnits); + mSamplersPS.resize(data.caps->maxTextureImageUnits); - mVertexHLSL = vertexShaderD3D->getTranslatedSource(); vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds); - mShaderVersion = vertexShaderD3D->getShaderVersion(); + fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds); + + if (mRenderer->getRendererLimitations().noFrontFacingSupport) + { + if (fragmentShaderD3D->usesFrontFacing()) + { + infoLog << "The current renderer doesn't support gl_FrontFacing"; + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + } + + std::vector packedVaryings = + MergeVaryings(*vertexShader, *fragmentShader, mData.getTransformFeedbackVaryingNames()); // Map the varyings to the register file - VaryingPacking packing = { NULL }; - *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings); + VaryingPacking varyingPacking(data.caps->maxVaryingVectors); + if (!varyingPacking.packVaryings(infoLog, packedVaryings, + mData.getTransformFeedbackVaryingNames())) + { + return LinkResult(false, gl::Error(GL_NO_ERROR)); + } + + ProgramD3DMetadata metadata(mRenderer->getMajorShaderModel(), mRenderer->getShaderModelSuffix(), + usesInstancedPointSpriteEmulation(), + mRenderer->presentPathFastEnabled(), vertexShaderD3D, + fragmentShaderD3D); + + varyingPacking.enableBuiltins(SHADER_VERTEX, metadata); + varyingPacking.enableBuiltins(SHADER_PIXEL, metadata); - if (*registers < 0) + if (static_cast(varyingPacking.getRegisterCount()) > data.caps->maxVaryingVectors) { + infoLog << "No varying registers left to support gl_FragCoord/gl_PointCoord"; return LinkResult(false, gl::Error(GL_NO_ERROR)); } - if (!gl::Program::linkVaryings(infoLog, fragmentShader, vertexShader)) + // TODO(jmadill): Implement more sophisticated component packing in D3D9. + // We can fail here because we use one semantic per GLSL varying. D3D11 can pack varyings + // intelligently, but D3D9 assumes one semantic per register. + if (mRenderer->getRendererClass() == RENDERER_D3D9 && + varyingPacking.getMaxSemanticIndex() > data.caps->maxVaryingVectors) { + infoLog << "Cannot pack these varyings on D3D9."; return LinkResult(false, gl::Error(GL_NO_ERROR)); } - if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL, mVertexHLSL, - fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings, - linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth)) + if (!mDynamicHLSL->generateShaderLinkHLSL(data, mData, metadata, varyingPacking, &mPixelHLSL, + &mVertexHLSL)) { return LinkResult(false, gl::Error(GL_NO_ERROR)); } mUsesPointSize = vertexShaderD3D->usesPointSize(); + mDynamicHLSL->getPixelShaderOutputKey(data, mData, metadata, &mPixelShaderKey); + mUsesFragDepth = metadata.usesFragDepth(mData); - initAttributesByLayout(); + // Cache if we use flat shading + mUsesFlatInterpolation = false; + for (const auto &varying : packedVaryings) + { + if (varying.interpolation == sh::INTERPOLATION_FLAT) + { + mUsesFlatInterpolation = true; + break; + } + } + + if (mRenderer->getMajorShaderModel() >= 4) + { + varyingPacking.enableBuiltins(SHADER_GEOMETRY, metadata); + mGeometryShaderPreamble = mDynamicHLSL->generateGeometryShaderPreamble(varyingPacking); + } + + initSemanticIndex(); + + defineUniformsAndAssignRegisters(); + + gatherTransformFeedbackVaryings(varyingPacking); + + LinkResult result = compileProgramExecutables(data, infoLog); + if (result.error.isError() || !result.linkSuccess) + { + infoLog << "Failed to create D3D shaders."; + return result; + } + + initUniformBlockInfo(); return LinkResult(true, gl::Error(GL_NO_ERROR)); } -void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const +GLboolean ProgramD3D::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/) +{ + // TODO(jmadill): Do something useful here? + return GL_TRUE; +} + +void ProgramD3D::initUniformBlockInfo() +{ + const gl::Shader *vertexShader = mData.getAttachedVertexShader(); + + for (const sh::InterfaceBlock &vertexBlock : vertexShader->getInterfaceBlocks()) + { + if (!vertexBlock.staticUse && vertexBlock.layout == sh::BLOCKLAYOUT_PACKED) + continue; + + if (mBlockDataSizes.count(vertexBlock.name) > 0) + continue; + + size_t dataSize = getUniformBlockInfo(vertexBlock); + mBlockDataSizes[vertexBlock.name] = dataSize; + } + + const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); + + for (const sh::InterfaceBlock &fragmentBlock : fragmentShader->getInterfaceBlocks()) + { + if (!fragmentBlock.staticUse && fragmentBlock.layout == sh::BLOCKLAYOUT_PACKED) + continue; + + if (mBlockDataSizes.count(fragmentBlock.name) > 0) + continue; + + size_t dataSize = getUniformBlockInfo(fragmentBlock); + mBlockDataSizes[fragmentBlock.name] = dataSize; + } +} + +void ProgramD3D::assignUniformBlockRegisters() { - mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); + mD3DUniformBlocks.clear(); + + // Assign registers and update sizes. + const ShaderD3D *vertexShaderD3D = GetImplAs(mData.getAttachedVertexShader()); + const ShaderD3D *fragmentShaderD3D = GetImplAs(mData.getAttachedFragmentShader()); + + for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks()) + { + unsigned int uniformBlockElement = uniformBlock.isArray ? uniformBlock.arrayElement : 0; + + D3DUniformBlock d3dUniformBlock; + + if (uniformBlock.vertexStaticUse) + { + unsigned int baseRegister = + vertexShaderD3D->getInterfaceBlockRegister(uniformBlock.name); + d3dUniformBlock.vsRegisterIndex = baseRegister + uniformBlockElement; + } + + if (uniformBlock.fragmentStaticUse) + { + unsigned int baseRegister = + fragmentShaderD3D->getInterfaceBlockRegister(uniformBlock.name); + d3dUniformBlock.psRegisterIndex = baseRegister + uniformBlockElement; + } + + mD3DUniformBlocks.push_back(d3dUniformBlock); + } } void ProgramD3D::initializeUniformStorage() { // Compute total default block size - unsigned int vertexRegisters = 0; + unsigned int vertexRegisters = 0; unsigned int fragmentRegisters = 0; - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + for (const D3DUniform *d3dUniform : mD3DUniforms) { - const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; - - if (!gl::IsSamplerType(uniform.type)) + if (!d3dUniform->isSampler()) { - if (uniform.isReferencedByVertexShader()) + if (d3dUniform->isReferencedByVertexShader()) { - vertexRegisters = std::max(vertexRegisters, uniform.vsRegisterIndex + uniform.registerCount); + vertexRegisters = std::max(vertexRegisters, + d3dUniform->vsRegisterIndex + d3dUniform->registerCount); } - if (uniform.isReferencedByFragmentShader()) + if (d3dUniform->isReferencedByFragmentShader()) { - fragmentRegisters = std::max(fragmentRegisters, uniform.psRegisterIndex + uniform.registerCount); + fragmentRegisters = std::max( + fragmentRegisters, d3dUniform->psRegisterIndex + d3dUniform->registerCount); } } } - mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); + mVertexUniformStorage = mRenderer->createUniformStorage(vertexRegisters * 16u); mFragmentUniformStorage = mRenderer->createUniformStorage(fragmentRegisters * 16u); } -gl::Error ProgramD3D::applyUniforms() +gl::Error ProgramD3D::applyUniforms(GLenum drawMode) { - updateSamplerMapping(); + ASSERT(!mDirtySamplerMapping); - gl::Error error = mRenderer->applyUniforms(*this, mUniforms); + gl::Error error = mRenderer->applyUniforms(*this, drawMode, mD3DUniforms); if (error.isError()) { return error; } - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + for (D3DUniform *d3dUniform : mD3DUniforms) { - mUniforms[uniformIndex]->dirty = false; + d3dUniform->dirty = false; } return gl::Error(GL_NO_ERROR); } -gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) +gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data) { - GLint vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; - GLint fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; - - for (unsigned int registerIndex = 0; registerIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; ++registerIndex) + if (mData.getUniformBlocks().empty()) { - vertexUniformBuffers[registerIndex] = -1; + return gl::Error(GL_NO_ERROR); } - for (unsigned int registerIndex = 0; registerIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; ++registerIndex) + // Lazy init. + if (mD3DUniformBlocks.empty()) { - fragmentUniformBuffers[registerIndex] = -1; + assignUniformBlockRegisters(); } + mVertexUBOCache.clear(); + mFragmentUBOCache.clear(); + const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers(); const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers(); - for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++) + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mD3DUniformBlocks.size(); + uniformBlockIndex++) { - gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex]; - GLuint blockBinding = uniformBlockBindings[uniformBlockIndex]; - - ASSERT(uniformBlock); + const D3DUniformBlock &uniformBlock = mD3DUniformBlocks[uniformBlockIndex]; + GLuint blockBinding = mData.getUniformBlockBinding(uniformBlockIndex); // Unnecessary to apply an unreferenced standard or shared UBO - if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader()) + if (!uniformBlock.vertexStaticUse() && !uniformBlock.fragmentStaticUse()) { continue; } - if (uniformBlock->isReferencedByVertexShader()) + if (uniformBlock.vertexStaticUse()) { - unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; - ASSERT(vertexUniformBuffers[registerIndex] == -1); + unsigned int registerIndex = uniformBlock.vsRegisterIndex - reservedBuffersInVS; ASSERT(registerIndex < data.caps->maxVertexUniformBlocks); - vertexUniformBuffers[registerIndex] = blockBinding; + + if (mVertexUBOCache.size() <= registerIndex) + { + mVertexUBOCache.resize(registerIndex + 1, -1); + } + + ASSERT(mVertexUBOCache[registerIndex] == -1); + mVertexUBOCache[registerIndex] = blockBinding; } - if (uniformBlock->isReferencedByFragmentShader()) + if (uniformBlock.fragmentStaticUse()) { - unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; - ASSERT(fragmentUniformBuffers[registerIndex] == -1); + unsigned int registerIndex = uniformBlock.psRegisterIndex - reservedBuffersInFS; ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks); - fragmentUniformBuffers[registerIndex] = blockBinding; - } - } - return mRenderer->setUniformBuffers(data, vertexUniformBuffers, fragmentUniformBuffers); -} + if (mFragmentUBOCache.size() <= registerIndex) + { + mFragmentUBOCache.resize(registerIndex + 1, -1); + } -bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, - unsigned int registerIndex, const gl::Caps &caps) -{ - if (shader == GL_VERTEX_SHADER) - { - uniformBlock->vsRegisterIndex = registerIndex; - if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) - { - infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", caps.maxVertexUniformBlocks); - return false; - } - } - else if (shader == GL_FRAGMENT_SHADER) - { - uniformBlock->psRegisterIndex = registerIndex; - if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) - { - infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); - return false; + ASSERT(mFragmentUBOCache[registerIndex] == -1); + mFragmentUBOCache[registerIndex] = blockBinding; } } - else UNREACHABLE(); - return true; + return mRenderer->setUniformBuffers(data, mVertexUBOCache, mFragmentUBOCache); } void ProgramD3D::dirtyAllUniforms() { - unsigned int numUniforms = mUniforms.size(); - for (unsigned int index = 0; index < numUniforms; index++) + for (D3DUniform *d3dUniform : mD3DUniforms) { - mUniforms[index]->dirty = true; + d3dUniform->dirty = true; } } -void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) +void ProgramD3D::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) { setUniform(location, count, v, GL_FLOAT); } @@ -1223,47 +1667,74 @@ void ProgramD3D::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) setUniform(location, count, v, GL_FLOAT_VEC4); } -void ProgramD3D::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); } -void ProgramD3D::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); } -void ProgramD3D::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); } -void ProgramD3D::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix2x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); } -void ProgramD3D::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix3x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); } -void ProgramD3D::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix2x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); } -void ProgramD3D::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix4x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); } -void ProgramD3D::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix3x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); } -void ProgramD3D::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +void ProgramD3D::setUniformMatrix4x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value) { setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); } @@ -1308,106 +1779,86 @@ void ProgramD3D::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) setUniform(location, count, v, GL_UNSIGNED_INT_VEC4); } -void ProgramD3D::getUniformfv(GLint location, GLfloat *params) +void ProgramD3D::setUniformBlockBinding(GLuint /*uniformBlockIndex*/, + GLuint /*uniformBlockBinding*/) { - getUniformv(location, params, GL_FLOAT); } -void ProgramD3D::getUniformiv(GLint location, GLint *params) +void ProgramD3D::defineUniformsAndAssignRegisters() { - getUniformv(location, params, GL_INT); -} - -void ProgramD3D::getUniformuiv(GLint location, GLuint *params) -{ - getUniformv(location, params, GL_UNSIGNED_INT); -} - -bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, - const gl::Caps &caps) -{ - const ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader.getImplementation()); - const ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader.getImplementation()); - - const std::vector &vertexUniforms = vertexShader.getUniforms(); - const std::vector &fragmentUniforms = fragmentShader.getUniforms(); - - // Check that uniforms defined in the vertex and fragment shaders are identical - typedef std::map UniformMap; - UniformMap linkedUniforms; + D3DUniformMap uniformMap; + const gl::Shader *vertexShader = mData.getAttachedVertexShader(); + for (const sh::Uniform &vertexUniform : vertexShader->getUniforms()) - for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++) { - const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex]; - linkedUniforms[vertexUniform.name] = &vertexUniform; - } - - for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++) - { - const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex]; - UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name); - if (entry != linkedUniforms.end()) + if (vertexUniform.staticUse) { - const sh::Uniform &vertexUniform = *entry->second; - const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; - if (!gl::Program::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } + defineUniformBase(vertexShader, vertexUniform, &uniformMap); } } - for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) + const gl::Shader *fragmentShader = mData.getAttachedFragmentShader(); + for (const sh::Uniform &fragmentUniform : fragmentShader->getUniforms()) { - const sh::Uniform &uniform = vertexUniforms[uniformIndex]; - - if (uniform.staticUse) + if (fragmentUniform.staticUse) { - defineUniformBase(vertexShaderD3D, uniform, vertexShaderD3D->getUniformRegister(uniform.name)); + defineUniformBase(fragmentShader, fragmentUniform, &uniformMap); } } - for (unsigned int uniformIndex = 0; uniformIndex < fragmentUniforms.size(); uniformIndex++) + // Initialize the D3DUniform list to mirror the indexing of the GL layer. + for (const gl::LinkedUniform &glUniform : mData.getUniforms()) { - const sh::Uniform &uniform = fragmentUniforms[uniformIndex]; + if (!glUniform.isInDefaultBlock()) + continue; - if (uniform.staticUse) - { - defineUniformBase(fragmentShaderD3D, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); - } - } - - if (!indexUniforms(infoLog, caps)) - { - return false; + auto mapEntry = uniformMap.find(glUniform.name); + ASSERT(mapEntry != uniformMap.end()); + mD3DUniforms.push_back(mapEntry->second); } + assignAllSamplerRegisters(); initializeUniformStorage(); +} - // special case for gl_DepthRange, the only built-in uniform (also a struct) - if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) +void ProgramD3D::defineUniformBase(const gl::Shader *shader, + const sh::Uniform &uniform, + D3DUniformMap *uniformMap) +{ + if (uniform.isBuiltIn()) { - const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); - - mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo)); - mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo)); - mUniforms.push_back(new gl::LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); + defineUniform(shader->getType(), uniform, uniform.name, nullptr, uniformMap); + return; } - return true; + const ShaderD3D *shaderD3D = GetImplAs(shader); + + unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name); + ShShaderOutput outputType = shaderD3D->getCompilerOutputType(); + sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); + encoder.skipRegisters(startRegister); + + defineUniform(shader->getType(), uniform, uniform.name, &encoder, uniformMap); } -void ProgramD3D::defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister) +D3DUniform *ProgramD3D::getD3DUniformByName(const std::string &name) { - ShShaderOutput outputType = shader->getCompilerOutputType(); - sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); - encoder.skipRegisters(uniformRegister); + for (D3DUniform *d3dUniform : mD3DUniforms) + { + if (d3dUniform->name == name) + { + return d3dUniform; + } + } - defineUniform(shader, uniform, uniform.name, &encoder); + return nullptr; } -void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform, - const std::string &fullName, sh::HLSLBlockEncoder *encoder) +void ProgramD3D::defineUniform(GLenum shaderType, + const sh::ShaderVariable &uniform, + const std::string &fullName, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap) { if (uniform.isStruct()) { @@ -1415,50 +1866,62 @@ void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable { const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); - encoder->enterAggregateType(); + if (encoder) + encoder->enterAggregateType(); for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) { - const sh::ShaderVariable &field = uniform.fields[fieldIndex]; + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; const std::string &fieldFullName = (fullName + elementString + "." + field.name); - defineUniform(shader, field, fieldFullName, encoder); + defineUniform(shaderType, field, fieldFullName, encoder, uniformMap); } - encoder->exitAggregateType(); + if (encoder) + encoder->exitAggregateType(); } + return; } - else // Not a struct + + // Not a struct. Arrays are treated as aggregate types. + if (uniform.isArray() && encoder) { - // Arrays are treated as aggregate types - if (uniform.isArray()) - { - encoder->enterAggregateType(); - } + encoder->enterAggregateType(); + } - gl::LinkedUniform *linkedUniform = getUniformByName(fullName); + // Advance the uniform offset, to track registers allocation for structs + sh::BlockMemberInfo blockInfo = + encoder ? encoder->encodeType(uniform.type, uniform.arraySize, false) + : sh::BlockMemberInfo::getDefaultBlockInfo(); - // Advance the uniform offset, to track registers allocation for structs - sh::BlockMemberInfo blockInfo = encoder->encodeType(uniform.type, uniform.arraySize, false); + auto uniformMapEntry = uniformMap->find(fullName); + D3DUniform *d3dUniform = nullptr; - if (!linkedUniform) - { - linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, - -1, sh::BlockMemberInfo::getDefaultBlockInfo()); - ASSERT(linkedUniform); - linkedUniform->registerElement = sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo); - mUniforms.push_back(linkedUniform); - } + if (uniformMapEntry != uniformMap->end()) + { + d3dUniform = uniformMapEntry->second; + } + else + { + d3dUniform = new D3DUniform(uniform.type, fullName, uniform.arraySize, true); + (*uniformMap)[fullName] = d3dUniform; + } - if (shader->getShaderType() == GL_FRAGMENT_SHADER) + if (encoder) + { + d3dUniform->registerElement = + static_cast(sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo)); + unsigned int reg = + static_cast(sh::HLSLBlockEncoder::getBlockRegister(blockInfo)); + if (shaderType == GL_FRAGMENT_SHADER) { - linkedUniform->psRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo); + d3dUniform->psRegisterIndex = reg; } - else if (shader->getShaderType() == GL_VERTEX_SHADER) + else { - linkedUniform->vsRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo); + ASSERT(shaderType == GL_VERTEX_SHADER); + d3dUniform->vsRegisterIndex = reg; } - else UNREACHABLE(); // Arrays are treated as aggregate types if (uniform.isArray()) @@ -1469,34 +1932,24 @@ void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable } template -static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag) -{ - ASSERT(dest != NULL); - ASSERT(dirtyFlag != NULL); - - *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); - *dest = source; -} - -template -void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType) +void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType) { - const int components = gl::VariableComponentCount(targetUniformType); + const int components = gl::VariableComponentCount(targetUniformType); const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType); - gl::LinkedUniform *targetUniform = getUniformByLocation(location); - - int elementCount = targetUniform->elementCount(); + D3DUniform *targetUniform = getD3DUniformFromLocation(location); - count = std::min(elementCount - (int)mUniformIndex[location].element, count); + unsigned int elementCount = targetUniform->elementCount(); + unsigned int arrayElement = mData.getUniformLocations()[location].element; + unsigned int count = std::min(elementCount - arrayElement, static_cast(countIn)); if (targetUniform->type == targetUniformType) { - T *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; + T *target = reinterpret_cast(targetUniform->data) + arrayElement * 4; - for (int i = 0; i < count; i++) + for (unsigned int i = 0; i < count; i++) { - T *dest = target + (i * 4); + T *dest = target + (i * 4); const T *source = v + (i * components); for (int c = 0; c < components; c++) @@ -1511,16 +1964,17 @@ void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum ta } else if (targetUniform->type == targetBoolType) { - GLint *boolParams = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; + GLint *boolParams = reinterpret_cast(targetUniform->data) + arrayElement * 4; - for (int i = 0; i < count; i++) + for (unsigned int i = 0; i < count; i++) { - GLint *dest = boolParams + (i * 4); + GLint *dest = boolParams + (i * 4); const T *source = v + (i * components); for (int c = 0; c < components; c++) { - SetIfDirty(dest + c, (source[c] == static_cast(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); + SetIfDirty(dest + c, (source[c] == static_cast(0)) ? GL_FALSE : GL_TRUE, + &targetUniform->dirty); } for (int c = components; c < 4; c++) { @@ -1528,18 +1982,18 @@ void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum ta } } } - else if (gl::IsSamplerType(targetUniform->type)) + else if (targetUniform->isSampler()) { ASSERT(targetUniformType == GL_INT); - GLint *target = reinterpret_cast(targetUniform->data) + mUniformIndex[location].element * 4; + GLint *target = reinterpret_cast(targetUniform->data) + arrayElement * 4; bool wasDirty = targetUniform->dirty; - for (int i = 0; i < count; i++) + for (unsigned int i = 0; i < count; i++) { - GLint *dest = target + (i * 4); - const GLint *source = reinterpret_cast(v) + (i * components); + GLint *dest = target + (i * 4); + const GLint *source = reinterpret_cast(v) + (i * components); SetIfDirty(dest + 0, source[0], &targetUniform->dirty); SetIfDirty(dest + 1, 0, &targetUniform->dirty); @@ -1552,404 +2006,142 @@ void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum ta mDirtySamplerMapping = true; } } - else UNREACHABLE(); -} - -template -bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetHeight, srcWidth); - int copyHeight = std::min(targetWidth, srcHeight); - - for (int x = 0; x < copyWidth; x++) - { - for (int y = 0; y < copyHeight; y++) - { - SetIfDirty(target + (x * targetWidth + y), static_cast(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyWidth; y++) - { - for (int x = copyHeight; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyWidth; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - - return dirty; -} - -template -bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) -{ - bool dirty = false; - int copyWidth = std::min(targetWidth, srcWidth); - int copyHeight = std::min(targetHeight, srcHeight); - - for (int y = 0; y < copyHeight; y++) - { - for (int x = 0; x < copyWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(value[y * srcWidth + x]), &dirty); - } - } - // clear unfilled right side - for (int y = 0; y < copyHeight; y++) - { - for (int x = copyWidth; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - // clear unfilled bottom. - for (int y = copyHeight; y < targetHeight; y++) - { - for (int x = 0; x < targetWidth; x++) - { - SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); - } - } - - return dirty; + else + UNREACHABLE(); } template -void ProgramD3D::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType) +void ProgramD3D::setUniformMatrixfv(GLint location, + GLsizei countIn, + GLboolean transpose, + const GLfloat *value, + GLenum targetUniformType) { - gl::LinkedUniform *targetUniform = getUniformByLocation(location); + D3DUniform *targetUniform = getD3DUniformFromLocation(location); - int elementCount = targetUniform->elementCount(); + unsigned int elementCount = targetUniform->elementCount(); + unsigned int arrayElement = mData.getUniformLocations()[location].element; + unsigned int count = std::min(elementCount - arrayElement, static_cast(countIn)); - count = std::min(elementCount - (int)mUniformIndex[location].element, count); const unsigned int targetMatrixStride = (4 * rows); - GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride); + GLfloat *target = + (GLfloat *)(targetUniform->data + arrayElement * sizeof(GLfloat) * targetMatrixStride); - for (int i = 0; i < count; i++) + for (unsigned int i = 0; i < count; i++) { // Internally store matrices as transposed versions to accomodate HLSL matrix indexing if (transpose == GL_FALSE) { - targetUniform->dirty = transposeMatrix(target, value, 4, rows, rows, cols) || targetUniform->dirty; + targetUniform->dirty = TransposeMatrix(target, value, 4, rows, rows, cols) || + targetUniform->dirty; } else { - targetUniform->dirty = expandMatrix(target, value, 4, rows, cols, rows) || targetUniform->dirty; + targetUniform->dirty = + ExpandMatrix(target, value, 4, rows, cols, rows) || targetUniform->dirty; } target += targetMatrixStride; value += cols * rows; } } -template -void ProgramD3D::getUniformv(GLint location, T *params, GLenum uniformType) +size_t ProgramD3D::getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock) { - gl::LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; + ASSERT(interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED); - if (gl::IsMatrixType(targetUniform->type)) - { - const int rows = gl::VariableRowCount(targetUniform->type); - const int cols = gl::VariableColumnCount(targetUniform->type); - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows); - } - else if (uniformType == gl::VariableComponentType(targetUniform->type)) + // define member uniforms + sh::Std140BlockEncoder std140Encoder; + sh::HLSLBlockEncoder hlslEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); + sh::BlockLayoutEncoder *encoder = nullptr; + + if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) { - unsigned int size = gl::VariableComponentCount(targetUniform->type); - memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T), - size * sizeof(T)); + encoder = &std140Encoder; } else { - unsigned int size = gl::VariableComponentCount(targetUniform->type); - switch (gl::VariableComponentType(targetUniform->type)) - { - case GL_BOOL: - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = (boolParams[i] == GL_FALSE) ? static_cast(0) : static_cast(1); - } - } - break; - - case GL_FLOAT: - { - GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast(floatParams[i]); - } - } - break; - - case GL_INT: - { - GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast(intParams[i]); - } - } - break; - - case GL_UNSIGNED_INT: - { - GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4; + encoder = &hlslEncoder; + } - for (unsigned int i = 0; i < size; i++) - { - params[i] = static_cast(uintParams[i]); - } - } - break; + GetUniformBlockInfo(interfaceBlock.fields, interfaceBlock.fieldPrefix(), encoder, + interfaceBlock.isRowMajorLayout, &mBlockInfo); - default: UNREACHABLE(); - } - } + return encoder->getBlockSize(); } -template -void ProgramD3D::defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, - bool inRowMajorLayout) +void ProgramD3D::assignAllSamplerRegisters() { - for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) + for (const D3DUniform *d3dUniform : mD3DUniforms) { - const VarT &field = fields[uniformIndex]; - const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); - - if (field.isStruct()) + if (d3dUniform->isSampler()) { - bool rowMajorLayout = (inRowMajorLayout || IsRowMajorLayout(field)); - - for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) - { - encoder->enterAggregateType(); - - const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); - defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); - - encoder->exitAggregateType(); - } - } - else - { - bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout); - - sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); - - gl::LinkedUniform *newUniform = new gl::LinkedUniform(field.type, field.precision, fieldName, field.arraySize, - blockIndex, memberInfo); - - // add to uniform list, but not index, since uniform block uniforms have no location - blockUniformIndexes->push_back(mUniforms.size()); - mUniforms.push_back(newUniform); + assignSamplerRegisters(d3dUniform); } } } -bool ProgramD3D::defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, - const gl::Caps &caps) +void ProgramD3D::assignSamplerRegisters(const D3DUniform *d3dUniform) { - const ShaderD3D* shaderD3D = ShaderD3D::makeShaderD3D(shader.getImplementation()); + ASSERT(d3dUniform->isSampler()); + ASSERT(d3dUniform->vsRegisterIndex != GL_INVALID_INDEX || + d3dUniform->psRegisterIndex != GL_INVALID_INDEX); - // create uniform block entries if they do not exist - if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) + if (d3dUniform->vsRegisterIndex != GL_INVALID_INDEX) { - std::vector blockUniformIndexes; - const unsigned int blockIndex = mUniformBlocks.size(); - - // define member uniforms - sh::BlockLayoutEncoder *encoder = NULL; - - if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) - { - encoder = new sh::Std140BlockEncoder; - } - else - { - encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); - } - ASSERT(encoder); - - defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes, interfaceBlock.isRowMajorLayout); - - size_t dataSize = encoder->getBlockSize(); - - // create all the uniform blocks - if (interfaceBlock.arraySize > 0) - { - for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++) - { - gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize); - newUniformBlock->memberUniformIndexes = blockUniformIndexes; - mUniformBlocks.push_back(newUniformBlock); - } - } - else - { - gl::UniformBlock *newUniformBlock = new gl::UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize); - newUniformBlock->memberUniformIndexes = blockUniformIndexes; - mUniformBlocks.push_back(newUniformBlock); - } + AssignSamplers(d3dUniform->vsRegisterIndex, d3dUniform->type, d3dUniform->arraySize, + mSamplersVS, &mUsedVertexSamplerRange); } - if (interfaceBlock.staticUse) + if (d3dUniform->psRegisterIndex != GL_INVALID_INDEX) { - // Assign registers to the uniform blocks - const GLuint blockIndex = getUniformBlockIndex(interfaceBlock.name); - const unsigned int elementCount = std::max(1u, interfaceBlock.arraySize); - ASSERT(blockIndex != GL_INVALID_INDEX); - ASSERT(blockIndex + elementCount <= mUniformBlocks.size()); - - unsigned int interfaceBlockRegister = shaderD3D->getInterfaceBlockRegister(interfaceBlock.name); - - for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) - { - gl::UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; - ASSERT(uniformBlock->name == interfaceBlock.name); - - if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), - interfaceBlockRegister + uniformBlockElement, caps)) - { - return false; - } - } + AssignSamplers(d3dUniform->psRegisterIndex, d3dUniform->type, d3dUniform->arraySize, + mSamplersPS, &mUsedPixelSamplerRange); } - - return true; } -bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex, - GLenum samplerType, - unsigned int samplerCount, - std::vector &outSamplers, - GLuint *outUsedRange) +// static +void ProgramD3D::AssignSamplers(unsigned int startSamplerIndex, + GLenum samplerType, + unsigned int samplerCount, + std::vector &outSamplers, + GLuint *outUsedRange) { unsigned int samplerIndex = startSamplerIndex; do { - if (samplerIndex < outSamplers.size()) - { - Sampler& sampler = outSamplers[samplerIndex]; - sampler.active = true; - sampler.textureType = GetTextureType(samplerType); - sampler.logicalTextureUnit = 0; - *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); - } - else - { - return false; - } - + ASSERT(samplerIndex < outSamplers.size()); + Sampler *sampler = &outSamplers[samplerIndex]; + sampler->active = true; + sampler->textureType = gl::SamplerTypeToTextureType(samplerType); + sampler->logicalTextureUnit = 0; + *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); samplerIndex++; } while (samplerIndex < startSamplerIndex + samplerCount); - - return true; -} - -bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps) -{ - ASSERT(gl::IsSamplerType(uniform.type)); - ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); - - if (uniform.vsRegisterIndex != GL_INVALID_INDEX) - { - if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, - &mUsedVertexSamplerRange)) - { - infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", - mSamplersVS.size()); - return false; - } - - unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; - if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) - { - infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", - caps.maxVertexUniformVectors); - return false; - } - } - - if (uniform.psRegisterIndex != GL_INVALID_INDEX) - { - if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, - &mUsedPixelSamplerRange)) - { - infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", - mSamplersPS.size()); - return false; - } - - unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; - if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) - { - infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", - caps.maxFragmentUniformVectors); - return false; - } - } - - return true; -} - -bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps) -{ - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const gl::LinkedUniform &uniform = *mUniforms[uniformIndex]; - - if (gl::IsSamplerType(uniform.type)) - { - if (!indexSamplerUniform(uniform, infoLog, caps)) - { - return false; - } - } - - for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++) - { - mUniformIndex.push_back(gl::VariableLocation(uniform.name, arrayElementIndex, uniformIndex)); - } - } - - return true; } void ProgramD3D::reset() { - ProgramImpl::reset(); - SafeDeleteContainer(mVertexExecutables); SafeDeleteContainer(mPixelExecutables); - SafeDelete(mGeometryExecutable); - mTransformFeedbackBufferMode = GL_NONE; + for (auto &element : mGeometryExecutables) + { + SafeDelete(element); + } mVertexHLSL.clear(); - mVertexWorkarounds.reset(); - mShaderVersion = 100; + mVertexWorkarounds = D3DCompilerWorkarounds(); mPixelHLSL.clear(); - mPixelWorkarounds.reset(); + mPixelWorkarounds = D3DCompilerWorkarounds(); mUsesFragDepth = false; mPixelShaderKey.clear(); mUsesPointSize = false; + mUsesFlatInterpolation = false; + + SafeDeleteContainer(mD3DUniforms); + mD3DUniformBlocks.clear(); SafeDelete(mVertexUniformStorage); SafeDelete(mFragmentUniformStorage); @@ -1958,10 +2150,15 @@ void ProgramD3D::reset() mSamplersVS.clear(); mUsedVertexSamplerRange = 0; - mUsedPixelSamplerRange = 0; - mDirtySamplerMapping = true; + mUsedPixelSamplerRange = 0; + mDirtySamplerMapping = true; + std::fill(mSemanticIndexes, mSemanticIndexes + ArraySize(mSemanticIndexes), -1); std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1); + + mStreamOutVaryings.clear(); + + mGeometryShaderPreamble.clear(); } unsigned int ProgramD3D::getSerial() const @@ -1974,6 +2171,27 @@ unsigned int ProgramD3D::issueSerial() return mCurrentSerial++; } +void ProgramD3D::initSemanticIndex() +{ + const gl::Shader *vertexShader = mData.getAttachedVertexShader(); + ASSERT(vertexShader != nullptr); + + // Init semantic index + for (const sh::Attribute &attribute : mData.getAttributes()) + { + int attributeIndex = attribute.location; + int index = vertexShader->getSemanticIndex(attribute.name); + int regs = gl::VariableRegisterCount(attribute.type); + + for (int reg = 0; reg < regs; ++reg) + { + mSemanticIndexes[attributeIndex + reg] = index + reg; + } + } + + initAttributesByLayout(); +} + void ProgramD3D::initAttributesByLayout() { for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) @@ -1981,25 +2199,142 @@ void ProgramD3D::initAttributesByLayout() mAttributesByLayout[i] = i; } - std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex)); + std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS], + AttributeSorter(mSemanticIndexes)); +} + +void ProgramD3D::sortAttributesByLayout( + const std::vector &unsortedAttributes, + int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS], + const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const +{ + for (size_t attribIndex = 0; attribIndex < unsortedAttributes.size(); ++attribIndex) + { + int oldIndex = mAttributesByLayout[attribIndex]; + sortedSemanticIndicesOut[attribIndex] = mSemanticIndexes[oldIndex]; + sortedAttributesOut[attribIndex] = &unsortedAttributes[oldIndex]; + } } -void ProgramD3D::sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]) const +void ProgramD3D::updateCachedInputLayout(const gl::State &state) { - rx::TranslatedAttribute oldTranslatedAttributes[gl::MAX_VERTEX_ATTRIBS]; + mCachedInputLayout.clear(); + const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes(); - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (unsigned int attributeIndex : angle::IterateBitSet(mData.getActiveAttribLocationsMask())) { - oldTranslatedAttributes[i] = attributes[i]; + int semanticIndex = mSemanticIndexes[attributeIndex]; + + if (semanticIndex != -1) + { + if (mCachedInputLayout.size() < static_cast(semanticIndex + 1)) + { + mCachedInputLayout.resize(semanticIndex + 1, gl::VERTEX_FORMAT_INVALID); + } + mCachedInputLayout[semanticIndex] = + GetVertexFormatType(vertexAttributes[attributeIndex], + state.getVertexAttribCurrentValue(attributeIndex).Type); + } } +} - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) +void ProgramD3D::gatherTransformFeedbackVaryings(const VaryingPacking &varyingPacking) +{ + const auto &builtins = varyingPacking.builtins(SHADER_VERTEX); + + const std::string &varyingSemantic = + GetVaryingSemantic(mRenderer->getMajorShaderModel(), usesPointSize()); + + // Gather the linked varyings that are used for transform feedback, they should all exist. + mStreamOutVaryings.clear(); + + const auto &tfVaryingNames = mData.getTransformFeedbackVaryingNames(); + for (unsigned int outputSlot = 0; outputSlot < static_cast(tfVaryingNames.size()); + ++outputSlot) { - int oldIndex = mAttributesByLayout[i]; - sortedSemanticIndices[i] = mSemanticIndex[oldIndex]; - attributes[i] = oldTranslatedAttributes[oldIndex]; + const auto &tfVaryingName = tfVaryingNames[outputSlot]; + if (tfVaryingName == "gl_Position") + { + if (builtins.glPosition.enabled) + { + mStreamOutVaryings.push_back(D3DVarying(builtins.glPosition.semantic, + builtins.glPosition.index, 4, outputSlot)); + } + } + else if (tfVaryingName == "gl_FragCoord") + { + if (builtins.glFragCoord.enabled) + { + mStreamOutVaryings.push_back(D3DVarying(builtins.glFragCoord.semantic, + builtins.glFragCoord.index, 4, outputSlot)); + } + } + else if (tfVaryingName == "gl_PointSize") + { + if (builtins.glPointSize.enabled) + { + mStreamOutVaryings.push_back(D3DVarying("PSIZE", 0, 1, outputSlot)); + } + } + else + { + for (const PackedVaryingRegister ®isterInfo : varyingPacking.getRegisterList()) + { + const auto &varying = *registerInfo.packedVarying->varying; + GLenum transposedType = gl::TransposeMatrixType(varying.type); + int componentCount = gl::VariableColumnCount(transposedType); + ASSERT(!varying.isBuiltIn()); + + // Transform feedback for varying structs is underspecified. + // See Khronos bug 9856. + // TODO(jmadill): Figure out how to be spec-compliant here. + if (registerInfo.packedVarying->isStructField() || varying.isStruct()) + continue; + + // There can be more than one register assigned to a particular varying, and each + // register needs its own stream out entry. + if (tfVaryingName == varying.name) + { + mStreamOutVaryings.push_back(D3DVarying( + varyingSemantic, registerInfo.semanticIndex, componentCount, outputSlot)); + } + } + } } } +D3DUniform *ProgramD3D::getD3DUniformFromLocation(GLint location) +{ + return mD3DUniforms[mData.getUniformLocations()[location].index]; +} + +bool ProgramD3D::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const +{ + std::string baseName = blockName; + gl::ParseAndStripArrayIndex(&baseName); + + auto sizeIter = mBlockDataSizes.find(baseName); + if (sizeIter == mBlockDataSizes.end()) + { + *sizeOut = 0; + return false; + } + + *sizeOut = sizeIter->second; + return true; +} + +bool ProgramD3D::getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const +{ + auto infoIter = mBlockInfo.find(memberUniformName); + if (infoIter == mBlockInfo.end()) + { + *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo(); + return false; + } + + *memberInfoOut = infoIter->second; + return true; +} } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h index 6f3eade81d..3dfe52db1c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h @@ -9,21 +9,15 @@ #ifndef LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ #define LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ +#include +#include + #include "compiler/translator/blocklayoutHLSL.h" #include "libANGLE/Constants.h" +#include "libANGLE/formatutils.h" #include "libANGLE/renderer/ProgramImpl.h" -#include "libANGLE/renderer/Workarounds.h" #include "libANGLE/renderer/d3d/DynamicHLSL.h" - -#include -#include - -namespace gl -{ -struct LinkedUniform; -struct VariableLocation; -struct VertexFormat; -} +#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" namespace rx { @@ -37,53 +31,155 @@ class ShaderExecutableD3D; #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1 #endif +// Helper struct representing a single shader uniform +struct D3DUniform : angle::NonCopyable +{ + D3DUniform(GLenum typeIn, + const std::string &nameIn, + unsigned int arraySizeIn, + bool defaultBlock); + ~D3DUniform(); + + bool isSampler() const; + unsigned int elementCount() const { return std::max(1u, arraySize); } + bool isReferencedByVertexShader() const; + bool isReferencedByFragmentShader() const; + + // Duplicated from the GL layer + GLenum type; + std::string name; + unsigned int arraySize; + + // Pointer to a system copy of the data. + // TODO(jmadill): remove this in favor of gl::LinkedUniform::data(). + uint8_t *data; + + // Has the data been updated since the last sync? + bool dirty; + + // Register information. + unsigned int vsRegisterIndex; + unsigned int psRegisterIndex; + unsigned int registerCount; + + // Register "elements" are used for uniform structs in ES3, to appropriately identify single + // uniforms + // inside aggregate types, which are packed according C-like structure rules. + unsigned int registerElement; +}; + +struct D3DUniformBlock +{ + D3DUniformBlock() : vsRegisterIndex(GL_INVALID_INDEX), psRegisterIndex(GL_INVALID_INDEX) {} + + bool vertexStaticUse() const { return vsRegisterIndex != GL_INVALID_INDEX; } + + bool fragmentStaticUse() const { return psRegisterIndex != GL_INVALID_INDEX; } + + unsigned int vsRegisterIndex; + unsigned int psRegisterIndex; +}; + +struct D3DVarying final +{ + D3DVarying(); + D3DVarying(const std::string &semanticNameIn, + unsigned int semanticIndexIn, + unsigned int componentCountIn, + unsigned int outputSlotIn); + + D3DVarying(const D3DVarying &) = default; + D3DVarying &operator=(const D3DVarying &) = default; + + std::string semanticName; + unsigned int semanticIndex; + unsigned int componentCount; + unsigned int outputSlot; +}; + +class ProgramD3DMetadata : angle::NonCopyable +{ + public: + ProgramD3DMetadata(int rendererMajorShaderModel, + const std::string &shaderModelSuffix, + bool usesInstancedPointSpriteEmulation, + bool usesViewScale, + const ShaderD3D *vertexShader, + const ShaderD3D *fragmentShader); + + int getRendererMajorShaderModel() const; + bool usesBroadcast(const gl::Data &data) const; + bool usesFragDepth(const gl::Program::Data &programData) const; + bool usesPointCoord() const; + bool usesFragCoord() const; + bool usesPointSize() const; + bool usesInsertedPointCoordValue() const; + bool usesViewScale() const; + bool addsPointCoordToVertexShader() const; + bool usesTransformFeedbackGLPosition() const; + bool usesSystemValuePointSize() const; + bool usesMultipleFragmentOuts() const; + GLint getMajorShaderVersion() const; + const ShaderD3D *getFragmentShader() const; + + private: + const int mRendererMajorShaderModel; + const std::string mShaderModelSuffix; + const bool mUsesInstancedPointSpriteEmulation; + const bool mUsesViewScale; + const ShaderD3D *mVertexShader; + const ShaderD3D *mFragmentShader; +}; + class ProgramD3D : public ProgramImpl { public: - ProgramD3D(RendererD3D *renderer); + typedef int SemanticIndexArray[gl::MAX_VERTEX_ATTRIBS]; + + ProgramD3D(const gl::Program::Data &data, RendererD3D *renderer); virtual ~ProgramD3D(); const std::vector &getPixelShaderKey() { return mPixelShaderKey; } - int getShaderVersion() const { return mShaderVersion; } - GLenum getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; } - GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const; + GLint getSamplerMapping(gl::SamplerType type, + unsigned int samplerIndex, + const gl::Caps &caps) const; GLenum getSamplerTextureType(gl::SamplerType type, unsigned int samplerIndex) const; GLint getUsedSamplerRange(gl::SamplerType type) const; void updateSamplerMapping(); - bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps); bool usesPointSize() const { return mUsesPointSize; } bool usesPointSpriteEmulation() const; - bool usesGeometryShader() const; + bool usesGeometryShader(GLenum drawMode) const; bool usesInstancedPointSpriteEmulation() const; - GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; } - LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); - gl::Error save(gl::BinaryOutputStream *stream); - - gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExectuable); - gl::Error getPixelExecutableForOutputLayout(const std::vector &outputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog); - gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog); - ShaderExecutableD3D *getGeometryExecutable() const { return mGeometryExecutable; } - - LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, - int registers); - - LinkResult link(const gl::Data &data, gl::InfoLog &infoLog, - gl::Shader *fragmentShader, gl::Shader *vertexShader, - const std::vector &transformFeedbackVaryings, - GLenum transformFeedbackBufferMode, - int *registers, std::vector *linkedVaryings, - std::map *outputVariables); - - void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; + LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) override; + gl::Error save(gl::BinaryOutputStream *stream) override; + void setBinaryRetrievableHint(bool retrievable) override; + + gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, + ShaderExecutableD3D **outExectuable); + gl::Error getPixelExecutableForOutputLayout(const std::vector &outputLayout, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog); + gl::Error getVertexExecutableForInputLayout(const gl::InputLayout &inputLayout, + ShaderExecutableD3D **outExectuable, + gl::InfoLog *infoLog); + gl::Error getGeometryExecutableForPrimitiveType(const gl::Data &data, + GLenum drawMode, + ShaderExecutableD3D **outExecutable, + gl::InfoLog *infoLog); + + LinkResult link(const gl::Data &data, gl::InfoLog &infoLog) override; + GLboolean validate(const gl::Caps &caps, gl::InfoLog *infoLog) override; + + bool getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const override; + bool getUniformBlockMemberInfo(const std::string &memberUniformName, + sh::BlockMemberInfo *memberInfoOut) const override; void initializeUniformStorage(); - gl::Error applyUniforms(); - gl::Error applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) override; - bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader, - unsigned int registerIndex, const gl::Caps &caps); + gl::Error applyUniforms(GLenum drawMode); + gl::Error applyUniformBuffers(const gl::Data &data); void dirtyAllUniforms(); void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); @@ -98,63 +194,99 @@ class ProgramD3D : public ProgramImpl void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); - void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - - void getUniformfv(GLint location, GLfloat *params); - void getUniformiv(GLint location, GLint *params); - void getUniformuiv(GLint location, GLuint *params); + void setUniformMatrix2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix2x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix3x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix2x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix4x2fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix3x4fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + void setUniformMatrix4x3fv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value); + + void setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding) override; const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; } const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } - bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader, - const gl::Caps &caps); - bool defineUniformBlock(gl::InfoLog &infoLog, const gl::Shader &shader, const sh::InterfaceBlock &interfaceBlock, const gl::Caps &caps); + unsigned int getSerial() const; - void reset(); + void sortAttributesByLayout( + const std::vector &unsortedAttributes, + int sortedSemanticIndicesOut[gl::MAX_VERTEX_ATTRIBS], + const rx::TranslatedAttribute *sortedAttributesOut[gl::MAX_VERTEX_ATTRIBS]) const; + const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndexes; } + const SemanticIndexArray &getAttributesByLayout() const { return mAttributesByLayout; } - unsigned int getSerial() const; + void updateCachedInputLayout(const gl::State &state); + const gl::InputLayout &getCachedInputLayout() const { return mCachedInputLayout; } - void initAttributesByLayout(); - void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]) const; + bool isSamplerMappingDirty() { return mDirtySamplerMapping; } private: class VertexExecutable { public: - VertexExecutable(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], - const GLenum signature[gl::MAX_VERTEX_ATTRIBS], + typedef std::vector Signature; + + VertexExecutable(const gl::InputLayout &inputLayout, + const Signature &signature, ShaderExecutableD3D *shaderExecutable); ~VertexExecutable(); - bool matchesSignature(const GLenum convertedLayout[gl::MAX_VERTEX_ATTRIBS]) const; + bool matchesSignature(const Signature &signature) const; + static void getSignature(RendererD3D *renderer, + const gl::InputLayout &inputLayout, + Signature *signatureOut); - const gl::VertexFormat *inputs() const { return mInputs; } - const GLenum *signature() const { return mSignature; } + const gl::InputLayout &inputs() const { return mInputs; } + const Signature &signature() const { return mSignature; } ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } private: - gl::VertexFormat mInputs[gl::MAX_VERTEX_ATTRIBS]; - GLenum mSignature[gl::MAX_VERTEX_ATTRIBS]; + gl::InputLayout mInputs; + Signature mSignature; ShaderExecutableD3D *mShaderExecutable; }; class PixelExecutable { public: - PixelExecutable(const std::vector &outputSignature, ShaderExecutableD3D *shaderExecutable); + PixelExecutable(const std::vector &outputSignature, + ShaderExecutableD3D *shaderExecutable); ~PixelExecutable(); - bool matchesSignature(const std::vector &signature) const { return mOutputSignature == signature; } + bool matchesSignature(const std::vector &signature) const + { + return mOutputSignature == signature; + } const std::vector &outputSignature() const { return mOutputSignature; } ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; } @@ -173,34 +305,57 @@ class ProgramD3D : public ProgramImpl GLenum textureType; }; - void defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister); - void defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform, const std::string &fullName, - sh::HLSLBlockEncoder *encoder); - bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps); - bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps); - static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, - std::vector &outSamplers, GLuint *outUsedRange); + typedef std::map D3DUniformMap; + + void defineUniformsAndAssignRegisters(); + void defineUniformBase(const gl::Shader *shader, + const sh::Uniform &uniform, + D3DUniformMap *uniformMap); + void defineUniform(GLenum shaderType, + const sh::ShaderVariable &uniform, + const std::string &fullName, + sh::HLSLBlockEncoder *encoder, + D3DUniformMap *uniformMap); + void assignAllSamplerRegisters(); + void assignSamplerRegisters(const D3DUniform *d3dUniform); + + static void AssignSamplers(unsigned int startSamplerIndex, + GLenum samplerType, + unsigned int samplerCount, + std::vector &outSamplers, + GLuint *outUsedRange); template - void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); + void setUniform(GLint location, GLsizei count, const T *v, GLenum targetUniformType); template - void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); + void setUniformMatrixfv(GLint location, + GLsizei count, + GLboolean transpose, + const GLfloat *value, + GLenum targetUniformType); - template - void getUniformv(GLint location, T *params, GLenum uniformType); + LinkResult compileProgramExecutables(const gl::Data &data, gl::InfoLog &infoLog); - template - void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, - bool inRowMajorLayout); + void gatherTransformFeedbackVaryings(const VaryingPacking &varyings); + D3DUniform *getD3DUniformByName(const std::string &name); + D3DUniform *getD3DUniformFromLocation(GLint location); + + void initSemanticIndex(); + void initAttributesByLayout(); + + void reset(); + void assignUniformBlockRegisters(); + + void initUniformBlockInfo(); + size_t getUniformBlockInfo(const sh::InterfaceBlock &interfaceBlock); RendererD3D *mRenderer; DynamicHLSL *mDynamicHLSL; std::vector mVertexExecutables; std::vector mPixelExecutables; - ShaderExecutableD3D *mGeometryExecutable; + std::vector mGeometryExecutables; std::string mVertexHLSL; D3DCompilerWorkarounds mVertexWorkarounds; @@ -210,35 +365,46 @@ class ProgramD3D : public ProgramImpl bool mUsesFragDepth; std::vector mPixelShaderKey; + // Common code for all dynamic geometry shaders. Consists mainly of the GS input and output + // structures, built from the linked varying info. We store the string itself instead of the + // packed varyings for simplicity. + std::string mGeometryShaderPreamble; + bool mUsesPointSize; + bool mUsesFlatInterpolation; UniformStorageD3D *mVertexUniformStorage; UniformStorageD3D *mFragmentUniformStorage; - GLenum mTransformFeedbackBufferMode; - std::vector mSamplersPS; std::vector mSamplersVS; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; bool mDirtySamplerMapping; - // Cache for validateSamplers - std::vector mTextureUnitTypesCache; - // Cache for getPixelExecutableForFramebuffer std::vector mPixelShaderOutputFormatCache; - int mShaderVersion; - - int mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS]; + SemanticIndexArray mSemanticIndexes; + SemanticIndexArray mAttributesByLayout; unsigned int mSerial; + std::vector mVertexUBOCache; + std::vector mFragmentUBOCache; + VertexExecutable::Signature mCachedVertexSignature; + gl::InputLayout mCachedInputLayout; + + std::vector mStreamOutVaryings; + std::vector mD3DUniforms; + std::vector mD3DUniformBlocks; + + std::map mBlockInfo; + std::map mBlockDataSizes; + static unsigned int issueSerial(); static unsigned int mCurrentSerial; }; - } -#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h index fe6afcecae..b2d895d9c6 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h @@ -12,11 +12,12 @@ #include "common/angleutils.h" #include "libANGLE/angletypes.h" +#include "libANGLE/FramebufferAttachment.h" namespace rx { -class RenderTargetD3D : angle::NonCopyable +class RenderTargetD3D : public FramebufferAttachmentRenderTarget { public: RenderTargetD3D(); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp index c91fedff06..991801a091 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp @@ -9,25 +9,22 @@ #include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/Image.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/RenderTargetD3D.h" namespace rx { -RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer) : mRenderer(renderer) +RenderbufferD3D::RenderbufferD3D(RendererD3D *renderer) + : mRenderer(renderer), mRenderTarget(nullptr), mImage(nullptr) { - mRenderTarget = NULL; } RenderbufferD3D::~RenderbufferD3D() { SafeDelete(mRenderTarget); -} - -RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(RenderbufferD3D*, renderbuffer)); - return static_cast(renderbuffer); + mImage = nullptr; } gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height) @@ -47,27 +44,58 @@ gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internal creationFormat = GL_DEPTH24_STENCIL8_OES; } + // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create + // the specified storage. + // Because ES 3.0 already knows the exact number of supported samples, it would already have been + // validated and generated GL_INVALID_VALUE. + const gl::TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(creationFormat); + if (samples > formatCaps.getMaxSamples()) + { + return gl::Error(GL_OUT_OF_MEMORY, "Renderbuffer format does not support %u samples, %u is the maximum.", + samples, formatCaps.getMaxSamples()); + } + RenderTargetD3D *newRT = NULL; - gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT); + gl::Error error = + mRenderer->createRenderTarget(static_cast(width), static_cast(height), + creationFormat, static_cast(samples), &newRT); if (error.isError()) { return error; } SafeDelete(mRenderTarget); + mImage = nullptr; mRenderTarget = newRT; return gl::Error(GL_NO_ERROR); } -RenderTargetD3D *RenderbufferD3D::getRenderTarget() +gl::Error RenderbufferD3D::setStorageEGLImageTarget(egl::Image *image) +{ + mImage = GetImplAs(image); + SafeDelete(mRenderTarget); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error RenderbufferD3D::getRenderTarget(RenderTargetD3D **outRenderTarget) { - return mRenderTarget; + if (mImage) + { + return mImage->getRenderTarget(outRenderTarget); + } + else + { + *outRenderTarget = mRenderTarget; + return gl::Error(GL_NO_ERROR); + } } -unsigned int RenderbufferD3D::getRenderTargetSerial() const +gl::Error RenderbufferD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) { - return (mRenderTarget ? mRenderTarget->getSerial() : 0); + return getRenderTarget(reinterpret_cast(rtOut)); } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h index 4c4b998683..20f6a10b2d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h @@ -16,6 +16,7 @@ namespace rx { +class EGLImageD3D; class RendererD3D; class RenderTargetD3D; class SwapChainD3D; @@ -26,18 +27,23 @@ class RenderbufferD3D : public RenderbufferImpl RenderbufferD3D(RendererD3D *renderer); virtual ~RenderbufferD3D(); - static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer); + gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override; + gl::Error setStorageMultisample(size_t samples, + GLenum internalformat, + size_t width, + size_t height) override; + gl::Error setStorageEGLImageTarget(egl::Image *image) override; - virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override; - virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) override; - - RenderTargetD3D *getRenderTarget(); - unsigned int getRenderTargetSerial() const; + gl::Error getRenderTarget(RenderTargetD3D **outRenderTarget); + gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) override; private: RendererD3D *mRenderer; RenderTargetD3D *mRenderTarget; + EGLImageD3D *mImage; }; + } #endif // LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp index 2ce0ce5a1b..105587f62c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp @@ -8,18 +8,22 @@ #include "libANGLE/renderer/d3d/RendererD3D.h" +#include "common/debug.h" #include "common/MemoryBuffer.h" #include "common/utilities.h" #include "libANGLE/Display.h" +#include "libANGLE/formatutils.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" -#include "libANGLE/ResourceManager.h" -#include "libANGLE/State.h" -#include "libANGLE/VertexArray.h" -#include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" #include "libANGLE/renderer/d3d/DisplayD3D.h" #include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/SamplerD3D.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" namespace rx { @@ -30,12 +34,17 @@ namespace // release and recreate the scratch buffer. This ensures we don't have a // degenerate case where we are stuck hogging memory. const int ScratchMemoryBufferLifetime = 1000; -} + +} // anonymous namespace RendererD3D::RendererD3D(egl::Display *display) : mDisplay(display), mDeviceLost(false), - mScratchMemoryBufferResetCounter(0) + mAnnotator(nullptr), + mPresentPathFastEnabled(false), + mScratchMemoryBufferResetCounter(0), + mWorkaroundsInitialized(false), + mDisjoint(false) { } @@ -47,35 +56,85 @@ RendererD3D::~RendererD3D() void RendererD3D::cleanup() { mScratchMemoryBuffer.resize(0); - for (auto it = mIncompleteTextures.begin(); it != mIncompleteTextures.end(); ++it) + for (auto &incompleteTexture : mIncompleteTextures) { - it->second.set(NULL); + incompleteTexture.second.set(NULL); } mIncompleteTextures.clear(); + + if (mAnnotator != nullptr) + { + gl::UninitializeDebugAnnotations(); + SafeDelete(mAnnotator); + } +} + +SamplerImpl *RendererD3D::createSampler() +{ + return new SamplerD3D(); } -// static -RendererD3D *RendererD3D::makeRendererD3D(Renderer *renderer) +gl::Error RendererD3D::drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count) { - ASSERT(HAS_DYNAMIC_TYPE(RendererD3D*, renderer)); - return static_cast(renderer); + return genericDrawArrays(data, mode, first, count, 0); +} + +gl::Error RendererD3D::drawArraysInstanced(const gl::Data &data, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) +{ + return genericDrawArrays(data, mode, first, count, instanceCount); } gl::Error RendererD3D::drawElements(const gl::Data &data, - GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const RangeUI &indexRange) + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) { - if (data.state->isPrimitiveRestartEnabled()) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "Primitive restart not implemented"); - } + return genericDrawElements(data, mode, count, type, indices, 0, indexRange); +} + +gl::Error RendererD3D::drawElementsInstanced(const gl::Data &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) +{ + return genericDrawElements(data, mode, count, type, indices, instances, indexRange); +} + +gl::Error RendererD3D::drawRangeElements(const gl::Data &data, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) +{ + return genericDrawElements(data, mode, count, type, indices, 0, indexRange); +} +gl::Error RendererD3D::genericDrawElements(const gl::Data &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) +{ gl::Program *program = data.state->getProgram(); - ASSERT(program != NULL); + ASSERT(program != nullptr); + ProgramD3D *programD3D = GetImplAs(program); + bool usesPointSize = programD3D->usesPointSize(); - program->updateSamplerMapping(); + programD3D->updateSamplerMapping(); gl::Error error = generateSwizzles(data); if (error.isError()) @@ -83,27 +142,21 @@ gl::Error RendererD3D::drawElements(const gl::Data &data, return error; } - if (!applyPrimitiveType(mode, count, program->usesPointSize())) + if (!applyPrimitiveType(mode, count, usesPointSize)) { return gl::Error(GL_NO_ERROR); } - error = applyRenderTarget(data, mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(data, mode); + error = updateState(data, mode); if (error.isError()) { return error; } - gl::VertexArray *vao = data.state->getVertexArray(); TranslatedIndexData indexInfo; indexInfo.indexRange = indexRange; - error = applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); + + error = applyIndexBuffer(data, indices, count, mode, type, &indexInfo); if (error.isError()) { return error; @@ -114,26 +167,27 @@ gl::Error RendererD3D::drawElements(const gl::Data &data, // layer. ASSERT(!data.state->isTransformFeedbackActiveUnpaused()); - GLsizei vertexCount = indexInfo.indexRange.length() + 1; - error = applyVertexBuffer(*data.state, mode, indexInfo.indexRange.start, vertexCount, instances); + size_t vertexCount = indexInfo.indexRange.vertexCount(); + error = applyVertexBuffer(*data.state, mode, static_cast(indexInfo.indexRange.start), + static_cast(vertexCount), instances, &indexInfo); if (error.isError()) { return error; } - error = applyShaders(data); + error = applyTextures(data); if (error.isError()) { return error; } - error = applyTextures(data); + error = applyShaders(data, mode); if (error.isError()) { return error; } - error = program->applyUniformBuffers(data); + error = programD3D->applyUniformBuffers(data); if (error.isError()) { return error; @@ -141,7 +195,7 @@ gl::Error RendererD3D::drawElements(const gl::Data &data, if (!skipDraw(data, mode)) { - error = drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); + error = drawElementsImpl(data, indexInfo, mode, count, type, indices, instances); if (error.isError()) { return error; @@ -151,14 +205,18 @@ gl::Error RendererD3D::drawElements(const gl::Data &data, return gl::Error(GL_NO_ERROR); } -gl::Error RendererD3D::drawArrays(const gl::Data &data, - GLenum mode, GLint first, - GLsizei count, GLsizei instances) +gl::Error RendererD3D::genericDrawArrays(const gl::Data &data, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances) { gl::Program *program = data.state->getProgram(); - ASSERT(program != NULL); + ASSERT(program != nullptr); + ProgramD3D *programD3D = GetImplAs(program); + bool usesPointSize = programD3D->usesPointSize(); - program->updateSamplerMapping(); + programD3D->updateSamplerMapping(); gl::Error error = generateSwizzles(data); if (error.isError()) @@ -166,18 +224,12 @@ gl::Error RendererD3D::drawArrays(const gl::Data &data, return error; } - if (!applyPrimitiveType(mode, count, program->usesPointSize())) + if (!applyPrimitiveType(mode, count, usesPointSize)) { return gl::Error(GL_NO_ERROR); } - error = applyRenderTarget(data, mode, false); - if (error.isError()) - { - return error; - } - - error = applyState(data, mode); + error = updateState(data, mode); if (error.isError()) { return error; @@ -185,25 +237,25 @@ gl::Error RendererD3D::drawArrays(const gl::Data &data, applyTransformFeedbackBuffers(*data.state); - error = applyVertexBuffer(*data.state, mode, first, count, instances); + error = applyVertexBuffer(*data.state, mode, first, count, instances, nullptr); if (error.isError()) { return error; } - error = applyShaders(data); + error = applyTextures(data); if (error.isError()) { return error; } - error = applyTextures(data); + error = applyShaders(data, mode); if (error.isError()) { return error; } - error = program->applyUniformBuffers(data); + error = programD3D->applyUniformBuffers(data); if (error.isError()) { return error; @@ -211,7 +263,7 @@ gl::Error RendererD3D::drawArrays(const gl::Data &data, if (!skipDraw(data, mode)) { - error = drawArrays(data, mode, count, instances, program->usesPointSize()); + error = drawArraysImpl(data, mode, count, instances); if (error.isError()) { return error; @@ -228,19 +280,19 @@ gl::Error RendererD3D::drawArrays(const gl::Data &data, gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type) { - gl::Program *program = data.state->getProgram(); + ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); - size_t samplerRange = program->getUsedSamplerRange(type); + unsigned int samplerRange = static_cast(programD3D->getUsedSamplerRange(type)); - for (size_t i = 0; i < samplerRange; i++) + for (unsigned int i = 0; i < samplerRange; i++) { - GLenum textureType = program->getSamplerTextureType(type, i); - GLint textureUnit = program->getSamplerMapping(type, i, *data.caps); + GLenum textureType = programD3D->getSamplerTextureType(type, i); + GLint textureUnit = programD3D->getSamplerMapping(type, i, *data.caps); if (textureUnit != -1) { gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); ASSERT(texture); - if (texture->getSamplerState().swizzleRequired()) + if (texture->getTextureState().swizzleRequired()) { gl::Error error = generateSwizzle(texture); if (error.isError()) @@ -271,51 +323,12 @@ gl::Error RendererD3D::generateSwizzles(const gl::Data &data) return gl::Error(GL_NO_ERROR); } -// Applies the render target surface, depth stencil surface, viewport rectangle and -// scissor rectangle to the renderer -gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport) -{ - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE); - - gl::Error error = applyRenderTarget(framebufferObject); - if (error.isError()) - { - return error; - } - - float nearZ, farZ; - data.state->getDepthRange(&nearZ, &farZ); - setViewport(data.state->getViewport(), nearZ, farZ, drawMode, - data.state->getRasterizerState().frontFace, ignoreViewport); - - setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); - - return gl::Error(GL_NO_ERROR); -} - -// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device -gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) +unsigned int RendererD3D::GetBlendSampleMask(const gl::Data &data, int samples) { - const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); - int samples = framebufferObject->getSamples(data); - - gl::RasterizerState rasterizer = data.state->getRasterizerState(); - rasterizer.pointDrawMode = (drawMode == GL_POINTS); - rasterizer.multiSample = (samples != 0); - - gl::Error error = setRasterizerState(rasterizer); - if (error.isError()) - { - return error; - } - unsigned int mask = 0; if (data.state->isSampleCoverageEnabled()) { - GLclampf coverageValue; - bool coverageInvert = false; - data.state->getSampleCoverageParams(&coverageValue, &coverageInvert); + GLclampf coverageValue = data.state->getSampleCoverageValue(); if (coverageValue != 0) { float threshold = 0.5f; @@ -332,6 +345,7 @@ gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) } } + bool coverageInvert = data.state->getSampleCoverageInvert(); if (coverageInvert) { mask = ~mask; @@ -341,71 +355,58 @@ gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode) { mask = 0xFFFFFFFF; } - error = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask); - if (error.isError()) - { - return error; - } - - error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(), - data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW); - if (error.isError()) - { - return error; - } - return gl::Error(GL_NO_ERROR); + return mask; } // Applies the shaders and shader constants to the Direct3D device -gl::Error RendererD3D::applyShaders(const gl::Data &data) +gl::Error RendererD3D::applyShaders(const gl::Data &data, GLenum drawMode) { gl::Program *program = data.state->getProgram(); + ProgramD3D *programD3D = GetImplAs(program); + programD3D->updateCachedInputLayout(*data.state); - gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; - gl::VertexFormat::GetInputLayout(inputLayout, program, *data.state); - - const gl::Framebuffer *fbo = data.state->getDrawFramebuffer(); - - gl::Error error = applyShaders(program, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, data.state->isTransformFeedbackActiveUnpaused()); + gl::Error error = applyShadersImpl(data, drawMode); if (error.isError()) { return error; } - return program->applyUniforms(); + return programD3D->applyUniforms(drawMode); } // For each Direct3D sampler of either the pixel or vertex stage, // looks up the corresponding OpenGL texture image unit and texture type, // and sets the texture and its addressing/filtering state (or NULL when inactive). +// Sampler mapping needs to be up-to-date on the program object before this is called. gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType, - const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) + const FramebufferTextureArray &framebufferTextures, size_t framebufferTextureCount) { - gl::Program *program = data.state->getProgram(); + ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); + + ASSERT(!programD3D->isSamplerMappingDirty()); - size_t samplerRange = program->getUsedSamplerRange(shaderType); - for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) + unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType); + for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) { - GLenum textureType = program->getSamplerTextureType(shaderType, samplerIndex); - GLint textureUnit = program->getSamplerMapping(shaderType, samplerIndex, *data.caps); + GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex); + GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, *data.caps); if (textureUnit != -1) { gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType); ASSERT(texture); - gl::SamplerState sampler = texture->getSamplerState(); gl::Sampler *samplerObject = data.state->getSampler(textureUnit); - if (samplerObject) - { - samplerObject->getState(&sampler); - } + + const gl::SamplerState &samplerState = + samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState(); // TODO: std::binary_search may become unavailable using older versions of GCC - if (texture->isSamplerComplete(sampler, data) && - !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) + if (texture->isSamplerComplete(samplerState, data) && + !std::binary_search(framebufferTextures.begin(), + framebufferTextures.begin() + framebufferTextureCount, texture)) { - gl::Error error = setSamplerState(shaderType, samplerIndex, texture, sampler); + gl::Error error = setSamplerState(shaderType, samplerIndex, texture, samplerState); if (error.isError()) { return error; @@ -421,7 +422,15 @@ gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shade { // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture. gl::Texture *incompleteTexture = getIncompleteTexture(textureType); - gl::Error error = setTexture(shaderType, samplerIndex, incompleteTexture); + + gl::Error error = setSamplerState(shaderType, samplerIndex, incompleteTexture, + incompleteTexture->getSamplerState()); + if (error.isError()) + { + return error; + } + + error = setTexture(shaderType, samplerIndex, incompleteTexture); if (error.isError()) { return error; @@ -442,30 +451,23 @@ gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shade // Set all the remaining textures to NULL size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits : data.caps->maxVertexTextureImageUnits; - for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) - { - gl::Error error = setTexture(shaderType, samplerIndex, NULL); - if (error.isError()) - { - return error; - } - } + clearTextures(shaderType, samplerRange, samplerCount); return gl::Error(GL_NO_ERROR); } gl::Error RendererD3D::applyTextures(const gl::Data &data) { - FramebufferTextureSerialArray framebufferSerials; - size_t framebufferSerialCount = getBoundFramebufferTextureSerials(data, &framebufferSerials); + FramebufferTextureArray framebufferTextures; + size_t framebufferSerialCount = getBoundFramebufferTextures(data, &framebufferTextures); - gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); + gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferTextures, framebufferSerialCount); if (error.isError()) { return error; } - error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); + error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferTextures, framebufferSerialCount); if (error.isError()) { return error; @@ -476,12 +478,16 @@ gl::Error RendererD3D::applyTextures(const gl::Data &data) bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) { + const gl::State &state = *data.state; + if (drawMode == GL_POINTS) { + bool usesPointSize = GetImplAs(state.getProgram())->usesPointSize(); + // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, // which affects varying interpolation. Since the value of gl_PointSize is // undefined when not written, just skip drawing to avoid unexpected results. - if (!data.state->getProgram()->usesPointSize() && !data.state->isTransformFeedbackActiveUnpaused()) + if (!usesPointSize && !state.isTransformFeedbackActiveUnpaused()) { // This is stictly speaking not an error, but developers should be // notified of risking undefined behavior. @@ -492,7 +498,8 @@ bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) } else if (gl::IsTriangleMode(drawMode)) { - if (data.state->getRasterizerState().cullFace && data.state->getRasterizerState().cullMode == GL_FRONT_AND_BACK) + if (state.getRasterizerState().cullFace && + state.getRasterizerState().cullMode == GL_FRONT_AND_BACK) { return true; } @@ -503,43 +510,41 @@ bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode) void RendererD3D::markTransformFeedbackUsage(const gl::Data &data) { - for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++) + const gl::TransformFeedback *transformFeedback = data.state->getCurrentTransformFeedback(); + for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++) { - gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i); - if (buffer) + const OffsetBindingPointer &binding = transformFeedback->getIndexedBuffer(i); + if (binding.get() != nullptr) { - BufferD3D *bufferD3D = GetImplAs(buffer); + BufferD3D *bufferD3D = GetImplAs(binding.get()); bufferD3D->markTransformFeedbackUsage(); } } } -size_t RendererD3D::getBoundFramebufferTextureSerials(const gl::Data &data, - FramebufferTextureSerialArray *outSerialArray) +size_t RendererD3D::getBoundFramebufferTextures(const gl::Data &data, FramebufferTextureArray *outTextureArray) { - size_t serialCount = 0; + size_t textureCount = 0; const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); - for (unsigned int i = 0; i < data.caps->maxColorAttachments; i++) + for (size_t i = 0; i < drawFramebuffer->getNumColorBuffers(); i++) { - gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); + const gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); if (attachment && attachment->type() == GL_TEXTURE) { - gl::Texture *texture = attachment->getTexture(); - (*outSerialArray)[serialCount++] = texture->getTextureSerial(); + (*outTextureArray)[textureCount++] = attachment->getTexture(); } } - gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); + const gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); if (depthStencilAttachment && depthStencilAttachment->type() == GL_TEXTURE) { - gl::Texture *depthStencilTexture = depthStencilAttachment->getTexture(); - (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); + (*outTextureArray)[textureCount++] = depthStencilAttachment->getTexture(); } - std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); + std::sort(outTextureArray->begin(), outTextureArray->begin() + textureCount); - return serialCount; + return textureCount; } gl::Texture *RendererD3D::getIncompleteTexture(GLenum type) @@ -548,20 +553,26 @@ gl::Texture *RendererD3D::getIncompleteTexture(GLenum type) { const GLubyte color[] = { 0, 0, 0, 255 }; const gl::Extents colorSize(1, 1, 1); - const gl::PixelUnpackState incompleteUnpackState(1, 0); + const gl::PixelUnpackState unpack(1, 0); + const gl::Box area(0, 0, 0, 1, 1, 1); - gl::Texture* t = new gl::Texture(createTexture(type), gl::Texture::INCOMPLETE_TEXTURE_ID, type); + // Skip the API layer to avoid needing to pass the Context and mess with dirty bits. + gl::Texture *t = + new gl::Texture(createTexture(type), std::numeric_limits::max(), type); + t->setStorage(type, 1, GL_RGBA8, colorSize); if (type == GL_TEXTURE_CUBE_MAP) { for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++) { - t->setImage(face, 0, GL_RGBA, colorSize, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + t->getImplementation()->setSubImage(face, 0, area, GL_RGBA8, GL_UNSIGNED_BYTE, + unpack, color); } } else { - t->setImage(type, 0, GL_RGBA, colorSize, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + t->getImplementation()->setSubImage(type, 0, area, GL_RGBA8, GL_UNSIGNED_BYTE, unpack, + color); } mIncompleteTextures[type].set(t); @@ -625,4 +636,68 @@ gl::Error RendererD3D::getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer return gl::Error(GL_NO_ERROR); } +void RendererD3D::insertEventMarker(GLsizei length, const char *marker) +{ + std::vector wcstring (length + 1); + size_t convertedChars = 0; + errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, marker, _TRUNCATE); + if (err == 0) + { + getAnnotator()->setMarker(wcstring.data()); + } +} + +void RendererD3D::pushGroupMarker(GLsizei length, const char *marker) +{ + std::vector wcstring(length + 1); + size_t convertedChars = 0; + errno_t err = mbstowcs_s(&convertedChars, wcstring.data(), length + 1, marker, _TRUNCATE); + if (err == 0) + { + getAnnotator()->beginEvent(wcstring.data()); + } +} + +void RendererD3D::popGroupMarker() +{ + getAnnotator()->endEvent(); +} + +void RendererD3D::setGPUDisjoint() +{ + mDisjoint = true; +} + +GLint RendererD3D::getGPUDisjoint() +{ + bool disjoint = mDisjoint; + + // Disjoint flag is cleared when read + mDisjoint = false; + + return disjoint; +} + +GLint64 RendererD3D::getTimestamp() +{ + // D3D has no way to get an actual timestamp reliably so 0 is returned + return 0; +} + +void RendererD3D::onMakeCurrent(const gl::Data &data) +{ +} + +void RendererD3D::initializeDebugAnnotator() +{ + createAnnotator(); + ASSERT(mAnnotator); + gl::InitializeDebugAnnotations(mAnnotator); +} + +gl::DebugAnnotator *RendererD3D::getAnnotator() +{ + ASSERT(mAnnotator); + return mAnnotator; +} } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h index 3de6c20886..f956f037e2 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h @@ -9,10 +9,15 @@ #ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ #define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_ +#include "common/debug.h" #include "common/MemoryBuffer.h" #include "libANGLE/Data.h" +#include "libANGLE/Device.h" +#include "libANGLE/formatutils.h" #include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/formatutilsD3D.h" +#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" #include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" //FIXME(jmadill): std::array is currently prohibited by Chromium style guide @@ -25,15 +30,21 @@ class ConfigSet; namespace gl { +class DebugAnnotator; class InfoLog; -struct LinkedVarying; class Texture; +struct LinkedVarying; } namespace rx { +struct D3DUniform; +struct D3DVarying; +class DeviceD3D; +class EGLImageD3D; class ImageD3D; class IndexBuffer; +class ProgramD3D; class RenderTargetD3D; class ShaderExecutableD3D; class SwapChainD3D; @@ -45,13 +56,23 @@ enum ShaderType { SHADER_VERTEX, SHADER_PIXEL, - SHADER_GEOMETRY + SHADER_GEOMETRY, + SHADER_TYPE_MAX +}; + +struct DeviceIdentifier +{ + UINT VendorId; + UINT DeviceId; + UINT SubSysId; + UINT Revision; + UINT FeatureLevel; }; enum RendererClass { RENDERER_D3D11, - RENDERER_D3D9, + RENDERER_D3D9 }; // Useful for unit testing @@ -65,8 +86,8 @@ class BufferFactoryD3D virtual IndexBuffer *createIndexBuffer() = 0; // TODO(jmadill): add VertexFormatCaps - virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; - virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; + virtual VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const = 0; + virtual GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const = 0; }; class RendererD3D : public Renderer, public BufferFactoryD3D @@ -77,68 +98,93 @@ class RendererD3D : public Renderer, public BufferFactoryD3D virtual egl::Error initialize() = 0; - static RendererD3D *makeRendererD3D(Renderer *renderer); - virtual egl::ConfigSet generateConfigs() const = 0; + virtual void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const = 0; - gl::Error drawArrays(const gl::Data &data, - GLenum mode, GLint first, - GLsizei count, GLsizei instances) override; + gl::Error drawArrays(const gl::Data &data, GLenum mode, GLint first, GLsizei count) override; + gl::Error drawArraysInstanced(const gl::Data &data, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) override; gl::Error drawElements(const gl::Data &data, - GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei instances, - const RangeUI &indexRange) override; + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) override; + gl::Error drawElementsInstanced(const gl::Data &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange) override; + gl::Error drawRangeElements(const gl::Data &data, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const GLvoid *indices, + const gl::IndexRange &indexRange) override; bool isDeviceLost() const override; std::string getVendorString() const override; + SamplerImpl *createSampler() override; + virtual int getMinorShaderModel() const = 0; virtual std::string getShaderModelSuffix() const = 0; // Direct3D Specific methods - virtual GUID getAdapterIdentifier() const = 0; + virtual DeviceIdentifier getAdapterIdentifier() const = 0; - virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; + virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) = 0; virtual gl::Error generateSwizzle(gl::Texture *texture) = 0; virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0; virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; virtual gl::Error setUniformBuffers(const gl::Data &data, - const GLint vertexUniformBuffers[], - const GLint fragmentUniformBuffers[]) = 0; - - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0; - virtual gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) = 0; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) = 0; + const std::vector &vertexUniformBuffers, + const std::vector &fragmentUniformBuffers) = 0; - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled) = 0; - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) = 0; + virtual gl::Error updateState(const gl::Data &data, GLenum drawMode) = 0; virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0; - virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) = 0; - virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) = 0; + virtual gl::Error applyUniforms(const ProgramD3D &programD3D, + GLenum drawMode, + const std::vector &uniformArray) = 0; virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0; - virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) = 0; - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; + virtual gl::Error applyVertexBuffer(const gl::State &state, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData *indexInfo) = 0; + virtual gl::Error applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo) = 0; virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0; - virtual void markAllStateDirty() = 0; - virtual unsigned int getReservedVertexUniformVectors() const = 0; virtual unsigned int getReservedFragmentUniformVectors() const = 0; virtual unsigned int getReservedVertexUniformBuffers() const = 0; virtual unsigned int getReservedFragmentUniformBuffers() const = 0; - virtual bool getShareHandleSupport() const = 0; - virtual bool getPostSubBufferSupport() const = 0; virtual int getMajorShaderModel() const = 0; + const WorkaroundsD3D &getWorkarounds() const; + // Pixel operations virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0; @@ -151,21 +197,31 @@ class RendererD3D : public Renderer, public BufferFactoryD3D // RenderTarget creation virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) = 0; + virtual gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) = 0; // Shader operations - virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) = 0; - virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, + virtual gl::Error loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) = 0; + virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, ShaderExecutableD3D **outExectuable) = 0; virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0; // Image operations virtual ImageD3D *createImage() = 0; virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0; + virtual gl::Error generateMipmapsUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) = 0; virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0; + virtual TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage) = 0; virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0; virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0; virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; @@ -179,61 +235,108 @@ class RendererD3D : public Renderer, public BufferFactoryD3D // Device lost void notifyDeviceLost() override; virtual bool resetDevice() = 0; - virtual RendererClass getRendererClass() const = 0; + virtual void *getD3DDevice() = 0; gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut); - protected: - virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) = 0; - virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; + // EXT_debug_marker + void insertEventMarker(GLsizei length, const char *marker) override; + void pushGroupMarker(GLsizei length, const char *marker) override; + void popGroupMarker() override; + + void setGPUDisjoint(); + + GLint getGPUDisjoint() override; + GLint64 getTimestamp() override; + + void onMakeCurrent(const gl::Data &data) override; + + // In D3D11, faster than calling setTexture a jillion times + virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0; + virtual egl::Error getEGLDevice(DeviceImpl **device) = 0; + + bool presentPathFastEnabled() const { return mPresentPathFastEnabled; } + + protected: virtual bool getLUID(LUID *adapterLuid) const = 0; + virtual gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) = 0; void cleanup(); + virtual void createAnnotator() = 0; + + static unsigned int GetBlendSampleMask(const gl::Data &data, int samples); + // dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state. + egl::Display *mDisplay; bool mDeviceLost; + void initializeDebugAnnotator(); + gl::DebugAnnotator *mAnnotator; + + std::vector mTranslatedAttribCache; + + bool mPresentPathFastEnabled; + private: + gl::Error genericDrawArrays(const gl::Data &data, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances); + + gl::Error genericDrawElements(const gl::Data &data, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances, + const gl::IndexRange &indexRange); + + virtual gl::Error drawArraysImpl(const gl::Data &data, + GLenum mode, + GLsizei count, + GLsizei instances) = 0; + virtual gl::Error drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances) = 0; + //FIXME(jmadill): std::array is currently prohibited by Chromium style guide - typedef std::array FramebufferTextureSerialArray; + typedef std::array FramebufferTextureArray; gl::Error generateSwizzles(const gl::Data &data, gl::SamplerType type); gl::Error generateSwizzles(const gl::Data &data); - gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport); gl::Error applyState(const gl::Data &data, GLenum drawMode); - gl::Error applyShaders(const gl::Data &data); + gl::Error applyShaders(const gl::Data &data, GLenum drawMode); gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType, - const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount); + const FramebufferTextureArray &framebufferTextures, size_t framebufferTextureCount); gl::Error applyTextures(const gl::Data &data); bool skipDraw(const gl::Data &data, GLenum drawMode); void markTransformFeedbackUsage(const gl::Data &data); - size_t getBoundFramebufferTextureSerials(const gl::Data &data, - FramebufferTextureSerialArray *outSerialArray); + size_t getBoundFramebufferTextures(const gl::Data &data, FramebufferTextureArray *outTextureArray); gl::Texture *getIncompleteTexture(GLenum type); + gl::DebugAnnotator *getAnnotator(); + + virtual WorkaroundsD3D generateWorkarounds() const = 0; + gl::TextureMap mIncompleteTextures; MemoryBuffer mScratchMemoryBuffer; unsigned int mScratchMemoryBufferResetCounter; -}; -struct dx_VertexConstants -{ - float depthRange[4]; - float viewAdjust[4]; - float viewCoords[4]; -}; + mutable bool mWorkaroundsInitialized; + mutable WorkaroundsD3D mWorkarounds; -struct dx_PixelConstants -{ - float depthRange[4]; - float viewCoords[4]; - float depthFront[4]; + bool mDisjoint; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h new file mode 100644 index 0000000000..7aabdc8132 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SamplerD3D.h @@ -0,0 +1,25 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SamplerD3D.h: Defines the rx::SamplerD3D class, an implementation of SamplerImpl. + +#ifndef LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_ +#define LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_ + +#include "libANGLE/renderer/SamplerImpl.h" + +namespace rx +{ + +class SamplerD3D : public SamplerImpl +{ + public: + SamplerD3D() {} + ~SamplerD3D() override {} +}; +} + +#endif // LIBANGLE_RENDERER_D3D_SAMPLERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp index 7d522a95d4..1ecbfb7410 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp @@ -6,14 +6,13 @@ // ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl. -#include "libANGLE/Shader.h" -#include "libANGLE/Compiler.h" -#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/ShaderD3D.h" -#include "libANGLE/renderer/d3d/CompilerD3D.h" -#include "libANGLE/features.h" #include "common/utilities.h" +#include "libANGLE/Compiler.h" +#include "libANGLE/Shader.h" +#include "libANGLE/features.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" // Definitions local to the translation unit namespace @@ -23,51 +22,24 @@ const char *GetShaderTypeString(GLenum type) { switch (type) { - case GL_VERTEX_SHADER: - return "VERTEX"; + case GL_VERTEX_SHADER: + return "VERTEX"; - case GL_FRAGMENT_SHADER: - return "FRAGMENT"; + case GL_FRAGMENT_SHADER: + return "FRAGMENT"; - default: - UNREACHABLE(); - return ""; + default: + UNREACHABLE(); + return ""; } } -} +} // anonymous namespace namespace rx { -template -void FilterInactiveVariables(std::vector *variableList) -{ - ASSERT(variableList); - - for (size_t varIndex = 0; varIndex < variableList->size();) - { - if (!(*variableList)[varIndex].staticUse) - { - variableList->erase(variableList->begin() + varIndex); - } - else - { - varIndex++; - } - } -} - -template -const std::vector *GetShaderVariables(const std::vector *variableList) -{ - ASSERT(variableList); - return variableList; -} - -ShaderD3D::ShaderD3D(GLenum type) - : mShaderType(type), - mShaderVersion(100) +ShaderD3D::ShaderD3D(const gl::Shader::Data &data) : ShaderImpl(data) { uncompile(); } @@ -76,58 +48,10 @@ ShaderD3D::~ShaderD3D() { } -ShaderD3D *ShaderD3D::makeShaderD3D(ShaderImpl *impl) -{ - ASSERT(HAS_DYNAMIC_TYPE(ShaderD3D*, impl)); - return static_cast(impl); -} - -const ShaderD3D *ShaderD3D::makeShaderD3D(const ShaderImpl *impl) -{ - ASSERT(HAS_DYNAMIC_TYPE(const ShaderD3D*, impl)); - return static_cast(impl); -} - std::string ShaderD3D::getDebugInfo() const { - return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mShaderType) + " SHADER END\n"; -} - - -void ShaderD3D::parseVaryings(ShHandle compiler) -{ - if (!mTranslatedSource.empty()) - { - const std::vector *varyings = ShGetVaryings(compiler); - ASSERT(varyings); - - for (size_t varyingIndex = 0; varyingIndex < varyings->size(); varyingIndex++) - { - mVaryings.push_back(gl::PackedVarying((*varyings)[varyingIndex])); - } - - mUsesMultipleRenderTargets = mTranslatedSource.find("GL_USES_MRT") != std::string::npos; - mUsesFragColor = mTranslatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos; - mUsesFragData = mTranslatedSource.find("GL_USES_FRAG_DATA") != std::string::npos; - mUsesFragCoord = mTranslatedSource.find("GL_USES_FRAG_COORD") != std::string::npos; - mUsesFrontFacing = mTranslatedSource.find("GL_USES_FRONT_FACING") != std::string::npos; - mUsesPointSize = mTranslatedSource.find("GL_USES_POINT_SIZE") != std::string::npos; - mUsesPointCoord = mTranslatedSource.find("GL_USES_POINT_COORD") != std::string::npos; - mUsesDepthRange = mTranslatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos; - mUsesFragDepth = mTranslatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos; - mUsesDiscardRewriting = mTranslatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; - mUsesNestedBreak = mTranslatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; - mUsesDeferredInit = mTranslatedSource.find("ANGLE_USES_DEFERRED_INIT") != std::string::npos; - mRequiresIEEEStrictCompiling = mTranslatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos; - } -} - -void ShaderD3D::resetVaryingsRegisterAssignment() -{ - for (size_t varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++) - { - mVaryings[varyingIndex].resetRegisterAssignment(); - } + return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mData.getShaderType()) + + " SHADER END\n"; } // initialize/clean up previous state @@ -135,8 +59,6 @@ void ShaderD3D::uncompile() { // set by compileToHLSL mCompilerOutputType = SH_ESSL_OUTPUT; - mTranslatedSource.clear(); - mInfoLog.clear(); mUsesMultipleRenderTargets = false; mUsesFragColor = false; @@ -147,125 +69,14 @@ void ShaderD3D::uncompile() mUsesPointCoord = false; mUsesDepthRange = false; mUsesFragDepth = false; - mShaderVersion = 100; mUsesDiscardRewriting = false; mUsesNestedBreak = false; mUsesDeferredInit = false; mRequiresIEEEStrictCompiling = false; - mVaryings.clear(); - mUniforms.clear(); - mInterfaceBlocks.clear(); - mActiveAttributes.clear(); - mActiveOutputVariables.clear(); mDebugInfo.clear(); } -void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source) -{ - int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES); - std::string sourcePath; - -#if !defined (ANGLE_ENABLE_WINDOWS_STORE) - if (gl::DebugAnnotationsActive()) - { - sourcePath = getTempPath(); - writeFile(sourcePath.c_str(), source.c_str(), source.length()); - compileOptions |= SH_LINE_DIRECTIVES; - } -#endif - - int result; - if (sourcePath.empty()) - { - const char* sourceStrings[] = - { - source.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); - } - else - { - const char* sourceStrings[] = - { - sourcePath.c_str(), - source.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); - } - - mShaderVersion = ShGetShaderVersion(compiler); - - if (result) - { - mTranslatedSource = ShGetObjectCode(compiler); - -#ifdef _DEBUG - // Prefix hlsl shader with commented out glsl shader - // Useful in diagnostics tools like pix which capture the hlsl shaders - std::ostringstream hlslStream; - hlslStream << "// GLSL\n"; - hlslStream << "//\n"; - - size_t curPos = 0; - while (curPos != std::string::npos) - { - size_t nextLine = source.find("\n", curPos); - size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); - - hlslStream << "// " << source.substr(curPos, len); - - curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); - } - hlslStream << "\n\n"; - hlslStream << mTranslatedSource; - mTranslatedSource = hlslStream.str(); -#endif - - mUniforms = *GetShaderVariables(ShGetUniforms(compiler)); - - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = mUniforms[uniformIndex]; - - if (uniform.staticUse) - { - unsigned int index = static_cast(-1); - bool getUniformRegisterResult = ShGetUniformRegister(compiler, uniform.name, &index); - UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult); - ASSERT(getUniformRegisterResult); - - mUniformRegisterMap[uniform.name] = index; - } - } - - mInterfaceBlocks = *GetShaderVariables(ShGetInterfaceBlocks(compiler)); - - for (size_t blockIndex = 0; blockIndex < mInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = mInterfaceBlocks[blockIndex]; - - if (interfaceBlock.staticUse) - { - unsigned int index = static_cast(-1); - bool blockRegisterResult = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index); - UNUSED_ASSERTION_VARIABLE(blockRegisterResult); - ASSERT(blockRegisterResult); - - mInterfaceBlockRegisterMap[interfaceBlock.name] = index; - } - } - } - else - { - mInfoLog = ShGetInfoLog(compiler); - - TRACE("\n%s", mInfoLog.c_str()); - } -} - void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const { if (mUsesDiscardRewriting) @@ -289,28 +100,6 @@ void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const } } -// true if varying x has a higher priority in packing than y -bool ShaderD3D::compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y) -{ - if (x.type == y.type) - { - return x.arraySize > y.arraySize; - } - - // Special case for handling structs: we sort these to the end of the list - if (x.type == GL_STRUCT_ANGLEX) - { - return false; - } - - if (y.type == GL_STRUCT_ANGLEX) - { - return true; - } - - return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type); -} - unsigned int ShaderD3D::getUniformRegister(const std::string &uniformName) const { ASSERT(mUniformRegisterMap.count(uniformName) > 0); @@ -323,66 +112,92 @@ unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName) return mInterfaceBlockRegisterMap.find(blockName)->second; } -GLenum ShaderD3D::getShaderType() const -{ - return mShaderType; -} - ShShaderOutput ShaderD3D::getCompilerOutputType() const { return mCompilerOutputType; } -bool ShaderD3D::compile(gl::Compiler *compiler, const std::string &source) +int ShaderD3D::prepareSourceAndReturnOptions(std::stringstream *shaderSourceStream, + std::string *sourcePath) { uncompile(); - CompilerD3D *compilerD3D = CompilerD3D::makeCompilerD3D(compiler->getImplementation()); - ShHandle compilerHandle = compilerD3D->getCompilerHandle(mShaderType); + int additionalOptions = 0; - mCompilerOutputType = ShGetShaderOutputType(compilerHandle); + const std::string &source = mData.getSource(); - compileToHLSL(compilerHandle, source); - - if (mShaderType == GL_VERTEX_SHADER) +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + if (gl::DebugAnnotationsActive()) { - parseAttributes(compilerHandle); + *sourcePath = getTempPath(); + writeFile(sourcePath->c_str(), source.c_str(), source.length()); + additionalOptions |= SH_LINE_DIRECTIVES | SH_SOURCE_PATH; } +#endif + + *shaderSourceStream << source; + return additionalOptions; +} + +bool ShaderD3D::postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) +{ + // TODO(jmadill): We shouldn't need to cache this. + mCompilerOutputType = compiler->getShaderOutputType(); - parseVaryings(compilerHandle); + const std::string &translatedSource = mData.getTranslatedSource(); - if (mShaderType == GL_FRAGMENT_SHADER) - { - std::sort(mVaryings.begin(), mVaryings.end(), compareVarying); + mUsesMultipleRenderTargets = translatedSource.find("GL_USES_MRT") != std::string::npos; + mUsesFragColor = translatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos; + mUsesFragData = translatedSource.find("GL_USES_FRAG_DATA") != std::string::npos; + mUsesFragCoord = translatedSource.find("GL_USES_FRAG_COORD") != std::string::npos; + mUsesFrontFacing = translatedSource.find("GL_USES_FRONT_FACING") != std::string::npos; + mUsesPointSize = translatedSource.find("GL_USES_POINT_SIZE") != std::string::npos; + mUsesPointCoord = translatedSource.find("GL_USES_POINT_COORD") != std::string::npos; + mUsesDepthRange = translatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos; + mUsesFragDepth = translatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos; + mUsesDiscardRewriting = + translatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos; + mUsesNestedBreak = translatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos; + mUsesDeferredInit = translatedSource.find("ANGLE_USES_DEFERRED_INIT") != std::string::npos; + mRequiresIEEEStrictCompiling = + translatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos; - const std::string &hlsl = getTranslatedSource(); - if (!hlsl.empty()) + ShHandle compilerHandle = compiler->getCompilerHandle(mData.getShaderType()); + + for (const sh::Uniform &uniform : mData.getUniforms()) + { + if (uniform.staticUse && !uniform.isBuiltIn()) { - mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compilerHandle)); - FilterInactiveVariables(&mActiveOutputVariables); + unsigned int index = static_cast(-1); + bool getUniformRegisterResult = + ShGetUniformRegister(compilerHandle, uniform.name, &index); + UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult); + ASSERT(getUniformRegisterResult); + + mUniformRegisterMap[uniform.name] = index; } } -#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED - mDebugInfo += std::string("// ") + GetShaderTypeString(mShaderType) + " SHADER BEGIN\n"; - mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n"; - mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + getTranslatedSource() + "\n// INITIAL HLSL END\n\n\n"; - // Successive steps will append more info -#else - mDebugInfo += getTranslatedSource(); -#endif - - return !getTranslatedSource().empty(); -} - -void ShaderD3D::parseAttributes(ShHandle compiler) -{ - const std::string &hlsl = getTranslatedSource(); - if (!hlsl.empty()) + for (const sh::InterfaceBlock &interfaceBlock : mData.getInterfaceBlocks()) { - mActiveAttributes = *GetShaderVariables(ShGetAttributes(compiler)); - FilterInactiveVariables(&mActiveAttributes); + if (interfaceBlock.staticUse) + { + unsigned int index = static_cast(-1); + bool blockRegisterResult = + ShGetInterfaceBlockRegister(compilerHandle, interfaceBlock.name, &index); + UNUSED_ASSERTION_VARIABLE(blockRegisterResult); + ASSERT(blockRegisterResult); + + mInterfaceBlockRegisterMap[interfaceBlock.name] = index; + } } -} + mDebugInfo += + std::string("// ") + GetShaderTypeString(mData.getShaderType()) + " SHADER BEGIN\n"; + mDebugInfo += "\n// GLSL BEGIN\n\n" + mData.getSource() + "\n\n// GLSL END\n\n\n"; + mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + translatedSource + "\n// INITIAL HLSL END\n\n\n"; + // Successive steps will append more info + return true; } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h index d0237b5985..47a73dc27b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h @@ -10,8 +10,6 @@ #define LIBANGLE_RENDERER_D3D_SHADERD3D_H_ #include "libANGLE/renderer/ShaderImpl.h" -#include "libANGLE/renderer/Workarounds.h" -#include "libANGLE/Shader.h" #include @@ -19,51 +17,42 @@ namespace rx { class DynamicHLSL; class RendererD3D; +struct D3DCompilerWorkarounds; class ShaderD3D : public ShaderImpl { - friend class DynamicHLSL; - public: - ShaderD3D(GLenum type); + ShaderD3D(const gl::Shader::Data &data); virtual ~ShaderD3D(); - static ShaderD3D *makeShaderD3D(ShaderImpl *impl); - static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl); - // ShaderImpl implementation - virtual std::string getDebugInfo() const; + int prepareSourceAndReturnOptions(std::stringstream *sourceStream, + std::string *sourcePath) override; + bool postTranslateCompile(gl::Compiler *compiler, std::string *infoLog) override; + std::string getDebugInfo() const override; // D3D-specific methods - virtual void uncompile(); - void resetVaryingsRegisterAssignment(); + void uncompile(); unsigned int getUniformRegister(const std::string &uniformName) const; unsigned int getInterfaceBlockRegister(const std::string &blockName) const; - void appendDebugInfo(const std::string &info) { mDebugInfo += info; } + void appendDebugInfo(const std::string &info) const { mDebugInfo += info; } void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const; - int getShaderVersion() const { return mShaderVersion; } - bool usesDepthRange() const { return mUsesDepthRange; } + + bool usesMultipleRenderTargets() const { return mUsesMultipleRenderTargets; } + bool usesFragColor() const { return mUsesFragColor; } + bool usesFragData() const { return mUsesFragData; } + bool usesFragCoord() const { return mUsesFragCoord; } + bool usesFrontFacing() const { return mUsesFrontFacing; } bool usesPointSize() const { return mUsesPointSize; } + bool usesPointCoord() const { return mUsesPointCoord; } + bool usesDepthRange() const { return mUsesDepthRange; } + bool usesFragDepth() const { return mUsesFragDepth; } bool usesDeferredInit() const { return mUsesDeferredInit; } - GLenum getShaderType() const; ShShaderOutput getCompilerOutputType() const; - virtual bool compile(gl::Compiler *compiler, const std::string &source); - private: - void compileToHLSL(ShHandle compiler, const std::string &source); - void parseVaryings(ShHandle compiler); - - void parseAttributes(ShHandle compiler); - - static bool compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y); - - GLenum mShaderType; - - int mShaderVersion; - bool mUsesMultipleRenderTargets; bool mUsesFragColor; bool mUsesFragData; @@ -79,11 +68,10 @@ class ShaderD3D : public ShaderImpl bool mRequiresIEEEStrictCompiling; ShShaderOutput mCompilerOutputType; - std::string mDebugInfo; + mutable std::string mDebugInfo; std::map mUniformRegisterMap; std::map mInterfaceBlockRegisterMap; }; - } -#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_ +#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp index 84515f4c6c..3d27548504 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp @@ -11,6 +11,7 @@ #include "libANGLE/Display.h" #include "libANGLE/Surface.h" #include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/RenderTargetD3D.h" #include "libANGLE/renderer/d3d/SwapChainD3D.h" #include @@ -23,38 +24,53 @@ namespace rx SurfaceD3D *SurfaceD3D::createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle, EGLint width, EGLint height) { - return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, shareHandle, NULL); + return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, 0, EGL_FALSE, + shareHandle, NULL); } -SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLNativeWindowType window, - EGLint fixedSize, EGLint width, EGLint height) +SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLNativeWindowType window, + EGLint fixedSize, + EGLint directComposition, + EGLint width, + EGLint height, + EGLint orientation) { - return new SurfaceD3D(renderer, display, config, width, height, fixedSize, static_cast(0), window); + return new SurfaceD3D(renderer, display, config, width, height, fixedSize, orientation, + directComposition, static_cast(0), window); } -SurfaceD3D::SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height, EGLint fixedSize, - EGLClientBuffer shareHandle, EGLNativeWindowType window) +SurfaceD3D::SurfaceD3D(RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLint width, + EGLint height, + EGLint fixedSize, + EGLint orientation, + EGLint directComposition, + EGLClientBuffer shareHandle, + EGLNativeWindowType window) : SurfaceImpl(), mRenderer(renderer), mDisplay(display), mFixedSize(fixedSize == EGL_TRUE), + mOrientation(orientation), mRenderTargetFormat(config->renderTargetFormat), mDepthStencilFormat(config->depthStencilFormat), mSwapChain(nullptr), mSwapIntervalDirty(true), - mWindowSubclassed(false), - mNativeWindow(window), + mNativeWindow(window, config, directComposition == EGL_TRUE), mWidth(width), mHeight(height), mSwapInterval(1), - mShareHandle(reinterpret_cast(shareHandle)) + mShareHandle(reinterpret_cast(shareHandle)) { - subclassWindow(); } SurfaceD3D::~SurfaceD3D() { - unsubclassWindow(); releaseSwapChain(); } @@ -82,7 +98,12 @@ egl::Error SurfaceD3D::initialize() return egl::Error(EGL_SUCCESS); } -egl::Error SurfaceD3D::bindTexImage(EGLint) +FramebufferImpl *SurfaceD3D::createDefaultFramebuffer(const gl::Framebuffer::Data &data) +{ + return mRenderer->createFramebuffer(data); +} + +egl::Error SurfaceD3D::bindTexImage(gl::Texture *, EGLint) { return egl::Error(EGL_SUCCESS); } @@ -119,7 +140,8 @@ egl::Error SurfaceD3D::resetSwapChain() height = mHeight; } - mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, mDepthStencilFormat); + mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, + mDepthStencilFormat, mOrientation); if (!mSwapChain) { return egl::Error(EGL_BAD_ALLOC); @@ -201,22 +223,19 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) } #endif - if (width == 0 || height == 0) + if (width != 0 && height != 0) { - checkForOutOfDateSwapChain(); - return egl::Error(EGL_SUCCESS); - } + EGLint status = mSwapChain->swapRect(x, y, width, height); - EGLint status = mSwapChain->swapRect(x, y, width, height); - - if (status == EGL_CONTEXT_LOST) - { - mRenderer->notifyDeviceLost(); - return egl::Error(status); - } - else if (status != EGL_SUCCESS) - { - return egl::Error(status); + if (status == EGL_CONTEXT_LOST) + { + mRenderer->notifyDeviceLost(); + return egl::Error(status); + } + else if (status != EGL_SUCCESS) + { + return egl::Error(status); + } } checkForOutOfDateSwapChain(); @@ -224,90 +243,6 @@ egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return egl::Error(EGL_SUCCESS); } -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) -#define kSurfaceProperty _TEXT("Egl::SurfaceOwner") -#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") - -static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) -{ - if (message == WM_SIZE) - { - SurfaceD3D* surf = reinterpret_cast(GetProp(hwnd, kSurfaceProperty)); - if(surf) - { - surf->checkForOutOfDateSwapChain(); - } - } - WNDPROC prevWndFunc = reinterpret_cast(GetProp(hwnd, kParentWndProc)); - return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam); -} -#endif - -void SurfaceD3D::subclassWindow() -{ -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - HWND window = mNativeWindow.getNativeWindow(); - if (!window) - { - return; - } - - DWORD processId; - DWORD threadId = GetWindowThreadProcessId(window, &processId); - if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId()) - { - return; - } - - SetLastError(0); - LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast(SurfaceWindowProc)); - if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS) - { - mWindowSubclassed = false; - return; - } - - SetProp(window, kSurfaceProperty, reinterpret_cast(this)); - SetProp(window, kParentWndProc, reinterpret_cast(oldWndProc)); - mWindowSubclassed = true; -#endif -} - -void SurfaceD3D::unsubclassWindow() -{ - if (!mWindowSubclassed) - { - return; - } - -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) - HWND window = mNativeWindow.getNativeWindow(); - if (!window) - { - return; - } - - // un-subclass - LONG_PTR parentWndFunc = reinterpret_cast(GetProp(window, kParentWndProc)); - - // Check the windowproc is still SurfaceWindowProc. - // If this assert fails, then it is likely the application has subclassed the - // hwnd as well and did not unsubclass before destroying its EGL context. The - // application should be modified to either subclass before initializing the - // EGL context, or to unsubclass before destroying the EGL context. - if(parentWndFunc) - { - LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc); - UNUSED_ASSERTION_VARIABLE(prevWndFunc); - ASSERT(prevWndFunc == reinterpret_cast(SurfaceWindowProc)); - } - - RemoveProp(window, kSurfaceProperty); - RemoveProp(window, kParentWndProc); -#endif - mWindowSubclassed = false; -} - bool SurfaceD3D::checkForOutOfDateSwapChain() { RECT client; @@ -386,14 +321,42 @@ EGLint SurfaceD3D::isPostSubBufferSupported() const return EGL_TRUE; } +EGLint SurfaceD3D::getSwapBehavior() const +{ + return EGL_BUFFER_PRESERVED; +} + egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value) { - ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || attribute == EGL_DEVICE_EXT); if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE) + { *value = mSwapChain->getShareHandle(); + } + else if (attribute == EGL_DXGI_KEYED_MUTEX_ANGLE) + { + *value = mSwapChain->getKeyedMutex(); + } else if (attribute == EGL_DEVICE_EXT) + { *value = mSwapChain->getDevice(); + } + else UNREACHABLE(); + return egl::Error(EGL_SUCCESS); } +gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) +{ + if (target.binding() == GL_BACK) + { + *rtOut = mSwapChain->getColorRenderTarget(); + } + else + { + *rtOut = mSwapChain->getDepthStencilRenderTarget(); + } + return gl::Error(GL_NO_ERROR); +} + } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h index 070b7cdbc4..b925bfc8cc 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h @@ -25,19 +25,27 @@ class RendererD3D; class SurfaceD3D : public SurfaceImpl { public: - static SurfaceD3D *createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, - EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height); + static SurfaceD3D *createFromWindow(RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLNativeWindowType window, + EGLint fixedSize, + EGLint directComposition, + EGLint width, + EGLint height, + EGLint orientation); static SurfaceD3D *createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle, EGLint width, EGLint height); ~SurfaceD3D() override; void releaseSwapChain(); egl::Error initialize() override; + FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override; egl::Error swap() override; egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override; egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override; - egl::Error bindTexImage(EGLint buffer) override; + egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override; egl::Error releaseTexImage(EGLint buffer) override; void setSwapInterval(EGLint interval) override; @@ -45,6 +53,7 @@ class SurfaceD3D : public SurfaceImpl EGLint getHeight() const override; EGLint isPostSubBufferSupported() const override; + EGLint getSwapBehavior() const override; // D3D implementations SwapChainD3D *getSwapChain() const; @@ -54,28 +63,36 @@ class SurfaceD3D : public SurfaceImpl // Returns true if swapchain changed due to resize or interval update bool checkForOutOfDateSwapChain(); + gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) override; + private: - SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height, - EGLint fixedSize, EGLClientBuffer shareHandle, EGLNativeWindowType window); + SurfaceD3D(RendererD3D *renderer, + egl::Display *display, + const egl::Config *config, + EGLint width, + EGLint height, + EGLint fixedSize, + EGLint orientation, + EGLint directComposition, + EGLClientBuffer shareHandle, + EGLNativeWindowType window); egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height); egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight); egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight); - void subclassWindow(); - void unsubclassWindow(); - RendererD3D *mRenderer; egl::Display *mDisplay; bool mFixedSize; + GLint mOrientation; GLenum mRenderTargetFormat; GLenum mDepthStencilFormat; SwapChainD3D *mSwapChain; bool mSwapIntervalDirty; - bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. EGLint mWidth; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h index da36e52ea7..171cab54dd 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h @@ -31,7 +31,7 @@ class SwapChainD3D : angle::NonCopyable { public: SwapChainD3D(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) - : mNativeWindow(nativeWindow), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat) + : mNativeWindow(nativeWindow), mOffscreenRenderTargetFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat), mShareHandle(shareHandle) { } @@ -46,14 +46,15 @@ class SwapChainD3D : angle::NonCopyable virtual RenderTargetD3D *getColorRenderTarget() = 0; virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0; - GLenum GetBackBufferInternalFormat() const { return mBackBufferFormat; } + GLenum GetRenderTargetInternalFormat() const { return mOffscreenRenderTargetFormat; } GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; } HANDLE getShareHandle() { return mShareHandle; } + virtual void *getKeyedMutex() = 0; protected: rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for. - const GLenum mBackBufferFormat; + const GLenum mOffscreenRenderTargetFormat; const GLenum mDepthBufferFormat; HANDLE mShareHandle; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp index 78b03f2283..430576b318 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp @@ -13,11 +13,13 @@ #include "libANGLE/Buffer.h" #include "libANGLE/Config.h" #include "libANGLE/Framebuffer.h" +#include "libANGLE/Image.h" #include "libANGLE/Surface.h" #include "libANGLE/Texture.h" #include "libANGLE/formatutils.h" #include "libANGLE/renderer/BufferImpl.h" #include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" #include "libANGLE/renderer/d3d/ImageD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/RenderTargetD3D.h" @@ -157,16 +159,12 @@ bool TextureD3D::shouldUseSetData(const ImageD3D *image) const return (mTexStorage && !internalFormat.compressed); } -gl::Error TextureD3D::setImage(const gl::ImageIndex &index, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixels, - ptrdiff_t layerOffset) +gl::Error TextureD3D::setImageImpl(const gl::ImageIndex &index, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels, + ptrdiff_t layerOffset) { - if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); - } - ImageD3D *image = getImage(index); ASSERT(image); @@ -185,7 +183,7 @@ gl::Error TextureD3D::setImage(const gl::ImageIndex &index, GLenum type, return error; } - if (pixelData != NULL) + if (pixelData != nullptr) { if (shouldUseSetData(image)) { @@ -247,15 +245,11 @@ gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D::setCompressedImage(const gl::ImageIndex &index, const gl::PixelUnpackState &unpack, - const uint8_t *pixels, ptrdiff_t layerOffset) +gl::Error TextureD3D::setCompressedImageImpl(const gl::ImageIndex &index, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels, + ptrdiff_t layerOffset) { - if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); - } - // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. const uint8_t *pixelData = NULL; @@ -287,12 +281,6 @@ gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl:: const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset) { - if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); - } - const uint8_t *pixelData = NULL; gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData); if (error.isError()) @@ -325,6 +313,15 @@ bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum siz gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea, GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget) { + if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || + unpack.skipImages != 0) + { + // TODO(jmadill): additional unpack parameters + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, + "Unimplemented pixel store parameters in fastUnpackPixels"); + } + // No-op if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) { @@ -337,7 +334,7 @@ gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uintptr_t offset = reinterpret_cast(pixels); - gl::Error error = mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); + gl::Error error = mRenderer->fastCopyBufferToTexture(unpack, static_cast(offset), destRenderTarget, sizedInternalFormat, type, destArea); if (error.isError()) { return error; @@ -376,7 +373,7 @@ ImageD3D *TextureD3D::getBaseLevelImage() const return getImage(getImageIndex(0, 0)); } -gl::Error TextureD3D::generateMipmaps() +gl::Error TextureD3D::generateMipmaps(const gl::TextureState &textureState) { GLint mipCount = mipLevels(); @@ -405,6 +402,38 @@ gl::Error TextureD3D::generateMipmaps() // Set up proper mipmap chain in our Image array. initMipmapsImages(); + if (mTexStorage && mTexStorage->supportsNativeMipmapFunction()) + { + gl::Error error = updateStorage(); + if (error.isError()) + { + return error; + } + + // Generate the mipmap chain using the ad-hoc DirectX function. + error = mRenderer->generateMipmapsUsingD3D(mTexStorage, textureState); + if (error.isError()) + { + return error; + } + } + else + { + // Generate the mipmap chain, one level at a time. + gl::Error error = generateMipmapsUsingImages(); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureD3D::generateMipmapsUsingImages() +{ + GLint mipCount = mipLevels(); + // We know that all layers have the same dimension, for the texture to be complete GLint layerCount = static_cast(getLayerCount(0)); @@ -421,9 +450,7 @@ gl::Error TextureD3D::generateMipmaps() gl::ImageIndex srcIndex = getImageIndex(0, layer); ImageD3D *image = getImage(srcIndex); - gl::Box area(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth()); - gl::Offset offset(0, 0, 0); - gl::Error error = image->copy(offset, area, srcIndex, mTexStorage); + gl::Error error = image->copyFromTexStorage(srcIndex, mTexStorage); if (error.isError()) { return error; @@ -576,9 +603,19 @@ gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box &r return gl::Error(GL_NO_ERROR); } +gl::Error TextureD3D::getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) +{ + RenderTargetD3D *rtD3D = nullptr; + gl::Error error = getRenderTarget(target.textureIndex(), &rtD3D); + *rtOut = static_cast(rtD3D); + return error; +} + TextureD3D_2D::TextureD3D_2D(RendererD3D *renderer) : TextureD3D(renderer) { + mEGLImageTarget = false; for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) { mImageArray[i] = renderer->createImage(); @@ -648,16 +685,23 @@ bool TextureD3D_2D::isDepth(GLint level) const return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -gl::Error TextureD3D_2D::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) +gl::Error TextureD3D_2D::setImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D && size.depth == 1); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); bool fastUnpacked = false; + GLint level = static_cast(imageLevel); - redefineImage(level, sizedInternalFormat, size); + redefineImage(level, sizedInternalFormat, size, false); gl::ImageIndex index = gl::ImageIndex::Make2D(level); @@ -688,7 +732,7 @@ gl::Error TextureD3D_2D::setImage(GLenum target, size_t level, GLenum internalFo if (!fastUnpacked) { - gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, 0); + gl::Error error = setImageImpl(index, type, unpack, pixels, 0); if (error.isError()) { return error; @@ -698,17 +742,17 @@ gl::Error TextureD3D_2D::setImage(GLenum target, size_t level, GLenum internalFo return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2D::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) +gl::Error TextureD3D_2D::setSubImage(GLenum target, + size_t imageLevel, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0); - if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0) - { - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state"); - } - + GLint level = static_cast(imageLevel); gl::ImageIndex index = gl::ImageIndex::Make2D(level); if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) { @@ -729,24 +773,29 @@ gl::Error TextureD3D_2D::setSubImage(GLenum target, size_t level, const gl::Box } } - -gl::Error TextureD3D_2D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) +gl::Error TextureD3D_2D::setCompressedImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D && size.depth == 1); + GLint level = static_cast(imageLevel); // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, internalFormat, size); + redefineImage(level, internalFormat, size, false); - return TextureD3D::setCompressedImage(gl::ImageIndex::Make2D(level), unpack, pixels, 0); + return setCompressedImageImpl(gl::ImageIndex::Make2D(level), unpack, pixels, 0); } gl::Error TextureD3D_2D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0); - gl::ImageIndex index = gl::ImageIndex::Make2D(level); + gl::ImageIndex index = gl::ImageIndex::Make2D(static_cast(level)); gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); if (error.isError()) { @@ -756,13 +805,18 @@ gl::Error TextureD3D_2D::setCompressedSubImage(GLenum target, size_t level, cons return commitRegion(index, area); } -gl::Error TextureD3D_2D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, +gl::Error TextureD3D_2D::copyImage(GLenum target, + size_t imageLevel, + const gl::Rectangle &sourceArea, + GLenum internalFormat, const gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_2D); + GLint level = static_cast(imageLevel); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE); - redefineImage(level, sizedInternalFormat, gl::Extents(sourceArea.width, sourceArea.height, 1)); + redefineImage(level, sizedInternalFormat, gl::Extents(sourceArea.width, sourceArea.height, 1), + false); gl::ImageIndex index = gl::ImageIndex::Make2D(level); gl::Offset destOffset(0, 0, 0); @@ -771,7 +825,7 @@ gl::Error TextureD3D_2D::copyImage(GLenum target, size_t level, const gl::Rectan // so we should use the non-rendering copy path. if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source); + gl::Error error = mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -802,7 +856,10 @@ gl::Error TextureD3D_2D::copyImage(GLenum target, size_t level, const gl::Rectan return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2D::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, +gl::Error TextureD3D_2D::copySubImage(GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, const gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_2D && destOffset.z == 0); @@ -810,13 +867,14 @@ gl::Error TextureD3D_2D::copySubImage(GLenum target, size_t level, const gl::Off // can only make our texture storage to a render target if level 0 is defined (with a width & height) and // the current level we're copying to is defined (with appropriate format, width & height) + GLint level = static_cast(imageLevel); gl::ImageIndex index = gl::ImageIndex::Make2D(level); // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, // so we should use the non-rendering copy path. if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source); + gl::Error error = mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -862,17 +920,18 @@ gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum interna gl::Extents levelSize(std::max(1, size.width >> level), std::max(1, size.height >> level), 1); - mImageArray[level]->redefine(GL_TEXTURE_2D, internalFormat, levelSize, true); + redefineImage(level, internalFormat, levelSize, true); } - for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - mImageArray[level]->redefine(GL_TEXTURE_2D, GL_NONE, gl::Extents(0, 0, 0), true); + redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true); } // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, size.width, size.height, levels, false); + TextureStorage *storage = mRenderer->createTextureStorage2D( + internalFormat, renderTarget, size.width, size.height, static_cast(levels), false); gl::Error error = setCompleteTexStorage(storage); if (error.isError()) @@ -898,7 +957,7 @@ void TextureD3D_2D::bindTexImage(egl::Surface *surface) GLenum internalformat = surface->getConfig()->renderTargetFormat; gl::Extents size(surface->getWidth(), surface->getHeight(), 1); - mImageArray[0]->redefine(GL_TEXTURE_2D, internalformat, size, true); + redefineImage(0, internalformat, size, true); if (mTexStorage) { @@ -909,6 +968,7 @@ void TextureD3D_2D::bindTexImage(egl::Surface *surface) ASSERT(surfaceD3D); mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain()); + mEGLImageTarget = false; mDirtyImages = true; } @@ -922,8 +982,32 @@ void TextureD3D_2D::releaseTexImage() for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mImageArray[i]->redefine(GL_TEXTURE_2D, GL_NONE, gl::Extents(0, 0, 0), true); + redefineImage(i, GL_NONE, gl::Extents(0, 0, 1), true); + } +} + +gl::Error TextureD3D_2D::setEGLImageTarget(GLenum target, egl::Image *image) +{ + EGLImageD3D *eglImaged3d = GetImplAs(image); + + // Set the properties of the base mip level from the EGL image + GLenum internalformat = image->getInternalFormat(); + gl::Extents size(static_cast(image->getWidth()), static_cast(image->getHeight()), 1); + redefineImage(0, internalformat, size, true); + + // Clear all other images. + for (size_t level = 1; level < ArraySize(mImageArray); level++) + { + redefineImage(level, GL_NONE, gl::Extents(0, 0, 1), true); } + + SafeDelete(mTexStorage); + mImageArray[0]->markClean(); + + mTexStorage = mRenderer->createTextureStorageEGLImage(eglImaged3d); + mEGLImageTarget = true; + + return gl::Error(GL_NO_ERROR); } void TextureD3D_2D::initMipmapsImages() @@ -936,16 +1020,10 @@ void TextureD3D_2D::initMipmapsImages() std::max(getBaseLevelHeight() >> level, 1), 1); - redefineImage(level, getBaseLevelInternalFormat(), levelSize); + redefineImage(level, getBaseLevelInternalFormat(), levelSize, false); } } -unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index) -{ - ASSERT(!index.hasLayer()); - return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); -} - gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); @@ -1152,7 +1230,10 @@ gl::Error TextureD3D_2D::updateStorageLevel(int level) return gl::Error(GL_NO_ERROR); } -void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size) +void TextureD3D_2D::redefineImage(size_t level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease) { ASSERT(size.depth == 1); @@ -1161,18 +1242,26 @@ void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, const gl:: const int storageHeight = std::max(1, getBaseLevelHeight() >> level); const GLenum storageFormat = getBaseLevelInternalFormat(); - mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, false); + mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, forceRelease); if (mTexStorage) { - const int storageLevels = mTexStorage->getLevelCount(); + const size_t storageLevels = mTexStorage->getLevelCount(); + + // If the storage was from an EGL image, copy it back into local images to preserve it + // while orphaning + if (level != 0 && mEGLImageTarget) + { + // TODO(jmadill): Don't discard error. + mImageArray[0]->copyFromTexStorage(gl::ImageIndex::Make2D(0), mTexStorage); + } if ((level >= storageLevels && storageLevels != 0) || size.width != storageWidth || size.height != storageHeight || internalformat != storageFormat) // Discard mismatched storage { - for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { mImageArray[i]->markDirty(); } @@ -1181,6 +1270,9 @@ void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, const gl:: mDirtyImages = true; } } + + // Can't be an EGL image target after being redefined + mEGLImageTarget = false; } gl::ImageIndexIterator TextureD3D_2D::imageIterator() const @@ -1261,17 +1353,23 @@ bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; } +gl::Error TextureD3D_Cube::setEGLImageTarget(GLenum target, egl::Image *image) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + gl::Error TextureD3D_Cube::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixels) { ASSERT(size.depth == 1); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast(level)); - redefineImage(index.layerIndex, level, sizedInternalFormat, size); + redefineImage(index.layerIndex, static_cast(level), sizedInternalFormat, size); - return TextureD3D::setImage(index, type, unpack, pixels, 0); + return setImageImpl(index, type, unpack, pixels, 0); } gl::Error TextureD3D_Cube::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, @@ -1279,30 +1377,30 @@ gl::Error TextureD3D_Cube::setSubImage(GLenum target, size_t level, const gl::Bo { ASSERT(area.depth == 1 && area.z == 0); - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast(level)); return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0); } gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) { ASSERT(size.depth == 1); // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); - redefineImage(faceIndex, level, internalFormat, size); + redefineImage(static_cast(faceIndex), static_cast(level), internalFormat, size); - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - return TextureD3D::setCompressedImage(index, unpack, pixels, 0); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast(level)); + return setCompressedImageImpl(index, unpack, pixels, 0); } gl::Error TextureD3D_Cube::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) { ASSERT(area.depth == 1 && area.z == 0); - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, static_cast(level)); gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); if (error.isError()) @@ -1313,14 +1411,19 @@ gl::Error TextureD3D_Cube::setCompressedSubImage(GLenum target, size_t level, co return commitRegion(index, area); } -gl::Error TextureD3D_Cube::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, +gl::Error TextureD3D_Cube::copyImage(GLenum target, + size_t imageLevel, + const gl::Rectangle &sourceArea, + GLenum internalFormat, const gl::Framebuffer *source) { - size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); + int faceIndex = static_cast(gl::CubeMapTextureTargetToLayerIndex(target)); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE); + GLint level = static_cast(imageLevel); + gl::Extents size(sourceArea.width, sourceArea.height, 1); - redefineImage(faceIndex, level, sizedInternalFormat, size); + redefineImage(static_cast(faceIndex), level, sizedInternalFormat, size); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); gl::Offset destOffset(0, 0, 0); @@ -1329,7 +1432,8 @@ gl::Error TextureD3D_Cube::copyImage(GLenum target, size_t level, const gl::Rect // so we should use the non-rendering copy path. if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - gl::Error error = mImageArray[faceIndex][level]->copy(destOffset, sourceArea, source); + gl::Error error = + mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -1362,18 +1466,23 @@ gl::Error TextureD3D_Cube::copyImage(GLenum target, size_t level, const gl::Rect return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_Cube::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, +gl::Error TextureD3D_Cube::copySubImage(GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, const gl::Framebuffer *source) { - size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target); + int faceIndex = static_cast(gl::CubeMapTextureTargetToLayerIndex(target)); + GLint level = static_cast(imageLevel); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders, // so we should use the non-rendering copy path. if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - gl::Error error = mImageArray[faceIndex][level]->copy(destOffset, sourceArea, source); + gl::Error error = + mImageArray[faceIndex][level]->copyFromFramebuffer(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -1423,7 +1532,7 @@ gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum inter } } - for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { for (int faceIndex = 0; faceIndex < 6; faceIndex++) { @@ -1434,7 +1543,8 @@ gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum inter // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width, levels, false); + TextureStorage *storage = mRenderer->createTextureStorageCube( + internalFormat, renderTarget, size.width, static_cast(levels), false); gl::Error error = setCompleteTexStorage(storage); if (error.isError()) @@ -1508,11 +1618,6 @@ void TextureD3D_Cube::initMipmapsImages() } } -unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index) -{ - return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); -} - gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { ASSERT(gl::IsCubeMapTextureTarget(index.type)); @@ -1851,12 +1956,25 @@ bool TextureD3D_3D::isDepth(GLint level) const return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -gl::Error TextureD3D_3D::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) +gl::Error TextureD3D_3D::setEGLImageTarget(GLenum target, egl::Image *image) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_3D::setImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_3D); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + GLint level = static_cast(imageLevel); redefineImage(level, sizedInternalFormat, size); bool fastUnpacked = false; @@ -1890,7 +2008,7 @@ gl::Error TextureD3D_3D::setImage(GLenum target, size_t level, GLenum internalFo if (!fastUnpacked) { - gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, 0); + gl::Error error = setImageImpl(index, type, unpack, pixels, 0); if (error.isError()) { return error; @@ -1900,11 +2018,17 @@ gl::Error TextureD3D_3D::setImage(GLenum target, size_t level, GLenum internalFo return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_3D::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) +gl::Error TextureD3D_3D::setSubImage(GLenum target, + size_t imageLevel, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_3D); + GLint level = static_cast(imageLevel); gl::ImageIndex index = gl::ImageIndex::Make3D(level); // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer @@ -1927,24 +2051,30 @@ gl::Error TextureD3D_3D::setSubImage(GLenum target, size_t level, const gl::Box } } -gl::Error TextureD3D_3D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) +gl::Error TextureD3D_3D::setCompressedImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_3D); + GLint level = static_cast(imageLevel); // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly redefineImage(level, internalFormat, size); gl::ImageIndex index = gl::ImageIndex::Make3D(level); - return TextureD3D::setCompressedImage(index, unpack, pixels, 0); + return setCompressedImageImpl(index, unpack, pixels, 0); } gl::Error TextureD3D_3D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_3D); - gl::ImageIndex index = gl::ImageIndex::Make3D(level); + gl::ImageIndex index = gl::ImageIndex::Make3D(static_cast(level)); gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0); if (error.isError()) { @@ -1961,16 +2091,20 @@ gl::Error TextureD3D_3D::copyImage(GLenum target, size_t level, const gl::Rectan return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented."); } -gl::Error TextureD3D_3D::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, +gl::Error TextureD3D_3D::copySubImage(GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, const gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_3D); + GLint level = static_cast(imageLevel); gl::ImageIndex index = gl::ImageIndex::Make3D(level); if (canCreateRenderTargetForImage(index)) { - gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source); + gl::Error error = mImageArray[level]->copyFromFramebuffer(destOffset, sourceArea, source); if (error.isError()) { return error; @@ -2019,14 +2153,16 @@ gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum interna mImageArray[level]->redefine(GL_TEXTURE_3D, internalFormat, levelSize, true); } - for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + for (size_t level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { mImageArray[level]->redefine(GL_TEXTURE_3D, GL_NONE, gl::Extents(0, 0, 0), true); } // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height, size.depth, levels); + TextureStorage *storage = + mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height, + size.depth, static_cast(levels)); gl::Error error = setCompleteTexStorage(storage); if (error.isError()) @@ -2071,11 +2207,6 @@ void TextureD3D_3D::initMipmapsImages() } } -unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index) -{ - return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); -} - gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { // ensure the underlying texture is created @@ -2384,23 +2515,37 @@ bool TextureD3D_2DArray::isDepth(GLint level) const return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -gl::Error TextureD3D_2DArray::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) +gl::Error TextureD3D_2DArray::setEGLImageTarget(GLenum target, egl::Image *image) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureD3D_2DArray::setImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + GLint level = static_cast(imageLevel); redefineImage(level, sizedInternalFormat, size); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment, unpack.rowLength); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch( + type, size.width, size.height, unpack.alignment, unpack.rowLength, unpack.imageHeight); for (int i = 0; i < size.depth; i++) { const ptrdiff_t layerOffset = (inputDepthPitch * i); gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); - gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, layerOffset); + gl::Error error = setImageImpl(index, type, unpack, pixels, layerOffset); if (error.isError()) { return error; @@ -2410,13 +2555,19 @@ gl::Error TextureD3D_2DArray::setImage(GLenum target, size_t level, GLenum inter return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2DArray::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) +gl::Error TextureD3D_2DArray::setSubImage(GLenum target, + size_t imageLevel, + const gl::Box &area, + GLenum format, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); - + GLint level = static_cast(imageLevel); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level)); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch( + type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight); for (int i = 0; i < area.depth; i++) { @@ -2436,23 +2587,30 @@ gl::Error TextureD3D_2DArray::setSubImage(GLenum target, size_t level, const gl: return gl::Error(GL_NO_ERROR); } -gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) +gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, + size_t imageLevel, + GLenum internalFormat, + const gl::Extents &size, + const gl::PixelUnpackState &unpack, + size_t imageSize, + const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); + GLint level = static_cast(imageLevel); // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly redefineImage(level, internalFormat, size); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0); + GLsizei inputDepthPitch = + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0); for (int i = 0; i < size.depth; i++) { const ptrdiff_t layerOffset = (inputDepthPitch * i); gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i); - gl::Error error = TextureD3D::setCompressedImage(index, unpack, pixels, layerOffset); + gl::Error error = setCompressedImageImpl(index, unpack, pixels, layerOffset); if (error.isError()) { return error; @@ -2463,12 +2621,13 @@ gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, size_t level, GL } gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) { ASSERT(target == GL_TEXTURE_2D_ARRAY); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0); + GLsizei inputDepthPitch = + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0); for (int i = 0; i < area.depth; i++) { @@ -2477,7 +2636,7 @@ gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1); - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(static_cast(level), layer); gl::Error error = TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset); if (error.isError()) { @@ -2501,17 +2660,22 @@ gl::Error TextureD3D_2DArray::copyImage(GLenum target, size_t level, const gl::R return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented."); } -gl::Error TextureD3D_2DArray::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea, +gl::Error TextureD3D_2DArray::copySubImage(GLenum target, + size_t imageLevel, + const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, const gl::Framebuffer *source) { ASSERT(target == GL_TEXTURE_2D_ARRAY); + GLint level = static_cast(imageLevel); gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); if (canCreateRenderTargetForImage(index)) { gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0); - gl::Error error = mImageArray[level][destOffset.z]->copy(destLayerOffset, sourceArea, source); + gl::Error error = mImageArray[level][destOffset.z]->copyFromFramebuffer(destLayerOffset, + sourceArea, source); if (error.isError()) { return error; @@ -2575,7 +2739,9 @@ gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum in // TODO(geofflang): Verify storage creation had no errors bool renderTarget = IsRenderTargetUsage(mUsage); - TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width, size.height, size.depth, levels); + TextureStorage *storage = + mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width, + size.height, size.depth, static_cast(levels)); gl::Error error = setCompleteTexStorage(storage); if (error.isError()) @@ -2625,11 +2791,6 @@ void TextureD3D_2DArray::initMipmapsImages() } } -unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &index) -{ - return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0); -} - gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { // ensure the underlying texture is created @@ -2840,21 +3001,30 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const const int storageDepth = getLayerCount(0); const GLenum storageFormat = getBaseLevelInternalFormat(); - for (int layer = 0; layer < mLayerCounts[level]; layer++) + // Only reallocate the layers if the size doesn't match + if (size.depth != mLayerCounts[level]) { - delete mImageArray[level][layer]; + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + SafeDelete(mImageArray[level][layer]); + } + SafeDeleteArray(mImageArray[level]); + mLayerCounts[level] = size.depth; + + if (size.depth > 0) + { + mImageArray[level] = new ImageD3D*[size.depth]; + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = mRenderer->createImage(); + } + } } - delete[] mImageArray[level]; - mImageArray[level] = NULL; - mLayerCounts[level] = size.depth; if (size.depth > 0) { - mImageArray[level] = new ImageD3D*[size.depth](); - for (int layer = 0; layer < mLayerCounts[level]; layer++) { - mImageArray[level][layer] = mRenderer->createImage(); mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat, gl::Extents(size.width, size.height, 1), false); } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h index d94be49a08..1d5faee703 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h @@ -20,8 +20,7 @@ class Framebuffer; namespace rx { - -class ImageD3D; +class EGLImageD3D; class ImageD3D; class RendererD3D; class RenderTargetD3D; @@ -50,7 +49,6 @@ class TextureD3D : public TextureImpl bool isImmutable() const { return mImmutable; } virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index) = 0; // Returns an iterator over all "Images" for this particular Texture. virtual gl::ImageIndexIterator imageIterator() const = 0; @@ -60,18 +58,25 @@ class TextureD3D : public TextureImpl virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const = 0; virtual bool isValidIndex(const gl::ImageIndex &index) const = 0; - virtual gl::Error generateMipmaps(); + gl::Error generateMipmaps(const gl::TextureState &textureState) override; TextureStorage *getStorage(); ImageD3D *getBaseLevelImage() const; + gl::Error getAttachmentRenderTarget(const gl::FramebufferAttachment::Target &target, + FramebufferAttachmentRenderTarget **rtOut) override; + protected: - gl::Error setImage(const gl::ImageIndex &index, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixels, - ptrdiff_t layerOffset); + gl::Error setImageImpl(const gl::ImageIndex &index, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels, + ptrdiff_t layerOffset); gl::Error subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset); - gl::Error setCompressedImage(const gl::ImageIndex &index, const gl::PixelUnpackState &unpack, - const uint8_t *pixels, ptrdiff_t layerOffset); + gl::Error setCompressedImageImpl(const gl::ImageIndex &index, + const gl::PixelUnpackState &unpack, + const uint8_t *pixels, + ptrdiff_t layerOffset); gl::Error subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format, const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset); bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); @@ -106,6 +111,8 @@ class TextureD3D : public TextureImpl virtual gl::Error updateStorage() = 0; bool shouldUseSetData(const ImageD3D *image) const; + + gl::Error generateMipmapsUsingImages(); }; class TextureD3D_2D : public TextureD3D @@ -129,9 +136,9 @@ class TextureD3D_2D : public TextureD3D const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, const gl::Framebuffer *source) override; @@ -143,8 +150,9 @@ class TextureD3D_2D : public TextureD3D virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); virtual gl::ImageIndexIterator imageIterator() const; virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; @@ -164,8 +172,12 @@ class TextureD3D_2D : public TextureD3D gl::Error updateStorageLevel(int level); - void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size); + void redefineImage(size_t level, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease); + bool mEGLImageTarget; ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; @@ -192,9 +204,9 @@ class TextureD3D_Cube : public TextureD3D const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, const gl::Framebuffer *source) override; @@ -206,8 +218,9 @@ class TextureD3D_Cube : public TextureD3D virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); virtual gl::ImageIndexIterator imageIterator() const; virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; @@ -254,9 +267,9 @@ class TextureD3D_3D : public TextureD3D const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, const gl::Framebuffer *source) override; @@ -268,8 +281,9 @@ class TextureD3D_3D : public TextureD3D virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); virtual gl::ImageIndexIterator imageIterator() const; virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; @@ -314,9 +328,9 @@ class TextureD3D_2DArray : public TextureD3D const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, - const gl::PixelUnpackState &unpack, const uint8_t *pixels) override; + const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels) override; gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat, const gl::Framebuffer *source) override; @@ -328,8 +342,9 @@ class TextureD3D_2DArray : public TextureD3D virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); + gl::Error setEGLImageTarget(GLenum target, egl::Image *image) override; + virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); - virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); virtual gl::ImageIndexIterator imageIterator() const; virtual gl::ImageIndex getImageIndex(GLint mip, GLint layer) const; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h index ae2d42ca8a..417237495d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h @@ -33,12 +33,13 @@ class ImageD3D; class TextureStorage : angle::NonCopyable { public: - TextureStorage(); - virtual ~TextureStorage() {}; + TextureStorage() {} + virtual ~TextureStorage() {} virtual int getTopLevel() const = 0; virtual bool isRenderTarget() const = 0; virtual bool isManaged() const = 0; + virtual bool supportsNativeMipmapFunction() const = 0; virtual int getLevelCount() const = 0; virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; @@ -48,18 +49,8 @@ class TextureStorage : angle::NonCopyable virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0; - unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const; - unsigned int getTextureSerial() const; - // This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D) might override it. virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) { return gl::Error(GL_NO_ERROR); } - - protected: - void initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride); - - private: - unsigned int mFirstRenderTargetSerial; - unsigned int mRenderTargetSerialsLayerStride; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp index 5c0bfdcd5b..80a4ec3ae1 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp @@ -35,4 +35,12 @@ void TransformFeedbackD3D::resume() { } +void TransformFeedbackD3D::bindGenericBuffer(const BindingPointer &binding) +{ +} + +void TransformFeedbackD3D::bindIndexedBuffer(size_t index, const OffsetBindingPointer &binding) +{ +} + } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h index 6b255b4a2b..6925966153 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h @@ -21,10 +21,13 @@ class TransformFeedbackD3D : public TransformFeedbackImpl TransformFeedbackD3D(); virtual ~TransformFeedbackD3D(); - virtual void begin(GLenum primitiveMode); - virtual void end(); - virtual void pause(); - virtual void resume(); + void begin(GLenum primitiveMode) override; + void end() override; + void pause() override; + void resume() override; + + void bindGenericBuffer(const BindingPointer &binding) override; + void bindIndexedBuffer(size_t index, const OffsetBindingPointer &binding) override; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp new file mode 100644 index 0000000000..f2654d34e3 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.cpp @@ -0,0 +1,397 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// VaryingPacking: +// Class which describes a mapping from varyings to registers in D3D +// for linking between shader stages. +// + +#include "libANGLE/renderer/d3d/VaryingPacking.h" + +#include "common/utilities.h" +#include "compiler/translator/blocklayoutHLSL.h" +#include "libANGLE/renderer/d3d/DynamicHLSL.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" + +namespace rx +{ + +// Implementation of VaryingPacking::BuiltinVarying +VaryingPacking::BuiltinVarying::BuiltinVarying() : enabled(false), index(0), systemValue(false) +{ +} + +std::string VaryingPacking::BuiltinVarying::str() const +{ + return (systemValue ? semantic : (semantic + Str(index))); +} + +void VaryingPacking::BuiltinVarying::enableSystem(const std::string &systemValueSemantic) +{ + enabled = true; + semantic = systemValueSemantic; + systemValue = true; +} + +void VaryingPacking::BuiltinVarying::enable(const std::string &semanticVal, unsigned int indexVal) +{ + enabled = true; + semantic = semanticVal; + index = indexVal; +} + +// Implementation of VaryingPacking +VaryingPacking::VaryingPacking(GLuint maxVaryingVectors) + : mRegisterMap(maxVaryingVectors), mBuiltinInfo(SHADER_TYPE_MAX) +{ +} + +// Packs varyings into generic varying registers, using the algorithm from +// See [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111 +// Also [OpenGL ES Shading Language 3.00 rev. 4] Section 11 page 119 +// Returns false if unsuccessful. +bool VaryingPacking::packVarying(const PackedVarying &packedVarying) +{ + unsigned int varyingRows = 0; + unsigned int varyingColumns = 0; + + const auto &varying = *packedVarying.varying; + + // "Non - square matrices of type matCxR consume the same space as a square matrix of type matN + // where N is the greater of C and R.Variables of type mat2 occupies 2 complete rows." + // Here we are a bit more conservative and allow packing non-square matrices more tightly. + // Make sure we use transposed matrix types to count registers correctly. + ASSERT(!varying.isStruct()); + GLenum transposedType = gl::TransposeMatrixType(varying.type); + varyingRows = gl::VariableRowCount(transposedType); + varyingColumns = gl::VariableColumnCount(transposedType); + + // "Arrays of size N are assumed to take N times the size of the base type" + varyingRows *= varying.elementCount(); + + unsigned int maxVaryingVectors = static_cast(mRegisterMap.size()); + + // "For 2, 3 and 4 component variables packing is started using the 1st column of the 1st row. + // Variables are then allocated to successive rows, aligning them to the 1st column." + if (varyingColumns >= 2 && varyingColumns <= 4) + { + for (unsigned int row = 0; row <= maxVaryingVectors - varyingRows; ++row) + { + if (isFree(row, 0, varyingRows, varyingColumns)) + { + insert(row, 0, packedVarying); + return true; + } + } + + // "For 2 component variables, when there are no spare rows, the strategy is switched to + // using the highest numbered row and the lowest numbered column where the variable will + // fit." + if (varyingColumns == 2) + { + for (unsigned int r = maxVaryingVectors - varyingRows + 1; r-- >= 1;) + { + if (isFree(r, 2, varyingRows, 2)) + { + insert(r, 2, packedVarying); + return true; + } + } + } + + return false; + } + + // "1 component variables have their own packing rule. They are packed in order of size, largest + // first. Each variable is placed in the column that leaves the least amount of space in the + // column and aligned to the lowest available rows within that column." + ASSERT(varyingColumns == 1); + unsigned int contiguousSpace[4] = {0}; + unsigned int bestContiguousSpace[4] = {0}; + unsigned int totalSpace[4] = {0}; + + for (unsigned int row = 0; row < maxVaryingVectors; ++row) + { + for (unsigned int column = 0; column < 4; ++column) + { + if (mRegisterMap[row][column]) + { + contiguousSpace[column] = 0; + } + else + { + contiguousSpace[column]++; + totalSpace[column]++; + + if (contiguousSpace[column] > bestContiguousSpace[column]) + { + bestContiguousSpace[column] = contiguousSpace[column]; + } + } + } + } + + unsigned int bestColumn = 0; + for (unsigned int column = 1; column < 4; ++column) + { + if (bestContiguousSpace[column] >= varyingRows && + (bestContiguousSpace[bestColumn] < varyingRows || + totalSpace[column] < totalSpace[bestColumn])) + { + bestColumn = column; + } + } + + if (bestContiguousSpace[bestColumn] >= varyingRows) + { + for (unsigned int row = 0; row < maxVaryingVectors; row++) + { + if (isFree(row, bestColumn, varyingRows, 1)) + { + for (unsigned int arrayIndex = 0; arrayIndex < varyingRows; ++arrayIndex) + { + // If varyingRows > 1, it must be an array. + PackedVaryingRegister registerInfo; + registerInfo.packedVarying = &packedVarying; + registerInfo.registerRow = row + arrayIndex; + registerInfo.registerColumn = bestColumn; + registerInfo.varyingArrayIndex = arrayIndex; + registerInfo.varyingRowIndex = 0; + mRegisterList.push_back(registerInfo); + mRegisterMap[row + arrayIndex][bestColumn] = true; + } + break; + } + } + return true; + } + + return false; +} + +bool VaryingPacking::isFree(unsigned int registerRow, + unsigned int registerColumn, + unsigned int varyingRows, + unsigned int varyingColumns) const +{ + for (unsigned int row = 0; row < varyingRows; ++row) + { + ASSERT(registerRow + row < mRegisterMap.size()); + for (unsigned int column = 0; column < varyingColumns; ++column) + { + ASSERT(registerColumn + column < 4); + if (mRegisterMap[registerRow + row][registerColumn + column]) + { + return false; + } + } + } + + return true; +} + +void VaryingPacking::insert(unsigned int registerRow, + unsigned int registerColumn, + const PackedVarying &packedVarying) +{ + unsigned int varyingRows = 0; + unsigned int varyingColumns = 0; + + const auto &varying = *packedVarying.varying; + ASSERT(!varying.isStruct()); + GLenum transposedType = gl::TransposeMatrixType(varying.type); + varyingRows = gl::VariableRowCount(transposedType); + varyingColumns = gl::VariableColumnCount(transposedType); + + PackedVaryingRegister registerInfo; + registerInfo.packedVarying = &packedVarying; + registerInfo.registerColumn = registerColumn; + + for (unsigned int arrayElement = 0; arrayElement < varying.elementCount(); ++arrayElement) + { + for (unsigned int varyingRow = 0; varyingRow < varyingRows; ++varyingRow) + { + registerInfo.registerRow = registerRow + (arrayElement * varyingRows) + varyingRow; + registerInfo.varyingRowIndex = varyingRow; + registerInfo.varyingArrayIndex = arrayElement; + mRegisterList.push_back(registerInfo); + + for (unsigned int columnIndex = 0; columnIndex < varyingColumns; ++columnIndex) + { + mRegisterMap[registerInfo.registerRow][registerColumn + columnIndex] = true; + } + } + } +} + +// See comment on packVarying. +bool VaryingPacking::packVaryings(gl::InfoLog &infoLog, + const std::vector &packedVaryings, + const std::vector &transformFeedbackVaryings) +{ + std::set uniqueVaryingNames; + + // "Variables are packed into the registers one at a time so that they each occupy a contiguous + // subrectangle. No splitting of variables is permitted." + for (const PackedVarying &packedVarying : packedVaryings) + { + const auto &varying = *packedVarying.varying; + + // Do not assign registers to built-in or unreferenced varyings + if (varying.isBuiltIn() || (!varying.staticUse && !packedVarying.isStructField())) + { + continue; + } + + ASSERT(!varying.isStruct()); + ASSERT(uniqueVaryingNames.count(varying.name) == 0); + + if (packVarying(packedVarying)) + { + uniqueVaryingNames.insert(varying.name); + } + else + { + infoLog << "Could not pack varying " << varying.name; + return false; + } + } + + for (const std::string &transformFeedbackVaryingName : transformFeedbackVaryings) + { + if (transformFeedbackVaryingName.compare(0, 3, "gl_") == 0) + { + // do not pack builtin XFB varyings + continue; + } + + for (const PackedVarying &packedVarying : packedVaryings) + { + const auto &varying = *packedVarying.varying; + + // Make sure transform feedback varyings aren't optimized out. + if (uniqueVaryingNames.count(transformFeedbackVaryingName) == 0) + { + bool found = false; + if (transformFeedbackVaryingName == varying.name) + { + if (!packVarying(packedVarying)) + { + infoLog << "Could not pack varying " << varying.name; + return false; + } + + found = true; + break; + } + if (!found) + { + infoLog << "Transform feedback varying " << transformFeedbackVaryingName + << " does not exist in the vertex shader."; + return false; + } + } + } + } + + // Sort the packed register list + std::sort(mRegisterList.begin(), mRegisterList.end()); + + // Assign semantic indices + for (unsigned int semanticIndex = 0; + semanticIndex < static_cast(mRegisterList.size()); ++semanticIndex) + { + mRegisterList[semanticIndex].semanticIndex = semanticIndex; + } + + return true; +} + +unsigned int VaryingPacking::getRegisterCount() const +{ + unsigned int count = 0; + + for (const Register ® : mRegisterMap) + { + if (reg.data[0] || reg.data[1] || reg.data[2] || reg.data[3]) + { + ++count; + } + } + + if (mBuiltinInfo[SHADER_PIXEL].glFragCoord.enabled) + { + ++count; + } + + if (mBuiltinInfo[SHADER_PIXEL].glPointCoord.enabled) + { + ++count; + } + + return count; +} + +void VaryingPacking::enableBuiltins(ShaderType shaderType, + const ProgramD3DMetadata &programMetadata) +{ + int majorShaderModel = programMetadata.getRendererMajorShaderModel(); + bool position = programMetadata.usesTransformFeedbackGLPosition(); + bool fragCoord = programMetadata.usesFragCoord(); + bool pointCoord = shaderType == SHADER_VERTEX ? programMetadata.addsPointCoordToVertexShader() + : programMetadata.usesPointCoord(); + bool pointSize = programMetadata.usesSystemValuePointSize(); + bool hlsl4 = (majorShaderModel >= 4); + const std::string &userSemantic = GetVaryingSemantic(majorShaderModel, pointSize); + + unsigned int reservedSemanticIndex = getMaxSemanticIndex(); + + BuiltinInfo *builtins = &mBuiltinInfo[shaderType]; + + if (hlsl4) + { + builtins->dxPosition.enableSystem("SV_Position"); + } + else if (shaderType == SHADER_PIXEL) + { + builtins->dxPosition.enableSystem("VPOS"); + } + else + { + builtins->dxPosition.enableSystem("POSITION"); + } + + if (position) + { + builtins->glPosition.enable(userSemantic, reservedSemanticIndex++); + } + + if (fragCoord) + { + builtins->glFragCoord.enable(userSemantic, reservedSemanticIndex++); + } + + if (pointCoord) + { + // SM3 reserves the TEXCOORD semantic for point sprite texcoords (gl_PointCoord) + // In D3D11 we manually compute gl_PointCoord in the GS. + if (hlsl4) + { + builtins->glPointCoord.enable(userSemantic, reservedSemanticIndex++); + } + else + { + builtins->glPointCoord.enable("TEXCOORD", 0); + } + } + + // Special case: do not include PSIZE semantic in HLSL 3 pixel shaders + if (pointSize && (shaderType != SHADER_PIXEL || hlsl4)) + { + builtins->glPointSize.enableSystem("PSIZE"); + } +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h new file mode 100644 index 0000000000..ca4640b000 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VaryingPacking.h @@ -0,0 +1,175 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// VaryingPacking: +// Class which describes a mapping from varyings to registers in D3D +// for linking between shader stages. +// + +#ifndef LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_ +#define LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_ + +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ +class ProgramD3DMetadata; + +struct PackedVarying +{ + PackedVarying(const sh::ShaderVariable &varyingIn, sh::InterpolationType interpolationIn) + : varying(&varyingIn), vertexOnly(false), interpolation(interpolationIn) + { + } + PackedVarying(const sh::ShaderVariable &varyingIn, + sh::InterpolationType interpolationIn, + const std::string &parentStructNameIn) + : varying(&varyingIn), + vertexOnly(false), + interpolation(interpolationIn), + parentStructName(parentStructNameIn) + { + } + + bool isStructField() const { return !parentStructName.empty(); } + + const sh::ShaderVariable *varying; + + // Transform feedback varyings can be only referenced in the VS. + bool vertexOnly; + + // Cached so we can store sh::ShaderVariable to point to varying fields. + sh::InterpolationType interpolation; + + // Struct name + std::string parentStructName; +}; + +struct PackedVaryingRegister final +{ + PackedVaryingRegister() + : packedVarying(nullptr), + varyingArrayIndex(0), + varyingRowIndex(0), + registerRow(0), + registerColumn(0) + { + } + + PackedVaryingRegister(const PackedVaryingRegister &) = default; + PackedVaryingRegister &operator=(const PackedVaryingRegister &) = default; + + bool operator<(const PackedVaryingRegister &other) const + { + return sortOrder() < other.sortOrder(); + } + + unsigned int sortOrder() const + { + // TODO(jmadill): Handle interpolation types + return registerRow * 4 + registerColumn; + } + + bool isStructField() const { return !structFieldName.empty(); } + + // Index to the array of varyings. + const PackedVarying *packedVarying; + + // The array element of the packed varying. + unsigned int varyingArrayIndex; + + // The row of the array element of the packed varying. + unsigned int varyingRowIndex; + + // The register row to which we've assigned this packed varying. + unsigned int registerRow; + + // The column of the register row into which we've packed this varying. + unsigned int registerColumn; + + // Assigned after packing + unsigned int semanticIndex; + + // Struct member this varying corresponds to. + std::string structFieldName; +}; + +class VaryingPacking final : angle::NonCopyable +{ + public: + VaryingPacking(GLuint maxVaryingVectors); + + bool packVaryings(gl::InfoLog &infoLog, + const std::vector &packedVaryings, + const std::vector &transformFeedbackVaryings); + + struct Register + { + Register() { data[0] = data[1] = data[2] = data[3] = false; } + + bool &operator[](unsigned int index) { return data[index]; } + bool operator[](unsigned int index) const { return data[index]; } + + bool data[4]; + }; + + Register &operator[](unsigned int index) { return mRegisterMap[index]; } + const Register &operator[](unsigned int index) const { return mRegisterMap[index]; } + + const std::vector &getRegisterList() const { return mRegisterList; } + unsigned int getMaxSemanticIndex() const + { + return static_cast(mRegisterList.size()); + } + unsigned int getRegisterCount() const; + + void enableBuiltins(ShaderType shaderType, const ProgramD3DMetadata &programMetadata); + + struct BuiltinVarying final : angle::NonCopyable + { + BuiltinVarying(); + + std::string str() const; + void enableSystem(const std::string &systemValueSemantic); + void enable(const std::string &semanticVal, unsigned int indexVal); + + bool enabled; + std::string semantic; + unsigned int index; + bool systemValue; + }; + + struct BuiltinInfo + { + BuiltinVarying dxPosition; + BuiltinVarying glPosition; + BuiltinVarying glFragCoord; + BuiltinVarying glPointCoord; + BuiltinVarying glPointSize; + }; + + const BuiltinInfo &builtins(ShaderType shaderType) const { return mBuiltinInfo[shaderType]; } + + bool usesPointSize() const { return mBuiltinInfo[SHADER_VERTEX].glPointSize.enabled; } + + private: + bool packVarying(const PackedVarying &packedVarying); + bool isFree(unsigned int registerRow, + unsigned int registerColumn, + unsigned int varyingRows, + unsigned int varyingColumns) const; + void insert(unsigned int registerRow, + unsigned int registerColumn, + const PackedVarying &packedVarying); + + std::vector mRegisterMap; + std::vector mRegisterList; + + std::vector mBuiltinInfo; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_VARYINGPACKING_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp index 19bd548fce..9efee9db7c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp @@ -90,8 +90,13 @@ gl::Error VertexBufferInterface::discard() return mVertexBuffer->discard(); } -gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) +gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int *outStreamOffset, + const uint8_t *sourceData) { gl::Error error(GL_NO_ERROR); @@ -102,7 +107,12 @@ gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute return error; } - if (mWritePosition + spaceRequired < mWritePosition) + // Align to 16-byte boundary + unsigned int alignedSpaceRequired = roundUp(spaceRequired, 16u); + + // Protect against integer overflow + if (!IsUnsignedAdditionSafe(mWritePosition, alignedSpaceRequired) || + alignedSpaceRequired < spaceRequired) { return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow."); } @@ -114,7 +124,7 @@ gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute } mReservedSpace = 0; - error = mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition); + error = mVertexBuffer->storeVertexAttributes(attrib, currentValueType, start, count, instances, mWritePosition, sourceData); if (error.isError()) { return error; @@ -125,10 +135,7 @@ gl::Error VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute *outStreamOffset = mWritePosition; } - mWritePosition += spaceRequired; - - // Align to 16-byte boundary - mWritePosition = roundUp(mWritePosition, 16u); + mWritePosition += alignedSpaceRequired; return gl::Error(GL_NO_ERROR); } @@ -144,17 +151,18 @@ gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &a return error; } + // Align to 16-byte boundary + unsigned int alignedRequiredSpace = roundUp(requiredSpace, 16u); + // Protect against integer overflow - if (mReservedSpace + requiredSpace < mReservedSpace) + if (!IsUnsignedAdditionSafe(mReservedSpace, alignedRequiredSpace) || + alignedRequiredSpace < requiredSpace) { return gl::Error(GL_OUT_OF_MEMORY, "Unable to reserve %u extra bytes in internal vertex buffer, " "it would result in an overflow.", requiredSpace); } - mReservedSpace += requiredSpace; - - // Align to 16-byte boundary - mReservedSpace = roundUp(mReservedSpace, 16u); + mReservedSpace += alignedRequiredSpace; return gl::Error(GL_NO_ERROR); } @@ -165,7 +173,7 @@ VertexBuffer* VertexBufferInterface::getVertexBuffer() const } bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const + GLenum currentValueType) const { gl::Buffer *buffer = attrib.buffer.get(); BufferD3D *storage = buffer ? GetImplAs(buffer) : NULL; @@ -183,14 +191,14 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att if (attrib.type != GL_FLOAT) { - gl::VertexFormat vertexFormat(attrib, currentValue.Type); + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType); unsigned int outputElementSize; getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); alignment = std::min(outputElementSize, 4); // TODO(jmadill): add VertexFormatCaps - requiresConversion = (mFactory->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0; + requiresConversion = (mFactory->getVertexConversionType(vertexFormatType) & VERTEX_CONVERT_CPU) != 0; } bool isAligned = (static_cast(ComputeVertexAttributeStride(attrib)) % alignment == 0) && @@ -202,7 +210,7 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize) : VertexBufferInterface(factory, true) { - setBufferSize(initialSize); + setBufferSize(static_cast(initialSize)); } StreamingVertexBufferInterface::~StreamingVertexBufferInterface() @@ -235,7 +243,7 @@ gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) } StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory) - : VertexBufferInterface(factory, false) + : VertexBufferInterface(factory, false), mIsCommitted(false) { } @@ -247,13 +255,14 @@ bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &att { for (unsigned int element = 0; element < mCache.size(); element++) { - if (mCache[element].type == attrib.type && - mCache[element].size == attrib.size && - mCache[element].stride == ComputeVertexAttributeStride(attrib) && + size_t attribStride = ComputeVertexAttributeStride(attrib); + + if (mCache[element].type == attrib.type && mCache[element].size == attrib.size && + mCache[element].stride == attribStride && mCache[element].normalized == attrib.normalized && mCache[element].pureInteger == attrib.pureInteger) { - size_t offset = (static_cast(attrib.offset) % ComputeVertexAttributeStride(attrib)); + size_t offset = (static_cast(attrib.offset) % attribStride); if (mCache[element].attributeOffset == offset) { if (outStreamOffset) @@ -286,11 +295,16 @@ gl::Error StaticVertexBufferInterface::reserveSpace(unsigned int size) } } -gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) +gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int *outStreamOffset, + const uint8_t *sourceData) { unsigned int streamOffset; - gl::Error error = VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset); + gl::Error error = VertexBufferInterface::storeVertexAttributes(attrib, currentValueType, start, count, instances, &streamOffset, sourceData); if (error.isError()) { return error; @@ -308,4 +322,11 @@ gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAtt return gl::Error(GL_NO_ERROR); } +void StaticVertexBufferInterface::commit() +{ + if (getBufferSize() > 0) + { + mIsCommitted = true; + } +} } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h index 5cb03fe3a1..692b6ac506 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h @@ -16,6 +16,7 @@ #include #include +#include #include namespace gl @@ -36,8 +37,13 @@ class VertexBuffer : angle::NonCopyable virtual gl::Error initialize(unsigned int size, bool dynamicUsage) = 0; - virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset) = 0; + virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) = 0; virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const = 0; @@ -70,11 +76,16 @@ class VertexBufferInterface : angle::NonCopyable unsigned int getSerial() const; - virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); + virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int *outStreamOffset, + const uint8_t *sourceData); bool directStoragePossible(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const; + GLenum currentValueType) const; VertexBuffer* getVertexBuffer() const; @@ -114,11 +125,21 @@ class StaticVertexBufferInterface : public VertexBufferInterface explicit StaticVertexBufferInterface(BufferFactoryD3D *factory); ~StaticVertexBufferInterface(); - gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); + gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int *outStreamOffset, + const uint8_t *sourceData) override; bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset); + // If a static vertex buffer is committed then no more attribute data can be added to it + // A new static vertex buffer should be created instead + void commit(); + bool isCommitted() { return mIsCommitted; } + protected: gl::Error reserveSpace(unsigned int size); @@ -135,6 +156,7 @@ class StaticVertexBufferInterface : public VertexBufferInterface unsigned int streamOffset; }; + bool mIsCommitted; std::vector mCache; }; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp index cb70b9e4ef..b392d0f4da 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp @@ -35,215 +35,217 @@ static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size size = static_cast(std::numeric_limits::max()); } - GLsizei stride = ComputeVertexAttributeStride(attrib); - return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride; + GLsizei stride = static_cast(ComputeVertexAttributeStride(attrib)); + return (size - attrib.offset % stride + + (stride - static_cast(ComputeVertexAttributeTypeSize(attrib)))) / + stride; } -static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount) +VertexDataManager::CurrentValueState::CurrentValueState() + : buffer(nullptr), + offset(0) { - // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. - // - // A vertex attribute with a positive divisor loads one instanced vertex for every set of - // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. - if (instanceDrawCount > 0 && attrib.divisor > 0) - { - // When instanceDrawCount is not a multiple attrib.divisor, the division must round up. - // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced vertices. - return (instanceDrawCount + attrib.divisor - 1) / attrib.divisor; - } + data.FloatValues[0] = std::numeric_limits::quiet_NaN(); + data.FloatValues[1] = std::numeric_limits::quiet_NaN(); + data.FloatValues[2] = std::numeric_limits::quiet_NaN(); + data.FloatValues[3] = std::numeric_limits::quiet_NaN(); + data.Type = GL_FLOAT; +} - return vertexDrawCount; +VertexDataManager::CurrentValueState::~CurrentValueState() +{ + SafeDelete(buffer); } VertexDataManager::VertexDataManager(BufferFactoryD3D *factory) - : mFactory(factory) + : mFactory(factory), + mStreamingBuffer(nullptr), + // TODO(jmadill): use context caps + mCurrentValueCache(gl::MAX_VERTEX_ATTRIBS) { - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentValue[i].FloatValues[0] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].FloatValues[1] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].FloatValues[2] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].FloatValues[3] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i].Type = GL_FLOAT; - mCurrentValueBuffer[i] = NULL; - mCurrentValueOffsets[i] = 0; - } - mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE); if (!mStreamingBuffer) { ERR("Failed to allocate the streaming vertex buffer."); } + + // TODO(jmadill): use context caps + mActiveEnabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); + mActiveDisabledAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); } VertexDataManager::~VertexDataManager() { - delete mStreamingBuffer; - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - delete mCurrentValueBuffer[i]; - } + SafeDelete(mStreamingBuffer); } void VertexDataManager::hintUnmapAllResources(const std::vector &vertexAttributes) { mStreamingBuffer->getVertexBuffer()->hintUnmapResource(); - for (size_t i = 0; i < vertexAttributes.size(); i++) + for (const TranslatedAttribute *translated : mActiveEnabledAttributes) { - const gl::VertexAttribute &attrib = vertexAttributes[i]; - if (attrib.enabled) + gl::Buffer *buffer = translated->attribute->buffer.get(); + BufferD3D *storage = buffer ? GetImplAs(buffer) : nullptr; + StaticVertexBufferInterface *staticBuffer = + storage + ? storage->getStaticVertexBuffer(*translated->attribute, D3D_BUFFER_DO_NOT_CREATE) + : nullptr; + + if (staticBuffer) { - gl::Buffer *buffer = attrib.buffer.get(); - BufferD3D *storage = buffer ? GetImplAs(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; + // Commit all the static vertex buffers. This fixes them in size/contents, and forces + // ANGLE to use a new static buffer (or recreate the static buffers) next time + staticBuffer->commit(); - if (staticBuffer) - { - staticBuffer->getVertexBuffer()->hintUnmapResource(); - } + staticBuffer->getVertexBuffer()->hintUnmapResource(); } } - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (auto ¤tValue : mCurrentValueCache) { - if (mCurrentValueBuffer[i] != NULL) + if (currentValue.buffer != nullptr) { - mCurrentValueBuffer[i]->getVertexBuffer()->hintUnmapResource(); + currentValue.buffer->getVertexBuffer()->hintUnmapResource(); } } } -gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, - TranslatedAttribute *translated, GLsizei instances) +gl::Error VertexDataManager::prepareVertexData(const gl::State &state, + GLint start, + GLsizei count, + std::vector *translatedAttribs, + GLsizei instances) { if (!mStreamingBuffer) { return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); } + // Compute active enabled and active disable attributes, for speed. + // TODO(jmadill): don't recompute if there was no state change const gl::VertexArray *vertexArray = state.getVertexArray(); - const std::vector &vertexAttributes = vertexArray->getVertexAttributes(); + const gl::Program *program = state.getProgram(); + const auto &vertexAttributes = vertexArray->getVertexAttributes(); + + mActiveEnabledAttributes.clear(); + mActiveDisabledAttributes.clear(); + translatedAttribs->clear(); - // Invalidate static buffers that don't contain matching attributes - for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) { - translated[attributeIndex].active = (state.getProgram()->getSemanticIndex(attributeIndex) != -1); - if (translated[attributeIndex].active && vertexAttributes[attributeIndex].enabled) + if (program->isAttribLocationActive(attribIndex)) { - invalidateMatchingStaticData(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex)); + // Resize automatically puts in empty attribs + translatedAttribs->resize(attribIndex + 1); + + TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex]; + + // Record the attribute now + translated->active = true; + translated->attribute = &vertexAttributes[attribIndex]; + translated->currentValueType = + state.getVertexAttribCurrentValue(static_cast(attribIndex)).Type; + translated->divisor = vertexAttributes[attribIndex].divisor; + + if (vertexAttributes[attribIndex].enabled) + { + mActiveEnabledAttributes.push_back(translated); + + gl::Buffer *buffer = vertexAttributes[attribIndex].buffer.get(); + if (buffer) + { + // Also reinitialize static buffers which didn't contain matching data + // last time they were used + BufferD3D *bufferImpl = GetImplAs(buffer); + bufferImpl->reinitOutOfDateStaticData(); + } + } + else + { + mActiveDisabledAttributes.push_back(attribIndex); + } } } // Reserve the required space in the buffers - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { - if (translated[i].active && vertexAttributes[i].enabled) + gl::Error error = reserveSpaceForAttrib(*activeAttrib, count, instances); + if (error.isError()) { - gl::Error error = reserveSpaceForAttrib(vertexAttributes[i], state.getVertexAttribCurrentValue(i), count, instances); - if (error.isError()) - { - return error; - } + return error; } } // Perform the vertex data translations - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { - const gl::VertexAttribute &curAttrib = vertexAttributes[i]; - if (translated[i].active) - { - if (curAttrib.enabled) - { - gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i), - &translated[i], start, count, instances); + gl::Error error = storeAttribute(activeAttrib, start, count, instances); - if (error.isError()) - { - hintUnmapAllResources(vertexAttributes); - return error; - } - } - else - { - if (!mCurrentValueBuffer[i]) - { - mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); - } - - gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], - &mCurrentValue[i], &mCurrentValueOffsets[i], - mCurrentValueBuffer[i]); - if (error.isError()) - { - hintUnmapAllResources(vertexAttributes); - return error; - } - } + if (error.isError()) + { + hintUnmapAllResources(vertexAttributes); + return error; } } - // Hint to unmap all the resources - hintUnmapAllResources(vertexAttributes); - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (size_t attribIndex : mActiveDisabledAttributes) { - const gl::VertexAttribute &curAttrib = vertexAttributes[i]; - if (translated[i].active && curAttrib.enabled) + if (mCurrentValueCache[attribIndex].buffer == nullptr) { - gl::Buffer *buffer = curAttrib.buffer.get(); + mCurrentValueCache[attribIndex].buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); + } - if (buffer) - { - BufferD3D *bufferImpl = GetImplAs(buffer); - bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib)); - } + gl::Error error = storeCurrentValue( + state.getVertexAttribCurrentValue(static_cast(attribIndex)), + &(*translatedAttribs)[attribIndex], &mCurrentValueCache[attribIndex]); + if (error.isError()) + { + hintUnmapAllResources(vertexAttributes); + return error; } } - return gl::Error(GL_NO_ERROR); -} - -void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const -{ - gl::Buffer *buffer = attrib.buffer.get(); + // Hint to unmap all the resources + hintUnmapAllResources(vertexAttributes); - if (buffer) + for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { - BufferD3D *bufferImpl = GetImplAs(buffer); - StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(); + gl::Buffer *buffer = activeAttrib->attribute->buffer.get(); - if (staticBuffer && - staticBuffer->getBufferSize() > 0 && - !staticBuffer->lookupAttribute(attrib, NULL) && - !staticBuffer->directStoragePossible(attrib, currentValue)) + if (buffer) { - bufferImpl->invalidateStaticData(); + BufferD3D *bufferD3D = GetImplAs(buffer); + size_t typeSize = ComputeVertexAttributeTypeSize(*activeAttrib->attribute); + bufferD3D->promoteStaticUsage(count * static_cast(typeSize)); } } + + return gl::Error(GL_NO_ERROR); } -gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, +gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib, GLsizei count, GLsizei instances) const { + const gl::VertexAttribute &attrib = *translatedAttrib.attribute; gl::Buffer *buffer = attrib.buffer.get(); BufferD3D *bufferImpl = buffer ? GetImplAs(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL; + StaticVertexBufferInterface *staticBuffer = + bufferImpl ? bufferImpl->getStaticVertexBuffer(attrib, D3D_BUFFER_CREATE_IF_NECESSARY) + : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); - if (!vertexBuffer->directStoragePossible(attrib, currentValue)) + if (!vertexBuffer->directStoragePossible(attrib, translatedAttrib.currentValueType)) { if (staticBuffer) { if (staticBuffer->getBufferSize() == 0) { - int totalCount = ElementsInBuffer(attrib, bufferImpl->getSize()); + int totalCount = + ElementsInBuffer(attrib, static_cast(bufferImpl->getSize())); gl::Error error = staticBuffer->reserveVertexSpace(attrib, totalCount, 0); if (error.isError()) { @@ -253,10 +255,13 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &at } else { - int totalCount = StreamingBufferElementCount(attrib, count, instances); - ASSERT(!bufferImpl || ElementsInBuffer(attrib, bufferImpl->getSize()) >= totalCount); + size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances); + ASSERT(!bufferImpl || + ElementsInBuffer(attrib, static_cast(bufferImpl->getSize())) >= + static_cast(totalCount)); - gl::Error error = mStreamingBuffer->reserveVertexSpace(attrib, totalCount, instances); + gl::Error error = mStreamingBuffer->reserveVertexSpace( + attrib, static_cast(totalCount), instances); if (error.isError()) { return error; @@ -267,33 +272,59 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &at return gl::Error(GL_NO_ERROR); } -gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, - TranslatedAttribute *translated, +gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated, GLint start, GLsizei count, GLsizei instances) { + const gl::VertexAttribute &attrib = *translated->attribute; + gl::Buffer *buffer = attrib.buffer.get(); ASSERT(buffer || attrib.pointer); + ASSERT(attrib.enabled); BufferD3D *storage = buffer ? GetImplAs(buffer) : NULL; - StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL; + StaticVertexBufferInterface *staticBuffer = + storage ? storage->getStaticVertexBuffer(attrib, D3D_BUFFER_DO_NOT_CREATE) : NULL; VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); - bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue); - - unsigned int streamOffset = 0; - unsigned int outputElementSize = 0; + bool directStorage = vertexBuffer->directStoragePossible(attrib, translated->currentValueType); // Instanced vertices do not apply the 'start' offset - GLint firstVertexIndex = (instances > 0 && attrib.divisor > 0 ? 0 : start); + GLint firstVertexIndex = (attrib.divisor > 0 ? 0 : start); + + translated->vertexBuffer = vertexBuffer->getVertexBuffer(); if (directStorage) { - outputElementSize = ComputeVertexAttributeStride(attrib); - streamOffset = attrib.offset + outputElementSize * firstVertexIndex; + translated->storage = storage; + translated->serial = storage->getSerial(); + translated->stride = static_cast(ComputeVertexAttributeStride(attrib)); + translated->offset = static_cast(attrib.offset + translated->stride * firstVertexIndex); + + return gl::Error(GL_NO_ERROR); + } + + // Compute source data pointer + const uint8_t *sourceData = nullptr; + + if (buffer) + { + gl::Error error = storage->getData(&sourceData); + if (error.isError()) + { + return error; + } + sourceData += static_cast(attrib.offset); + } + else + { + sourceData = static_cast(attrib.pointer); } - else if (staticBuffer) + + unsigned int streamOffset = 0; + unsigned int outputElementSize = 0; + + if (staticBuffer) { gl::Error error = staticBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); if (error.isError()) @@ -304,19 +335,30 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, if (!staticBuffer->lookupAttribute(attrib, &streamOffset)) { // Convert the entire buffer - int totalCount = ElementsInBuffer(attrib, storage->getSize()); - int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib); - - error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount, - 0, &streamOffset); + int totalCount = + ElementsInBuffer(attrib, static_cast(storage->getSize())); + int startIndex = static_cast(attrib.offset) / + static_cast(ComputeVertexAttributeStride(attrib)); + + error = staticBuffer->storeVertexAttributes(attrib, + translated->currentValueType, + -startIndex, + totalCount, + 0, + &streamOffset, + sourceData); if (error.isError()) { return error; } } - unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize; - unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? firstVertexIndex * outputElementSize : 0; + unsigned int firstElementOffset = + (static_cast(attrib.offset) / + static_cast(ComputeVertexAttributeStride(attrib))) * + outputElementSize; + ASSERT(attrib.divisor == 0 || firstVertexIndex == 0); + unsigned int startOffset = firstVertexIndex * outputElementSize; if (streamOffset + firstElementOffset + startOffset < streamOffset) { return gl::Error(GL_OUT_OF_MEMORY); @@ -326,69 +368,63 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib, } else { - int totalCount = StreamingBufferElementCount(attrib, count, instances); + size_t totalCount = ComputeVertexAttributeElementCount(attrib, count, instances); gl::Error error = mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); if (error.isError()) { return error; } - error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, firstVertexIndex, - totalCount, instances, &streamOffset); + error = mStreamingBuffer->storeVertexAttributes( + attrib, translated->currentValueType, firstVertexIndex, + static_cast(totalCount), instances, &streamOffset, sourceData); if (error.isError()) { return error; } } - translated->storage = directStorage ? storage : NULL; - translated->vertexBuffer = vertexBuffer->getVertexBuffer(); - translated->serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); - translated->divisor = attrib.divisor; - - translated->attribute = &attrib; - translated->currentValueType = currentValue.Type; + translated->storage = nullptr; + translated->serial = vertexBuffer->getSerial(); translated->stride = outputElementSize; translated->offset = streamOffset; return gl::Error(GL_NO_ERROR); } -gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, +gl::Error VertexDataManager::storeCurrentValue(const gl::VertexAttribCurrentValueData ¤tValue, TranslatedAttribute *translated, - gl::VertexAttribCurrentValueData *cachedValue, - size_t *cachedOffset, - StreamingVertexBufferInterface *buffer) + CurrentValueState *cachedState) { - if (*cachedValue != currentValue) + if (cachedState->data != currentValue) { - gl::Error error = buffer->reserveVertexSpace(attrib, 1, 0); + const gl::VertexAttribute &attrib = *translated->attribute; + + gl::Error error = cachedState->buffer->reserveVertexSpace(attrib, 1, 0); if (error.isError()) { return error; } + const uint8_t *sourceData = reinterpret_cast(currentValue.FloatValues); unsigned int streamOffset; - error = buffer->storeVertexAttributes(attrib, currentValue, 0, 1, 0, &streamOffset); + error = cachedState->buffer->storeVertexAttributes(attrib, currentValue.Type, 0, 1, 0, &streamOffset, sourceData); if (error.isError()) { return error; } - *cachedValue = currentValue; - *cachedOffset = streamOffset; + cachedState->data = currentValue; + cachedState->offset = streamOffset; } translated->storage = NULL; - translated->vertexBuffer = buffer->getVertexBuffer(); - translated->serial = buffer->getSerial(); + translated->vertexBuffer = cachedState->buffer->getVertexBuffer(); + translated->serial = cachedState->buffer->getSerial(); translated->divisor = 0; - translated->attribute = &attrib; - translated->currentValueType = currentValue.Type; translated->stride = 0; - translated->offset = *cachedOffset; + translated->offset = static_cast(cachedState->offset); return gl::Error(GL_NO_ERROR); } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h index 898ed340b8..fb349c4cc2 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h @@ -30,9 +30,18 @@ class VertexBuffer; struct TranslatedAttribute { - TranslatedAttribute() : active(false), attribute(NULL), currentValueType(GL_NONE), - offset(0), stride(0), vertexBuffer(NULL), storage(NULL), - serial(0), divisor(0) {}; + TranslatedAttribute() + : active(false), + attribute(NULL), + currentValueType(GL_NONE), + offset(0), + stride(0), + vertexBuffer(NULL), + storage(NULL), + serial(0), + divisor(0) + {} + bool active; const gl::VertexAttribute *attribute; @@ -52,42 +61,46 @@ class VertexDataManager : angle::NonCopyable VertexDataManager(BufferFactoryD3D *factory); virtual ~VertexDataManager(); - gl::Error prepareVertexData(const gl::State &state, GLint start, GLsizei count, - TranslatedAttribute *outAttribs, GLsizei instances); + gl::Error prepareVertexData(const gl::State &state, + GLint start, + GLsizei count, + std::vector *translatedAttribs, + GLsizei instances); private: - gl::Error reserveSpaceForAttrib(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, + struct CurrentValueState + { + CurrentValueState(); + ~CurrentValueState(); + + StreamingVertexBufferInterface *buffer; + gl::VertexAttribCurrentValueData data; + size_t offset; + }; + + gl::Error reserveSpaceForAttrib(const TranslatedAttribute &translatedAttrib, GLsizei count, GLsizei instances) const; - void invalidateMatchingStaticData(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue) const; - - gl::Error storeAttribute(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, - TranslatedAttribute *translated, + gl::Error storeAttribute(TranslatedAttribute *translated, GLint start, GLsizei count, GLsizei instances); - gl::Error storeCurrentValue(const gl::VertexAttribute &attrib, - const gl::VertexAttribCurrentValueData ¤tValue, + gl::Error storeCurrentValue(const gl::VertexAttribCurrentValueData ¤tValue, TranslatedAttribute *translated, - gl::VertexAttribCurrentValueData *cachedValue, - size_t *cachedOffset, - StreamingVertexBufferInterface *buffer); + CurrentValueState *cachedState); void hintUnmapAllResources(const std::vector &vertexAttributes); BufferFactoryD3D *const mFactory; StreamingVertexBufferInterface *mStreamingBuffer; + std::vector mCurrentValueCache; - gl::VertexAttribCurrentValueData mCurrentValue[gl::MAX_VERTEX_ATTRIBS]; - - StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS]; - std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS]; + // Cache variables + std::vector mActiveEnabledAttributes; + std::vector mActiveDisabledAttributes; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h new file mode 100644 index 0000000000..58f65f6496 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/WorkaroundsD3D.h @@ -0,0 +1,66 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// WorkaroundsD3D.h: Workarounds for D3D driver bugs and other issues. + +#ifndef LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_ +#define LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_ + +// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate +// independent of ANGLE's renderer. Workarounds should also be accessible +// outside of the Renderer. + +namespace rx +{ +struct D3DCompilerWorkarounds +{ + D3DCompilerWorkarounds() + : skipOptimization(false), useMaxOptimization(false), enableIEEEStrictness(false) + { + } + + bool skipOptimization; + bool useMaxOptimization; + + // IEEE strictness needs to be enabled for NANs to work. + bool enableIEEEStrictness; +}; + +struct WorkaroundsD3D +{ + WorkaroundsD3D() + : mrtPerfWorkaround(false), + setDataFasterThanImageUpload(false), + zeroMaxLodWorkaround(false), + useInstancedPointSpriteEmulation(false) + { + } + + // On some systems, having extra rendertargets than necessary slows down the shader. + // We can fix this by optimizing those out of the shader. At the same time, we can + // work around a bug on some nVidia drivers that they ignore "null" render targets + // in D3D11, by compacting the active color attachments list to omit null entries. + bool mrtPerfWorkaround; + + bool setDataFasterThanImageUpload; + + // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level + // zero, and ignore the other levels). D3D11 Feature Level 10+ does this by setting MaxLOD to + // 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE. There is no + // equivalent to this in D3D11 Feature Level 9_3. This causes problems when (for example) an + // application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST + // (i.e disables mipmaps). To work around this, D3D11 FL9_3 has to create two copies of the + // texture. The textures' level zeros are identical, but only one texture has mips. + bool zeroMaxLodWorkaround; + + // Some renderers do not support Geometry Shaders so the Geometry Shader-based PointSprite + // emulation will not work. To work around this, D3D11 FL9_3 has to use a different pointsprite + // emulation that is implemented using instanced quads. + bool useInstancedPointSpriteEmulation; +}; +} + +#endif // LIBANGLE_RENDERER_D3D_WORKAROUNDSD3D_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp index e38b61709f..e951e13408 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp @@ -10,10 +10,11 @@ #include +#include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/formatutils.h" +#include "third_party/trace_event/trace_event.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h" @@ -62,7 +63,10 @@ namespace rx { -static DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource) +namespace +{ + +DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource) { ID3D11Texture2D *texture = d3d11::DynamicCastComObject(resource); if (!texture) @@ -78,9 +82,9 @@ static DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource) return desc.Format; } -static ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context, - ID3D11Resource *source, unsigned int subresource, - const gl::Extents &size, unsigned int cpuAccessFlags) +ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context, + ID3D11Resource *source, unsigned int subresource, + const gl::Extents &size, unsigned int cpuAccessFlags) { D3D11_TEXTURE2D_DESC stagingDesc; stagingDesc.Width = size.width; @@ -95,23 +99,23 @@ static ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceCo stagingDesc.MiscFlags = 0; stagingDesc.BindFlags = 0; - ID3D11Texture2D *stagingTexture = NULL; - HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture); + ID3D11Texture2D *stagingTexture = nullptr; + HRESULT result = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture); if (FAILED(result)) { ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result); - return NULL; + return nullptr; } - context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL); + context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, nullptr); return stagingTexture; } -inline static void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize, - const gl::Box &destArea, const gl::Extents &destSize, - float *x1, float *y1, float *x2, float *y2, - float *u1, float *v1, float *u2, float *v2) +inline void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + float *x1, float *y1, float *x2, float *y2, + float *u1, float *v1, float *u2, float *v2) { *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f; *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f; @@ -124,10 +128,10 @@ inline static void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Ext *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height); } -static void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, - const gl::Box &destArea, const gl::Extents &destSize, - void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, - D3D11_PRIMITIVE_TOPOLOGY *outTopology) +void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) { float x1, y1, x2, y2, u1, v1, u2, v2; GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); @@ -144,10 +148,10 @@ static void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &source *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; } -static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, - const gl::Box &destArea, const gl::Extents &destSize, - void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, - D3D11_PRIMITIVE_TOPOLOGY *outTopology) +void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) { ASSERT(sourceSize.depth > 0 && destSize.depth > 0); @@ -174,28 +178,132 @@ static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &source *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; } +inline unsigned int GetSwizzleIndex(GLenum swizzle) +{ + unsigned int colorIndex = 0; + + switch (swizzle) + { + case GL_RED: colorIndex = 0; break; + case GL_GREEN: colorIndex = 1; break; + case GL_BLUE: colorIndex = 2; break; + case GL_ALPHA: colorIndex = 3; break; + case GL_ZERO: colorIndex = 4; break; + case GL_ONE: colorIndex = 5; break; + default: UNREACHABLE(); break; + } + + return colorIndex; +} + +D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc() +{ + D3D11_BLEND_DESC desc; + memset(&desc, 0, sizeof(desc)); + desc.RenderTarget[0].BlendEnable = TRUE; + desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE; + desc.RenderTarget[0].DestBlend = D3D11_BLEND_ZERO; + desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO; + desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; + desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; + desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_RED | + D3D11_COLOR_WRITE_ENABLE_GREEN | + D3D11_COLOR_WRITE_ENABLE_BLUE; + return desc; +} + +D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = +{ + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, +}; + +D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = +{ + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, +}; + +} // namespace + Blit11::Blit11(Renderer11 *renderer) - : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters), - mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL), - mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL), - mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL), - mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL), - mSwizzleCB(NULL) + : mRenderer(renderer), + mResourcesInitialized(false), + mVertexBuffer(nullptr), + mPointSampler(nullptr), + mLinearSampler(nullptr), + mScissorEnabledRasterizerState(nullptr), + mScissorDisabledRasterizerState(nullptr), + mDepthStencilState(nullptr), + mQuad2DIL(quad2DLayout, + ArraySize(quad2DLayout), + g_VS_Passthrough2D, + ArraySize(g_VS_Passthrough2D), + "Blit11 2D input layout"), + mQuad2DVS(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), "Blit11 2D vertex shader"), + mDepthPS(g_PS_PassthroughDepth2D, + ArraySize(g_PS_PassthroughDepth2D), + "Blit11 2D depth pixel shader"), + mQuad3DIL(quad3DLayout, + ArraySize(quad3DLayout), + g_VS_Passthrough3D, + ArraySize(g_VS_Passthrough3D), + "Blit11 3D input layout"), + mQuad3DVS(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), "Blit11 3D vertex shader"), + mQuad3DGS(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), "Blit11 3D geometry shader"), + mAlphaMaskBlendState(GetAlphaMaskBlendStateDesc(), "Blit11 Alpha Mask Blend"), + mSwizzleCB(nullptr) +{ +} + +Blit11::~Blit11() +{ + freeResources(); + + mQuad2DIL.release(); + mQuad2DVS.release(); + mDepthPS.release(); + + mQuad3DIL.release(); + mQuad3DVS.release(); + mQuad3DGS.release(); + + clearShaderMap(); +} + +gl::Error Blit11::initResources() { + if (mResourcesInitialized) + { + return gl::Error(GL_NO_ERROR); + } + + TRACE_EVENT0("gpu.angle", "Blit11::initResources"); + HRESULT result; ID3D11Device *device = mRenderer->getDevice(); D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) * - 6 * renderer->getRendererCaps().max3DTextureSize; + vbDesc.ByteWidth = + static_cast(std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), + sizeof(d3d11::PositionTexCoordVertex)) * + 6 * mRenderer->getRendererCaps().max3DTextureSize); vbDesc.Usage = D3D11_USAGE_DYNAMIC; vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; vbDesc.MiscFlags = 0; vbDesc.StructureByteStride = 0; - result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); + result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit vertex buffer, HRESULT: 0x%X", + result); + } d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer"); D3D11_SAMPLER_DESC pointSamplerDesc; @@ -215,6 +323,12 @@ Blit11::Blit11(Renderer11 *renderer) result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit point sampler state, HRESULT: 0x%X", result); + } d3d11::SetDebugName(mPointSampler, "Blit11 point sampler"); D3D11_SAMPLER_DESC linearSamplerDesc; @@ -234,6 +348,12 @@ Blit11::Blit11(Renderer11 *renderer) result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit linear sampler state, HRESULT: 0x%X", result); + } d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler"); // Use a rasterizer state that will not cull so that inverted quads will not be culled @@ -251,11 +371,25 @@ Blit11::Blit11(Renderer11 *renderer) rasterDesc.ScissorEnable = TRUE; result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit scissoring rasterizer state, HRESULT: 0x%X", + result); + } d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state"); rasterDesc.ScissorEnable = FALSE; result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit no scissoring rasterizer state, HRESULT: 0x%X", + result); + } d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state"); D3D11_DEPTH_STENCIL_DESC depthStencilDesc; @@ -276,49 +410,13 @@ Blit11::Blit11(Renderer11 *renderer) result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState); ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state"); - - D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = device->CreateInputLayout(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), &mQuad2DIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad2DIL, "Blit11 2D input layout"); - - result = device->CreateVertexShader(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), NULL, &mQuad2DVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader"); - - if (renderer->isES3Capable()) + if (FAILED(result)) { - result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader"); - - D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout"); - - result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader"); - - result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader"); + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create blit depth stencil state, HRESULT: 0x%X", result); } - - buildShaderMap(); + d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state"); D3D11_BUFFER_DESC swizzleBufferDesc; swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4; @@ -328,12 +426,22 @@ Blit11::Blit11(Renderer11 *renderer) swizzleBufferDesc.MiscFlags = 0; swizzleBufferDesc.StructureByteStride = 0; - result = device->CreateBuffer(&swizzleBufferDesc, NULL, &mSwizzleCB); + result = device->CreateBuffer(&swizzleBufferDesc, nullptr, &mSwizzleCB); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + freeResources(); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create blit swizzle buffer, HRESULT: 0x%X", + result); + } d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer"); + + mResourcesInitialized = true; + + return gl::Error(GL_NO_ERROR); } -Blit11::~Blit11() +void Blit11::freeResources() { SafeRelease(mVertexBuffer); SafeRelease(mPointSampler); @@ -341,41 +449,176 @@ Blit11::~Blit11() SafeRelease(mScissorEnabledRasterizerState); SafeRelease(mScissorDisabledRasterizerState); SafeRelease(mDepthStencilState); + SafeRelease(mSwizzleCB); - SafeRelease(mQuad2DIL); - SafeRelease(mQuad2DVS); - SafeRelease(mDepthPS); - - SafeRelease(mQuad3DIL); - SafeRelease(mQuad3DVS); - SafeRelease(mQuad3DGS); + mResourcesInitialized = false; +} - SafeRelease(mSwizzleCB); +// static +Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension) +{ + if (dimension == SHADER_3D) + { + if (isSigned) + { + switch (destinationFormat) + { + case GL_RGBA_INTEGER: return BLITSHADER_3D_RGBAI; + case GL_RGB_INTEGER: return BLITSHADER_3D_RGBI; + case GL_RG_INTEGER: return BLITSHADER_3D_RGI; + case GL_RED_INTEGER: return BLITSHADER_3D_RI; + default: + UNREACHABLE(); + return BLITSHADER_INVALID; + } + } + else + { + switch (destinationFormat) + { + case GL_RGBA: return BLITSHADER_3D_RGBAF; + case GL_RGBA_INTEGER: return BLITSHADER_3D_RGBAUI; + case GL_BGRA_EXT: return BLITSHADER_3D_BGRAF; + case GL_RGB: return BLITSHADER_3D_RGBF; + case GL_RGB_INTEGER: return BLITSHADER_3D_RGBUI; + case GL_RG: return BLITSHADER_3D_RGF; + case GL_RG_INTEGER: return BLITSHADER_3D_RGUI; + case GL_RED: return BLITSHADER_3D_RF; + case GL_RED_INTEGER: return BLITSHADER_3D_RUI; + case GL_ALPHA: return BLITSHADER_3D_ALPHA; + case GL_LUMINANCE: return BLITSHADER_3D_LUMA; + case GL_LUMINANCE_ALPHA: return BLITSHADER_3D_LUMAALPHA; + default: + UNREACHABLE(); + return BLITSHADER_INVALID; + } + } + } + else if (isSigned) + { + switch (destinationFormat) + { + case GL_RGBA_INTEGER: return BLITSHADER_2D_RGBAI; + case GL_RGB_INTEGER: return BLITSHADER_2D_RGBI; + case GL_RG_INTEGER: return BLITSHADER_2D_RGI; + case GL_RED_INTEGER: return BLITSHADER_2D_RI; + default: + UNREACHABLE(); + return BLITSHADER_INVALID; + } + } + else + { + switch (destinationFormat) + { + case GL_RGBA: return BLITSHADER_2D_RGBAF; + case GL_RGBA_INTEGER: return BLITSHADER_2D_RGBAUI; + case GL_BGRA_EXT: return BLITSHADER_2D_BGRAF; + case GL_RGB: return BLITSHADER_2D_RGBF; + case GL_RGB_INTEGER: return BLITSHADER_2D_RGBUI; + case GL_RG: return BLITSHADER_2D_RGF; + case GL_RG_INTEGER: return BLITSHADER_2D_RGUI; + case GL_RED: return BLITSHADER_2D_RF; + case GL_RED_INTEGER: return BLITSHADER_2D_RUI; + case GL_ALPHA: return BLITSHADER_2D_ALPHA; + case GL_LUMINANCE: return BLITSHADER_2D_LUMA; + case GL_LUMINANCE_ALPHA: return BLITSHADER_2D_LUMAALPHA; + default: + UNREACHABLE(); + return BLITSHADER_INVALID; + } + } +} - clearShaderMap(); +// static +Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality) +{ + switch (dimensionality) + { + case D3D11_SRV_DIMENSION_TEXTURE2D: + switch (type) + { + case GL_FLOAT: return SWIZZLESHADER_2D_FLOAT; + case GL_UNSIGNED_INT: return SWIZZLESHADER_2D_UINT; + case GL_INT: return SWIZZLESHADER_2D_INT; + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } + case D3D11_SRV_DIMENSION_TEXTURECUBE: + switch (type) + { + case GL_FLOAT: return SWIZZLESHADER_CUBE_FLOAT; + case GL_UNSIGNED_INT: return SWIZZLESHADER_CUBE_UINT; + case GL_INT: return SWIZZLESHADER_CUBE_INT; + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } + case D3D11_SRV_DIMENSION_TEXTURE3D: + switch (type) + { + case GL_FLOAT: return SWIZZLESHADER_3D_FLOAT; + case GL_UNSIGNED_INT: return SWIZZLESHADER_3D_UINT; + case GL_INT: return SWIZZLESHADER_3D_INT; + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + switch (type) + { + case GL_FLOAT: return SWIZZLESHADER_ARRAY_FLOAT; + case GL_UNSIGNED_INT: return SWIZZLESHADER_ARRAY_UINT; + case GL_INT: return SWIZZLESHADER_ARRAY_INT; + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } + default: + UNREACHABLE(); + return SWIZZLESHADER_INVALID; + } } -static inline unsigned int GetSwizzleIndex(GLenum swizzle) +Blit11::ShaderSupport Blit11::getShaderSupport(const Shader &shader) { - unsigned int colorIndex = 0; + ID3D11Device *device = mRenderer->getDevice(); + ShaderSupport support; - switch (swizzle) + if (shader.dimension == SHADER_2D) { - case GL_RED: colorIndex = 0; break; - case GL_GREEN: colorIndex = 1; break; - case GL_BLUE: colorIndex = 2; break; - case GL_ALPHA: colorIndex = 3; break; - case GL_ZERO: colorIndex = 4; break; - case GL_ONE: colorIndex = 5; break; - default: UNREACHABLE(); break; + support.inputLayout = mQuad2DIL.resolve(device); + support.vertexShader = mQuad2DVS.resolve(device); + support.geometryShader = nullptr; + support.vertexWriteFunction = Write2DVertices; + } + else + { + ASSERT(shader.dimension == SHADER_3D); + support.inputLayout = mQuad3DIL.resolve(device); + support.vertexShader = mQuad3DVS.resolve(device); + support.geometryShader = mQuad3DGS.resolve(device); + support.vertexWriteFunction = Write3DVertices; } - return colorIndex; + return support; } -gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, - GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, + ID3D11RenderTargetView *dest, + const gl::Extents &size, + GLenum swizzleRed, + GLenum swizzleGreen, + GLenum swizzleBlue, + GLenum swizzleAlpha) { + gl::Error error = initResources(); + if (error.isError()) + { + return error; + } + HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -404,19 +647,13 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT break; } - SwizzleParameters parameters = { 0 }; - parameters.mDestinationType = shaderType; - parameters.mViewDimension = sourceSRVDesc.ViewDimension; - - SwizzleShaderMap::const_iterator i = mSwizzleShaderMap.find(parameters); - if (i == mSwizzleShaderMap.end()) + const Shader *shader = nullptr; + error = getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader); + if (error.isError()) { - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION, "Internal error, missing swizzle shader."); + return error; } - const Shader &shader = i->second; - // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); @@ -425,13 +662,15 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for swizzle, HRESULT: 0x%X.", result); } + const ShaderSupport &support = getShaderSupport(*shader); + UINT stride = 0; UINT startIdx = 0; UINT drawCount = 0; D3D11_PRIMITIVE_TOPOLOGY topology; gl::Box area(0, 0, 0, size.width, size.height, size.depth); - shader.mVertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology); + support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology); deviceContext->Unmap(mVertexBuffer, 0); @@ -457,20 +696,21 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB); // Apply state - deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); deviceContext->RSSetState(mScissorDisabledRasterizerState); // Apply shaders - deviceContext->IASetInputLayout(shader.mInputLayout); + deviceContext->IASetInputLayout(support.inputLayout); deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); + deviceContext->VSSetShader(support.vertexShader, nullptr, 0); - deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); - deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); + deviceContext->PSSetShader(shader->pixelShader, nullptr, 0); + deviceContext->GSSetShader(support.geometryShader, nullptr, 0); // Unset the currently bound shader resource to avoid conflicts - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + auto stateManager = mRenderer->getStateManager(); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); // Apply render target mRenderer->setOneTimeRenderTarget(dest); @@ -479,14 +719,14 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = size.width; - viewport.Height = size.height; + viewport.Width = static_cast(size.width); + viewport.Height = static_cast(size.height); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source); // Apply samplers deviceContext->PSSetSamplers(0, 1, &mPointSampler); @@ -495,12 +735,12 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT deviceContext->Draw(drawCount, 0); // Unbind textures and render targets and vertex buffer - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); mRenderer->unapplyRenderTargets(); UINT zero = 0; - ID3D11Buffer *const nullBuffer = NULL; + ID3D11Buffer *const nullBuffer = nullptr; deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); mRenderer->markAllStateDirty(); @@ -508,10 +748,23 @@ gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderT return gl::Error(GL_NO_ERROR); } -gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, GLenum destFormat, GLenum filter) +gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + GLenum destFormat, + GLenum filter, + bool maskOffAlpha) { + gl::Error error = initResources(); + if (error.isError()) + { + return error; + } + HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -523,19 +776,17 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); - BlitParameters parameters = { 0 }; - parameters.mDestinationFormat = destFormat; - parameters.mSignedInteger = (internalFormatInfo.componentType == GL_INT); - parameters.m3DBlit = sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D; + bool isSigned = (internalFormatInfo.componentType == GL_INT); + ShaderDimension dimension = (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D; - BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters); - if (i == mBlitShaderMap.end()) + const Shader *shader = nullptr; + error = getBlitShader(destFormat, isSigned, dimension, &shader); + if (error.isError()) { - UNREACHABLE(); - return gl::Error(GL_OUT_OF_MEMORY, "Could not find appropriate shader for internal texture blit."); + return error; } - const Shader& shader = i->second; + const ShaderSupport &support = getShaderSupport(*shader); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; @@ -550,7 +801,7 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s UINT drawCount = 0; D3D11_PRIMITIVE_TOPOLOGY topology; - shader.mVertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, + support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride, &drawCount, &topology); deviceContext->Unmap(mVertexBuffer, 0); @@ -559,8 +810,17 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); // Apply state - deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + if (maskOffAlpha) + { + ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice()); + ASSERT(blendState); + deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF); + } + else + { + deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + } + deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); if (scissor) { @@ -579,15 +839,16 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s } // Apply shaders - deviceContext->IASetInputLayout(shader.mInputLayout); + deviceContext->IASetInputLayout(support.inputLayout); deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); + deviceContext->VSSetShader(support.vertexShader, nullptr, 0); - deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); - deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); + deviceContext->PSSetShader(shader->pixelShader, nullptr, 0); + deviceContext->GSSetShader(support.geometryShader, nullptr, 0); // Unset the currently bound shader resource to avoid conflicts - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + auto stateManager = mRenderer->getStateManager(); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); // Apply render target mRenderer->setOneTimeRenderTarget(dest); @@ -596,17 +857,17 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = destSize.width; - viewport.Height = destSize.height; + viewport.Width = static_cast(destSize.width); + viewport.Height = static_cast(destSize.height); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source); // Apply samplers - ID3D11SamplerState *sampler = NULL; + ID3D11SamplerState *sampler = nullptr; switch (filter) { case GL_NEAREST: sampler = mPointSampler; break; @@ -622,12 +883,12 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s deviceContext->Draw(drawCount, 0); // Unbind textures and render targets and vertex buffer - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); mRenderer->unapplyRenderTargets(); UINT zero = 0; - ID3D11Buffer *const nullBuffer = NULL; + ID3D11Buffer *const nullBuffer = nullptr; deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); mRenderer->markAllStateDirty(); @@ -648,6 +909,12 @@ gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sou ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, const gl::Rectangle *scissor) { + gl::Error error = initResources(); + if (error.isError()) + { + return error; + } + HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -673,7 +940,7 @@ gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sou deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); // Apply state - deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF); if (scissor) @@ -692,32 +959,40 @@ gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sou deviceContext->RSSetState(mScissorDisabledRasterizerState); } + ID3D11Device *device = mRenderer->getDevice(); + ID3D11VertexShader *quad2DVS = mQuad2DVS.resolve(device); + if (quad2DVS == nullptr) + { + return gl::Error(GL_INVALID_OPERATION, "Error compiling internal 2D blit vertex shader"); + } + // Apply shaders - deviceContext->IASetInputLayout(mQuad2DIL); + deviceContext->IASetInputLayout(mQuad2DIL.resolve(device)); deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(mQuad2DVS, NULL, 0); + deviceContext->VSSetShader(quad2DVS, nullptr, 0); - deviceContext->PSSetShader(mDepthPS, NULL, 0); - deviceContext->GSSetShader(NULL, NULL, 0); + deviceContext->PSSetShader(mDepthPS.resolve(device), nullptr, 0); + deviceContext->GSSetShader(nullptr, nullptr, 0); // Unset the currently bound shader resource to avoid conflicts - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + auto stateManager = mRenderer->getStateManager(); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); // Apply render target - deviceContext->OMSetRenderTargets(0, NULL, dest); + deviceContext->OMSetRenderTargets(0, nullptr, dest); // Set the viewport D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = destSize.width; - viewport.Height = destSize.height; + viewport.Width = static_cast(destSize.width); + viewport.Height = static_cast(destSize.height); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source); // Apply samplers deviceContext->PSSetSamplers(0, 1, &mPointSampler); @@ -726,12 +1001,12 @@ gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sou deviceContext->Draw(drawCount, 0); // Unbind textures and render targets and vertex buffer - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); mRenderer->unapplyRenderTargets(); UINT zero = 0; - ID3D11Buffer *const nullBuffer = NULL; + ID3D11Buffer *const nullBuffer = nullptr; deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); mRenderer->markAllStateDirty(); @@ -752,6 +1027,12 @@ gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSu ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, const gl::Rectangle *scissor, bool stencilOnly) { + gl::Error error = initResources(); + if (error.isError()) + { + return error; + } + ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -826,7 +1107,7 @@ gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSu float yPerc = static_cast(y - destArea.y) / (destArea.height - 1); // Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges - unsigned int readRow = gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1); + unsigned int readRow = static_cast(gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1)); unsigned int writeRow = y; if (wholeRowCopy) @@ -848,7 +1129,7 @@ gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSu float xPerc = static_cast(x - destArea.x) / (destArea.width - 1); // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges - unsigned int readColumn = gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1); + unsigned int readColumn = static_cast(gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1)); unsigned int writeColumn = x; void *sourcePixel = reinterpret_cast(sourceMapping.pData) + @@ -868,14 +1149,14 @@ gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSu // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion // according to MSDN. - deviceContext->UpdateSubresource(dest, destSubresource, NULL, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch); + deviceContext->UpdateSubresource(dest, destSubresource, nullptr, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch); deviceContext->Unmap(sourceStaging, 0); deviceContext->Unmap(destStaging, 0); // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some // systems when called repeatedly. - // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, NULL); + // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, nullptr); SafeRelease(sourceStaging); SafeRelease(destStaging); @@ -883,177 +1164,242 @@ gl::Error Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSu return gl::Error(GL_NO_ERROR); } -bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b) +void Blit11::addBlitShaderToMap(BlitShaderType blitShaderType, ShaderDimension dimension, ID3D11PixelShader *ps) { - return memcmp(&a, &b, sizeof(Blit11::BlitParameters)) < 0; -} + ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end()); + ASSERT(ps); -bool Blit11::compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b) -{ - return memcmp(&a, &b, sizeof(Blit11::SwizzleParameters)) < 0; + Shader shader; + shader.dimension = dimension; + shader.pixelShader = ps; + + mBlitShaderMap[blitShaderType] = shader; } -void Blit11::add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) +void Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, ShaderDimension dimension, ID3D11PixelShader *ps) { - BlitParameters params = { 0 }; - params.mDestinationFormat = destFormat; - params.mSignedInteger = signedInteger; - params.m3DBlit = false; - - ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); + ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end()); ASSERT(ps); Shader shader; - shader.mVertexWriteFunction = Write2DVertices; - shader.mInputLayout = mQuad2DIL; - shader.mVertexShader = mQuad2DVS; - shader.mGeometryShader = NULL; - shader.mPixelShader = ps; + shader.dimension = dimension; + shader.pixelShader = ps; - mBlitShaderMap[params] = shader; + mSwizzleShaderMap[swizzleShaderType] = shader; } -void Blit11::add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) +void Blit11::clearShaderMap() { - BlitParameters params = { 0 }; - params.mDestinationFormat = destFormat; - params.mSignedInteger = signedInteger; - params.m3DBlit = true; - - ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); - ASSERT(ps); - - Shader shader; - shader.mVertexWriteFunction = Write3DVertices; - shader.mInputLayout = mQuad3DIL; - shader.mVertexShader = mQuad3DVS; - shader.mGeometryShader = mQuad3DGS; - shader.mPixelShader = ps; + for (auto &blitShader : mBlitShaderMap) + { + SafeRelease(blitShader.second.pixelShader); + } + mBlitShaderMap.clear(); - mBlitShaderMap[params] = shader; + for (auto &swizzleShader : mSwizzleShaderMap) + { + SafeRelease(swizzleShader.second.pixelShader); + } + mSwizzleShaderMap.clear(); } -void Blit11::addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps) +gl::Error Blit11::getBlitShader(GLenum destFormat, bool isSigned, ShaderDimension dimension, const Shader **shader) { - SwizzleParameters params = { 0 }; - params.mDestinationType = destType; - params.mViewDimension = viewDimension; + BlitShaderType blitShaderType = GetBlitShaderType(destFormat, isSigned, dimension); - ASSERT(mSwizzleShaderMap.find(params) == mSwizzleShaderMap.end()); - ASSERT(ps); + if (blitShaderType == BLITSHADER_INVALID) + { + return gl::Error(GL_INVALID_OPERATION, "Internal blit shader type mismatch"); + } - Shader shader; - switch (viewDimension) + auto blitShaderIt = mBlitShaderMap.find(blitShaderType); + if (blitShaderIt != mBlitShaderMap.end()) { - case D3D_SRV_DIMENSION_TEXTURE2D: - shader.mVertexWriteFunction = Write2DVertices; - shader.mInputLayout = mQuad2DIL; - shader.mVertexShader = mQuad2DVS; - shader.mGeometryShader = NULL; - break; + *shader = &blitShaderIt->second; + return gl::Error(GL_NO_ERROR); + } - case D3D_SRV_DIMENSION_TEXTURE3D: - case D3D_SRV_DIMENSION_TEXTURE2DARRAY: - case D3D_SRV_DIMENSION_TEXTURECUBE: - shader.mVertexWriteFunction = Write3DVertices; - shader.mInputLayout = mQuad3DIL; - shader.mVertexShader = mQuad3DVS; - shader.mGeometryShader = mQuad3DGS; - break; + ASSERT(dimension == SHADER_2D || mRenderer->isES3Capable()); + ID3D11Device *device = mRenderer->getDevice(); + + switch (blitShaderType) + { + case BLITSHADER_2D_RGBAF: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader")); + break; + case BLITSHADER_2D_BGRAF: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader")); + break; + case BLITSHADER_2D_RGBF: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader")); + break; + case BLITSHADER_2D_RGF: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader")); + break; + case BLITSHADER_2D_RF: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader")); + break; + case BLITSHADER_2D_ALPHA: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader")); + break; + case BLITSHADER_2D_LUMA: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader")); + break; + case BLITSHADER_2D_LUMAALPHA: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader")); + break; + case BLITSHADER_2D_RGBAUI: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader")); + break; + case BLITSHADER_2D_RGBAI: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader")); + break; + case BLITSHADER_2D_RGBUI: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader")); + break; + case BLITSHADER_2D_RGBI: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader")); + break; + case BLITSHADER_2D_RGUI: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader")); + break; + case BLITSHADER_2D_RGI: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader")); + break; + case BLITSHADER_2D_RUI: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader")); + break; + case BLITSHADER_2D_RI: + addBlitShaderToMap(blitShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader")); + break; + case BLITSHADER_3D_RGBAF: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader")); + break; + case BLITSHADER_3D_RGBAUI: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader")); + break; + case BLITSHADER_3D_RGBAI: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader")); + break; + case BLITSHADER_3D_BGRAF: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader")); + break; + case BLITSHADER_3D_RGBF: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader")); + break; + case BLITSHADER_3D_RGBUI: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader")); + break; + case BLITSHADER_3D_RGBI: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader")); + break; + case BLITSHADER_3D_RGF: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader")); + break; + case BLITSHADER_3D_RGUI: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader")); + break; + case BLITSHADER_3D_RGI: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader")); + break; + case BLITSHADER_3D_RF: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader")); + break; + case BLITSHADER_3D_RUI: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader")); + break; + case BLITSHADER_3D_RI: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader")); + break; + case BLITSHADER_3D_ALPHA: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader")); + break; + case BLITSHADER_3D_LUMA: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader")); + break; + case BLITSHADER_3D_LUMAALPHA: + addBlitShaderToMap(blitShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); + break; default: UNREACHABLE(); - break; + return gl::Error(GL_INVALID_OPERATION, "Internal error"); } - shader.mPixelShader = ps; - mSwizzleShaderMap[params] = shader; + blitShaderIt = mBlitShaderMap.find(blitShaderType); + ASSERT(blitShaderIt != mBlitShaderMap.end()); + *shader = &blitShaderIt->second; + return gl::Error(GL_NO_ERROR); } -void Blit11::buildShaderMap() +gl::Error Blit11::getSwizzleShader(GLenum type, D3D11_SRV_DIMENSION viewDimension, const Shader **shader) { - ID3D11Device *device = mRenderer->getDevice(); + SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension); - // 2D shaders (OpenGL ES 2+) - add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" )); - add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" )); - add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" )); - add2DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader" )); - add2DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader" )); - add2DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader" )); - add2DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader" )); - add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader")); - - // 2D shaders (OpenGL ES 3+) - if (mRenderer->isES3Capable()) + if (swizzleShaderType == SWIZZLESHADER_INVALID) { - add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" )); - add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" )); - add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" )); - add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" )); - add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" )); - add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" )); - add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" )); - add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" )); + return gl::Error(GL_INVALID_OPERATION, "Swizzle shader type not found"); } - // 3D shaders (OpenGL ES 3+) - if (mRenderer->isES3Capable()) + auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType); + if (swizzleShaderIt != mSwizzleShaderMap.end()) { - add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" )); - add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" )); - add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); - add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" )); - add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" )); - add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" )); - add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" )); - add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); - add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" )); - add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" )); - add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); - add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" )); - add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" )); - add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" )); - add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" )); - add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); + *shader = &swizzleShaderIt->second; + return gl::Error(GL_NO_ERROR); } // Swizzling shaders (OpenGL ES 3+) - if (mRenderer->isES3Capable()) - { - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" )); - - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader" )); + ASSERT(mRenderer->isES3Capable()); - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader" )); - - addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader" )); - addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader")); - addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader" )); - } -} + ID3D11Device *device = mRenderer->getDevice(); -void Blit11::clearShaderMap() -{ - for (BlitShaderMap::iterator i = mBlitShaderMap.begin(); i != mBlitShaderMap.end(); ++i) + switch (swizzleShaderType) { - Shader &shader = i->second; - SafeRelease(shader.mPixelShader); + case SWIZZLESHADER_2D_FLOAT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader")); + break; + case SWIZZLESHADER_2D_UINT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); + break; + case SWIZZLESHADER_2D_INT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_FLOAT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_UINT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_INT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_FLOAT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_UINT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_INT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_FLOAT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_UINT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_INT: + addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader")); + break; + default: + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION, "Internal error"); } - mBlitShaderMap.clear(); - for (SwizzleShaderMap::iterator i = mSwizzleShaderMap.begin(); i != mSwizzleShaderMap.end(); ++i) - { - Shader &shader = i->second; - SafeRelease(shader.mPixelShader); - } - mSwizzleShaderMap.clear(); + swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType); + ASSERT(swizzleShaderIt != mSwizzleShaderMap.end()); + *shader = &swizzleShaderIt->second; + return gl::Error(GL_NO_ERROR); } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h index d3a8c2c8a3..906616131e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h @@ -12,6 +12,7 @@ #include "common/angleutils.h" #include "libANGLE/angletypes.h" #include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include @@ -28,9 +29,16 @@ class Blit11 : angle::NonCopyable gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); - gl::Error copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, GLenum destFormat, GLenum filter); + gl::Error copyTexture(ID3D11ShaderResourceView *source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + GLenum destFormat, + GLenum filter, + bool maskOffAlpha); gl::Error copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, @@ -45,59 +53,112 @@ class Blit11 : angle::NonCopyable const gl::Rectangle *scissor); private: - Renderer11 *mRenderer; - - struct BlitParameters + enum BlitShaderType { - GLenum mDestinationFormat; - bool mSignedInteger; - bool m3DBlit; + BLITSHADER_INVALID, + BLITSHADER_2D_RGBAF, + BLITSHADER_2D_BGRAF, + BLITSHADER_2D_RGBF, + BLITSHADER_2D_RGF, + BLITSHADER_2D_RF, + BLITSHADER_2D_ALPHA, + BLITSHADER_2D_LUMA, + BLITSHADER_2D_LUMAALPHA, + BLITSHADER_2D_RGBAUI, + BLITSHADER_2D_RGBAI, + BLITSHADER_2D_RGBUI, + BLITSHADER_2D_RGBI, + BLITSHADER_2D_RGUI, + BLITSHADER_2D_RGI, + BLITSHADER_2D_RUI, + BLITSHADER_2D_RI, + BLITSHADER_3D_RGBAF, + BLITSHADER_3D_RGBAUI, + BLITSHADER_3D_RGBAI, + BLITSHADER_3D_BGRAF, + BLITSHADER_3D_RGBF, + BLITSHADER_3D_RGBUI, + BLITSHADER_3D_RGBI, + BLITSHADER_3D_RGF, + BLITSHADER_3D_RGUI, + BLITSHADER_3D_RGI, + BLITSHADER_3D_RF, + BLITSHADER_3D_RUI, + BLITSHADER_3D_RI, + BLITSHADER_3D_ALPHA, + BLITSHADER_3D_LUMA, + BLITSHADER_3D_LUMAALPHA, }; - gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, - const gl::Rectangle *scissor, bool stencilOnly); - - static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b); + enum SwizzleShaderType + { + SWIZZLESHADER_INVALID, + SWIZZLESHADER_2D_FLOAT, + SWIZZLESHADER_2D_UINT, + SWIZZLESHADER_2D_INT, + SWIZZLESHADER_CUBE_FLOAT, + SWIZZLESHADER_CUBE_UINT, + SWIZZLESHADER_CUBE_INT, + SWIZZLESHADER_3D_FLOAT, + SWIZZLESHADER_3D_UINT, + SWIZZLESHADER_3D_INT, + SWIZZLESHADER_ARRAY_FLOAT, + SWIZZLESHADER_ARRAY_UINT, + SWIZZLESHADER_ARRAY_INT, + }; typedef void (*WriteVertexFunction)(const gl::Box &sourceArea, const gl::Extents &sourceSize, const gl::Box &destArea, const gl::Extents &destSize, void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, D3D11_PRIMITIVE_TOPOLOGY *outTopology); - struct Shader + enum ShaderDimension { - WriteVertexFunction mVertexWriteFunction; - ID3D11InputLayout *mInputLayout; - ID3D11VertexShader *mVertexShader; - ID3D11GeometryShader *mGeometryShader; - ID3D11PixelShader *mPixelShader; + SHADER_2D, + SHADER_3D, }; - typedef bool (*BlitParametersComparisonFunction)(const BlitParameters&, const BlitParameters &); - typedef std::map BlitShaderMap; - BlitShaderMap mBlitShaderMap; - - void add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); - void add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); + struct Shader + { + ShaderDimension dimension; + ID3D11PixelShader *pixelShader; + }; - struct SwizzleParameters + struct ShaderSupport { - GLenum mDestinationType; - D3D11_SRV_DIMENSION mViewDimension; + ID3D11InputLayout *inputLayout; + ID3D11VertexShader *vertexShader; + ID3D11GeometryShader *geometryShader; + WriteVertexFunction vertexWriteFunction; }; - static bool compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b); + gl::Error initResources(); + void freeResources(); + + ShaderSupport getShaderSupport(const Shader &shader); + + static BlitShaderType GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension); + static SwizzleShaderType GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality); + + gl::Error copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, bool stencilOnly); + + void addBlitShaderToMap(BlitShaderType blitShaderType, ShaderDimension dimension, ID3D11PixelShader *ps); - typedef bool (*SwizzleParametersComparisonFunction)(const SwizzleParameters&, const SwizzleParameters &); - typedef std::map SwizzleShaderMap; - SwizzleShaderMap mSwizzleShaderMap; + gl::Error getBlitShader(GLenum destFormat, bool isSigned, ShaderDimension dimension, const Shader **shaderOut); + gl::Error getSwizzleShader(GLenum type, D3D11_SRV_DIMENSION viewDimension, const Shader **shaderOut); - void addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps); + void addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, ShaderDimension dimension, ID3D11PixelShader *ps); - void buildShaderMap(); void clearShaderMap(); + Renderer11 *mRenderer; + + std::map mBlitShaderMap; + std::map mSwizzleShaderMap; + + bool mResourcesInitialized; ID3D11Buffer *mVertexBuffer; ID3D11SamplerState *mPointSampler; ID3D11SamplerState *mLinearSampler; @@ -105,13 +166,15 @@ class Blit11 : angle::NonCopyable ID3D11RasterizerState *mScissorDisabledRasterizerState; ID3D11DepthStencilState *mDepthStencilState; - ID3D11InputLayout *mQuad2DIL; - ID3D11VertexShader *mQuad2DVS; - ID3D11PixelShader *mDepthPS; + d3d11::LazyInputLayout mQuad2DIL; + d3d11::LazyShader mQuad2DVS; + d3d11::LazyShader mDepthPS; + + d3d11::LazyInputLayout mQuad3DIL; + d3d11::LazyShader mQuad3DVS; + d3d11::LazyShader mQuad3DGS; - ID3D11InputLayout *mQuad3DIL; - ID3D11VertexShader *mQuad3DVS; - ID3D11GeometryShader *mQuad3DGS; + d3d11::LazyBlendState mAlphaMaskBlendState; ID3D11Buffer *mSwizzleCB; }; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp index d56b0ea7ad..0d5dc08b03 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -8,10 +8,27 @@ #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include + #include "common/MemoryBuffer.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +namespace +{ + +template +GLuint ReadIndexValueFromIndices(const uint8_t *data, size_t index) +{ + return reinterpret_cast(data)[index]; +} +typedef GLuint (*ReadIndexValueFunction)(const uint8_t *data, size_t index); +} + #if defined(ANGLE_MINGW32_COMPAT) typedef enum D3D11_MAP_FLAG { D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000 @@ -20,32 +37,33 @@ typedef enum D3D11_MAP_FLAG { namespace rx { - PackPixelsParams::PackPixelsParams() - : format(GL_NONE), - type(GL_NONE), - outputPitch(0), - packBuffer(NULL), - offset(0) -{} - -PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, GLenum formatIn, GLenum typeIn, GLuint outputPitchIn, - const gl::PixelPackState &packIn, ptrdiff_t offsetIn) - : area(areaIn), - format(formatIn), - type(typeIn), - outputPitch(outputPitchIn), - packBuffer(packIn.pixelBuffer.get()), - pack(packIn.alignment, packIn.reverseRowOrder), - offset(offsetIn) -{} + : format(GL_NONE), type(GL_NONE), outputPitch(0), packBuffer(nullptr), offset(0) +{ +} + +PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, + GLenum formatIn, + GLenum typeIn, + GLuint outputPitchIn, + const gl::PixelPackState &packIn, + ptrdiff_t offsetIn) + : area(areaIn), + format(formatIn), + type(typeIn), + outputPitch(outputPitchIn), + packBuffer(packIn.pixelBuffer.get()), + pack(packIn.alignment, packIn.reverseRowOrder), + offset(offsetIn) +{ +} namespace gl_d3d11 { D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) { - bool readBit = ((access & GL_MAP_READ_BIT) != 0); + bool readBit = ((access & GL_MAP_READ_BIT) != 0); bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0); ASSERT(readBit || writeBit); @@ -71,7 +89,6 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) return D3D11_MAP_READ; } } - } // Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points @@ -91,8 +108,10 @@ class Buffer11::BufferStorage : angle::NonCopyable virtual bool isMappable() const = 0; - virtual bool copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) = 0; + virtual bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) = 0; virtual gl::Error resize(size_t size, bool preserveData) = 0; virtual uint8_t *map(size_t offset, size_t length, GLbitfield access) = 0; @@ -120,20 +139,57 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; } ID3D11Buffer *getNativeStorage() const { return mNativeStorage; } - - bool copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) override; + bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; gl::Error resize(size_t size, bool preserveData) override; uint8_t *map(size_t offset, size_t length, GLbitfield access) override; void unmap() override; private: - static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize); + static void fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, + Renderer11 *renderer, + BufferUsage usage, + unsigned int bufferSize); ID3D11Buffer *mNativeStorage; }; +// A emulated indexed buffer storage represents an underlying D3D11 buffer for data +// that has been expanded to match the indices list used. This storage is only +// used for FL9_3 pointsprite rendering emulation. +class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage +{ + public: + EmulatedIndexedStorage(Renderer11 *renderer); + ~EmulatedIndexedStorage() override; + + bool isMappable() const override { return true; } + + ID3D11Buffer *getNativeStorage(); + + bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + + gl::Error resize(size_t size, bool preserveData) override; + + uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + void unmap() override; + bool update(SourceIndexData *indexInfo, const TranslatedAttribute *attribute); + + private: + ID3D11Buffer *mNativeStorage; // contains expanded data for use by D3D + MemoryBuffer mMemoryBuffer; // original data (not expanded) + MemoryBuffer mIndicesMemoryBuffer; // indices data + SourceIndexData mIndexInfo; // indices information + size_t mAttributeStride; // per element stride in bytes + size_t mAttributeOffset; // starting offset +}; + // Pack storage represents internal storage for pack buffers. We implement pack buffers // as CPU memory, tied to a staging texture, for asynchronous texture readback. class Buffer11::PackStorage : public Buffer11::BufferStorage @@ -143,24 +199,24 @@ class Buffer11::PackStorage : public Buffer11::BufferStorage ~PackStorage() override; bool isMappable() const override { return true; } - - bool copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) override; + bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; gl::Error resize(size_t size, bool preserveData) override; uint8_t *map(size_t offset, size_t length, GLbitfield access) override; void unmap() override; - gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + gl::Error packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms); private: gl::Error flushQueuedPackCommand(); - ID3D11Texture2D *mStagingTexture; - DXGI_FORMAT mTextureFormat; - gl::Extents mTextureSize; + TextureHelper11 mStagingTexture; MemoryBuffer mMemoryBuffer; - PackPixelsParams *mQueuedPackCommand; + std::unique_ptr mQueuedPackCommand; PackPixelsParams mPackParams; bool mDataModified; }; @@ -175,9 +231,10 @@ class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage ~SystemMemoryStorage() override {} bool isMappable() const override { return true; } - - bool copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) override; + bool copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; gl::Error resize(size_t size, bool preserveData) override; uint8_t *map(size_t offset, size_t length, GLbitfield access) override; @@ -193,23 +250,27 @@ Buffer11::Buffer11(Renderer11 *renderer) : BufferD3D(renderer), mRenderer(renderer), mSize(0), - mMappedStorage(NULL), - mReadUsageCount(0), - mHasSystemMemoryStorage(false) -{} + mMappedStorage(nullptr), + mBufferStorages(BUFFER_USAGE_COUNT, nullptr), + mConstantBufferStorageAdditionalSize(0), + mMaxConstantBufferLruCount(0), + mReadUsageCount(0) +{ +} Buffer11::~Buffer11() { - for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + for (auto &storage : mBufferStorages) { - SafeDelete(it->second); + SafeDelete(storage); } -} -Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(Buffer11*, buffer)); - return static_cast(buffer); + for (auto &p : mConstantBufferRangeStoragesCache) + { + SafeDelete(p.second.storage); + } + + mRenderer->onBufferDelete(this); } gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) @@ -220,18 +281,14 @@ gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) return error; } - if (usage == GL_STATIC_DRAW) - { - initializeStaticData(); - } - + updateD3DBufferUsage(usage); return error; } gl::Error Buffer11::getData(const uint8_t **outData) { SystemMemoryStorage *systemMemoryStorage = nullptr; - gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); + gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); if (error.isError()) { @@ -310,15 +367,18 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) } mSize = std::max(mSize, requiredSize); - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } -gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +gl::Error Buffer11::copySubData(BufferImpl *source, + GLintptr sourceOffset, + GLintptr destOffset, + GLsizeiptr size) { - Buffer11 *sourceBuffer = makeBuffer11(source); - ASSERT(sourceBuffer != NULL); + Buffer11 *sourceBuffer = GetAs(source); + ASSERT(sourceBuffer != nullptr); BufferStorage *copyDest = getLatestBufferStorage(); if (!copyDest) @@ -363,19 +423,26 @@ gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLint copyDest->setDataRevision(copyDest->getDataRevision() + 1); mSize = std::max(mSize, destOffset + size); - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } -gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +gl::Error Buffer11::map(GLenum access, GLvoid **mapPtr) +{ + // GL_OES_mapbuffer uses an enum instead of a bitfield for it's access, convert to a bitfield + // and call mapRange. + ASSERT(access == GL_WRITE_ONLY_OES); + return mapRange(0, mSize, GL_MAP_WRITE_BIT, mapPtr); +} + +gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) { ASSERT(!mMappedStorage); BufferStorage *latestStorage = getLatestBufferStorage(); - if (latestStorage && - (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || - latestStorage->getUsage() == BUFFER_USAGE_STAGING)) + if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || + latestStorage->getUsage() == BUFFER_USAGE_STAGING)) { // Latest storage is mappable. mMappedStorage = latestStorage; @@ -396,6 +463,7 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid { // Update the data revision immediately, since the data might be changed at any time mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); } uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access); @@ -408,24 +476,29 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid return gl::Error(GL_NO_ERROR); } -gl::Error Buffer11::unmap() +gl::Error Buffer11::unmap(GLboolean *result) { ASSERT(mMappedStorage); mMappedStorage->unmap(); - mMappedStorage = NULL; + mMappedStorage = nullptr; + + // TODO: detect if we had corruption. if so, return false. + *result = GL_TRUE; + return gl::Error(GL_NO_ERROR); } void Buffer11::markTransformFeedbackUsage() { - BufferStorage *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + BufferStorage *transformFeedbackStorage = + getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); if (transformFeedbackStorage) { transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); } - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); } void Buffer11::markBufferUsage() @@ -435,14 +508,13 @@ void Buffer11::markBufferUsage() // Free the system memory storage if we decide it isn't being used very often. const unsigned int usageLimit = 5; - if (mReadUsageCount > usageLimit && mHasSystemMemoryStorage) + BufferStorage *&sysMemUsage = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY]; + if (mReadUsageCount > usageLimit && sysMemUsage != nullptr) { - auto systemMemoryStorageIt = mBufferStorages.find(BUFFER_USAGE_SYSTEM_MEMORY); - ASSERT(systemMemoryStorageIt != mBufferStorages.end()); - - SafeDelete(systemMemoryStorageIt->second); - mBufferStorages.erase(systemMemoryStorageIt); - mHasSystemMemoryStorage = false; + if (getLatestBufferStorage() != sysMemUsage) + { + SafeDelete(sysMemUsage); + } } } @@ -455,12 +527,59 @@ ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) if (!bufferStorage) { // Storage out-of-memory - return NULL; + return nullptr; } - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, bufferStorage)); + return GetAs(bufferStorage)->getNativeStorage(); +} + +ID3D11Buffer *Buffer11::getEmulatedIndexedBuffer(SourceIndexData *indexInfo, + const TranslatedAttribute *attribute) +{ + markBufferUsage(); + + assert(indexInfo != nullptr); + assert(attribute != nullptr); - return static_cast(bufferStorage)->getNativeStorage(); + BufferStorage *bufferStorage = getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX); + if (!bufferStorage) + { + // Storage out-of-memory + return nullptr; + } + + EmulatedIndexedStorage *emulatedStorage = GetAs(bufferStorage); + if (!emulatedStorage->update(indexInfo, attribute)) + { + // Storage out-of-memory + return nullptr; + } + + return emulatedStorage->getNativeStorage(); +} + +ID3D11Buffer *Buffer11::getConstantBufferRange(GLintptr offset, GLsizeiptr size) +{ + markBufferUsage(); + + BufferStorage *bufferStorage; + + if (offset == 0) + { + bufferStorage = getBufferStorage(BUFFER_USAGE_UNIFORM); + } + else + { + bufferStorage = getConstantBufferRangeStorage(offset, size); + } + + if (!bufferStorage) + { + // Storage out-of-memory + return nullptr; + } + + return GetAs(bufferStorage)->getNativeStorage(); } ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) @@ -470,11 +589,10 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) if (!storage) { // Storage out-of-memory - return NULL; + return nullptr; } - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, storage)); - ID3D11Buffer *buffer = static_cast(storage)->getNativeStorage(); + ID3D11Buffer *buffer = GetAs(storage)->getNativeStorage(); auto bufferSRVIt = mBufferResourceViews.find(srvFormat); @@ -491,16 +609,17 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) } } - ID3D11Device *device = mRenderer->getDevice(); - ID3D11ShaderResourceView *bufferSRV = NULL; + ID3D11Device *device = mRenderer->getDevice(); + ID3D11ShaderResourceView *bufferSRV = nullptr; const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat); D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; bufferSRVDesc.Buffer.ElementOffset = 0; - bufferSRVDesc.Buffer.ElementWidth = mSize / dxgiFormatInfo.pixelBytes; - bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - bufferSRVDesc.Format = srvFormat; + bufferSRVDesc.Buffer.ElementWidth = + static_cast(mSize) / dxgiFormatInfo.pixelBytes; + bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + bufferSRVDesc.Format = srvFormat; HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV); UNUSED_ASSERTION_VARIABLE(result); @@ -511,14 +630,15 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) return bufferSRV; } -gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) +gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms) { - PackStorage *packStorage = getPackStorage(); + PackStorage *packStorage = getPackStorage(); BufferStorage *latestStorage = getLatestBufferStorage(); if (packStorage) { - gl::Error error = packStorage->packPixels(srcTexture, srcSubresource, params); + gl::Error error = packStorage->packPixels(readAttachment, params); if (error.isError()) { return error; @@ -529,14 +649,23 @@ gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, return gl::Error(GL_NO_ERROR); } +size_t Buffer11::getTotalCPUBufferMemoryBytes() const +{ + size_t allocationSize = 0; + + BufferStorage *staging = mBufferStorages[BUFFER_USAGE_STAGING]; + allocationSize += staging ? staging->getSize() : 0; + + BufferStorage *sysMem = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY]; + allocationSize += sysMem ? sysMem->getSize() : 0; + + return allocationSize; +} + Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) { - BufferStorage *newStorage = NULL; - auto directBufferIt = mBufferStorages.find(usage); - if (directBufferIt != mBufferStorages.end()) - { - newStorage = directBufferIt->second; - } + ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT); + BufferStorage *&newStorage = mBufferStorages[usage]; if (!newStorage) { @@ -547,15 +676,16 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) else if (usage == BUFFER_USAGE_SYSTEM_MEMORY) { newStorage = new SystemMemoryStorage(mRenderer); - mHasSystemMemoryStorage = true; + } + else if (usage == BUFFER_USAGE_EMULATED_INDEXED_VERTEX) + { + newStorage = new EmulatedIndexedStorage(mRenderer); } else { // buffer is not allocated, create it newStorage = new NativeStorage(mRenderer, usage); } - - mBufferStorages.insert(std::make_pair(usage, newStorage)); } // resize buffer @@ -564,19 +694,88 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) if (newStorage->resize(mSize, true).isError()) { // Out of memory error - return NULL; + return nullptr; + } + } + + updateBufferStorage(newStorage, 0, mSize); + + return newStorage; +} + +Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size) +{ + BufferStorage *newStorage; + + { + // Keep the cacheEntry in a limited scope because it may be invalidated later in the code if + // we need to reclaim some space. + ConstantBufferCacheEntry *cacheEntry = &mConstantBufferRangeStoragesCache[offset]; + + if (!cacheEntry->storage) + { + cacheEntry->storage = new NativeStorage(mRenderer, BUFFER_USAGE_UNIFORM); + cacheEntry->lruCount = ++mMaxConstantBufferLruCount; } + + cacheEntry->lruCount = ++mMaxConstantBufferLruCount; + newStorage = cacheEntry->storage; } + if (newStorage->getSize() < static_cast(size)) + { + size_t maximumAllowedAdditionalSize = 2 * getSize(); + + size_t sizeDelta = size - newStorage->getSize(); + + while (mConstantBufferStorageAdditionalSize + sizeDelta > maximumAllowedAdditionalSize) + { + auto iter = std::min_element(std::begin(mConstantBufferRangeStoragesCache), + std::end(mConstantBufferRangeStoragesCache), + [](const ConstantBufferCache::value_type &a, + const ConstantBufferCache::value_type &b) + { + return a.second.lruCount < b.second.lruCount; + }); + + ASSERT(iter->second.storage != newStorage); + ASSERT(mConstantBufferStorageAdditionalSize >= iter->second.storage->getSize()); + + mConstantBufferStorageAdditionalSize -= iter->second.storage->getSize(); + SafeDelete(iter->second.storage); + mConstantBufferRangeStoragesCache.erase(iter); + } + + if (newStorage->resize(size, false).isError()) + { + // Out of memory error + return nullptr; + } + + mConstantBufferStorageAdditionalSize += sizeDelta; + + // We don't copy the old data when resizing the constant buffer because the data may be + // out-of-date therefore we reset the data revision and let updateBufferStorage() handle the + // copy. + newStorage->setDataRevision(0); + } + + updateBufferStorage(newStorage, offset, size); + + return newStorage; +} + +void Buffer11::updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize) +{ BufferStorage *latestBuffer = getLatestBufferStorage(); - if (latestBuffer && latestBuffer->getDataRevision() > newStorage->getDataRevision()) + if (latestBuffer && latestBuffer->getDataRevision() > storage->getDataRevision()) { // Copy through a staging buffer if we're copying from or to a non-staging, mappable // buffer storage. This is because we can't map a GPU buffer, and copy CPU // data directly. If we're already using a staging buffer we're fine. if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING && - newStorage->getUsage() != BUFFER_USAGE_STAGING && - (!latestBuffer->isMappable() || !newStorage->isMappable())) + storage->getUsage() != BUFFER_USAGE_STAGING && + (!latestBuffer->isMappable() || !storage->isMappable())) { NativeStorage *stagingBuffer = getStagingStorage(); @@ -588,28 +787,25 @@ Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) // if copyFromStorage returns true, the D3D buffer has been recreated // and we should update our serial - if (newStorage->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) + if (storage->copyFromStorage(latestBuffer, sourceOffset, storageSize, 0)) { updateSerial(); } - newStorage->setDataRevision(latestBuffer->getDataRevision()); + storage->setDataRevision(latestBuffer->getDataRevision()); } - - return newStorage; } Buffer11::BufferStorage *Buffer11::getLatestBufferStorage() const { // Even though we iterate over all the direct buffers, it is expected that only // 1 or 2 will be present. - BufferStorage *latestStorage = NULL; + BufferStorage *latestStorage = nullptr; DataRevision latestRevision = 0; - for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + for (auto &storage : mBufferStorages) { - BufferStorage *storage = it->second; - if (!latestStorage || storage->getDataRevision() > latestRevision) + if (storage && (!latestStorage || storage->getDataRevision() > latestRevision)) { - latestStorage = storage; + latestStorage = storage; latestRevision = storage->getDataRevision(); } } @@ -620,7 +816,7 @@ Buffer11::BufferStorage *Buffer11::getLatestBufferStorage() const if (latestStorage->resize(mSize, true).isError()) { // Out of memory error - return NULL; + return nullptr; } } @@ -634,11 +830,10 @@ Buffer11::NativeStorage *Buffer11::getStagingStorage() if (!stagingStorage) { // Out-of-memory - return NULL; + return nullptr; } - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, stagingStorage)); - return static_cast(stagingStorage); + return GetAs(stagingStorage); } Buffer11::PackStorage *Buffer11::getPackStorage() @@ -648,11 +843,10 @@ Buffer11::PackStorage *Buffer11::getPackStorage() if (!packStorage) { // Out-of-memory - return NULL; + return nullptr; } - ASSERT(HAS_DYNAMIC_TYPE(PackStorage*, packStorage)); - return static_cast(packStorage); + return GetAs(packStorage); } bool Buffer11::supportsDirectBinding() const @@ -664,10 +858,7 @@ bool Buffer11::supportsDirectBinding() const } Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) - : mRenderer(renderer), - mUsage(usage), - mRevision(0), - mBufferSize(0) + : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0) { } @@ -689,8 +880,7 @@ gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, s } Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage) - : BufferStorage(renderer, usage), - mNativeStorage(NULL) + : BufferStorage(renderer, usage), mNativeStorage(nullptr) { } @@ -700,19 +890,21 @@ Buffer11::NativeStorage::~NativeStorage() } // Returns true if it recreates the direct buffer -bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) +bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) { ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - size_t requiredSize = sourceOffset + size; - bool createBuffer = !mNativeStorage || mBufferSize < requiredSize; + size_t requiredSize = destOffset + size; + bool createBuffer = !mNativeStorage || mBufferSize < requiredSize; // (Re)initialize D3D buffer if needed if (createBuffer) { bool preserveData = (destOffset > 0); - resize(source->getSize(), preserveData); + resize(requiredSize, preserveData); } if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK || @@ -724,8 +916,12 @@ bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sour D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource); - UNUSED_ASSERTION_VARIABLE(hr); ASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) + { + source->unmap(); + return false; + } uint8_t *destPointer = static_cast(mappedResource.pData) + destOffset; @@ -738,20 +934,18 @@ bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sour } else { - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source)); - D3D11_BOX srcBox; - srcBox.left = sourceOffset; - srcBox.right = sourceOffset + size; - srcBox.top = 0; + srcBox.left = static_cast(sourceOffset); + srcBox.right = static_cast(sourceOffset + size); + srcBox.top = 0; srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; + srcBox.front = 0; + srcBox.back = 1; - ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source)); - ID3D11Buffer *sourceBuffer = static_cast(source)->getNativeStorage(); + ID3D11Buffer *sourceBuffer = GetAs(source)->getNativeStorage(); - context->CopySubresourceRegion(mNativeStorage, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox); + context->CopySubresourceRegion(mNativeStorage, 0, static_cast(destOffset), 0, + 0, sourceBuffer, 0, &srcBox); } return createBuffer; @@ -759,32 +953,35 @@ bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sour gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) { - ID3D11Device *device = mRenderer->getDevice(); + ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); D3D11_BUFFER_DESC bufferDesc; - fillBufferDesc(&bufferDesc, mRenderer, mUsage, size); + fillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast(size)); ID3D11Buffer *newBuffer; - HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); + HRESULT result = device->CreateBuffer(&bufferDesc, nullptr, &newBuffer); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", result); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", + result); } + d3d11::SetDebugName(newBuffer, "Buffer11::NativeStorage"); + if (mNativeStorage && preserveData) { // We don't call resize if the buffer is big enough already. ASSERT(mBufferSize <= size); D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = mBufferSize; - srcBox.top = 0; + srcBox.left = 0; + srcBox.right = static_cast(mBufferSize); + srcBox.top = 0; srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; + srcBox.front = 0; + srcBox.back = 1; context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox); } @@ -798,58 +995,62 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) return gl::Error(GL_NO_ERROR); } -void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, - BufferUsage usage, unsigned int bufferSize) +void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, + Renderer11 *renderer, + BufferUsage usage, + unsigned int bufferSize) { - bufferDesc->ByteWidth = bufferSize; - bufferDesc->MiscFlags = 0; + bufferDesc->ByteWidth = bufferSize; + bufferDesc->MiscFlags = 0; bufferDesc->StructureByteStride = 0; switch (usage) { - case BUFFER_USAGE_STAGING: - bufferDesc->Usage = D3D11_USAGE_STAGING; - bufferDesc->BindFlags = 0; - bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - break; + case BUFFER_USAGE_STAGING: + bufferDesc->Usage = D3D11_USAGE_STAGING; + bufferDesc->BindFlags = 0; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + break; - case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; + case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; - if (renderer->isES3Capable()) - { - bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; - } + if (renderer->isES3Capable()) + { + bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; + } - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_INDEX: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_PIXEL_UNPACK: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_UNIFORM: - bufferDesc->Usage = D3D11_USAGE_DYNAMIC; - bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER; - bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - - // Constant buffers must be of a limited size, and aligned to 16 byte boundaries - // For our purposes we ignore any buffer data past the maximum constant buffer size - bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u); - bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize); - break; - - default: - UNREACHABLE(); + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_INDEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_PIXEL_UNPACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_UNIFORM: + bufferDesc->Usage = D3D11_USAGE_DYNAMIC; + bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + // Constant buffers must be of a limited size, and aligned to 16 byte boundaries + // For our purposes we ignore any buffer data past the maximum constant buffer size + bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u); + bufferDesc->ByteWidth = + std::min(bufferDesc->ByteWidth, + static_cast(renderer->getRendererCaps().maxUniformBlockSize)); + break; + + default: + UNREACHABLE(); } } @@ -859,14 +1060,16 @@ uint8_t *Buffer11::NativeStorage::map(size_t offset, size_t length, GLbitfield a D3D11_MAPPED_SUBRESOURCE mappedResource; ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access); - UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); + D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access); + UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource); - UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); - - return static_cast(mappedResource.pData) + offset; + if (FAILED(result)) + { + return nullptr; + } + return static_cast(mappedResource.pData) + offset; } void Buffer11::NativeStorage::unmap() @@ -876,23 +1079,189 @@ void Buffer11::NativeStorage::unmap() context->Unmap(mNativeStorage, 0); } +Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer) + : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr) +{ +} + +Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage() +{ + SafeRelease(mNativeStorage); +} + +ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage() +{ + if (!mNativeStorage) + { + // Expand the memory storage upon request and cache the results. + unsigned int expandedDataSize = + static_cast((mIndexInfo.srcCount * mAttributeStride) + mAttributeOffset); + MemoryBuffer expandedData; + if (!expandedData.resize(expandedDataSize)) + { + return nullptr; + } + + // Clear the contents of the allocated buffer + ZeroMemory(expandedData.data(), expandedDataSize); + + uint8_t *curr = expandedData.data(); + const uint8_t *ptr = static_cast(mIndexInfo.srcIndices); + + // Ensure that we start in the correct place for the emulated data copy operation to + // maintain offset behaviors. + curr += mAttributeOffset; + + ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices; + + switch (mIndexInfo.srcIndexType) + { + case GL_UNSIGNED_INT: + readIndexValue = ReadIndexValueFromIndices; + break; + case GL_UNSIGNED_SHORT: + readIndexValue = ReadIndexValueFromIndices; + break; + case GL_UNSIGNED_BYTE: + readIndexValue = ReadIndexValueFromIndices; + break; + } + + // Iterate over the cached index data and copy entries indicated into the emulated buffer. + for (GLuint i = 0; i < mIndexInfo.srcCount; i++) + { + GLuint idx = readIndexValue(ptr, i); + memcpy(curr, mMemoryBuffer.data() + (mAttributeStride * idx), mAttributeStride); + curr += mAttributeStride; + } + + // Finally, initialize the emulated indexed native storage object with the newly copied data + // and free the temporary buffers used. + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = expandedDataSize; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + bufferDesc.Usage = D3D11_USAGE_DEFAULT; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + + D3D11_SUBRESOURCE_DATA subResourceData = {expandedData.data(), 0, 0}; + + HRESULT result = device->CreateBuffer(&bufferDesc, &subResourceData, &mNativeStorage); + if (FAILED(result)) + { + ERR("Could not create emulated index data buffer: %08lX", result); + return nullptr; + } + d3d11::SetDebugName(mNativeStorage, "Buffer11::EmulatedIndexedStorage"); + } + + return mNativeStorage; +} + +bool Buffer11::EmulatedIndexedStorage::update(SourceIndexData *indexInfo, + const TranslatedAttribute *attribute) +{ + // If a change in the indices applied from the last draw call is detected, then the emulated + // indexed buffer needs to be invalidated. After invalidation, the change detected flag should + // be cleared to avoid unnecessary recreation of the buffer. + if (mNativeStorage == nullptr || indexInfo->srcIndicesChanged) + { + SafeRelease(mNativeStorage); + + // Copy attribute offset and stride information + mAttributeStride = attribute->stride; + mAttributeOffset = attribute->offset; + + // Copy the source index data. This ensures that the lifetime of the indices pointer + // stays with this storage until the next time we invalidate. + size_t indicesDataSize = 0; + switch (indexInfo->srcIndexType) + { + case GL_UNSIGNED_INT: + indicesDataSize = sizeof(GLuint) * indexInfo->srcCount; + break; + case GL_UNSIGNED_SHORT: + indicesDataSize = sizeof(GLushort) * indexInfo->srcCount; + break; + case GL_UNSIGNED_BYTE: + indicesDataSize = sizeof(GLubyte) * indexInfo->srcCount; + break; + default: + indicesDataSize = sizeof(GLushort) * indexInfo->srcCount; + break; + } + + if (!mIndicesMemoryBuffer.resize(indicesDataSize)) + { + return false; + } + + memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize); + + // Copy the source index data description and update the srcIndices pointer to point + // to our cached index data. + mIndexInfo = *indexInfo; + mIndexInfo.srcIndices = mIndicesMemoryBuffer.data(); + + indexInfo->srcIndicesChanged = false; + } + return true; +} + +bool Buffer11::EmulatedIndexedStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) +{ + ASSERT(source->isMappable()); + const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT); + ASSERT(destOffset + size <= mMemoryBuffer.size()); + memcpy(mMemoryBuffer.data() + destOffset, sourceData, size); + source->unmap(); + return true; +} + +gl::Error Buffer11::EmulatedIndexedStorage::resize(size_t size, bool preserveData) +{ + if (mMemoryBuffer.size() < size) + { + if (!mMemoryBuffer.resize(size)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize EmulatedIndexedStorage"); + } + mBufferSize = size; + } + + return gl::Error(GL_NO_ERROR); +} + +uint8_t *Buffer11::EmulatedIndexedStorage::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size()); + return mMemoryBuffer.data() + offset; +} + +void Buffer11::EmulatedIndexedStorage::unmap() +{ + // No-op +} + Buffer11::PackStorage::PackStorage(Renderer11 *renderer) - : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), - mStagingTexture(NULL), - mTextureFormat(DXGI_FORMAT_UNKNOWN), - mQueuedPackCommand(NULL), - mDataModified(false) + : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false) { } Buffer11::PackStorage::~PackStorage() { - SafeRelease(mStagingTexture); - SafeDelete(mQueuedPackCommand); } -bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) +bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) { // We copy through a staging buffer when drawing with a pack buffer, // or for other cases where we access the pack buffer @@ -925,7 +1294,7 @@ uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield acc gl::Error error = flushQueuedPackCommand(); if (error.isError()) { - return NULL; + return nullptr; } mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); @@ -938,7 +1307,8 @@ void Buffer11::PackStorage::unmap() // No-op } -gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) +gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms) { gl::Error error = flushQueuedPackCommand(); if (error.isError()) @@ -946,54 +1316,37 @@ gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT src return error; } - mQueuedPackCommand = new PackPixelsParams(params); - - D3D11_TEXTURE2D_DESC textureDesc; - srcTexure->GetDesc(&textureDesc); - - if (mStagingTexture != NULL && - (mTextureFormat != textureDesc.Format || - mTextureSize.width != params.area.width || - mTextureSize.height != params.area.height)) + RenderTarget11 *renderTarget = nullptr; + error = readAttachment.getRenderTarget(&renderTarget); + if (error.isError()) { - SafeRelease(mStagingTexture); - mTextureSize.width = 0; - mTextureSize.height = 0; - mTextureFormat = DXGI_FORMAT_UNKNOWN; + return error; } - if (mStagingTexture == NULL) + ID3D11Resource *renderTargetResource = renderTarget->getTexture(); + ASSERT(renderTargetResource); + + unsigned int srcSubresource = renderTarget->getSubresourceIndex(); + TextureHelper11 srcTexture = TextureHelper11::MakeAndReference(renderTargetResource); + + mQueuedPackCommand.reset(new PackPixelsParams(params)); + + gl::Extents srcTextureSize(params.area.width, params.area.height, 1); + if (!mStagingTexture.getResource() || mStagingTexture.getFormat() != srcTexture.getFormat() || + mStagingTexture.getExtents() != srcTextureSize) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT hr; - - mTextureSize.width = params.area.width; - mTextureSize.height = params.area.height; - mTextureFormat = textureDesc.Format; - - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = params.area.width; - stagingDesc.Height = params.area.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = mTextureFormat; - stagingDesc.SampleDesc.Count = 1; - stagingDesc.SampleDesc.Quality = 0; - stagingDesc.Usage = D3D11_USAGE_STAGING; - stagingDesc.BindFlags = 0; - stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - stagingDesc.MiscFlags = 0; - - hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture); - if (FAILED(hr)) + auto textureOrError = + CreateStagingTexture(srcTexture.getTextureType(), srcTexture.getFormat(), + srcTextureSize, mRenderer->getDevice()); + if (textureOrError.isError()) { - ASSERT(hr == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging texture."); + return textureOrError.getError(); } + mStagingTexture = std::move(textureOrError.getResult()); } // ReadPixels from multisampled FBOs isn't supported in current GL - ASSERT(textureDesc.SampleDesc.Count <= 1); + ASSERT(srcTexture.getSampleCount() <= 1); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); D3D11_BOX srcBox; @@ -1001,11 +1354,18 @@ gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT src srcBox.right = params.area.x + params.area.width; srcBox.top = params.area.y; srcBox.bottom = params.area.y + params.area.height; - srcBox.front = 0; - srcBox.back = 1; + + // Select the correct layer from a 3D attachment + srcBox.front = 0; + if (mStagingTexture.getTextureType() == GL_TEXTURE_3D) + { + srcBox.front = static_cast(readAttachment.layer()); + } + srcBox.back = srcBox.front + 1; // Asynchronous copy - immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox); + immediateContext->CopySubresourceRegion(mStagingTexture.getResource(), 0, 0, 0, 0, + srcTexture.getResource(), srcSubresource, &srcBox); return gl::Error(GL_NO_ERROR); } @@ -1016,8 +1376,9 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand() if (mQueuedPackCommand) { - gl::Error error = mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); - SafeDelete(mQueuedPackCommand); + gl::Error error = + mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); + mQueuedPackCommand.reset(nullptr); if (error.isError()) { return error; @@ -1029,10 +1390,13 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand() Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer) : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY) -{} +{ +} -bool Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset, - size_t size, size_t destOffset) +bool Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) { ASSERT(source->isMappable()); const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT); @@ -1066,5 +1430,4 @@ void Buffer11::SystemMemoryStorage::unmap() { // No-op } - } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h index 39bafe880e..a748db57ae 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h @@ -9,12 +9,21 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ +#include + #include "libANGLE/angletypes.h" #include "libANGLE/renderer/d3d/BufferD3D.h" +namespace gl +{ +class FramebufferAttachment; +} + namespace rx { class Renderer11; +struct SourceIndexData; +struct TranslatedAttribute; enum BufferUsage { @@ -25,6 +34,9 @@ enum BufferUsage BUFFER_USAGE_PIXEL_PACK, BUFFER_USAGE_UNIFORM, BUFFER_USAGE_SYSTEM_MEMORY, + BUFFER_USAGE_EMULATED_INDEXED_VERTEX, + + BUFFER_USAGE_COUNT, }; struct PackPixelsParams @@ -50,28 +62,32 @@ class Buffer11 : public BufferD3D Buffer11(Renderer11 *renderer); virtual ~Buffer11(); - static Buffer11 *makeBuffer11(BufferImpl *buffer); - ID3D11Buffer *getBuffer(BufferUsage usage); + ID3D11Buffer *getEmulatedIndexedBuffer(SourceIndexData *indexInfo, const TranslatedAttribute *attribute); + ID3D11Buffer *getConstantBufferRange(GLintptr offset, GLsizeiptr size); ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); bool isMapped() const { return mMappedStorage != NULL; } - gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + gl::Error packPixels(const gl::FramebufferAttachment &readAttachment, + const PackPixelsParams ¶ms); + size_t getTotalCPUBufferMemoryBytes() const; // BufferD3D implementation virtual size_t getSize() const { return mSize; } virtual bool supportsDirectBinding() const; + gl::Error getData(const uint8_t **outData) override; // BufferImpl implementation virtual gl::Error setData(const void* data, size_t size, GLenum usage); - gl::Error getData(const uint8_t **outData) override; virtual gl::Error setSubData(const void* data, size_t size, size_t offset); virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); - virtual gl::Error unmap(); + virtual gl::Error map(GLenum access, GLvoid **mapPtr); + virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); + virtual gl::Error unmap(GLboolean *result); virtual void markTransformFeedbackUsage(); private: class BufferStorage; + class EmulatedIndexedStorage; class NativeStorage; class PackStorage; class SystemMemoryStorage; @@ -81,21 +97,41 @@ class Buffer11 : public BufferD3D BufferStorage *mMappedStorage; - std::map mBufferStorages; + std::vector mBufferStorages; + + struct ConstantBufferCacheEntry + { + ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) { } + + BufferStorage *storage; + unsigned int lruCount; + }; + + // Cache of D3D11 constant buffer for specific ranges of buffer data. + // This is used to emulate UBO ranges on 11.0 devices. + // Constant buffers are indexed by there start offset. + typedef std::map ConstantBufferCache; + ConstantBufferCache mConstantBufferRangeStoragesCache; + size_t mConstantBufferStorageAdditionalSize; + unsigned int mMaxConstantBufferLruCount; typedef std::pair BufferSRVPair; std::map mBufferResourceViews; unsigned int mReadUsageCount; - bool mHasSystemMemoryStorage; void markBufferUsage(); NativeStorage *getStagingStorage(); PackStorage *getPackStorage(); gl::Error getSystemMemoryStorage(SystemMemoryStorage **storageOut); + void updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize); BufferStorage *getBufferStorage(BufferUsage usage); BufferStorage *getLatestBufferStorage() const; + + BufferStorage *getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size); + + void invalidateEmulatedIndexedBuffer(); }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp index 057c3bed42..cd95c65d1c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp @@ -17,6 +17,7 @@ #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "third_party/trace_event/trace_event.h" // Precompiled shaders #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h" @@ -44,7 +45,7 @@ static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangl float bottom = 1.0f; // Clip the quad coordinates to the scissor if needed - if (scissor != NULL) + if (scissor != nullptr) { left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f); right = std::min(right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f); @@ -58,35 +59,46 @@ static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangl d3d11::SetPositionDepthColorVertex(vertices + 3, right, top, depthClear, color); } -template -Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]) +Clear11::ClearShader::ClearShader(DXGI_FORMAT colorType, + const char *inputLayoutName, + const BYTE *vsByteCode, + size_t vsSize, + const char *vsDebugName, + const BYTE *psByteCode, + size_t psSize, + const char *psDebugName) + : inputLayout(nullptr), + vertexShader(vsByteCode, vsSize, vsDebugName), + pixelShader(psByteCode, psSize, psDebugName) { - HRESULT result; - - ClearShader shader = { 0 }; - D3D11_INPUT_ELEMENT_DESC quadLayout[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, { "COLOR", 0, colorType, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - result = device->CreateInputLayout(quadLayout, ArraySize(quadLayout), vsByteCode, vsSize, &shader.inputLayout); - ASSERT(SUCCEEDED(result)); - - result = device->CreateVertexShader(vsByteCode, vsSize, NULL, &shader.vertexShader); - ASSERT(SUCCEEDED(result)); - - result = device->CreatePixelShader(psByteCode, psSize, NULL, &shader.pixelShader); - ASSERT(SUCCEEDED(result)); + inputLayout = new d3d11::LazyInputLayout(quadLayout, 2, vsByteCode, vsSize, inputLayoutName); +} - return shader; +Clear11::ClearShader::~ClearShader() +{ + SafeDelete(inputLayout); + vertexShader.release(); + pixelShader.release(); } Clear11::Clear11(Renderer11 *renderer) - : mRenderer(renderer), mClearBlendStates(StructLessThan), mClearDepthStencilStates(StructLessThan), - mVertexBuffer(NULL), mRasterizerState(NULL), mSupportsClearView(false) + : mRenderer(renderer), + mClearBlendStates(StructLessThan), + mFloatClearShader(nullptr), + mUintClearShader(nullptr), + mIntClearShader(nullptr), + mClearDepthStencilStates(StructLessThan), + mVertexBuffer(nullptr), + mRasterizerState(nullptr) { + TRACE_EVENT0("gpu.angle", "Clear11::Clear11"); + HRESULT result; ID3D11Device *device = renderer->getDevice(); @@ -98,7 +110,7 @@ Clear11::Clear11(Renderer11 *renderer) vbDesc.MiscFlags = 0; vbDesc.StructureByteStride = 0; - result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); + result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); @@ -118,29 +130,48 @@ Clear11::Clear11(Renderer11 *renderer) ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); - if (renderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) { - mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat_FL9); + mFloatClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT, + "Clear11 Float IL", + g_VS_ClearFloat, + ArraySize(g_VS_ClearFloat), + "Clear11 Float VS", + g_PS_ClearFloat_FL9, + ArraySize(g_PS_ClearFloat_FL9), + "Clear11 Float PS"); } else { - mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); + mFloatClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_FLOAT, + "Clear11 Float IL", + g_VS_ClearFloat, + ArraySize(g_VS_ClearFloat), + "Clear11 Float VS", + g_PS_ClearFloat, + ArraySize(g_PS_ClearFloat), + "Clear11 Float PS"); } if (renderer->isES3Capable()) { - mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); - mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); - } - -#if defined(ANGLE_ENABLE_D3D11_1) - if (renderer->getDeviceContext1IfSupported()) - { - D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; - device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); - mSupportsClearView = (d3d11Options.ClearView != FALSE); + mUintClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT, + "Clear11 UINT IL", + g_VS_ClearUint, + ArraySize(g_VS_ClearUint), + "Clear11 UINT VS", + g_PS_ClearUint, + ArraySize(g_PS_ClearUint), + "Clear11 UINT PS"); + mIntClearShader = new ClearShader(DXGI_FORMAT_R32G32B32A32_UINT, + "Clear11 SINT IL", + g_VS_ClearSint, + ArraySize(g_VS_ClearSint), + "Clear11 SINT VS", + g_PS_ClearSint, + ArraySize(g_PS_ClearSint), + "Clear11 SINT PS"); } -#endif } Clear11::~Clear11() @@ -151,20 +182,9 @@ Clear11::~Clear11() } mClearBlendStates.clear(); - SafeRelease(mFloatClearShader.inputLayout); - SafeRelease(mFloatClearShader.vertexShader); - SafeRelease(mFloatClearShader.pixelShader); - - if (mRenderer->isES3Capable()) - { - SafeRelease(mUintClearShader.inputLayout); - SafeRelease(mUintClearShader.vertexShader); - SafeRelease(mUintClearShader.pixelShader); - - SafeRelease(mIntClearShader.inputLayout); - SafeRelease(mIntClearShader.vertexShader); - SafeRelease(mIntClearShader.pixelShader); - } + SafeDelete(mFloatClearShader); + SafeDelete(mUintClearShader); + SafeDelete(mIntClearShader); for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++) { @@ -178,10 +198,10 @@ Clear11::~Clear11() gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData) { - const auto &colorAttachments = fboData.mColorAttachments; - const auto &drawBufferStates = fboData.mDrawBufferStates; - const auto *depthAttachment = fboData.mDepthAttachment; - const auto *stencilAttachment = fboData.mStencilAttachment; + const auto &colorAttachments = fboData.getColorAttachments(); + const auto &drawBufferStates = fboData.getDrawBufferStates(); + const auto *depthAttachment = fboData.getDepthAttachment(); + const auto *stencilAttachment = fboData.getStencilAttachment(); ASSERT(colorAttachments.size() == drawBufferStates.size()); @@ -206,24 +226,18 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl gl::Extents framebufferSize; - auto iter = std::find_if(colorAttachments.begin(), colorAttachments.end(), [](const gl::FramebufferAttachment *attachment) { return attachment != nullptr; }); - if (iter != colorAttachments.end()) + const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment(); + if (colorAttachment != nullptr) { - framebufferSize.width = (*iter)->getWidth(); - framebufferSize.height = (*iter)->getHeight(); - framebufferSize.depth = 1; + framebufferSize = colorAttachment->getSize(); } else if (depthAttachment != nullptr) { - framebufferSize.width = depthAttachment->getWidth(); - framebufferSize.height = depthAttachment->getHeight(); - framebufferSize.depth = 1; + framebufferSize = depthAttachment->getSize(); } else if (stencilAttachment != nullptr) { - framebufferSize.width = stencilAttachment->getWidth(); - framebufferSize.height = stencilAttachment->getHeight(); - framebufferSize.depth = 1; + framebufferSize = stencilAttachment->getSize(); } else { @@ -245,34 +259,40 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); std::vector maskedClearRenderTargets; - RenderTarget11* maskedClearDepthStencil = NULL; + RenderTarget11* maskedClearDepthStencil = nullptr; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); +#if defined(ANGLE_ENABLE_D3D11_1) ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); +#endif + ID3D11Device *device = mRenderer->getDevice(); - for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) + for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size(); + colorAttachmentIndex++) { - if (clearParams.clearColor[colorAttachment] && - colorAttachments[colorAttachment] != nullptr && - drawBufferStates[colorAttachment] != GL_NONE) - { - const gl::FramebufferAttachment *attachment = colorAttachments[colorAttachment]; + const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex]; - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); + if (clearParams.clearColor[colorAttachmentIndex] && attachment.isAttached() && + drawBufferStates[colorAttachmentIndex] != GL_NONE) + { + RenderTarget11 *renderTarget = nullptr; + gl::Error error = attachment.getRenderTarget(&renderTarget); if (error.isError()) { return error; } - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment.getInternalFormat()); if (clearParams.colorClearType == GL_FLOAT && !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED)) { - ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-" - "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, - attachment->getInternalFormat()); + ERR( + "It is undefined behaviour to clear a render buffer which is not normalized " + "fixed point or floating-" + "point to floating point values (color attachment %u has internal format " + "0x%X).", + colorAttachmentIndex, attachment.getInternalFormat()); } if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && @@ -283,7 +303,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl // Every channel either does not exist in the render target or is masked out continue; } - else if ((!mSupportsClearView && needScissoredClear) || clearParams.colorClearType != GL_FLOAT || + else if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) || clearParams.colorClearType != GL_FLOAT || (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || @@ -291,7 +311,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl { // A masked clear is required, or a scissored clear is required and ID3D11DeviceContext1::ClearView is unavailable MaskedRenderTarget maskAndRt; - bool clearColor = clearParams.clearColor[colorAttachment]; + bool clearColor = clearParams.clearColor[colorAttachmentIndex]; maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); @@ -313,7 +333,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl // Check if the actual format has a channel that the internal format does not and set them to the // default values - const float clearValues[4] = + float clearValues[4] = { ((formatInfo.redBits == 0 && dxgiFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red), ((formatInfo.greenBits == 0 && dxgiFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), @@ -321,9 +341,17 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl ((formatInfo.alphaBits == 0 && dxgiFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), }; - if (needScissoredClear) + if (dxgiFormatInfo.alphaBits == 1) { + // Some drivers do not correctly handle calling Clear() on a format with 1-bit alpha. + // They can incorrectly round all non-zero values up to 1.0f. Note that WARP does not do this. + // We should handle the rounding for them instead. + clearValues[3] = (clearParams.colorFClearValue.alpha >= 0.5f) ? 1.0f : 0.0f; + } + #if defined(ANGLE_ENABLE_D3D11_1) + if (needScissoredClear) + { // We shouldn't reach here if deviceContext1 is unavailable. ASSERT(deviceContext1); @@ -334,9 +362,9 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl rect.bottom = clearParams.scissor.y + clearParams.scissor.height; deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1); -#endif } else +#endif { deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); } @@ -349,8 +377,8 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl const gl::FramebufferAttachment *attachment = (depthAttachment != nullptr) ? depthAttachment : stencilAttachment; ASSERT(attachment != nullptr); - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget); + RenderTarget11 *renderTarget = nullptr; + gl::Error error = attachment->getRenderTarget(&renderTarget); if (error.isError()) { return error; @@ -421,7 +449,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl rtvs[i] = rtv; } - ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; + ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr; ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; @@ -433,7 +461,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl // Set the vertices UINT vertexStride = 0; const UINT startIdx = 0; - const ClearShader* shader = NULL; + ClearShader *shader = nullptr; D3D11_MAPPED_SUBRESOURCE mappedResource; HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) @@ -441,25 +469,25 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result); } - const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; + const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : nullptr; switch (clearParams.colorClearType) { case GL_FLOAT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex); - shader = &mFloatClearShader; + shader = mFloatClearShader; break; case GL_UNSIGNED_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex); - shader = &mUintClearShader; + shader = mUintClearShader; break; case GL_INT: ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); vertexStride = sizeof(d3d11::PositionDepthColorVertex); - shader = &mIntClearShader; + shader = mIntClearShader; break; default: @@ -473,8 +501,8 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = framebufferSize.width; - viewport.Height = framebufferSize.height; + viewport.Width = static_cast(framebufferSize.width); + viewport.Height = static_cast(framebufferSize.height); viewport.MinDepth = 0; viewport.MaxDepth = 1; deviceContext->RSSetViewports(1, &viewport); @@ -485,17 +513,18 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl deviceContext->RSSetState(mRasterizerState); // Apply shaders - deviceContext->IASetInputLayout(shader->inputLayout); - deviceContext->VSSetShader(shader->vertexShader, NULL, 0); - deviceContext->PSSetShader(shader->pixelShader, NULL, 0); - deviceContext->GSSetShader(NULL, NULL, 0); + deviceContext->IASetInputLayout(shader->inputLayout->resolve(device)); + deviceContext->VSSetShader(shader->vertexShader.resolve(device), nullptr, 0); + deviceContext->PSSetShader(shader->pixelShader.resolve(device), nullptr, 0); + deviceContext->GSSetShader(nullptr, nullptr, 0); // Apply vertex buffer deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); // Apply render targets - deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); + deviceContext->OMSetRenderTargets(static_cast(rtvs.size()), + (rtvs.empty() ? nullptr : &rtvs[0]), dsv); // Draw the clear quad deviceContext->Draw(4, 0); @@ -509,7 +538,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl ID3D11BlendState *Clear11::getBlendState(const std::vector& rts) { - ClearBlendInfo blendKey = { 0 }; + ClearBlendInfo blendKey = {}; for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { if (i < rts.size()) @@ -552,12 +581,12 @@ ID3D11BlendState *Clear11::getBlendState(const std::vector& } ID3D11Device *device = mRenderer->getDevice(); - ID3D11BlendState* blendState = NULL; + ID3D11BlendState* blendState = nullptr; HRESULT result = device->CreateBlendState(&blendDesc, &blendState); if (FAILED(result) || !blendState) { ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); - return NULL; + return nullptr; } mClearBlendStates[blendKey] = blendState; @@ -597,12 +626,12 @@ ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &cl dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; ID3D11Device *device = mRenderer->getDevice(); - ID3D11DepthStencilState* dsState = NULL; + ID3D11DepthStencilState* dsState = nullptr; HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState); if (FAILED(result) || !dsState) { ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - return NULL; + return nullptr; } mClearDepthStencilStates[dsKey] = dsState; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h index 4797ca1aa0..3ff73c85d1 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h @@ -15,6 +15,7 @@ #include "libANGLE/angletypes.h" #include "libANGLE/Error.h" #include "libANGLE/Framebuffer.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" namespace rx { @@ -41,29 +42,32 @@ class Clear11 : angle::NonCopyable ID3D11BlendState *getBlendState(const std::vector &rts); ID3D11DepthStencilState *getDepthStencilState(const ClearParameters &clearParams); - struct ClearShader + struct ClearShader final : public angle::NonCopyable { - ID3D11InputLayout *inputLayout; - ID3D11VertexShader *vertexShader; - ID3D11PixelShader *pixelShader; + ClearShader(DXGI_FORMAT colorType, + const char *inputLayoutName, + const BYTE *vsByteCode, + size_t vsSize, + const char *vsDebugName, + const BYTE *psByteCode, + size_t psSize, + const char *psDebugName); + ~ClearShader(); + + d3d11::LazyInputLayout *inputLayout; + d3d11::LazyShader vertexShader; + d3d11::LazyShader pixelShader; }; template static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE(&vsByteCode)[vsSize], const BYTE(&psByteCode)[psSize]); - Renderer11 *mRenderer; - struct ClearBlendInfo { bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; }; typedef bool(*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &); typedef std::map ClearBlendStateMap; - ClearBlendStateMap mClearBlendStates; - - ClearShader mFloatClearShader; - ClearShader mUintClearShader; - ClearShader mIntClearShader; struct ClearDepthStencilInfo { @@ -71,14 +75,21 @@ class Clear11 : angle::NonCopyable bool clearStencil; UINT8 stencilWriteMask; }; - typedef bool (*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &); + typedef bool(*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &); typedef std::map ClearDepthStencilStateMap; + + Renderer11 *mRenderer; + + ClearBlendStateMap mClearBlendStates; + + ClearShader *mFloatClearShader; + ClearShader *mUintClearShader; + ClearShader *mIntClearShader; + ClearDepthStencilStateMap mClearDepthStencilStates; ID3D11Buffer *mVertexBuffer; ID3D11RasterizerState *mRasterizerState; - - bool mSupportsClearView; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp index f1fe2bb2c7..1c35ab45cc 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp @@ -37,50 +37,90 @@ DebugAnnotator11::~DebugAnnotator11() } } -void DebugAnnotator11::beginEvent(const std::wstring &eventName) +void DebugAnnotator11::beginEvent(const wchar_t *eventName) { initializeDevice(); + if (mUserDefinedAnnotation != nullptr) + { #if defined(ANGLE_ENABLE_D3D11_1) - mUserDefinedAnnotation->BeginEvent(eventName.c_str()); + mUserDefinedAnnotation->BeginEvent(eventName); #endif + } } void DebugAnnotator11::endEvent() { initializeDevice(); + if (mUserDefinedAnnotation != nullptr) + { #if defined(ANGLE_ENABLE_D3D11_1) - mUserDefinedAnnotation->EndEvent(); + mUserDefinedAnnotation->EndEvent(); #endif + } } -void DebugAnnotator11::setMarker(const std::wstring &markerName) +void DebugAnnotator11::setMarker(const wchar_t *markerName) { initializeDevice(); + if (mUserDefinedAnnotation != nullptr) + { #if defined(ANGLE_ENABLE_D3D11_1) - mUserDefinedAnnotation->SetMarker(markerName.c_str()); + mUserDefinedAnnotation->SetMarker(markerName); #endif + } } bool DebugAnnotator11::getStatus() { - // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. +#if defined(ANGLE_ENABLE_WINDOWS_STORE) +#if (NTDDI_VERSION == NTDDI_WIN10) + initializeDevice(); + + if (mUserDefinedAnnotation != nullptr) + { + return !!(mUserDefinedAnnotation->GetStatus()); + } + + return true; // Default if initializeDevice() failed +#elif defined(_DEBUG) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) + static bool underCapture = true; -#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) - // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture. + // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in + // Windows 8.1/Visual Studio 2013. We can use IDXGraphicsAnalysis, though. + // The call to GetDebugInterface1 only succeeds if the app is under capture. // This should only be called in DEBUG mode. - // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks. - IDXGraphicsAnalysis *graphicsAnalysis; - DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis)); - bool underCapture = (graphicsAnalysis != nullptr); - SafeRelease(graphicsAnalysis); - return underCapture; -#endif // _DEBUG && !ANGLE_ENABLE_WINDOWS_STORE + // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows + // Store ingestion checks. + + // Cache the result to reduce the number of calls to DXGIGetDebugInterface1 + static bool triedIDXGraphicsAnalysis = false; + + if (!triedIDXGraphicsAnalysis) + { + IDXGraphicsAnalysis *graphicsAnalysis = nullptr; + + HRESULT result = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis)); + if (SUCCEEDED(result)) + { + underCapture = (graphicsAnalysis != nullptr); + } - // Otherwise, we have to return true here. + SafeRelease(graphicsAnalysis); + triedIDXGraphicsAnalysis = true; + } + + return underCapture; +#else + // We can't detect GetStatus() on release WinRT 8.1 builds, so always return true. + return true; +#endif // (NTDDI_VERSION == NTDDI_WIN10) or _DEBUG +#else + // We can't detect GetStatus() on desktop ANGLE builds so always return true. return true; +#endif // ANGLE_ENABLE_WINDOWS_STORE } void DebugAnnotator11::initializeDevice() @@ -103,16 +143,17 @@ void DebugAnnotator11::initializeDevice() // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device. hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context); ASSERT(SUCCEEDED(hr)); - + if (SUCCEEDED(hr)) + { #if defined(ANGLE_ENABLE_D3D11_1) - mUserDefinedAnnotation = d3d11::DynamicCastComObject(context); - ASSERT(mUserDefinedAnnotation != nullptr); + mUserDefinedAnnotation = d3d11::DynamicCastComObject(context); + ASSERT(mUserDefinedAnnotation != nullptr); #endif + mInitialized = true; + } SafeRelease(device); SafeRelease(context); - - mInitialized = true; } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h index 3df62b015c..d1a0f7fd2e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h @@ -21,9 +21,9 @@ class DebugAnnotator11 : public gl::DebugAnnotator public: DebugAnnotator11(); ~DebugAnnotator11() override; - void beginEvent(const std::wstring &eventName) override; + void beginEvent(const wchar_t *eventName) override; void endEvent() override; - void setMarker(const std::wstring &markerName) override; + void setMarker(const wchar_t *markerName) override; bool getStatus() override; private: diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp index 8552bc2beb..53fac65f2a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp @@ -76,23 +76,22 @@ FenceNV11::~FenceNV11() SafeRelease(mQuery); } -gl::Error FenceNV11::set() +gl::Error FenceNV11::set(GLenum condition) { return FenceSetHelper(this); } -gl::Error FenceNV11::test(bool flushCommandBuffer, GLboolean *outFinished) +gl::Error FenceNV11::test(GLboolean *outFinished) { - return FenceTestHelper(this, flushCommandBuffer, outFinished); + return FenceTestHelper(this, true, outFinished); } -gl::Error FenceNV11::finishFence(GLboolean *outFinished) +gl::Error FenceNV11::finish() { - ASSERT(outFinished); - - while (*outFinished != GL_TRUE) + GLboolean finished = GL_FALSE; + while (finished != GL_TRUE) { - gl::Error error = test(true, outFinished); + gl::Error error = FenceTestHelper(this, true, &finished); if (error.isError()) { return error; @@ -124,7 +123,7 @@ FenceSync11::FenceSync11(Renderer11 *renderer) mRenderer(renderer), mQuery(NULL) { - LARGE_INTEGER counterFreqency = { 0 }; + LARGE_INTEGER counterFreqency = {}; BOOL success = QueryPerformanceFrequency(&counterFreqency); UNUSED_ASSERTION_VARIABLE(success); ASSERT(success); @@ -137,8 +136,9 @@ FenceSync11::~FenceSync11() SafeRelease(mQuery); } -gl::Error FenceSync11::set() +gl::Error FenceSync11::set(GLenum condition, GLbitfield flags) { + ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0); return FenceSetHelper(this); } @@ -168,7 +168,7 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou return gl::Error(GL_NO_ERROR); } - LARGE_INTEGER currentCounter = { 0 }; + LARGE_INTEGER currentCounter = {}; BOOL success = QueryPerformanceCounter(¤tCounter); UNUSED_ASSERTION_VARIABLE(success); ASSERT(success); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h index 2d87f43e76..595978885b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h @@ -20,11 +20,11 @@ class FenceNV11 : public FenceNVImpl { public: explicit FenceNV11(Renderer11 *renderer); - virtual ~FenceNV11(); + ~FenceNV11() override; - gl::Error set(); - gl::Error test(bool flushCommandBuffer, GLboolean *outFinished); - gl::Error finishFence(GLboolean *outFinished); + gl::Error set(GLenum condition) override; + gl::Error test(GLboolean *outFinished) override; + gl::Error finish() override; private: template friend gl::Error FenceSetHelper(T *fence); @@ -38,12 +38,12 @@ class FenceSync11 : public FenceSyncImpl { public: explicit FenceSync11(Renderer11 *renderer); - virtual ~FenceSync11(); + ~FenceSync11() override; - gl::Error set(); - gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult); - gl::Error serverWait(GLbitfield flags, GLuint64 timeout); - gl::Error getStatus(GLint *outResult); + gl::Error set(GLenum condition, GLbitfield flags) override; + gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override; + gl::Error serverWait(GLbitfield flags, GLuint64 timeout) override; + gl::Error getStatus(GLint *outResult) override; private: template friend gl::Error FenceSetHelper(T *fence); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp index da01f320c0..186a035902 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp @@ -25,8 +25,7 @@ namespace rx { Framebuffer11::Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer) - : FramebufferD3D(data, renderer), - mRenderer(renderer) + : FramebufferD3D(data, renderer), mRenderer(renderer) { ASSERT(mRenderer != nullptr); } @@ -43,7 +42,7 @@ static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *a TextureD3D *textureD3D = GetImplAs(texture); - TextureStorage *texStorage = NULL; + TextureStorage *texStorage = nullptr; gl::Error error = textureD3D->getNativeTexture(&texStorage); if (error.isError()) { @@ -52,7 +51,7 @@ static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *a if (texStorage) { - TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); + TextureStorage11 *texStorage11 = GetAs(texStorage); ASSERT(texStorage11); texStorage11->invalidateSwizzleCacheLevel(attachment->mipLevel()); @@ -64,23 +63,25 @@ static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *a gl::Error Framebuffer11::invalidateSwizzles() const { - for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it) + for (const auto &colorAttachment : mData.getColorAttachments()) { - gl::FramebufferAttachment *colorAttachment = *it; - gl::Error error = InvalidateAttachmentSwizzles(colorAttachment); - if (error.isError()) + if (colorAttachment.isAttached()) { - return error; + gl::Error error = InvalidateAttachmentSwizzles(&colorAttachment); + if (error.isError()) + { + return error; + } } } - gl::Error error = InvalidateAttachmentSwizzles(mData.mDepthAttachment); + gl::Error error = InvalidateAttachmentSwizzles(mData.getDepthAttachment()); if (error.isError()) { return error; } - error = InvalidateAttachmentSwizzles(mData.mStencilAttachment); + error = InvalidateAttachmentSwizzles(mData.getStencilAttachment()); if (error.isError()) { return error; @@ -89,10 +90,30 @@ gl::Error Framebuffer11::invalidateSwizzles() const return gl::Error(GL_NO_ERROR); } -gl::Error Framebuffer11::clear(const gl::State &state, const ClearParameters &clearParams) +gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clearParams) { Clear11 *clearer = mRenderer->getClearer(); - gl::Error error = clearer->clearFramebuffer(clearParams, mData); + gl::Error error(GL_NO_ERROR); + + const gl::FramebufferAttachment *colorAttachment = mData.getFirstColorAttachment(); + if (clearParams.scissorEnabled == true && colorAttachment != nullptr && + UsePresentPathFast(mRenderer, colorAttachment)) + { + // If the current framebuffer is using the default colorbuffer, and present path fast is + // active, and the scissor rect is enabled, then we should invert the scissor rect + // vertically + ClearParameters presentPathFastClearParams = clearParams; + gl::Extents framebufferSize = colorAttachment->getSize(); + presentPathFastClearParams.scissor.y = framebufferSize.height - + presentPathFastClearParams.scissor.y - + presentPathFastClearParams.scissor.height; + error = clearer->clearFramebuffer(presentPathFastClearParams, mData); + } + else + { + error = clearer->clearFramebuffer(clearParams, mData); + } + if (error.isError()) { return error; @@ -107,76 +128,193 @@ gl::Error Framebuffer11::clear(const gl::State &state, const ClearParameters &cl return gl::Error(GL_NO_ERROR); } -static gl::Error getRenderTargetResource(const gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, - ID3D11Texture2D **texture2DOut) +gl::Error Framebuffer11::invalidate(size_t count, const GLenum *attachments) { - ASSERT(colorbuffer); + return invalidateBase(count, attachments, false); +} - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) +gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments) +{ + return invalidateBase(count, attachments, true); +} + +gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const +{ +#if defined(ANGLE_ENABLE_D3D11_1) + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); + + if (!deviceContext1) { - return error; + // DiscardView() is only supported on ID3D11DeviceContext1 + return gl::Error(GL_NO_ERROR); } - ID3D11Resource *renderTargetResource = renderTarget->getTexture(); - ASSERT(renderTargetResource); - - *subresourceIndexOut = renderTarget->getSubresourceIndex(); - *texture2DOut = d3d11::DynamicCastComObject(renderTargetResource); + bool foundDepth = false; + bool foundStencil = false; - if (!(*texture2DOut)) + for (size_t i = 0; i < count; ++i) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget"); - } + switch (attachments[i]) + { + // Handle depth and stencil attachments. Defer discarding until later. + case GL_DEPTH_STENCIL_ATTACHMENT: + foundDepth = true; + foundStencil = true; + break; + case GL_DEPTH_EXT: + case GL_DEPTH_ATTACHMENT: + foundDepth = true; + break; + case GL_STENCIL_EXT: + case GL_STENCIL_ATTACHMENT: + foundStencil = true; + break; + default: + { + // Handle color attachments + ASSERT((attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) || + (attachments[i] == GL_COLOR)); - return gl::Error(GL_NO_ERROR); -} + RenderTarget11 *renderTarget = nullptr; + ID3D11View *colorView = nullptr; + gl::Error error(GL_NO_ERROR); + size_t colorAttachmentID = 0; -gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const -{ - ID3D11Texture2D *colorBufferTexture = NULL; - unsigned int subresourceIndex = 0; + if (attachments[i] == GL_COLOR) + { + colorAttachmentID = 0; + } + else + { + colorAttachmentID = attachments[i] - GL_COLOR_ATTACHMENT0; + } - const gl::FramebufferAttachment *colorbuffer = mData.getReadAttachment(); - ASSERT(colorbuffer); + if (mData.getColorAttachment(static_cast(colorAttachmentID))) + { + error = mData.getColorAttachment(static_cast(colorAttachmentID)) + ->getRenderTarget(&renderTarget); + if (error.isError()) + { + return error; + } + + colorView = renderTarget->getRenderTargetView(); + + if (colorView != nullptr) + { + deviceContext1->DiscardView(colorView); + } + } - gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture); - if (error.isError()) + break; + } + } + } + + bool discardDepth = false; + bool discardStencil = false; + + // The D3D11 renderer uses the same view for depth and stencil buffers, so we must be careful. + if (useEXTBehavior) { - return error; + // In the extension, if the app discards only one of the depth and stencil attachments, but + // those are backed by the same packed_depth_stencil buffer, then both images become undefined. + discardDepth = foundDepth; + + // Don't bother discarding the stencil buffer if the depth buffer will already do it + discardStencil = foundStencil && (!discardDepth || mData.getDepthAttachment() == nullptr); + } + else + { + // In ES 3.0.4, if a specified attachment has base internal format DEPTH_STENCIL but the + // attachments list does not include DEPTH_STENCIL_ATTACHMENT or both DEPTH_ATTACHMENT and + // STENCIL_ATTACHMENT, then only the specified portion of every pixel in the subregion of pixels + // of the DEPTH_STENCIL buffer may be invalidated, and the other portion must be preserved. + discardDepth = (foundDepth && foundStencil) || (foundDepth && (mData.getStencilAttachment() == nullptr)); + discardStencil = (foundStencil && (mData.getDepthAttachment() == nullptr)); } - gl::Buffer *packBuffer = pack.pixelBuffer.get(); - if (packBuffer != NULL) + if (discardDepth && mData.getDepthAttachment()) { - Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation()); - PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast(pixels)); + RenderTarget11 *renderTarget = nullptr; + ID3D11View *depthView = nullptr; + gl::Error error(GL_NO_ERROR); - error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); + error = mData.getDepthAttachment()->getRenderTarget(&renderTarget); if (error.isError()) { - SafeRelease(colorBufferTexture); return error; } - packBuffer->getIndexRangeCache()->clear(); + depthView = renderTarget->getDepthStencilView(); + + if (depthView != nullptr) + { + deviceContext1->DiscardView(depthView); + } } - else + + if (discardStencil && mData.getStencilAttachment()) { - error = mRenderer->readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); + RenderTarget11 *renderTarget = nullptr; + ID3D11View *stencilView = nullptr; + gl::Error error(GL_NO_ERROR); + + error = mData.getStencilAttachment()->getRenderTarget(&renderTarget); if (error.isError()) { - SafeRelease(colorBufferTexture); return error; } + + stencilView = renderTarget->getDepthStencilView(); + + if (stencilView != nullptr) + { + deviceContext1->DiscardView(stencilView); + } } +#endif // ANGLE_ENABLE_D3D11_1 - SafeRelease(colorBufferTexture); + return gl::Error(GL_NO_ERROR); +} +gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) +{ + // A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED() return gl::Error(GL_NO_ERROR); } +gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const +{ + const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + ASSERT(readAttachment); + + gl::Buffer *packBuffer = pack.pixelBuffer.get(); + if (packBuffer != nullptr) + { + if (pack.rowLength != 0 || pack.skipRows != 0 || pack.skipPixels != 0) + { + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, + "Unimplemented pixel store parameters in readPixelsImpl"); + } + + Buffer11 *packBufferStorage = GetImplAs(packBuffer); + PackPixelsParams packParams(area, format, type, static_cast(outputPitch), pack, + reinterpret_cast(pixels)); + + return packBufferStorage->packPixels(*readAttachment, packParams); + } + + return mRenderer->readFromAttachment(*readAttachment, area, format, type, + static_cast(outputPitch), pack, pixels); +} + gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, const gl::Framebuffer *sourceFramebuffer) @@ -186,31 +324,53 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getReadColorbuffer(); ASSERT(readBuffer); - RenderTargetD3D *readRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + RenderTargetD3D *readRenderTarget = nullptr; + gl::Error error = readBuffer->getRenderTarget(&readRenderTarget); if (error.isError()) { return error; } ASSERT(readRenderTarget); - for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++) + const auto &colorAttachments = mData.getColorAttachments(); + const auto &drawBufferStates = mData.getDrawBufferStates(); + + for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) { - if (mData.mColorAttachments[colorAttachment] != nullptr && - mData.mDrawBufferStates[colorAttachment] != GL_NONE) - { - const gl::FramebufferAttachment *drawBuffer = mData.mColorAttachments[colorAttachment]; + const gl::FramebufferAttachment &drawBuffer = colorAttachments[colorAttachment]; - RenderTargetD3D *drawRenderTarget = NULL; - error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + if (drawBuffer.isAttached() && + drawBufferStates[colorAttachment] != GL_NONE) + { + RenderTargetD3D *drawRenderTarget = nullptr; + error = drawBuffer.getRenderTarget(&drawRenderTarget); if (error.isError()) { return error; } ASSERT(drawRenderTarget); - error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget, - filter, scissor, blitRenderTarget, false, false); + const bool invertColorSource = UsePresentPathFast(mRenderer, readBuffer); + gl::Rectangle actualSourceArea = sourceArea; + if (invertColorSource) + { + RenderTarget11 *readRenderTarget11 = GetAs(readRenderTarget); + actualSourceArea.y = readRenderTarget11->getHeight() - sourceArea.y; + actualSourceArea.height = -sourceArea.height; + } + + const bool invertColorDest = UsePresentPathFast(mRenderer, &drawBuffer); + gl::Rectangle actualDestArea = destArea; + if (invertColorDest) + { + RenderTarget11 *drawRenderTarget11 = GetAs(drawRenderTarget); + actualDestArea.y = drawRenderTarget11->getHeight() - destArea.y; + actualDestArea.height = -destArea.height; + } + + error = mRenderer->blitRenderbufferRect(actualSourceArea, actualDestArea, + readRenderTarget, drawRenderTarget, filter, + scissor, blitRenderTarget, false, false); if (error.isError()) { return error; @@ -221,11 +381,11 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang if (blitDepth || blitStencil) { - gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); + const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); ASSERT(readBuffer); - RenderTargetD3D *readRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + RenderTargetD3D *readRenderTarget = nullptr; + gl::Error error = readBuffer->getRenderTarget(&readRenderTarget); if (error.isError()) { return error; @@ -235,8 +395,8 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment(); ASSERT(drawBuffer); - RenderTargetD3D *drawRenderTarget = NULL; - error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + RenderTargetD3D *drawRenderTarget = nullptr; + error = drawBuffer->getRenderTarget(&drawRenderTarget); if (error.isError()) { return error; @@ -262,7 +422,7 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const { - RenderTarget11 *renderTarget11 = RenderTarget11::makeRenderTarget11(renderTarget); + RenderTarget11 *renderTarget11 = GetAs(renderTarget); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget11->getDXGIFormat()); return dxgiFormatInfo.internalFormat; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h index 07fa480fa2..c8a33ec7e5 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h @@ -21,19 +21,28 @@ class Framebuffer11 : public FramebufferD3D Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer); virtual ~Framebuffer11(); + gl::Error discard(size_t count, const GLenum *attachments) override; + gl::Error invalidate(size_t count, const GLenum *attachments) override; + gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; + // Invalidate the cached swizzles of all bound texture attachments. gl::Error invalidateSwizzles() const; private: - gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override; + gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override; - gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, - const gl::PixelPackState &pack, uint8_t *pixels) const override; + gl::Error readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const override; gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override; + gl::Error invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const; GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp index 956b78b5a6..c52092d81e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp @@ -7,17 +7,18 @@ // Image11.h: Implements the rx::Image11 class, which acts as the interface to // the actual underlying resources of a Texture -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/Image11.h" -#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" -#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" -#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" -#include "libANGLE/Framebuffer.h" -#include "libANGLE/FramebufferAttachment.h" -#include "libANGLE/formatutils.h" #include "common/utilities.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" namespace rx { @@ -32,9 +33,6 @@ Image11::Image11(Renderer11 *renderer) mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()), mRecoveredFromStorageCount(0) { - // mRenderer should remain unchanged during the lifetime of the Image11 object. - // This lets us safely use mRenderer (and its Feature Level) in Image11's methods. - mFeatureLevel = renderer->getFeatureLevel(); } Image11::~Image11() @@ -43,12 +41,6 @@ Image11::~Image11() releaseStagingTexture(); } -Image11 *Image11::makeImage11(ImageD3D *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(Image11*, img)); - return static_cast(img); -} - gl::Error Image11::generateMipmap(Image11 *dest, Image11 *src) { ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); @@ -94,9 +86,14 @@ bool Image11::isDirty() const // AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be recovered from TextureStorage // AND the texture doesn't require init data (i.e. a blank new texture will suffice) // then isDirty should still return false. - if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL)) + if (mDirty && !mStagingTexture && !mRecoverFromStorage) { - return false; + const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps(); + const d3d11::TextureFormat formatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, deviceCaps); + if (formatInfo.dataInitializerFunction == nullptr) + { + return false; + } } return mDirty; @@ -104,7 +101,7 @@ bool Image11::isDirty() const gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) { - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(storage); + TextureStorage11 *storage11 = GetAs(storage); // If an app's behavior results in an Image11 copying its data to/from to a TextureStorage multiple times, // then we should just keep the staging texture around to prevent the copying from impacting perf. @@ -222,7 +219,7 @@ bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents & mTarget = target; // compute the d3d format that will be used - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, mFeatureLevel); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, mRenderer->getRenderer11DeviceCaps()); mDXGIFormat = formatInfo.texFormat; mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); @@ -250,13 +247,16 @@ gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unp { const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch( + type, area.width, area.height, unpack.alignment, unpack.rowLength, unpack.imageHeight); + GLsizei inputSkipBytes = formatInfo.computeSkipPixels( + inputRowPitch, inputDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel); - LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type); + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); + LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type).loadFunction; D3D11_MAPPED_SUBRESOURCE mappedImage; gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); @@ -267,8 +267,8 @@ gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unp uint8_t *offsetMappedData = (reinterpret_cast(mappedImage.pData) + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + area.z * mappedImage.DepthPitch)); loadFunction(area.width, area.height, area.depth, - reinterpret_cast(input), inputRowPitch, inputDepthPitch, - offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + reinterpret_cast(input) + inputSkipBytes, inputRowPitch, + inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); unmap(); @@ -279,7 +279,8 @@ gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input) { const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0); + GLsizei inputDepthPitch = + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; @@ -289,8 +290,8 @@ gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input) ASSERT(area.x % outputBlockWidth == 0); ASSERT(area.y % outputBlockHeight == 0); - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel); - LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE); + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); + LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE).loadFunction; D3D11_MAPPED_SUBRESOURCE mappedImage; gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); @@ -312,180 +313,159 @@ gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input) return gl::Error(GL_NO_ERROR); } -gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) -{ - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(source); - ASSERT(sourceRenderTarget->getTexture()); - - ID3D11Resource *resource = sourceRenderTarget->getTexture(); - UINT subresourceIndex = sourceRenderTarget->getSubresourceIndex(); - - gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1); - gl::Error error = copy(destOffset, sourceBox, resource, subresourceIndex); - - SafeRelease(resource); - - return error; -} - -gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source) +gl::Error Image11::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) { - TextureStorage11 *sourceStorage11 = TextureStorage11::makeTextureStorage11(source); + TextureStorage11 *storage11 = GetAs(source); - UINT subresourceIndex = sourceStorage11->getSubresourceIndex(sourceIndex); - ID3D11Resource *resource = NULL; - gl::Error error = sourceStorage11->getResource(&resource); + ID3D11Resource *resource = nullptr; + gl::Error error = storage11->getResource(&resource); if (error.isError()) { return error; } - error = copy(destOffset, sourceArea, resource, subresourceIndex); - - SafeRelease(resource); + UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex); + TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(resource); - return error; + gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth); + return copyWithoutConversion(gl::Offset(), sourceBox, textureHelper, subresourceIndex); } -gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource) +gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *sourceFBO) { - D3D11_RESOURCE_DIMENSION dim; - source->GetType(&dim); - - DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; - gl::Extents extents; - UINT sampleCount = 0; + const gl::FramebufferAttachment *srcAttachment = sourceFBO->getReadColorbuffer(); + ASSERT(srcAttachment); - ID3D11Texture2D *source2D = NULL; + const auto &d3d11Format = d3d11::GetTextureFormatInfo(srcAttachment->getInternalFormat(), + mRenderer->getRenderer11DeviceCaps()); - if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) - { - D3D11_TEXTURE2D_DESC textureDesc2D; - source2D = d3d11::DynamicCastComObject(source); - ASSERT(source2D); - source2D->GetDesc(&textureDesc2D); - - format = textureDesc2D.Format; - extents = gl::Extents(textureDesc2D.Width, textureDesc2D.Height, 1); - sampleCount = textureDesc2D.SampleDesc.Count; - } - else if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE3D) + if (d3d11Format.texFormat == mDXGIFormat) { - D3D11_TEXTURE3D_DESC textureDesc3D; - ID3D11Texture3D *source3D = d3d11::DynamicCastComObject(source); - ASSERT(source3D); - source3D->GetDesc(&textureDesc3D); - - format = textureDesc3D.Format; - extents = gl::Extents(textureDesc3D.Width, textureDesc3D.Height, textureDesc3D.Depth); - sampleCount = 1; - } - else - { - UNREACHABLE(); - } - - if (format == mDXGIFormat) - { - // No conversion needed-- use copyback fastpath - ID3D11Resource *stagingTexture = NULL; - unsigned int stagingSubresourceIndex = 0; - gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); + RenderTargetD3D *renderTarget = nullptr; + gl::Error error = srcAttachment->getRenderTarget(&renderTarget); if (error.isError()) { return error; } - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + RenderTarget11 *rt11 = GetAs(renderTarget); + ASSERT(rt11->getTexture()); - UINT subresourceAfterResolve = sourceSubResource; + TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(rt11->getTexture()); + unsigned int sourceSubResource = rt11->getSubresourceIndex(); - ID3D11Resource *srcTex = NULL; + gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1); + return copyWithoutConversion(destOffset, sourceBox, textureHelper, sourceSubResource); + } - bool needResolve = (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D && sampleCount > 1); + // This format requires conversion, so we must copy the texture to staging and manually convert + // via readPixels + D3D11_MAPPED_SUBRESOURCE mappedImage; + gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); + if (error.isError()) + { + return error; + } - if (needResolve) - { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = extents.width; - resolveDesc.Height = extents.height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = D3D11_USAGE_DEFAULT; - resolveDesc.BindFlags = 0; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; - - ID3D11Texture2D *srcTex2D = NULL; - HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); - } - srcTex = srcTex2D; + // determine the offset coordinate into the destination buffer + const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); + GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x; - deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, format); - subresourceAfterResolve = 0; - } - else - { - srcTex = source; - } + uint8_t *dataOffset = static_cast(mappedImage.pData) + + mappedImage.RowPitch * destOffset.y + rowOffset + + destOffset.z * mappedImage.DepthPitch; - D3D11_BOX srcBox; - srcBox.left = sourceArea.x; - srcBox.right = sourceArea.x + sourceArea.width; - srcBox.top = sourceArea.y; - srcBox.bottom = sourceArea.y + sourceArea.height; - srcBox.front = sourceArea.z; - srcBox.back = sourceArea.z + sourceArea.depth; + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x, destOffset.y, - destOffset.z, srcTex, subresourceAfterResolve, &srcBox); + error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, formatInfo.format, + formatInfo.type, mappedImage.RowPitch, + gl::PixelPackState(), dataOffset); - if (needResolve) - { - SafeRelease(srcTex); - } - } - else + unmap(); + mDirty = true; + + return error; +} + +gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset, + const gl::Box &sourceArea, + const TextureHelper11 &textureHelper, + UINT sourceSubResource) +{ + // No conversion needed-- use copyback fastpath + ID3D11Resource *stagingTexture = nullptr; + unsigned int stagingSubresourceIndex = 0; + gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); + if (error.isError()) { - // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels - D3D11_MAPPED_SUBRESOURCE mappedImage; - gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); - if (error.isError()) - { - return error; - } + return error; + } - // determine the offset coordinate into the destination buffer - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); - GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x; - uint8_t *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * destOffset.y + rowOffset + destOffset.z * mappedImage.DepthPitch; + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + UINT subresourceAfterResolve = sourceSubResource; - // Currently in ANGLE, the source data may only need to be converted if the source is the current framebuffer - // and OpenGL ES framebuffers must be 2D textures therefore we should not need to convert 3D textures between different formats. - ASSERT(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D); - ASSERT(sourceArea.z == 0 && sourceArea.depth == 1); - gl::Rectangle sourceRect(sourceArea.x, sourceArea.y, sourceArea.width, sourceArea.height); - error = mRenderer->readTextureData(source2D, sourceSubResource, sourceRect, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + ID3D11Resource *srcTex = nullptr; + const gl::Extents &extents = textureHelper.getExtents(); - unmap(); + bool needResolve = + (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1); - if (error.isError()) + if (needResolve) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = extents.width; + resolveDesc.Height = extents.height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureHelper.getFormat(); + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ID3D11Texture2D *srcTex2D = NULL; + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D); + if (FAILED(result)) { - return error; + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", + result); } + srcTex = srcTex2D; + + deviceContext->ResolveSubresource(srcTex, 0, textureHelper.getTexture2D(), + sourceSubResource, textureHelper.getFormat()); + subresourceAfterResolve = 0; + } + else + { + srcTex = textureHelper.getResource(); } - mDirty = true; + D3D11_BOX srcBox; + srcBox.left = sourceArea.x; + srcBox.right = sourceArea.x + sourceArea.width; + srcBox.top = sourceArea.y; + srcBox.bottom = sourceArea.y + sourceArea.height; + srcBox.front = sourceArea.z; + srcBox.back = sourceArea.z + sourceArea.depth; + + deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x, + destOffset.y, destOffset.z, srcTex, + subresourceAfterResolve, &srcBox); + + if (needResolve) + { + SafeRelease(srcTex); + } + mDirty = true; return gl::Error(GL_NO_ERROR); } @@ -543,11 +523,11 @@ gl::Error Image11::createStagingTexture() desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL) + if (d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()).dataInitializerFunction != NULL) { std::vector initialData; - std::vector< std::vector > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, mFeatureLevel, width, height, mDepth, + std::vector> textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, mDepth, lodOffset + 1, &initialData, &textureData); result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); @@ -583,11 +563,11 @@ gl::Error Image11::createStagingTexture() desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL) + if (d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()).dataInitializerFunction != NULL) { std::vector initialData; - std::vector< std::vector > textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, mFeatureLevel, width, height, 1, + std::vector> textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, 1, lodOffset + 1, &initialData, &textureData); result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); @@ -637,13 +617,13 @@ gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) ASSERT(mStagingTexture); HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map); - // this can fail if the device is removed (from TDR) - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - } - else if (FAILED(result)) + if (FAILED(result)) { + // this can fail if the device is removed (from TDR) + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result); } @@ -661,4 +641,4 @@ void Image11::unmap() } } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h index 5734f73b15..a5fcec84f8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h @@ -23,6 +23,7 @@ class Framebuffer; namespace rx { class Renderer11; +class TextureHelper11; class TextureStorage11; class Image11 : public ImageD3D @@ -31,8 +32,6 @@ class Image11 : public ImageD3D Image11(Renderer11 *renderer); virtual ~Image11(); - static Image11 *makeImage11(ImageD3D *img); - static gl::Error generateMipmap(Image11 *dest, Image11 *src); virtual bool isDirty() const; @@ -46,9 +45,10 @@ class Image11 : public ImageD3D virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input); virtual gl::Error loadCompressedData(const gl::Box &area, const void *input); - virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source); - virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, - const gl::ImageIndex &sourceIndex, TextureStorage *source); + gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override; + gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; gl::Error recoverFromAssociatedStorage(); bool isAssociatedStorageValid(TextureStorage11* textureStorage) const; @@ -59,15 +59,16 @@ class Image11 : public ImageD3D void unmap(); private: - gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box ®ion); - gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource); + gl::Error copyWithoutConversion(const gl::Offset &destOffset, + const gl::Box &sourceArea, + const TextureHelper11 &textureHelper, + UINT sourceSubResource); gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex); gl::Error createStagingTexture(); void releaseStagingTexture(); Renderer11 *mRenderer; - D3D_FEATURE_LEVEL mFeatureLevel; DXGI_FORMAT mDXGIFormat; ID3D11Resource *mStagingTexture; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp index 99c199f2b9..a5e78a245d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -7,7 +7,9 @@ // IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" + #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" namespace rx { @@ -47,6 +49,15 @@ gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, b { return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); } + + if (dynamic) + { + d3d11::SetDebugName(mBuffer, "IndexBuffer11 (dynamic)"); + } + else + { + d3d11::SetDebugName(mBuffer, "IndexBuffer11 (static)"); + } } mBufferSize = bufferSize; @@ -56,12 +67,6 @@ gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, b return gl::Error(GL_NO_ERROR); } -IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer)); - return static_cast(indexBuffer); -} - gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) { if (!mBuffer) diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h index eadd03eb76..e730377e00 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h @@ -23,8 +23,6 @@ class IndexBuffer11 : public IndexBuffer virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); - static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer); - virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); virtual gl::Error unmapBuffer(); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp index 242c09d6ce..3a6d797ea6 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -8,43 +8,141 @@ // D3D11 input layouts. #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" -#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" + +#include "common/utilities.h" +#include "libANGLE/Program.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/renderer/d3d/ProgramD3D.h" -#include "libANGLE/renderer/d3d/VertexDataManager.h" -#include "libANGLE/Program.h" -#include "libANGLE/VertexAttribute.h" - #include "third_party/murmurhash/MurmurHash3.h" namespace rx { -static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS], - gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) +namespace +{ + +size_t GetReservedBufferCount(bool usesPointSpriteEmulation) { - for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + return usesPointSpriteEmulation ? 1 : 0; +} + +gl::InputLayout GetInputLayout(const SortedAttribArray &translatedAttributes, size_t attributeCount) +{ + gl::InputLayout inputLayout(attributeCount, gl::VERTEX_FORMAT_INVALID); + + for (size_t attributeIndex = 0; attributeIndex < attributeCount; ++attributeIndex) { - const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex]; + const TranslatedAttribute *translatedAttribute = translatedAttributes[attributeIndex]; + + if (translatedAttribute->active) + { + inputLayout[attributeIndex] = gl::GetVertexFormatType( + *translatedAttribute->attribute, translatedAttribute->currentValueType); + } + } + return inputLayout; +} + +GLenum GetGLSLAttributeType(const std::vector &shaderAttributes, int index) +{ + // Count matrices differently + for (const sh::Attribute &attrib : shaderAttributes) + { + if (attrib.location == -1) + { + continue; + } + + GLenum transposedType = gl::TransposeMatrixType(attrib.type); + int rows = gl::VariableRowCount(transposedType); + + if (index >= attrib.location && index < attrib.location + rows) + { + return transposedType; + } + } + + UNREACHABLE(); + return GL_NONE; +} + +const unsigned int kDefaultCacheSize = 1024; + +struct PackedAttribute +{ + uint8_t attribType; + uint8_t semanticIndex; + uint8_t vertexFormatType; + uint8_t divisor; +}; - if (translatedAttributes[attributeIndex].active) +Optional FindFirstNonInstanced(const SortedAttribArray &sortedAttributes, size_t maxIndex) +{ + for (size_t index = 0; index < maxIndex; ++index) + { + if (sortedAttributes[index]->divisor == 0) { - inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute, - translatedAttribute.currentValueType); + return Optional(index); } } + + return Optional::Invalid(); } -const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; +} // anonymous namespace + +void InputLayoutCache::PackedAttributeLayout::addAttributeData( + GLenum glType, + UINT semanticIndex, + gl::VertexFormatType vertexFormatType, + unsigned int divisor) +{ + gl::AttributeType attribType = gl::GetAttributeType(glType); + + PackedAttribute packedAttrib; + packedAttrib.attribType = static_cast(attribType); + packedAttrib.semanticIndex = static_cast(semanticIndex); + packedAttrib.vertexFormatType = static_cast(vertexFormatType); + packedAttrib.divisor = static_cast(divisor); + + ASSERT(static_cast(packedAttrib.attribType) == attribType); + ASSERT(static_cast(packedAttrib.semanticIndex) == semanticIndex); + ASSERT(static_cast(packedAttrib.vertexFormatType) == vertexFormatType); + ASSERT(static_cast(packedAttrib.divisor) == divisor); + + static_assert(sizeof(uint32_t) == sizeof(PackedAttribute), "PackedAttributes must be 32-bits exactly."); + + attributeData[numAttributes++] = gl::bitCast(packedAttrib); +} + +bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLayout &other) const +{ + if (numAttributes != other.numAttributes) + { + return numAttributes < other.numAttributes; + } + + if (flags != other.flags) + { + return flags < other.flags; + } + + return memcmp(attributeData, other.attributeData, sizeof(uint32_t) * numAttributes) < 0; +} -InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) +InputLayoutCache::InputLayoutCache() : mUnsortedAttributesCount(0), mCacheSize(kDefaultCacheSize) { mCounter = 0; mDevice = NULL; mDeviceContext = NULL; mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { mCurrentBuffers[i] = NULL; @@ -70,11 +168,11 @@ void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *con void InputLayoutCache::clear() { - for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + for (auto &layout : mLayoutMap) { - SafeRelease(i->second.inputLayout); + SafeRelease(layout.second); } - mInputLayoutMap.clear(); + mLayoutMap.clear(); SafeRelease(mPointSpriteVertexBuffer); SafeRelease(mPointSpriteIndexBuffer); markDirty(); @@ -89,236 +187,135 @@ void InputLayoutCache::markDirty() mCurrentVertexStrides[i] = static_cast(-1); mCurrentVertexOffsets[i] = static_cast(-1); } + mUnsortedAttributesCount = 0; } -gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - GLenum mode, gl::Program *program) +gl::Error InputLayoutCache::applyVertexBuffers( + const std::vector &unsortedAttributes, + GLenum mode, + gl::Program *program, + TranslatedIndexData *indexInfo, + GLsizei numIndicesPerInstance) { + ASSERT(mDevice && mDeviceContext); + ProgramD3D *programD3D = GetImplAs(program); - int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; - programD3D->sortAttributesByLayout(attributes, sortedSemanticIndices); bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); - if (!mDevice || !mDeviceContext) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal input layout cache is not initialized."); - } - - InputLayoutKey ilKey = { 0 }; - - static const char* semanticName = "TEXCOORD"; + SortedIndexArray sortedSemanticIndices; + mSortedAttributes.fill(nullptr); + mUnsortedAttributesCount = unsortedAttributes.size(); - unsigned int firstIndexedElement = gl::MAX_VERTEX_ATTRIBS; - unsigned int firstInstancedElement = gl::MAX_VERTEX_ATTRIBS; - unsigned int nextAvailableInputSlot = 0; + programD3D->sortAttributesByLayout(unsortedAttributes, sortedSemanticIndices.data(), + mSortedAttributes.data()); - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + // If we are using FL 9_3, make sure the first attribute is not instanced + if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && !unsortedAttributes.empty()) { - if (attributes[i].active) + if (mSortedAttributes[0]->divisor > 0) { - D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; - // If rendering points and instanced pointsprite emulation is being used, the inputClass is required to be configured as per instance data - inputClass = instancedPointSpritesActive ? D3D11_INPUT_PER_INSTANCE_DATA : inputClass; - - gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType); - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel); - - // Record the type of the associated vertex shader vector in our key - // This will prevent mismatched vertex shaders from using the same input layout - GLint attributeSize; - program->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); - - ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; - ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i]; - ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat; - ilKey.elements[ilKey.elementCount].desc.InputSlot = i; - ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; - ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; - ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = instancedPointSpritesActive ? 1 : attributes[i].divisor; - - if (inputClass == D3D11_INPUT_PER_VERTEX_DATA && firstIndexedElement == gl::MAX_VERTEX_ATTRIBS) + Optional firstNonInstancedIndex = + FindFirstNonInstanced(mSortedAttributes, unsortedAttributes.size()); + if (firstNonInstancedIndex.valid()) { - firstIndexedElement = ilKey.elementCount; + size_t index = firstNonInstancedIndex.value(); + std::swap(mSortedAttributes[0], mSortedAttributes[index]); + std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]); } - else if (inputClass == D3D11_INPUT_PER_INSTANCE_DATA && firstInstancedElement == gl::MAX_VERTEX_ATTRIBS) - { - firstInstancedElement = ilKey.elementCount; - } - - ilKey.elementCount++; - nextAvailableInputSlot = i + 1; } } - // Instanced PointSprite emulation requires additional entries in the - // inputlayout to support the vertices that make up the pointsprite quad. - // We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the input layout must match the shader - if (programUsesInstancedPointSprites) + gl::Error error = updateInputLayout(program, mode, mSortedAttributes, sortedSemanticIndices, + unsortedAttributes.size(), numIndicesPerInstance); + if (error.isError()) { - ilKey.elements[ilKey.elementCount].desc.SemanticName = "SPRITEPOSITION"; - ilKey.elements[ilKey.elementCount].desc.SemanticIndex = 0; - ilKey.elements[ilKey.elementCount].desc.Format = DXGI_FORMAT_R32G32B32_FLOAT; - ilKey.elements[ilKey.elementCount].desc.InputSlot = nextAvailableInputSlot; - ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; - ilKey.elements[ilKey.elementCount].desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; - ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = 0; - - // The new elements are D3D11_INPUT_PER_VERTEX_DATA data so the indexed element - // tracking must be applied. This ensures that the instancing specific - // buffer swapping logic continues to work. - if (firstIndexedElement == gl::MAX_VERTEX_ATTRIBS) - { - firstIndexedElement = ilKey.elementCount; - } - - ilKey.elementCount++; - - ilKey.elements[ilKey.elementCount].desc.SemanticName = "SPRITETEXCOORD"; - ilKey.elements[ilKey.elementCount].desc.SemanticIndex = 0; - ilKey.elements[ilKey.elementCount].desc.Format = DXGI_FORMAT_R32G32_FLOAT; - ilKey.elements[ilKey.elementCount].desc.InputSlot = nextAvailableInputSlot; - ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = sizeof(float) * 3; - ilKey.elements[ilKey.elementCount].desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; - ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = 0; - - ilKey.elementCount++; + return error; } - // On 9_3, we must ensure that slot 0 contains non-instanced data. - // If slot 0 currently contains instanced data then we swap it with a non-instanced element. - // Note that instancing is only available on 9_3 via ANGLE_instanced_arrays, since 9_3 doesn't support OpenGL ES 3.0. - // As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced simultaneously, so a non-instanced element must exist. - ASSERT(!(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && firstIndexedElement == gl::MAX_VERTEX_ATTRIBS)); - bool moveFirstIndexedIntoSlotZero = mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && firstInstancedElement == 0 && firstIndexedElement != gl::MAX_VERTEX_ATTRIBS; - - if (moveFirstIndexedIntoSlotZero) - { - ilKey.elements[firstInstancedElement].desc.InputSlot = ilKey.elements[firstIndexedElement].desc.InputSlot; - ilKey.elements[firstIndexedElement].desc.InputSlot = 0; - - // Instanced PointSprite emulation uses multiple layout entries across a single vertex buffer. - // If an index swap is performed, we need to ensure that all elements get the proper InputSlot. - if (programUsesInstancedPointSprites) - { - ilKey.elements[firstIndexedElement + 1].desc.InputSlot = 0; - } - } + bool dirtyBuffers = false; + size_t minDiff = gl::MAX_VERTEX_ATTRIBS; + size_t maxDiff = 0; - ID3D11InputLayout *inputLayout = NULL; + // Note that if we use instance emulation, we reserve the first buffer slot. + size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites); - InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey); - if (keyIter != mInputLayoutMap.end()) - { - inputLayout = keyIter->second.inputLayout; - keyIter->second.lastUsedTime = mCounter++; - } - else + for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers); + ++attribIndex) { - gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS]; - GetInputLayout(attributes, shaderInputLayout); - - ShaderExecutableD3D *shader = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr); - if (error.isError()) - { - return error; - } - - ShaderExecutableD3D *shader11 = ShaderExecutable11::makeShaderExecutable11(shader); + ID3D11Buffer *buffer = NULL; + UINT vertexStride = 0; + UINT vertexOffset = 0; - D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; - for (unsigned int j = 0; j < ilKey.elementCount; ++j) - { - descs[j] = ilKey.elements[j].desc; - } + const auto &attrib = *mSortedAttributes[attribIndex]; - HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout); - if (FAILED(result)) + if (attribIndex < unsortedAttributes.size() && attrib.active) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result); - } - - if (mInputLayoutMap.size() >= kMaxInputLayouts) - { - TRACE("Overflowed the limit of %u input layouts, removing the least recently used " - "to make room.", kMaxInputLayouts); - - InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin(); - for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + VertexBuffer11 *vertexBuffer = GetAs(attrib.vertexBuffer); + Buffer11 *bufferStorage = attrib.storage ? GetAs(attrib.storage) : nullptr; + + // If indexed pointsprite emulation is active, then we need to take a less efficent code path. + // Emulated indexed pointsprite rendering requires that the vertex buffers match exactly to + // the indices passed by the caller. This could expand or shrink the vertex buffer depending + // on the number of points indicated by the index list or how many duplicates are found on the index list. + if (bufferStorage == nullptr) { - if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime) + buffer = vertexBuffer->getBuffer(); + } + else if (instancedPointSpritesActive && (indexInfo != nullptr)) + { + if (indexInfo->srcIndexData.srcBuffer != nullptr) { - leastRecentlyUsed = i; + const uint8_t *bufferData = nullptr; + error = indexInfo->srcIndexData.srcBuffer->getData(&bufferData); + if (error.isError()) + { + return error; + } + ASSERT(bufferData != nullptr); + + ptrdiff_t offset = + reinterpret_cast(indexInfo->srcIndexData.srcIndices); + indexInfo->srcIndexData.srcBuffer = nullptr; + indexInfo->srcIndexData.srcIndices = bufferData + offset; } - } - SafeRelease(leastRecentlyUsed->second.inputLayout); - mInputLayoutMap.erase(leastRecentlyUsed); - } - - InputLayoutCounterPair inputCounterPair; - inputCounterPair.inputLayout = inputLayout; - inputCounterPair.lastUsedTime = mCounter++; - - mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); - } - - if (inputLayout != mCurrentIL) - { - mDeviceContext->IASetInputLayout(inputLayout); - mCurrentIL = inputLayout; - } - bool dirtyBuffers = false; - size_t minDiff = gl::MAX_VERTEX_ATTRIBS; - size_t maxDiff = 0; - unsigned int nextAvailableIndex = 0; - - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - ID3D11Buffer *buffer = NULL; - - if (attributes[i].active) - { - VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); - Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL; + buffer = bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData, &attrib); + } + else + { + buffer = bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + } - buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK) - : vertexBuffer->getBuffer(); + vertexStride = attrib.stride; + vertexOffset = attrib.offset; } - UINT vertexStride = attributes[i].stride; - UINT vertexOffset = attributes[i].offset; + size_t bufferIndex = reservedBuffers + attribIndex; - if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] || - vertexOffset != mCurrentVertexOffsets[i]) + if (buffer != mCurrentBuffers[bufferIndex] || + vertexStride != mCurrentVertexStrides[bufferIndex] || + vertexOffset != mCurrentVertexOffsets[bufferIndex]) { dirtyBuffers = true; - minDiff = std::min(minDiff, static_cast(i)); - maxDiff = std::max(maxDiff, static_cast(i)); - - mCurrentBuffers[i] = buffer; - mCurrentVertexStrides[i] = vertexStride; - mCurrentVertexOffsets[i] = vertexOffset; + minDiff = std::min(minDiff, bufferIndex); + maxDiff = std::max(maxDiff, bufferIndex); - // If a non null ID3D11Buffer is being assigned to mCurrentBuffers, - // then the next available index needs to be tracked to ensure - // that any instanced pointsprite emulation buffers will be properly packed. - if (buffer) - { - nextAvailableIndex = i + 1; - } + mCurrentBuffers[bufferIndex] = buffer; + mCurrentVertexStrides[bufferIndex] = vertexStride; + mCurrentVertexOffsets[bufferIndex] = vertexOffset; } } - // Instanced PointSprite emulation requires two additional ID3D11Buffers. - // A vertex buffer needs to be created and added to the list of current buffers, - // strides and offsets collections. This buffer contains the vertices for a single - // PointSprite quad. - // An index buffer also needs to be created and applied because rendering instanced - // data on D3D11 FL9_3 requires DrawIndexedInstanced() to be used. - if (instancedPointSpritesActive) + // Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs + // to be created and added to the list of current buffers, strides and offsets collections. + // This buffer contains the vertices for a single PointSprite quad. + // An index buffer also needs to be created and applied because rendering instanced data on + // D3D11 FL9_3 requires DrawIndexedInstanced() to be used. Shaders that contain gl_PointSize and + // used without the GL_POINTS rendering mode require a vertex buffer because some drivers cannot + // handle missing vertex data and will TDR the system. + if (programUsesInstancedPointSprites) { HRESULT result = S_OK; const UINT pointSpriteVertexStride = sizeof(float) * 5; @@ -352,9 +349,16 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl } } - mCurrentBuffers[nextAvailableIndex] = mPointSpriteVertexBuffer; - mCurrentVertexStrides[nextAvailableIndex] = pointSpriteVertexStride; - mCurrentVertexOffsets[nextAvailableIndex] = 0; + mCurrentBuffers[0] = mPointSpriteVertexBuffer; + // Set the stride to 0 if GL_POINTS mode is not being used to instruct the driver to avoid + // indexing into the vertex buffer. + mCurrentVertexStrides[0] = instancedPointSpritesActive ? pointSpriteVertexStride : 0; + mCurrentVertexOffsets[0] = 0; + + // Update maxDiff to include the additional point sprite vertex buffer + // to ensure that IASetVertexBuffers uses the correct buffer count. + minDiff = 0; + maxDiff = std::max(maxDiff, static_cast(0)); if (!mPointSpriteIndexBuffer) { @@ -381,50 +385,265 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl } } - // The index buffer is applied here because Instanced PointSprite emulation uses - // the a non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer() - // on the renderer will not be called and setting this buffer here ensures that the rendering - // path will contain the correct index buffers. - mDeviceContext->IASetIndexBuffer(mPointSpriteIndexBuffer, DXGI_FORMAT_R16_UINT, 0); - } - - if (moveFirstIndexedIntoSlotZero) - { - // In this case, we swapped the slots of the first instanced element and the first indexed element, to ensure - // that the first slot contains non-instanced data (required by Feature Level 9_3). - // We must also swap the corresponding buffers sent to IASetVertexBuffers so that the correct data is sent to each slot. - std::swap(mCurrentBuffers[firstIndexedElement], mCurrentBuffers[firstInstancedElement]); - std::swap(mCurrentVertexStrides[firstIndexedElement], mCurrentVertexStrides[firstInstancedElement]); - std::swap(mCurrentVertexOffsets[firstIndexedElement], mCurrentVertexOffsets[firstInstancedElement]); + if (instancedPointSpritesActive) + { + // The index buffer is applied here because Instanced PointSprite emulation uses the a + // non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer() + // on the renderer will not be called and setting this buffer here ensures that the + // rendering path will contain the correct index buffers. + mDeviceContext->IASetIndexBuffer(mPointSpriteIndexBuffer, DXGI_FORMAT_R16_UINT, 0); + } } if (dirtyBuffers) { ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS); - mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff, - mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff); + mDeviceContext->IASetVertexBuffers( + static_cast(minDiff), static_cast(maxDiff - minDiff + 1), + mCurrentBuffers + minDiff, mCurrentVertexStrides + minDiff, + mCurrentVertexOffsets + minDiff); } return gl::Error(GL_NO_ERROR); } -std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) +gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId) { - static const unsigned int seed = 0xDEADBEEF; + size_t reservedBuffers = GetReservedBufferCount(true); + for (size_t attribIndex = 0; attribIndex < mUnsortedAttributesCount; ++attribIndex) + { + const auto &attrib = *mSortedAttributes[attribIndex]; + size_t bufferIndex = reservedBuffers + attribIndex; + + if (attrib.active && attrib.divisor > 0) + { + mCurrentVertexOffsets[bufferIndex] = + attrib.offset + (attrib.stride * (emulatedInstanceId / attrib.divisor)); + } + } + + mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, mCurrentBuffers, + mCurrentVertexStrides, mCurrentVertexOffsets); - std::size_t hash = 0; - MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash); - return hash; + return gl::Error(GL_NO_ERROR); } -bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) +gl::Error InputLayoutCache::updateInputLayout(gl::Program *program, + GLenum mode, + const SortedAttribArray &sortedAttributes, + const SortedIndexArray &sortedSemanticIndices, + size_t attribCount, + GLsizei numIndicesPerInstance) { - if (a.elementCount != b.elementCount) + const std::vector &shaderAttributes = program->getAttributes(); + PackedAttributeLayout layout; + + ProgramD3D *programD3D = GetImplAs(program); + bool programUsesInstancedPointSprites = + programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); + bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); + + if (programUsesInstancedPointSprites) + { + layout.flags |= PackedAttributeLayout::FLAG_USES_INSTANCED_SPRITES; + } + + if (instancedPointSpritesActive) { - return false; + layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE; } - return std::equal(a.begin(), a.end(), b.begin()); + if (numIndicesPerInstance > 0) + { + layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE; + } + + const auto &semanticToLocation = programD3D->getAttributesByLayout(); + + for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex) + { + const auto &attrib = *sortedAttributes[attribIndex]; + int sortedIndex = sortedSemanticIndices[attribIndex]; + + if (!attrib.active) + continue; + + gl::VertexFormatType vertexFormatType = + gl::GetVertexFormatType(*attrib.attribute, attrib.currentValueType); + + // Record the type of the associated vertex shader vector in our key + // This will prevent mismatched vertex shaders from using the same input layout + GLenum glslElementType = + GetGLSLAttributeType(shaderAttributes, semanticToLocation[sortedIndex]); + + layout.addAttributeData(glslElementType, sortedIndex, vertexFormatType, attrib.divisor); + } + + ID3D11InputLayout *inputLayout = nullptr; + if (layout.numAttributes > 0 || layout.flags != 0) + { + auto layoutMapIt = mLayoutMap.find(layout); + if (layoutMapIt != mLayoutMap.end()) + { + inputLayout = layoutMapIt->second; + } + else + { + gl::Error error = + createInputLayout(sortedAttributes, sortedSemanticIndices, attribCount, mode, + program, numIndicesPerInstance, &inputLayout); + if (error.isError()) + { + return error; + } + if (mLayoutMap.size() >= mCacheSize) + { + TRACE("Overflowed the limit of %u input layouts, purging half the cache.", + mCacheSize); + + // Randomly release every second element + auto it = mLayoutMap.begin(); + while (it != mLayoutMap.end()) + { + it++; + if (it != mLayoutMap.end()) + { + // c++11 erase allows us to easily delete the current iterator. + SafeRelease(it->second); + it = mLayoutMap.erase(it); + } + } + } + + mLayoutMap[layout] = inputLayout; + } + } + + if (inputLayout != mCurrentIL) + { + mDeviceContext->IASetInputLayout(inputLayout); + mCurrentIL = inputLayout; + } + + return gl::Error(GL_NO_ERROR); } +gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAttributes, + const SortedIndexArray &sortedSemanticIndices, + size_t attribCount, + GLenum mode, + gl::Program *program, + GLsizei numIndicesPerInstance, + ID3D11InputLayout **inputLayoutOut) +{ + ProgramD3D *programD3D = GetImplAs(program); + + bool programUsesInstancedPointSprites = + programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); + + unsigned int inputElementCount = 0; + std::array inputElements; + + for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex) + { + const auto &attrib = *sortedAttributes[attribIndex]; + const int sortedIndex = sortedSemanticIndices[attribIndex]; + + if (!attrib.active) + continue; + + D3D11_INPUT_CLASSIFICATION inputClass = + attrib.divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + + const auto &vertexFormatType = + gl::GetVertexFormatType(*attrib.attribute, attrib.currentValueType); + const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, mFeatureLevel); + + auto *inputElement = &inputElements[inputElementCount]; + + inputElement->SemanticName = "TEXCOORD"; + inputElement->SemanticIndex = sortedIndex; + inputElement->Format = vertexFormatInfo.nativeFormat; + inputElement->InputSlot = static_cast(attribIndex); + inputElement->AlignedByteOffset = 0; + inputElement->InputSlotClass = inputClass; + inputElement->InstanceDataStepRate = attrib.divisor; + + inputElementCount++; + } + + // Instanced PointSprite emulation requires additional entries in the + // inputlayout to support the vertices that make up the pointsprite quad. + // We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the + // input layout must match the shader + if (programUsesInstancedPointSprites) + { + // On 9_3, we must ensure that slot 0 contains non-instanced data. + // If slot 0 currently contains instanced data then we swap it with a non-instanced element. + // Note that instancing is only available on 9_3 via ANGLE_instanced_arrays, since 9_3 + // doesn't support OpenGL ES 3.0. + // As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced + // simultaneously, so a non-instanced element must exist. + for (size_t elementIndex = 0; elementIndex < inputElementCount; ++elementIndex) + { + if (sortedAttributes[elementIndex]->active) + { + // If rendering points and instanced pointsprite emulation is being used, the + // inputClass is required to be configured as per instance data + if (mode == GL_POINTS) + { + inputElements[elementIndex].InputSlotClass = D3D11_INPUT_PER_INSTANCE_DATA; + inputElements[elementIndex].InstanceDataStepRate = 1; + if (numIndicesPerInstance > 0 && sortedAttributes[elementIndex]->divisor > 0) + { + inputElements[elementIndex].InstanceDataStepRate = numIndicesPerInstance; + } + } + inputElements[elementIndex].InputSlot++; + } + } + + inputElements[inputElementCount].SemanticName = "SPRITEPOSITION"; + inputElements[inputElementCount].SemanticIndex = 0; + inputElements[inputElementCount].Format = DXGI_FORMAT_R32G32B32_FLOAT; + inputElements[inputElementCount].InputSlot = 0; + inputElements[inputElementCount].AlignedByteOffset = 0; + inputElements[inputElementCount].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + inputElements[inputElementCount].InstanceDataStepRate = 0; + inputElementCount++; + + inputElements[inputElementCount].SemanticName = "SPRITETEXCOORD"; + inputElements[inputElementCount].SemanticIndex = 0; + inputElements[inputElementCount].Format = DXGI_FORMAT_R32G32_FLOAT; + inputElements[inputElementCount].InputSlot = 0; + inputElements[inputElementCount].AlignedByteOffset = sizeof(float) * 3; + inputElements[inputElementCount].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA; + inputElements[inputElementCount].InstanceDataStepRate = 0; + inputElementCount++; + } + + const gl::InputLayout &shaderInputLayout = GetInputLayout(sortedAttributes, attribCount); + + ShaderExecutableD3D *shader = nullptr; + gl::Error error = + programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr); + if (error.isError()) + { + return error; + } + + ShaderExecutableD3D *shader11 = GetAs(shader); + + HRESULT result = + mDevice->CreateInputLayout(inputElements.data(), inputElementCount, shader11->getFunction(), + shader11->getLength(), inputLayoutOut); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal input layout, HRESULT: 0x%08x", result); + } + + return gl::Error(GL_NO_ERROR); } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h index 2c94c57595..e208ae3c64 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h @@ -10,14 +10,17 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ #define LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ -#include "libANGLE/Constants.h" -#include "libANGLE/Error.h" -#include "common/angleutils.h" - #include #include -#include + +#include +#include + +#include "common/angleutils.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Error.h" +#include "libANGLE/formatutils.h" namespace gl { @@ -27,6 +30,12 @@ class Program; namespace rx { struct TranslatedAttribute; +struct TranslatedIndexData; +struct SourceIndexData; +class ProgramD3D; + +using SortedAttribArray = std::array; +using SortedIndexArray = std::array; class InputLayoutCache : angle::NonCopyable { @@ -38,59 +47,72 @@ class InputLayoutCache : angle::NonCopyable void clear(); void markDirty(); - gl::Error applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - GLenum mode, gl::Program *program); + gl::Error applyVertexBuffers(const std::vector &attributes, + GLenum mode, + gl::Program *program, + TranslatedIndexData *indexInfo, + GLsizei numIndicesPerInstance); - private: - struct InputLayoutElement - { - D3D11_INPUT_ELEMENT_DESC desc; - GLenum glslElementType; - }; + gl::Error updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId); - struct InputLayoutKey - { - unsigned int elementCount; - InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS]; + // Useful for testing + void setCacheSize(unsigned int cacheSize) { mCacheSize = cacheSize; } - const char *begin() const + private: + struct PackedAttributeLayout + { + PackedAttributeLayout() + : numAttributes(0), + flags(0) { - return reinterpret_cast(&elementCount); } - const char *end() const + void addAttributeData(GLenum glType, + UINT semanticIndex, + gl::VertexFormatType vertexFormatType, + unsigned int divisor); + + bool operator<(const PackedAttributeLayout &other) const; + + enum Flags { - return reinterpret_cast(&elements[elementCount]); - } + FLAG_USES_INSTANCED_SPRITES = 0x1, + FLAG_INSTANCED_SPRITES_ACTIVE = 0x2, + FLAG_INSTANCED_RENDERING_ACTIVE = 0x4, + }; + + size_t numAttributes; + unsigned int flags; + uint32_t attributeData[gl::MAX_VERTEX_ATTRIBS]; }; - struct InputLayoutCounterPair - { - ID3D11InputLayout *inputLayout; - unsigned long long lastUsedTime; - }; + gl::Error updateInputLayout(gl::Program *program, + GLenum mode, + const SortedAttribArray &sortedAttributes, + const SortedIndexArray &sortedSemanticIndices, + size_t attribCount, + GLsizei numIndicesPerInstance); + gl::Error createInputLayout(const SortedAttribArray &sortedAttributes, + const SortedIndexArray &sortedSemanticIndices, + size_t attribCount, + GLenum mode, + gl::Program *program, + GLsizei numIndicesPerInstance, + ID3D11InputLayout **inputLayoutOut); + + std::map mLayoutMap; ID3D11InputLayout *mCurrentIL; ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; + SortedAttribArray mSortedAttributes; + size_t mUnsortedAttributesCount; ID3D11Buffer *mPointSpriteVertexBuffer; ID3D11Buffer *mPointSpriteIndexBuffer; - static std::size_t hashInputLayout(const InputLayoutKey &inputLayout); - static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b); - - typedef std::size_t (*InputLayoutHashFunction)(const InputLayoutKey &); - typedef bool (*InputLayoutEqualityFunction)(const InputLayoutKey &, const InputLayoutKey &); - typedef std::unordered_map InputLayoutMap; - InputLayoutMap mInputLayoutMap; - - static const unsigned int kMaxInputLayouts; - + unsigned int mCacheSize; unsigned long long mCounter; ID3D11Device *mDevice; @@ -98,6 +120,6 @@ class InputLayoutCache : angle::NonCopyable D3D_FEATURE_LEVEL mFeatureLevel; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h index 0f70fe4615..612b06bb10 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h @@ -16,6 +16,7 @@ #include "common/platform.h" #include +#include "libANGLE/Config.h" // DXGISwapChain and DXGIFactory are typedef'd to specific required // types. The HWND NativeWindow implementation requires IDXGISwapChain @@ -43,6 +44,10 @@ typedef IDXGISwapChain DXGISwapChain; typedef IDXGIFactory DXGIFactory; #endif +typedef interface IDCompositionDevice IDCompositionDevice; +typedef interface IDCompositionTarget IDCompositionTarget; +typedef interface IDCompositionVisual IDCompositionVisual; + namespace rx { @@ -50,8 +55,11 @@ class NativeWindow { public: enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 }; - explicit NativeWindow(EGLNativeWindowType window); + explicit NativeWindow(EGLNativeWindowType window, + const egl::Config *config, + bool directComposition); + ~NativeWindow(); bool initialize(); bool getClientRect(LPRECT rect); bool isIconic(); @@ -68,9 +76,16 @@ class NativeWindow inline EGLNativeWindowType getNativeWindow() const { return mWindow; } + void commitChange(); + private: EGLNativeWindowType mWindow; + bool mDirectComposition; + IDCompositionDevice *mDevice; + IDCompositionTarget *mCompositionTarget; + IDCompositionVisual *mVisual; + const egl::Config *mConfig; #if defined(ANGLE_ENABLE_WINDOWS_STORE) std::shared_ptr mImpl; #endif diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp index 5fd5237d90..dfc521f14f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -10,23 +10,25 @@ // #include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" -#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" -#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" -#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" #include "libANGLE/Texture.h" -#include "libANGLE/Buffer.h" -#include "libANGLE/Context.h" // Precompiled shaders -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h" namespace rx { @@ -202,14 +204,14 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); - const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat, mRenderer->getFeatureLevel()); + const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat, mRenderer->getRenderer11DeviceCaps()); DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); - Buffer11 *bufferStorage11 = Buffer11::makeBuffer11(sourceBuffer.getImplementation()); + Buffer11 *bufferStorage11 = GetAs(sourceBuffer.getImplementation()); ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat); ASSERT(bufferSRV != NULL); - ID3D11RenderTargetView *textureRTV = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ID3D11RenderTargetView *textureRTV = GetAs(destRenderTarget)->getRenderTargetView(); ASSERT(textureRTV != NULL); CopyShaderParams shaderParams; @@ -222,11 +224,12 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac // Are we doing a 2D or 3D copy? ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); + auto stateManager = mRenderer->getStateManager(); deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); deviceContext->GSSetShader(geometryShader, NULL, 0); deviceContext->PSSetShader(pixelShader, NULL, 0); - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); deviceContext->IASetInputLayout(NULL); deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); @@ -249,8 +252,8 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = destSize.width; - viewport.Height = destSize.height; + viewport.Width = static_cast(destSize.width); + viewport.Height = static_cast(destSize.height); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); @@ -259,7 +262,7 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac deviceContext->Draw(numPixels, 0); // Unbind textures and render targets and vertex buffer - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); mRenderer->markAllStateDirty(); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp index 4979ff51a9..c0bed2b43a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp @@ -18,6 +18,11 @@ typedef struct D3D11_QUERY_DATA_SO_STATISTICS { UINT64 NumPrimitivesWritten; UINT64 PrimitivesStorageNeeded; } D3D11_QUERY_DATA_SO_STATISTICS; + +typedef struct D3D11_QUERY_DATA_TIMESTAMP_DISJOINT { + UINT64 Frequency; + BOOL Disjoint; +} D3D11_QUERY_DATA_TIMESTAMP_DISJOINT; #endif namespace rx @@ -28,38 +33,81 @@ Query11::Query11(Renderer11 *renderer, GLenum type) mResult(0), mQueryFinished(false), mRenderer(renderer), - mQuery(NULL) + mQuery(nullptr), + mTimestampBeginQuery(nullptr), + mTimestampEndQuery(nullptr) { } Query11::~Query11() { SafeRelease(mQuery); + SafeRelease(mTimestampBeginQuery); + SafeRelease(mTimestampEndQuery); } gl::Error Query11::begin() { - if (mQuery == NULL) + if (mQuery == nullptr) { D3D11_QUERY_DESC queryDesc; queryDesc.Query = gl_d3d11::ConvertQueryType(getType()); queryDesc.MiscFlags = 0; - HRESULT result = mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery); + ID3D11Device *device = mRenderer->getDevice(); + + HRESULT result = device->CreateQuery(&queryDesc, &mQuery); if (FAILED(result)) { return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); } + + // If we are doing time elapsed we also need a query to actually query the timestamp + if (getType() == GL_TIME_ELAPSED_EXT) + { + D3D11_QUERY_DESC desc; + desc.Query = D3D11_QUERY_TIMESTAMP; + desc.MiscFlags = 0; + result = device->CreateQuery(&desc, &mTimestampBeginQuery); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", + result); + } + result = device->CreateQuery(&desc, &mTimestampEndQuery); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", + result); + } + } } - mRenderer->getDeviceContext()->Begin(mQuery); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + context->Begin(mQuery); + + // If we are doing time elapsed query the begin timestamp + if (getType() == GL_TIME_ELAPSED_EXT) + { + context->End(mTimestampBeginQuery); + } return gl::Error(GL_NO_ERROR); } gl::Error Query11::end() { ASSERT(mQuery); - mRenderer->getDeviceContext()->End(mQuery); + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + // If we are doing time elapsed query the end timestamp + if (getType() == GL_TIME_ELAPSED_EXT) + { + context->End(mTimestampEndQuery); + } + + context->End(mQuery); mQueryFinished = false; mResult = GL_FALSE; @@ -67,7 +115,17 @@ gl::Error Query11::end() return gl::Error(GL_NO_ERROR); } -gl::Error Query11::getResult(GLuint *params) +gl::Error Query11::queryCounter() +{ + // This doesn't do anything for D3D11 as we don't support timestamps + ASSERT(getType() == GL_TIMESTAMP_EXT); + mQueryFinished = true; + mResult = 0; + return gl::Error(GL_NO_ERROR); +} + +template +gl::Error Query11::getResultBase(T *params) { while (!mQueryFinished) { @@ -84,12 +142,32 @@ gl::Error Query11::getResult(GLuint *params) } ASSERT(mQueryFinished); - *params = mResult; + *params = static_cast(mResult); return gl::Error(GL_NO_ERROR); } -gl::Error Query11::isResultAvailable(GLuint *available) +gl::Error Query11::getResult(GLint *params) +{ + return getResultBase(params); +} + +gl::Error Query11::getResult(GLuint *params) +{ + return getResultBase(params); +} + +gl::Error Query11::getResult(GLint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query11::getResult(GLuint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query11::isResultAvailable(bool *available) { gl::Error error = testQuery(); if (error.isError()) @@ -97,7 +175,7 @@ gl::Error Query11::isResultAvailable(GLuint *available) return error; } - *available = (mQueryFinished ? GL_TRUE : GL_FALSE); + *available = mQueryFinished; return gl::Error(GL_NO_ERROR); } @@ -141,8 +219,74 @@ gl::Error Query11::testQuery() if (result == S_OK) { mQueryFinished = true; - mResult = static_cast(soStats.NumPrimitivesWritten); + mResult = static_cast(soStats.NumPrimitivesWritten); + } + } + break; + + case GL_TIME_ELAPSED_EXT: + { + D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {0}; + HRESULT result = context->GetData(mQuery, &timeStats, sizeof(timeStats), 0); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to get the data of an internal query, result: 0x%X.", + result); } + + if (result == S_OK) + { + UINT64 beginTime = 0; + HRESULT beginRes = + context->GetData(mTimestampBeginQuery, &beginTime, sizeof(UINT64), 0); + if (FAILED(beginRes)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to get the data of an internal query, result: 0x%X.", beginRes); + } + UINT64 endTime = 0; + HRESULT endRes = + context->GetData(mTimestampEndQuery, &endTime, sizeof(UINT64), 0); + if (FAILED(endRes)) + { + return gl::Error( + GL_OUT_OF_MEMORY, + "Failed to get the data of an internal query, result: 0x%X.", endRes); + } + + if (beginRes == S_OK && endRes == S_OK) + { + mQueryFinished = true; + if (timeStats.Disjoint) + { + mRenderer->setGPUDisjoint(); + } + static_assert(sizeof(UINT64) == sizeof(unsigned long long), + "D3D UINT64 isn't 64 bits"); + if (rx::IsUnsignedMultiplicationSafe(endTime - beginTime, 1000000000ull)) + { + mResult = ((endTime - beginTime) * 1000000000ull) / timeStats.Frequency; + } + else + { + mResult = std::numeric_limits::max() / timeStats.Frequency; + // If an overflow does somehow occur, there is no way the elapsed time + // is accurate, so we generate a disjoint event + mRenderer->setGPUDisjoint(); + } + } + } + } + break; + + case GL_TIMESTAMP_EXT: + { + // D3D11 doesn't support GL timestamp queries as D3D timestamps are not guaranteed + // to have any sort of continuity outside of a disjoint timestamp query block, which + // GL depends on + mResult = 0; } break; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h index bd53fed250..29a6e6f85d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h @@ -23,18 +23,27 @@ class Query11 : public QueryImpl virtual gl::Error begin(); virtual gl::Error end(); + virtual gl::Error queryCounter(); + virtual gl::Error getResult(GLint *params); virtual gl::Error getResult(GLuint *params); - virtual gl::Error isResultAvailable(GLuint *available); + virtual gl::Error getResult(GLint64 *params); + virtual gl::Error getResult(GLuint64 *params); + virtual gl::Error isResultAvailable(bool *available); private: gl::Error testQuery(); - GLuint mResult; + template + gl::Error getResultBase(T *params); + + GLuint64 mResult; bool mQueryFinished; Renderer11 *mRenderer; ID3D11Query *mQuery; + ID3D11Query *mTimestampBeginQuery; + ID3D11Query *mTimestampEndQuery; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp index 4990e6bc6e..2ee25cfb6c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp @@ -21,6 +21,7 @@ namespace rx { +using namespace gl_d3d11; template static void ClearStateMap(mapType &map) @@ -42,12 +43,12 @@ const unsigned int RenderStateCache::kMaxSamplerStates = 4096; RenderStateCache::RenderStateCache(Renderer11 *renderer) : mRenderer(renderer), - mDevice(NULL), mCounter(0), mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), - mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates) + mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates), + mDevice(NULL) { } @@ -95,9 +96,9 @@ gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, co bool mrt = false; const FramebufferD3D *framebufferD3D = GetImplAs(framebuffer); - const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds()); + const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(); - BlendStateKey key = { 0 }; + BlendStateKey key = {}; key.blendState = blendState; for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { @@ -209,7 +210,7 @@ gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &raster return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); } - RasterizerStateKey key = { 0 }; + RasterizerStateKey key = {}; key.rasterizerState = rasterState; key.scissorEnabled = scissorEnabled; @@ -297,14 +298,31 @@ bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; } -gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState) +gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState, + bool disableDepth, + bool disableStencil, + ID3D11DepthStencilState **outDSState) { if (!mDevice) { return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); } - DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState); + gl::DepthStencilState glState = originalState; + if (disableDepth) + { + glState.depthTest = false; + glState.depthMask = false; + } + + if (disableStencil) + { + glState.stencilWritemask = 0; + glState.stencilBackWritemask = 0; + glState.stencilTest = false; + } + + auto keyIter = mDepthStencilStateCache.find(glState); if (keyIter != mDepthStencilStateCache.end()) { DepthStencilStateCounterPair &state = keyIter->second; @@ -312,53 +330,55 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &ds *outDSState = state.first; return gl::Error(GL_NO_ERROR); } - else + + if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) { - if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) - { - TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used " - "to make room.", kMaxDepthStencilStates); + TRACE( + "Overflowed the limit of %u depth stencil states, removing the least recently used " + "to make room.", + kMaxDepthStencilStates); - DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin(); - for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + auto leastRecentlyUsed = mDepthStencilStateCache.begin(); + for (auto i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } + leastRecentlyUsed = i; } - SafeRelease(leastRecentlyUsed->second.first); - mDepthStencilStateCache.erase(leastRecentlyUsed); } + SafeRelease(leastRecentlyUsed->second.first); + mDepthStencilStateCache.erase(leastRecentlyUsed); + } - D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; - dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE; - dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask); - dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc); - dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE; - dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask); - dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask); - dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail); - dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail); - dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass); - dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc); - dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail); - dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail); - dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass); - dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc); - - ID3D11DepthStencilState *dx11DepthStencilState = NULL; - HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); - if (FAILED(result) || !dx11DepthStencilState) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - } + D3D11_DEPTH_STENCIL_DESC dsDesc = {0}; + dsDesc.DepthEnable = glState.depthTest ? TRUE : FALSE; + dsDesc.DepthWriteMask = ConvertDepthMask(glState.depthMask); + dsDesc.DepthFunc = ConvertComparison(glState.depthFunc); + dsDesc.StencilEnable = glState.stencilTest ? TRUE : FALSE; + dsDesc.StencilReadMask = ConvertStencilMask(glState.stencilMask); + dsDesc.StencilWriteMask = ConvertStencilMask(glState.stencilWritemask); + dsDesc.FrontFace.StencilFailOp = ConvertStencilOp(glState.stencilFail); + dsDesc.FrontFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilPassDepthFail); + dsDesc.FrontFace.StencilPassOp = ConvertStencilOp(glState.stencilPassDepthPass); + dsDesc.FrontFace.StencilFunc = ConvertComparison(glState.stencilFunc); + dsDesc.BackFace.StencilFailOp = ConvertStencilOp(glState.stencilBackFail); + dsDesc.BackFace.StencilDepthFailOp = ConvertStencilOp(glState.stencilBackPassDepthFail); + dsDesc.BackFace.StencilPassOp = ConvertStencilOp(glState.stencilBackPassDepthPass); + dsDesc.BackFace.StencilFunc = ConvertComparison(glState.stencilBackFunc); + + ID3D11DepthStencilState *dx11DepthStencilState = NULL; + HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); + if (FAILED(result) || !dx11DepthStencilState) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + } - mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++))); + mDepthStencilStateCache.insert( + std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++))); - *outDSState = dx11DepthStencilState; - return gl::Error(GL_NO_ERROR); - } + *outDSState = dx11DepthStencilState; + return gl::Error(GL_NO_ERROR); } std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) @@ -416,7 +436,7 @@ gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR); samplerDesc.MipLODBias = 0; - samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy; + samplerDesc.MaxAnisotropy = static_cast(samplerState.maxAnisotropy); samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc); samplerDesc.BorderColor[0] = 0.0f; samplerDesc.BorderColor[1] = 0.0f; @@ -425,7 +445,7 @@ gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState samplerDesc.MinLOD = samplerState.minLod; samplerDesc.MaxLOD = samplerState.maxLod; - if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) { // Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support anything other than FLT_MAX. // Note that Feature Level 9_* only supports GL ES 2.0, so the consumer of ANGLE can't modify the Max LOD themselves. diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h index 0099b94a04..82cb13903c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h @@ -36,7 +36,10 @@ class RenderStateCache : angle::NonCopyable gl::Error getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, ID3D11BlendState **outBlendState); gl::Error getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, ID3D11RasterizerState **outRasterizerState); - gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState); + gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, + bool disableDepth, + bool disableStencil, + ID3D11DepthStencilState **outDSState); gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState); private: diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp index ecd9e13c90..cdfcacc287 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp @@ -8,10 +8,12 @@ // retained by Renderbuffers. #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" + +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" -#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" namespace rx { @@ -176,12 +178,6 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); } -RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTargetD3D *target) -{ - ASSERT(HAS_DYNAMIC_TYPE(RenderTarget11*, target)); - return static_cast(target); -} - TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) : mWidth(width), @@ -352,7 +348,7 @@ GLsizei SurfaceRenderTarget11::getDepth() const GLenum SurfaceRenderTarget11::getInternalFormat() const { - return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); + return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetRenderTargetInternalFormat()); } GLsizei SurfaceRenderTarget11::getSamples() const @@ -388,7 +384,7 @@ unsigned int SurfaceRenderTarget11::getSubresourceIndex() const DXGI_FORMAT SurfaceRenderTarget11::getDXGIFormat() const { - return d3d11::GetTextureFormatInfo(getInternalFormat(), mRenderer->getFeatureLevel()).texFormat; + return d3d11::GetTextureFormatInfo(getInternalFormat(), mRenderer->getRenderer11DeviceCaps()).texFormat; } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h index 4472a56175..d47b237c09 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h @@ -23,8 +23,6 @@ class RenderTarget11 : public RenderTargetD3D RenderTarget11() { } virtual ~RenderTarget11() { } - static RenderTarget11 *makeRenderTarget11(RenderTargetD3D *renderTarget); - virtual ID3D11Resource *getTexture() const = 0; virtual ID3D11RenderTargetView *getRenderTargetView() const = 0; virtual ID3D11DepthStencilView *getDepthStencilView() const = 0; @@ -33,9 +31,6 @@ class RenderTarget11 : public RenderTargetD3D virtual unsigned int getSubresourceIndex() const = 0; virtual DXGI_FORMAT getDXGIFormat() const = 0; - - private: - D3D_FEATURE_LEVEL mFeatureLevel; }; class TextureRenderTarget11 : public RenderTarget11 diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 223e2b019b..62badccefc 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -8,47 +8,63 @@ #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" -#include "common/utilities.h" +#include +#include +#if !defined(ANGLE_MINGW32_COMPAT) && WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP +#include +#endif + #include "common/tls.h" +#include "common/utilities.h" #include "libANGLE/Buffer.h" #include "libANGLE/Display.h" +#include "libANGLE/formatutils.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/histogram_macros.h" #include "libANGLE/Program.h" -#include "libANGLE/State.h" -#include "libANGLE/Surface.h" -#include "libANGLE/formatutils.h" #include "libANGLE/renderer/d3d/CompilerD3D.h" -#include "libANGLE/renderer/d3d/FramebufferD3D.h" -#include "libANGLE/renderer/d3d/IndexDataManager.h" -#include "libANGLE/renderer/d3d/ProgramD3D.h" -#include "libANGLE/renderer/d3d/RenderbufferD3D.h" -#include "libANGLE/renderer/d3d/ShaderD3D.h" -#include "libANGLE/renderer/d3d/SurfaceD3D.h" -#include "libANGLE/renderer/d3d/TextureD3D.h" -#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" -#include "libANGLE/renderer/d3d/VertexDataManager.h" #include "libANGLE/renderer/d3d/d3d11/Blit11.h" #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" #include "libANGLE/renderer/d3d/d3d11/Clear11.h" +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" #include "libANGLE/renderer/d3d/d3d11/Fence11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" #include "libANGLE/renderer/d3d/d3d11/Image11.h" #include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" #include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h" #include "libANGLE/renderer/d3d/d3d11/Query11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" #include "libANGLE/renderer/d3d/d3d11/Trim11.h" #include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" -#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" +#include "libANGLE/renderer/d3d/VertexDataManager.h" +#include "libANGLE/State.h" +#include "libANGLE/Surface.h" +#include "third_party/trace_event/trace_event.h" -#include -#include +// Include the D3D9 debug annotator header for use by the desktop D3D11 renderer +// because the D3D11 interface method ID3DUserDefinedAnnotation::GetStatus +// doesn't work with the Graphics Diagnostics tools in Visual Studio 2013. +#ifdef ANGLE_ENABLE_D3D9 +#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h" +#endif // Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process // HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. @@ -62,67 +78,6 @@ #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 #endif -#ifndef __d3d11sdklayers_h__ -#define D3D11_MESSAGE_CATEGORY UINT -#define D3D11_MESSAGE_SEVERITY UINT -#define D3D11_MESSAGE_ID UINT -struct D3D11_MESSAGE; -typedef struct D3D11_INFO_QUEUE_FILTER_DESC -{ - UINT NumCategories; - D3D11_MESSAGE_CATEGORY *pCategoryList; - UINT NumSeverities; - D3D11_MESSAGE_SEVERITY *pSeverityList; - UINT NumIDs; - D3D11_MESSAGE_ID *pIDList; -} D3D11_INFO_QUEUE_FILTER_DESC; -typedef struct D3D11_INFO_QUEUE_FILTER -{ - D3D11_INFO_QUEUE_FILTER_DESC AllowList; - D3D11_INFO_QUEUE_FILTER_DESC DenyList; -} D3D11_INFO_QUEUE_FILTER; -static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 }; -MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown -{ -public: - virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0; - virtual void __stdcall ClearStoredMessages() = 0; - virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0; - virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0; - virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0; - virtual UINT64 __stdcall GetNumStoredMessages() = 0; - virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0; - virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0; - virtual UINT64 __stdcall GetMessageCountLimit() = 0; - virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; - virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; - virtual void __stdcall ClearStorageFilter() = 0; - virtual HRESULT __stdcall PushEmptyStorageFilter() = 0; - virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0; - virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0; - virtual void __stdcall PopStorageFilter() = 0; - virtual UINT __stdcall GetStorageFilterStackSize() = 0; - virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0; - virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0; - virtual void __stdcall ClearRetrievalFilter() = 0; - virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0; - virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0; - virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0; - virtual void __stdcall PopRetrievalFilter() = 0; - virtual UINT __stdcall GetRetrievalFilterStackSize() = 0; - virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0; - virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0; - virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0; - virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0; - virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0; - virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0; - virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0; - virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0; - virtual void __stdcall SetMuteDebugOutput(BOOL) = 0; - virtual BOOL __stdcall GetMuteDebugOutput() = 0; -}; -#endif - namespace rx { @@ -134,107 +89,299 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 }; -// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state. -static const uintptr_t DirtyPointer = static_cast(-1); +#if defined(ANGLE_ENABLE_D3D11_1) +void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFirstConstant, UINT *outNumConstants) +{ + // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange). + ASSERT(offset % 256 == 0); + + // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must be a multiple of 16 constants. + *outFirstConstant = static_cast(offset / 16); + + // The GL size is not required to be aligned to a 256 bytes boundary. + // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes. + *outNumConstants = static_cast(rx::roundUp(size, static_cast(256)) / 16); + + // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size of the buffer. + // This behaviour is explictly allowed according to the documentation on ID3D11DeviceContext1::PSSetConstantBuffers1 + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx +} +#endif -static bool ImageIndexConflictsWithSRV(const gl::ImageIndex *index, D3D11_SHADER_RESOURCE_VIEW_DESC desc) +enum ANGLEFeatureLevel { - unsigned mipLevel = index->mipIndex; - unsigned layerIndex = index->layerIndex; - GLenum type = index->type; + ANGLE_FEATURE_LEVEL_INVALID, + ANGLE_FEATURE_LEVEL_9_3, + ANGLE_FEATURE_LEVEL_10_0, + ANGLE_FEATURE_LEVEL_10_1, + ANGLE_FEATURE_LEVEL_11_0, + ANGLE_FEATURE_LEVEL_11_1, + NUM_ANGLE_FEATURE_LEVELS +}; - switch (desc.ViewDimension) +ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel) +{ + switch (d3dFeatureLevel) { - case D3D11_SRV_DIMENSION_TEXTURE2D: - { - unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip; - maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip; + case D3D_FEATURE_LEVEL_9_3: return ANGLE_FEATURE_LEVEL_9_3; + case D3D_FEATURE_LEVEL_10_0: return ANGLE_FEATURE_LEVEL_10_0; + case D3D_FEATURE_LEVEL_10_1: return ANGLE_FEATURE_LEVEL_10_1; + case D3D_FEATURE_LEVEL_11_0: return ANGLE_FEATURE_LEVEL_11_0; + // Note: we don't ever request a 11_1 device, because this gives + // an E_INVALIDARG error on systems that don't have the platform update. + case D3D_FEATURE_LEVEL_11_1: return ANGLE_FEATURE_LEVEL_11_1; + default: return ANGLE_FEATURE_LEVEL_INVALID; + } +} - unsigned mipMin = index->mipIndex; - unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex; +void SetLineLoopIndices(GLuint *dest, size_t count) +{ + for (size_t i = 0; i < count; i++) + { + dest[i] = static_cast(i); + } + dest[count] = 0; +} - return type == GL_TEXTURE_2D && RangeUI(mipMin, mipMax).intersects(RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip)); - } +template +void CopyLineLoopIndices(const GLvoid *indices, GLuint *dest, size_t count) +{ + const T *srcPtr = static_cast(indices); + for (size_t i = 0; i < count; ++i) + { + dest[i] = static_cast(srcPtr[i]); + } + dest[count] = static_cast(srcPtr[0]); +} - case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: - { - unsigned maxSrvMip = desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip; - maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip; +void SetTriangleFanIndices(GLuint *destPtr, size_t numTris) +{ + for (size_t i = 0; i < numTris; i++) + { + destPtr[i * 3 + 0] = 0; + destPtr[i * 3 + 1] = static_cast(i) + 1; + destPtr[i * 3 + 2] = static_cast(i) + 2; + } +} - unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize; +template +void CopyLineLoopIndicesWithRestart(const GLvoid *indices, + size_t count, + GLenum indexType, + std::vector *bufferOut) +{ + GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType); + GLuint d3dRestartIndex = static_cast(d3d11::GetPrimitiveRestartIndex()); + const T *srcPtr = static_cast(indices); + Optional currentLoopStart; - // Cube maps can be mapped to Texture2DArray SRVs - return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) && - desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip && - desc.Texture2DArray.FirstArraySlice <= layerIndex && layerIndex < maxSlice; - } + bufferOut->clear(); - case D3D11_SRV_DIMENSION_TEXTURECUBE: - { - unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip; - maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip; + for (size_t indexIdx = 0; indexIdx < count; ++indexIdx) + { + GLuint value = static_cast(srcPtr[indexIdx]); - return gl::IsCubeMapTextureTarget(type) && - desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; + if (value == restartIndex) + { + if (currentLoopStart.valid()) + { + bufferOut->push_back(currentLoopStart.value()); + bufferOut->push_back(d3dRestartIndex); + currentLoopStart.reset(); + } } - - case D3D11_SRV_DIMENSION_TEXTURE3D: + else { - unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip; - maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip; - - return type == GL_TEXTURE_3D && - desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; + bufferOut->push_back(value); + if (!currentLoopStart.valid()) + { + currentLoopStart = value; + } } - default: - // We only handle the cases corresponding to valid image indexes - UNIMPLEMENTED(); } - return false; + if (currentLoopStart.valid()) + { + bufferOut->push_back(currentLoopStart.value()); + } +} + +void GetLineLoopIndices(const GLvoid *indices, + GLenum indexType, + GLuint count, + bool usePrimitiveRestartFixedIndex, + std::vector *bufferOut) +{ + if (indexType != GL_NONE && usePrimitiveRestartFixedIndex) + { + switch (indexType) + { + case GL_UNSIGNED_BYTE: + CopyLineLoopIndicesWithRestart(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_SHORT: + CopyLineLoopIndicesWithRestart(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_INT: + CopyLineLoopIndicesWithRestart(indices, count, indexType, bufferOut); + break; + default: + UNREACHABLE(); + break; + } + return; + } + + // For non-primitive-restart draws, the index count is static. + bufferOut->resize(static_cast(count) + 1); + + switch (indexType) + { + // Non-indexed draw + case GL_NONE: + SetLineLoopIndices(&(*bufferOut)[0], count); + break; + case GL_UNSIGNED_BYTE: + CopyLineLoopIndices(indices, &(*bufferOut)[0], count); + break; + case GL_UNSIGNED_SHORT: + CopyLineLoopIndices(indices, &(*bufferOut)[0], count); + break; + case GL_UNSIGNED_INT: + CopyLineLoopIndices(indices, &(*bufferOut)[0], count); + break; + default: + UNREACHABLE(); + break; + } } -// Does *not* increment the resource ref count!! -ID3D11Resource *GetViewResource(ID3D11View *view) +template +void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTris) { - ID3D11Resource *resource = NULL; - ASSERT(view); - view->GetResource(&resource); - resource->Release(); - return resource; + const T *srcPtr = static_cast(indices); + + for (size_t i = 0; i < numTris; i++) + { + destPtr[i * 3 + 0] = static_cast(srcPtr[0]); + destPtr[i * 3 + 1] = static_cast(srcPtr[i + 1]); + destPtr[i * 3 + 2] = static_cast(srcPtr[i + 2]); + } } -void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFirstConstant, UINT *outNumConstants) +template +void CopyTriangleFanIndicesWithRestart(const GLvoid *indices, + GLuint indexCount, + GLenum indexType, + std::vector *bufferOut) { - // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange). - ASSERT(offset % 256 == 0); + GLuint restartIndex = gl::GetPrimitiveRestartIndex(indexType); + GLuint d3dRestartIndex = gl::GetPrimitiveRestartIndex(GL_UNSIGNED_INT); + const T *srcPtr = static_cast(indices); + Optional vertexA; + Optional vertexB; - // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must be a multiple of 16 constants. - *outFirstConstant = offset / 16; + bufferOut->clear(); - // The GL size is not required to be aligned to a 256 bytes boundary. - // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes. - *outNumConstants = rx::roundUp(size, static_cast(256)) / 16; + for (size_t indexIdx = 0; indexIdx < indexCount; ++indexIdx) + { + GLuint value = static_cast(srcPtr[indexIdx]); - // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size of the buffer. - // This behaviour is explictly allowed according to the documentation on ID3D11DeviceContext1::PSSetConstantBuffers1 - // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx + if (value == restartIndex) + { + bufferOut->push_back(d3dRestartIndex); + vertexA.reset(); + vertexB.reset(); + } + else + { + if (!vertexA.valid()) + { + vertexA = value; + } + else if (!vertexB.valid()) + { + vertexB = value; + } + else + { + bufferOut->push_back(vertexA.value()); + bufferOut->push_back(vertexB.value()); + bufferOut->push_back(value); + vertexB = value; + } + } + } } +void GetTriFanIndices(const GLvoid *indices, + GLenum indexType, + GLuint count, + bool usePrimitiveRestartFixedIndex, + std::vector *bufferOut) +{ + if (indexType != GL_NONE && usePrimitiveRestartFixedIndex) + { + switch (indexType) + { + case GL_UNSIGNED_BYTE: + CopyTriangleFanIndicesWithRestart(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_SHORT: + CopyTriangleFanIndicesWithRestart(indices, count, indexType, bufferOut); + break; + case GL_UNSIGNED_INT: + CopyTriangleFanIndicesWithRestart(indices, count, indexType, bufferOut); + break; + default: + UNREACHABLE(); + break; + } + return; + } + + // For non-primitive-restart draws, the index count is static. + GLuint numTris = count - 2; + bufferOut->resize(numTris * 3); + + switch (indexType) + { + // Non-indexed draw + case GL_NONE: + SetTriangleFanIndices(&(*bufferOut)[0], numTris); + break; + case GL_UNSIGNED_BYTE: + CopyTriangleFanIndices(indices, &(*bufferOut)[0], numTris); + break; + case GL_UNSIGNED_SHORT: + CopyTriangleFanIndices(indices, &(*bufferOut)[0], numTris); + break; + case GL_UNSIGNED_INT: + CopyTriangleFanIndices(indices, &(*bufferOut)[0], numTris); + break; + default: + UNREACHABLE(); + break; + } } +} // anonymous namespace + Renderer11::Renderer11(egl::Display *display) : RendererD3D(display), - mStateCache(this) + mStateCache(this), + mStateManager(this), + mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()) +#if !defined(ANGLE_MINGW32_COMPAT) + ,mDebug(nullptr) +#endif { - // Initialize global annotator - gl::InitializeDebugAnnotations(&mAnnotator); - mVertexDataManager = NULL; mIndexDataManager = NULL; mLineLoopIB = NULL; mTriangleFanIB = NULL; + mAppliedIBChanged = false; mBlit = NULL; mPixelTransfer = NULL; @@ -245,10 +392,18 @@ Renderer11::Renderer11(egl::Display *display) mSyncQuery = NULL; - mSupportsConstantBufferOffsets = false; + mRenderer11DeviceCaps.supportsClearView = false; + mRenderer11DeviceCaps.supportsConstantBufferOffsets = false; + mRenderer11DeviceCaps.supportsDXGI1_2 = false; + mRenderer11DeviceCaps.B5G6R5support = 0; + mRenderer11DeviceCaps.B4G4R4A4support = 0; + mRenderer11DeviceCaps.B5G5R5A1support = 0; mD3d11Module = NULL; mDxgiModule = NULL; + mDCompModule = NULL; + mCreatedWithDeviceEXT = false; + mEGLDevice = nullptr; mDevice = NULL; mDeviceContext = NULL; @@ -265,89 +420,105 @@ Renderer11::Renderer11(egl::Display *display) mAppliedNumXFBBindings = static_cast(-1); - const auto &attributes = mDisplay->getAttributeMap(); - - EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); - EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); + ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription)); - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) + if (mDisplay->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE) { - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); - } - } + const auto &attributes = mDisplay->getAttributeMap(); - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10) - { - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + EGLint requestedMajorVersion = + attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE); + EGLint requestedMinorVersion = + attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE); + + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1); + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); + } } - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 10) { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0); + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_1); + } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_10_0); + } } - } #if defined(ANGLE_ENABLE_WINDOWS_STORE) - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) #else - if (requestedMajorVersion == 9 && requestedMinorVersion == 3) + if (requestedMajorVersion == 9 && requestedMinorVersion == 3) #endif - { - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); - } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + } #if defined(ANGLE_ENABLE_WINDOWS_STORE) - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) - { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); + } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); + } +#endif } - if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + + EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE); + switch (requestedDeviceType) { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); - } -#endif - } + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: + mRequestedDriverType = D3D_DRIVER_TYPE_HARDWARE; + break; - EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE); - switch (requestedDeviceType) - { - case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: - mDriverType = D3D_DRIVER_TYPE_HARDWARE; - break; + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE: + mRequestedDriverType = D3D_DRIVER_TYPE_WARP; + break; - case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE: - mDriverType = D3D_DRIVER_TYPE_WARP; - break; + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: + mRequestedDriverType = D3D_DRIVER_TYPE_REFERENCE; + break; - case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE: - mDriverType = D3D_DRIVER_TYPE_REFERENCE; - break; + case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: + mRequestedDriverType = D3D_DRIVER_TYPE_NULL; + break; - case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: - mDriverType = D3D_DRIVER_TYPE_NULL; - break; + default: + UNREACHABLE(); + } - default: - UNREACHABLE(); + const EGLenum presentPath = attributes.get(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, + EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE); + mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE); } -} + else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) + { + mEGLDevice = GetImplAs(display->getDevice()); + ASSERT(mEGLDevice != nullptr); + mCreatedWithDeviceEXT = true; -Renderer11::~Renderer11() -{ - release(); + // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE + // mAvailableFeatureLevels defaults to empty + mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN; + mPresentPathFastEnabled = false; + } - gl::UninitializeDebugAnnotations(); + initializeDebugAnnotator(); } -Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) +Renderer11::~Renderer11() { - ASSERT(HAS_DYNAMIC_TYPE(Renderer11*, renderer)); - return static_cast(renderer); + release(); } #ifndef __d3d11_1_h__ @@ -356,209 +527,268 @@ Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) egl::Error Renderer11::initialize() { - if (!mCompiler.initialize()) + HRESULT result = S_OK; + + egl::Error error = initializeD3DDevice(); + if (error.isError()) { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_COMPILER_ERROR, - "Failed to initialize compiler."); + return error; } #if !defined(ANGLE_ENABLE_WINDOWS_STORE) - mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); - mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); - - if (mD3d11Module == NULL || mDxgiModule == NULL) +#if !ANGLE_SKIP_DXGI_1_2_CHECK { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_MISSING_DEP, - "Could not load D3D11 or DXGI library."); - } - - // create the D3D11 device - ASSERT(mDevice == NULL); - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + TRACE_EVENT0("gpu.angle", "Renderer11::initialize (DXGICheck)"); + // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. + // The easiest way to check is to query for a IDXGIDevice2. + bool requireDXGI1_2 = false; + HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId()); + if (hwnd) + { + DWORD currentProcessId = GetCurrentProcessId(); + DWORD wndProcessId; + GetWindowThreadProcessId(hwnd, &wndProcessId); + requireDXGI1_2 = (currentProcessId != wndProcessId); + } + else + { + requireDXGI1_2 = true; + } - if (D3D11CreateDevice == NULL) - { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_MISSING_DEP, - "Could not retrieve D3D11CreateDevice address."); + if (requireDXGI1_2) + { + IDXGIDevice2 *dxgiDevice2 = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); + if (FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_INCOMPATIBLE_DXGI, + "DXGI 1.2 required to present to HWNDs owned by another process."); + } + SafeRelease(dxgiDevice2); + } } +#endif #endif - HRESULT result = S_OK; -#ifdef _DEBUG - result = D3D11CreateDevice(NULL, - mDriverType, - NULL, - D3D11_CREATE_DEVICE_DEBUG, - mAvailableFeatureLevels.data(), - mAvailableFeatureLevels.size(), - D3D11_SDK_VERSION, - &mDevice, - &mFeatureLevel, - &mDeviceContext); - - if (!mDevice || FAILED(result)) { - ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); - } - - if (!mDevice || FAILED(result)) + TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)"); + // Cast the DeviceContext to a DeviceContext1. + // This could fail on Windows 7 without the Platform Update. + // Don't error in this case- just don't use mDeviceContext1. +#if defined(ANGLE_ENABLE_D3D11_1) + mDeviceContext1 = d3d11::DynamicCastComObject(mDeviceContext); #endif - { - result = D3D11CreateDevice(NULL, - mDriverType, - NULL, - 0, - mAvailableFeatureLevels.data(), - mAvailableFeatureLevels.size(), - D3D11_SDK_VERSION, - &mDevice, - &mFeatureLevel, - &mDeviceContext); - if (result == E_INVALIDARG) + IDXGIDevice *dxgiDevice = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); + + if (FAILED(result)) { - // Cleanup done by destructor through glDestroyRenderer return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_CREATEDEVICE_INVALIDARG, - "Could not create D3D11 device."); + D3D11_INIT_OTHER_ERROR, + "Could not query DXGI device."); } - if (!mDevice || FAILED(result)) + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); + + if (FAILED(result)) { - // Cleanup done by destructor through glDestroyRenderer return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_CREATEDEVICE_ERROR, - "Could not create D3D11 device."); + D3D11_INIT_OTHER_ERROR, + "Could not retrieve DXGI adapter"); } - } -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) -#if !ANGLE_SKIP_DXGI_1_2_CHECK - // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. - // The easiest way to check is to query for a IDXGIDevice2. - bool requireDXGI1_2 = false; - HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId()); - if (hwnd) - { - DWORD currentProcessId = GetCurrentProcessId(); - DWORD wndProcessId; - GetWindowThreadProcessId(hwnd, &wndProcessId); - requireDXGI1_2 = (currentProcessId != wndProcessId); - } - else - { - requireDXGI1_2 = true; - } + SafeRelease(dxgiDevice); - if (requireDXGI1_2) - { - IDXGIDevice2 *dxgiDevice2 = NULL; - result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); - if (FAILED(result)) +#if defined(ANGLE_ENABLE_D3D11_1) + IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject(mDxgiAdapter); + + // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string. + // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual hardware values. + if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != NULL) { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_INCOMPATIBLE_DXGI, - "DXGI 1.2 required to present to HWNDs owned by another process."); + DXGI_ADAPTER_DESC2 adapterDesc2 = {}; + result = dxgiAdapter2->GetDesc2(&adapterDesc2); + if (SUCCEEDED(result)) + { + // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a DXGI_ADAPTER_DESC). + memcpy(mAdapterDescription.Description, adapterDesc2.Description, sizeof(mAdapterDescription.Description)); + mAdapterDescription.VendorId = adapterDesc2.VendorId; + mAdapterDescription.DeviceId = adapterDesc2.DeviceId; + mAdapterDescription.SubSysId = adapterDesc2.SubSysId; + mAdapterDescription.Revision = adapterDesc2.Revision; + mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory; + mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory; + mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory; + mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid; + } } - SafeRelease(dxgiDevice2); - } -#endif + else #endif + { + result = mDxgiAdapter->GetDesc(&mAdapterDescription); + } - // Cast the DeviceContext to a DeviceContext1. - // This could fail on Windows 7 without the Platform Update. - // Don't error in this case- just don't use mDeviceContext1. #if defined(ANGLE_ENABLE_D3D11_1) - mDeviceContext1 = d3d11::DynamicCastComObject(mDeviceContext); + SafeRelease(dxgiAdapter2); #endif - IDXGIDevice *dxgiDevice = NULL; - result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); + if (FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_OTHER_ERROR, + "Could not read DXGI adaptor description."); + } - if (FAILED(result)) - { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_OTHER_ERROR, - "Could not query DXGI device."); - } + memset(mDescription, 0, sizeof(mDescription)); + wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); - result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); + result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); - if (FAILED(result)) - { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_OTHER_ERROR, - "Could not retrieve DXGI adapter"); + if (!mDxgiFactory || FAILED(result)) + { + return egl::Error(EGL_NOT_INITIALIZED, + D3D11_INIT_OTHER_ERROR, + "Could not create DXGI factory."); + } } - SafeRelease(dxgiDevice); +#if !defined(ANGLE_MINGW32_COMPAT) + // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log +#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) + { + TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)"); + ID3D11InfoQueue *infoQueue; + result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); -#if defined(ANGLE_ENABLE_D3D11_1) - IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject(mDxgiAdapter); + if (SUCCEEDED(result)) + { + D3D11_MESSAGE_ID hideMessages[] = + { + D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET + }; - // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string. - // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual hardware values. - if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != NULL) - { - DXGI_ADAPTER_DESC2 adapterDesc2 = {0}; - dxgiAdapter2->GetDesc2(&adapterDesc2); + D3D11_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumIDs = static_cast(ArraySize(hideMessages)); + filter.DenyList.pIDList = hideMessages; - // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a DXGI_ADAPTER_DESC). - memcpy(mAdapterDescription.Description, adapterDesc2.Description, sizeof(mAdapterDescription.Description)); - mAdapterDescription.VendorId = adapterDesc2.VendorId; - mAdapterDescription.DeviceId = adapterDesc2.DeviceId; - mAdapterDescription.SubSysId = adapterDesc2.SubSysId; - mAdapterDescription.Revision = adapterDesc2.Revision; - mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory; - mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory; - mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory; - mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid; - } - else - { - mDxgiAdapter->GetDesc(&mAdapterDescription); + infoQueue->AddStorageFilterEntries(&filter); + SafeRelease(infoQueue); + } } +#endif - SafeRelease(dxgiAdapter2); +#if !defined(NDEBUG) + mDebug = d3d11::DynamicCastComObject(mDevice); #endif +#endif // !ANGLE_MINGW32_COMPAT + + initializeDevice(); - memset(mDescription, 0, sizeof(mDescription)); - wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); + return egl::Error(EGL_SUCCESS); +} - result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); +egl::Error Renderer11::initializeD3DDevice() +{ + HRESULT result = S_OK; - if (!mDxgiFactory || FAILED(result)) + if (!mCreatedWithDeviceEXT) { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_OTHER_ERROR, - "Could not create DXGI factory."); - } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr; + { + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDLLsMS"); + TRACE_EVENT0("gpu.angle", "Renderer11::initialize (Load DLLs)"); + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + mDCompModule = LoadLibrary(TEXT("dcomp.dll")); - // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log -#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) - ID3D11InfoQueue *infoQueue; - result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue); + if (mD3d11Module == nullptr || mDxgiModule == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, + "Could not load D3D11 or DXGI library."); + } + + // create the D3D11 device + ASSERT(mDevice == nullptr); + D3D11CreateDevice = reinterpret_cast( + GetProcAddress(mD3d11Module, "D3D11CreateDevice")); + + if (D3D11CreateDevice == nullptr) + { + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, + "Could not retrieve D3D11CreateDevice address."); + } + } +#endif + +#ifdef _DEBUG + { + TRACE_EVENT0("gpu.angle", "D3D11CreateDevice (Debug)"); + result = D3D11CreateDevice(nullptr, mRequestedDriverType, nullptr, + D3D11_CREATE_DEVICE_DEBUG, mAvailableFeatureLevels.data(), + static_cast(mAvailableFeatureLevels.size()), + D3D11_SDK_VERSION, &mDevice, + &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); + } + + if (!mDevice || FAILED(result)) + { + ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + } + + if (!mDevice || FAILED(result)) +#endif + { + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.D3D11CreateDeviceMS"); + TRACE_EVENT0("gpu.angle", "D3D11CreateDevice"); + + result = D3D11CreateDevice( + nullptr, mRequestedDriverType, nullptr, 0, mAvailableFeatureLevels.data(), + static_cast(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, + &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); - if (SUCCEEDED(result)) + // Cleanup done by destructor + if (!mDevice || FAILED(result)) + { + ANGLE_HISTOGRAM_SPARSE_SLOWLY("GPU.ANGLE.D3D11CreateDeviceError", + static_cast(result)); + return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_CREATEDEVICE_ERROR, + "Could not create D3D11 device."); + } + } + } + else { - D3D11_MESSAGE_ID hideMessages[] = + // We should use the inputted D3D11 device instead + void *device = nullptr; + egl::Error error = mEGLDevice->getDevice(&device); + if (error.isError()) + { + return error; + } + + ID3D11Device *d3dDevice = reinterpret_cast(device); + if (FAILED(d3dDevice->GetDeviceRemovedReason())) { - D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET - }; + return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost."); + } - D3D11_INFO_QUEUE_FILTER filter = {0}; - filter.DenyList.NumIDs = ArraySize(hideMessages); - filter.DenyList.pIDList = hideMessages; + if (d3dDevice->GetFeatureLevel() < D3D_FEATURE_LEVEL_9_3) + { + return egl::Error(EGL_NOT_INITIALIZED, + "Inputted D3D11 device must be Feature Level 9_3 or greater."); + } - infoQueue->AddStorageFilterEntries(&filter); - SafeRelease(infoQueue); + // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does. + mDevice = d3dDevice; + mDevice->AddRef(); + mDevice->GetImmediateContext(&mDeviceContext); + mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel(); } -#endif - initializeDevice(); + d3d11::SetDebugName(mDeviceContext, "DeviceContext"); return egl::Error(EGL_SUCCESS); } @@ -568,6 +798,11 @@ egl::Error Renderer11::initialize() // to reset the scene status and ensure the default states are reset. void Renderer11::initializeDevice() { + SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDeviceMS"); + TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice"); + + populateRenderer11DeviceCaps(); + mStateCache.initialize(mDevice); mInputLayoutCache.initialize(mDevice, mDeviceContext); @@ -598,14 +833,7 @@ void Renderer11::initializeDevice() const gl::Caps &rendererCaps = getRendererCaps(); -#if defined(ANGLE_ENABLE_D3D11_1) - if (getDeviceContext1IfSupported()) - { - D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; - mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); - mSupportsConstantBufferOffsets = (d3d11Options.ConstantBufferOffsetting != FALSE); - } -#endif + mStateManager.initialize(rendererCaps); mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); @@ -613,19 +841,94 @@ void Renderer11::initializeDevice() mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); - mCurVertexSRVs.resize(rendererCaps.maxVertexTextureImageUnits); - mCurPixelSRVs.resize(rendererCaps.maxTextureImageUnits); + mStateManager.initialize(rendererCaps); markAllStateDirty(); + + // Gather stats on DXGI and D3D feature level + ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2); + + ANGLEFeatureLevel angleFeatureLevel = GetANGLEFeatureLevel(mRenderer11DeviceCaps.featureLevel); + + // We don't actually request a 11_1 device, because of complications with the platform + // update. Instead we check if the mDeviceContext1 pointer cast succeeded. + // Note: we should support D3D11_0 always, but we aren't guaranteed to be at FL11_0 + // because the app can specify a lower version (such as 9_3) on Display creation. + if (mDeviceContext1 != nullptr) + { + angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1; + } + + ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", + angleFeatureLevel, + NUM_ANGLE_FEATURE_LEVELS); + + // TODO(jmadill): use context caps, and place in common D3D location + mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes); +} + +void Renderer11::populateRenderer11DeviceCaps() +{ + HRESULT hr = S_OK; + +#if defined(ANGLE_ENABLE_D3D11_1) + if (mDeviceContext1) + { + D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; + HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + if (SUCCEEDED(result)) + { + mRenderer11DeviceCaps.supportsClearView = (d3d11Options.ClearView != FALSE); + mRenderer11DeviceCaps.supportsConstantBufferOffsets = (d3d11Options.ConstantBufferOffsetting != FALSE); + } + } +#endif + + hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G6R5_UNORM, &(mRenderer11DeviceCaps.B5G6R5support)); + if (FAILED(hr)) + { + mRenderer11DeviceCaps.B5G6R5support = 0; + } + + hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B4G4R4A4_UNORM, &(mRenderer11DeviceCaps.B4G4R4A4support)); + if (FAILED(hr)) + { + mRenderer11DeviceCaps.B4G4R4A4support = 0; + } + + hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G5R5A1_UNORM, &(mRenderer11DeviceCaps.B5G5R5A1support)); + if (FAILED(hr)) + { + mRenderer11DeviceCaps.B5G5R5A1support = 0; + } + +#if defined(ANGLE_ENABLE_D3D11_1) + IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject(mDxgiAdapter); + mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr); + SafeRelease(dxgiAdapter2); +#endif } egl::ConfigSet Renderer11::generateConfigs() const { - static const GLenum colorBufferFormats[] = + std::vector colorBufferFormats; + + // 32-bit supported formats + colorBufferFormats.push_back(GL_BGRA8_EXT); + colorBufferFormats.push_back(GL_RGBA8_OES); + + // 24-bit supported formats + colorBufferFormats.push_back(GL_RGB8_OES); + + if (!mPresentPathFastEnabled) { - GL_BGRA8_EXT, - GL_RGBA8_OES, - }; + // 16-bit supported formats + // These aren't valid D3D11 swapchain formats, so don't expose them as configs + // if present path fast is active + colorBufferFormats.push_back(GL_RGBA4); + colorBufferFormats.push_back(GL_RGB5_A1); + colorBufferFormats.push_back(GL_RGB565); + } static const GLenum depthStencilBufferFormats[] = { @@ -637,64 +940,87 @@ egl::ConfigSet Renderer11::generateConfigs() const const gl::Caps &rendererCaps = getRendererCaps(); const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps(); + const EGLint optimalSurfaceOrientation = + mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE; + egl::ConfigSet configs; - for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++) + for (GLenum colorBufferInternalFormat : colorBufferFormats) { - GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex]; const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat); - if (colorBufferFormatCaps.renderable) + if (!colorBufferFormatCaps.renderable) + { + continue; + } + + for (GLenum depthStencilBufferInternalFormat : depthStencilBufferFormats) { - for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++) + const gl::TextureCaps &depthStencilBufferFormatCaps = + rendererTextureCaps.get(depthStencilBufferInternalFormat); + if (!depthStencilBufferFormatCaps.renderable && + depthStencilBufferInternalFormat != GL_NONE) { - GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex]; - const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat); - if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE) - { - const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat); - const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(depthStencilBufferInternalFormat); - - egl::Config config; - config.renderTargetFormat = colorBufferInternalFormat; - config.depthStencilFormat = depthStencilBufferInternalFormat; - config.bufferSize = colorBufferFormatInfo.pixelBytes * 8; - config.redSize = colorBufferFormatInfo.redBits; - config.greenSize = colorBufferFormatInfo.greenBits; - config.blueSize = colorBufferFormatInfo.blueBits; - config.luminanceSize = colorBufferFormatInfo.luminanceBits; - config.alphaSize = colorBufferFormatInfo.alphaBits; - config.alphaMaskSize = 0; - config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB); - config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT); - config.colorBufferType = EGL_RGB_BUFFER; - config.configID = static_cast(configs.size() + 1); - // Can only support a conformant ES2 with feature level greater than 10.0. - config.conformant = (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR) : EGL_NONE; - config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE; - config.depthSize = depthStencilBufferFormatInfo.depthBits; - config.level = 0; - config.matchNativePixmap = EGL_NONE; - config.maxPBufferWidth = rendererCaps.max2DTextureSize; - config.maxPBufferHeight = rendererCaps.max2DTextureSize; - config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize; - config.maxSwapInterval = 4; - config.minSwapInterval = 0; - config.nativeRenderable = EGL_FALSE; - config.nativeVisualID = 0; - config.nativeVisualType = EGL_NONE; - // Can't support ES3 at all without feature level 10.0 - config.renderableType = EGL_OPENGL_ES2_BIT | ((mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? EGL_OPENGL_ES3_BIT_KHR : 0); - config.sampleBuffers = 0; // FIXME: enumerate multi-sampling - config.samples = 0; - config.stencilSize = depthStencilBufferFormatInfo.stencilBits; - config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; - config.transparentType = EGL_NONE; - config.transparentRedValue = 0; - config.transparentGreenValue = 0; - config.transparentBlueValue = 0; - - configs.add(config); - } + continue; + } + + const gl::InternalFormat &colorBufferFormatInfo = + gl::GetInternalFormatInfo(colorBufferInternalFormat); + const gl::InternalFormat &depthStencilBufferFormatInfo = + gl::GetInternalFormatInfo(depthStencilBufferInternalFormat); + + egl::Config config; + config.renderTargetFormat = colorBufferInternalFormat; + config.depthStencilFormat = depthStencilBufferInternalFormat; + config.bufferSize = colorBufferFormatInfo.pixelBytes * 8; + config.redSize = colorBufferFormatInfo.redBits; + config.greenSize = colorBufferFormatInfo.greenBits; + config.blueSize = colorBufferFormatInfo.blueBits; + config.luminanceSize = colorBufferFormatInfo.luminanceBits; + config.alphaSize = colorBufferFormatInfo.alphaBits; + config.alphaMaskSize = 0; + config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB); + config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || + colorBufferFormatInfo.format == GL_BGRA_EXT); + config.colorBufferType = EGL_RGB_BUFFER; + config.configID = static_cast(configs.size() + 1); + // Can only support a conformant ES2 with feature level greater than 10.0. + config.conformant = (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) + ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR) + : 0; + config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE; + + // PresentPathFast may not be conformant + if (mPresentPathFastEnabled) + { + config.conformant = 0; } + + config.depthSize = depthStencilBufferFormatInfo.depthBits; + config.level = 0; + config.matchNativePixmap = EGL_NONE; + config.maxPBufferWidth = rendererCaps.max2DTextureSize; + config.maxPBufferHeight = rendererCaps.max2DTextureSize; + config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize; + config.maxSwapInterval = 4; + config.minSwapInterval = 0; + config.nativeRenderable = EGL_FALSE; + config.nativeVisualID = 0; + config.nativeVisualType = EGL_NONE; + // Can't support ES3 at all without feature level 10.0 + config.renderableType = + EGL_OPENGL_ES2_BIT | ((mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) + ? EGL_OPENGL_ES3_BIT_KHR + : 0); + config.sampleBuffers = 0; // FIXME: enumerate multi-sampling + config.samples = 0; + config.stencilSize = depthStencilBufferFormatInfo.stencilBits; + config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + config.transparentType = EGL_NONE; + config.transparentRedValue = 0; + config.transparentGreenValue = 0; + config.transparentBlueValue = 0; + config.optimalOrientation = optimalSurfaceOrientation; + + configs.add(config); } } @@ -702,6 +1028,42 @@ egl::ConfigSet Renderer11::generateConfigs() const return configs; } +void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const +{ + outExtensions->createContextRobustness = true; + + if (getShareHandleSupport()) + { + outExtensions->d3dShareHandleClientBuffer = true; + outExtensions->surfaceD3DTexture2DShareHandle = true; + } + + outExtensions->keyedMutex = true; + outExtensions->querySurfacePointer = true; + outExtensions->windowFixedSize = true; + + // If present path fast is active then the surface orientation extension isn't supported + outExtensions->surfaceOrientation = !mPresentPathFastEnabled; + + // D3D11 does not support present with dirty rectangles until DXGI 1.2. + outExtensions->postSubBuffer = mRenderer11DeviceCaps.supportsDXGI1_2; + + outExtensions->createContext = true; + + outExtensions->deviceQuery = true; + + outExtensions->createContextNoError = true; + + outExtensions->image = true; + outExtensions->imageBase = true; + outExtensions->glTexture2DImage = true; + outExtensions->glTextureCubemapImage = true; + outExtensions->glRenderbufferImage = true; + + outExtensions->flexibleSurfaceCompatibility = true; + outExtensions->directComposition = !!mDCompModule; +} + gl::Error Renderer11::flush() { mDeviceContext->Flush(); @@ -748,12 +1110,34 @@ gl::Error Renderer11::finish() } while (result == S_FALSE); - return gl::Error(GL_NO_ERROR); + return gl::Error(GL_NO_ERROR); +} + +SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) +{ + return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat, + orientation); +} + +CompilerImpl *Renderer11::createCompiler() +{ + if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT); + } + else + { + return new CompilerD3D(SH_HLSL_4_1_OUTPUT); + } } -SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +void *Renderer11::getD3DDevice() { - return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); + return reinterpret_cast(mDevice); } gl::Error Renderer11::generateSwizzle(gl::Texture *texture) @@ -772,11 +1156,11 @@ gl::Error Renderer11::generateSwizzle(gl::Texture *texture) if (texStorage) { - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); - error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed, - texture->getSamplerState().swizzleGreen, - texture->getSamplerState().swizzleBlue, - texture->getSamplerState().swizzleAlpha); + TextureStorage11 *storage11 = GetAs(texStorage); + const gl::TextureState &textureState = texture->getTextureState(); + error = + storage11->generateSwizzles(textureState.swizzleRed, textureState.swizzleGreen, + textureState.swizzleBlue, textureState.swizzleAlpha); if (error.isError()) { return error; @@ -787,11 +1171,13 @@ gl::Error Renderer11::generateSwizzle(gl::Texture *texture) return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerStateParam) +gl::Error Renderer11::setSamplerState(gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &samplerState) { // Make sure to add the level offset for our tiny compressed texture workaround TextureD3D *textureD3D = GetImplAs(texture); - gl::SamplerState samplerStateInternal = samplerStateParam; TextureStorage *storage = nullptr; gl::Error error = textureD3D->getNativeTexture(&storage); @@ -803,16 +1189,15 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Textu // Storage should exist, texture should be complete ASSERT(storage); - samplerStateInternal.baseLevel += storage->getTopLevel(); - if (type == gl::SAMPLER_PIXEL) { ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); - if (mForceSetPixelSamplerStates[index] || memcmp(&samplerStateInternal, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) + if (mForceSetPixelSamplerStates[index] || + memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) { ID3D11SamplerState *dxSamplerState = NULL; - error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); + error = mStateCache.getSamplerState(samplerState, &dxSamplerState); if (error.isError()) { return error; @@ -821,7 +1206,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Textu ASSERT(dxSamplerState != NULL); mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); - mCurPixelSamplerStates[index] = samplerStateInternal; + mCurPixelSamplerStates[index] = samplerState; } mForceSetPixelSamplerStates[index] = false; @@ -830,10 +1215,11 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Textu { ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); - if (mForceSetVertexSamplerStates[index] || memcmp(&samplerStateInternal, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) + if (mForceSetVertexSamplerStates[index] || + memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) { ID3D11SamplerState *dxSamplerState = NULL; - error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState); + error = mStateCache.getSamplerState(samplerState, &dxSamplerState); if (error.isError()) { return error; @@ -842,7 +1228,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Textu ASSERT(dxSamplerState != NULL); mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); - mCurVertexSamplerStates[index] = samplerStateInternal; + mCurVertexSamplerStates[index] = samplerState; } mForceSetVertexSamplerStates[index] = false; @@ -870,13 +1256,13 @@ gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *t // Texture should be complete and have a storage ASSERT(texStorage); - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); + TextureStorage11 *storage11 = GetAs(texStorage); // Make sure to add the level offset for our tiny compressed texture workaround - gl::SamplerState samplerState = texture->getSamplerState(); - samplerState.baseLevel += storage11->getTopLevel(); + gl::TextureState textureState = texture->getTextureState(); + textureState.baseLevel += storage11->getTopLevel(); - error = storage11->getSRV(samplerState, &textureSRV); + error = storage11->getSRV(textureState, &textureSRV); if (error.isError()) { return error; @@ -892,16 +1278,16 @@ gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *t ASSERT((type == gl::SAMPLER_PIXEL && static_cast(index) < getRendererCaps().maxTextureImageUnits) || (type == gl::SAMPLER_VERTEX && static_cast(index) < getRendererCaps().maxVertexTextureImageUnits)); - setShaderResource(type, index, textureSRV); + mStateManager.setShaderResource(type, index, textureSRV); return gl::Error(GL_NO_ERROR); } gl::Error Renderer11::setUniformBuffers(const gl::Data &data, - const GLint vertexUniformBuffers[], - const GLint fragmentUniformBuffers[]) + const std::vector &vertexUniformBuffers, + const std::vector &fragmentUniformBuffers) { - for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < data.caps->maxVertexUniformBlocks; uniformBufferIndex++) + for (size_t uniformBufferIndex = 0; uniformBufferIndex < vertexUniformBuffers.size(); uniformBufferIndex++) { GLint binding = vertexUniformBuffers[uniformBufferIndex]; @@ -910,14 +1296,24 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, continue; } - gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding); - GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding); - GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding); + const OffsetBindingPointer &uniformBuffer = + data.state->getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = uniformBuffer.getOffset(); + GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); - if (uniformBuffer) + if (uniformBuffer.get() != nullptr) { - Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); - ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + Buffer11 *bufferStorage = GetImplAs(uniformBuffer.get()); + ID3D11Buffer *constantBuffer; + + if (mRenderer11DeviceCaps.supportsConstantBufferOffsets) + { + constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + } + else + { + constantBuffer = bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize); + } if (!constantBuffer) { @@ -929,19 +1325,22 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize) { #if defined(ANGLE_ENABLE_D3D11_1) - if (mSupportsConstantBufferOffsets && uniformBufferSize != 0) + if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0) { UINT firstConstant = 0, numConstants = 0; CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); - mDeviceContext1->VSSetConstantBuffers1(getReservedVertexUniformBuffers() + uniformBufferIndex, - 1, &constantBuffer, &firstConstant, &numConstants); + mDeviceContext1->VSSetConstantBuffers1( + getReservedVertexUniformBuffers() + + static_cast(uniformBufferIndex), + 1, &constantBuffer, &firstConstant, &numConstants); } else #endif { - ASSERT(uniformBufferOffset == 0); - mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex, - 1, &constantBuffer); + mDeviceContext->VSSetConstantBuffers( + getReservedVertexUniformBuffers() + + static_cast(uniformBufferIndex), + 1, &constantBuffer); } mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); @@ -951,7 +1350,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, } } - for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < data.caps->maxFragmentUniformBlocks; uniformBufferIndex++) + for (size_t uniformBufferIndex = 0; uniformBufferIndex < fragmentUniformBuffers.size(); uniformBufferIndex++) { GLint binding = fragmentUniformBuffers[uniformBufferIndex]; @@ -960,14 +1359,24 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, continue; } - gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding); - GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding); - GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding); + const OffsetBindingPointer &uniformBuffer = + data.state->getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = uniformBuffer.getOffset(); + GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); - if (uniformBuffer) + if (uniformBuffer.get() != nullptr) { - Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); - ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + Buffer11 *bufferStorage = GetImplAs(uniformBuffer.get()); + ID3D11Buffer *constantBuffer; + + if (mRenderer11DeviceCaps.supportsConstantBufferOffsets) + { + constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + } + else + { + constantBuffer = bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize); + } if (!constantBuffer) { @@ -979,19 +1388,22 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize) { #if defined(ANGLE_ENABLE_D3D11_1) - if (mSupportsConstantBufferOffsets && uniformBufferSize != 0) + if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0) { UINT firstConstant = 0, numConstants = 0; CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); - mDeviceContext1->PSSetConstantBuffers1(getReservedFragmentUniformBuffers() + uniformBufferIndex, - 1, &constantBuffer, &firstConstant, &numConstants); + mDeviceContext1->PSSetConstantBuffers1( + getReservedFragmentUniformBuffers() + + static_cast(uniformBufferIndex), + 1, &constantBuffer, &firstConstant, &numConstants); } else #endif { - ASSERT(uniformBufferOffset == 0); - mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex, - 1, &constantBuffer); + mDeviceContext->PSSetConstantBuffers( + getReservedFragmentUniformBuffers() + + static_cast(uniformBufferIndex), + 1, &constantBuffer); } mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); @@ -1004,229 +1416,60 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data, return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) +gl::Error Renderer11::updateState(const gl::Data &data, GLenum drawMode) { - if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) + // Applies the render target surface, depth stencil surface, viewport rectangle and + // scissor rectangle to the renderer + const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); + ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE); + gl::Error error = applyRenderTarget(framebufferObject); + if (error.isError()) { - ID3D11RasterizerState *dxRasterState = NULL; - gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState); - if (error.isError()) - { - return error; - } - - mDeviceContext->RSSetState(dxRasterState); - - mCurRasterState = rasterState; + return error; } - mForceSetRasterState = false; - - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) -{ - if (mForceSetBlendState || - memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || - memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0 || - sampleMask != mCurSampleMask) - { - ID3D11BlendState *dxBlendState = NULL; - gl::Error error = mStateCache.getBlendState(framebuffer, blendState, &dxBlendState); - if (error.isError()) - { - return error; - } - - ASSERT(dxBlendState != NULL); + // Set the present path state + const bool presentPathFastActive = + UsePresentPathFast(this, framebufferObject->getFirstColorbuffer()); + mStateManager.updatePresentPath(presentPathFastActive, + framebufferObject->getFirstColorbuffer()); - float blendColors[4] = {0.0f}; - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - blendColors[0] = blendColor.red; - blendColors[1] = blendColor.green; - blendColors[2] = blendColor.blue; - blendColors[3] = blendColor.alpha; - } - else - { - blendColors[0] = blendColor.alpha; - blendColors[1] = blendColor.alpha; - blendColors[2] = blendColor.alpha; - blendColors[3] = blendColor.alpha; - } - - mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); - - mCurBlendState = blendState; - mCurBlendColor = blendColor; - mCurSampleMask = sampleMask; - } + // Setting viewport state + mStateManager.setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(), + data.state->getFarPlane()); - mForceSetBlendState = false; + // Setting scissor state + mStateManager.setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); - return gl::Error(GL_NO_ERROR); -} + // Applying rasterizer state to D3D11 device + int samples = framebufferObject->getSamples(data); + gl::RasterizerState rasterizer = data.state->getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); -gl::Error Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) -{ - if (mForceSetDepthStencilState || - memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || - stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) + error = mStateManager.setRasterizerState(rasterizer); + if (error.isError()) { - ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); - ASSERT(stencilRef == stencilBackRef); - ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); - - ID3D11DepthStencilState *dxDepthStencilState = NULL; - gl::Error error = mStateCache.getDepthStencilState(depthStencilState, &dxDepthStencilState); - if (error.isError()) - { - return error; - } - - ASSERT(dxDepthStencilState); - - // Max D3D11 stencil reference value is 0xFF, corresponding to the max 8 bits in a stencil buffer - // GL specifies we should clamp the ref value to the nearest bit depth when doing stencil ops - static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK"); - static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK"); - UINT dxStencilRef = std::min(stencilRef, 0xFFu); - - mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); - - mCurDepthStencilState = depthStencilState; - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; + return error; } - mForceSetDepthStencilState = false; - - return gl::Error(GL_NO_ERROR); -} - -void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) -{ - if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || - enabled != mScissorEnabled) + // Setting blend state + unsigned int mask = GetBlendSampleMask(data, samples); + error = mStateManager.setBlendState(framebufferObject, data.state->getBlendState(), + data.state->getBlendColor(), mask); + if (error.isError()) { - if (enabled) - { - D3D11_RECT rect; - rect.left = std::max(0, scissor.x); - rect.top = std::max(0, scissor.y); - rect.right = scissor.x + std::max(0, scissor.width); - rect.bottom = scissor.y + std::max(0, scissor.height); - - mDeviceContext->RSSetScissorRects(1, &rect); - } - - if (enabled != mScissorEnabled) - { - mForceSetRasterState = true; - } - - mCurScissor = scissor; - mScissorEnabled = enabled; + return error; } - mForceSetScissor = false; + // Setting depth stencil state + error = mStateManager.setDepthStencilState(*data.state); + return error; } -void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) +void Renderer11::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) { - gl::Rectangle actualViewport = viewport; - float actualZNear = gl::clamp01(zNear); - float actualZFar = gl::clamp01(zFar); - if (ignoreViewport) - { - actualViewport.x = 0; - actualViewport.y = 0; - actualViewport.width = mRenderTargetDesc.width; - actualViewport.height = mRenderTargetDesc.height; - actualZNear = 0.0f; - actualZFar = 1.0f; - } - - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar; - - if (viewportChanged) - { - const gl::Caps& caps = getRendererCaps(); - - int dxMaxViewportBoundsX = static_cast(caps.maxViewportWidth); - int dxMaxViewportBoundsY = static_cast(caps.maxViewportHeight); - int dxMinViewportBoundsX = -dxMaxViewportBoundsX; - int dxMinViewportBoundsY = -dxMaxViewportBoundsY; - - if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3) - { - // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. - dxMaxViewportBoundsX = mRenderTargetDesc.width; - dxMaxViewportBoundsY = mRenderTargetDesc.height; - dxMinViewportBoundsX = 0; - dxMinViewportBoundsY = 0; - } - - int dxViewportTopLeftX = gl::clamp(actualViewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX); - int dxViewportTopLeftY = gl::clamp(actualViewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY); - int dxViewportWidth = gl::clamp(actualViewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); - int dxViewportHeight = gl::clamp(actualViewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); - - D3D11_VIEWPORT dxViewport; - dxViewport.TopLeftX = static_cast(dxViewportTopLeftX); - dxViewport.TopLeftY = static_cast(dxViewportTopLeftY); - dxViewport.Width = static_cast(dxViewportWidth); - dxViewport.Height = static_cast(dxViewportHeight); - dxViewport.MinDepth = actualZNear; - dxViewport.MaxDepth = actualZFar; - - mDeviceContext->RSSetViewports(1, &dxViewport); - - mCurViewport = actualViewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - - // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders using viewAdjust (like the D3D9 renderer). - if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3) - { - mVertexConstants.viewAdjust[0] = static_cast((actualViewport.width - dxViewportWidth) + 2 * (actualViewport.x - dxViewportTopLeftX)) / dxViewport.Width; - mVertexConstants.viewAdjust[1] = static_cast((actualViewport.height - dxViewportHeight) + 2 * (actualViewport.y - dxViewportTopLeftY)) / dxViewport.Height; - mVertexConstants.viewAdjust[2] = static_cast(actualViewport.width) / dxViewport.Width; - mVertexConstants.viewAdjust[3] = static_cast(actualViewport.height) / dxViewport.Height; - } - - mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; - mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; - mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); - mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); - - // Instanced pointsprite emulation requires ViewCoords to be defined in the - // the vertex shader. - mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0]; - mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1]; - mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2]; - mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3]; - - mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - - mVertexConstants.depthRange[0] = actualZNear; - mVertexConstants.depthRange[1] = actualZFar; - mVertexConstants.depthRange[2] = actualZFar - actualZNear; - - mPixelConstants.depthRange[0] = actualZNear; - mPixelConstants.depthRange[1] = actualZFar; - mPixelConstants.depthRange[2] = actualZFar - actualZNear; - } - - mForceSetViewport = false; + mStateManager.syncState(state, bitmask); } bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) @@ -1267,176 +1510,51 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSi return count >= minCount; } -void Renderer11::unsetConflictingSRVs(gl::SamplerType samplerType, uintptr_t resource, const gl::ImageIndex *index) +gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) { - auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); - - for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) - { - auto &record = currentSRVs[resourceIndex]; - - if (record.srv && record.resource == resource && ImageIndexConflictsWithSRV(index, record.desc)) - { - setShaderResource(samplerType, static_cast(resourceIndex), NULL); - } - } + return mStateManager.syncFramebuffer(framebuffer); } -gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) +gl::Error Renderer11::applyVertexBuffer(const gl::State &state, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData *indexInfo) { - // Get the color render buffer and serial - // Also extract the render target dimensions and view - unsigned int renderTargetWidth = 0; - unsigned int renderTargetHeight = 0; - DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN; - ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; - bool missingColorRenderTarget = true; - - const FramebufferD3D *framebufferD3D = GetImplAs(framebuffer); - const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(getWorkarounds()); - - for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) - { - gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; - - if (colorbuffer) - { - // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) - - // check for zero-sized default framebuffer, which is a special case. - // in this case we do not wish to modify any state and just silently return false. - // this will not report any gl error but will cause the calling method to return. - if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) - { - return gl::Error(GL_NO_ERROR); - } - - // Extract the render target dimensions and view - RenderTarget11 *renderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget); - - framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); - ASSERT(framebufferRTVs[colorAttachment]); - - if (missingColorRenderTarget) - { - renderTargetWidth = renderTarget->getWidth(); - renderTargetHeight = renderTarget->getHeight(); - renderTargetFormat = renderTarget->getDXGIFormat(); - missingColorRenderTarget = false; - } - - // Unbind render target SRVs from the shader here to prevent D3D11 warnings. - if (colorbuffer->type() == GL_TEXTURE) - { - uintptr_t rtResource = reinterpret_cast(GetViewResource(framebufferRTVs[colorAttachment])); - const gl::ImageIndex *index = colorbuffer->getTextureImageIndex(); - ASSERT(index); - // The index doesn't need to be corrected for the small compressed texture workaround - // because a rendertarget is never compressed. - unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index); - unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index); - } - } - } - - // Get the depth stencil buffers - ID3D11DepthStencilView* framebufferDSV = NULL; - gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer(); - if (depthStencil) - { - RenderTarget11 *depthStencilRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget); - if (error.isError()) - { - SafeRelease(framebufferRTVs); - return error; - } - ASSERT(depthStencilRenderTarget); - - framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); - ASSERT(framebufferDSV); - - // If there is no render buffer, the width, height and format values come from - // the depth stencil - if (missingColorRenderTarget) - { - renderTargetWidth = depthStencilRenderTarget->getWidth(); - renderTargetHeight = depthStencilRenderTarget->getHeight(); - renderTargetFormat = depthStencilRenderTarget->getDXGIFormat(); - } - - // Unbind render target SRVs from the shader here to prevent D3D11 warnings. - if (depthStencil->type() == GL_TEXTURE) - { - uintptr_t depthStencilResource = reinterpret_cast(GetViewResource(framebufferDSV)); - const gl::ImageIndex *index = depthStencil->getTextureImageIndex(); - ASSERT(index); - // The index doesn't need to be corrected for the small compressed texture workaround - // because a rendertarget is never compressed. - unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index); - unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index); - } - } - - // Apply the render target and depth stencil - if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || - memcmp(framebufferRTVs, mAppliedRTVs, sizeof(framebufferRTVs)) != 0 || - reinterpret_cast(framebufferDSV) != mAppliedDSV) - { - mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV); - - mRenderTargetDesc.width = renderTargetWidth; - mRenderTargetDesc.height = renderTargetHeight; - mRenderTargetDesc.format = renderTargetFormat; - mForceSetViewport = true; - mForceSetScissor = true; - mForceSetBlendState = true; - - if (!mDepthStencilInitialized) - { - mForceSetRasterState = true; - } - - for (size_t rtIndex = 0; rtIndex < ArraySize(framebufferRTVs); rtIndex++) - { - mAppliedRTVs[rtIndex] = reinterpret_cast(framebufferRTVs[rtIndex]); - } - mAppliedDSV = reinterpret_cast(framebufferDSV); - mRenderTargetDescInitialized = true; - mDepthStencilInitialized = true; - } - - const Framebuffer11 *framebuffer11 = GetImplAs(framebuffer); - gl::Error error = framebuffer11->invalidateSwizzles(); + gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances); if (error.isError()) { return error; } - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) -{ - TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); - if (error.isError()) + // If index information is passed, mark it with the current changed status. + if (indexInfo) { - return error; + indexInfo->srcIndexData.srcIndicesChanged = mAppliedIBChanged; } - return mInputLayoutCache.applyVertexBuffers(attributes, mode, state.getProgram()); + GLsizei numIndicesPerInstance = 0; + if (instances > 0) + { + numIndicesPerInstance = count; + } + return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(), + indexInfo, numIndicesPerInstance); } -gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +gl::Error Renderer11::applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo) { - gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + gl::Error error = + mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo, + data.state->isPrimitiveRestartEnabled()); if (error.isError()) { return error; @@ -1447,15 +1565,16 @@ gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elemen if (indexInfo->storage) { - Buffer11 *storage = Buffer11::makeBuffer11(indexInfo->storage); + Buffer11 *storage = GetAs(indexInfo->storage); buffer = storage->getBuffer(BUFFER_USAGE_INDEX); } else { - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + IndexBuffer11* indexBuffer = GetAs(indexInfo->indexBuffer); buffer = indexBuffer->getBuffer(); } + mAppliedIBChanged = false; if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset) { mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); @@ -1463,6 +1582,7 @@ gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elemen mAppliedIB = buffer; mAppliedIBFormat = bufferFormat; mAppliedIBOffset = indexInfo->startOffset; + mAppliedIBChanged = true; } return gl::Error(GL_NO_ERROR); @@ -1475,22 +1595,23 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) if (state.isTransformFeedbackActiveUnpaused()) { - numXFBBindings = state.getTransformFeedbackBufferIndexRange(); + const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); + numXFBBindings = transformFeedback->getIndexedBufferCount(); ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); for (size_t i = 0; i < numXFBBindings; i++) { - gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); - GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); + const OffsetBindingPointer &binding = transformFeedback->getIndexedBuffer(i); + ID3D11Buffer *d3dBuffer = NULL; - if (curXFBBuffer) + if (binding.get() != nullptr) { - Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); + Buffer11 *storage = GetImplAs(binding.get()); d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); } // TODO: mAppliedTFBuffers and friends should also be kept in a vector. - if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i]) + if (d3dBuffer != mAppliedTFBuffers[i] || binding.getOffset() != mAppliedTFOffsets[i]) { requiresUpdate = true; } @@ -1499,18 +1620,17 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings) { + const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); for (size_t i = 0; i < numXFBBindings; ++i) { - gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i); - GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i); - - if (curXFBBuffer) + const OffsetBindingPointer &binding = transformFeedback->getIndexedBuffer(i); + if (binding.get() != nullptr) { - Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation()); + Buffer11 *storage = GetImplAs(binding.get()); ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != curXFBOffset) ? - static_cast(curXFBOffset) : -1; + mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != binding.getOffset()) ? + static_cast(binding.getOffset()) : -1; mAppliedTFBuffers[i] = d3dBuffer; } else @@ -1518,26 +1638,30 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) mAppliedTFBuffers[i] = NULL; mCurrentD3DOffsets[i] = 0; } - mAppliedTFOffsets[i] = curXFBOffset; + mAppliedTFOffsets[i] = binding.getOffset(); } mAppliedNumXFBBindings = numXFBBindings; - mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets); + mDeviceContext->SOSetTargets(static_cast(numXFBBindings), mAppliedTFBuffers, + mCurrentD3DOffsets); } } -gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) +gl::Error Renderer11::drawArraysImpl(const gl::Data &data, + GLenum mode, + GLsizei count, + GLsizei instances) { - bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation; - if (mode == GL_POINTS && data.state->isTransformFeedbackActiveUnpaused()) - { - // Since point sprites are generated with a geometry shader, too many vertices will - // be written if transform feedback is active. To work around this, draw only the points - // with the stream out shader and no pixel shader to feed the stream out buffers and then - // draw again with the point sprite geometry shader to rasterize the point sprites. + ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); - mDeviceContext->PSSetShader(NULL, NULL, 0); + if (programD3D->usesGeometryShader(mode) && data.state->isTransformFeedbackActiveUnpaused()) + { + // Since we use a geometry if-and-only-if we rewrite vertex streams, transform feedback + // won't get the correct output. To work around this, draw with *only* the stream out + // first (no pixel shader) to feed the stream out buffers and then draw again with the + // geometry shader + pixel shader to rasterize the primitives. + mDeviceContext->PSSetShader(nullptr, nullptr, 0); if (instances > 0) { @@ -1548,98 +1672,192 @@ gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei coun mDeviceContext->Draw(count, 0); } - ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); - - rx::ShaderExecutableD3D *pixelExe = NULL; + rx::ShaderExecutableD3D *pixelExe = nullptr; gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe); if (error.isError()) { return error; } - // Skip this step if we're doing rasterizer discard. - if (pixelExe && !data.state->getRasterizerState().rasterizerDiscard && usesPointSize) + // Skip the draw call if rasterizer discard is enabled (or no fragment shader). + if (!pixelExe || data.state->getRasterizerState().rasterizerDiscard) { - ID3D11PixelShader *pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); - ASSERT(reinterpret_cast(pixelShader) == mAppliedPixelShader); - mDeviceContext->PSSetShader(pixelShader, NULL, 0); + return gl::Error(GL_NO_ERROR); + } - // Retrieve the point sprite geometry shader - rx::ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable(); - ID3D11GeometryShader *geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL); - mAppliedGeometryShader = reinterpret_cast(geometryShader); - ASSERT(geometryShader); - mDeviceContext->GSSetShader(geometryShader, NULL, 0); + ID3D11PixelShader *pixelShader = GetAs(pixelExe)->getPixelShader(); + ASSERT(reinterpret_cast(pixelShader) == mAppliedPixelShader); + mDeviceContext->PSSetShader(pixelShader, NULL, 0); - if (instances > 0) - { - mDeviceContext->DrawInstanced(count, instances, 0, 0); - } - else - { - mDeviceContext->Draw(count, 0); - } + // Retrieve the geometry shader. + rx::ShaderExecutableD3D *geometryExe = nullptr; + error = + programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr); + if (error.isError()) + { + return error; } + ID3D11GeometryShader *geometryShader = + (geometryExe ? GetAs(geometryExe)->getGeometryShader() : NULL); + mAppliedGeometryShader = reinterpret_cast(geometryShader); + ASSERT(geometryShader); + mDeviceContext->GSSetShader(geometryShader, NULL, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } return gl::Error(GL_NO_ERROR); } - else if (mode == GL_LINE_LOOP) - { - return drawLineLoop(count, GL_NONE, NULL, 0, NULL); - } - else if (mode == GL_TRIANGLE_FAN) + + if (mode == GL_LINE_LOOP) { - return drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); + return drawLineLoop(data, count, GL_NONE, nullptr, nullptr, instances); } - else if (instances > 0) + + if (mode == GL_TRIANGLE_FAN) { - mDeviceContext->DrawInstanced(count, instances, 0, 0); - return gl::Error(GL_NO_ERROR); + return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances); } - else + + bool useInstancedPointSpriteEmulation = + programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation; + + if (instances > 0) { - // If gl_PointSize is used and GL_POINTS is specified, then it is expected to render pointsprites. - // If instanced pointsprite emulation is being used the topology is expexted to be - // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced must be used. if (mode == GL_POINTS && useInstancedPointSpriteEmulation) { - mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + // If pointsprite emulation is used with glDrawArraysInstanced then we need to take a + // less efficent code path. + // Instanced rendering of emulated pointsprites requires a loop to draw each batch of + // points. An offset into the instanced data buffer is calculated and applied on each + // iteration to ensure all instances are rendered correctly. + + // Each instance being rendered requires the inputlayout cache to reapply buffers and + // offsets. + for (GLsizei i = 0; i < instances; i++) + { + gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i); + if (error.isError()) + { + return error; + } + + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } } else { - mDeviceContext->Draw(count, 0); + mDeviceContext->DrawInstanced(count, instances, 0, 0); } return gl::Error(GL_NO_ERROR); } + + // If the shader is writing to gl_PointSize, then pointsprites are being rendered. + // Emulating instanced point sprites for FL9_3 requires the topology to be + // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. + if (mode == GL_POINTS && useInstancedPointSpriteEmulation) + { + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) +gl::Error Renderer11::drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances) { int minIndex = static_cast(indexInfo.indexRange.start); if (mode == GL_LINE_LOOP) { - return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); + return drawLineLoop(data, count, type, indices, &indexInfo, instances); } - else if (mode == GL_TRIANGLE_FAN) + + if (mode == GL_TRIANGLE_FAN) { - return drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances); + return drawTriangleFan(data, count, type, indices, minIndex, instances); } - else if (instances > 0) + + const ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); + if (instances > 0) { - mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); + if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation()) + { + // If pointsprite emulation is used with glDrawElementsInstanced then we need to take a + // less efficent code path. + // Instanced rendering of emulated pointsprites requires a loop to draw each batch of + // points. An offset into the instanced data buffer is calculated and applied on each + // iteration to ensure all instances are rendered correctly. + GLsizei elementsToRender = static_cast(indexInfo.indexRange.vertexCount()); + + // Each instance being rendered requires the inputlayout cache to reapply buffers and + // offsets. + for (GLsizei i = 0; i < instances; i++) + { + gl::Error error = mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation(i); + if (error.isError()) + { + return error; + } + + mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0); + } + } + else + { + mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); + } return gl::Error(GL_NO_ERROR); } + + // If the shader is writing to gl_PointSize, then pointsprites are being rendered. + // Emulating instanced point sprites for FL9_3 requires the topology to be + // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced is called instead. + if (mode == GL_POINTS && programD3D->usesInstancedPointSpriteEmulation()) + { + // The count parameter passed to drawElements represents the total number of instances + // to be rendered. Each instance is referenced by the bound index buffer from the + // the caller. + // + // Indexed pointsprite emulation replicates data for duplicate entries found + // in the index buffer. + // This is not an efficent rendering mechanism and is only used on downlevel renderers + // that do not support geometry shaders. + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + } else { mDeviceContext->DrawIndexed(count, 0, -minIndex); - return gl::Error(GL_NO_ERROR); } + return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +gl::Error Renderer11::drawLineLoop(const gl::Data &data, + GLsizei count, + GLenum type, + const GLvoid *indexPointer, + const TranslatedIndexData *indexInfo, + int instances) { + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + + const GLvoid *indices = indexPointer; + // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { @@ -1675,7 +1893,11 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); } - const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); + GetLineLoopIndices(indices, type, static_cast(count), + data.state->isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer); + + unsigned int spaceNeeded = + static_cast(sizeof(GLuint) * mScratchIndexDataBuffer.size()); gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); if (error.isError()) { @@ -1684,73 +1906,62 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind void* mappedMemory = NULL; unsigned int offset; - error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); - if (error.isError()) - { - return error; - } - - unsigned int *data = reinterpret_cast(mappedMemory); - unsigned int indexBufferOffset = offset; - - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); + error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) + { + return error; } + // Copy over the converted index data. + memcpy(mappedMemory, &mScratchIndexDataBuffer[0], + sizeof(GLuint) * mScratchIndexDataBuffer.size()); + error = mLineLoopIB->unmapBuffer(); if (error.isError()) { return error; } - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); + IndexBuffer11 *indexBuffer = GetAs(mLineLoopIB->getIndexBuffer()); ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); - if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || + mAppliedIBOffset != offset) { - mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset); mAppliedIB = d3dIndexBuffer; mAppliedIBFormat = indexFormat; - mAppliedIBOffset = indexBufferOffset; + mAppliedIBOffset = offset; } - mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); + INT baseVertexLocation = (indexInfo ? -static_cast(indexInfo->indexRange.start) : 0); + UINT indexCount = static_cast(mScratchIndexDataBuffer.size()); + + if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertexLocation, 0); + } + else + { + mDeviceContext->DrawIndexed(indexCount, 0, baseVertexLocation); + } return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) +gl::Error Renderer11::drawTriangleFan(const gl::Data &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + int minIndex, + int instances) { + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + + const GLvoid *indexPointer = indices; + // Get the raw indices for an indexed draw if (type != GL_NONE && elementArrayBuffer) { @@ -1764,7 +1975,7 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * return error; } - indices = bufferData + offset; + indexPointer = bufferData + offset; } if (!mTriangleFanIB) @@ -1781,21 +1992,25 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * // Checked by Renderer11::applyPrimitiveType ASSERT(count >= 3); - const unsigned int numTris = count - 2; + const GLuint numTris = count - 2; if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); } - const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); + GetTriFanIndices(indexPointer, type, count, data.state->isPrimitiveRestartEnabled(), + &mScratchIndexDataBuffer); + + const unsigned int spaceNeeded = + static_cast(mScratchIndexDataBuffer.size() * sizeof(unsigned int)); gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); if (error.isError()) { return error; } - void* mappedMemory = NULL; + void *mappedMemory = nullptr; unsigned int offset; error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); if (error.isError()) @@ -1803,45 +2018,7 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * return error; } - unsigned int *data = reinterpret_cast(mappedMemory); - unsigned int indexBufferOffset = offset; - - switch (type) - { - case GL_NONE: // Non-indexed draw - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = 0; - data[i*3 + 1] = i + 1; - data[i*3 + 2] = i + 2; - } - break; - case GL_UNSIGNED_BYTE: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_SHORT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_INT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - default: UNREACHABLE(); - } + memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded); error = mTriangleFanIB->unmapBuffer(); if (error.isError()) @@ -1849,34 +2026,37 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid * return error; } - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); + IndexBuffer11 *indexBuffer = GetAs(mTriangleFanIB->getIndexBuffer()); ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); - if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || + mAppliedIBOffset != offset) { - mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset); mAppliedIB = d3dIndexBuffer; mAppliedIBFormat = indexFormat; - mAppliedIBOffset = indexBufferOffset; + mAppliedIBOffset = offset; } + UINT indexCount = static_cast(mScratchIndexDataBuffer.size()); + if (instances > 0) { - mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, -minIndex, 0); } else { - mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); + mDeviceContext->DrawIndexed(indexCount, 0, -minIndex); } return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) +gl::Error Renderer11::applyShadersImpl(const gl::Data &data, GLenum drawMode) { - ProgramD3D *programD3D = GetImplAs(program); + ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); + const auto &inputLayout = programD3D->getCachedInputLayout(); ShaderExecutableD3D *vertexExe = NULL; gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr); @@ -1885,32 +2065,41 @@ gl::Error Renderer11::applyShaders(gl::Program *program, const gl::VertexFormat return error; } + const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); ShaderExecutableD3D *pixelExe = NULL; - error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); + error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe); if (error.isError()) { return error; } - ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable(); + ShaderExecutableD3D *geometryExe = nullptr; + error = + programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr); + if (error.isError()) + { + return error; + } - ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); + ID3D11VertexShader *vertexShader = (vertexExe ? GetAs(vertexExe)->getVertexShader() : NULL); ID3D11PixelShader *pixelShader = NULL; // Skip pixel shader if we're doing rasterizer discard. + bool rasterizerDiscard = data.state->getRasterizerState().rasterizerDiscard; if (!rasterizerDiscard) { - pixelShader = (pixelExe ? ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader() : NULL); + pixelShader = (pixelExe ? GetAs(pixelExe)->getPixelShader() : NULL); } ID3D11GeometryShader *geometryShader = NULL; + bool transformFeedbackActive = data.state->isTransformFeedbackActiveUnpaused(); if (transformFeedbackActive) { - geometryShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getStreamOutShader() : NULL); + geometryShader = (vertexExe ? GetAs(vertexExe)->getStreamOutShader() : NULL); } - else if (mCurRasterState.pointDrawMode) + else { - geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL); + geometryShader = (geometryExe ? GetAs(geometryExe)->getGeometryShader() : NULL); } bool dirtyUniforms = false; @@ -1944,7 +2133,9 @@ gl::Error Renderer11::applyShaders(gl::Program *program, const gl::VertexFormat return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) +gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D, + GLenum drawMode, + const std::vector &uniformArray) { unsigned int totalRegisterCountVS = 0; unsigned int totalRegisterCountPS = 0; @@ -1952,26 +2143,25 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto bool vertexUniformsDirty = false; bool pixelUniformsDirty = false; - for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) + for (const D3DUniform *uniform : uniformArray) { - const gl::LinkedUniform &uniform = *uniformArray[uniformIndex]; - - if (uniform.isReferencedByVertexShader() && !uniform.isSampler()) + if (uniform->isReferencedByVertexShader() && !uniform->isSampler()) { - totalRegisterCountVS += uniform.registerCount; - vertexUniformsDirty = (vertexUniformsDirty || uniform.dirty); + totalRegisterCountVS += uniform->registerCount; + vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty); } - if (uniform.isReferencedByFragmentShader() && !uniform.isSampler()) + if (uniform->isReferencedByFragmentShader() && !uniform->isSampler()) { - totalRegisterCountPS += uniform.registerCount; - pixelUniformsDirty = (pixelUniformsDirty || uniform.dirty); + totalRegisterCountPS += uniform->registerCount; + pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty); } } - const ProgramD3D *programD3D = GetAs(&program); - const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage()); - const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getFragmentUniformStorage()); + const UniformStorage11 *vertexUniformStorage = + GetAs(&programD3D.getVertexUniformStorage()); + const UniformStorage11 *fragmentUniformStorage = + GetAs(&programD3D.getFragmentUniformStorage()); ASSERT(vertexUniformStorage); ASSERT(fragmentUniformStorage); @@ -1999,26 +2189,26 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto mapPS = (float(*)[4])map.pData; } - for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) + for (const D3DUniform *uniform : uniformArray) { - gl::LinkedUniform *uniform = uniformArray[uniformIndex]; + if (uniform->isSampler()) + continue; - if (!uniform->isSampler()) - { - unsigned int componentCount = (4 - uniform->registerElement); + unsigned int componentCount = (4 - uniform->registerElement); - // we assume that uniforms from structs are arranged in struct order in our uniforms list. otherwise we would - // overwrite previously written regions of memory. + // we assume that uniforms from structs are arranged in struct order in our uniforms list. + // otherwise we would overwrite previously written regions of memory. - if (uniform->isReferencedByVertexShader() && mapVS) - { - memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); - } + if (uniform->isReferencedByVertexShader() && mapVS) + { + memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, + uniform->registerCount * sizeof(float) * componentCount); + } - if (uniform->isReferencedByFragmentShader() && mapPS) - { - memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); - } + if (uniform->isReferencedByFragmentShader() && mapPS) + { + memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, + uniform->registerCount * sizeof(float) * componentCount); } } @@ -2048,7 +2238,7 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto if (!mDriverConstantBufferVS) { D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); + constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants11); constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; constantBufferDescription.CPUAccessFlags = 0; @@ -2056,16 +2246,18 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto constantBufferDescription.StructureByteStride = 0; HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); - UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); - + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader constant buffer, result: 0x%X.", result); + } mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS); } if (!mDriverConstantBufferPS) { D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants); + constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants11); constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; constantBufferDescription.CPUAccessFlags = 0; @@ -2073,32 +2265,50 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto constantBufferDescription.StructureByteStride = 0; HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); - UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); - + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader constant buffer, result: 0x%X.", result); + } mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); } - if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) + const dx_VertexConstants11 &vertexConstants = mStateManager.getVertexConstants(); + if (memcmp(&vertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants11)) != 0) { - mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); - memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); + ASSERT(mDriverConstantBufferVS != nullptr); + if (mDriverConstantBufferVS) + { + mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &vertexConstants, + 16, 0); + memcpy(&mAppliedVertexConstants, &vertexConstants, sizeof(dx_VertexConstants11)); + } } - if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) + const dx_PixelConstants11 &pixelConstants = mStateManager.getPixelConstants(); + if (memcmp(&pixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants11)) != 0) { - mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); - memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); + ASSERT(mDriverConstantBufferPS != nullptr); + if (mDriverConstantBufferPS) + { + mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &pixelConstants, 16, + 0); + memcpy(&mAppliedPixelConstants, &pixelConstants, sizeof(dx_PixelConstants11)); + } } // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary - if (programD3D->usesGeometryShader()) + if (programD3D.usesGeometryShader(drawMode)) { // needed for the point sprite geometry shader if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) { - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; + ASSERT(mDriverConstantBufferPS != nullptr); + if (mDriverConstantBufferPS) + { + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; + } } } @@ -2107,45 +2317,27 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto void Renderer11::markAllStateDirty() { - for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) - { - mAppliedRTVs[rtIndex] = DirtyPointer; - } - mAppliedDSV = DirtyPointer; - mDepthStencilInitialized = false; - mRenderTargetDescInitialized = false; + TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty"); - // We reset the current SRV data because it might not be in sync with D3D's state - // anymore. For example when a currently used SRV is used as an RTV, D3D silently - // remove it from its state. - memset(mCurVertexSRVs.data(), 0, sizeof(SRVRecord) * mCurVertexSRVs.size()); - memset(mCurPixelSRVs.data(), 0, sizeof(SRVRecord) * mCurPixelSRVs.size()); - - ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexSRVs.size()); for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId) { mForceSetVertexSamplerStates[vsamplerId] = true; } - ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelSRVs.size()); for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId) { mForceSetPixelSamplerStates[fsamplerId] = true; } - mForceSetBlendState = true; - mForceSetRasterState = true; - mForceSetDepthStencilState = true; - mForceSetScissor = true; - mForceSetViewport = true; + mStateManager.invalidateEverything(); mAppliedIB = NULL; mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; mAppliedIBOffset = 0; - mAppliedVertexShader = DirtyPointer; - mAppliedGeometryShader = DirtyPointer; - mAppliedPixelShader = DirtyPointer; + mAppliedVertexShader = angle::DirtyPointer; + mAppliedGeometryShader = angle::DirtyPointer; + mAppliedPixelShader = angle::DirtyPointer; mAppliedNumXFBBindings = static_cast(-1); @@ -2155,8 +2347,8 @@ void Renderer11::markAllStateDirty() mAppliedTFOffsets[i] = 0; } - memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); - memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); + memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11)); + memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11)); mInputLayoutCache.markDirty(); @@ -2238,20 +2430,16 @@ bool Renderer11::testDeviceResettable() D3D_FEATURE_LEVEL dummyFeatureLevel; ID3D11DeviceContext* dummyContext; - HRESULT result = D3D11CreateDevice(NULL, - mDriverType, - NULL, + ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN); + HRESULT result = D3D11CreateDevice( + NULL, mRequestedDriverType, NULL, #if defined(_DEBUG) - D3D11_CREATE_DEVICE_DEBUG, + D3D11_CREATE_DEVICE_DEBUG, #else - 0, + 0, #endif - mAvailableFeatureLevels.data(), - mAvailableFeatureLevels.size(), - D3D11_SDK_VERSION, - &dummyDevice, - &dummyFeatureLevel, - &dummyContext); + mAvailableFeatureLevels.data(), static_cast(mAvailableFeatureLevels.size()), + D3D11_SDK_VERSION, &dummyDevice, &dummyFeatureLevel, &dummyContext); if (!mDevice || FAILED(result)) { @@ -2270,6 +2458,13 @@ void Renderer11::release() releaseDeviceResources(); + if (!mCreatedWithDeviceEXT) + { + // Only delete the device if the Renderer11 owns it + // Otherwise we should keep it around in case we try to reinitialize the renderer later + SafeDelete(mEGLDevice); + } + SafeRelease(mDxgiFactory); SafeRelease(mDxgiAdapter); @@ -2285,6 +2480,9 @@ void Renderer11::release() } SafeRelease(mDevice); +#if !defined(ANGLE_MINGW32_COMPAT) + SafeRelease(mDebug); +#endif if (mD3d11Module) { @@ -2298,7 +2496,15 @@ void Renderer11::release() mDxgiModule = NULL; } + if (mDCompModule) + { + FreeLibrary(mDCompModule); + mDCompModule = NULL; + } + mCompiler.release(); + + mSupportsShareHandles.reset(); } bool Renderer11::resetDevice() @@ -2318,11 +2524,6 @@ bool Renderer11::resetDevice() return true; } -VendorID Renderer11::getVendorId() const -{ - return static_cast(mAdapterDescription.VendorId); -} - std::string Renderer11::getRendererDescription() const { std::ostringstream rendererString; @@ -2336,24 +2537,29 @@ std::string Renderer11::getRendererDescription() const return rendererString.str(); } -GUID Renderer11::getAdapterIdentifier() const +DeviceIdentifier Renderer11::getAdapterIdentifier() const { - // Use the adapter LUID as our adapter ID - // This number is local to a machine is only guaranteed to be unique between restarts - static_assert(sizeof(LUID) <= sizeof(GUID), "Size of GUID must be at least as large as LUID."); - GUID adapterId = {0}; - memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); - return adapterId; + // Don't use the AdapterLuid here, since that doesn't persist across reboot. + DeviceIdentifier deviceIdentifier = { 0 }; + deviceIdentifier.VendorId = mAdapterDescription.VendorId; + deviceIdentifier.DeviceId = mAdapterDescription.DeviceId; + deviceIdentifier.SubSysId = mAdapterDescription.SubSysId; + deviceIdentifier.Revision = mAdapterDescription.Revision; + deviceIdentifier.FeatureLevel = static_cast(mRenderer11DeviceCaps.featureLevel); + + return deviceIdentifier; } unsigned int Renderer11::getReservedVertexUniformVectors() const { - return 0; // Driver uniforms are stored in a separate constant buffer + // Driver uniforms are stored in a separate constant buffer + return d3d11_gl::GetReservedVertexUniformVectors(mRenderer11DeviceCaps.featureLevel); } unsigned int Renderer11::getReservedFragmentUniformVectors() const { - return 0; // Driver uniforms are stored in a separate constant buffer + // Driver uniforms are stored in a separate constant buffer + return d3d11_gl::GetReservedFragmentUniformVectors(mRenderer11DeviceCaps.featureLevel); } unsigned int Renderer11::getReservedVertexUniformBuffers() const @@ -2368,24 +2574,100 @@ unsigned int Renderer11::getReservedFragmentUniformBuffers() const return 2; } +d3d11::ANGLED3D11DeviceType Renderer11::getDeviceType() const +{ + if (mCreatedWithDeviceEXT) + { + return d3d11::GetDeviceType(mDevice); + } + + if ((mRequestedDriverType == D3D_DRIVER_TYPE_SOFTWARE) || + (mRequestedDriverType == D3D_DRIVER_TYPE_REFERENCE) || + (mRequestedDriverType == D3D_DRIVER_TYPE_NULL)) + { + return d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL; + } + + if (mRequestedDriverType == D3D_DRIVER_TYPE_WARP) + { + return d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP; + } + + return d3d11::ANGLE_D3D11_DEVICE_TYPE_HARDWARE; +} + bool Renderer11::getShareHandleSupport() const { + if (mSupportsShareHandles.valid()) + { + return mSupportsShareHandles.value(); + } + // We only currently support share handles with BGRA surfaces, because // chrome needs BGRA. Once chrome fixes this, we should always support them. + if (!getRendererExtensions().textureFormatBGRA8888) + { + mSupportsShareHandles = false; + return false; + } + // PIX doesn't seem to support using share handles, so disable them. + if (gl::DebugAnnotationsActive()) + { + mSupportsShareHandles = false; + return false; + } + // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains. - return getRendererExtensions().textureFormatBGRA8888 && !gl::DebugAnnotationsActive();// && !(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3); Qt: we don't care about the 9_3 limitation -} + if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + mSupportsShareHandles = false; + return false; + } -bool Renderer11::getPostSubBufferSupport() const -{ - // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2. - return false; + // Find out which type of D3D11 device the Renderer11 is using + d3d11::ANGLED3D11DeviceType deviceType = getDeviceType(); + if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_UNKNOWN) + { + mSupportsShareHandles = false; + return false; + } + + if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL) + { + // Software/Reference/NULL devices don't support share handles + mSupportsShareHandles = false; + return false; + } + + if (deviceType == d3d11::ANGLE_D3D11_DEVICE_TYPE_WARP) + { +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) && !defined(__GNUC__) + if (!IsWindows8OrGreater()) + { + // WARP on Windows 7 doesn't support shared handles + mSupportsShareHandles = false; + return false; + } +#endif // ANGLE_ENABLE_WINDOWS_STORE + + // WARP on Windows 8.0+ supports shared handles when shared with another WARP device + // TODO: allow applications to query for HARDWARE or WARP-specific share handles, + // to prevent them trying to use a WARP share handle with an a HW device (or + // vice-versa) + // e.g. by creating EGL_D3D11_[HARDWARE/WARP]_DEVICE_SHARE_HANDLE_ANGLE + mSupportsShareHandles = true; + return true; + } + + ASSERT(mCreatedWithDeviceEXT || mRequestedDriverType == D3D_DRIVER_TYPE_HARDWARE); + mSupportsShareHandles = true; + return true; } int Renderer11::getMajorShaderModel() const { - switch (mFeatureLevel) + switch (mRenderer11DeviceCaps.featureLevel) { case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 @@ -2397,7 +2679,7 @@ int Renderer11::getMajorShaderModel() const int Renderer11::getMinorShaderModel() const { - switch (mFeatureLevel) + switch (mRenderer11DeviceCaps.featureLevel) { case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 @@ -2409,7 +2691,7 @@ int Renderer11::getMinorShaderModel() const std::string Renderer11::getShaderModelSuffix() const { - switch (mFeatureLevel) + switch (mRenderer11DeviceCaps.featureLevel) { case D3D_FEATURE_LEVEL_11_0: return ""; case D3D_FEATURE_LEVEL_10_1: return ""; @@ -2419,14 +2701,25 @@ std::string Renderer11::getShaderModelSuffix() const } } +const WorkaroundsD3D &RendererD3D::getWorkarounds() const +{ + if (!mWorkaroundsInitialized) + { + mWorkarounds = generateWorkarounds(); + mWorkaroundsInitialized = true; + } + + return mWorkarounds; +} + gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level) { - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); ASSERT(colorbuffer); RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); if (error.isError()) { return error; @@ -2436,7 +2729,7 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl:: ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); ASSERT(source); - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage); + TextureStorage11_2D *storage11 = GetAs(storage); ASSERT(storage11); gl::ImageIndex index = gl::ImageIndex::Make2D(level); @@ -2448,18 +2741,26 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl:: } ASSERT(destRenderTarget); - ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ID3D11RenderTargetView *dest = GetAs(destRenderTarget)->getRenderTargetView(); ASSERT(dest); gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + const bool invertSource = UsePresentPathFast(this, colorbuffer); + if (invertSource) + { + sourceArea.y = sourceSize.height - sourceRect.y; + sourceArea.height = -sourceArea.height; + } + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); // Use nearest filtering because source and destination are the same size for the direct // copy - mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST, false); if (error.isError()) { return error; @@ -2473,11 +2774,11 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl:: gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) { - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); ASSERT(colorbuffer); RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); if (error.isError()) { return error; @@ -2487,7 +2788,7 @@ gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); ASSERT(source); - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage); + TextureStorage11_Cube *storage11 = GetAs(storage); ASSERT(storage11); gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); @@ -2499,18 +2800,26 @@ gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl } ASSERT(destRenderTarget); - ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ID3D11RenderTargetView *dest = GetAs(destRenderTarget)->getRenderTargetView(); ASSERT(dest); gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + const bool invertSource = UsePresentPathFast(this, colorbuffer); + if (invertSource) + { + sourceArea.y = sourceSize.height - sourceRect.y; + sourceArea.height = -sourceArea.height; + } + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); // Use nearest filtering because source and destination are the same size for the direct // copy - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST, false); if (error.isError()) { return error; @@ -2524,11 +2833,11 @@ gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level) { - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); ASSERT(colorbuffer); RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); if (error.isError()) { return error; @@ -2538,7 +2847,7 @@ gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl:: ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); ASSERT(source); - TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); + TextureStorage11_3D *storage11 = GetAs(storage); ASSERT(storage11); gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); @@ -2550,7 +2859,7 @@ gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl:: } ASSERT(destRenderTarget); - ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ID3D11RenderTargetView *dest = GetAs(destRenderTarget)->getRenderTargetView(); ASSERT(dest); gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); @@ -2561,7 +2870,8 @@ gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl:: // Use nearest filtering because source and destination are the same size for the direct // copy - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST, false); if (error.isError()) { return error; @@ -2575,11 +2885,11 @@ gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl:: gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level) { - gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); ASSERT(colorbuffer); RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &sourceRenderTarget); + gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); if (error.isError()) { return error; @@ -2589,7 +2899,7 @@ gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); ASSERT(source); - TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); + TextureStorage11_2DArray *storage11 = GetAs(storage); ASSERT(storage11); gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); @@ -2601,7 +2911,7 @@ gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const } ASSERT(destRenderTarget); - ID3D11RenderTargetView *dest = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ID3D11RenderTargetView *dest = GetAs(destRenderTarget)->getRenderTargetView(); ASSERT(dest); gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); @@ -2612,7 +2922,8 @@ gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const // Use nearest filtering because source and destination are the same size for the direct // copy - error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, destFormat, GL_NEAREST); + error = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST, false); if (error.isError()) { return error; @@ -2640,14 +2951,14 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView // Do not preserve the serial for this one-time-use render target for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) { - mAppliedRTVs[rtIndex] = DirtyPointer; + mAppliedRTVs[rtIndex] = angle::DirtyPointer; } - mAppliedDSV = DirtyPointer; + mAppliedDSV = angle::DirtyPointer; } gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) { - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format, mFeatureLevel); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format, mRenderer11DeviceCaps); const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); GLuint supportedSamples = textureCaps.getNearestSamples(samples); @@ -2779,9 +3090,26 @@ gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, G return gl::Error(GL_NO_ERROR); } -FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::Framebuffer::Data &data) +gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) { - return createFramebuffer(data); + ASSERT(source != nullptr); + + RenderTargetD3D *newRT = nullptr; + gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(), + source->getInternalFormat(), source->getSamples(), &newRT); + if (error.isError()) + { + return error; + } + + RenderTarget11 *source11 = GetAs(source); + RenderTarget11 *dest11 = GetAs(newRT); + + mDeviceContext->CopySubresourceRegion(dest11->getTexture(), dest11->getSubresourceIndex(), 0, 0, + 0, source11->getTexture(), + source11->getSubresourceIndex(), nullptr); + *outRT = newRT; + return gl::Error(GL_NO_ERROR); } FramebufferImpl *Renderer11::createFramebuffer(const gl::Framebuffer::Data &data) @@ -2789,24 +3117,22 @@ FramebufferImpl *Renderer11::createFramebuffer(const gl::Framebuffer::Data &data return new Framebuffer11(data, this); } -CompilerImpl *Renderer11::createCompiler(const gl::Data &data) +ShaderImpl *Renderer11::createShader(const gl::Shader::Data &data) { - return new CompilerD3D(data, SH_HLSL11_OUTPUT); + return new ShaderD3D(data); } -ShaderImpl *Renderer11::createShader(GLenum type) +ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data) { - return new ShaderD3D(type); + return new ProgramD3D(data, this); } -ProgramImpl *Renderer11::createProgram() -{ - return new ProgramD3D(this); -} - -gl::Error Renderer11::loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) +gl::Error Renderer11::loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) { switch (type) { @@ -2822,29 +3148,28 @@ gl::Error Renderer11::loadExecutable(const void *function, size_t length, Shader return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result); } - if (transformFeedbackVaryings.size() > 0) + if (!streamOutVaryings.empty()) { std::vector soDeclaration; - for (size_t i = 0; i < transformFeedbackVaryings.size(); i++) + soDeclaration.reserve(streamOutVaryings.size()); + + for (const auto &streamOutVarying : streamOutVaryings) { - const gl::LinkedVarying &varying = transformFeedbackVaryings[i]; - GLenum transposedType = gl::TransposeMatrixType(varying.type); - - for (size_t j = 0; j < varying.semanticIndexCount; j++) - { - D3D11_SO_DECLARATION_ENTRY entry = { 0 }; - entry.Stream = 0; - entry.SemanticName = varying.semanticName.c_str(); - entry.SemanticIndex = varying.semanticIndex + j; - entry.StartComponent = 0; - entry.ComponentCount = gl::VariableColumnCount(transposedType); - entry.OutputSlot = (separatedOutputBuffers ? i : 0); - soDeclaration.push_back(entry); - } + D3D11_SO_DECLARATION_ENTRY entry = {0}; + entry.Stream = 0; + entry.SemanticName = streamOutVarying.semanticName.c_str(); + entry.SemanticIndex = streamOutVarying.semanticIndex; + entry.StartComponent = 0; + entry.ComponentCount = static_cast(streamOutVarying.componentCount); + entry.OutputSlot = static_cast( + (separatedOutputBuffers ? streamOutVarying.outputSlot : 0)); + soDeclaration.push_back(entry); } - result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(), - NULL, 0, 0, NULL, &streamOutShader); + result = mDevice->CreateGeometryShaderWithStreamOutput( + function, static_cast(length), soDeclaration.data(), + static_cast(soDeclaration.size()), NULL, 0, 0, NULL, + &streamOutShader); ASSERT(SUCCEEDED(result)); if (FAILED(result)) { @@ -2891,9 +3216,12 @@ gl::Error Renderer11::loadExecutable(const void *function, size_t length, Shader return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, +gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, ShaderExecutableD3D **outExectuable) { const char *profileType = NULL; @@ -2936,6 +3264,15 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" )); configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization")); + if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "") + { + // Some shaders might cause a "blob content mismatch between level9 and d3d10 shader". + // e.g. dEQP-GLES2.functional.shaders.struct.local.loop_nested_struct_array_*. + // Using the [unroll] directive works around this, as does this D3DCompile flag. + configs.push_back( + CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control")); + } + D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} }; ID3DBlob *binary = NULL; @@ -2955,7 +3292,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin } error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - transformFeedbackVaryings, separatedOutputBuffers, outExectuable); + streamOutVaryings, separatedOutputBuffers, outExectuable); SafeRelease(binary); if (error.isError()) @@ -2988,12 +3325,14 @@ IndexBuffer *Renderer11::createIndexBuffer() BufferImpl *Renderer11::createBuffer() { - return new Buffer11(this); + Buffer11 *buffer = new Buffer11(this); + mAliveBuffers.insert(buffer); + return buffer; } -VertexArrayImpl *Renderer11::createVertexArray() +VertexArrayImpl *Renderer11::createVertexArray(const gl::VertexArray::Data &data) { - return new VertexArray11(this); + return new VertexArray11(data); } QueryImpl *Renderer11::createQuery(GLenum type) @@ -3021,7 +3360,7 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const ASSERT(getRendererExtensions().pixelBufferObject); const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); - const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat, mFeatureLevel); + const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat, mRenderer11DeviceCaps); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat); // sRGB formats do not work with D3D11 buffer SRVs @@ -3065,17 +3404,42 @@ ImageD3D *Renderer11::createImage() gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src) { - Image11 *dest11 = Image11::makeImage11(dest); - Image11 *src11 = Image11::makeImage11(src); + Image11 *dest11 = GetAs(dest); + Image11 *src11 = GetAs(src); return Image11::generateMipmap(dest11, src11); } +gl::Error Renderer11::generateMipmapsUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) +{ + TextureStorage11 *storage11 = GetAs(storage); + + ASSERT(storage11->isRenderTarget()); + ASSERT(storage11->supportsNativeMipmapFunction()); + + ID3D11ShaderResourceView *srv; + gl::Error error = storage11->getSRVLevels(textureState.baseLevel, textureState.maxLevel, &srv); + if (error.isError()) + { + return error; + } + + mDeviceContext->GenerateMips(srv); + + return gl::Error(GL_NO_ERROR); +} + TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain) { - SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); + SwapChain11 *swapChain11 = GetAs(swapChain); return new TextureStorage11_2D(this, swapChain11); } +TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage) +{ + return new TextureStorage11_EGLImage(this, eglImage); +} + TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) { return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, hintLevelZeroOnly); @@ -3117,28 +3481,53 @@ RenderbufferImpl *Renderer11::createRenderbuffer() return renderbuffer; } -gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) +gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAttachment, + const gl::Rectangle &sourceArea, + GLenum format, + GLenum type, + GLuint outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixelsOut) { - ASSERT(area.width >= 0); - ASSERT(area.height >= 0); + ASSERT(sourceArea.width >= 0); + ASSERT(sourceArea.height >= 0); - D3D11_TEXTURE2D_DESC textureDesc; - texture->GetDesc(&textureDesc); + const bool invertTexture = UsePresentPathFast(this, &srcAttachment); + + RenderTargetD3D *renderTarget = nullptr; + gl::Error error = srcAttachment.getRenderTarget(&renderTarget); + if (error.isError()) + { + return error; + } + + RenderTarget11 *rt11 = GetAs(renderTarget); + ASSERT(rt11->getTexture()); + + TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(rt11->getTexture()); + unsigned int sourceSubResource = rt11->getSubresourceIndex(); + + const gl::Extents &texSize = textureHelper.getExtents(); + + gl::Rectangle actualArea = sourceArea; + if (invertTexture) + { + actualArea.y = texSize.height - actualArea.y - actualArea.height; + } // Clamp read region to the defined texture boundaries, preventing out of bounds reads // and reads of uninitialized data. gl::Rectangle safeArea; - safeArea.x = gl::clamp(area.x, 0, static_cast(textureDesc.Width)); - safeArea.y = gl::clamp(area.y, 0, static_cast(textureDesc.Height)); - safeArea.width = gl::clamp(area.width + std::min(area.x, 0), 0, - static_cast(textureDesc.Width) - safeArea.x); - safeArea.height = gl::clamp(area.height + std::min(area.y, 0), 0, - static_cast(textureDesc.Height) - safeArea.y); + safeArea.x = gl::clamp(actualArea.x, 0, texSize.width); + safeArea.y = gl::clamp(actualArea.y, 0, texSize.height); + safeArea.width = + gl::clamp(actualArea.width + std::min(actualArea.x, 0), 0, texSize.width - safeArea.x); + safeArea.height = + gl::clamp(actualArea.height + std::min(actualArea.y, 0), 0, texSize.height - safeArea.y); ASSERT(safeArea.x >= 0 && safeArea.y >= 0); - ASSERT(safeArea.x + safeArea.width <= static_cast(textureDesc.Width)); - ASSERT(safeArea.y + safeArea.height <= static_cast(textureDesc.Height)); + ASSERT(safeArea.x + safeArea.width <= texSize.width); + ASSERT(safeArea.y + safeArea.height <= texSize.height); if (safeArea.width == 0 || safeArea.height == 0) { @@ -3146,35 +3535,29 @@ gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int sub return gl::Error(GL_NO_ERROR); } - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = safeArea.width; - stagingDesc.Height = safeArea.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = textureDesc.Format; - stagingDesc.SampleDesc.Count = 1; - stagingDesc.SampleDesc.Quality = 0; - stagingDesc.Usage = D3D11_USAGE_STAGING; - stagingDesc.BindFlags = 0; - stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - stagingDesc.MiscFlags = 0; - - ID3D11Texture2D* stagingTex = NULL; - HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex); - if (FAILED(result)) + gl::Extents safeSize(safeArea.width, safeArea.height, 1); + auto errorOrResult = CreateStagingTexture(textureHelper.getTextureType(), + textureHelper.getFormat(), safeSize, mDevice); + if (errorOrResult.isError()) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging texture for ReadPixels, HRESULT: 0x%X.", result); + return errorOrResult.getError(); } - ID3D11Texture2D* srcTex = NULL; - if (textureDesc.SampleDesc.Count > 1) + TextureHelper11 stagingHelper(errorOrResult.getResult()); + TextureHelper11 resolvedTextureHelper; + + // "srcTexture" usually points to the source texture. + // For 2D multisampled textures, it points to the multisampled resolve texture. + const TextureHelper11 *srcTexture = &textureHelper; + + if (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1) { D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; + resolveDesc.Width = static_cast(texSize.width); + resolveDesc.Height = static_cast(texSize.height); resolveDesc.MipLevels = 1; resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; + resolveDesc.Format = textureHelper.getFormat(); resolveDesc.SampleDesc.Count = 1; resolveDesc.SampleDesc.Quality = 0; resolveDesc.Usage = D3D11_USAGE_DEFAULT; @@ -3182,20 +3565,22 @@ gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int sub resolveDesc.CPUAccessFlags = 0; resolveDesc.MiscFlags = 0; - result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex); + ID3D11Texture2D *resolveTex2D = nullptr; + HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTex2D); if (FAILED(result)) { - SafeRelease(stagingTex); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal resolve texture for ReadPixels, HRESULT: 0x%X.", result); + return gl::Error(GL_OUT_OF_MEMORY, + "Renderer11::readTextureData failed to create internal resolve " + "texture for ReadPixels, HRESULT: 0x%X.", + result); } - mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); - subResource = 0; - } - else - { - srcTex = texture; - srcTex->AddRef(); + mDeviceContext->ResolveSubresource(resolveTex2D, 0, textureHelper.getTexture2D(), + sourceSubResource, textureHelper.getFormat()); + resolvedTextureHelper = TextureHelper11::MakeAndReference(resolveTex2D); + + sourceSubResource = 0; + srcTexture = &resolvedTextureHelper; } D3D11_BOX srcBox; @@ -3203,28 +3588,52 @@ gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int sub srcBox.right = static_cast(safeArea.x + safeArea.width); srcBox.top = static_cast(safeArea.y); srcBox.bottom = static_cast(safeArea.y + safeArea.height); - srcBox.front = 0; - srcBox.back = 1; - mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); + // Select the correct layer from a 3D attachment + srcBox.front = 0; + if (textureHelper.getTextureType() == GL_TEXTURE_3D) + { + srcBox.front = static_cast(srcAttachment.layer()); + } + srcBox.back = srcBox.front + 1; + + mDeviceContext->CopySubresourceRegion(stagingHelper.getResource(), 0, 0, 0, 0, + srcTexture->getResource(), sourceSubResource, &srcBox); - SafeRelease(srcTex); + if (invertTexture) + { + gl::PixelPackState invertTexturePack; - PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); - gl::Error error = packPixels(stagingTex, packParams, pixels); + // Create a new PixelPackState with reversed row order. Note that we can't just assign + // 'invertTexturePack' to be 'pack' (or memcpy) since that breaks the ref counting/object + // tracking in the 'pixelBuffer' members, causing leaks. Instead we must use + // pixelBuffer.set() twice, which performs the addRef/release correctly + invertTexturePack.alignment = pack.alignment; + invertTexturePack.pixelBuffer.set(pack.pixelBuffer.get()); + invertTexturePack.reverseRowOrder = !pack.reverseRowOrder; - SafeRelease(stagingTex); + PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, 0); + error = packPixels(stagingHelper, packParams, pixelsOut); - return error; + invertTexturePack.pixelBuffer.set(nullptr); + + return error; + } + else + { + PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); + return packPixels(stagingHelper, packParams, pixelsOut); + } } -gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut) +gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper, + const PackPixelsParams ¶ms, + uint8_t *pixelsOut) { - D3D11_TEXTURE2D_DESC textureDesc; - readTexture->GetDesc(&textureDesc); + ID3D11Resource *readResource = textureHelper.getResource(); D3D11_MAPPED_SUBRESOURCE mapping; - HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping); + HRESULT hr = mDeviceContext->Map(readResource, 0, D3D11_MAP_READ, 0, &mapping); if (FAILED(hr)) { ASSERT(hr == E_OUTOFMEMORY); @@ -3244,7 +3653,7 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP inputPitch = static_cast(mapping.RowPitch); } - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(textureHelper.getFormat()); const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); if (sourceFormatInfo.format == params.format && sourceFormatInfo.type == params.type) { @@ -3256,9 +3665,8 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP } else { - const d3d11::DXGIFormat &sourceDXGIFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format); - ColorCopyFunction fastCopyFunc = sourceDXGIFormatInfo.getFastCopyFunction(params.format, params.type); - + ColorCopyFunction fastCopyFunc = + dxgiFormatInfo.getFastCopyFunction(params.format, params.type); GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(params.format, params.type); const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat); @@ -3278,7 +3686,7 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP } else { - ColorReadFunction colorReadFunction = sourceDXGIFormatInfo.colorReadFunction; + ColorReadFunction colorReadFunction = dxgiFormatInfo.colorReadFunction; ColorWriteFunction colorWriteFunction = GetColorWriteFunction(params.format, params.type); uint8_t temp[16]; // Maximum size of any Color type used. @@ -3303,21 +3711,27 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP } } - mDeviceContext->Unmap(readTexture, 0); + mDeviceContext->Unmap(readResource, 0); return gl::Error(GL_NO_ERROR); } -gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget, - RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, - bool colorBlit, bool depthBlit, bool stencilBlit) +gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, + const gl::Rectangle &drawRectIn, + RenderTargetD3D *readRenderTarget, + RenderTargetD3D *drawRenderTarget, + GLenum filter, + const gl::Rectangle *scissor, + bool colorBlit, + bool depthBlit, + bool stencilBlit) { // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, // it should never be the case that both color and depth/stencil need to be blitted at // at the same time. ASSERT(colorBlit != (depthBlit || stencilBlit)); - RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); + RenderTarget11 *drawRenderTarget11 = GetAs(drawRenderTarget); if (!drawRenderTarget) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal draw render target from the draw framebuffer."); @@ -3328,7 +3742,7 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView(); ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView(); - RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); + RenderTarget11 *readRenderTarget11 = GetAs(readRenderTarget); if (!readRenderTarget) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target from the read framebuffer."); @@ -3376,13 +3790,94 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + // From the spec: + // "The actual region taken from the read framebuffer is limited to the intersection of the + // source buffers being transferred, which may include the color buffer selected by the read + // buffer, the depth buffer, and / or the stencil buffer depending on mask." + // This means negative x and y are out of bounds, and not to be read from. We handle this here + // by internally scaling the read and draw rectangles. + gl::Rectangle readRect = readRectIn; + gl::Rectangle drawRect = drawRectIn; + auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) + { + double readToDrawScale = + static_cast(drawRectIn.width) / static_cast(readRectIn.width); + return static_cast(round(static_cast(readOffset) * readToDrawScale)); + }; + if (readRect.x < 0) + { + int readOffset = -readRect.x; + readRect.x += readOffset; + readRect.width -= readOffset; + + int drawOffset = readToDrawX(readOffset); + drawRect.x += drawOffset; + drawRect.width -= drawOffset; + } + + auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) + { + double readToDrawScale = + static_cast(drawRectIn.height) / static_cast(readRectIn.height); + return static_cast(round(static_cast(readOffset) * readToDrawScale)); + }; + if (readRect.y < 0) + { + int readOffset = -readRect.y; + readRect.y += readOffset; + readRect.height -= readOffset; + + int drawOffset = readToDrawY(readOffset); + drawRect.y += drawOffset; + drawRect.height -= drawOffset; + } + + if (readRect.x1() < 0) + { + int readOffset = -readRect.x1(); + readRect.width += readOffset; + + int drawOffset = readToDrawX(readOffset); + drawRect.width += drawOffset; + } + + if (readRect.y1() < 0) + { + int readOffset = -readRect.y1(); + readRect.height += readOffset; + + int drawOffset = readToDrawY(readOffset); + drawRect.height += drawOffset; + } + bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL); - bool wholeBufferCopy = !scissorNeeded && - readRect.x == 0 && readRect.width == readSize.width && - readRect.y == 0 && readRect.height == readSize.height && - drawRect.x == 0 && drawRect.width == drawSize.width && - drawRect.y == 0 && drawRect.height == drawSize.height; + const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()); + const auto &srcFormatInfo = gl::GetInternalFormatInfo(readRenderTarget->getInternalFormat()); + const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat()); + + // Some blits require masking off emulated texture channels. eg: from RGBA8 to RGB8, we + // emulate RGB8 with RGBA8, so we need to mask off the alpha channel when we copy. + + gl::Color colorMask; + colorMask.red = (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && + (dxgiFormatInfo.redBits > 0); + colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) && + (dxgiFormatInfo.greenBits > 0); + colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) && + (dxgiFormatInfo.blueBits > 0); + colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) && + (dxgiFormatInfo.alphaBits > 0); + + // We only currently support masking off the alpha channel. + bool colorMaskingNeeded = colorMask.alpha; + ASSERT(!colorMask.red && !colorMask.green && !colorMask.blue); + + bool wholeBufferCopy = !scissorNeeded && !colorMaskingNeeded && readRect.x == 0 && + readRect.width == readSize.width && readRect.y == 0 && + readRect.height == readSize.height && drawRect.x == 0 && + drawRect.width == drawSize.width && drawRect.y == 0 && + drawRect.height == drawSize.height; bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; @@ -3393,14 +3888,13 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat()); bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit); gl::Error result(GL_NO_ERROR); if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() && !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && - (!(depthBlit || stencilBlit) || wholeBufferCopy)) + !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy)) { UINT dstX = drawRect.x; UINT dstY = drawRect.y; @@ -3470,9 +3964,10 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const } else { - GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format; + // We don't currently support masking off any other channel than alpha + bool maskOffAlpha = colorMaskingNeeded && colorMask.alpha; result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, - scissor, format, filter); + scissor, destFormatInfo.format, filter, maskOffAlpha); } } @@ -3484,9 +3979,44 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const bool Renderer11::isES3Capable() const { - return (d3d11_gl::GetMaximumClientVersion(mFeatureLevel) > 2); + return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel) > 2); }; +void Renderer11::onSwap() +{ + // Send histogram updates every half hour + const double kHistogramUpdateInterval = 30 * 60; + + const double currentTime = ANGLEPlatformCurrent()->monotonicallyIncreasingTime(); + const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime; + + if (timeSinceLastUpdate > kHistogramUpdateInterval) + { + updateHistograms(); + mLastHistogramUpdateTime = currentTime; + } +} + +void Renderer11::updateHistograms() +{ + // Update the buffer CPU memory histogram + { + size_t sizeSum = 0; + for (auto &buffer : mAliveBuffers) + { + sizeSum += buffer->getTotalCPUBufferMemoryBytes(); + } + const int kOneMegaByte = 1024 * 1024; + ANGLE_HISTOGRAM_MEMORY_MB("GPU.ANGLE.Buffer11CPUMemoryMB", + static_cast(sizeSum) / kOneMegaByte); + } +} + +void Renderer11::onBufferDelete(const Buffer11 *deleted) +{ + mAliveBuffers.erase(deleted); +} + ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) { D3D11_TEXTURE2D_DESC textureDesc; @@ -3545,54 +4075,64 @@ bool Renderer11::getLUID(LUID *adapterLuid) const return true; } -VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const +VertexConversionType Renderer11::getVertexConversionType(gl::VertexFormatType vertexFormatType) const { - return d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel).conversionType; + return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel).conversionType; } -GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const +GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const { - return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel).nativeFormat).componentType; + return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel).nativeFormat).componentType; } -void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const +void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, gl::Limitations *outLimitations) const { - d3d11_gl::GenerateCaps(mDevice, mDeviceContext, outCaps, outTextureCaps, outExtensions); + d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps, + outExtensions, outLimitations); } -Workarounds Renderer11::generateWorkarounds() const +WorkaroundsD3D Renderer11::generateWorkarounds() const { - return d3d11::GenerateWorkarounds(mFeatureLevel); + return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps.featureLevel); } -void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv) +void Renderer11::createAnnotator() { - auto ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + // The D3D11 renderer must choose the D3D9 debug annotator because the D3D11 interface + // method ID3DUserDefinedAnnotation::GetStatus on desktop builds doesn't work with the Graphics + // Diagnostics tools in Visual Studio 2013. + // The D3D9 annotator works properly for both D3D11 and D3D9. + // Incorrect status reporting can cause ANGLE to log unnecessary debug events. +#ifdef ANGLE_ENABLE_D3D9 + mAnnotator = new DebugAnnotator9(); +#else + mAnnotator = new DebugAnnotator11(); +#endif +} - ASSERT(static_cast(resourceSlot) < currentSRVs.size()); - auto &record = currentSRVs[resourceSlot]; +gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) +{ + return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd); +} - if (record.srv != reinterpret_cast(srv)) +egl::Error Renderer11::getEGLDevice(DeviceImpl **device) +{ + if (mEGLDevice == nullptr) { - if (shaderType == gl::SAMPLER_VERTEX) - { - mDeviceContext->VSSetShaderResources(resourceSlot, 1, &srv); - } - else - { - mDeviceContext->PSSetShaderResources(resourceSlot, 1, &srv); - } + ASSERT(mDevice != nullptr); + mEGLDevice = new DeviceD3D(); + egl::Error error = mEGLDevice->initialize(reinterpret_cast(mDevice), + EGL_D3D11_DEVICE_ANGLE, EGL_FALSE); - record.srv = reinterpret_cast(srv); - if (srv) - { - record.resource = reinterpret_cast(GetViewResource(srv)); - srv->GetDesc(&record.desc); - } - else + if (error.isError()) { - record.resource = 0; + SafeDelete(mEGLDevice); + return error; } } + + *device = static_cast(mEGLDevice); + return egl::Error(EGL_SUCCESS); } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h index cc7d6c237b..b4e7761ffc 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h @@ -18,9 +18,9 @@ #include "libANGLE/renderer/d3d/RenderTargetD3D.h" #include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h" #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" - -struct ID3D11DeviceContext1; +#include "libANGLE/renderer/d3d/d3d11/StateManager11.h" namespace gl { @@ -28,6 +28,8 @@ class FramebufferAttachment; struct ImageIndex; } +struct ID3D11DeviceContext1; + namespace rx { @@ -35,12 +37,24 @@ class VertexDataManager; class IndexDataManager; class StreamingIndexBufferInterface; class Blit11; +class Buffer11; class Clear11; class PixelTransfer11; class RenderTarget11; class Trim11; struct PackPixelsParams; +struct Renderer11DeviceCaps +{ + D3D_FEATURE_LEVEL featureLevel; + bool supportsDXGI1_2; // Support for DXGI 1.2 + bool supportsClearView; // Support for ID3D11DeviceContext1::ClearView + bool supportsConstantBufferOffsets; // Support for Constant buffer offset + UINT B5G6R5support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM + UINT B4G4R4A4support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM + UINT B5G5R5A1support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G5R5A1_UNORM +}; + enum { MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, @@ -64,6 +78,24 @@ enum D3D11InitError D3D11_INIT_INCOMPATIBLE_DXGI, // Other initialization error D3D11_INIT_OTHER_ERROR, + // CreateDevice returned E_FAIL + D3D11_INIT_CREATEDEVICE_FAIL, + // CreateDevice returned E_NOTIMPL + D3D11_INIT_CREATEDEVICE_NOTIMPL, + // CreateDevice returned E_OUTOFMEMORY + D3D11_INIT_CREATEDEVICE_OUTOFMEMORY, + // CreateDevice returned DXGI_ERROR_INVALID_CALL + D3D11_INIT_CREATEDEVICE_INVALIDCALL, + // CreateDevice returned DXGI_ERROR_SDK_COMPONENT_MISSING + D3D11_INIT_CREATEDEVICE_COMPONENTMISSING, + // CreateDevice returned DXGI_ERROR_WAS_STILL_DRAWING + D3D11_INIT_CREATEDEVICE_WASSTILLDRAWING, + // CreateDevice returned DXGI_ERROR_NOT_CURRENTLY_AVAILABLE + D3D11_INIT_CREATEDEVICE_NOTAVAILABLE, + // CreateDevice returned DXGI_ERROR_DEVICE_HUNG + D3D11_INIT_CREATEDEVICE_DEVICEHUNG, + // CreateDevice returned NULL + D3D11_INIT_CREATEDEVICE_NULL, NUM_D3D11_INIT_ERRORS }; @@ -73,66 +105,65 @@ class Renderer11 : public RendererD3D explicit Renderer11(egl::Display *display); virtual ~Renderer11(); - static Renderer11 *makeRenderer11(Renderer *renderer); - egl::Error initialize() override; virtual bool resetDevice(); egl::ConfigSet generateConfigs() const override; + void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override; gl::Error flush() override; gl::Error finish() override; - virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) override; + + CompilerImpl *createCompiler() override; virtual gl::Error generateSwizzle(gl::Texture *texture); virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler); virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); gl::Error setUniformBuffers(const gl::Data &data, - const GLint vertexUniformBuffers[], - const GLint fragmentUniformBuffers[]) override; + const std::vector &vertexUniformBuffers, + const std::vector &fragmentUniformBuffers) override; - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); - gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) override; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); + gl::Error updateState(const gl::Data &data, GLenum drawMode) override; virtual bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize); gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; - virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive); - - virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray); - virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances); - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + gl::Error applyUniforms(const ProgramD3D &programD3D, + GLenum drawMode, + const std::vector &uniformArray) override; + virtual gl::Error applyVertexBuffer(const gl::State &state, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData *indexInfo); + gl::Error applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo) override; void applyTransformFeedbackBuffers(const gl::State &state) override; - gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override; - virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - - virtual void markAllStateDirty(); - // lost device bool testDeviceLost() override; bool testDeviceResettable() override; - VendorID getVendorId() const override; std::string getRendererDescription() const override; - GUID getAdapterIdentifier() const override; + DeviceIdentifier getAdapterIdentifier() const override; virtual unsigned int getReservedVertexUniformVectors() const; virtual unsigned int getReservedFragmentUniformVectors() const; virtual unsigned int getReservedVertexUniformBuffers() const; virtual unsigned int getReservedFragmentUniformBuffers() const; - virtual bool getShareHandleSupport() const; - virtual bool getPostSubBufferSupport() const; + + bool getShareHandleSupport() const; virtual int getMajorShaderModel() const; int getMinorShaderModel() const override; @@ -150,30 +181,38 @@ class Renderer11 : public RendererD3D // RenderTarget creation virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT); + gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override; // Framebuffer creation - FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override; FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override; // Shader creation - virtual CompilerImpl *createCompiler(const gl::Data &data); - virtual ShaderImpl *createShader(GLenum type); - virtual ProgramImpl *createProgram(); + ShaderImpl *createShader(const gl::Shader::Data &data) override; + ProgramImpl *createProgram(const gl::Program::Data &data) override; // Shader operations - virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable); - virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, - ShaderExecutableD3D **outExectuable); - virtual UniformStorageD3D *createUniformStorage(size_t storageSize); + gl::Error loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) override; + gl::Error compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) override; + UniformStorageD3D *createUniformStorage(size_t storageSize) override; // Image operations virtual ImageD3D *createImage(); gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; + gl::Error generateMipmapsUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) override; virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); + TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage) override; virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); @@ -191,7 +230,7 @@ class Renderer11 : public RendererD3D virtual IndexBuffer *createIndexBuffer(); // Vertex Array creation - virtual VertexArrayImpl *createVertexArray(); + VertexArrayImpl *createVertexArray(const gl::VertexArray::Data &data) override; // Query and Fence creation virtual QueryImpl *createQuery(GLenum type); @@ -203,10 +242,13 @@ class Renderer11 : public RendererD3D // D3D11-renderer specific methods ID3D11Device *getDevice() { return mDevice; } + void *getD3DDevice() override; ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; }; DXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + RenderStateCache &getStateCache() { return mStateCache; } + Blit11 *getBlitter() { return mBlit; } Clear11 *getClearer() { return mClear; } @@ -215,64 +257,108 @@ class Renderer11 : public RendererD3D virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + void markAllStateDirty(); void unapplyRenderTargets(); void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); - gl::Error packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut); + gl::Error packPixels(const TextureHelper11 &textureHelper, + const PackPixelsParams ¶ms, + uint8_t *pixelsOut); bool getLUID(LUID *adapterLuid) const override; - virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; - virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; - - gl::Error readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels); + VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override; + GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override; - void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv); + gl::Error readFromAttachment(const gl::FramebufferAttachment &srcAttachment, + const gl::Rectangle &sourceArea, + GLenum format, + GLenum type, + GLuint outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels); gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget, RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, bool colorBlit, bool depthBlit, bool stencilBlit); bool isES3Capable() const; - D3D_FEATURE_LEVEL getFeatureLevel() const { return mFeatureLevel; }; + const Renderer11DeviceCaps &getRenderer11DeviceCaps() { return mRenderer11DeviceCaps; }; RendererClass getRendererClass() const override { return RENDERER_D3D11; } + InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; } + StateManager11 *getStateManager() { return &mStateManager; } - private: - void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; - Workarounds generateWorkarounds() const override; + void onSwap(); + void onBufferDelete(const Buffer11 *deleted); + + egl::Error getEGLDevice(DeviceImpl **device) override; - gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); + protected: + void createAnnotator() override; + gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override; + gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override; + + void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override; + + private: + gl::Error drawArraysImpl(const gl::Data &data, + GLenum mode, + GLsizei count, + GLsizei instances) override; + gl::Error drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances) override; + + void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const override; + + WorkaroundsD3D generateWorkarounds() const override; + + gl::Error drawLineLoop(const gl::Data &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + const TranslatedIndexData *indexInfo, + int instances); + gl::Error drawTriangleFan(const gl::Data &data, + GLsizei count, + GLenum type, + const GLvoid *indices, + int minIndex, + int instances); ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); - void unsetConflictingSRVs(gl::SamplerType shaderType, uintptr_t resource, const gl::ImageIndex *index); + + void populateRenderer11DeviceCaps(); + + void updateHistograms(); HMODULE mD3d11Module; HMODULE mDxgiModule; + HMODULE mDCompModule; std::vector mAvailableFeatureLevels; - D3D_DRIVER_TYPE mDriverType; + D3D_DRIVER_TYPE mRequestedDriverType; + bool mCreatedWithDeviceEXT; + DeviceD3D *mEGLDevice; HLSLCompiler mCompiler; + egl::Error initializeD3DDevice(); void initializeDevice(); void releaseDeviceResources(); void release(); + d3d11::ANGLED3D11DeviceType getDeviceType() const; + RenderStateCache mStateCache; // current render target states uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; uintptr_t mAppliedDSV; - bool mDepthStencilInitialized; - bool mRenderTargetDescInitialized; - - struct RenderTargetDesc - { - size_t width; - size_t height; - DXGI_FORMAT format; - }; - RenderTargetDesc mRenderTargetDesc; // Currently applied sampler states std::vector mForceSetVertexSamplerStates; @@ -281,42 +367,7 @@ class Renderer11 : public RendererD3D std::vector mForceSetPixelSamplerStates; std::vector mCurPixelSamplerStates; - // Currently applied textures - struct SRVRecord - { - uintptr_t srv; - uintptr_t resource; - D3D11_SHADER_RESOURCE_VIEW_DESC desc; - }; - std::vector mCurVertexSRVs; - std::vector mCurPixelSRVs; - - // Currently applied blend state - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::ColorF mCurBlendColor; - unsigned int mCurSampleMask; - - // Currently applied rasterizer state - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - // Currently applied depth stencil state - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - - // Currently applied scissor rectangle - bool mForceSetScissor; - bool mScissorEnabled; - gl::Rectangle mCurScissor; - - // Currently applied viewport - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; + StateManager11 mStateManager; // Currently applied primitive topology D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; @@ -325,6 +376,7 @@ class Renderer11 : public RendererD3D ID3D11Buffer *mAppliedIB; DXGI_FORMAT mAppliedIBFormat; unsigned int mAppliedIBOffset; + bool mAppliedIBChanged; // Currently applied transform feedback buffers size_t mAppliedNumXFBBindings; @@ -342,16 +394,14 @@ class Renderer11 : public RendererD3D uintptr_t mAppliedGeometryShader; uintptr_t mAppliedPixelShader; - dx_VertexConstants mVertexConstants; - dx_VertexConstants mAppliedVertexConstants; + dx_VertexConstants11 mAppliedVertexConstants; ID3D11Buffer *mDriverConstantBufferVS; ID3D11Buffer *mCurrentVertexConstantBuffer; unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; - dx_PixelConstants mPixelConstants; - dx_PixelConstants mAppliedPixelConstants; + dx_PixelConstants11 mAppliedPixelConstants; ID3D11Buffer *mDriverConstantBufferPS; ID3D11Buffer *mCurrentPixelConstantBuffer; unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; @@ -381,19 +431,26 @@ class Renderer11 : public RendererD3D // Sync query ID3D11Query *mSyncQuery; - // Constant buffer offset support - bool mSupportsConstantBufferOffsets; + // Created objects state tracking + std::set mAliveBuffers; + + double mLastHistogramUpdateTime; ID3D11Device *mDevice; - D3D_FEATURE_LEVEL mFeatureLevel; + Renderer11DeviceCaps mRenderer11DeviceCaps; ID3D11DeviceContext *mDeviceContext; ID3D11DeviceContext1 *mDeviceContext1; IDXGIAdapter *mDxgiAdapter; DXGI_ADAPTER_DESC mAdapterDescription; char mDescription[128]; DXGIFactory *mDxgiFactory; +#if !defined(ANGLE_MINGW32_COMPAT) + ID3D11Debug *mDebug; +#endif + + std::vector mScratchIndexDataBuffer; - DebugAnnotator11 mAnnotator; + mutable Optional mSupportsShareHandles; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp index 7e64c3183d..4da51afe49 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -48,12 +48,6 @@ ShaderExecutable11::~ShaderExecutable11() SafeRelease(mStreamOutExecutable); } -ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutableD3D *executable) -{ - ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable)); - return static_cast(executable); -} - ID3D11VertexShader *ShaderExecutable11::getVertexShader() const { return mVertexExecutable; @@ -83,7 +77,7 @@ UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize) if (initialSize > 0) { D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = initialSize; + constantBufferDescription.ByteWidth = static_cast(initialSize); constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC; constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; @@ -101,10 +95,4 @@ UniformStorage11::~UniformStorage11() SafeRelease(mConstantBuffer); } -const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorageD3D *uniformStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(const UniformStorage11*, uniformStorage)); - return static_cast(uniformStorage); -} - } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h index 02558ee4dc..379f39fe53 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h @@ -26,8 +26,6 @@ class ShaderExecutable11 : public ShaderExecutableD3D virtual ~ShaderExecutable11(); - static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutableD3D *executable); - ID3D11PixelShader *getPixelShader() const; ID3D11VertexShader *getVertexShader() const; ID3D11GeometryShader *getGeometryShader() const; @@ -46,8 +44,6 @@ class UniformStorage11 : public UniformStorageD3D UniformStorage11(Renderer11 *renderer, size_t initialSize); virtual ~UniformStorage11(); - static const UniformStorage11 *makeUniformStorage11(const UniformStorageD3D *uniformStorage); - ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; } private: diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp new file mode 100644 index 0000000000..aa34fd4de8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp @@ -0,0 +1,1040 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManager11.cpp: Defines a class for caching D3D11 state + +#include "libANGLE/renderer/d3d/d3d11/StateManager11.h" + +#include "common/BitSetIterator.h" +#include "common/utilities.h" +#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" + +namespace rx +{ + +namespace +{ +bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc) +{ + unsigned mipLevel = index.mipIndex; + unsigned layerIndex = index.layerIndex; + GLenum type = index.type; + + switch (desc.ViewDimension) + { + case D3D11_SRV_DIMENSION_TEXTURE2D: + { + unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip; + maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip; + + unsigned mipMin = index.mipIndex; + unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex; + + return type == GL_TEXTURE_2D && + gl::RangeUI(mipMin, mipMax) + .intersects(gl::RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip)); + } + + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + { + unsigned maxSrvMip = + desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip; + maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip; + + unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize; + + // Cube maps can be mapped to Texture2DArray SRVs + return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) && + desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip && + desc.Texture2DArray.FirstArraySlice <= layerIndex && layerIndex < maxSlice; + } + + case D3D11_SRV_DIMENSION_TEXTURECUBE: + { + unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip; + maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip; + + return gl::IsCubeMapTextureTarget(type) && + desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; + } + + case D3D11_SRV_DIMENSION_TEXTURE3D: + { + unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip; + maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip; + + return type == GL_TEXTURE_3D && desc.Texture3D.MostDetailedMip <= mipLevel && + mipLevel < maxSrvMip; + } + default: + // We only handle the cases corresponding to valid image indexes + UNIMPLEMENTED(); + } + + return false; +} + +// Does *not* increment the resource ref count!! +ID3D11Resource *GetViewResource(ID3D11View *view) +{ + ID3D11Resource *resource = NULL; + ASSERT(view); + view->GetResource(&resource); + resource->Release(); + return resource; +} + +} // anonymous namespace + +void StateManager11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv) +{ + ASSERT(resourceIndex < mCurrentSRVs.size()); + SRVRecord *record = &mCurrentSRVs[resourceIndex]; + + record->srv = reinterpret_cast(srv); + if (srv) + { + record->resource = reinterpret_cast(GetViewResource(srv)); + srv->GetDesc(&record->desc); + mHighestUsedSRV = std::max(resourceIndex + 1, mHighestUsedSRV); + } + else + { + record->resource = 0; + + if (resourceIndex + 1 == mHighestUsedSRV) + { + do + { + --mHighestUsedSRV; + } while (mHighestUsedSRV > 0 && mCurrentSRVs[mHighestUsedSRV].srv == 0); + } + } +} + +void StateManager11::SRVCache::clear() +{ + if (mCurrentSRVs.empty()) + { + return; + } + + memset(&mCurrentSRVs[0], 0, sizeof(SRVRecord) * mCurrentSRVs.size()); + mHighestUsedSRV = 0; +} + +StateManager11::StateManager11(Renderer11 *renderer) + : mRenderer(renderer), + mBlendStateIsDirty(false), + mCurBlendColor(0, 0, 0, 0), + mCurSampleMask(0), + mDepthStencilStateIsDirty(false), + mCurStencilRef(0), + mCurStencilBackRef(0), + mCurStencilSize(0), + mRasterizerStateIsDirty(false), + mScissorStateIsDirty(false), + mCurScissorEnabled(false), + mCurScissorRect(), + mViewportStateIsDirty(false), + mCurViewport(), + mCurNear(0.0f), + mCurFar(0.0f), + mViewportBounds(), + mCurPresentPathFastEnabled(false), + mCurPresentPathFastColorBufferHeight(0), + mAppliedDSV(angle::DirtyPointer) +{ + mCurBlendState.blend = false; + mCurBlendState.sourceBlendRGB = GL_ONE; + mCurBlendState.destBlendRGB = GL_ZERO; + mCurBlendState.sourceBlendAlpha = GL_ONE; + mCurBlendState.destBlendAlpha = GL_ZERO; + mCurBlendState.blendEquationRGB = GL_FUNC_ADD; + mCurBlendState.blendEquationAlpha = GL_FUNC_ADD; + mCurBlendState.colorMaskRed = true; + mCurBlendState.colorMaskBlue = true; + mCurBlendState.colorMaskGreen = true; + mCurBlendState.colorMaskAlpha = true; + mCurBlendState.sampleAlphaToCoverage = false; + mCurBlendState.dither = false; + + mCurDepthStencilState.depthTest = false; + mCurDepthStencilState.depthFunc = GL_LESS; + mCurDepthStencilState.depthMask = true; + mCurDepthStencilState.stencilTest = false; + mCurDepthStencilState.stencilMask = true; + mCurDepthStencilState.stencilFail = GL_KEEP; + mCurDepthStencilState.stencilPassDepthFail = GL_KEEP; + mCurDepthStencilState.stencilPassDepthPass = GL_KEEP; + mCurDepthStencilState.stencilWritemask = static_cast(-1); + mCurDepthStencilState.stencilBackFunc = GL_ALWAYS; + mCurDepthStencilState.stencilBackMask = static_cast(-1); + mCurDepthStencilState.stencilBackFail = GL_KEEP; + mCurDepthStencilState.stencilBackPassDepthFail = GL_KEEP; + mCurDepthStencilState.stencilBackPassDepthPass = GL_KEEP; + mCurDepthStencilState.stencilBackWritemask = static_cast(-1); + + mCurRasterState.rasterizerDiscard = false; + mCurRasterState.cullFace = false; + mCurRasterState.cullMode = GL_BACK; + mCurRasterState.frontFace = GL_CCW; + mCurRasterState.polygonOffsetFill = false; + mCurRasterState.polygonOffsetFactor = 0.0f; + mCurRasterState.polygonOffsetUnits = 0.0f; + mCurRasterState.pointDrawMode = false; + mCurRasterState.multiSample = false; +} + +StateManager11::~StateManager11() +{ +} + +void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized, + unsigned int stencilSize) +{ + if (!depthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + mDepthStencilStateIsDirty = true; + } +} + +void StateManager11::setViewportBounds(const int width, const int height) +{ + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && + (mViewportBounds.width != width || mViewportBounds.height != height)) + { + mViewportBounds = gl::Extents(width, height, 1); + mViewportStateIsDirty = true; + } +} + +void StateManager11::updatePresentPath(bool presentPathFastActive, + const gl::FramebufferAttachment *framebufferAttachment) +{ + const int colorBufferHeight = + framebufferAttachment ? framebufferAttachment->getSize().height : 0; + + if ((mCurPresentPathFastEnabled != presentPathFastActive) || + (presentPathFastActive && (colorBufferHeight != mCurPresentPathFastColorBufferHeight))) + { + mCurPresentPathFastEnabled = presentPathFastActive; + mCurPresentPathFastColorBufferHeight = colorBufferHeight; + mViewportStateIsDirty = true; // Viewport may need to be vertically inverted + mScissorStateIsDirty = true; // Scissor rect may need to be vertically inverted + mRasterizerStateIsDirty = true; // Cull Mode may need to be inverted + } +} + +void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +{ + if (!dirtyBits.any()) + { + return; + } + + for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits)) + { + switch (dirtyBit) + { + case gl::State::DIRTY_BIT_BLEND_EQUATIONS: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || + blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) + { + mBlendStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_BLEND_FUNCS: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB || + blendState.destBlendRGB != mCurBlendState.destBlendRGB || + blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || + blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) + { + mBlendStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_BLEND_ENABLED: + if (state.getBlendState().blend != mCurBlendState.blend) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: + if (state.getBlendState().sampleAlphaToCoverage != + mCurBlendState.sampleAlphaToCoverage) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DITHER_ENABLED: + if (state.getBlendState().dither != mCurBlendState.dither) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_COLOR_MASK: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.colorMaskRed != mCurBlendState.colorMaskRed || + blendState.colorMaskGreen != mCurBlendState.colorMaskGreen || + blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || + blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) + { + mBlendStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_BLEND_COLOR: + if (state.getBlendColor() != mCurBlendColor) + { + mBlendStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_MASK: + if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: + if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_FUNC: + if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: + if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: + { + const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); + if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc || + depthStencil.stencilMask != mCurDepthStencilState.stencilMask || + state.getStencilRef() != mCurStencilRef) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: + { + const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); + if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc || + depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask || + state.getStencilBackRef() != mCurStencilBackRef) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + if (state.getDepthStencilState().stencilWritemask != + mCurDepthStencilState.stencilWritemask) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: + if (state.getDepthStencilState().stencilBackWritemask != + mCurDepthStencilState.stencilBackWritemask) + { + mDepthStencilStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: + { + const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); + if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail || + depthStencil.stencilPassDepthFail != + mCurDepthStencilState.stencilPassDepthFail || + depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: + { + const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); + if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail || + depthStencil.stencilBackPassDepthFail != + mCurDepthStencilState.stencilBackPassDepthFail || + depthStencil.stencilBackPassDepthPass != + mCurDepthStencilState.stencilBackPassDepthPass) + { + mDepthStencilStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: + if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_CULL_FACE: + if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_FRONT_FACE: + if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: + if (state.getRasterizerState().polygonOffsetFill != + mCurRasterState.polygonOffsetFill) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET: + { + const gl::RasterizerState &rasterState = state.getRasterizerState(); + if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || + rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) + { + mRasterizerStateIsDirty = true; + } + break; + } + case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED: + if (state.getRasterizerState().rasterizerDiscard != + mCurRasterState.rasterizerDiscard) + { + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_SCISSOR: + if (state.getScissor() != mCurScissorRect) + { + mScissorStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: + if (state.isScissorTestEnabled() != mCurScissorEnabled) + { + mScissorStateIsDirty = true; + // Rasterizer state update needs mCurScissorsEnabled and updates when it changes + mRasterizerStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_DEPTH_RANGE: + if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) + { + mViewportStateIsDirty = true; + } + break; + case gl::State::DIRTY_BIT_VIEWPORT: + if (state.getViewport() != mCurViewport) + { + mViewportStateIsDirty = true; + } + break; + default: + break; + } + } +} + +gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask) +{ + if (!mBlendStateIsDirty && sampleMask == mCurSampleMask) + { + return gl::Error(GL_NO_ERROR); + } + + ID3D11BlendState *dxBlendState = nullptr; + gl::Error error = + mRenderer->getStateCache().getBlendState(framebuffer, blendState, &dxBlendState); + if (error.isError()) + { + return error; + } + + ASSERT(dxBlendState != nullptr); + + float blendColors[4] = {0.0f}; + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && + blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + blendColors[0] = blendColor.red; + blendColors[1] = blendColor.green; + blendColors[2] = blendColor.blue; + blendColors[3] = blendColor.alpha; + } + else + { + blendColors[0] = blendColor.alpha; + blendColors[1] = blendColor.alpha; + blendColors[2] = blendColor.alpha; + blendColors[3] = blendColor.alpha; + } + + mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState, blendColors, sampleMask); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + mCurSampleMask = sampleMask; + + mBlendStateIsDirty = false; + + return error; +} + +gl::Error StateManager11::setDepthStencilState(const gl::State &glState) +{ + const auto &fbo = *glState.getDrawFramebuffer(); + + // Disable the depth test/depth write if we are using a stencil-only attachment. + // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read + // nor write to the unused depth part of this emulated texture. + bool disableDepth = (!fbo.hasDepth() && fbo.hasStencil()); + + // Similarly we disable the stencil portion of the DS attachment if the app only binds depth. + bool disableStencil = (fbo.hasDepth() && !fbo.hasStencil()); + + // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState. + if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() && + disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() && + disableStencil == mCurDisableStencil.value()) + { + return gl::Error(GL_NO_ERROR); + } + + const auto &depthStencilState = glState.getDepthStencilState(); + int stencilRef = glState.getStencilRef(); + int stencilBackRef = glState.getStencilBackRef(); + + // get the maximum size of the stencil ref + unsigned int maxStencil = 0; + if (depthStencilState.stencilTest && mCurStencilSize > 0) + { + maxStencil = (1 << mCurStencilSize) - 1; + } + ASSERT((depthStencilState.stencilWritemask & maxStencil) == + (depthStencilState.stencilBackWritemask & maxStencil)); + ASSERT(stencilRef == stencilBackRef); + ASSERT((depthStencilState.stencilMask & maxStencil) == + (depthStencilState.stencilBackMask & maxStencil)); + + ID3D11DepthStencilState *dxDepthStencilState = NULL; + gl::Error error = mRenderer->getStateCache().getDepthStencilState( + depthStencilState, disableDepth, disableStencil, &dxDepthStencilState); + if (error.isError()) + { + return error; + } + + ASSERT(dxDepthStencilState); + + // Max D3D11 stencil reference value is 0xFF, + // corresponding to the max 8 bits in a stencil buffer + // GL specifies we should clamp the ref value to the + // nearest bit depth when doing stencil ops + static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, + "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK"); + static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, + "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK"); + UINT dxStencilRef = std::min(stencilRef, 0xFFu); + + mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); + + mCurDepthStencilState = depthStencilState; + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + mCurDisableDepth = disableDepth; + mCurDisableStencil = disableStencil; + + mDepthStencilStateIsDirty = false; + + return gl::Error(GL_NO_ERROR); +} + +gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState) +{ + if (!mRasterizerStateIsDirty) + { + return gl::Error(GL_NO_ERROR); + } + + ID3D11RasterizerState *dxRasterState = nullptr; + gl::Error error(GL_NO_ERROR); + + if (mCurPresentPathFastEnabled) + { + gl::RasterizerState modifiedRasterState = rasterState; + + // If prseent path fast is active then we need invert the front face state. + // This ensures that both gl_FrontFacing is correct, and front/back culling + // is performed correctly. + if (modifiedRasterState.frontFace == GL_CCW) + { + modifiedRasterState.frontFace = GL_CW; + } + else + { + ASSERT(modifiedRasterState.frontFace == GL_CW); + modifiedRasterState.frontFace = GL_CCW; + } + + error = mRenderer->getStateCache().getRasterizerState(modifiedRasterState, + mCurScissorEnabled, &dxRasterState); + } + else + { + error = mRenderer->getStateCache().getRasterizerState(rasterState, mCurScissorEnabled, + &dxRasterState); + } + + if (error.isError()) + { + return error; + } + + mRenderer->getDeviceContext()->RSSetState(dxRasterState); + + mCurRasterState = rasterState; + mRasterizerStateIsDirty = false; + + return error; +} + +void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + if (!mScissorStateIsDirty) + return; + + int modifiedScissorY = scissor.y; + if (mCurPresentPathFastEnabled) + { + modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y; + } + + if (enabled) + { + D3D11_RECT rect; + rect.left = std::max(0, scissor.x); + rect.top = std::max(0, modifiedScissorY); + rect.right = scissor.x + std::max(0, scissor.width); + rect.bottom = modifiedScissorY + std::max(0, scissor.height); + + mRenderer->getDeviceContext()->RSSetScissorRects(1, &rect); + } + + mCurScissorRect = scissor; + mCurScissorEnabled = enabled; + mScissorStateIsDirty = false; +} + +void StateManager11::setViewport(const gl::Caps *caps, + const gl::Rectangle &viewport, + float zNear, + float zFar) +{ + if (!mViewportStateIsDirty) + return; + + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + + int dxMaxViewportBoundsX = static_cast(caps->maxViewportWidth); + int dxMaxViewportBoundsY = static_cast(caps->maxViewportHeight); + int dxMinViewportBoundsX = -dxMaxViewportBoundsX; + int dxMinViewportBoundsY = -dxMaxViewportBoundsY; + + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. + dxMaxViewportBoundsX = static_cast(mViewportBounds.width); + dxMaxViewportBoundsY = static_cast(mViewportBounds.height); + dxMinViewportBoundsX = 0; + dxMinViewportBoundsY = 0; + } + + int dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX); + int dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY); + int dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); + int dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); + + D3D11_VIEWPORT dxViewport; + dxViewport.TopLeftX = static_cast(dxViewportTopLeftX); + + if (mCurPresentPathFastEnabled) + { + // When present path fast is active and we're rendering to framebuffer 0, we must invert + // the viewport in Y-axis. + // NOTE: We delay the inversion until right before the call to RSSetViewports, and leave + // dxViewportTopLeftY unchanged. This allows us to calculate viewAdjust below using the + // unaltered dxViewportTopLeftY value. + dxViewport.TopLeftY = static_cast(mCurPresentPathFastColorBufferHeight - + dxViewportTopLeftY - dxViewportHeight); + } + else + { + dxViewport.TopLeftY = static_cast(dxViewportTopLeftY); + } + + dxViewport.Width = static_cast(dxViewportWidth); + dxViewport.Height = static_cast(dxViewportHeight); + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + + mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport); + + mCurViewport = viewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + + // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders + // using viewAdjust (like the D3D9 renderer). + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + mVertexConstants.viewAdjust[0] = static_cast((viewport.width - dxViewportWidth) + + 2 * (viewport.x - dxViewportTopLeftX)) / + dxViewport.Width; + mVertexConstants.viewAdjust[1] = static_cast((viewport.height - dxViewportHeight) + + 2 * (viewport.y - dxViewportTopLeftY)) / + dxViewport.Height; + mVertexConstants.viewAdjust[2] = static_cast(viewport.width) / dxViewport.Width; + mVertexConstants.viewAdjust[3] = static_cast(viewport.height) / dxViewport.Height; + } + + mPixelConstants.viewCoords[0] = viewport.width * 0.5f; + mPixelConstants.viewCoords[1] = viewport.height * 0.5f; + mPixelConstants.viewCoords[2] = viewport.x + (viewport.width * 0.5f); + mPixelConstants.viewCoords[3] = viewport.y + (viewport.height * 0.5f); + + // Instanced pointsprite emulation requires ViewCoords to be defined in the + // the vertex shader. + mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0]; + mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1]; + mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2]; + mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3]; + + mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + + mVertexConstants.depthRange[0] = actualZNear; + mVertexConstants.depthRange[1] = actualZFar; + mVertexConstants.depthRange[2] = actualZFar - actualZNear; + + mPixelConstants.depthRange[0] = actualZNear; + mPixelConstants.depthRange[1] = actualZFar; + mPixelConstants.depthRange[2] = actualZFar - actualZNear; + + mPixelConstants.viewScale[0] = 1.0f; + mPixelConstants.viewScale[1] = mCurPresentPathFastEnabled ? 1.0f : -1.0f; + mPixelConstants.viewScale[2] = 1.0f; + mPixelConstants.viewScale[3] = 1.0f; + + mVertexConstants.viewScale[0] = mPixelConstants.viewScale[0]; + mVertexConstants.viewScale[1] = mPixelConstants.viewScale[1]; + mVertexConstants.viewScale[2] = mPixelConstants.viewScale[2]; + mVertexConstants.viewScale[3] = mPixelConstants.viewScale[3]; + + mViewportStateIsDirty = false; +} + +void StateManager11::invalidateRenderTarget() +{ + for (auto &appliedRTV : mAppliedRTVs) + { + appliedRTV = angle::DirtyPointer; + } + mAppliedDSV = angle::DirtyPointer; +} + +void StateManager11::invalidateEverything() +{ + mBlendStateIsDirty = true; + mDepthStencilStateIsDirty = true; + mRasterizerStateIsDirty = true; + mScissorStateIsDirty = true; + mViewportStateIsDirty = true; + + // We reset the current SRV data because it might not be in sync with D3D's state + // anymore. For example when a currently used SRV is used as an RTV, D3D silently + // remove it from its state. + mCurVertexSRVs.clear(); + mCurPixelSRVs.clear(); + + invalidateRenderTarget(); +} + +bool StateManager11::setRenderTargets(const RenderTargetArray &renderTargets, + ID3D11DepthStencilView *depthStencil) +{ + // TODO(jmadill): Use context caps? + UINT drawBuffers = mRenderer->getRendererCaps().maxDrawBuffers; + + // Apply the render target and depth stencil + size_t arraySize = sizeof(uintptr_t) * drawBuffers; + if (memcmp(renderTargets.data(), mAppliedRTVs.data(), arraySize) == 0 && + reinterpret_cast(depthStencil) == mAppliedDSV) + { + return false; + } + + // The D3D11 blend state is heavily dependent on the current render target. + mBlendStateIsDirty = true; + + for (UINT rtIndex = 0; rtIndex < drawBuffers; rtIndex++) + { + mAppliedRTVs[rtIndex] = reinterpret_cast(renderTargets[rtIndex]); + } + mAppliedDSV = reinterpret_cast(depthStencil); + + mRenderer->getDeviceContext()->OMSetRenderTargets(drawBuffers, renderTargets.data(), + depthStencil); + return true; +} + +void StateManager11::setRenderTarget(ID3D11RenderTargetView *renderTarget, + ID3D11DepthStencilView *depthStencil) +{ + mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil); +} + +void StateManager11::setShaderResource(gl::SamplerType shaderType, + UINT resourceSlot, + ID3D11ShaderResourceView *srv) +{ + auto ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + ASSERT(static_cast(resourceSlot) < currentSRVs.size()); + const SRVRecord &record = currentSRVs[resourceSlot]; + + if (record.srv != reinterpret_cast(srv)) + { + auto deviceContext = mRenderer->getDeviceContext(); + if (shaderType == gl::SAMPLER_VERTEX) + { + deviceContext->VSSetShaderResources(resourceSlot, 1, &srv); + } + else + { + deviceContext->PSSetShaderResources(resourceSlot, 1, &srv); + } + + currentSRVs.update(resourceSlot, srv); + } +} + +gl::Error StateManager11::clearTextures(gl::SamplerType samplerType, + size_t rangeStart, + size_t rangeEnd) +{ + if (rangeStart == rangeEnd) + { + return gl::Error(GL_NO_ERROR); + } + + auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + gl::Range clearRange(rangeStart, rangeStart); + clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed())); + + if (clearRange.empty()) + { + return gl::Error(GL_NO_ERROR); + } + + auto deviceContext = mRenderer->getDeviceContext(); + if (samplerType == gl::SAMPLER_VERTEX) + { + deviceContext->VSSetShaderResources(static_cast(rangeStart), + static_cast(rangeEnd - rangeStart), + &mNullSRVs[0]); + } + else + { + deviceContext->PSSetShaderResources(static_cast(rangeStart), + static_cast(rangeEnd - rangeStart), + &mNullSRVs[0]); + } + + for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex) + { + currentSRVs.update(samplerIndex, nullptr); + } + + return gl::Error(GL_NO_ERROR); +} + +void StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType, + uintptr_t resource, + const gl::ImageIndex &index) +{ + auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + + for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) + { + auto &record = currentSRVs[resourceIndex]; + + if (record.srv && record.resource == resource && + ImageIndexConflictsWithSRV(index, record.desc)) + { + setShaderResource(samplerType, static_cast(resourceIndex), NULL); + } + } +} + +void StateManager11::initialize(const gl::Caps &caps) +{ + mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits); + mCurPixelSRVs.initialize(caps.maxTextureImageUnits); + + // Initialize cached NULL SRV block + mNullSRVs.resize(caps.maxTextureImageUnits, nullptr); +} + +gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer) +{ + // Get the color render buffer and serial + // Also extract the render target dimensions and view + unsigned int renderTargetWidth = 0; + unsigned int renderTargetHeight = 0; + DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN; + RenderTargetArray framebufferRTVs; + bool missingColorRenderTarget = true; + + framebufferRTVs.fill(nullptr); + + const Framebuffer11 *framebuffer11 = GetImplAs(framebuffer); + const gl::AttachmentList &colorbuffers = framebuffer11->getColorAttachmentsForRender(); + + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) + { + const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; + + if (colorbuffer) + { + // the draw buffer must be either "none", "back" for the default buffer or the same + // index as this color (in order) + + // check for zero-sized default framebuffer, which is a special case. + // in this case we do not wish to modify any state and just silently return false. + // this will not report any gl error but will cause the calling method to return. + const gl::Extents &size = colorbuffer->getSize(); + if (size.width == 0 || size.height == 0) + { + return gl::Error(GL_NO_ERROR); + } + + // Extract the render target dimensions and view + RenderTarget11 *renderTarget = NULL; + gl::Error error = colorbuffer->getRenderTarget(&renderTarget); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget); + + framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); + ASSERT(framebufferRTVs[colorAttachment]); + + if (missingColorRenderTarget) + { + renderTargetWidth = renderTarget->getWidth(); + renderTargetHeight = renderTarget->getHeight(); + renderTargetFormat = renderTarget->getDXGIFormat(); + missingColorRenderTarget = false; + } + + // Unbind render target SRVs from the shader here to prevent D3D11 warnings. + if (colorbuffer->type() == GL_TEXTURE) + { + uintptr_t rtResource = + reinterpret_cast(GetViewResource(framebufferRTVs[colorAttachment])); + const gl::ImageIndex &index = colorbuffer->getTextureImageIndex(); + // The index doesn't need to be corrected for the small compressed texture + // workaround + // because a rendertarget is never compressed. + unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index); + } + } + } + + // Get the depth stencil buffers + ID3D11DepthStencilView *framebufferDSV = NULL; + const gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer(); + if (depthStencil) + { + RenderTarget11 *depthStencilRenderTarget = NULL; + gl::Error error = depthStencil->getRenderTarget(&depthStencilRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(depthStencilRenderTarget); + + framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); + ASSERT(framebufferDSV); + + // If there is no render buffer, the width, height and format values come from + // the depth stencil + if (missingColorRenderTarget) + { + renderTargetWidth = depthStencilRenderTarget->getWidth(); + renderTargetHeight = depthStencilRenderTarget->getHeight(); + } + + // Unbind render target SRVs from the shader here to prevent D3D11 warnings. + if (depthStencil->type() == GL_TEXTURE) + { + uintptr_t depthStencilResource = + reinterpret_cast(GetViewResource(framebufferDSV)); + const gl::ImageIndex &index = depthStencil->getTextureImageIndex(); + // The index doesn't need to be corrected for the small compressed texture workaround + // because a rendertarget is never compressed. + unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index); + } + } + + if (setRenderTargets(framebufferRTVs, framebufferDSV)) + { + setViewportBounds(renderTargetWidth, renderTargetHeight); + } + + gl::Error error = framebuffer11->invalidateSwizzles(); + if (error.isError()) + { + return error; + } + + return gl::Error(GL_NO_ERROR); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h new file mode 100644 index 0000000000..f900882d7e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h @@ -0,0 +1,181 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManager11.h: Defines a class for caching D3D11 state + +#ifndef LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_ +#define LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_ + +#include + +#include "libANGLE/angletypes.h" +#include "libANGLE/Data.h" +#include "libANGLE/State.h" +#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ + +struct RenderTargetDesc; +struct Renderer11DeviceCaps; + +struct dx_VertexConstants11 +{ + float depthRange[4]; + float viewAdjust[4]; + float viewCoords[4]; + float viewScale[4]; +}; + +struct dx_PixelConstants11 +{ + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; + float viewScale[4]; +}; + +class StateManager11 final : angle::NonCopyable +{ + public: + StateManager11(Renderer11 *renderer); + ~StateManager11(); + + void initialize(const gl::Caps &caps); + void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits); + + gl::Error setBlendState(const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask); + + gl::Error setDepthStencilState(const gl::State &glState); + + gl::Error setRasterizerState(const gl::RasterizerState &rasterState); + + void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + + void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar); + + void updatePresentPath(bool presentPathFastActive, + const gl::FramebufferAttachment *framebufferAttachment); + + const dx_VertexConstants11 &getVertexConstants() const { return mVertexConstants; } + const dx_PixelConstants11 &getPixelConstants() const { return mPixelConstants; } + + void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); + + void setShaderResource(gl::SamplerType shaderType, + UINT resourceSlot, + ID3D11ShaderResourceView *srv); + gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd); + + gl::Error syncFramebuffer(const gl::Framebuffer *framebuffer); + + void invalidateRenderTarget(); + void invalidateEverything(); + bool setRenderTargets(const RenderTargetArray &renderTargets, + ID3D11DepthStencilView *depthStencil); + void setRenderTarget(ID3D11RenderTargetView *renderTarget, + ID3D11DepthStencilView *depthStencil); + + private: + void unsetConflictingSRVs(gl::SamplerType shaderType, + uintptr_t resource, + const gl::ImageIndex &index); + void setViewportBounds(const int width, const int height); + + Renderer11 *mRenderer; + + // Blend State + bool mBlendStateIsDirty; + // TODO(dianx) temporary representation of a dirty bit. once we move enough states in, + // try experimenting with dirty bit instead of a bool + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + unsigned int mCurSampleMask; + + // Currently applied depth stencil state + bool mDepthStencilStateIsDirty; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + unsigned int mCurStencilSize; + Optional mCurDisableDepth; + Optional mCurDisableStencil; + + // Currently applied rasterizer state + bool mRasterizerStateIsDirty; + gl::RasterizerState mCurRasterState; + + // Currently applied scissor rectangle state + bool mScissorStateIsDirty; + bool mCurScissorEnabled; + gl::Rectangle mCurScissorRect; + + // Currently applied viewport state + bool mViewportStateIsDirty; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + + // Things needed in viewport state + dx_VertexConstants11 mVertexConstants; + dx_PixelConstants11 mPixelConstants; + + // Render target variables + gl::Extents mViewportBounds; + + // EGL_ANGLE_experimental_present_path variables + bool mCurPresentPathFastEnabled; + int mCurPresentPathFastColorBufferHeight; + + // Current RenderTarget state + std::array mAppliedRTVs; + uintptr_t mAppliedDSV; + + // Currently applied textures + struct SRVRecord + { + uintptr_t srv; + uintptr_t resource; + D3D11_SHADER_RESOURCE_VIEW_DESC desc; + }; + + // A cache of current SRVs that also tracks the highest 'used' (non-NULL) SRV + // We might want to investigate a more robust approach that is also fast when there's + // a large gap between used SRVs (e.g. if SRV 0 and 7 are non-NULL, this approach will + // waste time on SRVs 1-6.) + class SRVCache : angle::NonCopyable + { + public: + SRVCache() : mHighestUsedSRV(0) {} + + void initialize(size_t size) { mCurrentSRVs.resize(size); } + + size_t size() const { return mCurrentSRVs.size(); } + size_t highestUsed() const { return mHighestUsedSRV; } + + const SRVRecord &operator[](size_t index) const { return mCurrentSRVs[index]; } + void clear(); + void update(size_t resourceIndex, ID3D11ShaderResourceView *srv); + + private: + std::vector mCurrentSRVs; + size_t mHighestUsedSRV; + }; + + SRVCache mCurVertexSRVs; + SRVCache mCurPixelSRVs; + + // A block of NULL pointers, cached so we don't re-allocate every draw call + std::vector mNullSRVs; +}; + +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D11_STATEMANAGER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp index 0af2cf12c6..785a83cd77 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -7,46 +7,82 @@ // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" -#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#include + +#include "libANGLE/features.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" -#include "libANGLE/features.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "third_party/trace_event/trace_event.h" // Precompiled shaders #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +#ifdef ANGLE_ENABLE_KEYEDMUTEX +#define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX +#else +#define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED +#endif namespace rx { -SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), - SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), +namespace +{ +bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow nativeWindow, EGLint orientation) +{ + // We don't need an offscreen texture if either orientation = INVERT_Y, + // or present path fast is enabled and we're not rendering onto an offscreen surface. + return orientation != EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE && + !(renderer->presentPathFastEnabled() && nativeWindow.getNativeWindow()); +} +} // anonymous namespace + +SwapChain11::SwapChain11(Renderer11 *renderer, + NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) + : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), + mRenderer(renderer), + mWidth(-1), + mHeight(-1), + mOrientation(orientation), + mAppCreatedShareHandle(mShareHandle != nullptr), + mSwapInterval(0), + mPassThroughResourcesInit(false), + mFirstSwap(true), + mSwapChain(nullptr), +#if defined(ANGLE_ENABLE_D3D11_1) + mSwapChain1(nullptr), +#endif + mKeyedMutex(nullptr), + mBackBufferTexture(nullptr), + mBackBufferRTView(nullptr), + mBackBufferSRView(nullptr), + mNeedsOffscreenTexture(NeedsOffscreenTexture(renderer, nativeWindow, orientation)), + mOffscreenTexture(nullptr), + mOffscreenRTView(nullptr), + mOffscreenSRView(nullptr), + mDepthStencilTexture(nullptr), + mDepthStencilDSView(nullptr), + mDepthStencilSRView(nullptr), + mQuadVB(nullptr), + mPassThroughSampler(nullptr), + mPassThroughIL(nullptr), + mPassThroughVS(nullptr), + mPassThroughPS(nullptr), + mPassThroughRS(nullptr), mColorRenderTarget(this, renderer, false), mDepthStencilRenderTarget(this, renderer, true) { - mSwapChain = NULL; - mBackBufferTexture = NULL; - mBackBufferRTView = NULL; - mOffscreenTexture = NULL; - mOffscreenRTView = NULL; - mOffscreenSRView = NULL; - mDepthStencilTexture = NULL; - mDepthStencilDSView = NULL; - mDepthStencilSRView = NULL; - mQuadVB = NULL; - mPassThroughSampler = NULL; - mPassThroughIL = NULL; - mPassThroughVS = NULL; - mPassThroughPS = NULL; - mWidth = -1; - mHeight = -1; - mSwapInterval = 0; - mAppCreatedShareHandle = mShareHandle != NULL; - mPassThroughResourcesInit = false; + // Sanity check that if present path fast is active then we're using the default orientation + ASSERT(!mRenderer->presentPathFastEnabled() || orientation == 0); } SwapChain11::~SwapChain11() @@ -56,9 +92,14 @@ SwapChain11::~SwapChain11() void SwapChain11::release() { +#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mSwapChain1); +#endif SafeRelease(mSwapChain); + SafeRelease(mKeyedMutex); SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); + SafeRelease(mBackBufferSRView); SafeRelease(mOffscreenTexture); SafeRelease(mOffscreenRTView); SafeRelease(mOffscreenSRView); @@ -70,6 +111,7 @@ void SwapChain11::release() SafeRelease(mPassThroughIL); SafeRelease(mPassThroughVS); SafeRelease(mPassThroughPS); + SafeRelease(mPassThroughRS); if (!mAppCreatedShareHandle) { @@ -77,18 +119,48 @@ void SwapChain11::release() } } -void SwapChain11::releaseOffscreenTexture() +void SwapChain11::releaseOffscreenColorBuffer() { SafeRelease(mOffscreenTexture); SafeRelease(mOffscreenRTView); SafeRelease(mOffscreenSRView); +} + +void SwapChain11::releaseOffscreenDepthBuffer() +{ SafeRelease(mDepthStencilTexture); SafeRelease(mDepthStencilDSView); SafeRelease(mDepthStencilSRView); } -EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) +EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight) +{ + if (mNeedsOffscreenTexture) + { + EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight); + if (result != EGL_SUCCESS) + { + return result; + } + } + + EGLint result = resetOffscreenDepthBuffer(backbufferWidth, backbufferHeight); + if (result != EGL_SUCCESS) + { + return result; + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight) { + ASSERT(mNeedsOffscreenTexture); + + TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture"); ID3D11Device *device = mRenderer->getDevice(); ASSERT(device != NULL); @@ -106,9 +178,9 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei const int previousWidth = mWidth; const int previousHeight = mHeight; - releaseOffscreenTexture(); + releaseOffscreenColorBuffer(); - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel()); + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); // If the app passed in a share handle, open the resource // See EGL_ANGLE_d3d_share_handle_client_buffer @@ -164,7 +236,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; offscreenTextureDesc.CPUAccessFlags = 0; - offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0; + offscreenTextureDesc.MiscFlags = useSharedResource ? ANGLE_RESOURCE_SHARE_TYPE : 0; HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); @@ -210,6 +282,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } } + // This may return null if the original texture was created without a keyed mutex. + mKeyedMutex = d3d11::DynamicCastComObject(mOffscreenTexture); D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; @@ -230,10 +304,41 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); - const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getFeatureLevel()); + if (previousOffscreenTexture != nullptr) + { + D3D11_BOX sourceBox = {0}; + sourceBox.left = 0; + sourceBox.right = std::min(previousWidth, backbufferWidth); + sourceBox.top = std::max(previousHeight - backbufferHeight, 0); + sourceBox.bottom = previousHeight; + sourceBox.front = 0; + sourceBox.back = 1; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + const int yoffset = std::max(backbufferHeight - previousHeight, 0); + deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, + previousOffscreenTexture, 0, &sourceBox); + + SafeRelease(previousOffscreenTexture); + + if (mSwapChain) + { + swapRect(0, 0, backbufferWidth, backbufferHeight); + } + } + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight) +{ + releaseOffscreenDepthBuffer(); if (mDepthBufferFormat != GL_NONE) { + const d3d11::TextureFormat &depthBufferFormatInfo = + d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps()); + D3D11_TEXTURE2D_DESC depthStencilTextureDesc; depthStencilTextureDesc.Width = backbufferWidth; depthStencilTextureDesc.Height = backbufferHeight; @@ -253,7 +358,9 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei depthStencilTextureDesc.CPUAccessFlags = 0; depthStencilTextureDesc.MiscFlags = 0; - result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture); + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = + device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture); if (FAILED(result)) { ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); @@ -294,36 +401,12 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei } } - mWidth = backbufferWidth; - mHeight = backbufferHeight; - - if (previousOffscreenTexture != NULL) - { - D3D11_BOX sourceBox = {0}; - sourceBox.left = 0; - sourceBox.right = std::min(previousWidth, mWidth); - sourceBox.top = std::max(previousHeight - mHeight, 0); - sourceBox.bottom = previousHeight; - sourceBox.front = 0; - sourceBox.back = 1; - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - const int yoffset = std::max(mHeight - previousHeight, 0); - deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); - - SafeRelease(previousOffscreenTexture); - - if (mSwapChain) - { - swapRect(0, 0, mWidth, mHeight); - } - } - return EGL_SUCCESS; } EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) { + TRACE_EVENT0("gpu.angle", "SwapChain11::resize"); ID3D11Device *device = mRenderer->getDevice(); if (device == NULL) @@ -337,17 +420,30 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) return EGL_SUCCESS; } + // Don't resize unnecessarily + if (mWidth == backbufferWidth && mHeight == backbufferHeight) + { + return EGL_SUCCESS; + } + // Can only call resize if we have already created our swap buffer and resources - ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView); SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); + SafeRelease(mBackBufferSRView); // Resize swap chain DXGI_SWAP_CHAIN_DESC desc; - mSwapChain->GetDesc(&desc); - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel()); - HRESULT result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0); + HRESULT result = mSwapChain->GetDesc(&desc); + if (FAILED(result)) + { + ERR("Error reading swap chain description: 0x%08X", result); + release(); + return EGL_BAD_ALLOC; + } + + result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, getSwapChainNativeFormat(), 0); if (FAILED(result)) { @@ -369,20 +465,50 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) if (SUCCEEDED(result)) { d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); - } + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + } - result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); - ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) - { - d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource"); + } } - return resetOffscreenTexture(backbufferWidth, backbufferHeight); + mFirstSwap = true; + + return resetOffscreenBuffers(backbufferWidth, backbufferHeight); +} + +DXGI_FORMAT SwapChain11::getSwapChainNativeFormat() const +{ + // Return a render target format for offscreen rendering is supported by IDXGISwapChain. + // MSDN https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064(v=vs.85).aspx + return (mOffscreenRenderTargetFormat == GL_BGRA8_EXT) ? DXGI_FORMAT_B8G8R8A8_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM; } EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) { + mSwapInterval = static_cast(swapInterval); + if (mSwapInterval > 4) + { + // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] + // range + return EGL_BAD_PARAMETER; + } + + // If the swap chain already exists, just resize + if (mSwapChain != nullptr) + { + return resize(backbufferWidth, backbufferHeight); + } + + TRACE_EVENT0("gpu.angle", "SwapChain11::reset"); ID3D11Device *device = mRenderer->getDevice(); if (device == NULL) @@ -392,30 +518,24 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap // Release specific resources to free up memory for the new render target, while the // old render target still exists for the purpose of preserving its contents. +#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mSwapChain1); +#endif SafeRelease(mSwapChain); SafeRelease(mBackBufferTexture); SafeRelease(mBackBufferRTView); - mSwapInterval = static_cast(swapInterval); - if (mSwapInterval > 4) - { - // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range - return EGL_BAD_PARAMETER; - } - // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains if (backbufferWidth < 1 || backbufferHeight < 1) { - releaseOffscreenTexture(); + releaseOffscreenColorBuffer(); return EGL_SUCCESS; } if (mNativeWindow.getNativeWindow()) { - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel()); - HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(), - backbufferFormatInfo.texFormat, + getSwapChainNativeFormat(), backbufferWidth, backbufferHeight, &mSwapChain); if (FAILED(result)) @@ -433,6 +553,13 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap } } + if (mRenderer->getRenderer11DeviceCaps().supportsDXGI1_2) + { +#if defined(ANGLE_ENABLE_D3D11_1) + mSwapChain1 = d3d11::DynamicCastComObject(mSwapChain); +#endif + } + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); @@ -440,20 +567,25 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); - } - // If we are resizing the swap chain, we don't wish to recreate all the static resources - if (!mPassThroughResourcesInit) - { - mPassThroughResourcesInit = true; - initPassThroughResources(); + result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view"); } - return resetOffscreenTexture(backbufferWidth, backbufferHeight); + mFirstSwap = true; + + return resetOffscreenBuffers(backbufferWidth, backbufferHeight); } void SwapChain11::initPassThroughResources() { + if (mPassThroughResourcesInit) + { + return; + } + + TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources"); ID3D11Device *device = mRenderer->getDevice(); ASSERT(device != NULL); @@ -510,17 +642,58 @@ void SwapChain11::initPassThroughResources() result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS); ASSERT(SUCCEEDED(result)); d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); + + // Use the default rasterizer state but without culling + D3D11_RASTERIZER_DESC rasterizerDesc; + rasterizerDesc.FillMode = D3D11_FILL_SOLID; + rasterizerDesc.CullMode = D3D11_CULL_NONE; + rasterizerDesc.FrontCounterClockwise = FALSE; + rasterizerDesc.DepthBias = 0; + rasterizerDesc.SlopeScaledDepthBias = 0.0f; + rasterizerDesc.DepthBiasClamp = 0.0f; + rasterizerDesc.DepthClipEnable = TRUE; + rasterizerDesc.ScissorEnable = FALSE; + rasterizerDesc.MultisampleEnable = FALSE; + rasterizerDesc.AntialiasedLineEnable = FALSE; + result = device->CreateRasterizerState(&rasterizerDesc, &mPassThroughRS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughRS, "Swap chain pass through rasterizer state"); + + mPassThroughResourcesInit = true; } // parameters should be validated/clamped by caller EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (mNeedsOffscreenTexture) + { + EGLint result = copyOffscreenToBackbuffer(x, y, width, height); + if (result != EGL_SUCCESS) + { + return result; + } + } + + EGLint result = present(x, y, width, height); + if (result != EGL_SUCCESS) + { + return result; + } + + mRenderer->onSwap(); + + return EGL_SUCCESS; +} + +EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height) { if (!mSwapChain) { return EGL_SUCCESS; } - ID3D11Device *device = mRenderer->getDevice(); + initPassThroughResources(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); // Set vertices @@ -544,6 +717,16 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) float u2 = (x + width) / float(mWidth); float v2 = (y + height) / float(mHeight); + // Invert the quad vertices depending on the surface orientation. + if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0) + { + std::swap(x1, x2); + } + if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) != 0) + { + std::swap(y1, y2); + } + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); @@ -561,7 +744,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); - deviceContext->RSSetState(NULL); + deviceContext->RSSetState(mPassThroughRS); // Apply shaders deviceContext->IASetInputLayout(mPassThroughIL); @@ -577,30 +760,79 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) D3D11_VIEWPORT viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = mWidth; - viewport.Height = mHeight; + viewport.Width = static_cast(mWidth); + viewport.Height = static_cast(mHeight); viewport.MinDepth = 0.0f; viewport.MaxDepth = 1.0f; deviceContext->RSSetViewports(1, &viewport); // Apply textures - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); + auto stateManager = mRenderer->getStateManager(); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); // Draw deviceContext->Draw(4, 0); + // Rendering to the swapchain is now complete. Now we can call Present(). + // Before that, we perform any cleanup on the D3D device. We do this before Present() to make sure the + // cleanup is caught under the current eglSwapBuffers() PIX/Graphics Diagnostics call rather than the next one. + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); + + mRenderer->unapplyRenderTargets(); + mRenderer->markAllStateDirty(); + + return EGL_SUCCESS; +} + +EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + UINT swapInterval = mSwapInterval; #if ANGLE_VSYNC == ANGLE_DISABLED - result = mSwapChain->Present(0, 0); -#else - result = mSwapChain->Present(mSwapInterval, 0); + swapInterval = 0; #endif + HRESULT result = S_OK; + +#if defined(ANGLE_ENABLE_D3D11_1) + // Use IDXGISwapChain1::Present1 with a dirty rect if DXGI 1.2 is available. + if (mSwapChain1 != nullptr) + { + if (mFirstSwap) + { + // Can't swap with a dirty rect if this swap chain has never swapped before + DXGI_PRESENT_PARAMETERS params = {0, nullptr, nullptr, nullptr}; + result = mSwapChain1->Present1(swapInterval, 0, ¶ms); + } + else + { + RECT rect = {static_cast(x), static_cast(mHeight - y - height), + static_cast(x + width), static_cast(mHeight - y)}; + DXGI_PRESENT_PARAMETERS params = {1, &rect, nullptr, nullptr}; + result = mSwapChain1->Present1(swapInterval, 0, ¶ms); + } + } + else +#endif + { + result = mSwapChain->Present(swapInterval, 0); + } + + mFirstSwap = false; + + // Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render + // target. Mark it dirty. + mRenderer->getStateManager()->invalidateRenderTarget(); + if (result == DXGI_ERROR_DEVICE_REMOVED) { - HRESULT removedReason = device->GetDeviceRemovedReason(); - UNUSED_TRACE_VARIABLE(removedReason); - ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); + ERR("Present failed: the D3D11 device was removed: 0x%08X", + mRenderer->getDevice()->GetDeviceRemovedReason()); return EGL_CONTEXT_LOST; } else if (result == DXGI_ERROR_DEVICE_RESET) @@ -613,28 +845,24 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) ERR("Present failed with error code 0x%08X", result); } - // Unbind - mRenderer->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - - mRenderer->unapplyRenderTargets(); - mRenderer->markAllStateDirty(); + mNativeWindow.commitChange(); return EGL_SUCCESS; } ID3D11Texture2D *SwapChain11::getOffscreenTexture() { - return mOffscreenTexture; + return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture; } ID3D11RenderTargetView *SwapChain11::getRenderTarget() { - return mOffscreenRTView; + return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView; } ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() { - return mOffscreenSRView; + return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView; } ID3D11DepthStencilView *SwapChain11::getDepthStencil() @@ -652,12 +880,6 @@ ID3D11Texture2D *SwapChain11::getDepthStencilTexture() return mDepthStencilTexture; } -SwapChain11 *SwapChain11::makeSwapChain11(SwapChainD3D *swapChain) -{ - ASSERT(HAS_DYNAMIC_TYPE(SwapChain11*, swapChain)); - return static_cast(swapChain); -} - void SwapChain11::recreate() { // possibly should use this method instead of reset diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h index 48c808a261..adcd07adb0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h @@ -20,8 +20,12 @@ class Renderer11; class SwapChain11 : public SwapChainD3D { public: - SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat); + SwapChain11(Renderer11 *renderer, + NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation); virtual ~SwapChain11(); EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); @@ -42,29 +46,45 @@ class SwapChain11 : public SwapChainD3D EGLint getWidth() const { return mWidth; } EGLint getHeight() const { return mHeight; } + void *getKeyedMutex() override { return mKeyedMutex; } virtual void *getDevice(); - static SwapChain11 *makeSwapChain11(SwapChainD3D *swapChain); - private: void release(); void initPassThroughResources(); - void releaseOffscreenTexture(); - EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight); + + void releaseOffscreenColorBuffer(); + void releaseOffscreenDepthBuffer(); + EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight); + EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight); + EGLint resetOffscreenDepthBuffer(int backbufferWidth, int backbufferHeight); + + DXGI_FORMAT getSwapChainNativeFormat() const; + + EGLint copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height); + EGLint present(EGLint x, EGLint y, EGLint width, EGLint height); Renderer11 *mRenderer; - EGLint mHeight; EGLint mWidth; + EGLint mHeight; + const EGLint mOrientation; bool mAppCreatedShareHandle; unsigned int mSwapInterval; bool mPassThroughResourcesInit; + bool mFirstSwap; DXGISwapChain *mSwapChain; +#if defined(ANGLE_ENABLE_D3D11_1) + IDXGISwapChain1 *mSwapChain1; +#endif + IDXGIKeyedMutex *mKeyedMutex; ID3D11Texture2D *mBackBufferTexture; ID3D11RenderTargetView *mBackBufferRTView; + ID3D11ShaderResourceView *mBackBufferSRView; + const bool mNeedsOffscreenTexture; ID3D11Texture2D *mOffscreenTexture; ID3D11RenderTargetView *mOffscreenRTView; ID3D11ShaderResourceView *mOffscreenSRView; @@ -78,6 +98,7 @@ class SwapChain11 : public SwapChainD3D ID3D11InputLayout *mPassThroughIL; ID3D11VertexShader *mPassThroughVS; ID3D11PixelShader *mPassThroughPS; + ID3D11RasterizerState *mPassThroughRS; SurfaceRenderTarget11 mColorRenderTarget; SurfaceRenderTarget11 mDepthStencilRenderTarget; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp index 103e90fed3..11b9f76464 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp @@ -13,22 +13,27 @@ #include "common/MemoryBuffer.h" #include "common/utilities.h" -#include "libANGLE/ImageIndex.h" #include "libANGLE/formatutils.h" -#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/ImageIndex.h" #include "libANGLE/renderer/d3d/d3d11/Blit11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/renderer/d3d/d3d11/Image11.h" -#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" -#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" -#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" namespace rx { TextureStorage11::SwizzleCacheValue::SwizzleCacheValue() - : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE) + : swizzleRed(GL_INVALID_INDEX), + swizzleGreen(GL_INVALID_INDEX), + swizzleBlue(GL_INVALID_INDEX), + swizzleAlpha(GL_INVALID_INDEX) { } @@ -60,8 +65,8 @@ bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const return std::tie(baseLevel, mipLevels, swizzle) < std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle); } -TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags) - : mBindFlags(bindFlags), +TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags) + : mRenderer(renderer), mTopLevel(0), mMipLevels(0), mInternalFormat(GL_NONE), @@ -71,13 +76,13 @@ TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags) mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), mTextureWidth(0), mTextureHeight(0), - mTextureDepth(0) + mTextureDepth(0), + mBindFlags(bindFlags), + mMiscFlags(miscFlags) { - mRenderer = Renderer11::makeRenderer11(renderer); - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mLevelSRVs[i] = NULL; + mLevelSRVs[i] = nullptr; } } @@ -95,17 +100,11 @@ TextureStorage11::~TextureStorage11() mSrvCache.clear(); } -TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); - return static_cast(storage); -} - -DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget) +DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget) { UINT bindFlags = 0; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, featureLevel); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_SHADER_RESOURCE; @@ -122,11 +121,34 @@ DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_L return bindFlags; } +DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels) +{ + UINT miscFlags = 0; + + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); + if (renderTarget && levels > 1) + { + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); + + if (dxgiFormatInfo.nativeMipmapSupport(renderer11DeviceCaps.featureLevel)) + { + miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; + } + } + + return miscFlags; +} + UINT TextureStorage11::getBindFlags() const { return mBindFlags; } +UINT TextureStorage11::getMiscFlags() const +{ + return mMiscFlags; +} + int TextureStorage11::getTopLevel() const { return mTopLevel; @@ -142,6 +164,11 @@ bool TextureStorage11::isManaged() const return false; } +bool TextureStorage11::supportsNativeMipmapFunction() const +{ + return (mMiscFlags & D3D11_RESOURCE_MISC_GENERATE_MIPS) != 0; +} + int TextureStorage11::getLevelCount() const { return mMipLevels - mTopLevel; @@ -171,16 +198,17 @@ UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const return subresource; } -gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV) +gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState, + ID3D11ShaderResourceView **outSRV) { - bool swizzleRequired = samplerState.swizzleRequired(); - bool mipmapping = gl::IsMipmapFiltered(samplerState); - unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel + 1) : 1; + bool swizzleRequired = textureState.swizzleRequired(); + bool mipmapping = gl::IsMipmapFiltered(textureState.samplerState); + unsigned int mipLevels = mipmapping ? (textureState.maxLevel - textureState.baseLevel + 1) : 1; - // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) - mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel); + // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) + mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - textureState.baseLevel); - if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) { ASSERT(!swizzleRequired); ASSERT(mipLevels == 1 || mipLevels == mMipLevels); @@ -198,47 +226,47 @@ gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11S if (swizzleRequired) { - verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha); + verifySwizzleExists(textureState.swizzleRed, textureState.swizzleGreen, + textureState.swizzleBlue, textureState.swizzleAlpha); } - SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired); - SRVCache::const_iterator iter = mSrvCache.find(key); + SRVKey key(textureState.baseLevel, mipLevels, swizzleRequired); + auto iter = mSrvCache.find(key); if (iter != mSrvCache.end()) { *outSRV = iter->second; + return gl::Error(GL_NO_ERROR); } - else + + ID3D11Resource *texture = nullptr; + if (swizzleRequired) { - ID3D11Resource *texture = NULL; - if (swizzleRequired) - { - gl::Error error = getSwizzleTexture(&texture); - if (error.isError()) - { - return error; - } - } - else + gl::Error error = getSwizzleTexture(&texture); + if (error.isError()) { - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } + return error; } - - ID3D11ShaderResourceView *srv = NULL; - DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); - gl::Error error = createSRV(samplerState.baseLevel, mipLevels, format, texture, &srv); + } + else + { + gl::Error error = getResource(&texture); if (error.isError()) { return error; } + } - mSrvCache.insert(std::make_pair(key, srv)); - *outSRV = srv; + ID3D11ShaderResourceView *srv = nullptr; + DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); + gl::Error error = createSRV(textureState.baseLevel, mipLevels, format, texture, &srv); + if (error.isError()) + { + return error; } + mSrvCache.insert(std::make_pair(key, srv)); + *outSRV = srv; + return gl::Error(GL_NO_ERROR); } @@ -267,6 +295,56 @@ gl::Error TextureStorage11::getSRVLevel(int mipLevel, ID3D11ShaderResourceView * return gl::Error(GL_NO_ERROR); } +gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV) +{ + unsigned int mipLevels = maxLevel - baseLevel + 1; + + // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) + mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - baseLevel); + + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + ASSERT(mipLevels == 1 || mipLevels == mMipLevels); + } + + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + // We must ensure that the level zero texture is in sync with mipped texture. + gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1); + if (error.isError()) + { + return error; + } + } + + SRVKey key(baseLevel, mipLevels, false); + auto iter = mSrvCache.find(key); + if (iter != mSrvCache.end()) + { + *outSRV = iter->second; + return gl::Error(GL_NO_ERROR); + } + + ID3D11Resource *texture = nullptr; + gl::Error error = getResource(&texture); + if (error.isError()) + { + return error; + } + + ID3D11ShaderResourceView *srv = nullptr; + error = createSRV(baseLevel, mipLevels, mShaderResourceFormat, texture, &srv); + if (error.isError()) + { + return error; + } + + mSrvCache[key] = srv; + *outSRV = srv; + + return gl::Error(GL_NO_ERROR); +} + gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) { SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); @@ -427,7 +505,7 @@ gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, uns // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox should be NULL. D3D11_BOX srcBox; D3D11_BOX *pSrcBox = NULL; - if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) { // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless the source box // is specified. This is okay, since we don't perform CopySubresourceRegion on depth/stencil @@ -469,8 +547,8 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, co return error; } - ID3D11ShaderResourceView *sourceSRV = RenderTarget11::makeRenderTarget11(source)->getShaderResourceView(); - ID3D11RenderTargetView *destRTV = RenderTarget11::makeRenderTarget11(dest)->getRenderTargetView(); + ID3D11ShaderResourceView *sourceSRV = GetAs(source)->getShaderResourceView(); + ID3D11RenderTargetView *destRTV = GetAs(dest)->getRenderTargetView(); gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); @@ -479,8 +557,9 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, co gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); Blit11 *blitter = mRenderer->getBlitter(); - return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, - gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR); + return blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, + NULL, gl::GetInternalFormatInfo(source->getInternalFormat()).format, + GL_LINEAR, false); } void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) @@ -492,6 +571,30 @@ void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGree } } +void TextureStorage11::clearSRVCache() +{ + invalidateSwizzleCache(); + + auto iter = mSrvCache.begin(); + while (iter != mSrvCache.end()) + { + if (!iter->first.swizzle) + { + SafeRelease(iter->second); + iter = mSrvCache.erase(iter); + } + else + { + iter++; + } + } + + for (size_t level = 0; level < ArraySize(mLevelSRVs); level++) + { + SafeRelease(mLevelSRVs[level]); + } +} + gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) { ASSERT(destStorage); @@ -503,7 +606,7 @@ gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) return error; } - TextureStorage11 *dest11 = TextureStorage11::makeTextureStorage11(destStorage); + TextureStorage11 *dest11 = GetAs(destStorage); ID3D11Resource *destResource = NULL; error = dest11->getResource(&destResource); if (error.isError()) @@ -550,29 +653,43 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image int height = destBox ? destBox->height : static_cast(image->getHeight()); int depth = destBox ? destBox->depth : static_cast(image->getDepth()); UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength); - UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment, unpack.rowLength); + UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment, + unpack.rowLength, unpack.imageHeight); + GLsizei srcSkipBytes = internalFormatInfo.computeSkipPixels( + srcRowPitch, srcDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels); - const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getFeatureLevel()); + const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps()); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat); size_t outputPixelSize = dxgiFormatInfo.pixelBytes; - UINT bufferRowPitch = outputPixelSize * width; + UINT bufferRowPitch = static_cast(outputPixelSize) * width; UINT bufferDepthPitch = bufferRowPitch * height; size_t neededSize = bufferDepthPitch * depth; - MemoryBuffer *conversionBuffer = NULL; - error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer); - if (error.isError()) + MemoryBuffer *conversionBuffer = nullptr; + const uint8_t *data = nullptr; + + d3d11::LoadImageFunctionInfo loadFunctionInfo = d3d11Format.loadFunctions.at(type); + if (loadFunctionInfo.requiresConversion) { - return error; - } + error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer); + if (error.isError()) + { + return error; + } - // TODO: fast path - LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type); - loadFunction(width, height, depth, - pixelData, srcRowPitch, srcDepthPitch, - conversionBuffer->data(), bufferRowPitch, bufferDepthPitch); + loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch, + srcDepthPitch, conversionBuffer->data(), bufferRowPitch, + bufferDepthPitch); + data = conversionBuffer->data(); + } + else + { + data = pixelData + srcSkipBytes; + bufferRowPitch = srcRowPitch; + bufferDepthPitch = srcDepthPitch; + } ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); @@ -588,27 +705,25 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image destD3DBox.front = destBox->z; destD3DBox.back = destBox->z + destBox->depth; - immediateContext->UpdateSubresource(resource, destSubresource, - &destD3DBox, conversionBuffer->data(), + immediateContext->UpdateSubresource(resource, destSubresource, &destD3DBox, data, bufferRowPitch, bufferDepthPitch); } else { - immediateContext->UpdateSubresource(resource, destSubresource, - NULL, conversionBuffer->data(), - bufferRowPitch, bufferDepthPitch); + immediateContext->UpdateSubresource(resource, destSubresource, NULL, data, bufferRowPitch, + bufferDepthPitch); } return gl::Error(GL_NO_ERROR); } TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), + : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0), mTexture(swapchain->getOffscreenTexture()), - mSwizzleTexture(NULL), mLevelZeroTexture(NULL), mLevelZeroRenderTarget(NULL), - mUseLevelZeroTexture(false) + mUseLevelZeroTexture(false), + mSwizzleTexture(NULL) { mTexture->AddRef(); @@ -627,7 +742,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swap mTextureHeight = texDesc.Height; mTextureDepth = 1; - mInternalFormat = swapchain->GetBackBufferInternalFormat(); + mInternalFormat = swapchain->GetRenderTargetInternalFormat(); ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; @@ -640,23 +755,23 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swap mRenderTargetFormat = rtvDesc.Format; const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat, mRenderer->getFeatureLevel()); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat, mRenderer->getRenderer11DeviceCaps()); mSwizzleTextureFormat = formatInfo.swizzleTexFormat; mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - - initializeSerials(1, 1); } TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)), + : TextureStorage11(renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels)), mTexture(NULL), - mSwizzleTexture(NULL), mLevelZeroTexture(NULL), mLevelZeroRenderTarget(NULL), - mUseLevelZeroTexture(false) + mUseLevelZeroTexture(false), + mSwizzleTexture(NULL) { for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { @@ -667,7 +782,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalfo mInternalFormat = internalformat; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; mDepthStencilFormat = formatInfo.dsvFormat; @@ -688,8 +803,6 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalfo ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); mUseLevelZeroTexture = true; } - - initializeSerials(getLevelCount(), 1); } TextureStorage11_2D::~TextureStorage11_2D() @@ -726,17 +839,11 @@ TextureStorage11_2D::~TextureStorage11_2D() } } -TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); - return static_cast(storage); -} - gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage) { ASSERT(destStorage); - TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(destStorage); + TextureStorage11_2D *dest11 = GetAs(destStorage); if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) { @@ -989,7 +1096,7 @@ gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels) desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = getBindFlags(); desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; + desc.MiscFlags = getMiscFlags(); HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture); @@ -1004,6 +1111,8 @@ gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels) ASSERT(result == E_OUTOFMEMORY); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result); } + + d3d11::SetDebugName(*outputTexture, "TexStorage2D.Texture"); } return gl::Error(GL_NO_ERROR); @@ -1021,7 +1130,7 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the individual levels of the texture, // so methods like generateMipmap can't do anything useful with non-zero-level RTVs. // Therefore if level > 0 on 9_3 then there's almost certainly something wrong. - ASSERT(!(mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3 && level > 0)); + ASSERT(!(mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0)); if (!mRenderTarget[level]) { @@ -1170,6 +1279,8 @@ gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORM return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); } + d3d11::SetDebugName(*outSRV, "TexStorage2D.SRV"); + return gl::Error(GL_NO_ERROR); } @@ -1201,6 +1312,8 @@ gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); } + + d3d11::SetDebugName(mSwizzleTexture, "TexStorage2D.SwizzleTexture"); } *outTexture = mSwizzleTexture; @@ -1241,8 +1354,337 @@ gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11Render return gl::Error(GL_NO_ERROR); } +TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer, EGLImageD3D *eglImage) + : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0), + mImage(eglImage), + mCurrentRenderTarget(0), + mSwizzleTexture(nullptr), + mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS, nullptr) +{ + RenderTargetD3D *renderTargetD3D = nullptr; + mImage->getRenderTarget(&renderTargetD3D); + RenderTarget11 *renderTarget11 = GetAs(renderTargetD3D); + mCurrentRenderTarget = reinterpret_cast(renderTarget11); + + mMipLevels = 1; + mTextureFormat = renderTarget11->getDXGIFormat(); + mTextureWidth = renderTarget11->getWidth(); + mTextureHeight = renderTarget11->getHeight(); + mTextureDepth = 1; + mInternalFormat = renderTarget11->getInternalFormat(); + + ID3D11ShaderResourceView *srv = renderTarget11->getShaderResourceView(); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srv->GetDesc(&srvDesc); + mShaderResourceFormat = srvDesc.Format; + + ID3D11RenderTargetView *rtv = renderTarget11->getRenderTargetView(); + if (rtv != nullptr) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtv->GetDesc(&rtvDesc); + mRenderTargetFormat = rtvDesc.Format; + } + else + { + mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; + } + + ID3D11DepthStencilView *dsv = renderTarget11->getDepthStencilView(); + if (dsv != nullptr) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsv->GetDesc(&dsvDesc); + mDepthStencilFormat = dsvDesc.Format; + } + else + { + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; + } + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo( + dxgiFormatInfo.internalFormat, mRenderer->getRenderer11DeviceCaps()); + mSwizzleTextureFormat = formatInfo.swizzleTexFormat; + mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; + mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; +} + +TextureStorage11_EGLImage::~TextureStorage11_EGLImage() +{ + SafeRelease(mSwizzleTexture); + for (size_t i = 0; i < mSwizzleRenderTargets.size(); i++) + { + SafeRelease(mSwizzleRenderTargets[i]); + } +} + +gl::Error TextureStorage11_EGLImage::getResource(ID3D11Resource **outResource) +{ + gl::Error error = checkForUpdatedRenderTarget(); + if (error.isError()) + { + return error; + } + + RenderTarget11 *renderTarget11 = nullptr; + error = getImageRenderTarget(&renderTarget11); + if (error.isError()) + { + return error; + } + + *outResource = renderTarget11->getTexture(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_EGLImage::getSRV(const gl::TextureState &textureState, + ID3D11ShaderResourceView **outSRV) +{ + gl::Error error = checkForUpdatedRenderTarget(); + if (error.isError()) + { + return error; + } + + return TextureStorage11::getSRV(textureState, outSRV); +} + +gl::Error TextureStorage11_EGLImage::getMippedResource(ID3D11Resource **) +{ + // This shouldn't be called unless the zero max LOD workaround is active. + // EGL images are unavailable in this configuration. + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + ASSERT(index.mipIndex == 0); + UNUSED_ASSERTION_VARIABLE(index); + + gl::Error error = checkForUpdatedRenderTarget(); + if (error.isError()) + { + return error; + } + + return mImage->getRenderTarget(outRT); +} + +gl::Error TextureStorage11_EGLImage::copyToStorage(TextureStorage *destStorage) +{ + ID3D11Resource *sourceResouce = nullptr; + gl::Error error = getResource(&sourceResouce); + if (error.isError()) + { + return error; + } + + ASSERT(destStorage); + TextureStorage11_2D *dest11 = GetAs(destStorage); + ID3D11Resource *destResource = nullptr; + error = dest11->getResource(&destResource); + if (error.isError()) + { + return error; + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + immediateContext->CopyResource(destResource, sourceResouce); + + dest11->invalidateSwizzleCache(); + + return gl::Error(GL_NO_ERROR); +} + +void TextureStorage11_EGLImage::associateImage(Image11 *, const gl::ImageIndex &) +{ +} + +void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &, Image11 *) +{ +} + +bool TextureStorage11_EGLImage::isAssociatedImageValid(const gl::ImageIndex &, Image11 *) +{ + return false; +} + +gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::ImageIndex &, Image11 *) +{ + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(bool) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTexture) +{ + ASSERT(outTexture); + + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 1; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle texture, result: 0x%X.", result); + } + + d3d11::SetDebugName(mSwizzleTexture, "TexStorageEGLImage.SwizzleTexture"); + } + + *outTexture = mSwizzleTexture; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_EGLImage::getSwizzleRenderTarget(int mipLevel, + ID3D11RenderTargetView **outRTV) +{ + ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); + ASSERT(outRTV); + + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = NULL; + gl::Error error = getSwizzleTexture(&swizzleTexture); + if (error.isError()) + { + return error; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, + &mSwizzleRenderTargets[mipLevel]); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal swizzle render target view, result: 0x%X.", + result); + } + } + + *outRTV = mSwizzleRenderTargets[mipLevel]; + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget() +{ + RenderTarget11 *renderTarget11 = nullptr; + gl::Error error = getImageRenderTarget(&renderTarget11); + if (error.isError()) + { + return error; + } + + if (mCurrentRenderTarget != reinterpret_cast(renderTarget11)) + { + clearSRVCache(); + mCurrentRenderTarget = reinterpret_cast(renderTarget11); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const +{ + ASSERT(baseLevel == 0); + ASSERT(mipLevels == 1); + ASSERT(outSRV); + + // Create a new SRV only for the swizzle texture. Otherwise just return the Image's + // RenderTarget's SRV. + if (texture == mSwizzleTexture) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2D.MipLevels = mipLevels; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + + ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to create internal texture storage SRV, result: 0x%X.", + result); + } + + d3d11::SetDebugName(*outSRV, "TexStorageEGLImage.SRV"); + } + else + { + RenderTarget11 *renderTarget = nullptr; + gl::Error error = getImageRenderTarget(&renderTarget); + if (error.isError()) + { + return error; + } + + ASSERT(texture == renderTarget->getTexture()); + + *outSRV = renderTarget->getShaderResourceView(); + (*outSRV)->AddRef(); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage11_EGLImage::getImageRenderTarget(RenderTarget11 **outRT) const +{ + RenderTargetD3D *renderTargetD3D = nullptr; + gl::Error error = mImage->getRenderTarget(&renderTargetD3D); + if (error.isError()) + { + return error; + } + + *outRT = GetAs(renderTargetD3D); + return gl::Error(GL_NO_ERROR); +} + TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)) + : TextureStorage11(renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels)) { mTexture = NULL; mSwizzleTexture = NULL; @@ -1267,7 +1709,7 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum intern mInternalFormat = internalformat; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; mDepthStencilFormat = formatInfo.dsvFormat; @@ -1291,8 +1733,6 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum intern ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); mUseLevelZeroTexture = true; } - - initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT); } TextureStorage11_Cube::~TextureStorage11_Cube() @@ -1334,12 +1774,6 @@ TextureStorage11_Cube::~TextureStorage11_Cube() } } -TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); - return static_cast(storage); -} - UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const { if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && index.mipIndex == 0) @@ -1363,7 +1797,7 @@ gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage) { ASSERT(destStorage); - TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(destStorage); + TextureStorage11_Cube *dest11 = GetAs(destStorage); if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) { @@ -1643,7 +2077,7 @@ gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels) desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = getBindFlags(); desc.CPUAccessFlags = 0; - desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags(); HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture); @@ -1658,6 +2092,8 @@ gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels) ASSERT(result == E_OUTOFMEMORY); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result); } + + d3d11::SetDebugName(*outputTexture, "TexStorageCube.Texture"); } return gl::Error(GL_NO_ERROR); @@ -1721,7 +2157,7 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re srvDesc.Texture2DArray.FirstArraySlice = faceIndex; srvDesc.Texture2DArray.ArraySize = 1; - if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3) + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) { srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; } @@ -1739,6 +2175,8 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); } + d3d11::SetDebugName(srv, "TexStorageCube.RenderTargetSRV"); + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; @@ -1758,6 +2196,8 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); } + d3d11::SetDebugName(rtv, "TexStorageCube.RenderTargetRTV"); + mRenderTarget[faceIndex][level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); // RenderTarget will take ownership of these resources @@ -1784,6 +2224,8 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal depth stencil view for texture storage, result: 0x%X.", result); } + d3d11::SetDebugName(dsv, "TexStorageCube.RenderTargetDSV"); + mRenderTarget[faceIndex][level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); // RenderTarget will take ownership of these resources @@ -1815,7 +2257,7 @@ gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FO { srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.MipLevels = mipLevels; srvDesc.Texture2DArray.FirstArraySlice = 0; srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; } @@ -1857,6 +2299,8 @@ gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FO return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); } + d3d11::SetDebugName(*outSRV, "TexStorageCube.SRV"); + return gl::Error(GL_NO_ERROR); } @@ -1888,6 +2332,8 @@ gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); } + + d3d11::SetDebugName(*outTexture, "TexStorageCube.SwizzleTexture"); } *outTexture = mSwizzleTexture; @@ -1932,7 +2378,9 @@ gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11Rend TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)) + : TextureStorage11(renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels)) { mTexture = NULL; mSwizzleTexture = NULL; @@ -1946,7 +2394,7 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalfo mInternalFormat = internalformat; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; mDepthStencilFormat = formatInfo.dsvFormat; @@ -1962,8 +2410,6 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalfo mTextureWidth = width; mTextureHeight = height; mTextureDepth = depth; - - initializeSerials(getLevelCount() * depth, depth); } TextureStorage11_3D::~TextureStorage11_3D() @@ -1999,12 +2445,6 @@ TextureStorage11_3D::~TextureStorage11_3D() } } -TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage)); - return static_cast(storage); -} - void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &index) { GLint level = index.mipIndex; @@ -2101,7 +2541,7 @@ gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource) desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = getBindFlags(); desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; + desc.MiscFlags = getMiscFlags(); HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture); @@ -2116,6 +2556,8 @@ gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource) ASSERT(result == E_OUTOFMEMORY); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result); } + + d3d11::SetDebugName(mTexture, "TexStorage3D.Texture"); } *outResource = mTexture; @@ -2142,6 +2584,8 @@ gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORM return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); } + d3d11::SetDebugName(*outSRV, "TexStorage3D.SRV"); + return gl::Error(GL_NO_ERROR); } @@ -2189,6 +2633,8 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); } + d3d11::SetDebugName(rtv, "TexStorage3D.RTV"); + mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0); // RenderTarget will take ownership of these resources @@ -2236,6 +2682,8 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend } ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(rtv, "TexStorage3D.LayerRTV"); + mLevelLayerRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); // RenderTarget will take ownership of these resources @@ -2274,6 +2722,8 @@ gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); } + + d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleTexture"); } *outTexture = mSwizzleTexture; @@ -2310,6 +2760,8 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle render target view, result: 0x%X.", result); } + + d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleRTV"); } *outRTV = mSwizzleRenderTargets[mipLevel]; @@ -2318,7 +2770,9 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)) + : TextureStorage11(renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels)) { mTexture = NULL; mSwizzleTexture = NULL; @@ -2330,7 +2784,7 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum mInternalFormat = internalformat; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel()); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); mTextureFormat = formatInfo.texFormat; mShaderResourceFormat = formatInfo.srvFormat; mDepthStencilFormat = formatInfo.dsvFormat; @@ -2346,8 +2800,6 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum mTextureWidth = width; mTextureHeight = height; mTextureDepth = depth; - - initializeSerials(getLevelCount() * depth, depth); } TextureStorage11_2DArray::~TextureStorage11_2DArray() @@ -2383,12 +2835,6 @@ TextureStorage11_2DArray::~TextureStorage11_2DArray() mRenderTargets.clear(); } -TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage)); - return static_cast(storage); -} - void TextureStorage11_2DArray::associateImage(Image11* image, const gl::ImageIndex &index) { GLint level = index.mipIndex; @@ -2486,7 +2932,7 @@ gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource) desc.Usage = D3D11_USAGE_DEFAULT; desc.BindFlags = getBindFlags(); desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; + desc.MiscFlags = getMiscFlags(); HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); @@ -2501,6 +2947,8 @@ gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource) ASSERT(result == E_OUTOFMEMORY); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result); } + + d3d11::SetDebugName(mTexture, "TexStorage2DArray.Texture"); } *outResource = mTexture; @@ -2527,6 +2975,8 @@ gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal texture storage SRV, result: 0x%X.", result); } + d3d11::SetDebugName(*outSRV, "TexStorage2DArray.SRV"); + return gl::Error(GL_NO_ERROR); } @@ -2569,6 +3019,8 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); } + d3d11::SetDebugName(srv, "TexStorage2DArray.RenderTargetSRV"); + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; @@ -2588,6 +3040,8 @@ gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); } + d3d11::SetDebugName(rtv, "TexStorage2DArray.RenderTargetRTV"); + mRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); // RenderTarget will take ownership of these resources @@ -2631,6 +3085,8 @@ gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTextur { return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal swizzle texture, result: 0x%X.", result); } + + d3d11::SetDebugName(*outTexture, "TexStorage2DArray.SwizzleTexture"); } *outTexture = mSwizzleTexture; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h index 456e2660f9..a88db2f0af 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h @@ -23,25 +23,28 @@ struct ImageIndex; namespace rx { +class EGLImageD3D; class RenderTargetD3D; class RenderTarget11; class Renderer11; class SwapChain11; class Image11; +struct Renderer11DeviceCaps; class TextureStorage11 : public TextureStorage { public: virtual ~TextureStorage11(); - static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); - - static DWORD GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget); + static DWORD GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget); + static DWORD GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels); UINT getBindFlags() const; + UINT getMiscFlags() const; virtual gl::Error getResource(ID3D11Resource **outResource) = 0; - virtual gl::Error getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV); + virtual gl::Error getSRV(const gl::TextureState &textureState, + ID3D11ShaderResourceView **outSRV); virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); @@ -49,6 +52,7 @@ class TextureStorage11 : public TextureStorage virtual int getTopLevel() const; virtual bool isRenderTarget() const; virtual bool isManaged() const; + bool supportsNativeMipmapFunction() const override; virtual int getLevelCount() const; virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; @@ -71,8 +75,10 @@ class TextureStorage11 : public TextureStorage virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, const gl::PixelUnpackState &unpack, const uint8_t *pixelData); + gl::Error getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV); + protected: - TextureStorage11(Renderer11 *renderer, UINT bindFlags); + TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags); int getLevelWidth(int mipLevel) const; int getLevelHeight(int mipLevel) const; int getLevelDepth(int mipLevel) const; @@ -89,6 +95,9 @@ class TextureStorage11 : public TextureStorage void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + // Clear all cached non-swizzle SRVs and invalidate the swizzle cache. + void clearSRVCache(); + Renderer11 *mRenderer; int mTopLevel; unsigned int mMipLevels; @@ -122,6 +131,7 @@ class TextureStorage11 : public TextureStorage private: const UINT mBindFlags; + const UINT mMiscFlags; struct SRVKey { @@ -146,8 +156,6 @@ class TextureStorage11_2D : public TextureStorage11 TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false); virtual ~TextureStorage11_2D(); - static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); - virtual gl::Error getResource(ID3D11Resource **outResource); virtual gl::Error getMippedResource(ID3D11Resource **outResource); virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); @@ -194,14 +202,58 @@ class TextureStorage11_2D : public TextureStorage11 Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; +class TextureStorage11_EGLImage final : public TextureStorage11 +{ + public: + TextureStorage11_EGLImage(Renderer11 *renderer, EGLImageD3D *eglImage); + ~TextureStorage11_EGLImage() override; + + gl::Error getResource(ID3D11Resource **outResource) override; + gl::Error getSRV(const gl::TextureState &textureState, + ID3D11ShaderResourceView **outSRV) override; + gl::Error getMippedResource(ID3D11Resource **outResource) override; + gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override; + + gl::Error copyToStorage(TextureStorage *destStorage) override; + + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + bool isAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11 *incomingImage) override; + + gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override; + + protected: + gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override; + + private: + // Check if the EGL image's render target has been updated due to orphaning and delete + // any SRVs and other resources based on the image's old render target. + gl::Error checkForUpdatedRenderTarget(); + + gl::Error createSRV(int baseLevel, + int mipLevels, + DXGI_FORMAT format, + ID3D11Resource *texture, + ID3D11ShaderResourceView **outSRV) const override; + + gl::Error getImageRenderTarget(RenderTarget11 **outRT) const; + + EGLImageD3D *mImage; + uintptr_t mCurrentRenderTarget; + + // Swizzle-related variables + ID3D11Texture2D *mSwizzleTexture; + std::vector mSwizzleRenderTargets; +}; + class TextureStorage11_Cube : public TextureStorage11 { public: TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); virtual ~TextureStorage11_Cube(); - static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); - virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; virtual gl::Error getResource(ID3D11Resource **outResource); @@ -250,8 +302,6 @@ class TextureStorage11_3D : public TextureStorage11 GLsizei width, GLsizei height, GLsizei depth, int levels); virtual ~TextureStorage11_3D(); - static TextureStorage11_3D *makeTextureStorage11_3D(TextureStorage *storage); - virtual gl::Error getResource(ID3D11Resource **outResource); // Handles both layer and non-layer RTs @@ -290,8 +340,6 @@ class TextureStorage11_2DArray : public TextureStorage11 GLsizei width, GLsizei height, GLsizei depth, int levels); virtual ~TextureStorage11_2DArray(); - static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage); - virtual gl::Error getResource(ID3D11Resource **outResource); virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h index f232ad7e8e..4741e81601 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h @@ -31,7 +31,9 @@ class Trim11 : angle::NonCopyable private: Renderer11 *mRenderer; +#if defined (ANGLE_ENABLE_WINDOWS_STORE) EventRegistrationToken mApplicationSuspendedEventToken; +#endif void trim(); bool registerForRendererTrimRequest(); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h index 78aad7d106..b397140e71 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h @@ -19,20 +19,11 @@ class Renderer11; class VertexArray11 : public VertexArrayImpl { public: - VertexArray11(Renderer11 *renderer) - : VertexArrayImpl(), - mRenderer(renderer) + VertexArray11(const gl::VertexArray::Data &data) + : VertexArrayImpl(data) { } - virtual ~VertexArray11() { } - - virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } - virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } - virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } - virtual void enableAttribute(size_t idx, bool enabledState) { } - - private: - Renderer11 *mRenderer; + virtual ~VertexArray11() {} }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp index adc64cef5e..098cefcd53 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -7,11 +7,14 @@ // VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" -#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" -#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + #include "libANGLE/Buffer.h" #include "libANGLE/VertexAttribute.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" namespace rx { @@ -53,6 +56,15 @@ gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) { return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); } + + if (dynamicUsage) + { + d3d11::SetDebugName(mBuffer, "VertexBuffer11 (dynamic)"); + } + else + { + d3d11::SetDebugName(mBuffer, "VertexBuffer11 (static)"); + } } mBufferSize = size; @@ -61,12 +73,6 @@ gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) return gl::Error(GL_NO_ERROR); } -VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); - return static_cast(vetexBuffer); -} - gl::Error VertexBuffer11::mapResource() { if (mMappedResourceData == NULL) @@ -98,16 +104,20 @@ void VertexBuffer11::hintUnmapResource() } } -gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset) +gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) { if (!mBuffer) { return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); } - gl::Buffer *buffer = attrib.buffer.get(); - int inputStride = ComputeVertexAttributeStride(attrib); + int inputStride = static_cast(ComputeVertexAttributeStride(attrib)); // This will map the resource if it isn't already mapped. gl::Error error = mapResource(); @@ -118,36 +128,16 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri uint8_t *output = mMappedResourceData + offset; - const uint8_t *input = NULL; - if (attrib.enabled) - { - if (buffer) - { - BufferD3D *storage = GetImplAs(buffer); - error = storage->getData(&input); - if (error.isError()) - { - return error; - } - input += static_cast(attrib.offset); - } - else - { - input = static_cast(attrib.pointer); - } - } - else - { - input = reinterpret_cast(currentValue.FloatValues); - } + const uint8_t *input = sourceData; if (instances == 0 || attrib.divisor == 0) { input += inputStride * start; } - gl::VertexFormat vertexFormat(attrib, currentValue.Type); - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mRenderer->getFeatureLevel()); + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType); + const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel; + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel); ASSERT(vertexFormatInfo.copyFunction != NULL); vertexFormatInfo.copyFunction(input, inputStride, count, output); @@ -170,8 +160,9 @@ gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GL elementCount = UnsignedCeilDivide(static_cast(instances), attrib.divisor); } - gl::VertexFormat vertexFormat(attrib); - const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mRenderer->getFeatureLevel()); + gl::VertexFormatType formatType = gl::GetVertexFormatType(attrib); + const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel; + const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(formatType, featureLevel); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat); unsigned int elementSize = dxgiFormatInfo.pixelBytes; if (elementSize <= std::numeric_limits::max() / elementCount) diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h index 2450e8955c..773c4474e1 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h @@ -25,10 +25,13 @@ class VertexBuffer11 : public VertexBuffer virtual gl::Error initialize(unsigned int size, bool dynamicUsage); - static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); - - virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset); + gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) override; virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl index 60678d7b9f..1ec21dee55 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl @@ -245,17 +245,17 @@ static inline void CopyPackedRGB(uint32_t data, uint8_t *output) if (data & rgbSignMask) { - *intOutput = data | negativeMask; + *intOutput = static_cast(data | negativeMask); } else { - *intOutput = data; + *intOutput = static_cast(data); } } else { GLushort *uintOutput = reinterpret_cast(output); - *uintOutput = data; + *uintOutput = static_cast(data); } } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json new file mode 100644 index 0000000000..e81b4deea5 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_data.json @@ -0,0 +1,1164 @@ +[ + { + "DXGI_FORMAT_UNKNOWN": + { + "texture2D": "never", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32B32A32_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32B32A32_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32B32A32_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32B32A32_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32B32_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32B32_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "11_0check", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32B32_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32B32_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16B16A16_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16B16A16_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16B16A16_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16B16A16_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16B16A16_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16B16A16_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G32_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32G8X24_TYPELESS": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_D32_FLOAT_S8X24_UINT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "check", + "depthStencil": "always" + }, + "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R10G10B10A2_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R10G10B10A2_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R10G10B10A2_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R11G11B10_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8B8A8_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8B8A8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8B8A8_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8B8A8_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8B8A8_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16G16_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_D32_FLOAT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "check", + "depthStencil": "always" + }, + "DXGI_FORMAT_R32_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R32_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R24G8_TYPELESS": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_D24_UNORM_S8_UINT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "check", + "depthStencil": "always" + }, + "DXGI_FORMAT_R24_UNORM_X8_TYPELESS": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "10_0check10_1always", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_X24_TYPELESS_G8_UINT": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16_FLOAT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_D16_UNORM": + { + "texture2D": "always", + "texture3D": "never", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "check", + "depthStencil": "always" + }, + "DXGI_FORMAT_R16_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R16_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8_UINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8_SINT": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_A8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R1_UNORM": + { + "texture2D": "always", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R9G9B9E5_SHAREDEXP": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_R8G8_B8G8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_G8R8_G8B8_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC1_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC1_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC1_UNORM_SRGB": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC2_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC2_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC2_UNORM_SRGB": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC3_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC3_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC3_UNORM_SRGB": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC4_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC4_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC4_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC5_TYPELESS": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC5_UNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC5_SNORM": + { + "texture2D": "always", + "texture3D": "always", + "textureCube": "always", + "shaderSample": "10_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_B5G6R5_UNORM": + { + "texture2D": "dxgi1_2", + "texture3D": "dxgi1_2", + "textureCube": "dxgi1_2", + "shaderSample": "dxgi1_2", + "renderTarget": "dxgi1_2", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_B5G5R5A1_UNORM": + { + "texture2D": "dxgi1_2", + "texture3D": "dxgi1_2", + "textureCube": "dxgi1_2", + "shaderSample": "dxgi1_2", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_B8G8R8A8_UNORM": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "10_0check11_0always", + "renderTarget": "10_0check11_0always", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_B8G8R8X8_UNORM": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "10_0check11_0always", + "renderTarget": "11_0", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_B8G8R8A8_TYPELESS": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "10_0check11_0always", + "renderTarget": "11_0", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_B8G8R8X8_TYPELESS": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB": + { + "texture2D": "check", + "texture3D": "check", + "textureCube": "check", + "shaderSample": "10_0check11_0always", + "renderTarget": "11_0", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC6H_TYPELESS": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC6H_UF16": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "11_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC6H_SF16": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "11_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC7_TYPELESS": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC7_UNORM": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "11_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_BC7_UNORM_SRGB": + { + "texture2D": "11_0", + "texture3D": "11_0", + "textureCube": "11_0", + "shaderSample": "11_0", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_AYUV": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_Y410": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_Y416": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_NV12": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_P010": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_P016": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_420_OPAQUE": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_YUY2": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_Y210": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_Y216": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_NV11": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "11_1", + "renderTarget": "11_1", + "multisampleRT": "check", + "depthStencil": "never" + }, + "DXGI_FORMAT_AI44": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_IA44": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_P8": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_A8P8": + { + "texture2D": "11_1", + "texture3D": "never", + "textureCube": "never", + "shaderSample": "never", + "renderTarget": "never", + "multisampleRT": "never", + "depthStencil": "never" + }, + "DXGI_FORMAT_B4G4R4A4_UNORM": + { + "texture2D": "dxgi1_2", + "texture3D": "dxgi1_2", + "textureCube": "dxgi1_2", + "shaderSample": "dxgi1_2", + "renderTarget": "check", + "multisampleRT": "check", + "depthStencil": "never" + } + } +] diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp new file mode 100644 index 0000000000..cbc36445e6 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.cpp @@ -0,0 +1,1846 @@ +// GENERATED FILE - DO NOT EDIT. See dxgi_support_data.json. +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// dxgi_support_table: +// Queries for DXGI support of various texture formats. Depends on DXGI +// version, D3D feature level, and is sometimes guaranteed or optional. +// + +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" + +#include "common/debug.h" + +namespace rx +{ + +namespace d3d11 +{ + +#define F_2D D3D11_FORMAT_SUPPORT_TEXTURE2D +#define F_3D D3D11_FORMAT_SUPPORT_TEXTURE3D +#define F_CUBE D3D11_FORMAT_SUPPORT_TEXTURECUBE +#define F_SAMPLE D3D11_FORMAT_SUPPORT_SHADER_SAMPLE +#define F_RT D3D11_FORMAT_SUPPORT_RENDER_TARGET +#define F_MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET +#define F_DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL + +namespace +{ + +const DXGISupport &GetDefaultSupport() +{ + static UINT AllSupportFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | + D3D11_FORMAT_SUPPORT_TEXTURE3D | + D3D11_FORMAT_SUPPORT_TEXTURECUBE | + D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | + D3D11_FORMAT_SUPPORT_RENDER_TARGET | + D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET | + D3D11_FORMAT_SUPPORT_DEPTH_STENCIL; + static const DXGISupport defaultSupport(0, 0, AllSupportFlags); + return defaultSupport; +} + +const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_AI44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_AYUV: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G6R5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM: + { + static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_BC1_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_SF16: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC6H_UF16: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_D16_UNORM: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_G8R8_G8B8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_IA44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_NV11: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + { + static const DXGISupport info(0, F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D); + return info; + } + case DXGI_FORMAT_R11G11B10_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R1_UNORM: + { + static const DXGISupport info(F_2D, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT, F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32G32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS, F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT, F_SAMPLE); + return info; + } + case DXGI_FORMAT_R32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_B8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R8G8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_UNKNOWN: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y210: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } +} + +const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_AI44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_AYUV: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G6R5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM: + { + static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + return info; + } + case DXGI_FORMAT_BC1_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_SF16: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC6H_UF16: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM_SRGB: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_D16_UNORM: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_G8R8_G8B8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_IA44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_NV11: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + { + static const DXGISupport info(0, F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D); + return info; + } + case DXGI_FORMAT_R11G11B10_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R1_UNORM: + { + static const DXGISupport info(F_2D, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_B8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R8G8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_UNKNOWN: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y210: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } +} + +const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_AI44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_AYUV: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_B5G6R5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + static const DXGISupport info(F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + { + static const DXGISupport info(F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM: + { + static const DXGISupport info(F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + { + static const DXGISupport info(F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_BC1_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC1_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC2_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC3_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC4_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC5_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC5_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_SF16: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC6H_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC6H_UF16: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_BC7_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_D16_UNORM: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_G8R8_G8B8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_IA44: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_NV11: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_RT | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + { + static const DXGISupport info(0, F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, F_2D | F_3D); + return info; + } + case DXGI_FORMAT_R11G11B10_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16G16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R16_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R16_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R1_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32B32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32G32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R32_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_B8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R8G8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8G8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R8_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_R8_UINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_UNKNOWN: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y210: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } +} + +} + +#undef F_2D +#undef F_3D +#undef F_CUBE +#undef F_SAMPLE +#undef F_RT +#undef F_MS +#undef F_DS + +const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_10_0: + return GetDXGISupport_10_0(dxgiFormat); + case D3D_FEATURE_LEVEL_10_1: + return GetDXGISupport_10_1(dxgiFormat); + case D3D_FEATURE_LEVEL_11_0: + return GetDXGISupport_11_0(dxgiFormat); + default: + return GetDefaultSupport(); + } +} + +} // namespace d3d11 + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h new file mode 100644 index 0000000000..1d8d68565e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h @@ -0,0 +1,44 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// dxgi_support_table: +// Queries for DXGI support of various texture formats. Depends on DXGI +// version, D3D feature level, and is sometimes guaranteed or optional. +// + +#include "common/platform.h" + +namespace rx +{ + +namespace d3d11 +{ + +struct DXGISupport +{ + DXGISupport() + : alwaysSupportedFlags(0), + neverSupportedFlags(0), + optionallySupportedFlags(0) + { + } + + DXGISupport(UINT alwaysSupportedIn, UINT neverSupportedIn, UINT optionallySupportedIn) + : alwaysSupportedFlags(alwaysSupportedIn), + neverSupportedFlags(neverSupportedIn), + optionallySupportedFlags(optionallySupportedIn) + { + } + + UINT alwaysSupportedFlags; + UINT neverSupportedFlags; + UINT optionallySupportedFlags; +}; + +const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel); + +} // namespace d3d11 + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp index 2f81d6d608..f073e9f46f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp @@ -10,11 +10,13 @@ #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" #include "libANGLE/formatutils.h" -#include "libANGLE/renderer/Renderer.h" #include "libANGLE/renderer/d3d/copyimage.h" +#include "libANGLE/renderer/d3d/d3d11/copyvertex.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/generatemip.h" #include "libANGLE/renderer/d3d/loadimage.h" -#include "libANGLE/renderer/d3d/d3d11/copyvertex.h" +#include "libANGLE/renderer/Renderer.h" namespace rx { @@ -99,6 +101,10 @@ static DXGIToESFormatMap BuildDXGIToESFormatMap() AddDXGIToESEntry(&map, DXGI_FORMAT_BC2_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); AddDXGIToESEntry(&map, DXGI_FORMAT_BC3_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + AddDXGIToESEntry(&map, DXGI_FORMAT_B5G6R5_UNORM, GL_RGB565); + AddDXGIToESEntry(&map, DXGI_FORMAT_B5G5R5A1_UNORM, GL_RGB5_A1); + AddDXGIToESEntry(&map, DXGI_FORMAT_B4G4R4A4_UNORM, GL_RGBA4); + return map; } @@ -210,6 +216,10 @@ static ColorFormatInfoMap BuildColorFormatInfoMap() InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 9, 9, 9, 0, 5); InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R11G11B10_FLOAT, 11, 11, 10, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B5G6R5_UNORM, 5, 6, 5, 0, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B4G4R4A4_UNORM, 4, 4, 4, 4, 0); + InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B5G5R5A1_UNORM, 5, 5, 5, 1, 0); + return map; } @@ -278,8 +288,20 @@ DXGIFormat::DXGIFormat() componentType(GL_NONE), mipGenerationFunction(NULL), colorReadFunction(NULL), - fastCopyFunctions() + fastCopyFunctions(), + nativeMipmapSupport(NULL) +{ +} + +static bool NeverSupported(D3D_FEATURE_LEVEL) +{ + return false; +} + +template +static bool RequiresFeatureLevel(D3D_FEATURE_LEVEL featureLevel) { + return featureLevel >= requiredFeatureLevel; } ColorCopyFunction DXGIFormat::getFastCopyFunction(GLenum format, GLenum type) const @@ -289,7 +311,7 @@ ColorCopyFunction DXGIFormat::getFastCopyFunction(GLenum format, GLenum type) co } void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, - GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc) + GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc, NativeMipmapGenerationSupportFunction nativeMipmapSupport) { DXGIFormat info; info.pixelBytes = pixelBits / 8; @@ -301,11 +323,11 @@ void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelB if (colorInfoIter != colorInfoMap.end()) { const DXGIColorFormatInfo &colorInfo = colorInfoIter->second; - info.redBits = colorInfo.redBits; - info.greenBits = colorInfo.greenBits; - info.blueBits = colorInfo.blueBits; - info.alphaBits = colorInfo.alphaBits; - info.sharedBits = colorInfo.sharedBits; + info.redBits = static_cast(colorInfo.redBits); + info.greenBits = static_cast(colorInfo.greenBits); + info.blueBits = static_cast(colorInfo.blueBits); + info.alphaBits = static_cast(colorInfo.alphaBits); + info.sharedBits = static_cast(colorInfo.sharedBits); } static const DepthStencilInfoMap dsInfoMap = BuildDepthStencilInfoMap(); @@ -335,6 +357,8 @@ void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelB info.fastCopyFunctions.insert(std::make_pair(std::make_pair(i->second.destFormat, i->second.destType), i->second.copyFunction)); } + info.nativeMipmapSupport = nativeMipmapSupport; + map->insert(std::make_pair(dxgiFormat, info)); } @@ -343,80 +367,86 @@ static DXGIFormatInfoMap BuildDXGIFormatInfoMap() { DXGIFormatInfoMap map; - // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function - AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL); - - AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); - - AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL); - - AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function | Native mipmap function + AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL, NeverSupported); + + AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, RequiresFeatureLevel); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor , RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor , RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor, RequiresFeatureLevel); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip, ReadColor, NeverSupported); + + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor, NeverSupported); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor, RequiresFeatureLevel); + + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip, ReadColor, RequiresFeatureLevel); + + AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor, RequiresFeatureLevel); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL, NeverSupported); + + AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); + + // B5G6R5 in D3D11 is treated the same as R5G6B5 in D3D9, so reuse the R5G6B5 functions used by the D3D9 renderer. + // The same applies to B4G4R4A4 and B5G5R5A1 with A4R4G4B4 and A1R5G5B5 respectively. + AddDXGIFormat(&map, DXGI_FORMAT_B5G6R5_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, RequiresFeatureLevel); + AddDXGIFormat(&map, DXGI_FORMAT_B4G4R4A4_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_B5G5R5A1_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor, NeverSupported); // Useful formats for vertex buffers - AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); - AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL, NeverSupported); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL, NeverSupported); return map; } @@ -436,613 +466,8 @@ const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format) } } -struct SwizzleSizeType -{ - size_t maxComponentSize; - GLenum componentType; - - SwizzleSizeType() - : maxComponentSize(0), componentType(GL_NONE) - { } - - SwizzleSizeType(size_t maxComponentSize, GLenum componentType) - : maxComponentSize(maxComponentSize), componentType(componentType) - { } - - bool operator<(const SwizzleSizeType& other) const - { - return (maxComponentSize != other.maxComponentSize) ? (maxComponentSize < other.maxComponentSize) - : (componentType < other.componentType); - } -}; - -struct SwizzleFormatInfo -{ - DXGI_FORMAT mTexFormat; - DXGI_FORMAT mSRVFormat; - DXGI_FORMAT mRTVFormat; - - SwizzleFormatInfo() - : mTexFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN) - { } - - SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat) - : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat) - { } -}; - -typedef std::map SwizzleInfoMap; -typedef std::pair SwizzleInfoPair; - -static SwizzleInfoMap BuildSwizzleInfoMap() -{ - SwizzleInfoMap map; - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM))); - map.insert(SwizzleInfoPair(SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_SIGNED_NORMALIZED ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM ))); - - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT ))); - - map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT ))); - map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT ))); - - return map; -} - -typedef std::pair InternalFormatInitializerPair; -typedef std::map InternalFormatInitializerMap; - -static InternalFormatInitializerMap BuildInternalFormatInitializerMap() -{ - InternalFormatInitializerMap map; - - map.insert(InternalFormatInitializerPair(GL_RGB8, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB565, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_SRGB8, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB16F, Initialize4ComponentData)); - map.insert(InternalFormatInitializerPair(GL_RGB32F, Initialize4ComponentData)); - map.insert(InternalFormatInitializerPair(GL_RGB8UI, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB8I, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB16UI, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB16I, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB32UI, Initialize4ComponentData )); - map.insert(InternalFormatInitializerPair(GL_RGB32I, Initialize4ComponentData )); - - return map; -} - -// ES3 image loading functions vary based on the internal format and data type given, -// this map type determines the loading function from the internal format and type supplied -// to glTex*Image*D and the destination DXGI_FORMAT. Source formats and types are taken from -// Tables 3.2 and 3.3 of the ES 3 spec. -typedef std::pair TypeLoadFunctionPair; -typedef std::map > D3D11LoadFunctionMap; - -static void UnimplementedLoadFunction(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - UNIMPLEMENTED(); -} - -static void UnreachableLoadFunction(size_t width, size_t height, size_t depth, - const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, - uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) -{ - UNREACHABLE(); -} - -// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters. -static inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type, - LoadImageFunction loadFunc) -{ - (*map)[internalFormat].push_back(TypeLoadFunctionPair(type, loadFunc)); -} - -D3D11LoadFunctionMap BuildD3D11_FL9_3_LoadFunctionMap() -{ - D3D11LoadFunctionMap map; - - // From GL_EXT_texture_storage. Also used by GL_ALPHA8 - // On feature level 9_3, A8_UNORM doesn't support mipmaps, so we must use RGBA8 instead - InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8); - - return map; -} - -D3D11LoadFunctionMap BuildD3D11_FL10_0Plus_LoadFunctionMap() -{ - D3D11LoadFunctionMap map; - - // From GL_EXT_texture_storage. Also used by GL_ALPHA8 - InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadToNative); - - return map; -} - -D3D11LoadFunctionMap BuildBaseD3D11LoadFunctionMap() -{ - D3D11LoadFunctionMap map; - - // | Internal format | Type | Load function | - InsertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA8_SNORM, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, LoadRGBA4ToRGBA8 ); - InsertLoadFunction(&map, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); - InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, LoadRGB5A1ToRGBA8 ); - InsertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_INT_2_10_10_10_REV, LoadRGB10A2ToRGBA8 ); - InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT_OES, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA32F, GL_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA16F, GL_FLOAT, Load32FTo16F<4> ); - InsertLoadFunction(&map, GL_RGBA8UI, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA8I, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA16UI, GL_UNSIGNED_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA16I, GL_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA32UI, GL_UNSIGNED_INT, LoadToNative ); - InsertLoadFunction(&map, GL_RGBA32I, GL_INT, LoadToNative ); - InsertLoadFunction(&map, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); - InsertLoadFunction(&map, GL_RGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_SRGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB8_SNORM, GL_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, LoadR5G6B5ToRGBA8 ); - InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, LoadToNative ); - InsertLoadFunction(&map, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, LoadToNative ); - InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT, LoadToNative3To4); - InsertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT_OES, LoadToNative3To4); - InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT, LoadRGB16FToRG11B10F ); - InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT_OES, LoadRGB16FToRG11B10F ); - InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT, LoadRGB16FToRGB9E5 ); - InsertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT_OES, LoadRGB16FToRGB9E5 ); - InsertLoadFunction(&map, GL_RGB32F, GL_FLOAT, LoadToNative3To4); - InsertLoadFunction(&map, GL_RGB16F, GL_FLOAT, LoadRGB32FToRGBA16F ); - InsertLoadFunction(&map, GL_R11F_G11F_B10F, GL_FLOAT, LoadRGB32FToRG11B10F ); - InsertLoadFunction(&map, GL_RGB9_E5, GL_FLOAT, LoadRGB32FToRGB9E5 ); - InsertLoadFunction(&map, GL_RGB8UI, GL_UNSIGNED_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB8I, GL_BYTE, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB16UI, GL_UNSIGNED_SHORT, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB16I, GL_SHORT, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB32UI, GL_UNSIGNED_INT, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RGB32I, GL_INT, LoadToNative3To4 ); - InsertLoadFunction(&map, GL_RG8, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RG8_SNORM, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT_OES, LoadToNative ); - InsertLoadFunction(&map, GL_RG32F, GL_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_RG16F, GL_FLOAT, Load32FTo16F<2> ); - InsertLoadFunction(&map, GL_RG8UI, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RG8I, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_RG16UI, GL_UNSIGNED_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_RG16I, GL_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_RG32UI, GL_UNSIGNED_INT, LoadToNative ); - InsertLoadFunction(&map, GL_RG32I, GL_INT, LoadToNative ); - InsertLoadFunction(&map, GL_R8, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_R8_SNORM, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT_OES, LoadToNative ); - InsertLoadFunction(&map, GL_R32F, GL_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_R16F, GL_FLOAT, Load32FTo16F<1> ); - InsertLoadFunction(&map, GL_R8UI, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_R8I, GL_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_R16UI, GL_UNSIGNED_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_R16I, GL_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_R32UI, GL_UNSIGNED_INT, LoadToNative ); - InsertLoadFunction(&map, GL_R32I, GL_INT, LoadToNative ); - InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, LoadToNative ); - InsertLoadFunction(&map, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, LoadR32ToR24G8 ); - InsertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_INT, LoadR32ToR16 ); - InsertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT, LoadToNative ); - InsertLoadFunction(&map, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, LoadR32ToR24G8 ); - InsertLoadFunction(&map, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, LoadToNative ); - - // Unsized formats - // Load functions are unreachable because they are converted to sized internal formats based on - // the format and type before loading takes place. - InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - InsertLoadFunction(&map, GL_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); - - // From GL_OES_texture_float - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, LoadLA32FToRGBA32F ); - InsertLoadFunction(&map, GL_LUMINANCE, GL_FLOAT, LoadL32FToRGBA32F ); - InsertLoadFunction(&map, GL_ALPHA, GL_FLOAT, LoadA32FToRGBA32F ); - - // From GL_OES_texture_half_float - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT, LoadL16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); - InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT, LoadA16FToRGBA16F ); - InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); - - // From GL_EXT_texture_storage - // GL_ALPHA8_EXT GL_UNSIGNED_BYTE is in the feature-level-specific load function maps, due to differences between 9_3 and 10_0+ - InsertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 ); - InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 ); - InsertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F ); - InsertLoadFunction(&map, GL_LUMINANCE32F_EXT, GL_FLOAT, LoadL32FToRGBA32F ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA32F_EXT, GL_FLOAT, LoadLA32FToRGBA32F ); - InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT, LoadA16FToRGBA16F ); - InsertLoadFunction(&map, GL_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT, LoadL16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE16F_EXT, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); - InsertLoadFunction(&map, GL_LUMINANCE_ALPHA16F_EXT, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); - - // From GL_ANGLE_depth_texture - InsertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES, GL_UNSIGNED_INT, LoadR32ToR24G8 ); - - // From GL_EXT_texture_format_BGRA8888 - InsertLoadFunction(&map, GL_BGRA8_EXT, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, LoadRGBA4ToRGBA8 ); - InsertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); - InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, LoadRGB5A1ToRGBA8 ); - InsertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); - - // Compressed formats - // From ES 3.0.1 spec, table 3.16 - // | Internal format | Type | Load function | - InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - InsertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); - - // From GL_EXT_texture_compression_dxt1 - InsertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); - InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); - - // From GL_ANGLE_texture_compression_dxt3 - InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); - - // From GL_ANGLE_texture_compression_dxt5 - InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); - - return map; -} - -// For sized GL internal formats, there is only one corresponding D3D11 format. This map type allows -// querying for the DXGI texture formats to use for textures, SRVs, RTVs and DSVs given a GL internal -// format. -typedef std::map D3D11ES3FormatMap; - -TextureFormat::TextureFormat() - : texFormat(DXGI_FORMAT_UNKNOWN), - srvFormat(DXGI_FORMAT_UNKNOWN), - rtvFormat(DXGI_FORMAT_UNKNOWN), - dsvFormat(DXGI_FORMAT_UNKNOWN), - renderFormat(DXGI_FORMAT_UNKNOWN), - swizzleTexFormat(DXGI_FORMAT_UNKNOWN), - swizzleSRVFormat(DXGI_FORMAT_UNKNOWN), - swizzleRTVFormat(DXGI_FORMAT_UNKNOWN), - dataInitializerFunction(NULL), - loadFunctions() -{ -} - -static inline void InsertD3D11FormatInfoBase(D3D11ES3FormatMap *formatMap, const D3D11LoadFunctionMap &flLoadFunctions, GLenum internalFormat, DXGI_FORMAT texFormat, - DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) -{ - TextureFormat info; - info.texFormat = texFormat; - info.srvFormat = srvFormat; - info.rtvFormat = rtvFormat; - info.dsvFormat = dsvFormat; - - // Given a GL internal format, the renderFormat is the DSV format if it is depth- or stencil-renderable, - // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise. - if (dsvFormat != DXGI_FORMAT_UNKNOWN) - { - info.renderFormat = dsvFormat; - } - else if (rtvFormat != DXGI_FORMAT_UNKNOWN) - { - info.renderFormat = rtvFormat; - } - else if (texFormat != DXGI_FORMAT_UNKNOWN) - { - info.renderFormat = texFormat; - } - else - { - info.renderFormat = DXGI_FORMAT_UNKNOWN; - } - - // Compute the swizzle formats - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0) - { - if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN || - srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN) - { - // Get the maximum sized component - unsigned int maxBits = 1; - if (formatInfo.compressed) - { - unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8; - unsigned int blockSize = formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight; - maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits); - } - else - { - maxBits = std::max(maxBits, formatInfo.alphaBits); - maxBits = std::max(maxBits, formatInfo.redBits); - maxBits = std::max(maxBits, formatInfo.greenBits); - maxBits = std::max(maxBits, formatInfo.blueBits); - maxBits = std::max(maxBits, formatInfo.luminanceBits); - maxBits = std::max(maxBits, formatInfo.depthBits); - } - - maxBits = roundUp(maxBits, 8U); - - static const SwizzleInfoMap swizzleMap = BuildSwizzleInfoMap(); - SwizzleInfoMap::const_iterator swizzleIter = swizzleMap.find(SwizzleSizeType(maxBits, formatInfo.componentType)); - ASSERT(swizzleIter != swizzleMap.end()); - - const SwizzleFormatInfo &swizzleInfo = swizzleIter->second; - info.swizzleTexFormat = swizzleInfo.mTexFormat; - info.swizzleSRVFormat = swizzleInfo.mSRVFormat; - info.swizzleRTVFormat = swizzleInfo.mRTVFormat; - } - else - { - // The original texture format is suitable for swizzle operations - info.swizzleTexFormat = texFormat; - info.swizzleSRVFormat = srvFormat; - info.swizzleRTVFormat = rtvFormat; - } - } - else - { - // Not possible to swizzle with this texture format since it is either unsized or GL_NONE - info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN; - info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN; - info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN; - } - - // Check if there is an initialization function for this texture format - static const InternalFormatInitializerMap initializerMap = BuildInternalFormatInitializerMap(); - InternalFormatInitializerMap::const_iterator initializerIter = initializerMap.find(internalFormat); - info.dataInitializerFunction = (initializerIter != initializerMap.end()) ? initializerIter->second : NULL; - - // Gather all the load functions for this internal format from the base list - static const D3D11LoadFunctionMap loadFunctions = BuildBaseD3D11LoadFunctionMap(); - D3D11LoadFunctionMap::const_iterator loadFunctionIter = loadFunctions.find(internalFormat); - if (loadFunctionIter != loadFunctions.end()) - { - const std::vector &loadFunctionVector = loadFunctionIter->second; - for (size_t i = 0; i < loadFunctionVector.size(); i++) - { - GLenum type = loadFunctionVector[i].first; - LoadImageFunction function = loadFunctionVector[i].second; - info.loadFunctions.insert(std::make_pair(type, function)); - } - } - - // Gather load functions for this internal format from the feature-level-specific list - D3D11LoadFunctionMap::const_iterator flLoadFunctionIter = flLoadFunctions.find(internalFormat); - if (flLoadFunctionIter != flLoadFunctions.end()) - { - const std::vector &flLoadFunctionVector = flLoadFunctionIter->second; - for (size_t i = 0; i < flLoadFunctionVector.size(); i++) - { - GLenum type = flLoadFunctionVector[i].first; - LoadImageFunction function = flLoadFunctionVector[i].second; - info.loadFunctions.insert(std::make_pair(type, function)); - } - } - - formatMap->insert(std::make_pair(internalFormat, info)); -} - -static inline void InsertD3D11_FL9_3_FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, - DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) -{ - static const D3D11LoadFunctionMap flLoadFunctions = BuildD3D11_FL9_3_LoadFunctionMap(); - InsertD3D11FormatInfoBase(map, flLoadFunctions, internalFormat, texFormat, srvFormat, rtvFormat, dsvFormat); -} - -static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, - DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) -{ - static const D3D11LoadFunctionMap flLoadFunctions = BuildD3D11_FL10_0Plus_LoadFunctionMap(); - InsertD3D11FormatInfoBase(map, flLoadFunctions, internalFormat, texFormat, srvFormat, rtvFormat, dsvFormat); -} - -static D3D11ES3FormatMap BuildD3D11_FL9_3FormatOverrideMap() -{ - // D3D11 Feature Level 9_3 doesn't support as many texture formats as Feature Level 10_0+. - // In particular, it doesn't support: - // - mipmaps on DXGI_FORMAT_A8_NORM - // - *_TYPELESS formats - // - DXGI_FORMAT_D32_FLOAT_S8X24_UINT or DXGI_FORMAT_D32_FLOAT - - D3D11ES3FormatMap map; - - // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format - InsertD3D11_FL9_3_FormatInfo(&map, GL_ALPHA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11_FL9_3_FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT16, DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM); - InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT24, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); - InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT32F, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH24_STENCIL8, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); - InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH32F_STENCIL8, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11_FL9_3_FormatInfo(&map, GL_STENCIL_INDEX8, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); - - return map; -} - -static D3D11ES3FormatMap BuildD3D11FormatMap() -{ - D3D11ES3FormatMap map; - - // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - InsertD3D11FormatInfo(&map, GL_NONE, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R8, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG8, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB565, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA4, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB5_A1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA8, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB10_A2, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB10_A2UI, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_SRGB8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_SRGB8_ALPHA8, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R16F, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG16F, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA16F, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R32F, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG32F, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA32F, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R11F_G11F_B10F, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB9_E5, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R8I, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R8UI, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R16I, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R16UI, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R32I, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_R32UI, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG8I, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG8UI, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG16I, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG16UI, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG32I, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RG32UI, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA8I, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA8UI, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA16I, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA16UI, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA32I, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA32UI, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN); - - // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would it change the DXGI format? - InsertD3D11FormatInfo(&map, GL_ALPHA, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_LUMINANCE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGB, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_RGBA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_BGRA_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN); - - // From GL_EXT_texture_storage - // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE8_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_LUMINANCE_ALPHA16F_EXT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_BGRA8_EXT, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_BGRA4_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - InsertD3D11FormatInfo(&map, GL_BGR5_A1_ANGLEX, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ); - - // Depth stencil formats - InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT16, DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM ); - InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT24, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); - InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32F, DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT ); - InsertD3D11FormatInfo(&map, GL_DEPTH24_STENCIL8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); - InsertD3D11FormatInfo(&map, GL_DEPTH32F_STENCIL8, DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT_S8X24_UINT); - InsertD3D11FormatInfo(&map, GL_STENCIL_INDEX8, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ); - - // From GL_ANGLE_depth_texture - // Since D3D11 doesn't have a D32_UNORM format, use D24S8 which has comparable precision and matches the ES3 format. - InsertD3D11FormatInfo(&map, GL_DEPTH_COMPONENT32_OES, DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT); - - // Compressed formats, From ES 3.0.1 spec, table 3.16 - // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - InsertD3D11FormatInfo(&map, GL_COMPRESSED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_R11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SIGNED_RG11_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - - // From GL_EXT_texture_compression_dxt1 - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - - // From GL_ANGLE_texture_compression_dxt3 - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - - // From GL_ANGLE_texture_compression_dxt5 - InsertD3D11FormatInfo(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN); - - return map; -} - -const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel) -{ - static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap(); - static const D3D11ES3FormatMap formatMapFL9_3Override = BuildD3D11_FL9_3FormatOverrideMap(); - - if (featureLevel == D3D_FEATURE_LEVEL_9_3) - { - // First see if the internalFormat has a special map for FL9_3 - D3D11ES3FormatMap::const_iterator fl9_3Iter = formatMapFL9_3Override.find(internalFormat); - if (fl9_3Iter != formatMapFL9_3Override.end()) - { - return fl9_3Iter->second; - } - } - - D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); - if (iter != formatMap.end()) - { - return iter->second; - } - else - { - static const TextureFormat defaultInfo; - return defaultInfo; - } -} - -typedef std::map D3D11VertexFormatInfoMap; -typedef std::pair D3D11VertexFormatPair; +typedef std::map D3D11VertexFormatInfoMap; +typedef std::pair D3D11VertexFormatPair; VertexFormat::VertexFormat() : conversionType(VERTEX_CONVERT_NONE), @@ -1051,30 +476,31 @@ VertexFormat::VertexFormat() { } -static void AddVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLboolean normalized, GLuint componentCount, - VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) +VertexFormat::VertexFormat(VertexConversionType conversionTypeIn, + DXGI_FORMAT nativeFormatIn, + VertexCopyFunction copyFunctionIn) + : conversionType(conversionTypeIn), + nativeFormat(nativeFormatIn), + copyFunction(copyFunctionIn) { - gl::VertexFormat inputFormat(inputType, normalized, componentCount, false); - - VertexFormat info; - info.conversionType = conversionType; - info.nativeFormat = nativeFormat; - info.copyFunction = copyFunction; - - map->insert(D3D11VertexFormatPair(inputFormat, info)); } -static void AddIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLuint componentCount, - VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) +static void AddVertexFormatInfo(D3D11VertexFormatInfoMap *map, + GLenum inputType, + GLboolean normalized, + GLuint componentCount, + VertexConversionType conversionType, + DXGI_FORMAT nativeFormat, + VertexCopyFunction copyFunction) { - gl::VertexFormat inputFormat(inputType, GL_FALSE, componentCount, true); + gl::VertexFormatType formatType = gl::GetVertexFormatType(inputType, normalized, componentCount, false); VertexFormat info; info.conversionType = conversionType; info.nativeFormat = nativeFormat; info.copyFunction = copyFunction; - map->insert(D3D11VertexFormatPair(inputFormat, info)); + map->insert(D3D11VertexFormatPair(formatType, info)); } static D3D11VertexFormatInfoMap BuildD3D11_FL9_3VertexFormatInfoOverrideMap() @@ -1139,187 +565,536 @@ static D3D11VertexFormatInfoMap BuildD3D11_FL9_3VertexFormatInfoOverrideMap() return map; } -static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() +const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D3D_FEATURE_LEVEL featureLevel) { - D3D11VertexFormatInfoMap map; + if (featureLevel == D3D_FEATURE_LEVEL_9_3) + { + static const D3D11VertexFormatInfoMap vertexFormatMapFL9_3Override = + BuildD3D11_FL9_3VertexFormatInfoOverrideMap(); - // TODO: column legend + // First see if the format has a special mapping for FL9_3 + auto iter = vertexFormatMapFL9_3Override.find(vertexFormatType); + if (iter != vertexFormatMapFL9_3Override.end()) + { + return iter->second; + } + } - // - // Float formats - // + switch (vertexFormatType) + { + // + // Float formats + // - // GL_BYTE -- un-normalized - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + // GL_BYTE -- un-normalized + case gl::VERTEX_FORMAT_SBYTE1: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SBYTE2: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SBYTE3: + { + static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SBYTE4: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + return info; + } - // GL_BYTE -- normalized - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); + // GL_BYTE -- normalized + case gl::VERTEX_FORMAT_SBYTE1_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SBYTE2_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SBYTE3_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SBYTE4_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData); + return info; + } - // GL_UNSIGNED_BYTE -- un-normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + // GL_UNSIGNED_BYTE -- un-normalized + case gl::VERTEX_FORMAT_UBYTE1: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UBYTE2: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UBYTE3: + { + static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UBYTE4: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + return info; + } - // GL_UNSIGNED_BYTE -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); + // GL_UNSIGNED_BYTE -- normalized + case gl::VERTEX_FORMAT_UBYTE1_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UBYTE2_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UBYTE3_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UBYTE4_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); + return info; + } - // GL_SHORT -- un-normalized - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + // GL_SHORT -- un-normalized + case gl::VERTEX_FORMAT_SSHORT1: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SSHORT2: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SSHORT3: + { + static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SSHORT4: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + return info; + } - // GL_SHORT -- normalized - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); + // GL_SHORT -- normalized + case gl::VERTEX_FORMAT_SSHORT1_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SSHORT2_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SSHORT3_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SSHORT4_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData); + return info; + } - // GL_UNSIGNED_SHORT -- un-normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + // GL_UNSIGNED_SHORT -- un-normalized + case gl::VERTEX_FORMAT_USHORT1: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_USHORT2: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_USHORT3: + { + static const VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_USHORT4: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + return info; + } - // GL_UNSIGNED_SHORT -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); - - // GL_INT -- un-normalized - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); - - // GL_INT -- normalized - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); - - // GL_UNSIGNED_INT -- un-normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData); - - // GL_UNSIGNED_INT -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); + // GL_UNSIGNED_SHORT -- normalized + case gl::VERTEX_FORMAT_USHORT1_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_USHORT2_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_USHORT3_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_USHORT4_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData); + return info; + } - // GL_FIXED - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1, 1>); - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2, 2>); - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3, 3>); - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4, 4>); + // GL_INT -- un-normalized + case gl::VERTEX_FORMAT_SINT1: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT2: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT3: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT4: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); + return info; + } - // GL_HALF_FLOAT - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); + // GL_INT -- normalized + case gl::VERTEX_FORMAT_SINT1_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT2_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT3_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT4_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); + return info; + } - // GL_FLOAT - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData); - - // GL_INT_2_10_10_10_REV - AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); - AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); - - // GL_UNSIGNED_INT_2_10_10_10_REV - AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData); - - // - // Integer Formats - // - - // GL_BYTE - AddIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); - - // GL_UNSIGNED_BYTE - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); - - // GL_SHORT - AddIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); - - // GL_UNSIGNED_SHORT - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); - - // GL_INT - AddIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); - - // GL_UNSIGNED_INT - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); - - // GL_INT_2_10_10_10_REV - AddIntegerVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData); - - // GL_UNSIGNED_INT_2_10_10_10_REV - AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData); + // GL_UNSIGNED_INT -- un-normalized + case gl::VERTEX_FORMAT_UINT1: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT2: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT3: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT4: + { + static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData); + return info; + } - return map; -} + // GL_UNSIGNED_INT -- normalized + case gl::VERTEX_FORMAT_UINT1_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT2_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT3_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT4_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); + return info; + } -const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D_FEATURE_LEVEL featureLevel) -{ - static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap(); - static const D3D11VertexFormatInfoMap vertexFormatMapFL9_3Override = BuildD3D11_FL9_3VertexFormatInfoOverrideMap(); + // GL_FIXED + case gl::VERTEX_FORMAT_FIXED1: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1, 1>); + return info; + } + case gl::VERTEX_FORMAT_FIXED2: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2, 2>); + return info; + } + case gl::VERTEX_FORMAT_FIXED3: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3, 3>); + return info; + } + case gl::VERTEX_FORMAT_FIXED4: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4, 4>); + return info; + } - if (featureLevel == D3D_FEATURE_LEVEL_9_3) - { - // First see if the format has a special mapping for FL9_3 - D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMapFL9_3Override.find(vertexFormat); - if (iter != vertexFormatMapFL9_3Override.end()) + // GL_HALF_FLOAT + case gl::VERTEX_FORMAT_HALF1: { - return iter->second; + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_HALF2: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_HALF3: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_HALF4: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData); + return info; } - } - D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat); - if (iter != vertexFormatMap.end()) - { - return iter->second; - } - else - { - static const VertexFormat defaultInfo; - return defaultInfo; + // GL_FLOAT + case gl::VERTEX_FORMAT_FLOAT1: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_FLOAT2: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_FLOAT3: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_FLOAT4: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData); + return info; + } + + // GL_INT_2_10_10_10_REV + case gl::VERTEX_FORMAT_SINT210: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT210_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); + return info; + } + + // GL_UNSIGNED_INT_2_10_10_10_REV + case gl::VERTEX_FORMAT_UINT210: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT210_NORM: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData); + return info; + } + + // + // Integer Formats + // + + // GL_BYTE + case gl::VERTEX_FORMAT_SBYTE1_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SBYTE2_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SBYTE3_INT: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SBYTE4_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData); + return info; + } + + // GL_UNSIGNED_BYTE + case gl::VERTEX_FORMAT_UBYTE1_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UBYTE2_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UBYTE3_INT: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UBYTE4_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); + return info; + } + + // GL_SHORT + case gl::VERTEX_FORMAT_SSHORT1_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SSHORT2_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SSHORT3_INT: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SSHORT4_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData); + return info; + } + + // GL_UNSIGNED_SHORT + case gl::VERTEX_FORMAT_USHORT1_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_USHORT2_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_USHORT3_INT: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_USHORT4_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData); + return info; + } + + // GL_INT + case gl::VERTEX_FORMAT_SINT1_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT2_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT3_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_SINT4_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); + return info; + } + + // GL_UNSIGNED_INT + case gl::VERTEX_FORMAT_UINT1_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT2_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT3_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData); + return info; + } + case gl::VERTEX_FORMAT_UINT4_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData); + return info; + } + + // GL_INT_2_10_10_10_REV + case gl::VERTEX_FORMAT_SINT210_INT: + { + static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData); + return info; + } + + // GL_UNSIGNED_INT_2_10_10_10_REV + case gl::VERTEX_FORMAT_UINT210_INT: + { + static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData); + return info; + } + + default: + { + static const VertexFormat info; + return info; + } } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h index 33fe29dc39..7b97527140 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h @@ -10,20 +10,22 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ -#include "libANGLE/renderer/d3d/formatutilsD3D.h" -#include "libANGLE/angletypes.h" +#include #include "common/platform.h" - -#include +#include "libANGLE/angletypes.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" namespace rx { +struct Renderer11DeviceCaps; namespace d3d11 { typedef std::map, ColorCopyFunction> FastCopyFunctionMap; +typedef bool (*NativeMipmapGenerationSupportFunction)(D3D_FEATURE_LEVEL); struct DXGIFormat { @@ -51,43 +53,29 @@ struct DXGIFormat ColorReadFunction colorReadFunction; FastCopyFunctionMap fastCopyFunctions; - ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; -}; -const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format); - -struct TextureFormat -{ - TextureFormat(); - DXGI_FORMAT texFormat; - DXGI_FORMAT srvFormat; - DXGI_FORMAT rtvFormat; - DXGI_FORMAT dsvFormat; - DXGI_FORMAT renderFormat; + NativeMipmapGenerationSupportFunction nativeMipmapSupport; - DXGI_FORMAT swizzleTexFormat; - DXGI_FORMAT swizzleSRVFormat; - DXGI_FORMAT swizzleRTVFormat; - - InitializeTextureDataFunction dataInitializerFunction; - - typedef std::map LoadFunctionMap; - LoadFunctionMap loadFunctions; + ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; }; -const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel); +const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format); struct VertexFormat { VertexFormat(); + VertexFormat(VertexConversionType conversionType, + DXGI_FORMAT nativeFormat, + VertexCopyFunction copyFunction); VertexConversionType conversionType; DXGI_FORMAT nativeFormat; VertexCopyFunction copyFunction; }; -const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D_FEATURE_LEVEL featureLevel); +const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, + D3D_FEATURE_LEVEL featureLevel); -} +} // namespace d3d11 -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp new file mode 100644 index 0000000000..adb20a5e60 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp @@ -0,0 +1,170 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// internal_format_initializer_table: +// Contains table to go from internal format and dxgi format to initializer function +// for TextureFormat +// + +#include "libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h" +#include "libANGLE/renderer/d3d/loadimage.h" + +namespace rx +{ + +namespace d3d11 +{ + +// TODO: This should be generated by a JSON file +InitializeTextureDataFunction GetInternalFormatInitializer(GLenum internalFormat, + DXGI_FORMAT dxgiFormat) +{ + switch (internalFormat) + { + case GL_RGB8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_RGB565: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_SRGB8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_RGB16F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_RGB32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_RGB8UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UINT: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_RGB8I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_SINT: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_RGB16UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_UINT: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_RGB16I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_SINT: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_RGB32UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_UINT: + { + return Initialize4ComponentData; + } + default: + break; + } + } + case GL_RGB32I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_SINT: + { + return Initialize4ComponentData; + } + default: + break; + } + } + default: + { + return nullptr; + } + } +} + +} // namespace d3d11 + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h new file mode 100644 index 0000000000..2d538e1d82 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h @@ -0,0 +1,31 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// internal_format_initializer_table: +// Contains table to go from internal format and dxgi format to initializer function +// for TextureFormat +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_ + +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +#include + +namespace rx +{ + +namespace d3d11 +{ + +InitializeTextureDataFunction GetInternalFormatInitializer(GLenum internalFormat, + DXGI_FORMAT dxgiFormat); + +} // namespace d3d11 + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_INTERNALFORMATINITIALIZERTABLE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json new file mode 100644 index 0000000000..c85393e06b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json @@ -0,0 +1,1116 @@ +{ + "GL_RG8_SNORM": { + "GL_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8_SNORM", + "requiresConversion": "false" + } + ] + }, + "GL_SRGB8": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "requiresConversion": "true" + } + ] + }, + "GL_RGBA8I": { + "GL_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "requiresConversion": "false" + } + ] + }, + "GL_R8_SNORM": { + "GL_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8_SNORM", + "requiresConversion": "false" + } + ] + }, + "GL_RGBA8_SNORM": { + "GL_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "requiresConversion": "false" + } + ] + }, + "GL_R16I": { + "GL_SHORT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16_SINT", + "requiresConversion": "false" + } + ] + }, + "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadETC2SRGBA8ToSRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadETC2RGB8A1ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_RGB32UI": { + "GL_UNSIGNED_INT": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "requiresConversion": "true" + } + ] + }, + "GL_ALPHA32F_EXT": { + "GL_FLOAT": [ + { + "loadFunction": "LoadA32FToRGBA32F", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_R16UI": { + "GL_UNSIGNED_SHORT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_RGB9_E5": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadRGB16FToRGB9E5", + "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_INT_5_9_9_9_REV": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", + "requiresConversion": "false" + } + ], + "GL_FLOAT": [ + { + "loadFunction": "LoadRGB32FToRGB9E5", + "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadRGB16FToRGB9E5", + "dxgiFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_R11_EAC": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadEACR11ToR8", + "dxgiFormat": "DXGI_FORMAT_R8_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_RGBA32UI": { + "GL_UNSIGNED_INT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_RG8UI": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_LUMINANCE32F_EXT": { + "GL_FLOAT": [ + { + "loadFunction": "LoadL32FToRGBA32F", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadETC2SRGB8A1ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "requiresConversion": "true" + } + ] + }, + "GL_R16F": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16_FLOAT", + "requiresConversion": "false" + } + ], + "GL_FLOAT": [ + { + "loadFunction": "Load32FTo16F<1>", + "dxgiFormat": "DXGI_FORMAT_R16_FLOAT", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16_FLOAT", + "requiresConversion": "false" + } + ] + }, + "GL_RGBA8UI": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_BGRA4_ANGLEX": { + "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT": [ + { + "loadFunction": "LoadRGBA4ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "false" + } + ] + }, + "GL_RGBA16F": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "false" + } + ], + "GL_FLOAT": [ + { + "loadFunction": "Load32FTo16F<4>", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "false" + } + ] + }, + "GL_LUMINANCE8_EXT": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadL8ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadCompressedToNative<4,4,16>", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RGB": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "UnreachableLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_SHORT_5_6_5": [ + { + "loadFunction": "UnreachableLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RGB5_A1": { + "GL_UNSIGNED_INT_2_10_10_10_REV": [ + { + "loadFunction": "LoadRGB10A2ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "false" + } + ], + "GL_UNSIGNED_SHORT_5_5_5_1": [ + { + "loadFunction": "LoadRGB5A1ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + }, + { + "loadFunction": "LoadRGB5A1ToA1RGB5", + "dxgiFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_RGB16UI": { + "GL_UNSIGNED_SHORT": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "requiresConversion": "true" + } + ] + }, + "GL_BGRA_EXT": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "UnreachableLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_RGB8_ETC2": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadETC2RGB8ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_RGBA32F": { + "GL_FLOAT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "requiresConversion": "false" + } + ] + }, + "GL_RGBA32I": { + "GL_INT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "requiresConversion": "false" + } + ] + }, + "GL_LUMINANCE8_ALPHA8_EXT": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadLA8ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RG8": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8_UNORM", + "requiresConversion": "false" + } + ] + }, + "GL_RGB10_A2": { + "GL_UNSIGNED_INT_2_10_10_10_REV": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", + "requiresConversion": "false" + } + ] + }, + "GL_COMPRESSED_SIGNED_RG11_EAC": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadEACRG11SToRG8", + "dxgiFormat": "DXGI_FORMAT_R8G8_SNORM", + "requiresConversion": "true" + } + ] + }, + "GL_DEPTH_COMPONENT16": { + "GL_UNSIGNED_INT": [ + { + "loadFunction": "LoadR32ToR16", + "dxgiFormat": "DXGI_FORMAT_R16_TYPELESS", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_SHORT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16_TYPELESS", + "requiresConversion": "false" + }, + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_D16_UNORM", + "requiresConversion": "false" + } + ] + }, + "GL_RGB32I": { + "GL_INT": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "requiresConversion": "true" + } + ] + }, + "GL_R8": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8_UNORM", + "requiresConversion": "false" + } + ] + }, + "GL_RGB32F": { + "GL_FLOAT": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "requiresConversion": "true" + } + ] + }, + "GL_R11F_G11F_B10F": { + "GL_UNSIGNED_INT_10F_11F_11F_REV": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "requiresConversion": "false" + } + ], + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadRGB16FToRG11B10F", + "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "requiresConversion": "true" + } + ], + "GL_FLOAT": [ + { + "loadFunction": "LoadRGB32FToRG11B10F", + "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadRGB16FToRG11B10F", + "dxgiFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "requiresConversion": "true" + } + ] + }, + "GL_RGB8": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_LUMINANCE_ALPHA": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadLA16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "UnreachableLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_FLOAT": [ + { + "loadFunction": "LoadLA32FToRGBA32F", + "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadLA16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ] + }, + "GL_RGBA16I": { + "GL_SHORT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "requiresConversion": "false" + } + ] + }, + "GL_R8I": { + "GL_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8_SINT", + "requiresConversion": "false" + } + ] + }, + "GL_RGB8_SNORM": { + "GL_BYTE": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "requiresConversion": "true" + } + ] + }, + "GL_RG32F": { + "GL_FLOAT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32G32_FLOAT", + "requiresConversion": "false" + } + ] + }, + "GL_DEPTH_COMPONENT32F": { + "GL_FLOAT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32_TYPELESS", + "requiresConversion": "false" + }, + { + "loadFunction": "UnimplementedLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RG32I": { + "GL_INT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32G32_SINT", + "requiresConversion": "false" + } + ] + }, + "GL_ALPHA8_EXT": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_A8_UNORM", + "requiresConversion": "false" + }, + { + "loadFunction": "LoadA8ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_RG32UI": { + "GL_UNSIGNED_INT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32G32_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_RGBA16UI": { + "GL_UNSIGNED_SHORT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_COMPRESSED_RGBA8_ETC2_EAC": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadETC2RGBA8ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_RGB8I": { + "GL_BYTE": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_SRGB8_ETC2": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadETC2SRGB8ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "requiresConversion": "true" + } + ] + }, + "GL_DEPTH32F_STENCIL8": { + "GL_FLOAT_32_UNSIGNED_INT_24_8_REV": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32G8X24_TYPELESS", + "requiresConversion": "false" + }, + { + "loadFunction": "UnimplementedLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RG8I": { + "GL_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8_SINT", + "requiresConversion": "false" + } + ] + }, + "GL_R32UI": { + "GL_UNSIGNED_INT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_BGR5_A1_ANGLEX": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "false" + } + ], + "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT": [ + { + "loadFunction": "LoadRGB5A1ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_RG11_EAC": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadEACRG11ToRG8", + "dxgiFormat": "DXGI_FORMAT_R8G8_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_SRGB8_ALPHA8": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "requiresConversion": "false" + } + ] + }, + "GL_LUMINANCE_ALPHA16F_EXT": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadLA16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadLA16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RGBA": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "UnreachableLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_SHORT_4_4_4_4": [ + { + "loadFunction": "UnreachableLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_SHORT_5_5_5_1": [ + { + "loadFunction": "UnreachableLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_DEPTH24_STENCIL8": { + "GL_UNSIGNED_INT_24_8": [ + { + "loadFunction": "LoadR32ToR24G8", + "dxgiFormat": "DXGI_FORMAT_R24G8_TYPELESS", + "requiresConversion": "true" + }, + { + "loadFunction": "LoadR32ToR24G8", + "dxgiFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requiresConversion": "true" + } + ] + }, + "GL_RGB16I": { + "GL_SHORT": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "requiresConversion": "true" + } + ] + }, + "GL_R8UI": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_ALPHA": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadA16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "UnreachableLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_FLOAT": [ + { + "loadFunction": "LoadA32FToRGBA32F", + "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadA16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ] + }, + "GL_RGB16F": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ], + "GL_FLOAT": [ + { + "loadFunction": "LoadRGB32FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_SIGNED_R11_EAC": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadEACR11SToR8", + "dxgiFormat": "DXGI_FORMAT_R8_SNORM", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadCompressedToNative<4,4,8>", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadCompressedToNative<4,4,8>", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_STENCIL_INDEX8": { + "DXGI_FORMAT_R24G8_TYPELESS": [ + { + "loadFunction": "UnimplementedLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "DXGI_FORMAT_D24_UNORM_S8_UINT": [ + { + "loadFunction": "UnimplementedLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_LUMINANCE_ALPHA32F_EXT": { + "GL_FLOAT": [ + { + "loadFunction": "LoadLA32FToRGBA32F", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RGB8UI": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "requiresConversion": "true" + } + ] + }, + "GL_DEPTH_COMPONENT24": { + "GL_UNSIGNED_INT": [ + { + "loadFunction": "LoadR32ToR24G8", + "dxgiFormat": "DXGI_FORMAT_R24G8_TYPELESS", + "requiresConversion": "true" + }, + { + "loadFunction": "LoadR32ToR24G8", + "dxgiFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requiresConversion": "true" + } + ] + }, + "GL_R32I": { + "GL_INT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32_SINT", + "requiresConversion": "false" + } + ] + }, + "GL_DEPTH_COMPONENT32_OES": { + "GL_UNSIGNED_INT": [ + { + "loadFunction": "LoadR32ToR24G8", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_R32F": { + "GL_FLOAT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R32_FLOAT", + "requiresConversion": "false" + } + ] + }, + "GL_RG16F": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT", + "requiresConversion": "false" + } + ], + "GL_FLOAT": [ + { + "loadFunction": "Load32FTo16F<2>", + "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16G16_FLOAT", + "requiresConversion": "false" + } + ] + }, + "GL_RGB565": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative3To4", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_SHORT_5_6_5": [ + { + "loadFunction": "LoadR5G6B5ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + }, + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "requiresConversion": "false" + } + ] + }, + "GL_LUMINANCE16F_EXT": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadL16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadL16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RG16UI": { + "GL_UNSIGNED_SHORT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16G16_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadCompressedToNative<4,4,16>", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RG16I": { + "GL_SHORT": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R16G16_SINT", + "requiresConversion": "false" + } + ] + }, + "GL_BGRA8_EXT": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "false" + } + ] + }, + "GL_ALPHA16F_EXT": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadA16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadA16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ] + }, + "GL_RGBA4": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "false" + } + ], + "GL_UNSIGNED_SHORT_4_4_4_4": [ + { + "loadFunction": "LoadRGBA4ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + }, + { + "loadFunction": "LoadRGBA4ToARGB4", + "dxgiFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_RGBA8": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "false" + } + ] + }, + "GL_LUMINANCE": { + "GL_HALF_FLOAT": [ + { + "loadFunction": "LoadL16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ], + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "UnreachableLoadFunction", + "dxgiFormat": "DXGI_FORMAT_UNKNOWN", + "requiresConversion": "true" + } + ], + "GL_FLOAT": [ + { + "loadFunction": "LoadL32FToRGBA32F", + "dxgiFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "requiresConversion": "true" + } + ], + "GL_HALF_FLOAT_OES": [ + { + "loadFunction": "LoadL16FToRGBA16F", + "dxgiFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "requiresConversion": "true" + } + ] + }, + "GL_RGB10_A2UI": { + "GL_UNSIGNED_INT_2_10_10_10_REV": [ + { + "loadFunction": "LoadToNative", + "dxgiFormat": "DXGI_FORMAT_R10G10B10A2_UINT", + "requiresConversion": "false" + } + ] + }, + "GL_ETC1_RGB8_OES": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadETC1RGB8ToRGBA8", + "dxgiFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requiresConversion": "true" + } + ] + }, + "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": { + "GL_UNSIGNED_BYTE": [ + { + "loadFunction": "LoadETC1RGB8ToBC1", + "dxgiFormat": "DXGI_FORMAT_BC1_UNORM", + "requiresConversion": "true" + } + ] + } +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h new file mode 100644 index 0000000000..b17062f68d --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h @@ -0,0 +1,31 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// load_functions_table: +// Contains load functions table depending on internal format and dxgi format +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_ + +#include + +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +namespace rx +{ + +namespace d3d11 +{ + +const std::map &GetLoadFunctionsMap(GLenum internalFormat, + DXGI_FORMAT dxgiFormat); + +} // namespace d3d11 + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_LOADFUNCTIONSTABLE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp new file mode 100644 index 0000000000..acb48b9573 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp @@ -0,0 +1,2098 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_load_functions_table.py using data from load_functions_data.json +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// load_functions_table: +// Contains the GetLoadFunctionsMap for texture_format_util.h +// + +#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/d3d/loadimage.h" +#include "libANGLE/renderer/d3d/loadimage_etc.h" + +namespace rx +{ + +namespace d3d11 +{ + +namespace +{ + +// ES3 image loading functions vary based on: +// - the GL internal format (supplied to glTex*Image*D) +// - the GL data type given (supplied to glTex*Image*D) +// - the target DXGI_FORMAT that the image will be loaded into (which is chosen based on the D3D +// device's capabilities) +// This map type determines which loading function to use, based on these three parameters. +// Source formats and types are taken from Tables 3.2 and 3.3 of the ES 3 spec. +void UnimplementedLoadFunction(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + UNIMPLEMENTED(); +} + +void UnreachableLoadFunction(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +} // namespace + +// TODO we can replace these maps with more generated code +const std::map &GetLoadFunctionsMap(GLenum internalFormat, + DXGI_FORMAT dxgiFormat) +{ + // clang-format off + switch (internalFormat) + { + case GL_ALPHA: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadA32FToRGBA32F, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_ALPHA16F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadA16FToRGBA16F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_ALPHA32F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadA32FToRGBA32F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadA32FToRGBA32F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_ALPHA8_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadA8ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_BGR5_A1_ANGLEX: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, true); + loadMap[GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT] = LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_BGRA4_ANGLEX: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, true); + loadMap[GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT] = LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_BGRA8_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_BGRA_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_R11_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACR11ToR8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_RG11_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACRG11ToRG8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_RGB8_ETC2: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2RGB8ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2RGB8A1ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_RGBA8_ETC2_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2RGBA8ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,16>, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadCompressedToNative<4,4,8>, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_COMPRESSED_SIGNED_R11_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_SNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACR11SToR8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_SIGNED_RG11_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_SNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadEACRG11SToRG8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2SRGBA8ToSRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_SRGB8_ETC2: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2SRGB8ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC2SRGB8A1ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_DEPTH24_STENCIL8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT_24_8] = LoadImageFunctionInfo(LoadR32ToR24G8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT_24_8] = LoadImageFunctionInfo(LoadR32ToR24G8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_DEPTH32F_STENCIL8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT_32_UNSIGNED_INT_24_8_REV] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_DEPTH_COMPONENT16: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_D16_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R16_TYPELESS: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR16, true); + loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_DEPTH_COMPONENT24: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_D24_UNORM_S8_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R24G8_TYPELESS: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_DEPTH_COMPONENT32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32_TYPELESS: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_DEPTH_COMPONENT32_OES: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadR32ToR24G8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_BC1_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC1RGB8ToBC1, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_ETC1_RGB8_OES: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadETC1RGB8ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_LUMINANCE: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadL32FToRGBA32F, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE16F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadL16FToRGBA16F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE32F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadL32FToRGBA32F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadL32FToRGBA32F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE8_ALPHA8_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadLA8ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadLA8ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE8_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadL8ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadL8ToRGBA8, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE_ALPHA: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadLA32FToRGBA32F, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE_ALPHA16F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadLA16FToRGBA16F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_LUMINANCE_ALPHA32F_EXT: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadLA32FToRGBA32F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadLA32FToRGBA32F, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_R11F_G11F_B10F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R11G11B10_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadRGB16FToRG11B10F, true); + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadRGB32FToRG11B10F, true); + loadMap[GL_UNSIGNED_INT_10F_11F_11F_REV] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R16F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(Load32FTo16F<1>, true); + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative, false); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R16I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R16UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R32I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R32UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R8I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R8UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_R8_SNORM: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8_SNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG16F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(Load32FTo16F<2>, true); + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative, false); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG16I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG16UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG32I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG32UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG8I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG8UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RG8_SNORM: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8_SNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_RGB10_A2: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB10_A2UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R10G10B10A2_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB16F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadRGB32FToRGBA16F, true); + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative3To4, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB16I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB16UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB32I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB32UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB565: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_B5G6R5_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT_5_6_5] = LoadImageFunctionInfo(LoadR5G6B5ToRGBA8, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB5_A1: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_B5G5R5A1_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(LoadRGB5A1ToA1RGB5, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT_2_10_10_10_REV] = LoadImageFunctionInfo(LoadRGB10A2ToRGBA8, true); + loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(LoadRGB5A1ToRGBA8, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB8I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB8UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB8_SNORM: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGB9_E5: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadRGB16FToRGB9E5, true); + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadRGB32FToRGB9E5, true); + loadMap[GL_UNSIGNED_INT_5_9_9_9_REV] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + loadMap[GL_UNSIGNED_SHORT_5_5_5_1] = LoadImageFunctionInfo(UnreachableLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + case GL_RGBA16F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(Load32FTo16F<4>, true); + loadMap[GL_HALF_FLOAT] = LoadImageFunctionInfo(LoadToNative, false); + loadMap[GL_HALF_FLOAT_OES] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA16I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_SHORT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA16UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R16G16B16A16_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA32F: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_FLOAT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA32I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_INT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA32UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R32G32B32A32_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_INT] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA4: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(LoadRGBA4ToARGB4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_SHORT_4_4_4_4] = LoadImageFunctionInfo(LoadRGBA4ToRGBA8, true); + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA8I: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_SINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA8UI: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UINT: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_RGBA8_SNORM: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_SRGB8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative3To4, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_SRGB8_ALPHA8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[GL_UNSIGNED_BYTE] = LoadImageFunctionInfo(LoadToNative, false); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + break; + } + } + case GL_STENCIL_INDEX8: + { + switch (dxgiFormat) + { + case DXGI_FORMAT_UNKNOWN: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); + loadMap[DXGI_FORMAT_R24G8_TYPELESS] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + default: + { + static const std::map loadFunctionsMap = []() { + std::map loadMap; + loadMap[DXGI_FORMAT_D24_UNORM_S8_UINT] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); + loadMap[DXGI_FORMAT_R24G8_TYPELESS] = LoadImageFunctionInfo(UnimplementedLoadFunction, true); + return loadMap; + }(); + + return loadFunctionsMap; + } + } + } + + default: + { + static std::map emptyLoadFunctionsMap; + return emptyLoadFunctionsMap; + } + } + // clang-format on + +} // GetLoadFunctionsMap + +} // namespace d3d11 + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp index 63085f497f..a1175db9af 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp @@ -8,17 +8,20 @@ // specific to the D3D11 renderer. #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#include + +#include "common/debug.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/Program.h" +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" #include "libANGLE/renderer/d3d/FramebufferD3D.h" -#include "libANGLE/renderer/Workarounds.h" -#include "libANGLE/formatutils.h" -#include "libANGLE/Program.h" -#include "libANGLE/Framebuffer.h" - -#include "common/debug.h" - -#include +#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" #ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY # define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2 @@ -300,23 +303,111 @@ D3D11_QUERY ConvertQueryType(GLenum queryType) case GL_ANY_SAMPLES_PASSED_EXT: case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: return D3D11_QUERY_OCCLUSION; case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS; + case GL_TIME_ELAPSED_EXT: + // Two internal queries are also created for begin/end timestamps + return D3D11_QUERY_TIMESTAMP_DISJOINT; default: UNREACHABLE(); return D3D11_QUERY_EVENT; } } -} - +} // namespace gl_d3d11 namespace d3d11_gl { +namespace +{ + +// Helper functor for querying DXGI support. Saves passing the parameters repeatedly. +class DXGISupportHelper : angle::NonCopyable +{ + public: + DXGISupportHelper(ID3D11Device *device, D3D_FEATURE_LEVEL featureLevel) + : mDevice(device), + mFeatureLevel(featureLevel) + { + } + + bool query(DXGI_FORMAT dxgiFormat, UINT supportMask) + { + if (dxgiFormat == DXGI_FORMAT_UNKNOWN) + return false; + + auto dxgiSupport = d3d11::GetDXGISupport(dxgiFormat, mFeatureLevel); + + UINT supportedBits = dxgiSupport.alwaysSupportedFlags; + + if ((dxgiSupport.optionallySupportedFlags & supportMask) != 0) + { + UINT formatSupport; + if (SUCCEEDED(mDevice->CheckFormatSupport(dxgiFormat, &formatSupport))) + { + supportedBits |= (formatSupport & supportMask); + } + else + { + // TODO(jmadill): find out why we fail this call sometimes in FL9_3 + // ERR("Error checking format support for format 0x%x", dxgiFormat); + } + } + + return ((supportedBits & supportMask) == supportMask); + } + + private: + ID3D11Device *mDevice; + D3D_FEATURE_LEVEL mFeatureLevel; +}; + +} // anonymous namespace + +unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 0; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 3; // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale + + default: + UNREACHABLE(); + return 0; + } +} + +unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 0; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 3; + + default: + UNREACHABLE(); + return 0; + } +} + GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return 3; @@ -329,52 +420,52 @@ GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel) } } -static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum internalFormat, ID3D11Device *device) +static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum internalFormat, ID3D11Device *device, const Renderer11DeviceCaps &renderer11DeviceCaps) { gl::TextureCaps textureCaps; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, device->GetFeatureLevel()); + DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel); + const d3d11::TextureFormat &formatInfo = + d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); + + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); - UINT formatSupport; - if (SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &formatSupport))) + UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D; + if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0) { - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); - if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0) + texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE; + if (maxClientVersion > 2) { - textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); - } - else - { - UINT formatSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; - if (maxClientVersion > 2) - { - formatSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D; - } - textureCaps.texturable = ((formatSupport & formatSupportMask) == formatSupportMask); + texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D; } } - if (SUCCEEDED(device->CheckFormatSupport(formatInfo.renderFormat, &formatSupport)) && - ((formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET) != 0)) + textureCaps.texturable = support.query(formatInfo.texFormat, texSupportMask); + textureCaps.filterable = support.query(formatInfo.srvFormat, D3D11_FORMAT_SUPPORT_SHADER_SAMPLE); + textureCaps.renderable = (support.query(formatInfo.rtvFormat, D3D11_FORMAT_SUPPORT_RENDER_TARGET)) || + (support.query(formatInfo.dsvFormat, D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)); + + if (support.query(formatInfo.renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) { - for (size_t sampleCount = 1; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount++) + // Assume 1x + textureCaps.sampleCounts.insert(1); + + for (unsigned int sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; + sampleCount *= 2) { UINT qualityCount = 0; - if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount)) && - qualityCount > 0) + if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount))) { + // Assume we always support lower sample counts + if (qualityCount == 0) + { + break; + } textureCaps.sampleCounts.insert(sampleCount); } } } - textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(formatInfo.srvFormat, &formatSupport)) && - ((formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) != 0; - textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(formatInfo.rtvFormat, &formatSupport)) && - ((formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) != 0) || - (SUCCEEDED(device->CheckFormatSupport(formatInfo.dsvFormat, &formatSupport)) && - ((formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0)); - return textureCaps; } @@ -382,9 +473,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; @@ -402,9 +491,7 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; case D3D_FEATURE_LEVEL_10_1: @@ -424,9 +511,7 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; @@ -446,9 +531,7 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: @@ -466,9 +549,7 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; @@ -491,9 +572,7 @@ static bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; @@ -510,9 +589,7 @@ static bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; @@ -535,9 +612,7 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: @@ -553,9 +628,7 @@ static bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return true; @@ -574,9 +647,7 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; case D3D_FEATURE_LEVEL_10_1: @@ -594,9 +665,7 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; case D3D_FEATURE_LEVEL_10_1: @@ -654,9 +723,7 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; case D3D_FEATURE_LEVEL_10_1: @@ -674,9 +741,7 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; case D3D_FEATURE_LEVEL_10_1: @@ -700,9 +765,7 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); @@ -724,9 +787,7 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits::max(); @@ -743,9 +804,7 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT; @@ -765,9 +824,7 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; case D3D_FEATURE_LEVEL_10_1: @@ -776,7 +833,8 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::VSSetConstantBuffers case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 255; + case D3D_FEATURE_LEVEL_9_1: + return 255 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel); default: UNREACHABLE(); return 0; } @@ -792,9 +850,7 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); case D3D_FEATURE_LEVEL_10_1: @@ -822,9 +878,7 @@ static size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) // We must reserve one output vector for dx_Position. // We also reserve one for gl_Position, which we unconditionally output on Feature Levels 10_0+, // even if it's unused in the shader (e.g. for transform feedback). TODO: This could be improved. -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return 2; @@ -846,9 +900,7 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); @@ -867,9 +919,7 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; case D3D_FEATURE_LEVEL_10_1: @@ -891,9 +941,7 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; case D3D_FEATURE_LEVEL_10_1: @@ -902,7 +950,8 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetConstantBuffers case D3D_FEATURE_LEVEL_9_3: case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 32; + case D3D_FEATURE_LEVEL_9_1: + return 32 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel); default: UNREACHABLE(); return 0; } @@ -918,9 +967,7 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); case D3D_FEATURE_LEVEL_10_1: @@ -939,9 +986,7 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); case D3D_FEATURE_LEVEL_10_1: @@ -960,9 +1005,7 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; case D3D_FEATURE_LEVEL_10_1: @@ -981,9 +1024,7 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; case D3D_FEATURE_LEVEL_10_1: @@ -1002,9 +1043,7 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE; @@ -1027,9 +1066,7 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; case D3D_FEATURE_LEVEL_10_1: @@ -1048,9 +1085,7 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT; case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT; @@ -1068,9 +1103,7 @@ static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL feat { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: case D3D_FEATURE_LEVEL_10_1: @@ -1088,9 +1121,7 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature { switch (featureLevel) { -#if defined(ANGLE_ENABLE_D3D11_1) case D3D_FEATURE_LEVEL_11_1: -#endif case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / GetMaximumStreamOutputBuffers(featureLevel); @@ -1107,15 +1138,15 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature } } -void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations) { - D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel(); - GLuint maxSamples = 0; + D3D_FEATURE_LEVEL featureLevel = renderer11DeviceCaps.featureLevel; const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat) { - gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device); + gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device, renderer11DeviceCaps); textureCapsMap->insert(*internalFormat, textureCaps); maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); @@ -1127,11 +1158,12 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl:: } // GL core feature limits - caps->maxElementIndex = static_cast(std::numeric_limits::max()); - caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel); - caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel); - caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel); - caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel); + // Reserve MAX_UINT for D3D11's primitive restart. + caps->maxElementIndex = static_cast(std::numeric_limits::max() - 1); + caps->max3DTextureSize = static_cast(GetMaximum3DTextureSize(featureLevel)); + caps->max2DTextureSize = static_cast(GetMaximum2DTextureSize(featureLevel)); + caps->maxCubeMapTextureSize = static_cast(GetMaximumCubeMapTextureSize(featureLevel)); + caps->maxArrayTextureLayers = static_cast(GetMaximum2DTextureArraySize(featureLevel)); // Unimplemented, set to minimum required caps->maxLODBias = 2.0f; @@ -1141,11 +1173,12 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl:: // Maximum draw buffers and color attachments are the same, max color attachments could eventually be // increased to 16 - caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel); - caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel); + caps->maxDrawBuffers = static_cast(GetMaximumSimultaneousRenderTargets(featureLevel)); + caps->maxColorAttachments = + static_cast(GetMaximumSimultaneousRenderTargets(featureLevel)); // D3D11 has the same limit for viewport width and height - caps->maxViewportWidth = GetMaximumViewportSize(featureLevel); + caps->maxViewportWidth = static_cast(GetMaximumViewportSize(featureLevel)); caps->maxViewportHeight = caps->maxViewportWidth; // Choose a reasonable maximum, enforced in the shader. @@ -1157,8 +1190,8 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl:: caps->maxAliasedLineWidth = 1.0f; // Primitive count limits - caps->maxElementsIndices = GetMaximumDrawIndexedIndexCount(featureLevel); - caps->maxElementsVertices = GetMaximumDrawVertexCount(featureLevel); + caps->maxElementsIndices = static_cast(GetMaximumDrawIndexedIndexCount(featureLevel)); + caps->maxElementsVertices = static_cast(GetMaximumDrawVertexCount(featureLevel)); // Program and shader binary formats (no supported shader binary formats) caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE); @@ -1182,19 +1215,27 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl:: caps->maxServerWaitTimeout = 0; // Vertex shader limits - caps->maxVertexAttributes = GetMaximumVertexInputSlots(featureLevel); - caps->maxVertexUniformComponents = GetMaximumVertexUniformVectors(featureLevel) * 4; - caps->maxVertexUniformVectors = GetMaximumVertexUniformVectors(featureLevel); - caps->maxVertexUniformBlocks = GetMaximumVertexUniformBlocks(featureLevel); - caps->maxVertexOutputComponents = GetMaximumVertexOutputVectors(featureLevel) * 4; - caps->maxVertexTextureImageUnits = GetMaximumVertexTextureUnits(featureLevel); + caps->maxVertexAttributes = static_cast(GetMaximumVertexInputSlots(featureLevel)); + caps->maxVertexUniformComponents = + static_cast(GetMaximumVertexUniformVectors(featureLevel)) * 4; + caps->maxVertexUniformVectors = + static_cast(GetMaximumVertexUniformVectors(featureLevel)); + caps->maxVertexUniformBlocks = static_cast(GetMaximumVertexUniformBlocks(featureLevel)); + caps->maxVertexOutputComponents = + static_cast(GetMaximumVertexOutputVectors(featureLevel)) * 4; + caps->maxVertexTextureImageUnits = + static_cast(GetMaximumVertexTextureUnits(featureLevel)); // Fragment shader limits - caps->maxFragmentUniformComponents = GetMaximumPixelUniformVectors(featureLevel) * 4; - caps->maxFragmentUniformVectors = GetMaximumPixelUniformVectors(featureLevel); - caps->maxFragmentUniformBlocks = GetMaximumPixelUniformBlocks(featureLevel); - caps->maxFragmentInputComponents = GetMaximumPixelInputVectors(featureLevel) * 4; - caps->maxTextureImageUnits = GetMaximumPixelTextureUnits(featureLevel); + caps->maxFragmentUniformComponents = + static_cast(GetMaximumPixelUniformVectors(featureLevel)) * 4; + caps->maxFragmentUniformVectors = + static_cast(GetMaximumPixelUniformVectors(featureLevel)); + caps->maxFragmentUniformBlocks = + static_cast(GetMaximumPixelUniformBlocks(featureLevel)); + caps->maxFragmentInputComponents = + static_cast(GetMaximumPixelInputVectors(featureLevel)) * 4; + caps->maxTextureImageUnits = static_cast(GetMaximumPixelTextureUnits(featureLevel)); caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel); caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel); @@ -1202,45 +1243,36 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl:: caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel); - // Setting a large alignment forces uniform buffers to bind with zero offset - caps->uniformBufferOffsetAlignment = static_cast(std::numeric_limits::max()); -#if defined(ANGLE_ENABLE_D3D11_1) - ID3D11DeviceContext1 *deviceContext1 = d3d11::DynamicCastComObject(deviceContext); - - if (deviceContext1) - { - D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; - device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); - - if (d3d11Options.ConstantBufferOffsetting) - { - // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16 bytes each. - // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx - caps->uniformBufferOffsetAlignment = 256; - } - - SafeRelease(deviceContext1); - } -#endif + // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16 bytes each. + // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx + // With DirectX 11.0, we emulate UBO offsets using copies of ranges of the UBO however + // we still keep the same alignment as 11.1 for consistency. + caps->uniformBufferOffsetAlignment = 256; caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; caps->maxCombinedVertexUniformComponents = (static_cast(caps->maxVertexUniformBlocks) * static_cast(caps->maxUniformBlockSize / 4)) + static_cast(caps->maxVertexUniformComponents); caps->maxCombinedFragmentUniformComponents = (static_cast(caps->maxFragmentUniformBlocks) * static_cast(caps->maxUniformBlockSize / 4)) + static_cast(caps->maxFragmentUniformComponents); - caps->maxVaryingComponents = GetMaximumVertexOutputVectors(featureLevel) * 4; - caps->maxVaryingVectors = GetMaximumVertexOutputVectors(featureLevel); + caps->maxVaryingComponents = + static_cast(GetMaximumVertexOutputVectors(featureLevel)) * 4; + caps->maxVaryingVectors = static_cast(GetMaximumVertexOutputVectors(featureLevel)); caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; // Transform feedback limits - caps->maxTransformFeedbackInterleavedComponents = GetMaximumStreamOutputInterleavedComponents(featureLevel); - caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel); - caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateComponents(featureLevel); + caps->maxTransformFeedbackInterleavedComponents = + static_cast(GetMaximumStreamOutputInterleavedComponents(featureLevel)); + caps->maxTransformFeedbackSeparateAttributes = + static_cast(GetMaximumStreamOutputBuffers(featureLevel)); + caps->maxTransformFeedbackSeparateComponents = + static_cast(GetMaximumStreamOutputSeparateComponents(featureLevel)); + + // Multisample limits + caps->maxSamples = maxSamples; // GL extension support extensions->setTextureExtensionSupport(*textureCapsMap); extensions->elementIndexUint = true; - extensions->packedDepthStencil = true; extensions->getProgramBinary = true; extensions->rgb8rgba8 = true; extensions->readFormatBGRA = true; @@ -1255,25 +1287,136 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl:: extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel); extensions->fence = GetEventQuerySupport(featureLevel); extensions->timerQuery = false; // Unimplemented + extensions->disjointTimerQuery = true; + extensions->queryCounterBitsTimeElapsed = 64; + extensions->queryCounterBitsTimestamp = + 0; // Timestamps cannot be supported due to D3D11 limitations extensions->robustness = true; extensions->blendMinMax = true; extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel); extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel); - extensions->maxSamples = maxSamples; extensions->instancedArrays = GetInstancingSupport(featureLevel); extensions->packReverseRowOrder = true; extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel); extensions->fragDepth = true; extensions->textureUsage = true; // This could be false since it has no effect in D3D11 + extensions->discardFramebuffer = true; extensions->translatedShaderSource = true; + extensions->fboRenderMipmap = false; + extensions->debugMarker = true; + extensions->eglImage = true; + extensions->unpackSubimage = true; + extensions->packSubimage = true; + extensions->vertexArrayObject = true; + extensions->noError = true; + extensions->lossyETCDecode = true; + + // D3D11 Feature Level 10_0+ uses SV_IsFrontFace in HLSL to emulate gl_FrontFacing. + // D3D11 Feature Level 9_3 doesn't support SV_IsFrontFace, and has no equivalent, so can't support gl_FrontFacing. + limitations->noFrontFacingSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); + + // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage + limitations->noSampleAlphaToCoverageSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); + + // D3D11 Feature Levels 9_3 and below do not support non-constant loop indexing and require + // additional + // pre-validation of the shader at compile time to produce a better error message. + limitations->shadersRequireIndexedLoopValidation = + (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); + + // D3D11 has no concept of separate masks and refs for front and back faces in the depth stencil + // state. + limitations->noSeparateStencilRefsAndMasks = true; + + // D3D11 cannot support constant color and alpha blend funcs together + limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true; + +#ifdef ANGLE_ENABLE_WINDOWS_STORE + // Setting a non-zero divisor on attribute zero doesn't work on certain Windows Phone 8-era devices. + // We should prevent developers from doing this on ALL Windows Store devices. This will maintain consistency across all Windows devices. + // We allow non-zero divisors on attribute zero if the Client Version >= 3, since devices affected by this issue don't support ES3+. + limitations->attributeZeroRequiresZeroDivisorInEXT = true; +#endif } -} +} // namespace d3d11_gl namespace d3d11 { +ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) +{ + // Note that this function returns an ANGLED3D11DeviceType rather than a D3D_DRIVER_TYPE value, + // since it is difficult to tell Software and Reference devices apart + + IDXGIDevice *dxgiDevice = nullptr; + IDXGIAdapter *dxgiAdapter = nullptr; +#if defined(ANGLE_ENABLE_D3D11_1) + IDXGIAdapter2 *dxgiAdapter2 = nullptr; +#endif + + ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN; + + HRESULT hr = device->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice); + if (SUCCEEDED(hr)) + { + hr = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&dxgiAdapter); + if (SUCCEEDED(hr)) + { + std::wstring adapterString; +#if defined(ANGLE_ENABLE_D3D11_1) + HRESULT adapter2hr = + dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2); + if (SUCCEEDED(adapter2hr)) + { + // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" + // for the description string. Try to use IDXGIAdapter2::GetDesc2 to get the + // actual hardware values if possible. + DXGI_ADAPTER_DESC2 adapterDesc2; + dxgiAdapter2->GetDesc2(&adapterDesc2); + adapterString = std::wstring(adapterDesc2.Description); + } + else +#endif + { + DXGI_ADAPTER_DESC adapterDesc; + dxgiAdapter->GetDesc(&adapterDesc); + adapterString = std::wstring(adapterDesc.Description); + } + + // Both Reference and Software adapters will be 'Software Adapter' + const bool isSoftwareDevice = + (adapterString.find(std::wstring(L"Software Adapter")) != std::string::npos); + const bool isNullDevice = (adapterString == L""); + const bool isWARPDevice = + (adapterString.find(std::wstring(L"Basic Render")) != std::string::npos); + + if (isSoftwareDevice || isNullDevice) + { + ASSERT(!isWARPDevice); + retDeviceType = ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL; + } + else if (isWARPDevice) + { + retDeviceType = ANGLE_D3D11_DEVICE_TYPE_WARP; + } + else + { + retDeviceType = ANGLE_D3D11_DEVICE_TYPE_HARDWARE; + } + } + } + + SafeRelease(dxgiDevice); + SafeRelease(dxgiAdapter); +#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(dxgiAdapter2); +#endif + + return retDeviceType; +} + void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) { const DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); @@ -1293,11 +1436,16 @@ void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsi *levelOffset = upsampleCount; } -void GenerateInitialTextureData(GLint internalFormat, D3D_FEATURE_LEVEL featureLevel, GLuint width, GLuint height, GLuint depth, - GLuint mipLevels, std::vector *outSubresourceData, - std::vector< std::vector > *outData) +void GenerateInitialTextureData(GLint internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + GLuint width, + GLuint height, + GLuint depth, + GLuint mipLevels, + std::vector *outSubresourceData, + std::vector> *outData) { - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat, featureLevel); + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); ASSERT(d3dFormatInfo.dataInitializerFunction != NULL); const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat); @@ -1323,6 +1471,11 @@ void GenerateInitialTextureData(GLint internalFormat, D3D_FEATURE_LEVEL featureL } } +UINT GetPrimitiveRestartIndex() +{ + return std::numeric_limits::max(); +} + void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) { vertex->x = x; @@ -1345,27 +1498,94 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) { #if defined(_DEBUG) - return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); + UINT existingDataSize = 0; + resource->GetPrivateData(WKPDID_D3DDebugObjectName, &existingDataSize, nullptr); + // Don't check the HRESULT- if it failed then that probably just means that no private data + // exists yet + + if (existingDataSize > 0) + { + // In some cases, ANGLE will try to apply two names to one object, which causes + // a D3D SDK Layers warning. This can occur if, for example, you 'create' two objects + // (e.g.Rasterizer States) with identical DESCs on the same device. D3D11 will optimize + // these calls and return the same object both times. + static const char *multipleNamesUsed = "Multiple names set by ANGLE"; + + // Remove the existing name + HRESULT hr = resource->SetPrivateData(WKPDID_D3DDebugObjectName, 0, nullptr); + if (FAILED(hr)) + { + return hr; + } + + // Apply the new name + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, + static_cast(strlen(multipleNamesUsed)), + multipleNamesUsed); + } + else + { + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, + static_cast(strlen(name)), name); + } #else return S_OK; #endif } -gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT) +LazyInputLayout::LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc, + size_t inputDescLen, + const BYTE *byteCode, + size_t byteCodeLen, + const char *debugName) + : mInputDesc(inputDescLen), + mByteCodeLen(byteCodeLen), + mByteCode(byteCode), + mDebugName(debugName) +{ + memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen); +} + +ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + + if (mResource == nullptr) + { + HRESULT result = + device->CreateInputLayout(&mInputDesc[0], static_cast(mInputDesc.size()), + mByteCode, mByteCodeLen, &mResource); + ASSERT(SUCCEEDED(result)); + UNUSED_ASSERTION_VARIABLE(result); + d3d11::SetDebugName(mResource, mDebugName); + } + + return mResource; +} + +LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName) + : mDesc(desc), mDebugName(debugName) +{ +} + +ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device) { - RenderTargetD3D *renderTarget = NULL; - gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) + checkAssociatedDevice(device); + + if (mResource == nullptr) { - return error; + HRESULT result = device->CreateBlendState(&mDesc, &mResource); + ASSERT(SUCCEEDED(result)); + UNUSED_ASSERTION_VARIABLE(result); + d3d11::SetDebugName(mResource, mDebugName); } - *outRT = RenderTarget11::makeRenderTarget11(renderTarget); - return gl::Error(GL_NO_ERROR); + + return mResource; } -Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel) +WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel) { - Workarounds workarounds; + WorkaroundsD3D workarounds; workarounds.mrtPerfWorkaround = true; workarounds.setDataFasterThanImageUpload = true; workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3); @@ -1373,6 +1593,188 @@ Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel) return workarounds; } +} // namespace d3d11 + +TextureHelper11::TextureHelper11() + : mTextureType(GL_NONE), + mFormat(DXGI_FORMAT_UNKNOWN), + mSampleCount(0), + mTexture2D(nullptr), + mTexture3D(nullptr) +{ +} + +TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) + : mTextureType(toCopy.mTextureType), + mExtents(toCopy.mExtents), + mFormat(toCopy.mFormat), + mSampleCount(toCopy.mSampleCount), + mTexture2D(toCopy.mTexture2D), + mTexture3D(toCopy.mTexture3D) +{ + toCopy.reset(); +} + +// static +TextureHelper11 TextureHelper11::MakeAndReference(ID3D11Resource *genericResource) +{ + TextureHelper11 newHelper; + newHelper.mTexture2D = d3d11::DynamicCastComObject(genericResource); + newHelper.mTexture3D = d3d11::DynamicCastComObject(genericResource); + newHelper.mTextureType = newHelper.mTexture2D ? GL_TEXTURE_2D : GL_TEXTURE_3D; + newHelper.initDesc(); + return newHelper; +} + +// static +TextureHelper11 TextureHelper11::MakeAndPossess2D(ID3D11Texture2D *texToOwn) +{ + TextureHelper11 newHelper; + newHelper.mTexture2D = texToOwn; + newHelper.mTextureType = GL_TEXTURE_2D; + newHelper.initDesc(); + return newHelper; +} + +// static +TextureHelper11 TextureHelper11::MakeAndPossess3D(ID3D11Texture3D *texToOwn) +{ + TextureHelper11 newHelper; + newHelper.mTexture3D = texToOwn; + newHelper.mTextureType = GL_TEXTURE_3D; + newHelper.initDesc(); + return newHelper; +} + +void TextureHelper11::initDesc() +{ + if (mTextureType == GL_TEXTURE_2D) + { + ASSERT(!mTexture3D); + D3D11_TEXTURE2D_DESC desc2D; + mTexture2D->GetDesc(&desc2D); + + mExtents.width = static_cast(desc2D.Width); + mExtents.height = static_cast(desc2D.Height); + mExtents.depth = 1; + mFormat = desc2D.Format; + mSampleCount = desc2D.SampleDesc.Count; + } + else + { + ASSERT(mTexture3D && mTextureType == GL_TEXTURE_3D); + D3D11_TEXTURE3D_DESC desc3D; + mTexture3D->GetDesc(&desc3D); + + mExtents.width = static_cast(desc3D.Width); + mExtents.height = static_cast(desc3D.Height); + mExtents.depth = static_cast(desc3D.Depth); + mFormat = desc3D.Format; + mSampleCount = 1; + } +} + +TextureHelper11::~TextureHelper11() +{ + SafeRelease(mTexture2D); + SafeRelease(mTexture3D); +} + +ID3D11Resource *TextureHelper11::getResource() const +{ + return mTexture2D ? static_cast(mTexture2D) + : static_cast(mTexture3D); +} + +TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&texture) +{ + SafeRelease(mTexture2D); + SafeRelease(mTexture3D); + + mTextureType = texture.mTextureType; + mExtents = texture.mExtents; + mFormat = texture.mFormat; + mSampleCount = texture.mSampleCount; + mTexture2D = texture.mTexture2D; + mTexture3D = texture.mTexture3D; + texture.reset(); + return *this; +} + +void TextureHelper11::reset() +{ + mTextureType = GL_NONE; + mExtents = gl::Extents(); + mFormat = DXGI_FORMAT_UNKNOWN; + mSampleCount = 0; + mTexture2D = nullptr; + mTexture3D = nullptr; +} + +gl::ErrorOrResult CreateStagingTexture(GLenum textureType, + DXGI_FORMAT dxgiFormat, + const gl::Extents &size, + ID3D11Device *device) +{ + if (textureType == GL_TEXTURE_2D) + { + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = size.width; + stagingDesc.Height = size.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = dxgiFormat; + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + ID3D11Texture2D *stagingTex = nullptr; + HRESULT result = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTex); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.", + result); + } + + return TextureHelper11::MakeAndPossess2D(stagingTex); + } + ASSERT(textureType == GL_TEXTURE_3D); + + D3D11_TEXTURE3D_DESC stagingDesc; + stagingDesc.Width = size.width; + stagingDesc.Height = size.height; + stagingDesc.Depth = 1; + stagingDesc.MipLevels = 1; + stagingDesc.Format = dxgiFormat; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + ID3D11Texture3D *stagingTex = nullptr; + HRESULT result = device->CreateTexture3D(&stagingDesc, nullptr, &stagingTex); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.", + result); + } + + return TextureHelper11::MakeAndPossess3D(stagingTex); } +bool UsePresentPathFast(const Renderer11 *renderer, + const gl::FramebufferAttachment *framebufferAttachment) +{ + if (framebufferAttachment == nullptr) + { + return false; + } + + return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT && + renderer->presentPathFastEnabled()); } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h index 207e6b5404..4925a2d227 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h @@ -10,11 +10,13 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ #define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ +#include +#include + #include "libANGLE/angletypes.h" #include "libANGLE/Caps.h" #include "libANGLE/Error.h" - -#include +#include "libANGLE/renderer/d3d/RendererD3D.h" namespace gl { @@ -23,8 +25,12 @@ class FramebufferAttachment; namespace rx { +class Renderer11; class RenderTarget11; -struct Workarounds; +struct WorkaroundsD3D; +struct Renderer11DeviceCaps; + +using RenderTargetArray = std::array; namespace gl_d3d11 { @@ -45,24 +51,46 @@ D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); D3D11_QUERY ConvertQueryType(GLenum queryType); -} +} // namespace gl_d3d11 namespace d3d11_gl { +unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel); + +unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel); + GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel); -void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); +void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations); -} +} // namespace d3d11_gl namespace d3d11 { +enum ANGLED3D11DeviceType +{ + ANGLE_D3D11_DEVICE_TYPE_UNKNOWN, + ANGLE_D3D11_DEVICE_TYPE_HARDWARE, + ANGLE_D3D11_DEVICE_TYPE_SOFTWARE_REF_OR_NULL, + ANGLE_D3D11_DEVICE_TYPE_WARP, +}; + +ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device); + void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); -void GenerateInitialTextureData(GLint internalFormat, D3D_FEATURE_LEVEL featureLevel, GLuint width, GLuint height, GLuint depth, - GLuint mipLevels, std::vector *outSubresourceData, - std::vector< std::vector > *outData); +void GenerateInitialTextureData(GLint internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + GLuint width, + GLuint height, + GLuint depth, + GLuint mipLevels, + std::vector *outSubresourceData, + std::vector> *outData); + +UINT GetPrimitiveRestartIndex(); struct PositionTexCoordVertex { @@ -133,58 +161,230 @@ inline bool isDeviceLostError(HRESULT errorCode) } } -template -inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name) { - ID3D11VertexShader *vs = NULL; - HRESULT result = device->CreateVertexShader(byteCode, N, NULL, &vs); - UNUSED_ASSERTION_VARIABLE(result); + ID3D11VertexShader *vs = nullptr; + HRESULT result = device->CreateVertexShader(byteCode, N, nullptr, &vs); ASSERT(SUCCEEDED(result)); - SetDebugName(vs, name); - return vs; + if (SUCCEEDED(result)) + { + SetDebugName(vs, name); + return vs; + } + return nullptr; } template -inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + return CompileVS(device, byteCode, N, name); +} + +inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name) { - ID3D11GeometryShader *gs = NULL; - HRESULT result = device->CreateGeometryShader(byteCode, N, NULL, &gs); - UNUSED_ASSERTION_VARIABLE(result); + ID3D11GeometryShader *gs = nullptr; + HRESULT result = device->CreateGeometryShader(byteCode, N, nullptr, &gs); ASSERT(SUCCEEDED(result)); - SetDebugName(gs, name); - return gs; + if (SUCCEEDED(result)) + { + SetDebugName(gs, name); + return gs; + } + return nullptr; } template -inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + return CompileGS(device, byteCode, N, name); +} + +inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name) { - ID3D11PixelShader *ps = NULL; - HRESULT result = device->CreatePixelShader(byteCode, N, NULL, &ps); - UNUSED_ASSERTION_VARIABLE(result); + ID3D11PixelShader *ps = nullptr; + HRESULT result = device->CreatePixelShader(byteCode, N, nullptr, &ps); ASSERT(SUCCEEDED(result)); - SetDebugName(ps, name); - return ps; + if (SUCCEEDED(result)) + { + SetDebugName(ps, name); + return ps; + } + return nullptr; } -// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to -// represent an entire buffer. -template -inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value) +template +ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + return CompilePS(device, byteCode, N, name); +} + +template +class LazyResource : public angle::NonCopyable { - D3D11_MAPPED_SUBRESOURCE mappedResource; - context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + public: + LazyResource() : mResource(nullptr), mAssociatedDevice(nullptr) {} + virtual ~LazyResource() { release(); } + + virtual ResourceType *resolve(ID3D11Device *device) = 0; + void release() { SafeRelease(mResource); } - memcpy(mappedResource.pData, &value, sizeof(T)); + protected: + void checkAssociatedDevice(ID3D11Device *device); - context->Unmap(constantBuffer, 0); + ResourceType *mResource; + ID3D11Device *mAssociatedDevice; +}; + +template +void LazyResource::checkAssociatedDevice(ID3D11Device *device) +{ + ASSERT(mAssociatedDevice == nullptr || device == mAssociatedDevice); + mAssociatedDevice = device; } -gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT); +template +class LazyShader final : public LazyResource +{ + public: + // All parameters must be constexpr. Not supported in VS2013. + LazyShader(const BYTE *byteCode, + size_t byteCodeSize, + const char *name) + : mByteCode(byteCode), + mByteCodeSize(byteCodeSize), + mName(name) + { + } -Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel); + D3D11ShaderType *resolve(ID3D11Device *device) override; + private: + const BYTE *mByteCode; + size_t mByteCodeSize; + const char *mName; +}; + +template <> +inline ID3D11VertexShader *LazyShader::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + if (mResource == nullptr) + { + mResource = CompileVS(device, mByteCode, mByteCodeSize, mName); + } + return mResource; } +template <> +inline ID3D11GeometryShader *LazyShader::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + if (mResource == nullptr) + { + mResource = CompileGS(device, mByteCode, mByteCodeSize, mName); + } + return mResource; } +template <> +inline ID3D11PixelShader *LazyShader::resolve(ID3D11Device *device) +{ + checkAssociatedDevice(device); + if (mResource == nullptr) + { + mResource = CompilePS(device, mByteCode, mByteCodeSize, mName); + } + return mResource; +} + +class LazyInputLayout final : public LazyResource +{ + public: + LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc, + size_t inputDescLen, + const BYTE *byteCode, + size_t byteCodeLen, + const char *debugName); + + ID3D11InputLayout *resolve(ID3D11Device *device) override; + + private: + std::vector mInputDesc; + size_t mByteCodeLen; + const BYTE *mByteCode; + const char *mDebugName; +}; + +class LazyBlendState final : public LazyResource +{ + public: + LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName); + + ID3D11BlendState *resolve(ID3D11Device *device) override; + + private: + D3D11_BLEND_DESC mDesc; + const char *mDebugName; +}; + +// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to +// represent an entire buffer. +template +void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value) +{ + D3D11_MAPPED_SUBRESOURCE mappedResource = {}; + HRESULT result = context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + memcpy(mappedResource.pData, &value, sizeof(T)); + context->Unmap(constantBuffer, 0); + } +} + +WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel); +} // namespace d3d11 + +// A helper class which wraps a 2D or 3D texture. +class TextureHelper11 : angle::NonCopyable +{ + public: + TextureHelper11(); + TextureHelper11(TextureHelper11 &&toCopy); + ~TextureHelper11(); + TextureHelper11 &operator=(TextureHelper11 &&texture); + + static TextureHelper11 MakeAndReference(ID3D11Resource *genericResource); + static TextureHelper11 MakeAndPossess2D(ID3D11Texture2D *texToOwn); + static TextureHelper11 MakeAndPossess3D(ID3D11Texture3D *texToOwn); + + GLenum getTextureType() const { return mTextureType; } + gl::Extents getExtents() const { return mExtents; } + DXGI_FORMAT getFormat() const { return mFormat; } + int getSampleCount() const { return mSampleCount; } + ID3D11Texture2D *getTexture2D() const { return mTexture2D; } + ID3D11Texture3D *getTexture3D() const { return mTexture3D; } + ID3D11Resource *getResource() const; + + private: + void reset(); + void initDesc(); + + GLenum mTextureType; + gl::Extents mExtents; + DXGI_FORMAT mFormat; + int mSampleCount; + ID3D11Texture2D *mTexture2D; + ID3D11Texture3D *mTexture3D; +}; + +gl::ErrorOrResult CreateStagingTexture(GLenum textureType, + DXGI_FORMAT dxgiFormat, + const gl::Extents &size, + ID3D11Device *device); + +bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer); + +} // namespace rx + #endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json new file mode 100644 index 0000000000..3e9e6877d9 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json @@ -0,0 +1,77 @@ +{ + "GL_UNSIGNED_NORMALIZED": { + "8": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + }, + "16": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM" + }, + "24": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" + }, + "32": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" + } + }, + "GL_SIGNED_NORMALIZED": { + "8": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM" + } + }, + "GL_FLOAT": { + "16": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" + }, + "32": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" + } + }, + "GL_UNSIGNED_INT": { + "8": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT" + }, + "16": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT" + }, + "32": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT" + } + }, + "GL_INT": { + "8": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT" + }, + "16": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT" + }, + "32": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT" + } + } +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h new file mode 100644 index 0000000000..df9a30ff50 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h @@ -0,0 +1,51 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// swizzle_format_info: +// Provides information for swizzle format and a map from type->formatinfo +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_ + +#include +#include + +#include "common/platform.h" + +namespace rx +{ + +namespace d3d11 +{ + +struct SwizzleSizeType +{ + size_t maxComponentSize; + GLenum componentType; + + SwizzleSizeType(); + SwizzleSizeType(size_t maxComponentSize, GLenum componentType); + + bool operator<(const SwizzleSizeType &other) const; +}; + +struct SwizzleFormatInfo +{ + DXGI_FORMAT mTexFormat; + DXGI_FORMAT mSRVFormat; + DXGI_FORMAT mRTVFormat; + + SwizzleFormatInfo(); + SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat); +}; + +const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType); + +} // namespace d3d11 + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_SWIZZLEFORMATINFO_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp new file mode 100644 index 0000000000..84d6fada97 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp @@ -0,0 +1,203 @@ +// GENERATED FILE - DO NOT EDIT +// Generated by gen_swizzle_format_table.py using data from swizzle_format_data.json +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// swizzle_format_info: +// Provides information for swizzle format and a map from type->formatinfo +// + +#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h" + +#include + +namespace rx +{ + +namespace d3d11 +{ + +SwizzleSizeType::SwizzleSizeType() : maxComponentSize(0), componentType(GL_NONE) +{ +} + +SwizzleSizeType::SwizzleSizeType(size_t maxComponentSize, GLenum componentType) + : maxComponentSize(maxComponentSize), componentType(componentType) +{ +} + +bool SwizzleSizeType::operator<(const SwizzleSizeType &other) const +{ + return (maxComponentSize != other.maxComponentSize) + ? (maxComponentSize < other.maxComponentSize) + : (componentType < other.componentType); +} + +SwizzleFormatInfo::SwizzleFormatInfo() + : mTexFormat(DXGI_FORMAT_UNKNOWN), + mSRVFormat(DXGI_FORMAT_UNKNOWN), + mRTVFormat(DXGI_FORMAT_UNKNOWN) +{ +} + +SwizzleFormatInfo::SwizzleFormatInfo(DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, + DXGI_FORMAT rtvFormat) + : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat) +{ +} + +const SwizzleFormatInfo &GetSwizzleFormatInfo(GLuint maxBits, GLenum componentType) +{ + // clang-format off + switch (componentType) + { + case GL_FLOAT: + { + switch (maxBits) + { + case 16: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT); + return formatInfo; + } + case 32: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT); + return formatInfo; + } + default: + break; + } + } + case GL_INT: + { + switch (maxBits) + { + case 16: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT); + return formatInfo; + } + case 32: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT); + return formatInfo; + } + case 8: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT); + return formatInfo; + } + default: + break; + } + } + case GL_SIGNED_NORMALIZED: + { + switch (maxBits) + { + case 8: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM); + return formatInfo; + } + default: + break; + } + } + case GL_UNSIGNED_INT: + { + switch (maxBits) + { + case 16: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT); + return formatInfo; + } + case 32: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT); + return formatInfo; + } + case 8: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT); + return formatInfo; + } + default: + break; + } + } + case GL_UNSIGNED_NORMALIZED: + { + switch (maxBits) + { + case 16: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM); + return formatInfo; + } + case 24: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT); + return formatInfo; + } + case 32: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT); + return formatInfo; + } + case 8: + { + static const SwizzleFormatInfo formatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM); + return formatInfo; + } + default: + break; + } + } + + default: + { + static const SwizzleFormatInfo defaultInfo(DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return defaultInfo; + } + } + // clang-format on + +} // GetSwizzleFormatInfo + +} // namespace d3d11 + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json new file mode 100644 index 0000000000..87d303437f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json @@ -0,0 +1,692 @@ +{ + "GL_ALPHA": [ + { + "texFormat": "DXGI_FORMAT_A8_UNORM", + "srvFormat": "DXGI_FORMAT_A8_UNORM", + "rtvFormat": "DXGI_FORMAT_A8_UNORM", + "requirementsFcn": "OnlyFL10Plus" + }, + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requirementsFcn": "OnlyFL9_3" + } + ], + "GL_ALPHA16F_EXT": [ + { + "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" + } + ], + "GL_ALPHA32F_EXT": [ + { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" + } + ], + "GL_ALPHA8_EXT": [ + { + "texFormat": "DXGI_FORMAT_A8_UNORM", + "srvFormat": "DXGI_FORMAT_A8_UNORM", + "rtvFormat": "DXGI_FORMAT_A8_UNORM", + "requirementsFcn": "OnlyFL10Plus" + }, + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requirementsFcn": "OnlyFL9_3" + } + ], + "GL_BGR5_A1_ANGLEX": [ + { + "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM" + } + ], + "GL_BGRA4_ANGLEX": [ + { + "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM" + } + ], + "GL_BGRA8_EXT": [ + { + "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM" + } + ], + "GL_BGRA_EXT": [ + { + "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM" + } + ], + "GL_COMPRESSED_R11_EAC": [ + { + "texFormat": "DXGI_FORMAT_R8_UNORM", + "srvFormat": "DXGI_FORMAT_R8_UNORM", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_COMPRESSED_RG11_EAC": [ + { + "texFormat": "DXGI_FORMAT_R8G8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8_UNORM", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_COMPRESSED_RGB8_ETC2": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_COMPRESSED_RGBA8_ETC2_EAC": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": [ + { + "texFormat": "DXGI_FORMAT_BC1_UNORM", + "srvFormat": "DXGI_FORMAT_BC1_UNORM" + } + ], + "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": [ + { + "texFormat": "DXGI_FORMAT_BC2_UNORM", + "srvFormat": "DXGI_FORMAT_BC2_UNORM" + } + ], + "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": [ + { + "texFormat": "DXGI_FORMAT_BC3_UNORM", + "srvFormat": "DXGI_FORMAT_BC3_UNORM" + } + ], + "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": [ + { + "texFormat": "DXGI_FORMAT_BC1_UNORM", + "srvFormat": "DXGI_FORMAT_BC1_UNORM" + } + ], + "GL_COMPRESSED_SIGNED_R11_EAC": [ + { + "texFormat": "DXGI_FORMAT_R8_SNORM", + "srvFormat": "DXGI_FORMAT_R8_SNORM", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_COMPRESSED_SIGNED_RG11_EAC": [ + { + "texFormat": "DXGI_FORMAT_R8G8_SNORM", + "srvFormat": "DXGI_FORMAT_R8G8_SNORM", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_COMPRESSED_SRGB8_ETC2": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_DEPTH24_STENCIL8": [ + { + "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", + "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS", + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requirementsFcn": "OnlyFL10Plus" + }, + { + "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requirementsFcn": "OnlyFL9_3" + } + ], + "GL_DEPTH32F_STENCIL8": [ + { + "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS", + "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS", + "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT", + "requirementsFcn": "OnlyFL10Plus" + }, + { + "requirementsFcn": "OnlyFL9_3" + } + ], + "GL_DEPTH_COMPONENT16": [ + { + "texFormat": "DXGI_FORMAT_R16_TYPELESS", + "srvFormat": "DXGI_FORMAT_R16_UNORM", + "dsvFormat": "DXGI_FORMAT_D16_UNORM", + "requirementsFcn": "OnlyFL10Plus" + }, + { + "texFormat": "DXGI_FORMAT_D16_UNORM", + "dsvFormat": "DXGI_FORMAT_D16_UNORM", + "requirementsFcn": "OnlyFL9_3" + } + ], + "GL_DEPTH_COMPONENT24": [ + { + "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", + "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS", + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requirementsFcn": "OnlyFL10Plus" + }, + { + "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requirementsFcn": "OnlyFL9_3" + } + ], + "GL_DEPTH_COMPONENT32F": [ + { + "texFormat": "DXGI_FORMAT_R32_TYPELESS", + "srvFormat": "DXGI_FORMAT_R32_FLOAT", + "dsvFormat": "DXGI_FORMAT_D32_FLOAT", + "requirementsFcn": "OnlyFL10Plus" + }, + { + "requirementsFcn": "OnlyFL9_3" + } + ], + "GL_DEPTH_COMPONENT32_OES": [ + { + "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", + "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS", + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requirementsFcn": "OnlyFL10Plus" + } + ], + "GL_ETC1_RGB8_OES": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + } + ], + "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": [ + { + "texFormat": "DXGI_FORMAT_BC1_UNORM", + "srvFormat": "DXGI_FORMAT_BC1_UNORM" + } + ], + "GL_LUMINANCE": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + } + ], + "GL_LUMINANCE16F_EXT": [ + { + "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" + } + ], + "GL_LUMINANCE32F_EXT": [ + { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" + } + ], + "GL_LUMINANCE8_ALPHA8_EXT": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + } + ], + "GL_LUMINANCE8_EXT": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + } + ], + "GL_LUMINANCE_ALPHA": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + } + ], + "GL_LUMINANCE_ALPHA16F_EXT": [ + { + "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" + } + ], + "GL_LUMINANCE_ALPHA32F_EXT": [ + { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" + } + ], + "GL_NONE": [ + { + } + ], + "GL_R11F_G11F_B10F": [ + { + "texFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "srvFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "rtvFormat": "DXGI_FORMAT_R11G11B10_FLOAT" + } + ], + "GL_R16F": [ + { + "texFormat": "DXGI_FORMAT_R16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16_FLOAT" + } + ], + "GL_R16I": [ + { + "texFormat": "DXGI_FORMAT_R16_SINT", + "srvFormat": "DXGI_FORMAT_R16_SINT", + "rtvFormat": "DXGI_FORMAT_R16_SINT" + } + ], + "GL_R16UI": [ + { + "texFormat": "DXGI_FORMAT_R16_UINT", + "srvFormat": "DXGI_FORMAT_R16_UINT", + "rtvFormat": "DXGI_FORMAT_R16_UINT" + } + ], + "GL_R32F": [ + { + "texFormat": "DXGI_FORMAT_R32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32_FLOAT" + } + ], + "GL_R32I": [ + { + "texFormat": "DXGI_FORMAT_R32_SINT", + "srvFormat": "DXGI_FORMAT_R32_SINT", + "rtvFormat": "DXGI_FORMAT_R32_SINT" + } + ], + "GL_R32UI": [ + { + "texFormat": "DXGI_FORMAT_R32_UINT", + "srvFormat": "DXGI_FORMAT_R32_UINT", + "rtvFormat": "DXGI_FORMAT_R32_UINT" + } + ], + "GL_R8": [ + { + "texFormat": "DXGI_FORMAT_R8_UNORM", + "srvFormat": "DXGI_FORMAT_R8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8_UNORM" + } + ], + "GL_R8I": [ + { + "texFormat": "DXGI_FORMAT_R8_SINT", + "srvFormat": "DXGI_FORMAT_R8_SINT", + "rtvFormat": "DXGI_FORMAT_R8_SINT" + } + ], + "GL_R8UI": [ + { + "texFormat": "DXGI_FORMAT_R8_UINT", + "srvFormat": "DXGI_FORMAT_R8_UINT", + "rtvFormat": "DXGI_FORMAT_R8_UINT" + } + ], + "GL_R8_SNORM": [ + { + "texFormat": "DXGI_FORMAT_R8_SNORM", + "srvFormat": "DXGI_FORMAT_R8_SNORM" + } + ], + "GL_RG16F": [ + { + "texFormat": "DXGI_FORMAT_R16G16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16_FLOAT" + } + ], + "GL_RG16I": [ + { + "texFormat": "DXGI_FORMAT_R16G16_SINT", + "srvFormat": "DXGI_FORMAT_R16G16_SINT", + "rtvFormat": "DXGI_FORMAT_R16G16_SINT" + } + ], + "GL_RG16UI": [ + { + "texFormat": "DXGI_FORMAT_R16G16_UINT", + "srvFormat": "DXGI_FORMAT_R16G16_UINT", + "rtvFormat": "DXGI_FORMAT_R16G16_UINT" + } + ], + "GL_RG32F": [ + { + "texFormat": "DXGI_FORMAT_R32G32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32_FLOAT" + } + ], + "GL_RG32I": [ + { + "texFormat": "DXGI_FORMAT_R32G32_SINT", + "srvFormat": "DXGI_FORMAT_R32G32_SINT", + "rtvFormat": "DXGI_FORMAT_R32G32_SINT" + } + ], + "GL_RG32UI": [ + { + "texFormat": "DXGI_FORMAT_R32G32_UINT", + "srvFormat": "DXGI_FORMAT_R32G32_UINT", + "rtvFormat": "DXGI_FORMAT_R32G32_UINT" + } + ], + "GL_RG8": [ + { + "texFormat": "DXGI_FORMAT_R8G8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8_UNORM" + } + ], + "GL_RG8I": [ + { + "texFormat": "DXGI_FORMAT_R8G8_SINT", + "srvFormat": "DXGI_FORMAT_R8G8_SINT", + "rtvFormat": "DXGI_FORMAT_R8G8_SINT" + } + ], + "GL_RG8UI": [ + { + "texFormat": "DXGI_FORMAT_R8G8_UINT", + "srvFormat": "DXGI_FORMAT_R8G8_UINT", + "rtvFormat": "DXGI_FORMAT_R8G8_UINT" + } + ], + "GL_RG8_SNORM": [ + { + "texFormat": "DXGI_FORMAT_R8G8_SNORM", + "srvFormat": "DXGI_FORMAT_R8G8_SNORM" + } + ], + "GL_RGB": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + } + ], + "GL_RGB10_A2": [ + { + "texFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", + "srvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", + "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM" + } + ], + "GL_RGB10_A2UI": [ + { + "texFormat": "DXGI_FORMAT_R10G10B10A2_UINT", + "srvFormat": "DXGI_FORMAT_R10G10B10A2_UINT", + "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UINT" + } + ], + "GL_RGB16F": [ + { + "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" + } + ], + "GL_RGB16I": [ + { + "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT" + } + ], + "GL_RGB16UI": [ + { + "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT" + } + ], + "GL_RGB32F": [ + { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" + } + ], + "GL_RGB32I": [ + { + "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT" + } + ], + "GL_RGB32UI": [ + { + "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT" + } + ], + "GL_RGB565": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requirementsFcn": "SupportsFormat" + }, + { + "texFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "requirementsFcn": "SupportsFormat" + } + ], + "GL_RGB5_A1": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requirementsFcn": "SupportsFormat" + }, + { + "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "srvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "rtvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "requirementsFcn": "SupportsFormat" + } + ], + "GL_RGB8": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + } + ], + "GL_RGB8I": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT" + } + ], + "GL_RGB8UI": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT" + } + ], + "GL_RGB8_SNORM": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM" + } + ], + "GL_RGB9_E5": [ + { + "texFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", + "srvFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP" + } + ], + "GL_RGBA": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + } + ], + "GL_RGBA16F": [ + { + "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT" + } + ], + "GL_RGBA16I": [ + { + "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT" + } + ], + "GL_RGBA16UI": [ + { + "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT" + } + ], + "GL_RGBA32F": [ + { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT" + } + ], + "GL_RGBA32I": [ + { + "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT" + } + ], + "GL_RGBA32UI": [ + { + "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT" + } + ], + "GL_RGBA4": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "requirementsFcn": "SupportsFormat" + }, + { + "texFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "srvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "rtvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "requirementsFcn": "SupportsFormat" + } + ], + "GL_RGBA8": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM" + } + ], + "GL_RGBA8I": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT" + } + ], + "GL_RGBA8UI": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT" + } + ], + "GL_RGBA8_SNORM": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM" + } + ], + "GL_SRGB8": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB" + } + ], + "GL_SRGB8_ALPHA8": [ + { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB" + } + ], + "GL_STENCIL_INDEX8": [ + { + "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", + "srvFormat": "DXGI_FORMAT_X24_TYPELESS_G8_UINT", + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requirementsFcn": "OnlyFL10Plus" + }, + { + "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "requirementsFcn": "OnlyFL9_3" + } + ] +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h new file mode 100644 index 0000000000..1606a28a73 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h @@ -0,0 +1,64 @@ +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// texture_format_table: +// Queries for full textureFormat information based on internalFormat +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_ + +#include + +#include "common/platform.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +namespace d3d11 +{ + +struct LoadImageFunctionInfo +{ + LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {} + LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion) + : loadFunction(loadFunction), requiresConversion(requiresConversion) + { + } + + LoadImageFunction loadFunction; + bool requiresConversion; +}; + +struct TextureFormat +{ + TextureFormat(); + + DXGI_FORMAT texFormat; + DXGI_FORMAT srvFormat; + DXGI_FORMAT rtvFormat; + DXGI_FORMAT dsvFormat; + DXGI_FORMAT renderFormat; + + DXGI_FORMAT swizzleTexFormat; + DXGI_FORMAT swizzleSRVFormat; + DXGI_FORMAT swizzleRTVFormat; + + InitializeTextureDataFunction dataInitializerFunction; + typedef std::map LoadFunctionMap; + + LoadFunctionMap loadFunctions; +}; + +const TextureFormat &GetTextureFormatInfo(GLenum internalformat, + const Renderer11DeviceCaps &renderer11DeviceCaps); + +} // namespace d3d11 + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTUREFORMATTABLE_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp new file mode 100644 index 0000000000..0b214c9756 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp @@ -0,0 +1,1791 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_texture_format_table.py using data from texture_format_data.json +// +// Copyright 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// texture_format_table: +// Queries for full textureFormat information based in internalFormat +// + +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h" +#include "libANGLE/renderer/d3d/d3d11/load_functions_table.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/swizzle_format_info.h" +#include "libANGLE/renderer/d3d/loadimage.h" + +namespace rx +{ + +namespace d3d11 +{ + +namespace +{ + +typedef bool (*FormatSupportFunction)(const Renderer11DeviceCaps &); + +bool AnyDevice(const Renderer11DeviceCaps &deviceCaps) +{ + return true; +} + +bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps) +{ + return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0); +} + +bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps) +{ + return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3); +} + +template +bool SupportsFormat(const Renderer11DeviceCaps &deviceCaps) +{ + // Must support texture, SRV and RTV support + UINT mustSupport = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE | + D3D11_FORMAT_SUPPORT_SHADER_SAMPLE | D3D11_FORMAT_SUPPORT_MIP | + D3D11_FORMAT_SUPPORT_RENDER_TARGET; + + if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel) > 2) + { + mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D; + } + + bool fullSupport = false; + if (format == DXGI_FORMAT_B5G6R5_UNORM) + { + // All hardware that supports DXGI_FORMAT_B5G6R5_UNORM should support autogen mipmaps, but + // check anyway. + mustSupport |= D3D11_FORMAT_SUPPORT_MIP_AUTOGEN; + fullSupport = ((deviceCaps.B5G6R5support & mustSupport) == mustSupport); + } + else if (format == DXGI_FORMAT_B4G4R4A4_UNORM) + { + fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport); + } + else if (format == DXGI_FORMAT_B5G5R5A1_UNORM) + { + fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport); + } + else + { + UNREACHABLE(); + return false; + } + + // This 'SupportsFormat' function is used by individual entries in the D3D11 Format Map below, + // which maps GL formats to DXGI formats. + if (requireSupport) + { + // This means that ANGLE would like to use the entry in the map if the inputted DXGI format + // *IS* supported. + // e.g. the entry might map GL_RGB5_A1 to DXGI_FORMAT_B5G5R5A1, which should only be used if + // DXGI_FORMAT_B5G5R5A1 is supported. + // In this case, we should only return 'true' if the format *IS* supported. + return fullSupport; + } + else + { + // This means that ANGLE would like to use the entry in the map if the inputted DXGI format + // *ISN'T* supported. + // This might be a fallback entry. e.g. for ANGLE to use DXGI_FORMAT_R8G8B8A8_UNORM if + // DXGI_FORMAT_B5G5R5A1 isn't supported. + // In this case, we should only return 'true' if the format *ISN'T* supported. + return !fullSupport; + } +} + +// End Format Support Functions + +// For sized GL internal formats, there are several possible corresponding D3D11 formats depending +// on device capabilities. +// This function allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and +// DSVs given a GL internal format. +const TextureFormat GetD3D11FormatInfo(GLenum internalFormat, + DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, + DXGI_FORMAT rtvFormat, + DXGI_FORMAT dsvFormat) +{ + TextureFormat info; + info.texFormat = texFormat; + info.srvFormat = srvFormat; + info.rtvFormat = rtvFormat; + info.dsvFormat = dsvFormat; + + // Given a GL internal format, the renderFormat is the DSV format if it is depth- or + // stencil-renderable, + // the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise. + if (dsvFormat != DXGI_FORMAT_UNKNOWN) + { + info.renderFormat = dsvFormat; + } + else if (rtvFormat != DXGI_FORMAT_UNKNOWN) + { + info.renderFormat = rtvFormat; + } + else if (texFormat != DXGI_FORMAT_UNKNOWN) + { + info.renderFormat = texFormat; + } + else + { + info.renderFormat = DXGI_FORMAT_UNKNOWN; + } + + // Compute the swizzle formats + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0) + { + if (formatInfo.componentCount != 4 || texFormat == DXGI_FORMAT_UNKNOWN || + srvFormat == DXGI_FORMAT_UNKNOWN || rtvFormat == DXGI_FORMAT_UNKNOWN) + { + // Get the maximum sized component + unsigned int maxBits = 1; + if (formatInfo.compressed) + { + unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8; + unsigned int blockSize = + formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight; + maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits); + } + else + { + maxBits = std::max(maxBits, formatInfo.alphaBits); + maxBits = std::max(maxBits, formatInfo.redBits); + maxBits = std::max(maxBits, formatInfo.greenBits); + maxBits = std::max(maxBits, formatInfo.blueBits); + maxBits = std::max(maxBits, formatInfo.luminanceBits); + maxBits = std::max(maxBits, formatInfo.depthBits); + } + + maxBits = roundUp(maxBits, 8U); + + const SwizzleFormatInfo &swizzleInfo = + GetSwizzleFormatInfo(maxBits, formatInfo.componentType); + info.swizzleTexFormat = swizzleInfo.mTexFormat; + info.swizzleSRVFormat = swizzleInfo.mSRVFormat; + info.swizzleRTVFormat = swizzleInfo.mRTVFormat; + } + else + { + // The original texture format is suitable for swizzle operations + info.swizzleTexFormat = texFormat; + info.swizzleSRVFormat = srvFormat; + info.swizzleRTVFormat = rtvFormat; + } + } + else + { + // Not possible to swizzle with this texture format since it is either unsized or GL_NONE + info.swizzleTexFormat = DXGI_FORMAT_UNKNOWN; + info.swizzleSRVFormat = DXGI_FORMAT_UNKNOWN; + info.swizzleRTVFormat = DXGI_FORMAT_UNKNOWN; + } + + // Check if there is an initialization function for this texture format + info.dataInitializerFunction = GetInternalFormatInitializer(internalFormat, texFormat); + // Gather all the load functions for this internal format + info.loadFunctions = GetLoadFunctionsMap(internalFormat, texFormat); + + ASSERT(info.loadFunctions.size() != 0 || internalFormat == GL_NONE); + + return info; +} + +} // namespace + +TextureFormat::TextureFormat() + : texFormat(DXGI_FORMAT_UNKNOWN), + srvFormat(DXGI_FORMAT_UNKNOWN), + rtvFormat(DXGI_FORMAT_UNKNOWN), + dsvFormat(DXGI_FORMAT_UNKNOWN), + renderFormat(DXGI_FORMAT_UNKNOWN), + swizzleTexFormat(DXGI_FORMAT_UNKNOWN), + swizzleSRVFormat(DXGI_FORMAT_UNKNOWN), + swizzleRTVFormat(DXGI_FORMAT_UNKNOWN), + dataInitializerFunction(NULL), + loadFunctions() +{ +} + +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps) +{ + // clang-format off + switch (internalFormat) + { + case GL_ALPHA: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else if (OnlyFL9_3(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_ALPHA16F_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_ALPHA32F_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_ALPHA8_EXT: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else if (OnlyFL9_3(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_BGR5_A1_ANGLEX: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_BGRA4_ANGLEX: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_BGRA8_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_BGRA_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_R11_EAC: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_RG11_EAC: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_RGB8_ETC2: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_RGBA8_ETC2_EAC: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_BC2_UNORM, + DXGI_FORMAT_BC2_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_BC3_UNORM, + DXGI_FORMAT_BC3_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_SIGNED_R11_EAC: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_SIGNED_RG11_EAC: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_SRGB8_ETC2: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_DEPTH24_STENCIL8: + { + if (OnlyFL9_3(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT); + return textureFormat; + } + else if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT); + return textureFormat; + } + else + { + break; + } + } + case GL_DEPTH32F_STENCIL8: + { + if (OnlyFL9_3(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G8X24_TYPELESS, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT); + return textureFormat; + } + else + { + break; + } + } + case GL_DEPTH_COMPONENT16: + { + if (OnlyFL9_3(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_D16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D16_UNORM); + return textureFormat; + } + else if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16_TYPELESS, + DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D16_UNORM); + return textureFormat; + } + else + { + break; + } + } + case GL_DEPTH_COMPONENT24: + { + if (OnlyFL9_3(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT); + return textureFormat; + } + else if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT); + return textureFormat; + } + else + { + break; + } + } + case GL_DEPTH_COMPONENT32F: + { + if (OnlyFL9_3(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32_TYPELESS, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D32_FLOAT); + return textureFormat; + } + else + { + break; + } + } + case GL_DEPTH_COMPONENT32_OES: + { + if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT); + return textureFormat; + } + else + { + break; + } + } + case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_ETC1_RGB8_OES: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_LUMINANCE: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_LUMINANCE16F_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_LUMINANCE32F_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_LUMINANCE8_ALPHA8_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_LUMINANCE8_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_LUMINANCE_ALPHA: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_LUMINANCE_ALPHA16F_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_LUMINANCE_ALPHA32F_EXT: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_NONE: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R11F_G11F_B10F: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R11G11B10_FLOAT, + DXGI_FORMAT_R11G11B10_FLOAT, + DXGI_FORMAT_R11G11B10_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R16F: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R16I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R16UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16_UINT, + DXGI_FORMAT_R16_UINT, + DXGI_FORMAT_R16_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R32F: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R32I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32_SINT, + DXGI_FORMAT_R32_SINT, + DXGI_FORMAT_R32_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R32UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32_UINT, + DXGI_FORMAT_R32_UINT, + DXGI_FORMAT_R32_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R8: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R8I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8_SINT, + DXGI_FORMAT_R8_SINT, + DXGI_FORMAT_R8_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R8UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_R8_SNORM: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG16F: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG16I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG16UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16_UINT, + DXGI_FORMAT_R16G16_UINT, + DXGI_FORMAT_R16G16_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG32F: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG32I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32_SINT, + DXGI_FORMAT_R32G32_SINT, + DXGI_FORMAT_R32G32_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG32UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32_UINT, + DXGI_FORMAT_R32G32_UINT, + DXGI_FORMAT_R32G32_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG8: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG8I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8_SINT, + DXGI_FORMAT_R8G8_SINT, + DXGI_FORMAT_R8G8_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG8UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RG8_SNORM: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB10_A2: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB10_A2UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R10G10B10A2_UINT, + DXGI_FORMAT_R10G10B10A2_UINT, + DXGI_FORMAT_R10G10B10A2_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB16F: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB16I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB16UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB32F: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB32I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB32UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB565: + { + if (SupportsFormat(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else if (SupportsFormat(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB5_A1: + { + if (SupportsFormat(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else if (SupportsFormat(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB8: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB8I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB8UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB8_SNORM: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGB9_E5: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA16F: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA16I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA16UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA32F: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA32I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA32UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA4: + { + if (SupportsFormat(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else if (SupportsFormat(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA8: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA8I: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA8UI: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_RGBA8_SNORM: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_SRGB8: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_SRGB8_ALPHA8: + { + if (AnyDevice(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN); + return textureFormat; + } + else + { + break; + } + } + case GL_STENCIL_INDEX8: + { + if (OnlyFL9_3(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT); + return textureFormat; + } + else if (OnlyFL10Plus(renderer11DeviceCaps)) + { + static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_X24_TYPELESS_G8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT); + return textureFormat; + } + else + { + break; + } + } + + default: + break; + } + // clang-format on + + static const TextureFormat defaultInfo; + return defaultInfo; +} // GetTextureFormatInfo + +} // namespace d3d11 + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp index 696dfd72f8..da6460b136 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp @@ -7,19 +7,42 @@ // NativeWindow.cpp: Handler for managing HWND native window types. #include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "common/debug.h" +#include +#if !defined(__MINGW32__) +#include +#endif + namespace rx { -NativeWindow::NativeWindow(EGLNativeWindowType window) : mWindow(window) +NativeWindow::NativeWindow(EGLNativeWindowType window, + const egl::Config *config, + bool directComposition) + : mWindow(window), + mDirectComposition(directComposition), + mDevice(nullptr), + mCompositionTarget(nullptr), + mVisual(nullptr), + mConfig(config) { } +NativeWindow::~NativeWindow() +{ +#if !defined(__MINGW32__) + SafeRelease(mCompositionTarget); + SafeRelease(mDevice); + SafeRelease(mVisual); +#endif +} + bool NativeWindow::initialize() -{ - return true; +{ + return true; } bool NativeWindow::getClientRect(LPRECT rect) @@ -47,7 +70,117 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory return E_INVALIDARG; } - DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 }; +#if !defined(__MINGW32__) + if (mDirectComposition) + { + HMODULE dcomp = ::GetModuleHandle(TEXT("dcomp.dll")); + if (!dcomp) + { + return E_INVALIDARG; + } + + typedef HRESULT(WINAPI * PFN_DCOMPOSITION_CREATE_DEVICE)( + IDXGIDevice * dxgiDevice, REFIID iid, void **dcompositionDevice); + PFN_DCOMPOSITION_CREATE_DEVICE createDComp = + reinterpret_cast( + GetProcAddress(dcomp, "DCompositionCreateDevice")); + if (!createDComp) + { + return E_INVALIDARG; + } + + if (!mDevice) + { + IDXGIDevice *dxgiDevice = d3d11::DynamicCastComObject(device); + HRESULT result = createDComp(dxgiDevice, __uuidof(IDCompositionDevice), + reinterpret_cast(&mDevice)); + SafeRelease(dxgiDevice); + + if (FAILED(result)) + { + return result; + } + } + + if (!mCompositionTarget) + { + HRESULT result = mDevice->CreateTargetForHwnd(mWindow, TRUE, &mCompositionTarget); + if (FAILED(result)) + { + return result; + } + } + + if (!mVisual) + { + HRESULT result = mDevice->CreateVisual(&mVisual); + if (FAILED(result)) + { + return result; + } + } + + IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject(factory); + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = + DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT; + swapChainDesc.BufferCount = 2; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + swapChainDesc.AlphaMode = + mConfig->alphaSize == 0 ? DXGI_ALPHA_MODE_IGNORE : DXGI_ALPHA_MODE_PREMULTIPLIED; + swapChainDesc.Flags = 0; + IDXGISwapChain1 *swapChain1 = nullptr; + HRESULT result = + factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1); + if (SUCCEEDED(result)) + { + *swapChain = static_cast(swapChain1); + } + mVisual->SetContent(swapChain1); + mCompositionTarget->SetRoot(mVisual); + SafeRelease(factory2); + return result; + } + + // Use IDXGIFactory2::CreateSwapChainForHwnd if DXGI 1.2 is available to create a DXGI_SWAP_EFFECT_SEQUENTIAL swap chain. + IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject(factory); + if (factory2 != nullptr) + { + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; + swapChainDesc.Width = width; + swapChainDesc.Height = height; + swapChainDesc.Format = format; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = + DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferCount = 1; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + swapChainDesc.Flags = 0; + IDXGISwapChain1 *swapChain1 = nullptr; + HRESULT result = factory2->CreateSwapChainForHwnd(device, mWindow, &swapChainDesc, nullptr, nullptr, &swapChain1); + if (SUCCEEDED(result)) + { + const HRESULT makeWindowAssociationResult = factory->MakeWindowAssociation(mWindow, DXGI_MWA_NO_ALT_ENTER); + UNUSED_VARIABLE(makeWindowAssociationResult); + *swapChain = static_cast(swapChain1); + } + SafeRelease(factory2); + return result; + } +#endif // !__MINGW32__ + + DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; swapChainDesc.BufferCount = 1; swapChainDesc.BufferDesc.Format = format; swapChainDesc.BufferDesc.Width = width; @@ -56,7 +189,8 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferUsage = + DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; swapChainDesc.Flags = 0; swapChainDesc.OutputWindow = mWindow; swapChainDesc.SampleDesc.Count = 1; @@ -68,9 +202,19 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory if (SUCCEEDED(result)) { const HRESULT makeWindowAssociationResult = factory->MakeWindowAssociation(mWindow, DXGI_MWA_NO_ALT_ENTER); - UNUSED_TRACE_VARIABLE(makeWindowAssociationResult); + UNUSED_VARIABLE(makeWindowAssociationResult); } return result; } #endif + +void NativeWindow::commitChange() +{ +#if !defined(__MINGW32__) + if (mDevice) + { + mDevice->Commit(); + } +#endif +} } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp index f45a077d97..f401db614b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp @@ -23,7 +23,6 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet ComPtr props = propertySet; ComPtr win = window; SIZE swapChainSize = {}; - bool swapChainSizeSpecified = false; HRESULT result = S_OK; // IPropertySet is an optional parameter and can be null. @@ -32,12 +31,40 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet if (propertySet) { result = props.As(&mPropertyMap); - if (SUCCEEDED(result)) + if (FAILED(result)) + { + return false; + } + + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &mSwapChainSizeSpecified); + if (FAILED(result)) + { + return false; + } + + // The EGLRenderResolutionScaleProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSinglePropertyValue(mPropertyMap, EGLRenderResolutionScaleProperty, &mSwapChainScale, &mSwapChainScaleSpecified); + if (FAILED(result)) + { + return false; + } + + if (!mSwapChainScaleSpecified) { - // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet - // was prevalidated to contain the EGLNativeWindowType before being passed to - // this host. - result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + // Default value for the scale is 1.0f + mSwapChainScale = 1.0f; + } + + // A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified + if (mSwapChainScaleSpecified && mSwapChainSizeSpecified) + { + ERR("It is invalid to specify both an EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty."); + return false; } } @@ -54,14 +81,19 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet // of the host. // Scaling of the swapchain output occurs automatically because if // the scaling mode setting DXGI_SCALING_STRETCH on the swapchain. - if (swapChainSizeSpecified) + if (mSwapChainSizeSpecified) { mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; - mSupportsSwapChainResize = false; } else { - result = GetCoreWindowSizeInPixels(mCoreWindow, &mClientRect); + SIZE coreWindowSize; + result = GetCoreWindowSizeInPixels(mCoreWindow, &coreWindowSize); + + if (SUCCEEDED(result)) + { + mClientRect = { 0, 0, static_cast(coreWindowSize.cx * mSwapChainScale), static_cast(coreWindowSize.cy * mSwapChainScale) }; + } } } @@ -118,17 +150,25 @@ void CoreWindowNativeWindow::unregisterForSizeChangeEvents() { (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken); } + #if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) if (mDisplayInformation) { (void)mDisplayInformation->remove_OrientationChanged(mOrientationChangedEventToken); } #endif + mSizeChangedEventToken.value = 0; mOrientationChangedEventToken.value = 0; } -HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, + DXGIFactory *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + DXGISwapChain **swapChain) { if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) { @@ -142,10 +182,12 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferUsage = + DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; swapChainDesc.BufferCount = 2; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; *swapChain = nullptr; @@ -180,13 +222,20 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor return result; } -HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, RECT *windowSize) +inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect) +{ + // We don't need to do any additional work to scale CoreWindow swapchains. + // Using DXGI_SCALING_STRETCH to create the swapchain above does all the necessary work. + return S_OK; +} + +HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, SIZE *windowSize) { ABI::Windows::Foundation::Rect bounds; HRESULT result = coreWindow->get_Bounds(&bounds); if (SUCCEEDED(result)) { - *windowSize = { 0, 0, ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) }; + *windowSize = { ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) }; } return result; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h index 87cdfe6f22..fc1cd124a1 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h @@ -19,16 +19,25 @@ typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CD namespace rx { - class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this { public: ~CoreWindowNativeWindow(); - bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); + bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override; + HRESULT createSwapChain(ID3D11Device *device, + DXGIFactory *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + DXGISwapChain **swapChain) override; + + protected: + HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override; + bool registerForSizeChangeEvents(); void unregisterForSizeChangeEvents(); - HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); private: ComPtr mCoreWindow; @@ -70,39 +79,40 @@ class CoreWindowSizeChangedHandler : return S_OK; } - IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *) - { -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - NativeWindow::RotationFlags flags = NativeWindow::RotateNone; - ABI::Windows::Graphics::Display::DisplayOrientations orientation; - if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation))) + IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *) { - switch (orientation) + #if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + NativeWindow::RotationFlags flags = NativeWindow::RotateNone; + ABI::Windows::Graphics::Display::DisplayOrientations orientation; + if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation))) { - case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape: - flags = NativeWindow::RotateLeft; - break; - case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped: - flags = NativeWindow::RotateRight; - break; - default: - break; + switch (orientation) + { + case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape: + flags = NativeWindow::RotateLeft; + break; + case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped: + flags = NativeWindow::RotateRight; + break; + default: + break; + } } + std::shared_ptr host = mHost.lock(); + if (host) + { + host->setRotationFlags(flags); + } + #endif + return S_OK; } - std::shared_ptr host = mHost.lock(); - if (host) - { - host->setRotationFlags(flags); - } -#endif - return S_OK; - } + private: std::weak_ptr mHost; }; -HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, RECT *windowSize); +HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, SIZE *windowSize); } #endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp index e83f47929f..aacfadd2f0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp @@ -11,9 +11,20 @@ namespace rx { -NativeWindow::NativeWindow(EGLNativeWindowType window) +NativeWindow::NativeWindow(EGLNativeWindowType window, + const egl::Config *config, + bool directComposition) { mWindow = window; + mConfig = config; +} + +NativeWindow::~NativeWindow() +{ +} + +void NativeWindow::commitChange() +{ } bool NativeWindow::initialize() @@ -95,7 +106,9 @@ HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory { if (mImpl) { - return mImpl->createSwapChain(device, factory, format, width, height, swapChain); + bool containsAlpha = (mConfig->alphaSize > 0); + return mImpl->createSwapChain(device, factory, format, width, height, containsAlpha, + swapChain); } return E_UNEXPECTED; @@ -209,16 +222,47 @@ bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Founda // A Valid EGLNativeWindowType IInspectable can only be: // // ICoreWindow +// ISwapChainPanel // IPropertySet -// +// // Anything else will be rejected as an invalid IInspectable. bool IsValidEGLNativeWindowType(EGLNativeWindowType window) { return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window); } +// Retrieve an optional property from a property set +HRESULT GetOptionalPropertyValue(const ComPtr> &propertyMap, + const wchar_t *propertyName, + boolean *hasKey, + ComPtr &propertyValue) +{ + if (!propertyMap || !hasKey) + { + return E_INVALIDARG; + } + + // Assume that the value does not exist + *hasKey = false; + + HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), hasKey); + if (SUCCEEDED(result) && !(*hasKey)) + { + // Value does not exist, so return S_OK and set the exists parameter to false to indicate + // that a the optional property does not exist. + return S_OK; + } + + if (SUCCEEDED(result)) + { + result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue); + } + + return result; +} + // Attempts to read an optional SIZE property value that is assumed to be in the form of -// an ABI::Windows::Foundation::Size. This function validates the Size value before returning +// an ABI::Windows::Foundation::Size. This function validates the Size value before returning // it to the caller. // // Possible return values are: @@ -229,62 +273,110 @@ bool IsValidEGLNativeWindowType(EGLNativeWindowType window) // * Invalid property value (width/height must be > 0) // Additional errors may be returned from IMap or IPropertyValue // -HRESULT GetOptionalSizePropertyValue(const ComPtr>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists) +HRESULT GetOptionalSizePropertyValue(const ComPtr> &propertyMap, + const wchar_t *propertyName, SIZE *value, bool *valueExists) { - if (!propertyMap || !propertyName || !value || !valueExists) + ComPtr propertyValue; + ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; + Size sizeValue = { 0, 0 }; + boolean hasKey = false; + + if (!propertyMap || !value || !valueExists) { - return false; + return E_INVALIDARG; } // Assume that the value does not exist *valueExists = false; *value = { 0, 0 }; + HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue); + if (SUCCEEDED(result) && hasKey) + { + result = propertyValue->get_Type(&propertyType); + + // Check if the expected Size property is of PropertyType_Size type. + if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size) + { + if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0)) + { + // A valid property value exists + *value = { static_cast(sizeValue.Width), static_cast(sizeValue.Height) }; + *valueExists = true; + result = S_OK; + } + else + { + // An invalid Size property was detected. Width/Height values must > 0 + result = E_INVALIDARG; + } + } + else + { + // An invalid property type was detected. Size property must be of PropertyType_Size + result = E_INVALIDARG; + } + } + + return result; +} + +// Attempts to read an optional float property value that is assumed to be in the form of +// an ABI::Windows::Foundation::Single. This function validates the Single value before returning +// it to the caller. +// +// Possible return values are: +// S_OK, valueExists == true - optional Single value was successfully retrieved and validated +// S_OK, valueExists == false - optional Single value was not found +// E_INVALIDARG, valueExists = false - optional Single value was malformed in the property set. +// * Incorrect property type ( must be PropertyType_Single) +// * Invalid property value (must be > 0) +// Additional errors may be returned from IMap or IPropertyValue +// +HRESULT GetOptionalSinglePropertyValue(const ComPtr> &propertyMap, + const wchar_t *propertyName, float *value, bool *valueExists) +{ ComPtr propertyValue; ABI::Windows::Foundation::PropertyType propertyType = ABI::Windows::Foundation::PropertyType::PropertyType_Empty; - Size sizeValue = { 0, 0 }; + float scaleValue = 0.0f; boolean hasKey = false; - HRESULT result = propertyMap->HasKey(HStringReference(propertyName).Get(), &hasKey); - if (SUCCEEDED(result) && !hasKey) + if (!propertyMap || !value || !valueExists) { - // Value does not exist, so return S_OK and set the exists parameter to false to indicate - // that a the optional property does not exist. - *valueExists = false; - return S_OK; + return E_INVALIDARG; } - if (SUCCEEDED(result)) - { - result = propertyMap->Lookup(HStringReference(propertyName).Get(), &propertyValue); - } + // Assume that the value does not exist + *valueExists = false; + *value = 0.0f; - if (SUCCEEDED(result)) + HRESULT result = GetOptionalPropertyValue(propertyMap, propertyName, &hasKey, propertyValue); + if (SUCCEEDED(result) && hasKey) { result = propertyValue->get_Type(&propertyType); - } - // Check if the expected Size property is of PropertyType_Size type. - if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Size) - { - if (SUCCEEDED(propertyValue->GetSize(&sizeValue)) && (sizeValue.Width > 0 && sizeValue.Height > 0)) + // Check if the expected Scale property is of PropertyType_Single type. + if (SUCCEEDED(result) && propertyType == ABI::Windows::Foundation::PropertyType::PropertyType_Single) { - // A valid property value exists - *value = { static_cast(sizeValue.Width), static_cast(sizeValue.Height) }; - *valueExists = true; - result = S_OK; + if (SUCCEEDED(propertyValue->GetSingle(&scaleValue)) && (scaleValue > 0.0f)) + { + // A valid property value exists + *value = scaleValue; + *valueExists = true; + result = S_OK; + } + else + { + // An invalid scale was set + result = E_INVALIDARG; + } } else { - // An invalid Size property was detected. Width/Height values must > 0 + // An invalid property type was detected. Size property must be of PropertyType_Single result = E_INVALIDARG; } } - else - { - // An invalid property type was detected. Size property must be of PropertyType_Size - result = E_INVALIDARG; - } return result; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h index f0534077ae..2d58f1c00a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h @@ -33,7 +33,9 @@ class InspectableNativeWindow public: InspectableNativeWindow() : mSupportsSwapChainResize(true), - mRequiresSwapChainScaling(false), + mSwapChainSizeSpecified(false), + mSwapChainScaleSpecified(false), + mSwapChainScale(1.0f), mClientRectChanged(false), mClientRect({0,0,0,0}), mNewClientRect({0,0,0,0}), @@ -44,14 +46,17 @@ class InspectableNativeWindow virtual ~InspectableNativeWindow(){} virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0; - virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0; - virtual bool registerForSizeChangeEvents() = 0; - virtual void unregisterForSizeChangeEvents() = 0; - virtual HRESULT scaleSwapChain(const Size& newSize) { return S_OK; } + virtual HRESULT createSwapChain(ID3D11Device *device, + DXGIFactory *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + DXGISwapChain **swapChain) = 0; bool getClientRect(RECT *rect) { - if (mClientRectChanged && mSupportsSwapChainResize) + if (mClientRectChanged) { mClientRect = mNewClientRect; } @@ -61,17 +66,34 @@ class InspectableNativeWindow return true; } - void setNewClientSize(const Size &newSize) + // setNewClientSize is used by the WinRT size change handler. It isn't used by the rest of ANGLE. + void setNewClientSize(const Size &newWindowSize) { - if (mSupportsSwapChainResize) - { - mNewClientRect = { 0, 0, ConvertDipsToPixels(newSize.Width), ConvertDipsToPixels(newSize.Height) }; - mClientRectChanged = true; - } + // If the client doesn't support swapchain resizing then we should have already unregistered from size change handler + ASSERT(mSupportsSwapChainResize); - if (mRequiresSwapChainScaling) + if (mSupportsSwapChainResize) { - scaleSwapChain(newSize); + // If the swapchain size was specified then we should ignore this call too + if (!mSwapChainSizeSpecified) + { + // We don't have to check if a swapchain scale was specified here; the default value is 1.0f which will have no effect. + mNewClientRect = { 0, 0, ConvertDipsToPixels(newWindowSize.Width), ConvertDipsToPixels(newWindowSize.Height) }; + mClientRectChanged = true; + + // If a scale was specified, then now is the time to apply the scale matrix for the new swapchain size and window size + if (mSwapChainScaleSpecified) + { + scaleSwapChain(newWindowSize, mNewClientRect); + } + } + + // Even if the swapchain size was fixed, the window might have changed size. + // In this case, we should recalculate the scale matrix to account for the new window size + if (mSwapChainSizeSpecified) + { + scaleSwapChain(newWindowSize, mClientRect); + } } } @@ -85,9 +107,13 @@ class InspectableNativeWindow mRotationFlags = flags; } -protected: - bool mSupportsSwapChainResize; - bool mRequiresSwapChainScaling; + protected: + virtual HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) = 0; + + bool mSupportsSwapChainResize; // Support for IDXGISwapChain::ResizeBuffers method + bool mSwapChainSizeSpecified; // If an EGLRenderSurfaceSizeProperty was specified + bool mSwapChainScaleSpecified; // If an EGLRenderResolutionScaleProperty was specified + float mSwapChainScale; // The scale value specified by the EGLRenderResolutionScaleProperty property RECT mClientRect; RECT mNewClientRect; bool mClientRectChanged; @@ -100,8 +126,17 @@ bool IsValidEGLNativeWindowType(EGLNativeWindowType window); bool IsCoreWindow(EGLNativeWindowType window, ComPtr *coreWindow = nullptr); bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr *swapChainPanel = nullptr); bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr); -HRESULT GetOptionalSizePropertyValue(const ComPtr>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists); +HRESULT GetOptionalPropertyValue(const ComPtr> &propertyMap, + const wchar_t *propertyName, + boolean *hasKey, + ComPtr &propertyValue); + +HRESULT GetOptionalSizePropertyValue(const ComPtr> &propertyMap, + const wchar_t *propertyName, SIZE *value, bool *valueExists); + +HRESULT GetOptionalSinglePropertyValue(const ComPtr> &propertyMap, + const wchar_t *propertyName, float *value, bool *valueExists); } #endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp index 0b48b54334..d3ed35b3c6 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp @@ -11,7 +11,11 @@ #include #include +using namespace ABI::Windows::Foundation; using namespace ABI::Windows::Foundation::Collections; +using namespace ABI::Windows::UI::Core; +using namespace ABI::Windows::UI::Xaml; +using namespace Microsoft::WRL; namespace rx { @@ -20,12 +24,74 @@ SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() unregisterForSizeChangeEvents(); } +template +struct AddFtmBase +{ + typedef Implements, T, FtmBase> Type; +}; + +template +HRESULT RunOnUIThread(CODE &&code, const ComPtr &dispatcher) +{ + ComPtr asyncAction; + HRESULT result = S_OK; + + boolean hasThreadAccess; + result = dispatcher->get_HasThreadAccess(&hasThreadAccess); + if (FAILED(result)) + { + return result; + } + + if (hasThreadAccess) + { + return code(); + } + else + { + Event waitEvent(CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS)); + if (!waitEvent.IsValid()) + { + return E_FAIL; + } + + HRESULT codeResult = E_FAIL; + auto handler = + Callback::Type>([&codeResult, &code, &waitEvent] + { + codeResult = code(); + SetEvent(waitEvent.Get()); + return S_OK; + }); + + result = dispatcher->RunAsync(CoreDispatcherPriority_Normal, handler.Get(), + asyncAction.GetAddressOf()); + if (FAILED(result)) + { + return result; + } + + auto waitResult = WaitForSingleObjectEx(waitEvent.Get(), 10 * 1000, true); + if (waitResult != WAIT_OBJECT_0) + { + // Wait 10 seconds before giving up. At this point, the application is in an + // unrecoverable state (probably deadlocked). We therefore terminate the application + // entirely. This also prevents stack corruption if the async operation is eventually + // run. + ERR("Timeout waiting for async action on UI thread. The UI thread might be blocked."); + std::terminate(); + return E_FAIL; + } + + return codeResult; + } +} + bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) { ComPtr props = propertySet; ComPtr win = window; SIZE swapChainSize = {}; - bool swapChainSizeSpecified = false; HRESULT result = S_OK; // IPropertySet is an optional parameter and can be null. @@ -34,12 +100,40 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert if (propertySet) { result = props.As(&mPropertyMap); - if (SUCCEEDED(result)) + if (FAILED(result)) + { + return false; + } + + // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &mSwapChainSizeSpecified); + if (FAILED(result)) + { + return false; + } + + // The EGLRenderResolutionScaleProperty is optional and may be missing. The IPropertySet + // was prevalidated to contain the EGLNativeWindowType before being passed to + // this host. + result = GetOptionalSinglePropertyValue(mPropertyMap, EGLRenderResolutionScaleProperty, &mSwapChainScale, &mSwapChainScaleSpecified); + if (FAILED(result)) + { + return false; + } + + if (!mSwapChainScaleSpecified) + { + // Default value for the scale is 1.0f + mSwapChainScale = 1.0f; + } + + // A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified + if (mSwapChainScaleSpecified && mSwapChainSizeSpecified) { - // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet - // was prevalidated to contain the EGLNativeWindowType before being passed to - // this host. - result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); + ERR("It is invalid to specify both an EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty."); + return false; } } @@ -48,6 +142,18 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert result = win.As(&mSwapChainPanel); } + ComPtr swapChainPanelDependencyObject; + if (SUCCEEDED(result)) + { + result = mSwapChainPanel.As(&swapChainPanelDependencyObject); + } + + if (SUCCEEDED(result)) + { + result = swapChainPanelDependencyObject->get_Dispatcher( + mSwapChainPanelDispatcher.GetAddressOf()); + } + if (SUCCEEDED(result)) { // If a swapchain size is specfied, then the automatic resize @@ -57,16 +163,24 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert // Scaling of the swapchain output needs to be handled by the // host for swapchain panels even though the scaling mode setting // DXGI_SCALING_STRETCH is configured on the swapchain. - if (swapChainSizeSpecified) + if (mSwapChainSizeSpecified) { mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; - - // Enable host swapchain scaling - mRequiresSwapChainScaling = true; } else { - result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect, &mRequiresSwapChainScaling); + SIZE swapChainPanelSize; + result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher, + &swapChainPanelSize, &mSwapChainScale); + if (mSwapChainScale != 1.0f) + mSwapChainScaleSpecified = true; + + if (SUCCEEDED(result)) + { + // Update the client rect to account for any swapchain scale factor + mClientRect = { 0, 0, static_cast(ConvertDipsToPixels(swapChainPanelSize.cx * mSwapChainScale)), + static_cast(ConvertDipsToPixels(swapChainPanelSize.cy * mSwapChainScale)) }; + } } } @@ -82,8 +196,8 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() { - ComPtr sizeChangedHandler; - ComPtr frameworkElement; + ComPtr sizeChangedHandler; + ComPtr frameworkElement; HRESULT result = Microsoft::WRL::MakeAndInitialize(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); if (SUCCEEDED(result)) @@ -93,7 +207,13 @@ bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() if (SUCCEEDED(result)) { - result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); + result = RunOnUIThread( + [this, frameworkElement, sizeChangedHandler] + { + return frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), + &mSizeChangedEventToken); + }, + mSwapChainPanelDispatcher); } if (SUCCEEDED(result)) @@ -106,16 +226,27 @@ bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() { - ComPtr frameworkElement; - if (SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) + ComPtr frameworkElement; + if (mSwapChainPanel && SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) { - (void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken); + RunOnUIThread( + [this, frameworkElement] + { + return frameworkElement->remove_SizeChanged(mSizeChangedEventToken); + }, + mSwapChainPanelDispatcher); } mSizeChangedEventToken.value = 0; } -HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) +HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, + DXGIFactory *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + DXGISwapChain **swapChain) { if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) { @@ -129,11 +260,13 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFa swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.BufferUsage = + DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; swapChainDesc.BufferCount = 2; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swapChainDesc.Scaling = DXGI_SCALING_STRETCH; - swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.AlphaMode = + containsAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; *swapChain = nullptr; @@ -149,7 +282,12 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFa if (SUCCEEDED(result)) { - result = swapChainPanelNative->SetSwapChain(newSwapChain.Get()); + result = RunOnUIThread( + [swapChainPanelNative, newSwapChain] + { + return swapChainPanelNative->SetSwapChain(newSwapChain.Get()); + }, + mSwapChainPanelDispatcher); } if (SUCCEEDED(result)) @@ -164,34 +302,28 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFa // If the host is responsible for scaling the output of the swapchain, then // scale it now before returning an instance to the caller. This is done by // first reading the current size of the swapchain panel, then scaling - if (SUCCEEDED(result) && mRequiresSwapChainScaling) - { - ComPtr uiElement; - result = mSwapChainPanel.As(&uiElement); - ASSERT(SUCCEEDED(result)); - - Size currentSize; - result = uiElement->get_RenderSize(¤tSize); - ASSERT(SUCCEEDED(result)); - result = scaleSwapChain(currentSize); - } - if (SUCCEEDED(result)) { - // If automatic swapchain resize behaviors have been disabled, then - // unregister for the resize change events. - if (mSupportsSwapChainResize == false) + if (mSwapChainSizeSpecified || mSwapChainScaleSpecified) { - unregisterForSizeChangeEvents(); + ComPtr uiElement; + result = mSwapChainPanel.As(&uiElement); + ASSERT(SUCCEEDED(result)); + + Size currentSize; + result = uiElement->get_RenderSize(¤tSize); + ASSERT(SUCCEEDED(result)); + result = scaleSwapChain(currentSize, mClientRect); } } return result; } -HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &newSize) +HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect) { - ABI::Windows::Foundation::Size renderScale = { newSize.Width / mNewClientRect.right, newSize.Height / mNewClientRect.bottom }; + Size renderScale = {windowSize.Width / clientRect.right, + windowSize.Height / clientRect.bottom}; // Setup a scale matrix for the swap chain DXGI_MATRIX_3X2_F scaleMatrix = {}; scaleMatrix._11 = renderScale.Width; @@ -207,25 +339,33 @@ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &newSize) return result; } -HRESULT GetSwapChainPanelSize(const ComPtr &swapChainPanel, RECT *windowSize, bool *scalingActive) +HRESULT GetSwapChainPanelSize( + const ComPtr &swapChainPanel, + const ComPtr &dispatcher, + SIZE *windowSize, float *scaleFactor) { - ComPtr uiElement; - ABI::Windows::Foundation::Size renderSize = { 0, 0 }; + ComPtr uiElement; + Size renderSize = {0, 0}; HRESULT result = swapChainPanel.As(&uiElement); if (SUCCEEDED(result)) { - result = uiElement->get_RenderSize(&renderSize); + result = RunOnUIThread( + [uiElement, &renderSize] + { + return uiElement->get_RenderSize(&renderSize); + }, + dispatcher); } if (SUCCEEDED(result)) { long width = ConvertDipsToPixels(renderSize.Width); long height = ConvertDipsToPixels(renderSize.Height); - *windowSize = { 0, 0, width, height }; + *windowSize = { width, height }; - if (scalingActive) + if (scaleFactor) { - *scalingActive = width != renderSize.Width || height != renderSize.Height; + *scaleFactor = renderSize.Width / width; } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h index 5debd2fd0b..09d87ad523 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h @@ -18,14 +18,24 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e public: ~SwapChainPanelNativeWindow(); - bool initialize(EGLNativeWindowType window, IPropertySet *propertySet); + bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override; + HRESULT createSwapChain(ID3D11Device *device, + DXGIFactory *factory, + DXGI_FORMAT format, + unsigned int width, + unsigned int height, + bool containsAlpha, + DXGISwapChain **swapChain) override; + + protected: + HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override; + bool registerForSizeChangeEvents(); void unregisterForSizeChangeEvents(); - HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain); - HRESULT scaleSwapChain(const Size &newSize) override; private: ComPtr mSwapChainPanel; + ComPtr mSwapChainPanelDispatcher; ComPtr> mPropertyMap; ComPtr mSwapChain; }; @@ -73,6 +83,9 @@ class SwapChainPanelSizeChangedHandler : std::weak_ptr mHost; }; -HRESULT GetSwapChainPanelSize(const ComPtr &swapChainPanel, RECT *windowSize, bool *scalingActive = nullptr); +HRESULT GetSwapChainPanelSize( + const ComPtr &swapChainPanel, + const ComPtr &dispatcher, + SIZE *windowSize, float *scaleFactor); } #endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp index a0bc2960b7..2ac8ee3a29 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp @@ -135,7 +135,7 @@ gl::Error Blit9::setShader(ShaderId source, const char *profile, { IDirect3DDevice9 *device = mRenderer->getDevice(); - D3DShaderType *shader; + D3DShaderType *shader = nullptr; if (mCompiledShaders[source] != NULL) { @@ -236,11 +236,11 @@ gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRe return error; } - gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); ASSERT(colorbuffer); - RenderTarget9 *renderTarget9 = NULL; - error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9); + RenderTarget9 *renderTarget9 = nullptr; + error = colorbuffer->getRenderTarget(&renderTarget9); if (error.isError()) { return error; @@ -251,10 +251,11 @@ gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRe ASSERT(source); IDirect3DSurface9 *destSurface = NULL; - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - error = storage9->getSurfaceLevel(level, true, &destSurface); + TextureStorage9 *storage9 = GetAs(storage); + error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, true, &destSurface); if (error.isError()) { + SafeRelease(source); return error; } ASSERT(destSurface); @@ -275,11 +276,11 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source return error; } - gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + const gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); ASSERT(colorbuffer); - RenderTarget9 *renderTarget9 = NULL; - error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget9); + RenderTarget9 *renderTarget9 = nullptr; + error = colorbuffer->getRenderTarget(&renderTarget9); if (error.isError()) { return error; @@ -290,10 +291,11 @@ gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &source ASSERT(source); IDirect3DSurface9 *destSurface = NULL; - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - error = storage9->getCubeMapSurface(target, level, true, &destSurface); + TextureStorage9 *storage9 = GetAs(storage); + error = storage9->getSurfaceLevel(target, level, true, &destSurface); if (error.isError()) { + SafeRelease(source); return error; } ASSERT(destSurface); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp index b051c81aa8..804b6971ce 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp @@ -14,7 +14,6 @@ namespace rx Buffer9::Buffer9(Renderer9 *renderer) : BufferD3D(renderer), - mRenderer(renderer), mSize(0) {} @@ -23,12 +22,6 @@ Buffer9::~Buffer9() mSize = 0; } -Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(Buffer9*, buffer)); - return static_cast(buffer); -} - gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) { if (size > mMemory.size()) @@ -45,13 +38,9 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) memcpy(mMemory.data(), data, size); } - invalidateStaticData(); - - if (usage == GL_STATIC_DRAW) - { - initializeStaticData(); - } + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + updateD3DBufferUsage(usage); return gl::Error(GL_NO_ERROR); } @@ -77,7 +66,7 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) memcpy(mMemory.data() + offset, data, size); } - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } @@ -85,24 +74,30 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) { // Note: this method is currently unreachable - Buffer9* sourceBuffer = makeBuffer9(source); + Buffer9* sourceBuffer = GetAs(source); ASSERT(sourceBuffer); memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); - invalidateStaticData(); + invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); return gl::Error(GL_NO_ERROR); } // We do not support buffer mapping in D3D9 -gl::Error Buffer9::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +gl::Error Buffer9::map(GLenum access, GLvoid **mapPtr) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error Buffer9::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) { UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION); } -gl::Error Buffer9::unmap() +gl::Error Buffer9::unmap(GLboolean *result) { UNREACHABLE(); return gl::Error(GL_INVALID_OPERATION); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h index c1984146fc..44a524ba28 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h @@ -23,23 +23,21 @@ class Buffer9 : public BufferD3D Buffer9(Renderer9 *renderer); virtual ~Buffer9(); - static Buffer9 *makeBuffer9(BufferImpl *buffer); - // BufferD3D implementation virtual size_t getSize() const { return mSize; } virtual bool supportsDirectBinding() const { return false; } + gl::Error getData(const uint8_t **outData) override; // BufferImpl implementation virtual gl::Error setData(const void* data, size_t size, GLenum usage); - gl::Error getData(const uint8_t **outData) override; virtual gl::Error setSubData(const void* data, size_t size, size_t offset); virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); - virtual gl::Error unmap(); + virtual gl::Error map(GLenum access, GLvoid **mapPtr); + virtual gl::Error mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr); + virtual gl::Error unmap(GLboolean *result); virtual void markTransformFeedbackUsage(); private: - Renderer9 *mRenderer; MemoryBuffer mMemory; size_t mSize; }; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp index 09b229bcb1..6ec35e16a7 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp @@ -13,9 +13,9 @@ namespace rx { -void DebugAnnotator9::beginEvent(const std::wstring &eventName) +void DebugAnnotator9::beginEvent(const wchar_t *eventName) { - D3DPERF_BeginEvent(0, eventName.c_str()); + D3DPERF_BeginEvent(0, eventName); } void DebugAnnotator9::endEvent() @@ -23,9 +23,9 @@ void DebugAnnotator9::endEvent() D3DPERF_EndEvent(); } -void DebugAnnotator9::setMarker(const std::wstring &markerName) +void DebugAnnotator9::setMarker(const wchar_t *markerName) { - D3DPERF_SetMarker(0, markerName.c_str()); + D3DPERF_SetMarker(0, markerName); } bool DebugAnnotator9::getStatus() diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h index 02956f7183..54e3bb9490 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h @@ -18,9 +18,9 @@ class DebugAnnotator9 : public gl::DebugAnnotator { public: DebugAnnotator9() {} - void beginEvent(const std::wstring &eventName) override; + void beginEvent(const wchar_t *eventName) override; void endEvent() override; - void setMarker(const std::wstring &markerName) override; + void setMarker(const wchar_t *markerName) override; bool getStatus() override; }; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp index 27c265e28d..3300681277 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp @@ -25,7 +25,7 @@ FenceNV9::~FenceNV9() SafeRelease(mQuery); } -gl::Error FenceNV9::set() +gl::Error FenceNV9::set(GLenum condition) { if (!mQuery) { @@ -47,7 +47,29 @@ gl::Error FenceNV9::set() return gl::Error(GL_NO_ERROR); } -gl::Error FenceNV9::test(bool flushCommandBuffer, GLboolean *outFinished) +gl::Error FenceNV9::test(GLboolean *outFinished) +{ + return testHelper(true, outFinished); +} + +gl::Error FenceNV9::finish() +{ + GLboolean finished = GL_FALSE; + while (finished != GL_TRUE) + { + gl::Error error = testHelper(true, &finished); + if (error.isError()) + { + return error; + } + + Sleep(0); + } + + return gl::Error(GL_NO_ERROR); +} + +gl::Error FenceNV9::testHelper(bool flushCommandBuffer, GLboolean *outFinished) { ASSERT(mQuery); @@ -69,22 +91,4 @@ gl::Error FenceNV9::test(bool flushCommandBuffer, GLboolean *outFinished) return gl::Error(GL_NO_ERROR); } -gl::Error FenceNV9::finishFence(GLboolean *outFinished) -{ - ASSERT(outFinished); - - while (*outFinished != GL_TRUE) - { - gl::Error error = test(true, outFinished); - if (error.isError()) - { - return error; - } - - Sleep(0); - } - - return gl::Error(GL_NO_ERROR); -} - } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h index 4b86747396..200ac68d27 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h @@ -20,13 +20,15 @@ class FenceNV9 : public FenceNVImpl { public: explicit FenceNV9(Renderer9 *renderer); - virtual ~FenceNV9(); + ~FenceNV9() override; - gl::Error set(); - gl::Error test(bool flushCommandBuffer, GLboolean *outFinished); - gl::Error finishFence(GLboolean *outFinished); + gl::Error set(GLenum condition) override; + gl::Error test(GLboolean *outFinished) override; + gl::Error finish() override; private: + gl::Error testHelper(bool flushCommandBuffer, GLboolean *outFinished); + Renderer9 *mRenderer; IDirect3DQuery9 *mQuery; }; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp index dbdfc6d6de..9c269a8565 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp @@ -22,8 +22,7 @@ namespace rx { Framebuffer9::Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer) - : FramebufferD3D(data, renderer), - mRenderer(renderer) + : FramebufferD3D(data, renderer), mRenderer(renderer) { ASSERT(mRenderer != nullptr); } @@ -32,9 +31,30 @@ Framebuffer9::~Framebuffer9() { } -gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams) +gl::Error Framebuffer9::discard(size_t, const GLenum *) { - const gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[0]; + // Extension not implemented in D3D9 renderer + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer9::invalidate(size_t, const GLenum *) +{ + // Shouldn't ever reach here in D3D9 + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer9::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) +{ + // Shouldn't ever reach here in D3D9 + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error Framebuffer9::clear(const gl::Data &data, const ClearParameters &clearParams) +{ + const gl::FramebufferAttachment *colorAttachment = mData.getColorAttachment(0); const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment(); gl::Error error = mRenderer->applyRenderTarget(colorAttachment, depthStencilAttachment); @@ -43,24 +63,30 @@ gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &cle return error; } - float nearZ, farZ; - state.getDepthRange(&nearZ, &farZ); - mRenderer->setViewport(state.getViewport(), nearZ, farZ, GL_TRIANGLES, state.getRasterizerState().frontFace, true); + float nearZ = data.state->getNearPlane(); + float farZ = data.state->getFarPlane(); + mRenderer->setViewport(data.caps, data.state->getViewport(), nearZ, farZ, GL_TRIANGLES, + data.state->getRasterizerState().frontFace, true); - mRenderer->setScissorRectangle(state.getScissor(), state.isScissorTestEnabled()); + mRenderer->setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment); } -gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const +gl::Error Framebuffer9::readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const { - ASSERT(pack.pixelBuffer.get() == NULL); + ASSERT(pack.pixelBuffer.get() == nullptr); - const gl::FramebufferAttachment *colorbuffer = mData.mColorAttachments[0]; + const gl::FramebufferAttachment *colorbuffer = mData.getColorAttachment(0); ASSERT(colorbuffer); - RenderTarget9 *renderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget); + RenderTarget9 *renderTarget = nullptr; + gl::Error error = colorbuffer->getRenderTarget(&renderTarget); if (error.isError()) { return error; @@ -84,7 +110,7 @@ gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLe ASSERT(device); HRESULT result; - IDirect3DSurface9 *systemSurface = NULL; + IDirect3DSurface9 *systemSurface = nullptr; bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() && area.x == 0 && area.y == 0 && static_cast(area.width) == desc.Width && static_cast(area.height) == desc.Height && @@ -104,7 +130,7 @@ gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLe if (!directToPixels) { result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, NULL); + D3DPOOL_SYSTEMMEM, &systemSurface, nullptr); if (FAILED(result)) { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); @@ -246,19 +272,19 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorbuffer(0); ASSERT(readBuffer); - RenderTarget9 *readRenderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readRenderTarget); + RenderTarget9 *readRenderTarget = nullptr; + gl::Error error = readBuffer->getRenderTarget(&readRenderTarget); if (error.isError()) { return error; } ASSERT(readRenderTarget); - const gl::FramebufferAttachment *drawBuffer = mData.mColorAttachments[0]; + const gl::FramebufferAttachment *drawBuffer = mData.getColorAttachment(0); ASSERT(drawBuffer); - RenderTarget9 *drawRenderTarget = NULL; - error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget); + RenderTarget9 *drawRenderTarget = nullptr; + error = drawBuffer->getRenderTarget(&drawRenderTarget); if (error.isError()) { return error; @@ -372,8 +398,8 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer(); ASSERT(readBuffer); - RenderTarget9 *readDepthStencil = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readDepthStencil); + RenderTarget9 *readDepthStencil = nullptr; + gl::Error error = readBuffer->getRenderTarget(&readDepthStencil); if (error.isError()) { return error; @@ -383,8 +409,8 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment(); ASSERT(drawBuffer); - RenderTarget9 *drawDepthStencil = NULL; - error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawDepthStencil); + RenderTarget9 *drawDepthStencil = nullptr; + error = drawBuffer->getRenderTarget(&drawDepthStencil); if (error.isError()) { return error; @@ -398,7 +424,7 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface(); ASSERT(drawDepthStencil); - HRESULT result = device->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); + HRESULT result = device->StretchRect(readSurface, nullptr, drawSurface, nullptr, D3DTEXF_NONE); SafeRelease(readSurface); SafeRelease(drawSurface); @@ -414,7 +440,7 @@ gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangl GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const { - RenderTarget9 *renderTarget9 = RenderTarget9::makeRenderTarget9(renderTarget); + RenderTarget9 *renderTarget9 = GetAs(renderTarget); const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat()); return d3dFormatInfo.internalFormat; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h index 292118e6db..fe12079ae0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h @@ -21,11 +21,19 @@ class Framebuffer9 : public FramebufferD3D Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer); virtual ~Framebuffer9(); - private: - gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override; + gl::Error discard(size_t count, const GLenum *attachments) override; + gl::Error invalidate(size_t count, const GLenum *attachments) override; + gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override; - gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, - const gl::PixelPackState &pack, uint8_t *pixels) const override; + private: + gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override; + + gl::Error readPixelsImpl(const gl::Rectangle &area, + GLenum format, + GLenum type, + size_t outputPitch, + const gl::PixelPackState &pack, + uint8_t *pixels) const override; gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter, diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp index d149f7a806..fec7e3e19d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp @@ -94,12 +94,6 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 return gl::Error(GL_NO_ERROR); } -Image9 *Image9::makeImage9(ImageD3D *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(Image9*, img)); - return static_cast(img); -} - gl::Error Image9::generateMipmap(Image9 *dest, Image9 *source) { IDirect3DSurface9 *sourceSurface = NULL; @@ -336,8 +330,8 @@ gl::Error Image9::getSurface(IDirect3DSurface9 **outSurface) gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level) { IDirect3DSurface9 *surface = NULL; - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - gl::Error error = storage9->getSurfaceLevel(level, false, &surface); + TextureStorage9 *storage9 = GetAs(storage); + gl::Error error = storage9->getSurfaceLevel(GL_TEXTURE_2D, level, false, &surface); if (error.isError()) { return error; @@ -348,8 +342,9 @@ gl::Error Image9::setManagedSurface2D(TextureStorage *storage, int level) gl::Error Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level) { IDirect3DSurface9 *surface = NULL; - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - gl::Error error = storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface); + TextureStorage9 *storage9 = GetAs(storage); + gl::Error error = + storage9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false, &surface); if (error.isError()) { return error; @@ -390,12 +385,13 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i return error; } + TextureStorage9 *storage9 = GetAs(storage); + IDirect3DSurface9 *destSurface = NULL; if (index.type == GL_TEXTURE_2D) { - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); - error = storage9->getSurfaceLevel(index.mipIndex, true, &destSurface); + error = storage9->getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, true, &destSurface); if (error.isError()) { return error; @@ -404,8 +400,7 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i else { ASSERT(gl::IsCubeMapTextureTarget(index.type)); - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); - error = storage9->getCubeMapSurface(index.type, index.mipIndex, true, &destSurface); + error = storage9->getSurfaceLevel(index.type, index.mipIndex, true, &destSurface); if (error.isError()) { return error; @@ -485,6 +480,8 @@ gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpa const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength); + GLsizei inputSkipBytes = formatInfo.computeSkipPixels(inputRowPitch, 0, unpack.skipImages, + unpack.skipRows, unpack.skipPixels); const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); ASSERT(d3dFormatInfo.loadFunction != NULL); @@ -503,8 +500,9 @@ gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpa } d3dFormatInfo.loadFunction(area.width, area.height, area.depth, - reinterpret_cast(input), inputRowPitch, 0, - reinterpret_cast(locked.pBits), locked.Pitch, 0); + reinterpret_cast(input) + inputSkipBytes, + inputRowPitch, 0, reinterpret_cast(locked.pBits), + locked.Pitch, 0); unlock(); @@ -518,7 +516,8 @@ gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input) const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0); - GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0); + GLsizei inputDepthPitch = + formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0); const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); @@ -550,14 +549,16 @@ gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input) } // This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures -gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) +gl::Error Image9::copyFromRTInternal(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + RenderTargetD3D *source) { ASSERT(source); // ES3.0 only behaviour to copy into a 3d texture ASSERT(destOffset.z == 0); - RenderTarget9 *renderTarget = RenderTarget9::makeRenderTarget9(source); + RenderTarget9 *renderTarget = GetAs(source); IDirect3DSurface9 *surface = renderTarget->getSurface(); ASSERT(surface); @@ -667,9 +668,9 @@ gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Rectangle &source for (int x = 0; x < width; x++) { unsigned short rgb = ((unsigned short*)sourcePixels)[x]; - unsigned char red = (rgb & 0xF800) >> 8; - unsigned char green = (rgb & 0x07E0) >> 3; - unsigned char blue = (rgb & 0x001F) << 3; + unsigned char red = static_cast((rgb & 0xF800) >> 8); + unsigned char green = static_cast((rgb & 0x07E0) >> 3); + unsigned char blue = static_cast((rgb & 0x001F) << 3); destPixels[x + 0] = blue | (blue >> 5); destPixels[x + 1] = green | (green >> 6); destPixels[x + 2] = red | (red >> 5); @@ -704,9 +705,9 @@ gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Rectangle &source for (int x = 0; x < width; x++) { unsigned short argb = ((unsigned short*)sourcePixels)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; + unsigned char red = static_cast((argb & 0x7C00) >> 7); + unsigned char green = static_cast((argb & 0x03E0) >> 2); + unsigned char blue = static_cast((argb & 0x001F) << 3); destPixels[x + 0] = blue | (blue >> 5); destPixels[x + 1] = green | (green >> 5); destPixels[x + 2] = red | (red >> 5); @@ -722,9 +723,9 @@ gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Rectangle &source for (int x = 0; x < width; x++) { unsigned short argb = ((unsigned short*)sourcePixels)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; + unsigned char red = static_cast((argb & 0x7C00) >> 7); + unsigned char green = static_cast((argb & 0x03E0) >> 2); + unsigned char blue = static_cast((argb & 0x001F) << 3); unsigned char alpha = (signed short)argb >> 15; destPixels[x + 0] = blue | (blue >> 5); destPixels[x + 1] = green | (green >> 5); @@ -778,11 +779,35 @@ gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Rectangle &source return gl::Error(GL_NO_ERROR); } -gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Box &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage) +gl::Error Image9::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) { - // Currently unreachable, due to only being used in a D3D11-only workaround - UNIMPLEMENTED(); - return gl::Error(GL_INVALID_OPERATION); + RenderTargetD3D *renderTarget = nullptr; + gl::Error error = source->getRenderTarget(imageIndex, &renderTarget); + if (error.isError()) + { + return error; + } + + gl::Rectangle sourceArea(0, 0, mWidth, mHeight); + return copyFromRTInternal(gl::Offset(), sourceArea, renderTarget); } +gl::Error Image9::copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) +{ + const gl::FramebufferAttachment *srcAttachment = source->getReadColorbuffer(); + ASSERT(srcAttachment); + + RenderTargetD3D *renderTarget = NULL; + gl::Error error = srcAttachment->getRenderTarget(&renderTarget); + if (error.isError()) + { + return error; + } + + ASSERT(renderTarget); + return copyFromRTInternal(destOffset, sourceArea, renderTarget); } + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h index 8cbfbbebf6..91448cc849 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h @@ -28,8 +28,6 @@ class Image9 : public ImageD3D Image9(Renderer9 *renderer); ~Image9(); - static Image9 *makeImage9(ImageD3D *img); - static gl::Error generateMipmap(Image9 *dest, Image9 *source); static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); @@ -47,9 +45,10 @@ class Image9 : public ImageD3D virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input); virtual gl::Error loadCompressedData(const gl::Box &area, const void *input); - virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source); - virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, - const gl::ImageIndex &sourceIndex, TextureStorage *source); + gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override; + gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + const gl::Framebuffer *source) override; private: gl::Error getSurface(IDirect3DSurface9 **outSurface); @@ -61,6 +60,10 @@ class Image9 : public ImageD3D gl::Error lock(D3DLOCKED_RECT *lockedRect, const RECT &rect); void unlock(); + gl::Error copyFromRTInternal(const gl::Offset &destOffset, + const gl::Rectangle &sourceArea, + RenderTargetD3D *source); + Renderer9 *mRenderer; D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp index c5d72e6a50..97c7f72136 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp @@ -65,12 +65,6 @@ gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bo return gl::Error(GL_NO_ERROR); } -IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer)); - return static_cast(indexBuffer); -} - gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) { if (!mIndexBuffer) diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h index 61f8b11566..ba03ba703f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h @@ -23,8 +23,6 @@ class IndexBuffer9 : public IndexBuffer virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); - static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer); - virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); virtual gl::Error unmapBuffer(); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp index 96f12d7868..c826abf81c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp @@ -66,7 +66,14 @@ gl::Error Query9::end() return gl::Error(GL_NO_ERROR); } -gl::Error Query9::getResult(GLuint *params) +gl::Error Query9::queryCounter() +{ + UNIMPLEMENTED(); + return gl::Error(GL_INVALID_OPERATION, "Unimplemented"); +} + +template +gl::Error Query9::getResultBase(T *params) { while (!mQueryFinished) { @@ -83,12 +90,31 @@ gl::Error Query9::getResult(GLuint *params) } ASSERT(mQueryFinished); - *params = mResult; - + *params = static_cast(mResult); return gl::Error(GL_NO_ERROR); } -gl::Error Query9::isResultAvailable(GLuint *available) +gl::Error Query9::getResult(GLint *params) +{ + return getResultBase(params); +} + +gl::Error Query9::getResult(GLuint *params) +{ + return getResultBase(params); +} + +gl::Error Query9::getResult(GLint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query9::getResult(GLuint64 *params) +{ + return getResultBase(params); +} + +gl::Error Query9::isResultAvailable(bool *available) { gl::Error error = testQuery(); if (error.isError()) @@ -96,7 +122,7 @@ gl::Error Query9::isResultAvailable(GLuint *available) return error; } - *available = (mQueryFinished ? GL_TRUE : GL_FALSE); + *available = mQueryFinished; return gl::Error(GL_NO_ERROR); } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h index 399da2ed83..9d17711a00 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h @@ -23,13 +23,20 @@ class Query9 : public QueryImpl virtual gl::Error begin(); virtual gl::Error end(); + virtual gl::Error queryCounter(); + virtual gl::Error getResult(GLint *params); virtual gl::Error getResult(GLuint *params); - virtual gl::Error isResultAvailable(GLuint *available); + virtual gl::Error getResult(GLint64 *params); + virtual gl::Error getResult(GLuint64 *params); + virtual gl::Error isResultAvailable(bool *available); private: gl::Error testQuery(); - GLuint mResult; + template + gl::Error getResultBase(T *params); + + GLuint64 mResult; bool mQueryFinished; Renderer9 *mRenderer; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp index 412c0109f5..419bff1f63 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp @@ -16,14 +16,14 @@ namespace rx { -RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTargetD3D *target) -{ - ASSERT(HAS_DYNAMIC_TYPE(RenderTarget9*, target)); - return static_cast(target); -} - // TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. -TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, +TextureRenderTarget9::TextureRenderTarget9(IDirect3DBaseTexture9 *texture, + size_t textureLevel, + IDirect3DSurface9 *surface, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, GLsizei samples) : mWidth(width), mHeight(height), @@ -31,6 +31,8 @@ TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum in mInternalFormat(internalFormat), mD3DFormat(D3DFMT_UNKNOWN), mSamples(samples), + mTexture(texture), + mTextureLevel(textureLevel), mRenderTarget(surface) { ASSERT(mDepth == 1); @@ -45,6 +47,7 @@ TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum in TextureRenderTarget9::~TextureRenderTarget9() { + SafeRelease(mTexture); SafeRelease(mRenderTarget); } @@ -73,7 +76,17 @@ GLsizei TextureRenderTarget9::getSamples() const return mSamples; } -IDirect3DSurface9 *TextureRenderTarget9::getSurface() +IDirect3DBaseTexture9 *TextureRenderTarget9::getTexture() const +{ + return mTexture; +} + +size_t TextureRenderTarget9::getTextureLevel() const +{ + return mTextureLevel; +} + +IDirect3DSurface9 *TextureRenderTarget9::getSurface() const { // Caller is responsible for releasing the returned surface reference. // TODO: remove the AddRef to match RenderTarget11 @@ -117,7 +130,7 @@ GLsizei SurfaceRenderTarget9::getDepth() const GLenum SurfaceRenderTarget9::getInternalFormat() const { - return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat()); + return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetRenderTargetInternalFormat()); } GLsizei SurfaceRenderTarget9::getSamples() const @@ -126,11 +139,21 @@ GLsizei SurfaceRenderTarget9::getSamples() const return 0; } -IDirect3DSurface9 *SurfaceRenderTarget9::getSurface() +IDirect3DSurface9 *SurfaceRenderTarget9::getSurface() const { return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget()); } +IDirect3DBaseTexture9 *SurfaceRenderTarget9::getTexture() const +{ + return (mDepth ? nullptr : mSwapChain->getOffscreenTexture()); +} + +size_t SurfaceRenderTarget9::getTextureLevel() const +{ + return 0; +} + D3DFORMAT SurfaceRenderTarget9::getD3DFormat() const { return d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h index 32c7dfa09c..f19c54de7b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h @@ -22,10 +22,12 @@ class RenderTarget9 : public RenderTargetD3D public: RenderTarget9() { } virtual ~RenderTarget9() { } + // Retrieve the texture that backs this render target, may be null for swap chain render + // targets. + virtual IDirect3DBaseTexture9 *getTexture() const = 0; + virtual size_t getTextureLevel() const = 0; - static RenderTarget9 *makeRenderTarget9(RenderTargetD3D *renderTarget); - - virtual IDirect3DSurface9 *getSurface() = 0; + virtual IDirect3DSurface9 *getSurface() const = 0; virtual D3DFORMAT getD3DFormat() const = 0; }; @@ -33,7 +35,13 @@ class RenderTarget9 : public RenderTargetD3D class TextureRenderTarget9 : public RenderTarget9 { public: - TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, + TextureRenderTarget9(IDirect3DBaseTexture9 *texture, + size_t textureLevel, + IDirect3DSurface9 *surface, + GLenum internalFormat, + GLsizei width, + GLsizei height, + GLsizei depth, GLsizei samples); virtual ~TextureRenderTarget9(); @@ -43,7 +51,9 @@ class TextureRenderTarget9 : public RenderTarget9 GLenum getInternalFormat() const override; GLsizei getSamples() const override; - IDirect3DSurface9 *getSurface() override; + IDirect3DBaseTexture9 *getTexture() const override; + size_t getTextureLevel() const override; + IDirect3DSurface9 *getSurface() const override; D3DFORMAT getD3DFormat() const override; @@ -55,6 +65,8 @@ class TextureRenderTarget9 : public RenderTarget9 D3DFORMAT mD3DFormat; GLsizei mSamples; + IDirect3DBaseTexture9 *mTexture; + size_t mTextureLevel; IDirect3DSurface9 *mRenderTarget; }; @@ -70,7 +82,9 @@ class SurfaceRenderTarget9 : public RenderTarget9 GLenum getInternalFormat() const override; GLsizei getSamples() const override; - IDirect3DSurface9 *getSurface() override; + IDirect3DBaseTexture9 *getTexture() const override; + size_t getTextureLevel() const override; + IDirect3DSurface9 *getSurface() const override; D3DFORMAT getD3DFormat() const override; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp index bf1c367693..6bb975b0e4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp @@ -8,49 +8,50 @@ #include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include +#include + #include "common/utilities.h" +#include "libANGLE/angletypes.h" #include "libANGLE/Buffer.h" #include "libANGLE/Display.h" +#include "libANGLE/features.h" +#include "libANGLE/formatutils.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/Program.h" #include "libANGLE/Renderbuffer.h" -#include "libANGLE/State.h" -#include "libANGLE/Surface.h" -#include "libANGLE/Texture.h" -#include "libANGLE/angletypes.h" -#include "libANGLE/features.h" -#include "libANGLE/formatutils.h" -#include "libANGLE/renderer/d3d/CompilerD3D.h" -#include "libANGLE/renderer/d3d/FramebufferD3D.h" -#include "libANGLE/renderer/d3d/IndexDataManager.h" -#include "libANGLE/renderer/d3d/ProgramD3D.h" -#include "libANGLE/renderer/d3d/RenderbufferD3D.h" -#include "libANGLE/renderer/d3d/ShaderD3D.h" -#include "libANGLE/renderer/d3d/SurfaceD3D.h" -#include "libANGLE/renderer/d3d/TextureD3D.h" -#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" #include "libANGLE/renderer/d3d/d3d9/Blit9.h" #include "libANGLE/renderer/d3d/d3d9/Buffer9.h" #include "libANGLE/renderer/d3d/d3d9/Fence9.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" #include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" #include "libANGLE/renderer/d3d/d3d9/Image9.h" #include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h" #include "libANGLE/renderer/d3d/d3d9/Query9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" #include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" #include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h" #include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" #include "libANGLE/renderer/d3d/d3d9/VertexArray9.h" #include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" -#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" -#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" - +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/SurfaceD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h" +#include "libANGLE/State.h" +#include "libANGLE/Surface.h" +#include "libANGLE/Texture.h" #include "third_party/trace_event/trace_event.h" -#include -#include #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) #define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 @@ -76,12 +77,8 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 }; -Renderer9::Renderer9(egl::Display *display) - : RendererD3D(display) +Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this) { - // Initialize global annotator - gl::InitializeDebugAnnotations(&mAnnotator); - mD3d9Module = NULL; mD3d9 = NULL; @@ -133,6 +130,10 @@ Renderer9::Renderer9(egl::Display *display) mAppliedVertexShader = NULL; mAppliedPixelShader = NULL; mAppliedProgramSerial = 0; + + initializeDebugAnnotator(); + + mEGLDevice = nullptr; } Renderer9::~Renderer9() @@ -147,8 +148,6 @@ Renderer9::~Renderer9() } release(); - - gl::UninitializeDebugAnnotations(); } void Renderer9::release() @@ -157,6 +156,7 @@ void Renderer9::release() releaseDeviceResources(); + SafeDelete(mEGLDevice); SafeRelease(mDevice); SafeRelease(mDeviceEx); SafeRelease(mD3d9); @@ -173,22 +173,9 @@ void Renderer9::release() mD3d9Module = NULL; } -Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) -{ - ASSERT(HAS_DYNAMIC_TYPE(Renderer9*, renderer)); - return static_cast(renderer); -} - egl::Error Renderer9::initialize() { - if (!mCompiler.initialize()) - { - return egl::Error(EGL_NOT_INITIALIZED, - D3D9_INIT_COMPILER_ERROR, - "Compiler failed to initialize."); - } - - TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); + TRACE_EVENT0("gpu.angle", "GetModuleHandle_d3d9"); mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); if (mD3d9Module == NULL) @@ -204,14 +191,14 @@ egl::Error Renderer9::initialize() // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) { - TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); + TRACE_EVENT0("gpu.angle", "D3d9Ex_QueryInterface"); ASSERT(mD3d9Ex); mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); ASSERT(mD3d9); } else { - TRACE_EVENT0("gpu", "Direct3DCreate9"); + TRACE_EVENT0("gpu.angle", "Direct3DCreate9"); mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); } @@ -229,7 +216,7 @@ egl::Error Renderer9::initialize() // Give up on getting device caps after about one second. { - TRACE_EVENT0("gpu", "GetDeviceCaps"); + TRACE_EVENT0("gpu.angle", "GetDeviceCaps"); for (int i = 0; i < 10; ++i) { result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); @@ -273,7 +260,7 @@ egl::Error Renderer9::initialize() } { - TRACE_EVENT0("gpu", "GetAdapterIdentifier"); + TRACE_EVENT0("gpu.angle", "GetAdapterIdentifier"); mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); } @@ -281,7 +268,7 @@ egl::Error Renderer9::initialize() static const TCHAR className[] = TEXT("STATIC"); { - TRACE_EVENT0("gpu", "CreateWindowEx"); + TRACE_EVENT0("gpu.angle", "CreateWindowEx"); mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); } @@ -289,7 +276,7 @@ egl::Error Renderer9::initialize() DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED; { - TRACE_EVENT0("gpu", "D3d9_CreateDevice"); + TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice"); result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); } if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) @@ -300,7 +287,7 @@ egl::Error Renderer9::initialize() if (FAILED(result)) { - TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); + TRACE_EVENT0("gpu.angle", "D3d9_CreateDevice2"); result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); if (FAILED(result)) @@ -313,13 +300,13 @@ egl::Error Renderer9::initialize() if (mD3d9Ex) { - TRACE_EVENT0("gpu", "mDevice_QueryInterface"); + TRACE_EVENT0("gpu.angle", "mDevice_QueryInterface"); result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx); ASSERT(SUCCEEDED(result)); } { - TRACE_EVENT0("gpu", "ShaderCache initialize"); + TRACE_EVENT0("gpu.angle", "ShaderCache initialize"); mVertexShaderCache.initialize(mDevice); mPixelShaderCache.initialize(mDevice); } @@ -359,14 +346,11 @@ void Renderer9::initializeDevice() const gl::Caps &rendererCaps = getRendererCaps(); - mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); - - mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); - mCurVertexTextureSerials.resize(rendererCaps.maxVertexTextureImageUnits); - mCurPixelTextureSerials.resize(rendererCaps.maxTextureImageUnits); + mCurVertexTextures.resize(rendererCaps.maxVertexTextureImageUnits); + mCurPixelTextures.resize(rendererCaps.maxTextureImageUnits); markAllStateDirty(); @@ -379,6 +363,9 @@ void Renderer9::initializeDevice() ASSERT(!mVertexDataManager && !mIndexDataManager); mVertexDataManager = new VertexDataManager(this); mIndexDataManager = new IndexDataManager(this, getRendererClass()); + + // TODO(jmadill): use context caps, and place in common D3D location + mTranslatedAttribCache.resize(getRendererCaps().maxVertexAttributes); } D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() @@ -523,6 +510,31 @@ egl::ConfigSet Renderer9::generateConfigs() const return configs; } +void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const +{ + outExtensions->createContextRobustness = true; + + if (getShareHandleSupport()) + { + outExtensions->d3dShareHandleClientBuffer = true; + outExtensions->surfaceD3DTexture2DShareHandle = true; + } + + outExtensions->querySurfacePointer = true; + outExtensions->windowFixedSize = true; + outExtensions->postSubBuffer = true; + outExtensions->createContext = true; + outExtensions->deviceQuery = true; + outExtensions->createContextNoError = true; + + outExtensions->image = true; + outExtensions->imageBase = true; + outExtensions->glTexture2DImage = true; + outExtensions->glRenderbufferImage = true; + + outExtensions->flexibleSurfaceCompatibility = true; +} + void Renderer9::startScene() { if (!mSceneStarted) @@ -612,7 +624,7 @@ gl::Error Renderer9::finish() while (result == S_FALSE) { // Keep polling, but allow other threads to do something useful first - Sleep(0); + ScheduleYield(); result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); @@ -642,9 +654,24 @@ gl::Error Renderer9::finish() return gl::Error(GL_NO_ERROR); } -SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) +{ + return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat, + orientation); +} + +CompilerImpl *Renderer9::createCompiler() +{ + return new CompilerD3D(SH_HLSL_3_0_OUTPUT); +} + +void *Renderer9::getD3DDevice() { - return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat); + return reinterpret_cast(mDevice); } gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery) @@ -716,9 +743,9 @@ BufferImpl *Renderer9::createBuffer() return new Buffer9(this); } -VertexArrayImpl *Renderer9::createVertexArray() +VertexArrayImpl *Renderer9::createVertexArray(const gl::VertexArray::Data &data) { - return new VertexArray9(this); + return new VertexArray9(data); } QueryImpl *Renderer9::createQuery(GLenum type) @@ -766,46 +793,52 @@ gl::Error Renderer9::generateSwizzle(gl::Texture *texture) gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerState) { - std::vector &forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; - std::vector &appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; + CurSamplerState &appliedSampler = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates[index] + : mCurVertexSamplerStates[index]; - if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0) - { - int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; - int d3dSampler = index + d3dSamplerOffset; + // Make sure to add the level offset for our tiny compressed texture workaround + TextureD3D *textureD3D = GetImplAs(texture); - // Make sure to add the level offset for our tiny compressed texture workaround - TextureD3D *textureD3D = GetImplAs(texture); + TextureStorage *storage = nullptr; + gl::Error error = textureD3D->getNativeTexture(&storage); + if (error.isError()) + { + return error; + } - TextureStorage *storage = nullptr; - gl::Error error = textureD3D->getNativeTexture(&storage); - if (error.isError()) - { - return error; - } + // Storage should exist, texture should be complete + ASSERT(storage); - // Storage should exist, texture should be complete - ASSERT(storage); + DWORD baseLevel = texture->getBaseLevel() + storage->getTopLevel(); - DWORD baseLevel = samplerState.baseLevel + storage->getTopLevel(); + if (appliedSampler.forceSet || appliedSampler.baseLevel != baseLevel || + memcmp(&samplerState, &appliedSampler, sizeof(gl::SamplerState)) != 0) + { + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); + D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; - gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); + float lodBias; + gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, &lodBias, + samplerState.maxAnisotropy, baseLevel); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, baseLevel); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPMAPLODBIAS, static_cast(lodBias)); if (getRendererExtensions().textureFilterAnisotropic) { mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); } } - forceSetSamplers[index] = false; - appliedSamplers[index] = samplerState; + appliedSampler.forceSet = false; + appliedSampler.samplerState = samplerState; + appliedSampler.baseLevel = baseLevel; return gl::Error(GL_NO_ERROR); } @@ -815,10 +848,9 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; int d3dSampler = index + d3dSamplerOffset; IDirect3DBaseTexture9 *d3dTexture = NULL; - unsigned int serial = 0; bool forceSetTexture = false; - std::vector &appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; + std::vector &appliedTextures = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextures : mCurVertexTextures; if (texture) { @@ -834,7 +866,7 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te // Texture should be complete and have a storage ASSERT(texStorage); - TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage); + TextureStorage9 *storage9 = GetAs(texStorage); error = storage9->getBaseTexture(&d3dTexture); if (error.isError()) { @@ -845,372 +877,99 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te // in the texture class and we're unexpectedly missing the d3d texture ASSERT(d3dTexture != NULL); - serial = texture->getTextureSerial(); forceSetTexture = textureImpl->hasDirtyImages(); textureImpl->resetDirty(); } - if (forceSetTexture || appliedSerials[index] != serial) + if (forceSetTexture || appliedTextures[index] != reinterpret_cast(d3dTexture)) { mDevice->SetTexture(d3dSampler, d3dTexture); } - appliedSerials[index] = serial; + appliedTextures[index] = reinterpret_cast(d3dTexture); return gl::Error(GL_NO_ERROR); } gl::Error Renderer9::setUniformBuffers(const gl::Data &/*data*/, - const GLint /*vertexUniformBuffers*/[], - const GLint /*fragmentUniformBuffers*/[]) + const std::vector &/*vertexUniformBuffers*/, + const std::vector &/*fragmentUniformBuffers*/) { // No effect in ES2/D3D9 return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) +void Renderer9::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) { - bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; - - if (rasterStateChanged) - { - // Set the cull mode - if (rasterState.cullFace) - { - mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace)); - } - else - { - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - } - - if (rasterState.polygonOffsetFill) - { - if (mCurDepthSize > 0) - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor); - - float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(mCurDepthSize)); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias); - } - } - else - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); - } - - mCurRasterState = rasterState; - } - - mForceSetRasterState = false; - - return gl::Error(GL_NO_ERROR); + mStateManager.syncState(state, bitmask); } -gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) +gl::Error Renderer9::updateState(const gl::Data &data, GLenum drawMode) { - bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; - bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0; - bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; - - if (blendStateChanged || blendColorChanged) - { - if (blendState.blend) - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor)); - } - else - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha))); - } - - mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); - mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); - mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); - - if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || - blendState.destBlendRGB != blendState.destBlendAlpha || - blendState.blendEquationRGB != blendState.blendEquationAlpha) - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); - mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); - mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); - } - else - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); - } - } - else - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - } - - if (blendState.sampleAlphaToCoverage) - { - FIXME("Sample alpha to coverage is unimplemented."); - } - - gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); - GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; + // Applies the render target surface, depth stencil surface, viewport rectangle and + // scissor rectangle to the renderer + const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer(); + ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE); - // Set the color mask - bool zeroColorMaskAllowed = getVendorId() != VENDOR_ID_AMD; - // Apparently some ATI cards have a bug where a draw with a zero color - // write mask can cause later draws to have incorrect results. Instead, - // set a nonzero color write mask but modify the blend state so that no - // drawing is done. - // http://code.google.com/p/angleproject/issues/detail?id=169 - - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); - DWORD colorMask = gl_d3d9::ConvertColorMask(formatInfo.redBits > 0 && blendState.colorMaskRed, - formatInfo.greenBits > 0 && blendState.colorMaskGreen, - formatInfo.blueBits > 0 && blendState.colorMaskBlue, - formatInfo.alphaBits > 0 && blendState.colorMaskAlpha); - if (colorMask == 0 && !zeroColorMaskAllowed) - { - // Enable green channel, but set blending so nothing will be drawn. - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); - mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); - } - - mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE); - - mCurBlendState = blendState; - mCurBlendColor = blendColor; - } - - if (sampleMaskChanged) + gl::Error error = applyRenderTarget(framebufferObject); + if (error.isError()) { - // Set the multisample mask - mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast(sampleMask)); - - mCurSampleMask = sampleMask; + return error; } - mForceSetBlendState = false; + // Setting viewport state + setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(), + data.state->getFarPlane(), drawMode, data.state->getRasterizerState().frontFace, + false); - return gl::Error(GL_NO_ERROR); -} + // Setting scissors state + setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); -gl::Error Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) -{ - bool depthStencilStateChanged = mForceSetDepthStencilState || - memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; - bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef || - stencilBackRef != mCurStencilBackRef; - bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW; + // Setting blend, depth stencil, and rasterizer states + int samples = framebufferObject->getSamples(data); + gl::RasterizerState rasterizer = data.state->getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); - if (depthStencilStateChanged) - { - if (depthStencilState.depthTest) - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc)); - } - else - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - } + unsigned int mask = GetBlendSampleMask(data, samples); + error = setBlendDepthRasterStates(data, mask); - mCurDepthStencilState = depthStencilState; - } - - if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged) + if (error.isError()) { - if (depthStencilState.stencilTest && mCurStencilSize > 0) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); - - // FIXME: Unsupported by D3D9 - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; - - ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); - ASSERT(stencilRef == stencilBackRef); - ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); - - // get the maximum size of the stencil ref - unsigned int maxStencil = (1 << mCurStencilSize) - 1; - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, - depthStencilState.stencilWritemask); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - gl_d3d9::ConvertComparison(depthStencilState.stencilFunc)); - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, - (stencilRef < (int)maxStencil) ? stencilRef : maxStencil); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, - depthStencilState.stencilMask); - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail)); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail)); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass)); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, - depthStencilState.stencilBackWritemask); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc)); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, - (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, - depthStencilState.stencilBackMask); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail)); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail)); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass)); - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE); - - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; - mCurFrontFaceCCW = frontFaceCCW; + return error; } - mForceSetDepthStencilState = false; + mStateManager.resetDirtyBits(); - return gl::Error(GL_NO_ERROR); + return error; } void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) { - bool scissorChanged = mForceSetScissor || - memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || - enabled != mScissorEnabled; - - if (scissorChanged) - { - if (enabled) - { - RECT rect; - rect.left = gl::clamp(scissor.x, 0, static_cast(mRenderTargetDesc.width)); - rect.top = gl::clamp(scissor.y, 0, static_cast(mRenderTargetDesc.height)); - rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast(mRenderTargetDesc.width)); - rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast(mRenderTargetDesc.height)); - mDevice->SetScissorRect(&rect); - } - - mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE); + mStateManager.setScissorState(scissor, enabled); +} - mScissorEnabled = enabled; - mCurScissor = scissor; - } +gl::Error Renderer9::setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode) +{ + int samples = glData.state->getDrawFramebuffer()->getSamples(glData); + gl::RasterizerState rasterizer = glData.state->getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); - mForceSetScissor = false; + unsigned int mask = GetBlendSampleMask(glData, samples); + return mStateManager.setBlendDepthRasterStates(*glData.state, mask); } -void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, +void Renderer9::setViewport(const gl::Caps *caps, + const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, bool ignoreViewport) { - gl::Rectangle actualViewport = viewport; - float actualZNear = gl::clamp01(zNear); - float actualZFar = gl::clamp01(zFar); - if (ignoreViewport) - { - actualViewport.x = 0; - actualViewport.y = 0; - actualViewport.width = mRenderTargetDesc.width; - actualViewport.height = mRenderTargetDesc.height; - actualZNear = 0.0f; - actualZFar = 1.0f; - } - - D3DVIEWPORT9 dxViewport; - dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast(mRenderTargetDesc.width)); - dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast(mRenderTargetDesc.height)); - dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast(mRenderTargetDesc.width) - static_cast(dxViewport.X)); - dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast(mRenderTargetDesc.height) - static_cast(dxViewport.Y)); - dxViewport.MinZ = actualZNear; - dxViewport.MaxZ = actualZFar; - - float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); - - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; - if (viewportChanged) - { - mDevice->SetViewport(&dxViewport); - - mCurViewport = actualViewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - mCurDepthFront = depthFront; - - dx_VertexConstants vc = {0}; - dx_PixelConstants pc = {0}; - - vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; - vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; - vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; - vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; - - pc.viewCoords[0] = actualViewport.width * 0.5f; - pc.viewCoords[1] = actualViewport.height * 0.5f; - pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); - pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); - - pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - pc.depthFront[2] = depthFront; - - vc.depthRange[0] = actualZNear; - vc.depthRange[1] = actualZFar; - vc.depthRange[2] = actualZFar - actualZNear; - - pc.depthRange[0] = actualZNear; - pc.depthRange[1] = actualZFar; - pc.depthRange[2] = actualZFar - actualZNear; - - if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) - { - mVertexConstants = vc; - mDxUniformsDirty = true; - } - - if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) - { - mPixelConstants = pc; - mDxUniformsDirty = true; - } - } - - mForceSetViewport = false; + mStateManager.setViewportState(caps, viewport, zNear, zFar, drawMode, frontFace, + ignoreViewport); } bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) @@ -1258,15 +1017,14 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu { ASSERT(depthbuffer); - GLsizei width = depthbuffer->getWidth(); - GLsizei height = depthbuffer->getHeight(); + const gl::Extents &size = depthbuffer->getSize(); // search cached nullcolorbuffers for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) { if (mNullColorbufferCache[i].buffer != NULL && - mNullColorbufferCache[i].width == width && - mNullColorbufferCache[i].height == height) + mNullColorbufferCache[i].width == size.width && + mNullColorbufferCache[i].height == size.height) { mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; *outColorBuffer = mNullColorbufferCache[i].buffer; @@ -1275,14 +1033,14 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu } gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0); - gl::Error error = nullRenderbuffer->setStorage(GL_NONE, width, height); + gl::Error error = nullRenderbuffer->setStorage(GL_NONE, size.width, size.height); if (error.isError()) { SafeDelete(nullRenderbuffer); return error; } - gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer); + gl::FramebufferAttachment *nullbuffer = new gl::FramebufferAttachment(GL_RENDERBUFFER, GL_NONE, gl::ImageIndex::MakeInvalid(), nullRenderbuffer); // add nullbuffer to the cache NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; @@ -1297,44 +1055,48 @@ gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbu delete oldest->buffer; oldest->buffer = nullbuffer; oldest->lruCount = ++mMaxNullColorbufferLRU; - oldest->width = width; - oldest->height = height; + oldest->width = size.width; + oldest->height = size.height; *outColorBuffer = nullbuffer; return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer) +gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorAttachment, + const gl::FramebufferAttachment *depthStencilAttachment) { + const gl::FramebufferAttachment *renderAttachment = colorAttachment; + gl::Error error(GL_NO_ERROR); + // if there is no color attachment we must synthesize a NULL colorattachment // to keep the D3D runtime happy. This should only be possible if depth texturing. - if (!colorBuffer) + if (renderAttachment == nullptr) { - gl::Error error = getNullColorbuffer(depthStencilBuffer, &colorBuffer); + error = getNullColorbuffer(depthStencilAttachment, &renderAttachment); if (error.isError()) { return error; } } - ASSERT(colorBuffer); + ASSERT(renderAttachment != nullptr); size_t renderTargetWidth = 0; size_t renderTargetHeight = 0; D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN; + RenderTarget9 *renderTarget = nullptr; + error = renderAttachment->getRenderTarget(&renderTarget); + if (error.isError()) + { + return error; + } + ASSERT(renderTarget); + bool renderTargetChanged = false; - unsigned int renderTargetSerial = GetAttachmentSerial(colorBuffer); + unsigned int renderTargetSerial = renderTarget->getSerial(); if (renderTargetSerial != mAppliedRenderTargetSerial) { // Apply the render target on the device - RenderTarget9 *renderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(colorBuffer, &renderTarget); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget); - IDirect3DSurface9 *renderTargetSurface = renderTarget->getSurface(); ASSERT(renderTargetSurface); @@ -1349,48 +1111,45 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorBuf renderTargetChanged = true; } - unsigned int depthStencilSerial = (depthStencilBuffer != nullptr) ? GetAttachmentSerial(depthStencilBuffer) : 0; + RenderTarget9 *depthStencilRenderTarget = nullptr; + unsigned int depthStencilSerial = 0; + + if (depthStencilAttachment != nullptr) + { + error = depthStencilAttachment->getRenderTarget(&depthStencilRenderTarget); + if (error.isError()) + { + return error; + } + ASSERT(depthStencilRenderTarget); + + depthStencilSerial = depthStencilRenderTarget->getSerial(); + } + if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized) { unsigned int depthSize = 0; unsigned int stencilSize = 0; // Apply the depth stencil on the device - if (depthStencilBuffer) + if (depthStencilRenderTarget) { - RenderTarget9 *depthStencilRenderTarget = NULL; - gl::Error error = d3d9::GetAttachmentRenderTarget(depthStencilBuffer, &depthStencilRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(depthStencilRenderTarget); - IDirect3DSurface9 *depthStencilSurface = depthStencilRenderTarget->getSurface(); ASSERT(depthStencilSurface); mDevice->SetDepthStencilSurface(depthStencilSurface); SafeRelease(depthStencilSurface); - depthSize = depthStencilBuffer->getDepthSize(); - stencilSize = depthStencilBuffer->getStencilSize(); + depthSize = depthStencilAttachment->getDepthSize(); + stencilSize = depthStencilAttachment->getStencilSize(); } else { mDevice->SetDepthStencilSurface(NULL); } - if (!mDepthStencilInitialized || depthSize != mCurDepthSize) - { - mCurDepthSize = depthSize; - mForceSetRasterState = true; - } - - if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) - { - mCurStencilSize = stencilSize; - mForceSetDepthStencilState = true; - } + mStateManager.updateDepthSizeIfChanged(mDepthStencilInitialized, depthSize); + mStateManager.updateStencilSizeIfChanged(mDepthStencilInitialized, stencilSize); mAppliedDepthStencilSerial = depthStencilSerial; mDepthStencilInitialized = true; @@ -1398,13 +1157,9 @@ gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorBuf if (renderTargetChanged || !mRenderTargetDescInitialized) { - mForceSetScissor = true; - mForceSetViewport = true; - mForceSetBlendState = true; - - mRenderTargetDesc.width = renderTargetWidth; - mRenderTargetDesc.height = renderTargetHeight; - mRenderTargetDesc.format = renderTargetFormat; + mStateManager.forceSetBlendState(); + mStateManager.forceSetScissorState(); + mStateManager.setRenderTargetBounds(renderTargetWidth, renderTargetHeight); mRenderTargetDescInitialized = true; } @@ -1416,22 +1171,34 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer) return applyRenderTarget(framebuffer->getColorbuffer(0), framebuffer->getDepthOrStencilbuffer()); } -gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) +gl::Error Renderer9::applyVertexBuffer(const gl::State &state, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData * /*indexInfo*/) { - TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances); + gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances); if (error.isError()) { return error; } - return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, state.getProgram(), instances, &mRepeatDraw); + return mVertexDeclarationCache.applyDeclaration(mDevice, mTranslatedAttribCache, state.getProgram(), instances, &mRepeatDraw); } // Applies the indices and element array bindings to the Direct3D 9 device -gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); +gl::Error Renderer9::applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo) +{ + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, + indexInfo, false); if (error.isError()) { return error; @@ -1442,7 +1209,7 @@ gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *element if (indexInfo->serial != mAppliedIBSerial) { - IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); + IndexBuffer9* indexBuffer = GetAs(indexInfo->indexBuffer); mDevice->SetIndices(indexBuffer->getBuffer()); mAppliedIBSerial = indexInfo->serial; @@ -1456,7 +1223,10 @@ void Renderer9::applyTransformFeedbackBuffers(const gl::State& state) ASSERT(!state.isTransformFeedbackActiveUnpaused()); } -gl::Error Renderer9::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) +gl::Error Renderer9::drawArraysImpl(const gl::Data &data, + GLenum mode, + GLsizei count, + GLsizei instances) { ASSERT(!data.state->isTransformFeedbackActiveUnpaused()); @@ -1477,7 +1247,7 @@ gl::Error Renderer9::drawArrays(const gl::Data &data, GLenum mode, GLsizei count if (mAppliedIBSerial != countingIB->getSerial()) { - IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); + IndexBuffer9 *indexBuffer = GetAs(countingIB->getIndexBuffer()); mDevice->SetIndices(indexBuffer->getBuffer()); mAppliedIBSerial = countingIB->getSerial(); @@ -1497,13 +1267,21 @@ gl::Error Renderer9::drawArrays(const gl::Data &data, GLenum mode, GLsizei count } } -gl::Error Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) +gl::Error Renderer9::drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei /*instances*/) { startScene(); int minIndex = static_cast(indexInfo.indexRange.start); + gl::VertexArray *vao = data.state->getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + if (mode == GL_POINTS) { return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); @@ -1514,10 +1292,12 @@ gl::Error Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const } else { + size_t vertexCount = indexInfo.indexRange.vertexCount(); for (int i = 0; i < mRepeatDraw; i++) { - GLsizei vertexCount = static_cast(indexInfo.indexRange.length()) + 1; - mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); + mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, + static_cast(vertexCount), indexInfo.startIndex, + mPrimitiveCount); } return gl::Error(GL_NO_ERROR); } @@ -1663,7 +1443,7 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi case GL_NONE: // Non-indexed draw for (int i = 0; i < count; i++) { - data[i] = i; + data[i] = static_cast(i); } data[count] = 0; break; @@ -1684,9 +1464,9 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi case GL_UNSIGNED_INT: for (int i = 0; i < count; i++) { - data[i] = static_cast(indices)[i]; + data[i] = static_cast(static_cast(indices)[i]); } - data[count] = static_cast(indices)[0]; + data[count] = static_cast(static_cast(indices)[0]); break; default: UNREACHABLE(); } @@ -1700,7 +1480,7 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi if (mAppliedIBSerial != mLineLoopIB->getSerial()) { - IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer()); + IndexBuffer9 *indexBuffer = GetAs(mLineLoopIB->getIndexBuffer()); mDevice->SetIndices(indexBuffer->getBuffer()); mAppliedIBSerial = mLineLoopIB->getSerial(); @@ -1757,7 +1537,7 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou // Update the counting index buffer if it is not large enough or has not been created yet. if (count <= 65536) // 16-bit indices { - const unsigned int spaceNeeded = count * sizeof(unsigned short); + const unsigned int spaceNeeded = static_cast(count) * sizeof(unsigned short); if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) { @@ -1775,7 +1555,7 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou unsigned short *data = reinterpret_cast(mappedMemory); for (size_t i = 0; i < count; i++) { - data[i] = i; + data[i] = static_cast(i); } error = mCountingIB->unmapBuffer(); @@ -1787,7 +1567,7 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou } else if (getRendererExtensions().elementIndexUint) { - const unsigned int spaceNeeded = count * sizeof(unsigned int); + const unsigned int spaceNeeded = static_cast(count) * sizeof(unsigned int); if (!mCountingIB || mCountingIB->getBufferSize() < spaceNeeded) { @@ -1803,7 +1583,7 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou } unsigned int *data = reinterpret_cast(mappedMemory); - for (size_t i = 0; i < count; i++) + for (unsigned int i = 0; i < count; i++) { data[i] = i; } @@ -1824,13 +1604,10 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) +gl::Error Renderer9::applyShadersImpl(const gl::Data &data, GLenum /*drawMode*/) { - ASSERT(!transformFeedbackActive); - ASSERT(!rasterizerDiscard); - - ProgramD3D *programD3D = GetImplAs(program); + ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); + const auto &inputLayout = programD3D->getCachedInputLayout(); ShaderExecutableD3D *vertexExe = NULL; gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr); @@ -1839,15 +1616,16 @@ gl::Error Renderer9::applyShaders(gl::Program *program, const gl::VertexFormat i return error; } + const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); ShaderExecutableD3D *pixelExe = NULL; - error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe); + error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe); if (error.isError()) { return error; } - IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL); - IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL); + IDirect3DVertexShader9 *vertexShader = (vertexExe ? GetAs(vertexExe)->getVertexShader() : nullptr); + IDirect3DPixelShader9 *pixelShader = (pixelExe ? GetAs(pixelExe)->getPixelShader() : nullptr); if (vertexShader != mAppliedVertexShader) { @@ -1870,68 +1648,63 @@ gl::Error Renderer9::applyShaders(gl::Program *program, const gl::VertexFormat i if (programSerial != mAppliedProgramSerial) { programD3D->dirtyAllUniforms(); - mDxUniformsDirty = true; + mStateManager.forceSetDXUniformsState(); mAppliedProgramSerial = programSerial; } return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::applyUniforms(const ProgramImpl &program, const std::vector &uniformArray) +gl::Error Renderer9::applyUniforms(const ProgramD3D &programD3D, + GLenum /*drawMode*/, + const std::vector &uniformArray) { - for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) + for (const D3DUniform *targetUniform : uniformArray) { - gl::LinkedUniform *targetUniform = uniformArray[uniformIndex]; + if (!targetUniform->dirty) + continue; - if (targetUniform->dirty) - { - GLfloat *f = (GLfloat*)targetUniform->data; - GLint *i = (GLint*)targetUniform->data; + GLfloat *f = (GLfloat *)targetUniform->data; + GLint *i = (GLint *)targetUniform->data; - switch (targetUniform->type) - { - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: + switch (targetUniform->type) + { + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: break; - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: applyUniformnbv(targetUniform, i); break; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: applyUniformnfv(targetUniform, f); break; - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: applyUniformniv(targetUniform, i); break; - default: + default: UNREACHABLE(); - } } } // Driver uniforms - if (mDxUniformsDirty) - { - mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4])); - mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4])); - mDxUniformsDirty = false; - } + mStateManager.setShaderConstants(); return gl::Error(GL_NO_ERROR); } -void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v) +void Renderer9::applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v) { if (targetUniform->isReferencedByFragmentShader()) { @@ -1944,7 +1717,7 @@ void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat } } -void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v) +void Renderer9::applyUniformniv(const D3DUniform *targetUniform, const GLint *v) { ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; @@ -1960,7 +1733,7 @@ void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v applyUniformnfv(targetUniform, (GLfloat*)vector); } -void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v) +void Renderer9::applyUniformnbv(const D3DUniform *targetUniform, const GLint *v) { ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; @@ -2004,14 +1777,16 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, unsigned int stencilUnmasked = 0x0; if (clearParams.clearStencil && depthStencilBuffer->getStencilSize() > 0) { - RenderTargetD3D *stencilRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(depthStencilBuffer, &stencilRenderTarget); + ASSERT(depthStencilBuffer != nullptr); + + RenderTargetD3D *stencilRenderTarget = nullptr; + gl::Error error = depthStencilBuffer->getRenderTarget(&stencilRenderTarget); if (error.isError()) { return error; } - RenderTarget9 *stencilRenderTarget9 = RenderTarget9::makeRenderTarget9(stencilRenderTarget); + RenderTarget9 *stencilRenderTarget9 = GetAs(stencilRenderTarget); ASSERT(stencilRenderTarget9); const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat()); @@ -2025,14 +1800,16 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); if (clearColor) { + ASSERT(colorBuffer != nullptr); + RenderTargetD3D *colorRenderTarget = NULL; - gl::Error error = GetAttachmentRenderTarget(colorBuffer, &colorRenderTarget); + gl::Error error = colorBuffer->getRenderTarget(&colorRenderTarget); if (error.isError()) { return error; } - RenderTarget9 *colorRenderTarget9 = RenderTarget9::makeRenderTarget9(colorRenderTarget); + RenderTarget9 *colorRenderTarget9 = GetAs(colorRenderTarget); ASSERT(colorRenderTarget9); const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(colorBuffer->getInternalFormat()); @@ -2156,14 +1933,17 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, mDevice->SetStreamSourceFreq(i, 1); } + int renderTargetWidth = mStateManager.getRenderTargetWidth(); + int renderTargetHeight = mStateManager.getRenderTargetHeight(); + float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges quad[0][0] = -0.5f; - quad[0][1] = mRenderTargetDesc.height - 0.5f; + quad[0][1] = renderTargetHeight - 0.5f; quad[0][2] = 0.0f; quad[0][3] = 1.0f; - quad[1][0] = mRenderTargetDesc.width - 0.5f; - quad[1][1] = mRenderTargetDesc.height - 0.5f; + quad[1][0] = renderTargetWidth - 0.5f; + quad[1][1] = renderTargetHeight - 0.5f; quad[1][2] = 0.0f; quad[1][3] = 1.0f; @@ -2172,7 +1952,7 @@ gl::Error Renderer9::clear(const ClearParameters &clearParams, quad[2][2] = 0.0f; quad[2][3] = 1.0f; - quad[3][0] = mRenderTargetDesc.width - 0.5f; + quad[3][0] = renderTargetWidth - 0.5f; quad[3][1] = -0.5f; quad[3][2] = 0.0f; quad[3][3] = 1.0f; @@ -2221,31 +2001,31 @@ void Renderer9::markAllStateDirty() mDepthStencilInitialized = false; mRenderTargetDescInitialized = false; - mForceSetDepthStencilState = true; - mForceSetRasterState = true; - mForceSetScissor = true; - mForceSetViewport = true; - mForceSetBlendState = true; + mStateManager.forceSetRasterState(); + mStateManager.forceSetDepthStencilState(); + mStateManager.forceSetBlendState(); + mStateManager.forceSetScissorState(); + mStateManager.forceSetViewportState(); - ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexTextureSerials.size()); - for (unsigned int i = 0; i < mForceSetVertexSamplerStates.size(); i++) + ASSERT(mCurVertexSamplerStates.size() == mCurVertexTextures.size()); + for (unsigned int i = 0; i < mCurVertexTextures.size(); i++) { - mForceSetVertexSamplerStates[i] = true; - mCurVertexTextureSerials[i] = 0; + mCurVertexSamplerStates[i].forceSet = true; + mCurVertexTextures[i] = angle::DirtyPointer; } - ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelTextureSerials.size()); - for (unsigned int i = 0; i < mForceSetPixelSamplerStates.size(); i++) + ASSERT(mCurPixelSamplerStates.size() == mCurPixelTextures.size()); + for (unsigned int i = 0; i < mCurPixelSamplerStates.size(); i++) { - mForceSetPixelSamplerStates[i] = true; - mCurPixelTextureSerials[i] = 0; + mCurPixelSamplerStates[i].forceSet = true; + mCurPixelTextures[i] = angle::DirtyPointer; } mAppliedIBSerial = 0; mAppliedVertexShader = NULL; mAppliedPixelShader = NULL; mAppliedProgramSerial = 0; - mDxUniformsDirty = true; + mStateManager.forceSetDXUniformsState(); mVertexDeclarationCache.markStateDirty(); } @@ -2458,19 +2238,26 @@ std::string Renderer9::getRendererDescription() const return rendererString.str(); } -GUID Renderer9::getAdapterIdentifier() const +DeviceIdentifier Renderer9::getAdapterIdentifier() const { - return mAdapterIdentifier.DeviceIdentifier; + DeviceIdentifier deviceIdentifier = { 0 }; + deviceIdentifier.VendorId = static_cast(mAdapterIdentifier.VendorId); + deviceIdentifier.DeviceId = static_cast(mAdapterIdentifier.DeviceId); + deviceIdentifier.SubSysId = static_cast(mAdapterIdentifier.SubSysId); + deviceIdentifier.Revision = static_cast(mAdapterIdentifier.Revision); + deviceIdentifier.FeatureLevel = 0; + + return deviceIdentifier; } unsigned int Renderer9::getReservedVertexUniformVectors() const { - return 2; // dx_ViewAdjust and dx_DepthRange. + return d3d9_gl::GetReservedVertexUniformVectors(); } unsigned int Renderer9::getReservedFragmentUniformVectors() const { - return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. + return d3d9_gl::GetReservedFragmentUniformVectors(); } unsigned int Renderer9::getReservedVertexUniformBuffers() const @@ -2489,11 +2276,6 @@ bool Renderer9::getShareHandleSupport() const return (mD3d9Ex != NULL) && !gl::DebugAnnotationsActive(); } -bool Renderer9::getPostSubBufferSupport() const -{ - return true; -} - int Renderer9::getMajorShaderModel() const { return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); @@ -2578,6 +2360,7 @@ gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GL const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); GLuint supportedSamples = textureCaps.getNearestSamples(samples); + IDirect3DTexture9 *texture = nullptr; IDirect3DSurface9 *renderTarget = NULL; if (width > 0 && height > 0) { @@ -2593,10 +2376,23 @@ gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GL } else { - requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL); - result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat, - gl_d3d9::GetMultisampleType(supportedSamples), - 0, FALSE, &renderTarget, NULL); + requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != nullptr); + if (supportedSamples > 0) + { + result = mDevice->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &renderTarget, nullptr); + } + else + { + result = mDevice->CreateTexture( + width, height, 1, D3DUSAGE_RENDERTARGET, d3d9FormatInfo.texFormat, + getTexturePool(D3DUSAGE_RENDERTARGET), &texture, nullptr); + if (!FAILED(result)) + { + result = texture->GetSurfaceLevel(0, &renderTarget); + } + } } if (FAILED(result)) @@ -2618,13 +2414,36 @@ gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GL } } - *outRT = new TextureRenderTarget9(renderTarget, format, width, height, 1, supportedSamples); + *outRT = new TextureRenderTarget9(texture, 0, renderTarget, format, width, height, 1, + supportedSamples); return gl::Error(GL_NO_ERROR); } -FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::Framebuffer::Data &data) +gl::Error Renderer9::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) { - return createFramebuffer(data); + ASSERT(source != nullptr); + + RenderTargetD3D *newRT = nullptr; + gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(), + source->getInternalFormat(), source->getSamples(), &newRT); + if (error.isError()) + { + return error; + } + + RenderTarget9 *source9 = GetAs(source); + RenderTarget9 *dest9 = GetAs(newRT); + + HRESULT result = mDevice->StretchRect(source9->getSurface(), nullptr, dest9->getSurface(), + nullptr, D3DTEXF_NONE); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to copy render target, result: 0x%X.", result); + } + + *outRT = newRT; + return gl::Error(GL_NO_ERROR); } FramebufferImpl *Renderer9::createFramebuffer(const gl::Framebuffer::Data &data) @@ -2632,27 +2451,25 @@ FramebufferImpl *Renderer9::createFramebuffer(const gl::Framebuffer::Data &data) return new Framebuffer9(data, this); } -CompilerImpl *Renderer9::createCompiler(const gl::Data &data) +ShaderImpl *Renderer9::createShader(const gl::Shader::Data &data) { - return new CompilerD3D(data, SH_HLSL9_OUTPUT); + return new ShaderD3D(data); } -ShaderImpl *Renderer9::createShader(GLenum type) +ProgramImpl *Renderer9::createProgram(const gl::Program::Data &data) { - return new ShaderD3D(type); + return new ProgramD3D(data, this); } -ProgramImpl *Renderer9::createProgram() -{ - return new ProgramD3D(this); -} - -gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) +gl::Error Renderer9::loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) { // Transform feedback is not supported in ES2 or D3D9 - ASSERT(transformFeedbackVaryings.size() == 0); + ASSERT(streamOutVaryings.empty()); switch (type) { @@ -2686,13 +2503,16 @@ gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderT return gl::Error(GL_NO_ERROR); } -gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, +gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, ShaderExecutableD3D **outExectuable) { // Transform feedback is not supported in ES2 or D3D9 - ASSERT(transformFeedbackVaryings.size() == 0); + ASSERT(streamOutVaryings.empty()); const char *profileType = NULL; switch (type) @@ -2755,7 +2575,7 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string } error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - transformFeedbackVaryings, separatedOutputBuffers, outExectuable); + streamOutVaryings, separatedOutputBuffers, outExectuable); SafeRelease(binary); if (error.isError()) @@ -2841,17 +2661,29 @@ ImageD3D *Renderer9::createImage() gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src) { - Image9 *src9 = Image9::makeImage9(src); - Image9 *dst9 = Image9::makeImage9(dest); + Image9 *src9 = GetAs(src); + Image9 *dst9 = GetAs(dest); return Image9::generateMipmap(dst9, src9); } +gl::Error Renderer9::generateMipmapsUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) +{ + UNREACHABLE(); + return gl::Error(GL_NO_ERROR); +} + TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain) { - SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); + SwapChain9 *swapChain9 = GetAs(swapChain); return new TextureStorage9_2D(this, swapChain9); } +TextureStorage *Renderer9::createTextureStorageEGLImage(EGLImageD3D *eglImage) +{ + return new TextureStorage9_EGLImage(this, eglImage); +} + TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) { return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); @@ -2910,24 +2742,75 @@ bool Renderer9::getLUID(LUID *adapterLuid) const return false; } -VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const +VertexConversionType Renderer9::getVertexConversionType(gl::VertexFormatType vertexFormatType) const { - return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).conversionType; + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).conversionType; } -GLenum Renderer9::getVertexComponentType(const gl::VertexFormat &vertexFormat) const +GLenum Renderer9::getVertexComponentType(gl::VertexFormatType vertexFormatType) const { - return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).componentType; + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormatType).componentType; } -void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const +void Renderer9::generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const { - d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions); + d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, + outExtensions, outLimitations); } -Workarounds Renderer9::generateWorkarounds() const +WorkaroundsD3D Renderer9::generateWorkarounds() const { return d3d9::GenerateWorkarounds(); } +void Renderer9::createAnnotator() +{ + mAnnotator = new DebugAnnotator9(); +} + +gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) +{ + // TODO(jmadill): faster way? + for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; samplerIndex++) + { + gl::Error error = setTexture(samplerType, static_cast(samplerIndex), nullptr); + if (error.isError()) + { + return error; + } + } + + return gl::Error(GL_NO_ERROR); +} + +egl::Error Renderer9::getEGLDevice(DeviceImpl **device) +{ + if (mEGLDevice == nullptr) + { + ASSERT(mDevice != nullptr); + mEGLDevice = new DeviceD3D(); + egl::Error error = mEGLDevice->initialize(reinterpret_cast(mDevice), + EGL_D3D9_DEVICE_ANGLE, EGL_FALSE); + + if (error.isError()) + { + SafeDelete(mEGLDevice); + return error; + } + } + + *device = static_cast(mEGLDevice); + return egl::Error(EGL_SUCCESS); +} + +Renderer9::CurSamplerState::CurSamplerState() + : forceSet(true), + baseLevel(std::numeric_limits::max()), + samplerState() +{ +} + } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h index 19bea3eb35..a0dfecb02e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h @@ -17,6 +17,7 @@ #include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h" #include "libANGLE/renderer/d3d/d3d9/ShaderCache.h" #include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h" +#include "libANGLE/renderer/d3d/d3d9/StateManager9.h" namespace gl { @@ -32,10 +33,12 @@ namespace rx { class Blit9; class IndexDataManager; +class ProgramD3D; class StreamingIndexBufferInterface; class StaticIndexBufferInterface; class VertexDataManager; struct ClearParameters; +struct D3DUniform; struct TranslatedAttribute; enum D3D9InitError @@ -64,12 +67,11 @@ class Renderer9 : public RendererD3D explicit Renderer9(egl::Display *display); virtual ~Renderer9(); - static Renderer9 *makeRenderer9(Renderer *renderer); - egl::Error initialize() override; virtual bool resetDevice(); egl::ConfigSet generateConfigs() const override; + void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override; void startScene(); void endScene(); @@ -77,7 +79,13 @@ class Renderer9 : public RendererD3D gl::Error flush() override; gl::Error finish() override; - virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) override; + + CompilerImpl *createCompiler() override; gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery); void freeEventQuery(IDirect3DQuery9* query); @@ -92,34 +100,42 @@ class Renderer9 : public RendererD3D virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); gl::Error setUniformBuffers(const gl::Data &data, - const GLint vertexUniformBuffers[], - const GLint fragmentUniformBuffers[]) override; + const std::vector &vertexUniformBuffers, + const std::vector &fragmentUniformBuffers) override; - virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); - gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) override; - virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); + gl::Error updateState(const gl::Data &data, GLenum drawMode) override; - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); + void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + void setViewport(const gl::Caps *caps, + const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, + bool ignoreViewport); gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override; - gl::Error applyRenderTarget(const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer); - virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive); - virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector &uniformArray); + gl::Error applyRenderTarget(const gl::FramebufferAttachment *colorAttachment, + const gl::FramebufferAttachment *depthStencilAttachment); + gl::Error applyUniforms(const ProgramD3D &programD3D, + GLenum drawMode, + const std::vector &uniformArray) override; virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize); - virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances); - virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + virtual gl::Error applyVertexBuffer(const gl::State &state, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instances, + TranslatedIndexData *indexInfo); + gl::Error applyIndexBuffer(const gl::Data &data, + const GLvoid *indices, + GLsizei count, + GLenum mode, + GLenum type, + TranslatedIndexData *indexInfo) override; void applyTransformFeedbackBuffers(const gl::State &state) override; - gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override; - virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - gl::Error clear(const ClearParameters &clearParams, const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer); @@ -130,18 +146,19 @@ class Renderer9 : public RendererD3D bool testDeviceLost() override; bool testDeviceResettable() override; - VendorID getVendorId() const override; + VendorID getVendorId() const; std::string getRendererDescription() const override; - GUID getAdapterIdentifier() const override; + DeviceIdentifier getAdapterIdentifier() const override; IDirect3DDevice9 *getDevice() { return mDevice; } + void *getD3DDevice() override; virtual unsigned int getReservedVertexUniformVectors() const; virtual unsigned int getReservedFragmentUniformVectors() const; virtual unsigned int getReservedVertexUniformBuffers() const; virtual unsigned int getReservedFragmentUniformBuffers() const; - virtual bool getShareHandleSupport() const; - virtual bool getPostSubBufferSupport() const; + + bool getShareHandleSupport() const; virtual int getMajorShaderModel() const; int getMinorShaderModel() const override; @@ -161,30 +178,38 @@ class Renderer9 : public RendererD3D // RenderTarget creation virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT); + gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override; // Framebuffer creation - FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override; FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override; // Shader creation - virtual CompilerImpl *createCompiler(const gl::Data &data); - virtual ShaderImpl *createShader(GLenum type); - virtual ProgramImpl *createProgram(); + ShaderImpl *createShader(const gl::Shader::Data &data) override; + ProgramImpl *createProgram(const gl::Program::Data &data) override; // Shader operations - virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable); - virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type, - const std::vector &transformFeedbackVaryings, - bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds, - ShaderExecutableD3D **outExectuable); - virtual UniformStorageD3D *createUniformStorage(size_t storageSize); + gl::Error loadExecutable(const void *function, + size_t length, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + ShaderExecutableD3D **outExecutable) override; + gl::Error compileToExecutable(gl::InfoLog &infoLog, + const std::string &shaderHLSL, + ShaderType type, + const std::vector &streamOutVaryings, + bool separatedOutputBuffers, + const D3DCompilerWorkarounds &workarounds, + ShaderExecutableD3D **outExectuable) override; + UniformStorageD3D *createUniformStorage(size_t storageSize) override; // Image operations virtual ImageD3D *createImage(); gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override; + gl::Error generateMipmapsUsingD3D(TextureStorage *storage, + const gl::TextureState &textureState) override; virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain); + TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage) override; virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly); virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); @@ -202,7 +227,7 @@ class Renderer9 : public RendererD3D virtual IndexBuffer *createIndexBuffer(); // Vertex Array creation - virtual VertexArrayImpl *createVertexArray(); + VertexArrayImpl *createVertexArray(const gl::VertexArray::Data &data) override; // Query and Fence creation virtual QueryImpl *createQuery(GLenum type); @@ -217,14 +242,16 @@ class Renderer9 : public RendererD3D virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override; + // D3D9-renderer specific methods gl::Error boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); D3DPOOL getTexturePool(DWORD usage) const; bool getLUID(LUID *adapterLuid) const override; - virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; - virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; + VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override; + GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override; gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); @@ -232,15 +259,39 @@ class Renderer9 : public RendererD3D D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; } + egl::Error getEGLDevice(DeviceImpl **device) override; + + protected: + void createAnnotator() override; + gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override; + gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override; + private: - void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override; - Workarounds generateWorkarounds() const override; + gl::Error drawArraysImpl(const gl::Data &data, + GLenum mode, + GLsizei count, + GLsizei instances) override; + gl::Error drawElementsImpl(const gl::Data &data, + const TranslatedIndexData &indexInfo, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei instances) override; + + void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const override; + + WorkaroundsD3D generateWorkarounds() const override; + + gl::Error setBlendDepthRasterStates(const gl::Data &glData, GLenum drawMode); void release(); - void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v); - void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v); - void applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v); + void applyUniformnfv(const D3DUniform *targetUniform, const GLfloat *v); + void applyUniformniv(const D3DUniform *targetUniform, const GLint *v); + void applyUniformnbv(const D3DUniform *targetUniform, const GLint *v); gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); gl::Error drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); @@ -290,64 +341,32 @@ class Renderer9 : public RendererD3D unsigned int mAppliedDepthStencilSerial; bool mDepthStencilInitialized; bool mRenderTargetDescInitialized; - unsigned int mCurStencilSize; - unsigned int mCurDepthSize; - - struct RenderTargetDesc - { - size_t width; - size_t height; - D3DFORMAT format; - }; - RenderTargetDesc mRenderTargetDesc; IDirect3DStateBlock9 *mMaskedClearSavedState; - // previously set render states - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - bool mCurFrontFaceCCW; - - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - bool mForceSetScissor; - gl::Rectangle mCurScissor; - bool mScissorEnabled; - - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; - float mCurDepthFront; - - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::ColorF mCurBlendColor; - GLuint mCurSampleMask; + StateManager9 mStateManager; // Currently applied sampler states - std::vector mForceSetVertexSamplerStates; - std::vector mCurVertexSamplerStates; + struct CurSamplerState + { + CurSamplerState(); - std::vector mForceSetPixelSamplerStates; - std::vector mCurPixelSamplerStates; + bool forceSet; + size_t baseLevel; + gl::SamplerState samplerState; + }; + std::vector mCurVertexSamplerStates; + std::vector mCurPixelSamplerStates; // Currently applied textures - std::vector mCurVertexTextureSerials; - std::vector mCurPixelTextureSerials; + std::vector mCurVertexTextures; + std::vector mCurPixelTextures; unsigned int mAppliedIBSerial; IDirect3DVertexShader9 *mAppliedVertexShader; IDirect3DPixelShader9 *mAppliedPixelShader; unsigned int mAppliedProgramSerial; - dx_VertexConstants mVertexConstants; - dx_PixelConstants mPixelConstants; - bool mDxUniformsDirty; - // A pool of event queries that are currently unused. std::vector mEventQueryPool; VertexShaderCache mVertexShaderCache; @@ -370,7 +389,7 @@ class Renderer9 : public RendererD3D } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; UINT mMaxNullColorbufferLRU; - DebugAnnotator9 mAnnotator; + DeviceD3D *mEGLDevice; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp index 280e80930b..28a486056b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp @@ -34,12 +34,6 @@ ShaderExecutable9::~ShaderExecutable9() SafeRelease(mPixelExecutable); } -ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutableD3D *executable) -{ - ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable)); - return static_cast(executable); -} - IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const { return mVertexExecutable; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h index 561f7defc8..382a68c820 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h @@ -22,8 +22,6 @@ class ShaderExecutable9 : public ShaderExecutableD3D ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); virtual ~ShaderExecutable9(); - static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutableD3D *executable); - IDirect3DPixelShader9 *getPixelShader() const; IDirect3DVertexShader9 *getVertexShader() const; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp new file mode 100644 index 0000000000..c4c600aedb --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.cpp @@ -0,0 +1,903 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManager9.cpp: Defines a class for caching D3D9 state +#include "libANGLE/renderer/d3d/d3d9/StateManager9.h" + +#include "common/BitSetIterator.h" +#include "common/utilities.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +StateManager9::StateManager9(Renderer9 *renderer9) + : mCurBlendState(), + mCurBlendColor(0, 0, 0, 0), + mCurSampleMask(0), + mCurRasterState(), + mCurDepthSize(0), + mCurDepthStencilState(), + mCurStencilRef(0), + mCurStencilBackRef(0), + mCurFrontFaceCCW(0), + mCurStencilSize(0), + mCurScissorRect(), + mCurScissorEnabled(false), + mCurViewport(), + mCurNear(0.0f), + mCurFar(0.0f), + mCurDepthFront(0.0f), + mCurIgnoreViewport(false), + mRenderer9(renderer9), + mDirtyBits() +{ + mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); + mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + mBlendStateDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE); + mBlendStateDirtyBits.set(DIRTY_BIT_COLOR_MASK); + mBlendStateDirtyBits.set(DIRTY_BIT_DITHER); + mBlendStateDirtyBits.set(DIRTY_BIT_SAMPLE_MASK); + + mRasterizerStateDirtyBits.set(DIRTY_BIT_CULL_MODE); + mRasterizerStateDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); + + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); + mDepthStencilStateDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); + + mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED); + mScissorStateDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); +} + +StateManager9::~StateManager9() +{ +} + +void StateManager9::forceSetBlendState() +{ + mDirtyBits |= mBlendStateDirtyBits; +} + +void StateManager9::forceSetRasterState() +{ + mDirtyBits |= mRasterizerStateDirtyBits; +} + +void StateManager9::forceSetDepthStencilState() +{ + mDirtyBits |= mDepthStencilStateDirtyBits; +} + +void StateManager9::forceSetScissorState() +{ + mDirtyBits |= mScissorStateDirtyBits; +} + +void StateManager9::forceSetViewportState() +{ + mForceSetViewport = true; +} + +void StateManager9::forceSetDXUniformsState() +{ + mDxUniformsDirty = true; +} + +void StateManager9::updateStencilSizeIfChanged(bool depthStencilInitialized, + unsigned int stencilSize) +{ + if (!depthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + forceSetDepthStencilState(); + } +} + +void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +{ + if (!dirtyBits.any()) + { + return; + } + + for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) + { + switch (dirtyBit) + { + case gl::State::DIRTY_BIT_BLEND_ENABLED: + if (state.getBlendState().blend != mCurBlendState.blend) + { + mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); + // BlendColor and funcs and equations has to be set if blend is enabled + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + } + break; + case gl::State::DIRTY_BIT_BLEND_FUNCS: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB || + blendState.destBlendRGB != mCurBlendState.destBlendRGB || + blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || + blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) + { + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + // BlendColor depends on the values of blend funcs + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + } + break; + } + case gl::State::DIRTY_BIT_BLEND_EQUATIONS: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || + blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) + { + mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); + } + break; + } + case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: + if (state.getBlendState().sampleAlphaToCoverage != + mCurBlendState.sampleAlphaToCoverage) + { + mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE); + } + break; + case gl::State::DIRTY_BIT_COLOR_MASK: + { + const gl::BlendState &blendState = state.getBlendState(); + if (blendState.colorMaskRed != mCurBlendState.colorMaskRed || + blendState.colorMaskGreen != mCurBlendState.colorMaskGreen || + blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || + blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) + { + mDirtyBits.set(DIRTY_BIT_COLOR_MASK); + } + break; + } + case gl::State::DIRTY_BIT_DITHER_ENABLED: + if (state.getBlendState().dither != mCurBlendState.dither) + { + mDirtyBits.set(DIRTY_BIT_DITHER); + } + break; + case gl::State::DIRTY_BIT_BLEND_COLOR: + if (state.getBlendColor() != mCurBlendColor) + { + mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); + } + break; + case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: + if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) + { + mDirtyBits.set(DIRTY_BIT_CULL_MODE); + } + break; + case gl::State::DIRTY_BIT_CULL_FACE: + if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) + { + mDirtyBits.set(DIRTY_BIT_CULL_MODE); + } + break; + case gl::State::DIRTY_BIT_FRONT_FACE: + if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) + { + mDirtyBits.set(DIRTY_BIT_CULL_MODE); + + // Viewport state depends on rasterizer.frontface + mDirtyBits.set(DIRTY_BIT_VIEWPORT); + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: + if (state.getRasterizerState().polygonOffsetFill != + mCurRasterState.polygonOffsetFill) + { + mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); + } + break; + case gl::State::DIRTY_BIT_POLYGON_OFFSET: + { + const gl::RasterizerState &rasterizerState = state.getRasterizerState(); + if (rasterizerState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || + rasterizerState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) + { + mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); + } + } + case gl::State::DIRTY_BIT_DEPTH_MASK: + if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK); + } + break; + case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: + if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); + } + break; + case gl::State::DIRTY_BIT_DEPTH_FUNC: + if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); + } + break; + case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: + if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); + // If we enable the stencil test, all of these must be set + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); + } + break; + case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilFunc != mCurDepthStencilState.stencilFunc || + depthStencilState.stencilMask != mCurDepthStencilState.stencilMask || + state.getStencilRef() != mCurStencilRef) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilBackFunc != mCurDepthStencilState.stencilBackFunc || + depthStencilState.stencilBackMask != mCurDepthStencilState.stencilBackMask || + state.getStencilBackRef() != mCurStencilBackRef) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + if (state.getDepthStencilState().stencilWritemask != + mCurDepthStencilState.stencilWritemask) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); + } + break; + case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: + if (state.getDepthStencilState().stencilBackWritemask != + mCurDepthStencilState.stencilBackWritemask) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); + } + break; + case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilFail != mCurDepthStencilState.stencilFail || + depthStencilState.stencilPassDepthFail != + mCurDepthStencilState.stencilPassDepthFail || + depthStencilState.stencilPassDepthPass != + mCurDepthStencilState.stencilPassDepthPass) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); + } + break; + } + case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: + { + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); + if (depthStencilState.stencilBackFail != mCurDepthStencilState.stencilBackFail || + depthStencilState.stencilBackPassDepthFail != + mCurDepthStencilState.stencilBackPassDepthFail || + depthStencilState.stencilBackPassDepthPass != + mCurDepthStencilState.stencilBackPassDepthPass) + { + mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); + } + break; + } + case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: + if (state.isScissorTestEnabled() != mCurScissorEnabled) + { + mDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED); + // If scissor is enabled, we have to set the scissor rect + mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); + } + break; + case gl::State::DIRTY_BIT_SCISSOR: + if (state.getScissor() != mCurScissorRect) + { + mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); + } + break; + case gl::State::DIRTY_BIT_DEPTH_RANGE: + if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) + { + mDirtyBits.set(DIRTY_BIT_VIEWPORT); + } + break; + case gl::State::DIRTY_BIT_VIEWPORT: + if (state.getViewport() != mCurViewport) + { + mDirtyBits.set(DIRTY_BIT_VIEWPORT); + } + break; + default: + break; + } + } +} + +gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState, + unsigned int sampleMask) +{ + const gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + + const gl::BlendState &blendState = glState.getBlendState(); + const gl::ColorF &blendColor = glState.getBlendColor(); + const gl::RasterizerState &rasterState = glState.getRasterizerState(); + + const auto &depthStencilState = glState.getDepthStencilState(); + bool frontFaceCCW = (glState.getRasterizerState().frontFace == GL_CCW); + unsigned int maxStencil = (1 << mCurStencilSize) - 1; + + // All the depth stencil states depends on the front face ccw variable + if (frontFaceCCW != mCurFrontFaceCCW) + { + forceSetDepthStencilState(); + mCurFrontFaceCCW = frontFaceCCW; + } + + for (auto dirtyBit : angle::IterateBitSet(mDirtyBits)) + { + switch (dirtyBit) + { + case DIRTY_BIT_BLEND_ENABLED: + setBlendEnabled(blendState.blend); + break; + case DIRTY_BIT_BLEND_COLOR: + setBlendColor(blendState, blendColor); + break; + case DIRTY_BIT_BLEND_FUNCS_EQUATIONS: + setBlendFuncsEquations(blendState); + break; + case DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE: + setSampleAlphaToCoverage(blendState.sampleAlphaToCoverage); + break; + case DIRTY_BIT_COLOR_MASK: + setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue, + blendState.colorMaskGreen, blendState.colorMaskAlpha); + break; + case DIRTY_BIT_DITHER: + setDither(blendState.dither); + break; + case DIRTY_BIT_CULL_MODE: + setCullMode(rasterState.cullFace, rasterState.cullMode, rasterState.frontFace); + break; + case DIRTY_BIT_DEPTH_BIAS: + setDepthBias(rasterState.polygonOffsetFill, rasterState.polygonOffsetFactor, + rasterState.polygonOffsetUnits); + break; + case DIRTY_BIT_STENCIL_DEPTH_MASK: + setDepthMask(depthStencilState.depthMask); + break; + case DIRTY_BIT_STENCIL_DEPTH_FUNC: + setDepthFunc(depthStencilState.depthTest, depthStencilState.depthFunc); + break; + case DIRTY_BIT_STENCIL_TEST_ENABLED: + setStencilTestEnabled(depthStencilState.stencilTest); + break; + case DIRTY_BIT_STENCIL_FUNCS_FRONT: + setStencilFuncsFront(depthStencilState.stencilFunc, depthStencilState.stencilMask, + glState.getStencilRef(), frontFaceCCW, maxStencil); + break; + case DIRTY_BIT_STENCIL_FUNCS_BACK: + setStencilFuncsBack(depthStencilState.stencilBackFunc, + depthStencilState.stencilBackMask, glState.getStencilBackRef(), + frontFaceCCW, maxStencil); + break; + case DIRTY_BIT_STENCIL_WRITEMASK_FRONT: + setStencilWriteMask(depthStencilState.stencilWritemask, frontFaceCCW); + break; + case DIRTY_BIT_STENCIL_WRITEMASK_BACK: + setStencilBackWriteMask(depthStencilState.stencilBackWritemask, frontFaceCCW); + break; + case DIRTY_BIT_STENCIL_OPS_FRONT: + setStencilOpsFront(depthStencilState.stencilFail, + depthStencilState.stencilPassDepthFail, + depthStencilState.stencilPassDepthPass, frontFaceCCW); + break; + case DIRTY_BIT_STENCIL_OPS_BACK: + setStencilOpsBack(depthStencilState.stencilBackFail, + depthStencilState.stencilBackPassDepthFail, + depthStencilState.stencilBackPassDepthPass, frontFaceCCW); + break; + default: + break; + } + } + + if (sampleMask != mCurSampleMask) + { + setSampleMask(sampleMask); + } + + return gl::Error(GL_NO_ERROR); +} + +void StateManager9::setViewportState(const gl::Caps *caps, + const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, + bool ignoreViewport) +{ + if (!mDirtyBits.test(DIRTY_BIT_VIEWPORT) && mCurIgnoreViewport == ignoreViewport) + return; + + gl::Rectangle actualViewport = viewport; + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + + if (ignoreViewport) + { + actualViewport.x = 0; + actualViewport.y = 0; + actualViewport.width = static_cast(mRenderTargetBounds.width); + actualViewport.height = static_cast(mRenderTargetBounds.height); + actualZNear = 0.0f; + actualZFar = 1.0f; + } + + D3DVIEWPORT9 dxViewport; + dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast(mRenderTargetBounds.width)); + dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast(mRenderTargetBounds.height)); + dxViewport.Width = + gl::clamp(actualViewport.width, 0, + static_cast(mRenderTargetBounds.width) - static_cast(dxViewport.X)); + dxViewport.Height = + gl::clamp(actualViewport.height, 0, + static_cast(mRenderTargetBounds.height) - static_cast(dxViewport.Y)); + dxViewport.MinZ = actualZNear; + dxViewport.MaxZ = actualZFar; + + float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); + + mRenderer9->getDevice()->SetViewport(&dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + mCurDepthFront = depthFront; + mCurIgnoreViewport = ignoreViewport; + + // Setting shader constants + dx_VertexConstants9 vc = {}; + dx_PixelConstants9 pc = {}; + + vc.viewAdjust[0] = + static_cast((actualViewport.width - static_cast(dxViewport.Width)) + + 2 * (actualViewport.x - static_cast(dxViewport.X)) - 1) / + dxViewport.Width; + vc.viewAdjust[1] = + static_cast((actualViewport.height - static_cast(dxViewport.Height)) + + 2 * (actualViewport.y - static_cast(dxViewport.Y)) - 1) / + dxViewport.Height; + vc.viewAdjust[2] = static_cast(actualViewport.width) / dxViewport.Width; + vc.viewAdjust[3] = static_cast(actualViewport.height) / dxViewport.Height; + + pc.viewCoords[0] = actualViewport.width * 0.5f; + pc.viewCoords[1] = actualViewport.height * 0.5f; + pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + pc.depthFront[2] = depthFront; + + vc.depthRange[0] = actualZNear; + vc.depthRange[1] = actualZFar; + vc.depthRange[2] = actualZFar - actualZNear; + + pc.depthRange[0] = actualZNear; + pc.depthRange[1] = actualZFar; + pc.depthRange[2] = actualZFar - actualZNear; + + if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants9)) != 0) + { + mVertexConstants = vc; + mDxUniformsDirty = true; + } + + if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants9)) != 0) + { + mPixelConstants = pc; + mDxUniformsDirty = true; + } + + mForceSetViewport = false; +} + +void StateManager9::setShaderConstants() +{ + if (!mDxUniformsDirty) + return; + + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetVertexShaderConstantF(0, reinterpret_cast(&mVertexConstants), + sizeof(dx_VertexConstants9) / sizeof(float[4])); + device->SetPixelShaderConstantF(0, reinterpret_cast(&mPixelConstants), + sizeof(dx_PixelConstants9) / sizeof(float[4])); + mDxUniformsDirty = false; +} + +// This is separate from the main state loop because other functions +// outside call only setScissorState to update scissor state +void StateManager9::setScissorState(const gl::Rectangle &scissor, bool enabled) +{ + if (mDirtyBits.test(DIRTY_BIT_SCISSOR_ENABLED)) + setScissorEnabled(enabled); + + if (mDirtyBits.test(DIRTY_BIT_SCISSOR_RECT)) + setScissorRect(scissor, enabled); +} + +void StateManager9::setRenderTargetBounds(size_t width, size_t height) +{ + mRenderTargetBounds.width = (int)width; + mRenderTargetBounds.height = (int)height; + forceSetViewportState(); +} + +void StateManager9::setScissorEnabled(bool scissorEnabled) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_SCISSORTESTENABLE, scissorEnabled ? TRUE : FALSE); + mCurScissorEnabled = scissorEnabled; +} + +void StateManager9::setScissorRect(const gl::Rectangle &scissor, bool enabled) +{ + if (!enabled) + return; + + RECT rect; + rect.left = gl::clamp(scissor.x, 0, static_cast(mRenderTargetBounds.width)); + rect.top = gl::clamp(scissor.y, 0, static_cast(mRenderTargetBounds.height)); + rect.right = + gl::clamp(scissor.x + scissor.width, 0, static_cast(mRenderTargetBounds.width)); + rect.bottom = + gl::clamp(scissor.y + scissor.height, 0, static_cast(mRenderTargetBounds.height)); + mRenderer9->getDevice()->SetScissorRect(&rect); +} + +void StateManager9::setDepthFunc(bool depthTest, GLenum depthFunc) +{ + if (depthTest) + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + device->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthFunc)); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + } + + mCurDepthStencilState.depthTest = depthTest; + mCurDepthStencilState.depthFunc = depthFunc; +} + +void StateManager9::setStencilOpsFront(GLenum stencilFail, + GLenum stencilPassDepthFail, + GLenum stencilPassDepthPass, + bool frontFaceCCW) +{ + // TODO(dianx) It may be slightly more efficient todo these and other similar areas + // with separate dirty bits. + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(stencilFail)); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(stencilPassDepthFail)); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(stencilPassDepthPass)); + + mCurDepthStencilState.stencilFail = stencilFail; + mCurDepthStencilState.stencilPassDepthFail = stencilPassDepthFail; + mCurDepthStencilState.stencilPassDepthPass = stencilPassDepthPass; +} + +void StateManager9::setStencilOpsBack(GLenum stencilBackFail, + GLenum stencilBackPassDepthFail, + GLenum stencilBackPassDepthPass, + bool frontFaceCCW) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(stencilBackFail)); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(stencilBackPassDepthFail)); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(stencilBackPassDepthPass)); + + mCurDepthStencilState.stencilBackFail = stencilBackFail; + mCurDepthStencilState.stencilBackPassDepthFail = stencilBackPassDepthFail; + mCurDepthStencilState.stencilBackPassDepthPass = stencilBackPassDepthPass; +} + +void StateManager9::setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW) +{ + mRenderer9->getDevice()->SetRenderState( + !frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilBackWriteMask); + + mCurDepthStencilState.stencilBackWritemask = stencilBackWriteMask; +} + +void StateManager9::setStencilFuncsBack(GLenum stencilBackFunc, + GLuint stencilBackMask, + GLint stencilBackRef, + bool frontFaceCCW, + unsigned int maxStencil) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(stencilBackFunc)); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); + device->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, + stencilBackMask); + + mCurDepthStencilState.stencilBackFunc = stencilBackFunc; + mCurStencilBackRef = stencilBackRef; + mCurDepthStencilState.stencilBackMask = stencilBackMask; +} + +void StateManager9::setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW) +{ + mRenderer9->getDevice()->SetRenderState( + frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, stencilWriteMask); + mCurDepthStencilState.stencilWritemask = stencilWriteMask; +} + +void StateManager9::setStencilFuncsFront(GLenum stencilFunc, + GLuint stencilMask, + GLint stencilRef, + bool frontFaceCCW, + unsigned int maxStencil) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(stencilFunc)); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilRef < static_cast(maxStencil)) ? stencilRef : maxStencil); + device->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, stencilMask); + + mCurDepthStencilState.stencilFunc = stencilFunc; + mCurStencilRef = stencilRef; + mCurDepthStencilState.stencilMask = stencilMask; +} +void StateManager9::setStencilTestEnabled(bool stencilTestEnabled) +{ + if (stencilTestEnabled && mCurStencilSize > 0) + { + mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, TRUE); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mCurDepthStencilState.stencilTest = stencilTestEnabled; +} + +void StateManager9::setDepthMask(bool depthMask) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_ZWRITEENABLE, depthMask ? TRUE : FALSE); + mCurDepthStencilState.depthMask = depthMask; +} + +// TODO(dianx) one bit for sampleAlphaToCoverage +void StateManager9::setSampleAlphaToCoverage(bool enabled) +{ + if (enabled) + { + FIXME("Sample alpha to coverage is unimplemented."); + } +} + +void StateManager9::setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor) +{ + if (!blendState.blend) + return; + + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && + blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + mRenderer9->getDevice()->SetRenderState(D3DRS_BLENDFACTOR, + gl_d3d9::ConvertColor(blendColor)); + } + else + { + mRenderer9->getDevice()->SetRenderState( + D3DRS_BLENDFACTOR, + D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha), gl::unorm<8>(blendColor.alpha))); + } + mCurBlendColor = blendColor; +} + +void StateManager9::setBlendFuncsEquations(const gl::BlendState &blendState) +{ + if (!blendState.blend) + return; + + IDirect3DDevice9 *device = mRenderer9->getDevice(); + + device->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); + device->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); + device->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); + + if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || + blendState.destBlendRGB != blendState.destBlendAlpha || + blendState.blendEquationRGB != blendState.blendEquationAlpha) + { + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + + device->SetRenderState(D3DRS_SRCBLENDALPHA, + gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); + device->SetRenderState(D3DRS_DESTBLENDALPHA, + gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); + device->SetRenderState(D3DRS_BLENDOPALPHA, + gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); + } + else + { + device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); + } + + mCurBlendState.sourceBlendRGB = blendState.sourceBlendRGB; + mCurBlendState.destBlendRGB = blendState.destBlendRGB; + mCurBlendState.blendEquationRGB = blendState.blendEquationRGB; + mCurBlendState.blendEquationAlpha = blendState.blendEquationAlpha; +} + +void StateManager9::setBlendEnabled(bool enabled) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_ALPHABLENDENABLE, enabled ? TRUE : FALSE); + mCurBlendState.blend = enabled; +} + +void StateManager9::setDither(bool dither) +{ + mRenderer9->getDevice()->SetRenderState(D3DRS_DITHERENABLE, dither ? TRUE : FALSE); + mCurBlendState.dither = dither; +} + +// TODO(dianx) one bit for color mask +void StateManager9::setColorMask(const gl::Framebuffer *framebuffer, + bool red, + bool blue, + bool green, + bool alpha) +{ + // Set the color mask + bool zeroColorMaskAllowed = mRenderer9->getVendorId() != VENDOR_ID_AMD; + // Apparently some ATI cards have a bug where a draw with a zero color + // write mask can cause later draws to have incorrect results. Instead, + // set a nonzero color write mask but modify the blend state so that no + // drawing is done. + // http://code.google.com/p/angleproject/issues/detail?id=169 + + const gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); + GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; + + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + + DWORD colorMask = gl_d3d9::ConvertColorMask( + formatInfo.redBits > 0 && red, formatInfo.greenBits > 0 && green, + formatInfo.blueBits > 0 && blue, formatInfo.alphaBits > 0 && alpha); + + if (colorMask == 0 && !zeroColorMaskAllowed) + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + // Enable green channel, but set blending so nothing will be drawn. + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); + } + + mCurBlendState.colorMaskRed = red; + mCurBlendState.colorMaskGreen = green; + mCurBlendState.colorMaskBlue = blue; + mCurBlendState.colorMaskAlpha = alpha; +} + +void StateManager9::setSampleMask(unsigned int sampleMask) +{ + IDirect3DDevice9 *device = mRenderer9->getDevice(); + // Set the multisample mask + device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); + device->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast(sampleMask)); + + mCurSampleMask = sampleMask; +} + +void StateManager9::setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace) +{ + if (cullFace) + { + mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, + gl_d3d9::ConvertCullMode(cullMode, frontFace)); + } + else + { + mRenderer9->getDevice()->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + } + + mCurRasterState.cullFace = cullFace; + mCurRasterState.cullMode = cullMode; + mCurRasterState.frontFace = frontFace; +} + +void StateManager9::setDepthBias(bool polygonOffsetFill, + GLfloat polygonOffsetFactor, + GLfloat polygonOffsetUnits) +{ + if (polygonOffsetFill) + { + if (mCurDepthSize > 0) + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD *)&polygonOffsetFactor); + + float depthBias = ldexp(polygonOffsetUnits, -static_cast(mCurDepthSize)); + device->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD *)&depthBias); + } + } + else + { + IDirect3DDevice9 *device = mRenderer9->getDevice(); + device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); + device->SetRenderState(D3DRS_DEPTHBIAS, 0); + } + + mCurRasterState.polygonOffsetFill = polygonOffsetFill; + mCurRasterState.polygonOffsetFactor = polygonOffsetFactor; + mCurRasterState.polygonOffsetUnits = polygonOffsetUnits; +} + +void StateManager9::updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize) +{ + if (!depthStencilInitialized || depthSize != mCurDepthSize) + { + mCurDepthSize = depthSize; + forceSetRasterState(); + } +} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h new file mode 100644 index 0000000000..d8c1eb9812 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/StateManager9.h @@ -0,0 +1,206 @@ +// +// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// StateManager9.h: Defines a class for caching D3D9 state + +#ifndef LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ +#define LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ + +#include "libANGLE/angletypes.h" +#include "libANGLE/Data.h" +#include "libANGLE/State.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" + +namespace rx +{ + +class Renderer9; + +struct dx_VertexConstants9 +{ + float depthRange[4]; + float viewAdjust[4]; + float viewCoords[4]; +}; + +struct dx_PixelConstants9 +{ + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; +}; + +class StateManager9 final : angle::NonCopyable +{ + public: + StateManager9(Renderer9 *renderer9); + ~StateManager9(); + + void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits); + + gl::Error setBlendDepthRasterStates(const gl::State &glState, unsigned int sampleMask); + void setScissorState(const gl::Rectangle &scissor, bool enabled); + void setViewportState(const gl::Caps *caps, + const gl::Rectangle &viewport, + float zNear, + float zFar, + GLenum drawMode, + GLenum frontFace, + bool ignoreViewport); + + void setShaderConstants(); + + void forceSetBlendState(); + void forceSetRasterState(); + void forceSetDepthStencilState(); + void forceSetScissorState(); + void forceSetViewportState(); + void forceSetDXUniformsState(); + + void updateDepthSizeIfChanged(bool depthStencilInitialized, unsigned int depthSize); + void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); + + void setRenderTargetBounds(size_t width, size_t height); + + int getRenderTargetWidth() const { return mRenderTargetBounds.width; } + int getRenderTargetHeight() const { return mRenderTargetBounds.height; } + + void resetDirtyBits() { mDirtyBits.reset(); } + + private: + // Blend state functions + void setBlendEnabled(bool enabled); + void setBlendColor(const gl::BlendState &blendState, const gl::ColorF &blendColor); + void setBlendFuncsEquations(const gl::BlendState &blendState); + void setColorMask(const gl::Framebuffer *framebuffer, + bool red, + bool blue, + bool green, + bool alpha); + void setSampleAlphaToCoverage(bool enabled); + void setDither(bool dither); + void setSampleMask(unsigned int sampleMask); + + // Current raster state functions + void setCullMode(bool cullFace, GLenum cullMode, GLenum frontFace); + void setDepthBias(bool polygonOffsetFill, + GLfloat polygonOffsetFactor, + GLfloat polygonOffsetUnits); + + // Depth stencil state functions + void setStencilOpsFront(GLenum stencilFail, + GLenum stencilPassDepthFail, + GLenum stencilPassDepthPass, + bool frontFaceCCW); + void setStencilOpsBack(GLenum stencilBackFail, + GLenum stencilBackPassDepthFail, + GLenum stencilBackPassDepthPass, + bool frontFaceCCW); + void setStencilBackWriteMask(GLuint stencilBackWriteMask, bool frontFaceCCW); + void setDepthFunc(bool depthTest, GLenum depthFunc); + void setStencilTestEnabled(bool enabled); + void setDepthMask(bool depthMask); + void setStencilFuncsFront(GLenum stencilFunc, + GLuint stencilMask, + GLint stencilRef, + bool frontFaceCCW, + unsigned int maxStencil); + void setStencilFuncsBack(GLenum stencilBackFunc, + GLuint stencilBackMask, + GLint stencilBackRef, + bool frontFaceCCW, + unsigned int maxStencil); + void setStencilWriteMask(GLuint stencilWriteMask, bool frontFaceCCW); + + void setScissorEnabled(bool scissorEnabled); + void setScissorRect(const gl::Rectangle &scissor, bool enabled); + + enum DirtyBitType + { + // Blend dirty bits + DIRTY_BIT_BLEND_ENABLED, + DIRTY_BIT_BLEND_COLOR, + DIRTY_BIT_BLEND_FUNCS_EQUATIONS, + DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE, + DIRTY_BIT_COLOR_MASK, + DIRTY_BIT_DITHER, + DIRTY_BIT_SAMPLE_MASK, + + // Rasterizer dirty bits + DIRTY_BIT_CULL_MODE, + DIRTY_BIT_DEPTH_BIAS, + + // Depth stencil dirty bits + DIRTY_BIT_STENCIL_DEPTH_MASK, + DIRTY_BIT_STENCIL_DEPTH_FUNC, + DIRTY_BIT_STENCIL_TEST_ENABLED, + DIRTY_BIT_STENCIL_FUNCS_FRONT, + DIRTY_BIT_STENCIL_FUNCS_BACK, + DIRTY_BIT_STENCIL_WRITEMASK_FRONT, + DIRTY_BIT_STENCIL_WRITEMASK_BACK, + DIRTY_BIT_STENCIL_OPS_FRONT, + DIRTY_BIT_STENCIL_OPS_BACK, + + // Scissor dirty bits + DIRTY_BIT_SCISSOR_ENABLED, + DIRTY_BIT_SCISSOR_RECT, + + // Viewport dirty bits + DIRTY_BIT_VIEWPORT, + + DIRTY_BIT_MAX + }; + + typedef std::bitset DirtyBits; + + // Currently applied blend state + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + unsigned int mCurSampleMask; + DirtyBits mBlendStateDirtyBits; + + // Currently applied raster state + gl::RasterizerState mCurRasterState; + unsigned int mCurDepthSize; + DirtyBits mRasterizerStateDirtyBits; + + // Currently applied depth stencil state + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + bool mCurFrontFaceCCW; + unsigned int mCurStencilSize; + DirtyBits mDepthStencilStateDirtyBits; + + // Currently applied scissor states + gl::Rectangle mCurScissorRect; + bool mCurScissorEnabled; + gl::Extents mRenderTargetBounds; + DirtyBits mScissorStateDirtyBits; + + // Currently applied viewport states + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + float mCurDepthFront; + bool mCurIgnoreViewport; + + dx_VertexConstants9 mVertexConstants; + dx_PixelConstants9 mPixelConstants; + bool mDxUniformsDirty; + + // FIXME: Unsupported by D3D9 + static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; + static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; + static const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; + + Renderer9 *mRenderer9; + DirtyBits mDirtyBits; +}; + +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D9_STATEMANAGER9_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp index 1620668166..be6a9c424c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp @@ -15,21 +15,26 @@ namespace rx { -SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), - SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), +SwapChain9::SwapChain9(Renderer9 *renderer, + NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation) + : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), + mRenderer(renderer), + mWidth(-1), + mHeight(-1), + mSwapInterval(-1), + mSwapChain(nullptr), + mBackBuffer(nullptr), + mRenderTarget(nullptr), + mDepthStencil(nullptr), + mOffscreenTexture(nullptr), mColorRenderTarget(this, false), mDepthStencilRenderTarget(this, true) { - mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; - mWidth = -1; - mHeight = -1; - mSwapInterval = -1; + ASSERT(orientation == 0); } SwapChain9::~SwapChain9() @@ -104,7 +109,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI pShareHandle = &mShareHandle; } - const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mBackBufferFormat); + const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat); result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); @@ -286,7 +291,7 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) device->SetStreamSourceFreq(streamIndex, 1); } - D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; + D3DVIEWPORT9 viewport = {0, 0, static_cast(mWidth), static_cast(mHeight), 0.0f, 1.0f}; device->SetViewport(&viewport); float x1 = x - 0.5f; @@ -312,8 +317,8 @@ EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) RECT rect = { - x, mHeight - y - height, - x + width, mHeight - y + static_cast(x), static_cast(mHeight - y - height), + static_cast(x + width), static_cast(mHeight - y) }; HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); @@ -384,10 +389,10 @@ IDirect3DTexture9 *SwapChain9::getOffscreenTexture() return mOffscreenTexture; } -SwapChain9 *SwapChain9::makeSwapChain9(SwapChainD3D *swapChain) +void *SwapChain9::getKeyedMutex() { - ASSERT(HAS_DYNAMIC_TYPE(SwapChain9*, swapChain)); - return static_cast(swapChain); + UNREACHABLE(); + return nullptr; } void SwapChain9::recreate() diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h index 81ac08ca7b..55a700c2d6 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h @@ -20,8 +20,12 @@ class Renderer9; class SwapChain9 : public SwapChainD3D { public: - SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat); + SwapChain9(Renderer9 *renderer, + NativeWindow nativeWindow, + HANDLE shareHandle, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation); virtual ~SwapChain9(); EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); @@ -39,14 +43,14 @@ class SwapChain9 : public SwapChainD3D EGLint getWidth() const { return mWidth; } EGLint getHeight() const { return mHeight; } - static SwapChain9 *makeSwapChain9(SwapChainD3D *swapChain); + void *getKeyedMutex() override; private: void release(); Renderer9 *mRenderer; - EGLint mHeight; EGLint mWidth; + EGLint mHeight; EGLint mSwapInterval; IDirect3DSwapChain9 *mSwapChain; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp index 139cb3eb08..b28d5076b5 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp @@ -9,14 +9,16 @@ // D3D9 texture. #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h" -#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" -#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" -#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" -#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" -#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" -#include "libANGLE/renderer/d3d/TextureD3D.h" + #include "libANGLE/formatutils.h" #include "libANGLE/Texture.h" +#include "libANGLE/renderer/d3d/EGLImageD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" +#include "libANGLE/renderer/d3d/d3d9/Renderer9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h" namespace rx { @@ -27,7 +29,7 @@ TextureStorage9::TextureStorage9(Renderer9 *renderer, DWORD usage) mTextureHeight(0), mInternalFormat(GL_NONE), mTextureFormat(D3DFMT_UNKNOWN), - mRenderer(Renderer9::makeRenderer9(renderer)), + mRenderer(renderer), mD3DUsage(usage), mD3DPool(mRenderer->getTexturePool(usage)) { @@ -37,12 +39,6 @@ TextureStorage9::~TextureStorage9() { } -TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage)); - return static_cast(storage); -} - DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget) { DWORD d3dusage = 0; @@ -72,6 +68,11 @@ bool TextureStorage9::isManaged() const return (mD3DPool == D3DPOOL_MANAGED); } +bool TextureStorage9::supportsNativeMipmapFunction() const +{ + return false; +} + D3DPOOL TextureStorage9::getPool() const { return mD3DPool; @@ -89,7 +90,7 @@ int TextureStorage9::getTopLevel() const int TextureStorage9::getLevelCount() const { - return mMipLevels - mTopLevel; + return static_cast(mMipLevels) - mTopLevel; } gl::Error TextureStorage9::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, @@ -106,7 +107,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchai mTexture = surfaceTexture; mMipLevels = surfaceTexture->GetLevelCount(); - mInternalFormat = swapchain->GetBackBufferInternalFormat(); + mInternalFormat = swapchain->GetRenderTargetInternalFormat(); D3DSURFACE_DESC surfaceDesc; surfaceTexture->GetLevelDesc(0, &surfaceDesc); @@ -114,16 +115,13 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, SwapChain9 *swapchai mTextureHeight = surfaceDesc.Height; mTextureFormat = surfaceDesc.Format; - mRenderTarget = NULL; - - initializeSerials(1, 1); + mRenderTargets.resize(mMipLevels, nullptr); } TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { mTexture = NULL; - mRenderTarget = NULL; mInternalFormat = internalformat; @@ -135,25 +133,28 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer9 *renderer, GLenum internalforma mTextureHeight = height; mMipLevels = mTopLevel + levels; - initializeSerials(getLevelCount(), 1); + mRenderTargets.resize(levels, nullptr); } TextureStorage9_2D::~TextureStorage9_2D() { SafeRelease(mTexture); - SafeDelete(mRenderTarget); -} - -TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage)); - return static_cast(storage); + for (auto &renderTarget : mRenderTargets) + { + SafeDelete(renderTarget); + } } // Increments refcount on surface. // caller must Release() the returned surface -gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface) +gl::Error TextureStorage9_2D::getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) { + ASSERT(target == GL_TEXTURE_2D); + UNUSED_ASSERTION_VARIABLE(target); + IDirect3DBaseTexture9 *baseTexture = NULL; gl::Error error = getBaseTexture(&baseTexture); if (error.isError()) @@ -180,36 +181,52 @@ gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSu return gl::Error(GL_NO_ERROR); } -gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTargetD3D **outRT) +gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) { - if (!mRenderTarget && isRenderTarget()) + ASSERT(index.mipIndex < getLevelCount()); + + if (!mRenderTargets[index.mipIndex] && isRenderTarget()) { + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) + { + return error; + } + IDirect3DSurface9 *surface = NULL; - gl::Error error = getSurfaceLevel(0, false, &surface); + error = getSurfaceLevel(GL_TEXTURE_2D, index.mipIndex, false, &surface); if (error.isError()) { return error; } - mRenderTarget = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); + size_t textureMipLevel = mTopLevel + index.mipIndex; + size_t mipWidth = std::max(mTextureWidth >> textureMipLevel, 1u); + size_t mipHeight = std::max(mTextureHeight >> textureMipLevel, 1u); + + baseTexture->AddRef(); + mRenderTargets[index.mipIndex] = new TextureRenderTarget9( + baseTexture, textureMipLevel, surface, mInternalFormat, static_cast(mipWidth), + static_cast(mipHeight), 1, 0); } ASSERT(outRT); - *outRT = mRenderTarget; + *outRT = mRenderTargets[index.mipIndex]; return gl::Error(GL_NO_ERROR); } gl::Error TextureStorage9_2D::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) { IDirect3DSurface9 *upper = NULL; - gl::Error error = getSurfaceLevel(sourceIndex.mipIndex, false, &upper); + gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, sourceIndex.mipIndex, false, &upper); if (error.isError()) { return error; } IDirect3DSurface9 *lower = NULL; - error = getSurfaceLevel(destIndex.mipIndex, true, &lower); + error = getSurfaceLevel(GL_TEXTURE_2D, destIndex.mipIndex, true, &lower); if (error.isError()) { SafeRelease(upper); @@ -234,8 +251,10 @@ gl::Error TextureStorage9_2D::getBaseTexture(IDirect3DBaseTexture9 **outTexture) ASSERT(mMipLevels > 0); IDirect3DDevice9 *device = mRenderer->getDevice(); - HRESULT result = device->CreateTexture(mTextureWidth, mTextureHeight, mMipLevels, getUsage(), mTextureFormat, - getPool(), &mTexture, NULL); + HRESULT result = device->CreateTexture(static_cast(mTextureWidth), + static_cast(mTextureHeight), + static_cast(mMipLevels), getUsage(), + mTextureFormat, getPool(), &mTexture, NULL); if (FAILED(result)) { @@ -252,20 +271,20 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) { ASSERT(destStorage); - TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(destStorage); + TextureStorage9_2D *dest9 = GetAs(destStorage); int levels = getLevelCount(); for (int i = 0; i < levels; ++i) { IDirect3DSurface9 *srcSurf = NULL; - gl::Error error = getSurfaceLevel(i, false, &srcSurf); + gl::Error error = getSurfaceLevel(GL_TEXTURE_2D, i, false, &srcSurf); if (error.isError()) { return error; } IDirect3DSurface9 *dstSurf = NULL; - error = dest9->getSurfaceLevel(i, true, &dstSurf); + error = dest9->getSurfaceLevel(GL_TEXTURE_2D, i, true, &dstSurf); if (error.isError()) { SafeRelease(srcSurf); @@ -286,6 +305,131 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage) return gl::Error(GL_NO_ERROR); } +TextureStorage9_EGLImage::TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image) + : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET), mImage(image) +{ + RenderTargetD3D *renderTargetD3D = nullptr; + mImage->getRenderTarget(&renderTargetD3D); + + RenderTarget9 *renderTarget9 = GetAs(renderTargetD3D); + + mInternalFormat = renderTarget9->getInternalFormat(); + mTextureFormat = renderTarget9->getD3DFormat(); + mTextureWidth = renderTarget9->getWidth(); + mTextureHeight = renderTarget9->getHeight(); + mTopLevel = static_cast(renderTarget9->getTextureLevel()); + mMipLevels = mTopLevel + 1; +} + +TextureStorage9_EGLImage::~TextureStorage9_EGLImage() +{ +} + +gl::Error TextureStorage9_EGLImage::getSurfaceLevel(GLenum target, + int level, + bool, + IDirect3DSurface9 **outSurface) +{ + ASSERT(target == GL_TEXTURE_2D); + ASSERT(level == 0); + UNUSED_ASSERTION_VARIABLE(target); + UNUSED_ASSERTION_VARIABLE(level); + + RenderTargetD3D *renderTargetD3D = nullptr; + gl::Error error = mImage->getRenderTarget(&renderTargetD3D); + if (error.isError()) + { + return error; + } + + RenderTarget9 *renderTarget9 = GetAs(renderTargetD3D); + + *outSurface = renderTarget9->getSurface(); + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_EGLImage::getRenderTarget(const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + ASSERT(index.mipIndex == 0); + UNUSED_ASSERTION_VARIABLE(index); + + return mImage->getRenderTarget(outRT); +} + +gl::Error TextureStorage9_EGLImage::getBaseTexture(IDirect3DBaseTexture9 **outTexture) +{ + RenderTargetD3D *renderTargetD3D = nullptr; + gl::Error error = mImage->getRenderTarget(&renderTargetD3D); + if (error.isError()) + { + return error; + } + + RenderTarget9 *renderTarget9 = GetAs(renderTargetD3D); + *outTexture = renderTarget9->getTexture(); + ASSERT(*outTexture != nullptr); + + return gl::Error(GL_NO_ERROR); +} + +gl::Error TextureStorage9_EGLImage::generateMipmap(const gl::ImageIndex &, const gl::ImageIndex &) +{ + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); +} + +gl::Error TextureStorage9_EGLImage::copyToStorage(TextureStorage *destStorage) +{ + ASSERT(destStorage); + ASSERT(getLevelCount() == 1); + + TextureStorage9 *dest9 = GetAs(destStorage); + + IDirect3DBaseTexture9 *destBaseTexture9 = nullptr; + gl::Error error = dest9->getBaseTexture(&destBaseTexture9); + if (error.isError()) + { + return error; + } + + IDirect3DTexture9 *destTexture9 = static_cast(destBaseTexture9); + + IDirect3DSurface9 *destSurface = nullptr; + HRESULT result = destTexture9->GetSurfaceLevel(destStorage->getTopLevel(), &destSurface); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, + "Failed to get the surface from a texture, result: 0x%X.", result); + } + + RenderTargetD3D *sourceRenderTarget = nullptr; + error = mImage->getRenderTarget(&sourceRenderTarget); + if (error.isError()) + { + SafeRelease(destSurface); + return error; + } + + RenderTarget9 *sourceRenderTarget9 = GetAs(sourceRenderTarget); + error = + mRenderer->copyToRenderTarget(destSurface, sourceRenderTarget9->getSurface(), isManaged()); + if (error.isError()) + { + SafeRelease(destSurface); + return error; + } + + if (destStorage->getTopLevel() != 0) + { + destTexture9->AddDirtyRect(nullptr); + } + + SafeRelease(destSurface); + return gl::Error(GL_NO_ERROR); +} + TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) { @@ -305,8 +449,6 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalf mTextureWidth = size; mTextureHeight = size; mMipLevels = mTopLevel + levels; - - initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT); } TextureStorage9_Cube::~TextureStorage9_Cube() @@ -319,15 +461,12 @@ TextureStorage9_Cube::~TextureStorage9_Cube() } } -TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage)); - return static_cast(storage); -} - // Increments refcount on surface. // caller must Release() the returned surface -gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface) +gl::Error TextureStorage9_Cube::getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) { IDirect3DBaseTexture9 *baseTexture = NULL; gl::Error error = getBaseTexture(&baseTexture); @@ -338,8 +477,8 @@ gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, IDirect3DCubeTexture9 *texture = static_cast(baseTexture); - D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); - HRESULT result = texture->GetCubeMapSurface(face, level + mTopLevel, outSurface); + D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(target); + HRESULT result = texture->GetCubeMapSurface(face, level, outSurface); ASSERT(SUCCEEDED(result)); if (FAILED(result)) @@ -364,14 +503,25 @@ gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, Ren if (mRenderTarget[index.layerIndex] == NULL && isRenderTarget()) { + IDirect3DBaseTexture9 *baseTexture = NULL; + gl::Error error = getBaseTexture(&baseTexture); + if (error.isError()) + { + return error; + } + IDirect3DSurface9 *surface = NULL; - gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, 0, false, &surface); + error = getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index.layerIndex, + mTopLevel + index.mipIndex, false, &surface); if (error.isError()) { return error; } - mRenderTarget[index.layerIndex] = new TextureRenderTarget9(surface, mInternalFormat, mTextureWidth, mTextureHeight, 1, 0); + baseTexture->AddRef(); + mRenderTarget[index.layerIndex] = new TextureRenderTarget9( + baseTexture, mTopLevel + index.mipIndex, surface, mInternalFormat, + static_cast(mTextureWidth), static_cast(mTextureHeight), 1, 0); } *outRT = mRenderTarget[index.layerIndex]; @@ -381,14 +531,14 @@ gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, Ren gl::Error TextureStorage9_Cube::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) { IDirect3DSurface9 *upper = NULL; - gl::Error error = getCubeMapSurface(sourceIndex.type, sourceIndex.mipIndex, false, &upper); + gl::Error error = getSurfaceLevel(sourceIndex.type, sourceIndex.mipIndex, false, &upper); if (error.isError()) { return error; } IDirect3DSurface9 *lower = NULL; - error = getCubeMapSurface(destIndex.type, destIndex.mipIndex, true, &lower); + error = getSurfaceLevel(destIndex.type, destIndex.mipIndex, true, &lower); if (error.isError()) { SafeRelease(upper); @@ -414,8 +564,9 @@ gl::Error TextureStorage9_Cube::getBaseTexture(IDirect3DBaseTexture9 **outTextur ASSERT(mTextureWidth == mTextureHeight); IDirect3DDevice9 *device = mRenderer->getDevice(); - HRESULT result = device->CreateCubeTexture(mTextureWidth, mMipLevels, getUsage(), mTextureFormat, getPool(), - &mTexture, NULL); + HRESULT result = device->CreateCubeTexture( + static_cast(mTextureWidth), static_cast(mMipLevels), + getUsage(), mTextureFormat, getPool(), &mTexture, NULL); if (FAILED(result)) { @@ -432,7 +583,7 @@ gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage) { ASSERT(destStorage); - TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(destStorage); + TextureStorage9_Cube *dest9 = GetAs(destStorage); int levels = getLevelCount(); for (int f = 0; f < CUBE_FACE_COUNT; f++) @@ -440,14 +591,15 @@ gl::Error TextureStorage9_Cube::copyToStorage(TextureStorage *destStorage) for (int i = 0; i < levels; i++) { IDirect3DSurface9 *srcSurf = NULL; - gl::Error error = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf); + gl::Error error = + getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false, &srcSurf); if (error.isError()) { return error; } IDirect3DSurface9 *dstSurf = NULL; - error = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf); + error = dest9->getSurfaceLevel(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true, &dstSurf); if (error.isError()) { SafeRelease(srcSurf); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h index 5cc06f07b1..50e63a6f14 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h @@ -16,6 +16,7 @@ namespace rx { +class EGLImageD3D; class Renderer9; class SwapChain9; class RenderTargetD3D; @@ -26,19 +27,22 @@ class TextureStorage9 : public TextureStorage public: virtual ~TextureStorage9(); - static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); - static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget); D3DPOOL getPool() const; DWORD getUsage() const; + virtual gl::Error getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) = 0; virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0; virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0; virtual int getTopLevel() const; virtual bool isRenderTarget() const; virtual bool isManaged() const; + bool supportsNativeMipmapFunction() const override; virtual int getLevelCount() const; virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, @@ -68,9 +72,10 @@ class TextureStorage9_2D : public TextureStorage9 TextureStorage9_2D(Renderer9 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); virtual ~TextureStorage9_2D(); - static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); - - gl::Error getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface); + gl::Error getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) override; virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); @@ -78,7 +83,27 @@ class TextureStorage9_2D : public TextureStorage9 private: IDirect3DTexture9 *mTexture; - RenderTarget9 *mRenderTarget; + std::vector mRenderTargets; +}; + +class TextureStorage9_EGLImage final : public TextureStorage9 +{ + public: + TextureStorage9_EGLImage(Renderer9 *renderer, EGLImageD3D *image); + ~TextureStorage9_EGLImage() override; + + gl::Error getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) override; + gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) override; + gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) override; + gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) override; + gl::Error copyToStorage(TextureStorage *destStorage) override; + + private: + EGLImageD3D *mImage; }; class TextureStorage9_Cube : public TextureStorage9 @@ -87,9 +112,10 @@ class TextureStorage9_Cube : public TextureStorage9 TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly); virtual ~TextureStorage9_Cube(); - static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); - - gl::Error getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface); + gl::Error getSurfaceLevel(GLenum target, + int level, + bool dirty, + IDirect3DSurface9 **outSurface) override; virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture); virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h index fb626bc0cf..992201737f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h @@ -19,21 +19,12 @@ class Renderer9; class VertexArray9 : public VertexArrayImpl { public: - VertexArray9(Renderer9 *renderer) - : VertexArrayImpl(), - mRenderer(renderer) + VertexArray9(const gl::VertexArray::Data &data) + : VertexArrayImpl(data) { } virtual ~VertexArray9() { } - - virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } - virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } - virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } - virtual void enableAttribute(size_t idx, bool enabledState) { } - - private: - Renderer9 *mRenderer; }; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp index cb5003997f..bfdf137126 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -56,24 +56,21 @@ gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) return gl::Error(GL_NO_ERROR); } -VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); - return static_cast(vertexBuffer); -} - -gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset) +gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) { if (!mVertexBuffer) { return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); } - gl::Buffer *buffer = attrib.buffer.get(); - - int inputStride = gl::ComputeVertexAttributeStride(attrib); - int elementSize = gl::ComputeVertexAttributeTypeSize(attrib); + int inputStride = static_cast(gl::ComputeVertexAttributeStride(attrib)); + int elementSize = static_cast(gl::ComputeVertexAttributeTypeSize(attrib)); DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; @@ -92,37 +89,15 @@ gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal vertex buffer, HRESULT: 0x%08x.", result); } - const uint8_t *input = NULL; - if (attrib.enabled) - { - if (buffer) - { - BufferD3D *storage = GetImplAs(buffer); - ASSERT(storage); - error = storage->getData(&input); - if (error.isError()) - { - return error; - } - input += static_cast(attrib.offset); - } - else - { - input = static_cast(attrib.pointer); - } - } - else - { - input = reinterpret_cast(currentValue.FloatValues); - } + const uint8_t *input = sourceData; if (instances == 0 || attrib.divisor == 0) { input += inputStride * start; } - gl::VertexFormat vertexFormat(attrib, currentValue.Type); - const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValueType); + const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatType); bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0; if (!needsConversion && inputStride == elementSize) @@ -196,15 +171,15 @@ IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, unsigned int *outSpaceRequired) const { - gl::VertexFormat vertexFormat(attrib, GL_FLOAT); - const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, GL_FLOAT); + const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormatType); if (attrib.enabled) { unsigned int elementCount = 0; if (instances == 0 || attrib.divisor == 0) { - elementCount = count; + elementCount = static_cast(count); } else { @@ -216,7 +191,8 @@ gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::s { if (outSpaceRequired) { - *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount; + *outSpaceRequired = + static_cast(d3d9VertexInfo.outputElementSize) * elementCount; } return gl::Error(GL_NO_ERROR); } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h index f5b110b22b..64271cbe2a 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h @@ -23,10 +23,13 @@ class VertexBuffer9 : public VertexBuffer virtual gl::Error initialize(unsigned int size, bool dynamicUsage); - static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); - - virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset); + gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + GLenum currentValueType, + GLint start, + GLsizei count, + GLsizei instances, + unsigned int offset, + const uint8_t *sourceData) override; virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp index f9eded9b50..a23ab4a290 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -7,10 +7,12 @@ // VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. #include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h" + +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" #include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h" #include "libANGLE/renderer/d3d/d3d9/formatutils9.h" -#include "libANGLE/Program.h" -#include "libANGLE/VertexAttribute.h" namespace rx { @@ -40,16 +42,23 @@ VertexDeclarationCache::~VertexDeclarationCache() } } -gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::Program *program, GLsizei instances, GLsizei *repeatDraw) +gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, + const std::vector &attributes, + gl::Program *program, + GLsizei instances, + GLsizei *repeatDraw) { + ASSERT(gl::MAX_VERTEX_ATTRIBS >= attributes.size()); + *repeatDraw = 1; - int indexedAttribute = gl::MAX_VERTEX_ATTRIBS; - int instancedAttribute = gl::MAX_VERTEX_ATTRIBS; + const size_t invalidAttribIndex = attributes.size(); + size_t indexedAttribute = invalidAttribIndex; + size_t instancedAttribute = invalidAttribIndex; if (instances == 0) { - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; ++i) + for (size_t i = 0; i < attributes.size(); ++i) { if (attributes[i].divisor != 0) { @@ -64,26 +73,26 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Tra if (instances > 0) { // Find an indexed attribute to be mapped to D3D stream 0 - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + for (size_t i = 0; i < attributes.size(); i++) { if (attributes[i].active) { - if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0) + if (indexedAttribute == invalidAttribIndex && attributes[i].divisor == 0) { indexedAttribute = i; } - else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0) + else if (instancedAttribute == invalidAttribIndex && attributes[i].divisor != 0) { instancedAttribute = i; } - if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS) + if (indexedAttribute != invalidAttribIndex && instancedAttribute != invalidAttribIndex) break; // Found both an indexed and instanced attribute } } // The validation layer checks that there is at least one active attribute with a zero divisor as per // the GL_ANGLE_instanced_arrays spec. - ASSERT(indexedAttribute != gl::MAX_VERTEX_ATTRIBS); + ASSERT(indexedAttribute != invalidAttribIndex); } D3DCAPS9 caps; @@ -92,19 +101,22 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Tra D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1]; D3DVERTEXELEMENT9 *element = &elements[0]; - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + ProgramD3D *programD3D = GetImplAs(program); + const auto &semanticIndexes = programD3D->getSemanticIndexes(); + + for (size_t i = 0; i < attributes.size(); i++) { if (attributes[i].active) { // Directly binding the storage buffer is not supported for d3d9 ASSERT(attributes[i].storage == NULL); - int stream = i; + int stream = static_cast(i); if (instances > 0) { // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. - if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS) + if (instancedAttribute == invalidAttribIndex) { *repeatDraw = instances; } @@ -116,7 +128,7 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Tra } else if (i == 0) { - stream = indexedAttribute; + stream = static_cast(indexedAttribute); } UINT frequency = 1; @@ -135,7 +147,7 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Tra } } - VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer); + VertexBuffer9 *vertexBuffer = GetAs(attributes[i].vertexBuffer); if (mAppliedVBs[stream].serial != attributes[i].serial || mAppliedVBs[stream].stride != attributes[i].stride || @@ -147,20 +159,20 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Tra mAppliedVBs[stream].offset = attributes[i].offset; } - gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT); - const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexFormat); + gl::VertexFormatType vertexformatType = gl::GetVertexFormatType(*attributes[i].attribute, GL_FLOAT); + const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(caps.DeclTypes, vertexformatType); - element->Stream = stream; + element->Stream = static_cast(stream); element->Offset = 0; - element->Type = d3d9VertexInfo.nativeFormat; + element->Type = static_cast(d3d9VertexInfo.nativeFormat); element->Method = D3DDECLMETHOD_DEFAULT; element->Usage = D3DDECLUSAGE_TEXCOORD; - element->UsageIndex = program->getSemanticIndex(i); + element->UsageIndex = static_cast(semanticIndexes[i]); element++; } } - if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS) + if (instances == 0 || instancedAttribute == invalidAttribIndex) { if (mInstancingEnabled) { diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h index fbd673097f..bad4de4d6b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h @@ -27,7 +27,11 @@ class VertexDeclarationCache VertexDeclarationCache(); ~VertexDeclarationCache(); - gl::Error applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::Program *program, GLsizei instances, GLsizei *repeatDraw); + gl::Error applyDeclaration(IDirect3DDevice9 *device, + const std::vector &attributes, + gl::Program *program, + GLsizei instances, + GLsizei *repeatDraw); void markStateDirty(); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp index 9bad5503d9..b672a60e3c 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp @@ -119,8 +119,8 @@ static D3D9FormatInfoMap BuildD3D9FormatInfoMap() InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, 0, 0, 0, 0, 8, 0, 0, GL_LUMINANCE8_EXT, GenerateMip, ReadColor ); InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, 0, 0, 0, 8, 0, 0, 0, GL_ALPHA8_EXT, GenerateMip, ReadColor ); InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, 0, 0, 0, 8, 8, 0, 0, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, 4, 4, 4, 4, 0, 0, 0, GL_BGRA4_ANGLEX, GenerateMip, ReadColor ); - InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, 5, 5, 5, 1, 0, 0, 0, GL_BGR5_A1_ANGLEX, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, 4, 4, 4, 4, 0, 0, 0, GL_BGRA4_ANGLEX, GenerateMip, ReadColor ); + InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, 5, 5, 5, 1, 0, 0, 0, GL_BGR5_A1_ANGLEX, GenerateMip, ReadColor ); InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, 5, 6, 5, 0, 0, 0, 0, GL_RGB565, GenerateMip, ReadColor ); InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, 8, 8, 8, 0, 0, 0, 0, GL_BGRA8_EXT, GenerateMip, ReadColor ); InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, 8, 8, 8, 8, 0, 0, 0, GL_BGRA8_EXT, GenerateMip, ReadColor ); @@ -475,16 +475,25 @@ template struct UseFallback { enum { type = T::fallback }; }; // and the D3DDECLTYPE member needed for the vertex declaration in declflag. template class PreferenceRule> struct Converter - : VertexDataConverter::type, - WidenRule >::type, size>, - ConversionRule >::type>, - DefaultVertexValues >::type>::type, normalized > > + : VertexDataConverter< + typename GLToCType::type, + WidenRule>::type, size>, + ConversionRule>::type>, + DefaultVertexValues>::type>::type, + normalized>> { private: - enum { d3dtype = PreferenceRule< VertexTypeMapping >::type }; - enum { d3dsize = WidenRule::finalWidth }; + enum + { + d3dtype = PreferenceRule>::type + }; + enum + { + d3dsize = WidenRule::finalWidth + }; public: enum { capflag = VertexTypeFlags::capflag }; @@ -555,12 +564,12 @@ static inline unsigned int ComputeTypeIndex(GLenum type) } } -const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat) +const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, gl::VertexFormatType vertexFormatType) { static bool initialized = false; - static DWORD intializedDeclTypes = 0; + static DWORD initializedDeclTypes = 0; static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - if (intializedDeclTypes != supportedDeclTypes) + if (initializedDeclTypes != supportedDeclTypes) { const TranslationDescription translations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] { @@ -589,12 +598,14 @@ const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::Vert } } initialized = true; - intializedDeclTypes = supportedDeclTypes; + initializedDeclTypes = supportedDeclTypes; } + const gl::VertexFormat &vertexFormat = gl::GetVertexFormatFromType(vertexFormatType); + // Pure integer attributes only supported in ES3.0 - ASSERT(!vertexFormat.mPureInteger); - return formatConverters[ComputeTypeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1]; + ASSERT(!vertexFormat.pureInteger); + return formatConverters[ComputeTypeIndex(vertexFormat.type)][vertexFormat.normalized][vertexFormat.components - 1]; } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h index 15e26599c8..c55010760d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h @@ -10,12 +10,12 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ #define LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_ -#include "libANGLE/renderer/d3d/formatutilsD3D.h" -#include "libANGLE/angletypes.h" +#include #include "common/platform.h" - -#include +#include "libANGLE/angletypes.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/formatutilsD3D.h" namespace rx { @@ -64,7 +64,7 @@ struct VertexFormat D3DDECLTYPE nativeFormat; GLenum componentType; }; -const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat); +const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, gl::VertexFormatType vertexFormatType); struct TextureFormat { diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp index c9711ac052..8622dc4d13 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp @@ -8,16 +8,17 @@ // specific to the D3D9 renderer. #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h" -#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" -#include "libANGLE/renderer/d3d/FramebufferD3D.h" -#include "libANGLE/renderer/Workarounds.h" -#include "libANGLE/formatutils.h" -#include "libANGLE/Framebuffer.h" -#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" #include "common/mathutil.h" #include "common/debug.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/renderer/d3d/d3d9/formatutils9.h" +#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/WorkaroundsD3D.h" + #include "third_party/systeminfo/SystemInfo.h" namespace rx @@ -208,7 +209,8 @@ D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) return d3dMagFilter; } -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, + float *d3dLodBias, float maxAnisotropy, size_t baseLevel) { switch (minFilter) { @@ -242,6 +244,20 @@ void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DT UNREACHABLE(); } + // Disabling mipmapping will always sample from level 0 of the texture. It is possible to work + // around this by modifying D3DSAMP_MAXMIPLEVEL to force a specific mip level to become the + // lowest sampled mip level and using a large negative value for D3DSAMP_MIPMAPLODBIAS to + // ensure that only the base mip level is sampled. + if (baseLevel > 0 && *d3dMipFilter == D3DTEXF_NONE) + { + *d3dMipFilter = D3DTEXF_POINT; + *d3dLodBias = -static_cast(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + } + else + { + *d3dLodBias = 0.0f; + } + if (maxAnisotropy > 1.0f) { *d3dMinFilter = D3DTEXF_ANISOTROPIC; @@ -258,6 +274,16 @@ D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples) namespace d3d9_gl { +unsigned int GetReservedVertexUniformVectors() +{ + return 3; // dx_ViewCoords, dx_ViewAdjust and dx_DepthRange. +} + +unsigned int GetReservedFragmentUniformVectors() +{ + return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. +} + GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type) { return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0; @@ -303,7 +329,7 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3 } textureCaps.sampleCounts.insert(1); - for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) + for (unsigned int i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++) { D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i); @@ -318,8 +344,14 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3 return textureCaps; } -void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, - gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +void GenerateCaps(IDirect3D9 *d3d9, + IDirect3DDevice9 *device, + D3DDEVTYPE deviceType, + UINT adapter, + gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, + gl::Extensions *extensions, + gl::Limitations *limitations) { D3DCAPS9 deviceCaps; if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps))) @@ -413,9 +445,9 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT // Vertex shader limits caps->maxVertexAttributes = 16; - const size_t reservedVertexUniformVectors = 2; // dx_ViewAdjust and dx_DepthRange. const size_t MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256; - caps->maxVertexUniformVectors = MAX_VERTEX_CONSTANT_VECTORS_D3D9 - reservedVertexUniformVectors; + caps->maxVertexUniformVectors = + MAX_VERTEX_CONSTANT_VECTORS_D3D9 - GetReservedVertexUniformVectors(); caps->maxVertexUniformComponents = caps->maxVertexUniformVectors * 4; caps->maxVertexUniformBlocks = 0; @@ -441,12 +473,12 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT } // Fragment shader limits - const size_t reservedPixelUniformVectors = 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. - const size_t MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224; const size_t MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32; - caps->maxFragmentUniformVectors = ((deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 - : MAX_PIXEL_CONSTANT_VECTORS_SM2) - reservedPixelUniformVectors; + caps->maxFragmentUniformVectors = + ((deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 + : MAX_PIXEL_CONSTANT_VECTORS_SM2) - + GetReservedFragmentUniformVectors(); caps->maxFragmentUniformComponents = caps->maxFragmentUniformVectors * 4; caps->maxFragmentUniformBlocks = 0; caps->maxFragmentInputComponents = caps->maxVertexOutputComponents; @@ -472,10 +504,12 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT caps->maxTransformFeedbackSeparateAttributes = 0; caps->maxTransformFeedbackSeparateComponents = 0; + // Multisample limits + caps->maxSamples = maxSamples; + // GL extension support extensions->setTextureExtensionSupport(*textureCapsMap); extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16); - extensions->packedDepthStencil = true; extensions->getProgramBinary = true; extensions->rgb8rgba8 = true; extensions->readFormatBGRA = true; @@ -486,7 +520,7 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT // textureRG is emulated and not performant. extensions->textureRG = false; - D3DADAPTER_IDENTIFIER9 adapterId = { 0 }; + D3DADAPTER_IDENTIFIER9 adapterId = {}; if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId))) { // ATI cards on XP have problems with non-power-of-two textures. @@ -524,11 +558,11 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT SafeRelease(eventQuery); extensions->timerQuery = false; // Unimplemented + extensions->disjointTimerQuery = false; extensions->robustness = true; extensions->blendMinMax = true; extensions->framebufferBlit = true; extensions->framebufferMultisample = true; - extensions->maxSamples = maxSamples; extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); extensions->packReverseRowOrder = true; extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; @@ -536,7 +570,27 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT extensions->fragDepth = true; extensions->textureUsage = true; extensions->translatedShaderSource = true; + extensions->fboRenderMipmap = false; + extensions->discardFramebuffer = false; // It would be valid to set this to true, since glDiscardFramebufferEXT is just a hint extensions->colorBufferFloat = false; + extensions->debugMarker = true; + extensions->eglImage = true; + extensions->unpackSubimage = true; + extensions->packSubimage = true; + extensions->vertexArrayObject = true; + extensions->noError = true; + + // D3D9 has no concept of separate masks and refs for front and back faces in the depth stencil + // state. + limitations->noSeparateStencilRefsAndMasks = true; + + // D3D9 shader models have limited support for looping, so the Appendix A + // index/loop limitations are necessary. Workarounds that are needed to + // support dynamic indexing of vectors on HLSL also don't work on D3D9. + limitations->shadersRequireIndexedLoopValidation = true; + + // D3D9 cannot support constant color and alpha blend funcs together + limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true; } } @@ -571,21 +625,9 @@ void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsize *levelOffset = upsampleCount; } -gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget9 **outRT) -{ - RenderTargetD3D *renderTarget = NULL; - gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget); - if (error.isError()) - { - return error; - } - *outRT = RenderTarget9::makeRenderTarget9(renderTarget); - return gl::Error(GL_NO_ERROR); -} - -Workarounds GenerateWorkarounds() +WorkaroundsD3D GenerateWorkarounds() { - Workarounds workarounds; + WorkaroundsD3D workarounds; workarounds.mrtPerfWorkaround = true; workarounds.setDataFasterThanImageUpload = false; workarounds.useInstancedPointSpriteEmulation = false; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h index 3c6a57aee3..aa494adb62 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h @@ -22,7 +22,7 @@ class FramebufferAttachment; namespace rx { class RenderTarget9; -struct Workarounds; +struct WorkaroundsD3D; namespace gl_d3d9 { @@ -37,7 +37,8 @@ D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy); +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, + float *d3dLodBias, float maxAnisotropy, size_t baseLevel); D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples); @@ -46,13 +47,22 @@ D3DMULTISAMPLE_TYPE GetMultisampleType(GLuint samples); namespace d3d9_gl { +unsigned int GetReservedVertexUniformVectors(); + +unsigned int GetReservedFragmentUniformVectors(); + GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type); bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); -void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, - gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); - +void GenerateCaps(IDirect3D9 *d3d9, + IDirect3DDevice9 *device, + D3DDEVTYPE deviceType, + UINT adapter, + gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, + gl::Extensions *extensions, + gl::Limitations *limitations); } namespace d3d9 @@ -76,9 +86,7 @@ inline bool isDeviceLostError(HRESULT errorCode) } } -gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget9 **outRT); -Workarounds GenerateWorkarounds(); - +WorkaroundsD3D GenerateWorkarounds(); } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h index 32eb376a78..aa05934bc8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h @@ -149,7 +149,10 @@ struct NormalizedDefaultValues // static const std::size_t finalSize: number of bytes per output vertex // static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided. -template > +template > struct VertexDataConverter { typedef typename Converter::OutputType OutputType; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp index 8a4d41cbd9..e1c955eb06 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp @@ -106,8 +106,8 @@ static FormatWriteFunctionMap BuildFormatWriteFunctionMap() InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, WriteColor ); InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, WriteColor ); - InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor ); - InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor ); + InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor ); InsertFormatWriteFunctionMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, WriteColor ); InsertFormatWriteFunctionMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, WriteColor ); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h index e0f9a16c1a..76f1830e64 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h @@ -285,6 +285,8 @@ struct B8G8R8 struct R5G6B5 { + // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the most significant + // bits of the bitfield, and successive component occupying progressively less significant locations" unsigned short RGB; static void readColor(gl::ColorF *dst, const R5G6B5 *src) @@ -491,157 +493,123 @@ struct B8G8R8X8 } }; -struct B5G5R5A1 +struct A1R5G5B5 { - unsigned short BGRA; + unsigned short ARGB; - static void readColor(gl::ColorF *dst, const B5G5R5A1 *src) + static void readColor(gl::ColorF *dst, const A1R5G5B5 *src) { - dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->BGRA)); - dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->BGRA)); - dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->BGRA)); - dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGRA)); + dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->ARGB)); + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->ARGB)); + dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->ARGB)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->ARGB)); } - static void writeColor(B5G5R5A1 *dst, const gl::ColorF *src) + static void writeColor(A1R5G5B5 *dst, const gl::ColorF *src) { - dst->BGRA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | + dst->ARGB = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->red)) | gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); } - static void average(B5G5R5A1 *dst, const B5G5R5A1 *src1, const B5G5R5A1 *src2) + static void average(A1R5G5B5 *dst, const A1R5G5B5 *src1, const A1R5G5B5 *src2) { - dst->BGRA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->BGRA), gl::getShiftedData<1, 15>(src2->BGRA))) | - gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->BGRA), gl::getShiftedData<5, 10>(src2->BGRA))) | - gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->BGRA), gl::getShiftedData<5, 5>(src2->BGRA))) | - gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->BGRA), gl::getShiftedData<5, 0>(src2->BGRA))); + dst->ARGB = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->ARGB), gl::getShiftedData<1, 15>(src2->ARGB))) | + gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->ARGB), gl::getShiftedData<5, 10>(src2->ARGB))) | + gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->ARGB), gl::getShiftedData<5, 5>(src2->ARGB))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->ARGB), gl::getShiftedData<5, 0>(src2->ARGB))); } }; struct R5G5B5A1 { + // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the most significant + // bits of the bitfield, and successive component occupying progressively less significant locations" unsigned short RGBA; static void readColor(gl::ColorF *dst, const R5G5B5A1 *src) { - dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->RGBA)); - dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->RGBA)); - dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->RGBA)); - dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGBA)); + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGBA)); + dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 6>(src->RGBA)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 1>(src->RGBA)); + dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 0>(src->RGBA)); } static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src) { - dst->RGBA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | - gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->blue)) | - gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | - gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->red)); + dst->RGBA = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) | + gl::shiftData<5, 6>(gl::floatToNormalized<5, unsigned short>(src->green)) | + gl::shiftData<5, 1>(gl::floatToNormalized<5, unsigned short>(src->blue)) | + gl::shiftData<1, 0>(gl::floatToNormalized<1, unsigned short>(src->alpha)); } static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2) { - dst->RGBA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->RGBA), gl::getShiftedData<1, 15>(src2->RGBA))) | - gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->RGBA), gl::getShiftedData<5, 10>(src2->RGBA))) | - gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->RGBA), gl::getShiftedData<5, 5>(src2->RGBA))) | - gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGBA), gl::getShiftedData<5, 0>(src2->RGBA))); + dst->RGBA = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGBA), gl::getShiftedData<5, 11>(src2->RGBA))) | + gl::shiftData<5, 6>(gl::average(gl::getShiftedData<5, 6>(src1->RGBA), gl::getShiftedData<5, 6>(src2->RGBA))) | + gl::shiftData<5, 1>(gl::average(gl::getShiftedData<5, 1>(src1->RGBA), gl::getShiftedData<5, 1>(src2->RGBA))) | + gl::shiftData<1, 0>(gl::average(gl::getShiftedData<1, 0>(src1->RGBA), gl::getShiftedData<1, 0>(src2->RGBA))); } }; struct R4G4B4A4 { - unsigned char R : 4; - unsigned char G : 4; - unsigned char B : 4; - unsigned char A : 4; + // OpenGL ES 2.0.25 spec Section 3.6.2: "Components are packed with the first component in the most significant + // bits of the bitfield, and successive component occupying progressively less significant locations" + unsigned short RGBA; static void readColor(gl::ColorF *dst, const R4G4B4A4 *src) { - dst->red = gl::normalizedToFloat<4>(src->R); - dst->green = gl::normalizedToFloat<4>(src->G); - dst->blue = gl::normalizedToFloat<4>(src->B); - dst->alpha = gl::normalizedToFloat<4>(src->A); + dst->red = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->RGBA)); + dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->RGBA)); + dst->blue = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->RGBA)); + dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->RGBA)); } static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src) { - dst->R = gl::floatToNormalized<4, unsigned char>(src->red); - dst->G = gl::floatToNormalized<4, unsigned char>(src->green); - dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); - dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + dst->RGBA = gl::shiftData<4, 12>(gl::floatToNormalized<4, unsigned short>(src->red)) | + gl::shiftData<4, 8>(gl::floatToNormalized<4, unsigned short>(src->green)) | + gl::shiftData<4, 4>(gl::floatToNormalized<4, unsigned short>(src->blue)) | + gl::shiftData<4, 0>(gl::floatToNormalized<4, unsigned short>(src->alpha)); } static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2) { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); + dst->RGBA = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->RGBA), gl::getShiftedData<4, 12>(src2->RGBA))) | + gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->RGBA), gl::getShiftedData<4, 8>(src2->RGBA))) | + gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->RGBA), gl::getShiftedData<4, 4>(src2->RGBA))) | + gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->RGBA), gl::getShiftedData<4, 0>(src2->RGBA))); } }; struct A4R4G4B4 { - unsigned char A : 4; - unsigned char R : 4; - unsigned char G : 4; - unsigned char B : 4; + unsigned short ARGB; static void readColor(gl::ColorF *dst, const A4R4G4B4 *src) { - dst->red = gl::normalizedToFloat<4>(src->R); - dst->green = gl::normalizedToFloat<4>(src->G); - dst->blue = gl::normalizedToFloat<4>(src->B); - dst->alpha = gl::normalizedToFloat<4>(src->A); + dst->alpha = gl::normalizedToFloat<4>(gl::getShiftedData<4, 12>(src->ARGB)); + dst->red = gl::normalizedToFloat<4>(gl::getShiftedData<4, 8>(src->ARGB)); + dst->green = gl::normalizedToFloat<4>(gl::getShiftedData<4, 4>(src->ARGB)); + dst->blue = gl::normalizedToFloat<4>(gl::getShiftedData<4, 0>(src->ARGB)); } static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src) { - dst->R = gl::floatToNormalized<4, unsigned char>(src->red); - dst->G = gl::floatToNormalized<4, unsigned char>(src->green); - dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); - dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + dst->ARGB = gl::shiftData<4, 12>(gl::floatToNormalized<4, unsigned short>(src->alpha)) | + gl::shiftData<4, 8>(gl::floatToNormalized<4, unsigned short>(src->red)) | + gl::shiftData<4, 4>(gl::floatToNormalized<4, unsigned short>(src->green)) | + gl::shiftData<4, 0>(gl::floatToNormalized<4, unsigned short>(src->blue)); } static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2) { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); - } -}; - -struct B4G4R4A4 -{ - unsigned char B : 4; - unsigned char G : 4; - unsigned char R : 4; - unsigned char A : 4; - - static void readColor(gl::ColorF *dst, const B4G4R4A4 *src) - { - dst->red = gl::normalizedToFloat<4>(src->R); - dst->green = gl::normalizedToFloat<4>(src->G); - dst->blue = gl::normalizedToFloat<4>(src->B); - dst->alpha = gl::normalizedToFloat<4>(src->A); - } - - static void writeColor(B4G4R4A4 *dst, const gl::ColorF *src) - { - dst->R = gl::floatToNormalized<4, unsigned char>(src->red); - dst->G = gl::floatToNormalized<4, unsigned char>(src->green); - dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); - dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); - } - - static void average(B4G4R4A4 *dst, const B4G4R4A4 *src1, const B4G4R4A4 *src2) - { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); + dst->ARGB = gl::shiftData<4, 12>(gl::average(gl::getShiftedData<4, 12>(src1->ARGB), gl::getShiftedData<4, 12>(src2->ARGB))) | + gl::shiftData<4, 8>(gl::average(gl::getShiftedData<4, 8>(src1->ARGB), gl::getShiftedData<4, 8>(src2->ARGB))) | + gl::shiftData<4, 4>(gl::average(gl::getShiftedData<4, 4>(src1->ARGB), gl::getShiftedData<4, 4>(src2->ARGB))) | + gl::shiftData<4, 0>(gl::average(gl::getShiftedData<4, 0>(src1->ARGB), gl::getShiftedData<4, 0>(src2->ARGB))); } }; @@ -1013,7 +981,7 @@ struct R8S static void average(R8S *dst, const R8S *src1, const R8S *src2) { - dst->R = gl::average(src1->R, src2->R); + dst->R = static_cast(gl::average(src1->R, src2->R)); } }; @@ -1052,8 +1020,8 @@ struct R8G8S static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2) { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); + dst->R = static_cast(gl::average(src1->R, src2->R)); + dst->G = static_cast(gl::average(src1->G, src2->G)); } }; @@ -1095,9 +1063,9 @@ struct R8G8B8S static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2) { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); + dst->R = static_cast(gl::average(src1->R, src2->R)); + dst->G = static_cast(gl::average(src1->G, src2->G)); + dst->B = static_cast(gl::average(src1->B, src2->B)); } }; @@ -1142,10 +1110,10 @@ struct R8G8B8A8S static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2) { - dst->R = gl::average(src1->R, src2->R); - dst->G = gl::average(src1->G, src2->G); - dst->B = gl::average(src1->B, src2->B); - dst->A = gl::average(src1->A, src2->A); + dst->R = static_cast(gl::average(src1->R, src2->R)); + dst->G = static_cast(gl::average(src1->G, src2->G)); + dst->B = static_cast(gl::average(src1->B, src2->B)); + dst->A = static_cast(gl::average(src1->A, src2->A)); } }; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp index 172832b3e7..b9b9e5e4ab 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp @@ -298,9 +298,9 @@ void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint16_t rgb = source[x]; - dest[4 * x + 0] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); - dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); + dest[4 * x + 0] = static_cast(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2)); + dest[4 * x + 1] = static_cast(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9)); + dest[4 * x + 2] = static_cast(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13)); dest[4 * x + 3] = 0xFF; } } @@ -320,9 +320,9 @@ void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint16_t rgb = source[x]; - dest[4 * x + 0] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); - dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); + dest[4 * x + 0] = static_cast(((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13)); + dest[4 * x + 1] = static_cast(((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9)); + dest[4 * x + 2] = static_cast(((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2)); dest[4 * x + 3] = 0xFF; } } @@ -348,6 +348,24 @@ void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, } } +void LoadRGBA4ToARGB4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = ANGLE_ROTR16(source[x], 4); + } + } + } +} + void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) @@ -361,10 +379,10 @@ void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint16_t rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); - dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); - dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); - dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + dest[4 * x + 0] = static_cast(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4)); + dest[4 * x + 1] = static_cast(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8)); + dest[4 * x + 2] = static_cast(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12)); + dest[4 * x + 3] = static_cast(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0)); } } } @@ -383,10 +401,10 @@ void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint16_t rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); - dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); - dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); - dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + dest[4 * x + 0] = static_cast(((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12)); + dest[4 * x + 1] = static_cast(((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8)); + dest[4 * x + 2] = static_cast(((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4)); + dest[4 * x + 3] = static_cast(((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0)); } } } @@ -405,10 +423,28 @@ void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint16_t bgra = source[x]; - dest[4 * x + 0] = ((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12); - dest[4 * x + 1] = ((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8); - dest[4 * x + 2] = ((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4); - dest[4 * x + 3] = ((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0); + dest[4 * x + 0] = static_cast(((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12)); + dest[4 * x + 1] = static_cast(((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8)); + dest[4 * x + 2] = static_cast(((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4)); + dest[4 * x + 3] = static_cast(((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0)); + } + } + } +} + +void LoadRGB5A1ToA1RGB5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = ANGLE_ROTR16(source[x], 1); } } } @@ -427,10 +463,10 @@ void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint16_t rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); - dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); - dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + dest[4 * x + 0] = static_cast(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3)); + dest[4 * x + 1] = static_cast(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8)); + dest[4 * x + 2] = static_cast(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13)); + dest[4 * x + 3] = static_cast((rgba & 0x0001) ? 0xFF : 0); } } } @@ -449,16 +485,15 @@ void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint16_t rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); - dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); - dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + dest[4 * x + 0] = static_cast(((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13)); + dest[4 * x + 1] = static_cast(((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8)); + dest[4 * x + 2] = static_cast(((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3)); + dest[4 * x + 3] = static_cast((rgba & 0x0001) ? 0xFF : 0); } } } } - void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) @@ -472,10 +507,10 @@ void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint16_t bgra = source[x]; - dest[4 * x + 0] = ((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13); - dest[4 * x + 1] = ((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8); - dest[4 * x + 2] = ((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3); - dest[4 * x + 3] = (bgra & 0x0001) ? 0xFF : 0; + dest[4 * x + 0] = static_cast(((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13)); + dest[4 * x + 1] = static_cast(((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8)); + dest[4 * x + 2] = static_cast(((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3)); + dest[4 * x + 3] = static_cast((bgra & 0x0001) ? 0xFF : 0); } } } @@ -494,10 +529,10 @@ void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, for (size_t x = 0; x < width; x++) { uint32_t rgba = source[x]; - dest[4 * x + 0] = (rgba & 0x000003FF) >> 2; - dest[4 * x + 1] = (rgba & 0x000FFC00) >> 12; - dest[4 * x + 2] = (rgba & 0x3FF00000) >> 22; - dest[4 * x + 3] = ((rgba & 0xC0000000) >> 30) * 0x55; + dest[4 * x + 0] = static_cast((rgba & 0x000003FF) >> 2); + dest[4 * x + 1] = static_cast((rgba & 0x000FFC00) >> 12); + dest[4 * x + 2] = static_cast((rgba & 0x3FF00000) >> 22); + dest[4 * x + 3] = static_cast(((rgba & 0xC0000000) >> 30) * 0x55); } } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h index 6967dc868e..6c5118365e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h @@ -96,6 +96,10 @@ void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); +void LoadRGBA4ToARGB4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); @@ -108,6 +112,10 @@ void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); +void LoadRGB5A1ToA1RGB5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp new file mode 100644 index 0000000000..26a3b32ce0 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.cpp @@ -0,0 +1,1435 @@ +// +// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// loadimage_etc.cpp: Decodes ETC and EAC encoded textures. + +#include "libANGLE/renderer/d3d/loadimage_etc.h" + +#include "libANGLE/renderer/d3d/loadimage.h" +#include "libANGLE/renderer/d3d/imageformats.h" + +namespace rx +{ +namespace +{ +// Table 3.17.2 sorted according to table 3.17.3 +// clang-format off +static const int intensityModifierDefault[][4] = +{ + { 2, 8, -2, -8 }, + { 5, 17, -5, -17 }, + { 9, 29, -9, -29 }, + { 13, 42, -13, -42 }, + { 18, 60, -18, -60 }, + { 24, 80, -24, -80 }, + { 33, 106, -33, -106 }, + { 47, 183, -47, -183 }, +}; +// clang-format on + +// Table C.12, intensity modifier for non opaque punchthrough alpha +// clang-format off +static const int intensityModifierNonOpaque[][4] = +{ + { 0, 8, 0, -8 }, + { 0, 17, 0, -17 }, + { 0, 29, 0, -29 }, + { 0, 42, 0, -42 }, + { 0, 60, 0, -60 }, + { 0, 80, 0, -80 }, + { 0, 106, 0, -106 }, + { 0, 183, 0, -183 }, +}; +// clang-format on + +// Table C.7, mapping from pixel index values to modifier value orders +// clang-format off +static const int valueMappingTable[] = +{ + 2, 3, 1, 0 +}; +// clang-format on + +struct ETC2Block +{ + // Decodes unsigned single or dual channel block to bytes + void decodeAsSingleChannel(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + size_t destPixelStride, + size_t destRowPitch, + bool isSigned) const + { + for (size_t j = 0; j < 4 && (y + j) < h; j++) + { + uint8_t *row = dest + (j * destRowPitch); + for (size_t i = 0; i < 4 && (x + i) < w; i++) + { + uint8_t *pixel = row + (i * destPixelStride); + if (isSigned) + { + *pixel = clampSByte(getSingleChannel(i, j, isSigned)); + } + else + { + *pixel = clampByte(getSingleChannel(i, j, isSigned)); + } + } + } + } + + // Decodes RGB block to rgba8 + void decodeAsRGB(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + size_t destRowPitch, + const uint8_t alphaValues[4][4], + bool punchThroughAlpha) const + { + bool opaqueBit = u.idht.mode.idm.diffbit; + bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit; + // Select mode + if (u.idht.mode.idm.diffbit || punchThroughAlpha) + { + const auto &block = u.idht.mode.idm.colors.diff; + int r = (block.R + block.dR); + int g = (block.G + block.dG); + int b = (block.B + block.dB); + if (r < 0 || r > 31) + { + decodeTBlock(dest, x, y, w, h, destRowPitch, alphaValues, + nonOpaquePunchThroughAlpha); + } + else if (g < 0 || g > 31) + { + decodeHBlock(dest, x, y, w, h, destRowPitch, alphaValues, + nonOpaquePunchThroughAlpha); + } + else if (b < 0 || b > 31) + { + decodePlanarBlock(dest, x, y, w, h, destRowPitch, alphaValues); + } + else + { + decodeDifferentialBlock(dest, x, y, w, h, destRowPitch, alphaValues, + nonOpaquePunchThroughAlpha); + } + } + else + { + decodeIndividualBlock(dest, x, y, w, h, destRowPitch, alphaValues, + nonOpaquePunchThroughAlpha); + } + } + + // Transcodes RGB block to BC1 + void transcodeAsBC1(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + const uint8_t alphaValues[4][4], + bool punchThroughAlpha) const + { + bool opaqueBit = u.idht.mode.idm.diffbit; + bool nonOpaquePunchThroughAlpha = punchThroughAlpha && !opaqueBit; + // Select mode + if (u.idht.mode.idm.diffbit || punchThroughAlpha) + { + const auto &block = u.idht.mode.idm.colors.diff; + int r = (block.R + block.dR); + int g = (block.G + block.dG); + int b = (block.B + block.dB); + if (r < 0 || r > 31) + { + transcodeTBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha); + } + else if (g < 0 || g > 31) + { + transcodeHBlockToBC1(dest, x, y, w, h, alphaValues, nonOpaquePunchThroughAlpha); + } + else if (b < 0 || b > 31) + { + transcodePlanarBlockToBC1(dest, x, y, w, h, alphaValues); + } + else + { + transcodeDifferentialBlockToBC1(dest, x, y, w, h, alphaValues, + nonOpaquePunchThroughAlpha); + } + } + else + { + transcodeIndividualBlockToBC1(dest, x, y, w, h, alphaValues, + nonOpaquePunchThroughAlpha); + } + } + + private: + union + { + // Individual, differential, H and T modes + struct + { + union + { + // Individual and differential modes + struct + { + union + { + struct // Individual colors + { + unsigned char R2 : 4; + unsigned char R1 : 4; + unsigned char G2 : 4; + unsigned char G1 : 4; + unsigned char B2 : 4; + unsigned char B1 : 4; + } indiv; + struct // Differential colors + { + signed char dR : 3; + unsigned char R : 5; + signed char dG : 3; + unsigned char G : 5; + signed char dB : 3; + unsigned char B : 5; + } diff; + } colors; + bool flipbit : 1; + bool diffbit : 1; + unsigned char cw2 : 3; + unsigned char cw1 : 3; + } idm; + // T mode + struct + { + // Byte 1 + unsigned char TR1b : 2; + unsigned char TdummyB : 1; + unsigned char TR1a : 2; + unsigned char TdummyA : 3; + // Byte 2 + unsigned char TB1 : 4; + unsigned char TG1 : 4; + // Byte 3 + unsigned char TG2 : 4; + unsigned char TR2 : 4; + // Byte 4 + unsigned char Tdb : 1; + bool Tflipbit : 1; + unsigned char Tda : 2; + unsigned char TB2 : 4; + } tm; + // H mode + struct + { + // Byte 1 + unsigned char HG1a : 3; + unsigned char HR1 : 4; + unsigned char HdummyA : 1; + // Byte 2 + unsigned char HB1b : 2; + unsigned char HdummyC : 1; + unsigned char HB1a : 1; + unsigned char HG1b : 1; + unsigned char HdummyB : 3; + // Byte 3 + unsigned char HG2a : 3; + unsigned char HR2 : 4; + unsigned char HB1c : 1; + // Byte 4 + unsigned char Hdb : 1; + bool Hflipbit : 1; + unsigned char Hda : 1; + unsigned char HB2 : 4; + unsigned char HG2b : 1; + } hm; + } mode; + unsigned char pixelIndexMSB[2]; + unsigned char pixelIndexLSB[2]; + } idht; + // planar mode + struct + { + // Byte 1 + unsigned char GO1 : 1; + unsigned char RO : 6; + unsigned char PdummyA : 1; + // Byte 2 + unsigned char BO1 : 1; + unsigned char GO2 : 6; + unsigned char PdummyB : 1; + // Byte 3 + unsigned char BO3a : 2; + unsigned char PdummyD : 1; + unsigned char BO2 : 2; + unsigned char PdummyC : 3; + // Byte 4 + unsigned char RH2 : 1; + bool Pflipbit : 1; + unsigned char RH1 : 5; + unsigned char BO3b : 1; + // Byte 5 + unsigned char BHa : 1; + unsigned char GH : 7; + // Byte 6 + unsigned char RVa : 3; + unsigned char BHb : 5; + // Byte 7 + unsigned char GVa : 5; + unsigned char RVb : 3; + // Byte 8 + unsigned char BV : 6; + unsigned char GVb : 2; + } pblk; + // Single channel block + struct + { + union + { + unsigned char us; + signed char s; + } base_codeword; + unsigned char table_index : 4; + unsigned char multiplier : 4; + unsigned char mc1 : 2; + unsigned char mb : 3; + unsigned char ma : 3; + unsigned char mf1 : 1; + unsigned char me : 3; + unsigned char md : 3; + unsigned char mc2 : 1; + unsigned char mh : 3; + unsigned char mg : 3; + unsigned char mf2 : 2; + unsigned char mk1 : 2; + unsigned char mj : 3; + unsigned char mi : 3; + unsigned char mn1 : 1; + unsigned char mm : 3; + unsigned char ml : 3; + unsigned char mk2 : 1; + unsigned char mp : 3; + unsigned char mo : 3; + unsigned char mn2 : 2; + } scblk; + } u; + + static unsigned char clampByte(int value) + { + return static_cast(gl::clamp(value, 0, 255)); + } + + static signed char clampSByte(int value) + { + return static_cast(gl::clamp(value, -128, 127)); + } + + static R8G8B8A8 createRGBA(int red, int green, int blue, int alpha) + { + R8G8B8A8 rgba; + rgba.R = clampByte(red); + rgba.G = clampByte(green); + rgba.B = clampByte(blue); + rgba.A = clampByte(alpha); + return rgba; + } + + static R8G8B8A8 createRGBA(int red, int green, int blue) + { + return createRGBA(red, green, blue, 255); + } + + static int extend_4to8bits(int x) { return (x << 4) | x; } + static int extend_5to8bits(int x) { return (x << 3) | (x >> 2); } + static int extend_6to8bits(int x) { return (x << 2) | (x >> 4); } + static int extend_7to8bits(int x) { return (x << 1) | (x >> 6); } + + void decodeIndividualBlock(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + size_t destRowPitch, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + const auto &block = u.idht.mode.idm.colors.indiv; + int r1 = extend_4to8bits(block.R1); + int g1 = extend_4to8bits(block.G1); + int b1 = extend_4to8bits(block.B1); + int r2 = extend_4to8bits(block.R2); + int g2 = extend_4to8bits(block.G2); + int b2 = extend_4to8bits(block.B2); + decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2, + alphaValues, nonOpaquePunchThroughAlpha); + } + + void decodeDifferentialBlock(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + size_t destRowPitch, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + const auto &block = u.idht.mode.idm.colors.diff; + int b1 = extend_5to8bits(block.B); + int g1 = extend_5to8bits(block.G); + int r1 = extend_5to8bits(block.R); + int r2 = extend_5to8bits(block.R + block.dR); + int g2 = extend_5to8bits(block.G + block.dG); + int b2 = extend_5to8bits(block.B + block.dB); + decodeIndividualOrDifferentialBlock(dest, x, y, w, h, destRowPitch, r1, g1, b1, r2, g2, b2, + alphaValues, nonOpaquePunchThroughAlpha); + } + + void decodeIndividualOrDifferentialBlock(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + size_t destRowPitch, + int r1, + int g1, + int b1, + int r2, + int g2, + int b2, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + const auto intensityModifier = + nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault; + + R8G8B8A8 subblockColors0[4]; + R8G8B8A8 subblockColors1[4]; + for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++) + { + const int i1 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx]; + subblockColors0[modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1); + + const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx]; + subblockColors1[modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2); + } + + if (u.idht.mode.idm.flipbit) + { + uint8_t *curPixel = dest; + for (size_t j = 0; j < 2 && (y + j) < h; j++) + { + R8G8B8A8 *row = reinterpret_cast(curPixel); + for (size_t i = 0; i < 4 && (x + i) < w; i++) + { + row[i] = subblockColors0[getIndex(i, j)]; + row[i].A = alphaValues[j][i]; + } + curPixel += destRowPitch; + } + for (size_t j = 2; j < 4 && (y + j) < h; j++) + { + R8G8B8A8 *row = reinterpret_cast(curPixel); + for (size_t i = 0; i < 4 && (x + i) < w; i++) + { + row[i] = subblockColors1[getIndex(i, j)]; + row[i].A = alphaValues[j][i]; + } + curPixel += destRowPitch; + } + } + else + { + uint8_t *curPixel = dest; + for (size_t j = 0; j < 4 && (y + j) < h; j++) + { + R8G8B8A8 *row = reinterpret_cast(curPixel); + for (size_t i = 0; i < 2 && (x + i) < w; i++) + { + row[i] = subblockColors0[getIndex(i, j)]; + row[i].A = alphaValues[j][i]; + } + for (size_t i = 2; i < 4 && (x + i) < w; i++) + { + row[i] = subblockColors1[getIndex(i, j)]; + row[i].A = alphaValues[j][i]; + } + curPixel += destRowPitch; + } + } + if (nonOpaquePunchThroughAlpha) + { + decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch); + } + } + + void decodeTBlock(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + size_t destRowPitch, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + // Table C.8, distance index for T and H modes + const auto &block = u.idht.mode.tm; + + int r1 = extend_4to8bits(block.TR1a << 2 | block.TR1b); + int g1 = extend_4to8bits(block.TG1); + int b1 = extend_4to8bits(block.TB1); + int r2 = extend_4to8bits(block.TR2); + int g2 = extend_4to8bits(block.TG2); + int b2 = extend_4to8bits(block.TB2); + + static int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64}; + const int d = distance[block.Tda << 1 | block.Tdb]; + + const R8G8B8A8 paintColors[4] = { + createRGBA(r1, g1, b1), createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2, g2, b2), + createRGBA(r2 - d, g2 - d, b2 - d), + }; + + uint8_t *curPixel = dest; + for (size_t j = 0; j < 4 && (y + j) < h; j++) + { + R8G8B8A8 *row = reinterpret_cast(curPixel); + for (size_t i = 0; i < 4 && (x + i) < w; i++) + { + row[i] = paintColors[getIndex(i, j)]; + row[i].A = alphaValues[j][i]; + } + curPixel += destRowPitch; + } + + if (nonOpaquePunchThroughAlpha) + { + decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch); + } + } + + void decodeHBlock(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + size_t destRowPitch, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + // Table C.8, distance index for T and H modes + const auto &block = u.idht.mode.hm; + + int r1 = extend_4to8bits(block.HR1); + int g1 = extend_4to8bits(block.HG1a << 1 | block.HG1b); + int b1 = extend_4to8bits(block.HB1a << 3 | block.HB1b << 1 | block.HB1c); + int r2 = extend_4to8bits(block.HR2); + int g2 = extend_4to8bits(block.HG2a << 1 | block.HG2b); + int b2 = extend_4to8bits(block.HB2); + + static const int distance[8] = {3, 6, 11, 16, 23, 32, 41, 64}; + const int d = distance[(block.Hda << 2) | (block.Hdb << 1) | + ((r1 << 16 | g1 << 8 | b1) >= (r2 << 16 | g2 << 8 | b2) ? 1 : 0)]; + + const R8G8B8A8 paintColors[4] = { + createRGBA(r1 + d, g1 + d, b1 + d), createRGBA(r1 - d, g1 - d, b1 - d), + createRGBA(r2 + d, g2 + d, b2 + d), createRGBA(r2 - d, g2 - d, b2 - d), + }; + + uint8_t *curPixel = dest; + for (size_t j = 0; j < 4 && (y + j) < h; j++) + { + R8G8B8A8 *row = reinterpret_cast(curPixel); + for (size_t i = 0; i < 4 && (x + i) < w; i++) + { + row[i] = paintColors[getIndex(i, j)]; + row[i].A = alphaValues[j][i]; + } + curPixel += destRowPitch; + } + + if (nonOpaquePunchThroughAlpha) + { + decodePunchThroughAlphaBlock(dest, x, y, w, h, destRowPitch); + } + } + + void decodePlanarBlock(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + size_t pitch, + const uint8_t alphaValues[4][4]) const + { + int ro = extend_6to8bits(u.pblk.RO); + int go = extend_7to8bits(u.pblk.GO1 << 6 | u.pblk.GO2); + int bo = + extend_6to8bits(u.pblk.BO1 << 5 | u.pblk.BO2 << 3 | u.pblk.BO3a << 1 | u.pblk.BO3b); + int rh = extend_6to8bits(u.pblk.RH1 << 1 | u.pblk.RH2); + int gh = extend_7to8bits(u.pblk.GH); + int bh = extend_6to8bits(u.pblk.BHa << 5 | u.pblk.BHb); + int rv = extend_6to8bits(u.pblk.RVa << 3 | u.pblk.RVb); + int gv = extend_7to8bits(u.pblk.GVa << 2 | u.pblk.GVb); + int bv = extend_6to8bits(u.pblk.BV); + + uint8_t *curPixel = dest; + for (size_t j = 0; j < 4 && (y + j) < h; j++) + { + R8G8B8A8 *row = reinterpret_cast(curPixel); + + int ry = static_cast(j) * (rv - ro) + 2; + int gy = static_cast(j) * (gv - go) + 2; + int by = static_cast(j) * (bv - bo) + 2; + for (size_t i = 0; i < 4 && (x + i) < w; i++) + { + row[i] = createRGBA(((static_cast(i) * (rh - ro) + ry) >> 2) + ro, + ((static_cast(i) * (gh - go) + gy) >> 2) + go, + ((static_cast(i) * (bh - bo) + by) >> 2) + bo, + alphaValues[j][i]); + } + curPixel += pitch; + } + } + + // Index for individual, differential, H and T modes + size_t getIndex(size_t x, size_t y) const + { + size_t bitIndex = x * 4 + y; + size_t bitOffset = bitIndex & 7; + size_t lsb = (u.idht.pixelIndexLSB[1 - (bitIndex >> 3)] >> bitOffset) & 1; + size_t msb = (u.idht.pixelIndexMSB[1 - (bitIndex >> 3)] >> bitOffset) & 1; + return (msb << 1) | lsb; + } + + void decodePunchThroughAlphaBlock(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + size_t destRowPitch) const + { + uint8_t *curPixel = dest; + for (size_t j = 0; j < 4 && (y + j) < h; j++) + { + R8G8B8A8 *row = reinterpret_cast(curPixel); + for (size_t i = 0; i < 4 && (x + i) < w; i++) + { + if (getIndex(i, j) == 2) // msb == 1 && lsb == 0 + { + row[i] = createRGBA(0, 0, 0, 0); + } + } + curPixel += destRowPitch; + } + } + + uint16_t RGB8ToRGB565(const R8G8B8A8 &rgba) const + { + return (static_cast(rgba.R >> 3) << 11) | + (static_cast(rgba.G >> 2) << 5) | + (static_cast(rgba.B >> 3) << 0); + } + + uint32_t matchBC1Bits(const R8G8B8A8 *rgba, + const R8G8B8A8 &minColor, + const R8G8B8A8 &maxColor, + bool opaque) const + { + // Project each pixel on the (maxColor, minColor) line to decide which + // BC1 code to assign to it. + + uint8_t decodedColors[2][3] = {{maxColor.R, maxColor.G, maxColor.B}, + {minColor.R, minColor.G, minColor.B}}; + + int direction[3]; + for (int ch = 0; ch < 3; ch++) + { + direction[ch] = decodedColors[0][ch] - decodedColors[1][ch]; + } + + int stops[2]; + for (int i = 0; i < 2; i++) + { + stops[i] = decodedColors[i][0] * direction[0] + decodedColors[i][1] * direction[1] + + decodedColors[i][2] * direction[2]; + } + + uint32_t bits = 0; + if (opaque) + { + for (int i = 15; i >= 0; i--) + { + // In opaque mode, the code is from 0 to 3. + + bits <<= 2; + const int dot = + rgba[i].R * direction[0] + rgba[i].G * direction[1] + rgba[i].B * direction[2]; + const int factor = gl::clamp( + static_cast( + (static_cast(dot - stops[1]) / (stops[0] - stops[1])) * 3 + 0.5f), + 0, 3); + switch (factor) + { + case 0: + bits |= 1; + break; + case 1: + bits |= 3; + break; + case 2: + bits |= 2; + break; + case 3: + default: + bits |= 0; + break; + } + } + } + else + { + for (int i = 15; i >= 0; i--) + { + // In non-opaque mode, 3 is for tranparent pixels. + + bits <<= 2; + if (0 == rgba[i].A) + { + bits |= 3; + } + else + { + const int dot = rgba[i].R * direction[0] + rgba[i].G * direction[1] + + rgba[i].B * direction[2]; + const int factor = gl::clamp( + static_cast( + (static_cast(dot - stops[1]) / (stops[0] - stops[1])) * 2 + + 0.5f), + 0, 2); + switch (factor) + { + case 0: + bits |= 0; + break; + case 1: + bits |= 2; + break; + case 2: + default: + bits |= 1; + break; + } + } + } + } + + return bits; + } + + void packBC1(void *bc1, + const R8G8B8A8 *rgba, + R8G8B8A8 &minColor, + R8G8B8A8 &maxColor, + bool opaque) const + { + uint32_t bits; + uint16_t max16 = RGB8ToRGB565(maxColor); + uint16_t min16 = RGB8ToRGB565(minColor); + if (max16 != min16) + { + // Find the best BC1 code for each pixel + bits = matchBC1Bits(rgba, minColor, maxColor, opaque); + } + else + { + // Same colors, BC1 index 0 is the color in both opaque and transparent mode + bits = 0; + // BC1 index 3 is transparent + if (!opaque) + { + for (int i = 0; i < 16; i++) + { + if (0 == rgba[i].A) + { + bits |= (3 << (i * 2)); + } + } + } + } + + if (max16 < min16) + { + std::swap(max16, min16); + + uint32_t xorMask = 0; + if (opaque) + { + // In opaque mode switching the two colors is doing the + // following code swaps: 0 <-> 1 and 2 <-> 3. This is + // equivalent to flipping the first bit of each code + // (5 = 0b0101) + xorMask = 0x55555555; + } + else + { + // In transparent mode switching the colors is doing the + // following code swap: 0 <-> 1. 0xA selects the second bit of + // each code, bits >> 1 selects the first bit of the code when + // the seconds bit is set (case 2 and 3). We invert all the + // non-selected bits, that is the first bit when the code is + // 0 or 1. + xorMask = ~((bits >> 1) | 0xAAAAAAAA); + } + bits ^= xorMask; + } + + struct BC1Block + { + uint16_t color0; + uint16_t color1; + uint32_t bits; + }; + + // Encode the opaqueness in the order of the two BC1 colors + BC1Block *dest = reinterpret_cast(bc1); + if (opaque) + { + dest->color0 = max16; + dest->color1 = min16; + } + else + { + dest->color0 = min16; + dest->color1 = max16; + } + dest->bits = bits; + } + + void transcodeIndividualBlockToBC1(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + const auto &block = u.idht.mode.idm.colors.indiv; + int r1 = extend_4to8bits(block.R1); + int g1 = extend_4to8bits(block.G1); + int b1 = extend_4to8bits(block.B1); + int r2 = extend_4to8bits(block.R2); + int g2 = extend_4to8bits(block.G2); + int b2 = extend_4to8bits(block.B2); + transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2, + alphaValues, nonOpaquePunchThroughAlpha); + } + + void transcodeDifferentialBlockToBC1(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + const auto &block = u.idht.mode.idm.colors.diff; + int b1 = extend_5to8bits(block.B); + int g1 = extend_5to8bits(block.G); + int r1 = extend_5to8bits(block.R); + int r2 = extend_5to8bits(block.R + block.dR); + int g2 = extend_5to8bits(block.G + block.dG); + int b2 = extend_5to8bits(block.B + block.dB); + transcodeIndividualOrDifferentialBlockToBC1(dest, x, y, w, h, r1, g1, b1, r2, g2, b2, + alphaValues, nonOpaquePunchThroughAlpha); + } + + void decodeSubblock(R8G8B8A8 *rgbaBlock, + size_t pixelRange[2][2], + size_t x, + size_t y, + size_t w, + size_t h, + const uint8_t alphaValues[4][4], + bool flipbit, + size_t subblockIdx, + const R8G8B8A8 subblockColors[2][4]) const + { + size_t dxBegin = 0; + size_t dxEnd = 4; + size_t dyBegin = subblockIdx * 2; + size_t dyEnd = dyBegin + 2; + if (!flipbit) + { + std::swap(dxBegin, dyBegin); + std::swap(dxEnd, dyEnd); + } + + for (size_t j = dyBegin; j < dyEnd && (y + j) < h; j++) + { + R8G8B8A8 *row = &rgbaBlock[j * 4]; + for (size_t i = dxBegin; i < dxEnd && (x + i) < w; i++) + { + const size_t pixelIndex = getIndex(i, j); + if (valueMappingTable[pixelIndex] < valueMappingTable[pixelRange[subblockIdx][0]]) + { + pixelRange[subblockIdx][0] = pixelIndex; + } + if (valueMappingTable[pixelIndex] > valueMappingTable[pixelRange[subblockIdx][1]]) + { + pixelRange[subblockIdx][1] = pixelIndex; + } + + row[i] = subblockColors[subblockIdx][pixelIndex]; + row[i].A = alphaValues[j][i]; + } + } + } + + void transcodeIndividualOrDifferentialBlockToBC1(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + int r1, + int g1, + int b1, + int r2, + int g2, + int b2, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + // A BC1 block has 2 endpoints, pixels is encoded as linear + // interpolations of them. A ETC1/ETC2 individual or differential block + // has 2 subblocks. Each subblock has one color and a modifier. We + // compute the max intensity and min intensity pixel values to use as + // our two BC1 endpoints and then map pixels to BC1 by projecting on the + // line between the two endpoints and choosing the right fraction. + // + // In the future, we have 2 potential improvements to this algorithm. + // 1. We don't actually need to decode ETC blocks to RGBs. Instead, + // the subblock colors and pixel indices alreay contains enough + // information for transcode. A direct mapping would be more + // efficient here. + // 2. Currently the BC1 endpoints come from the max and min intensity + // of ETC colors. A principal component analysis (PCA) on them might + // give us better quality results, with limited costs + + const auto intensityModifier = + nonOpaquePunchThroughAlpha ? intensityModifierNonOpaque : intensityModifierDefault; + + // Compute the colors that pixels can have in each subblock both for + // the decoding of the RGBA data and BC1 encoding + R8G8B8A8 subblockColors[2][4]; + for (size_t modifierIdx = 0; modifierIdx < 4; modifierIdx++) + { + const int i1 = intensityModifier[u.idht.mode.idm.cw1][modifierIdx]; + subblockColors[0][modifierIdx] = createRGBA(r1 + i1, g1 + i1, b1 + i1); + + const int i2 = intensityModifier[u.idht.mode.idm.cw2][modifierIdx]; + subblockColors[1][modifierIdx] = createRGBA(r2 + i2, g2 + i2, b2 + i2); + } + + // 1 and 3 are the argmax and argmin of valueMappingTable + size_t pixelRange[2][2] = {{1, 3}, {1, 3}}; + R8G8B8A8 rgbaBlock[16]; + // Decode the block in rgbaBlock and store the inverse valueTableMapping + // of {min(modifier index), max(modifier index)} + for (size_t blockIdx = 0; blockIdx < 2; blockIdx++) + { + decodeSubblock(rgbaBlock, pixelRange, x, y, w, h, alphaValues, u.idht.mode.idm.flipbit, + blockIdx, subblockColors); + } + if (nonOpaquePunchThroughAlpha) + { + decodePunchThroughAlphaBlock(reinterpret_cast(rgbaBlock), x, y, w, h, + sizeof(R8G8B8A8) * 4); + } + + // Get the "min" and "max" pixel colors that have been used. + R8G8B8A8 minColor; + const R8G8B8A8 &minColor0 = subblockColors[0][pixelRange[0][0]]; + const R8G8B8A8 &minColor1 = subblockColors[1][pixelRange[1][0]]; + if (minColor0.R + minColor0.G + minColor0.B < minColor1.R + minColor1.G + minColor1.B) + { + minColor = minColor0; + } + else + { + minColor = minColor1; + } + + R8G8B8A8 maxColor; + const R8G8B8A8 &maxColor0 = subblockColors[0][pixelRange[0][1]]; + const R8G8B8A8 &maxColor1 = subblockColors[1][pixelRange[1][1]]; + if (maxColor0.R + maxColor0.G + maxColor0.B < maxColor1.R + maxColor1.G + maxColor1.B) + { + maxColor = maxColor1; + } + else + { + maxColor = maxColor0; + } + + packBC1(dest, rgbaBlock, minColor, maxColor, !nonOpaquePunchThroughAlpha); + } + + void transcodeTBlockToBC1(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + // TODO (mgong): Will be implemented soon + UNIMPLEMENTED(); + } + + void transcodeHBlockToBC1(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + const uint8_t alphaValues[4][4], + bool nonOpaquePunchThroughAlpha) const + { + // TODO (mgong): Will be implemented soon + UNIMPLEMENTED(); + } + + void transcodePlanarBlockToBC1(uint8_t *dest, + size_t x, + size_t y, + size_t w, + size_t h, + const uint8_t alphaValues[4][4]) const + { + // TODO (mgong): Will be implemented soon + UNIMPLEMENTED(); + } + + // Single channel utility functions + int getSingleChannel(size_t x, size_t y, bool isSigned) const + { + int codeword = isSigned ? u.scblk.base_codeword.s : u.scblk.base_codeword.us; + return codeword + getSingleChannelModifier(x, y) * u.scblk.multiplier; + } + + int getSingleChannelIndex(size_t x, size_t y) const + { + ASSERT(x < 4 && y < 4); + + // clang-format off + switch (x * 4 + y) + { + case 0: return u.scblk.ma; + case 1: return u.scblk.mb; + case 2: return u.scblk.mc1 << 1 | u.scblk.mc2; + case 3: return u.scblk.md; + case 4: return u.scblk.me; + case 5: return u.scblk.mf1 << 2 | u.scblk.mf2; + case 6: return u.scblk.mg; + case 7: return u.scblk.mh; + case 8: return u.scblk.mi; + case 9: return u.scblk.mj; + case 10: return u.scblk.mk1 << 1 | u.scblk.mk2; + case 11: return u.scblk.ml; + case 12: return u.scblk.mm; + case 13: return u.scblk.mn1 << 2 | u.scblk.mn2; + case 14: return u.scblk.mo; + case 15: return u.scblk.mp; + default: UNREACHABLE(); return 0; + } + // clang-format on + } + + int getSingleChannelModifier(size_t x, size_t y) const + { + // clang-format off + static const int modifierTable[16][8] = + { + { -3, -6, -9, -15, 2, 5, 8, 14 }, + { -3, -7, -10, -13, 2, 6, 9, 12 }, + { -2, -5, -8, -13, 1, 4, 7, 12 }, + { -2, -4, -6, -13, 1, 3, 5, 12 }, + { -3, -6, -8, -12, 2, 5, 7, 11 }, + { -3, -7, -9, -11, 2, 6, 8, 10 }, + { -4, -7, -8, -11, 3, 6, 7, 10 }, + { -3, -5, -8, -11, 2, 4, 7, 10 }, + { -2, -6, -8, -10, 1, 5, 7, 9 }, + { -2, -5, -8, -10, 1, 4, 7, 9 }, + { -2, -4, -8, -10, 1, 3, 7, 9 }, + { -2, -5, -7, -10, 1, 4, 6, 9 }, + { -3, -4, -7, -10, 2, 3, 6, 9 }, + { -1, -2, -3, -10, 0, 1, 2, 9 }, + { -4, -6, -8, -9, 3, 5, 7, 8 }, + { -3, -5, -7, -9, 2, 4, 6, 8 } + }; + // clang-format on + + return modifierTable[u.scblk.table_index][getSingleChannelIndex(x, y)]; + } +}; + +// clang-format off +static const uint8_t DefaultETCAlphaValues[4][4] = +{ + { 255, 255, 255, 255 }, + { 255, 255, 255, 255 }, + { 255, 255, 255, 255 }, + { 255, 255, 255, 255 }, +}; +// clang-format on + +void LoadR11EACToR8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch, + bool isSigned) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y += 4) + { + const ETC2Block *sourceRow = + OffsetDataPointer(input, y / 4, z, inputRowPitch, inputDepthPitch); + uint8_t *destRow = + OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < width; x += 4) + { + const ETC2Block *sourceBlock = sourceRow + (x / 4); + uint8_t *destPixels = destRow + x; + + sourceBlock->decodeAsSingleChannel(destPixels, x, y, width, height, 1, + outputRowPitch, isSigned); + } + } + } +} + +void LoadRG11EACToRG8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch, + bool isSigned) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y += 4) + { + const ETC2Block *sourceRow = + OffsetDataPointer(input, y / 4, z, inputRowPitch, inputDepthPitch); + uint8_t *destRow = + OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < width; x += 4) + { + uint8_t *destPixelsRed = destRow + (x * 2); + const ETC2Block *sourceBlockRed = sourceRow + (x / 2); + sourceBlockRed->decodeAsSingleChannel(destPixelsRed, x, y, width, height, 2, + outputRowPitch, isSigned); + + uint8_t *destPixelsGreen = destPixelsRed + 1; + const ETC2Block *sourceBlockGreen = sourceBlockRed + 1; + sourceBlockGreen->decodeAsSingleChannel(destPixelsGreen, x, y, width, height, 2, + outputRowPitch, isSigned); + } + } + } +} + +void LoadETC2RGB8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch, + bool punchthroughAlpha) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y += 4) + { + const ETC2Block *sourceRow = + OffsetDataPointer(input, y / 4, z, inputRowPitch, inputDepthPitch); + uint8_t *destRow = + OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < width; x += 4) + { + const ETC2Block *sourceBlock = sourceRow + (x / 4); + uint8_t *destPixels = destRow + (x * 4); + + sourceBlock->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch, + DefaultETCAlphaValues, punchthroughAlpha); + } + } + } +} + +void LoadETC2RGB8ToBC1(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch, + bool punchthroughAlpha) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y += 4) + { + const ETC2Block *sourceRow = + OffsetDataPointer(input, y / 4, z, inputRowPitch, inputDepthPitch); + uint8_t *destRow = + OffsetDataPointer(output, y / 4, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < width; x += 4) + { + const ETC2Block *sourceBlock = sourceRow + (x / 4); + uint8_t *destPixels = destRow + (x * 2); + + sourceBlock->transcodeAsBC1(destPixels, x, y, width, height, DefaultETCAlphaValues, + punchthroughAlpha); + } + } + } +} + +void LoadETC2RGBA8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch, + bool srgb) +{ + uint8_t decodedAlphaValues[4][4]; + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y += 4) + { + const ETC2Block *sourceRow = + OffsetDataPointer(input, y / 4, z, inputRowPitch, inputDepthPitch); + uint8_t *destRow = + OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < width; x += 4) + { + const ETC2Block *sourceBlockAlpha = sourceRow + (x / 2); + sourceBlockAlpha->decodeAsSingleChannel( + reinterpret_cast(decodedAlphaValues), x, y, width, height, 1, 4, + false); + + uint8_t *destPixels = destRow + (x * 4); + const ETC2Block *sourceBlockRGB = sourceBlockAlpha + 1; + sourceBlockRGB->decodeAsRGB(destPixels, x, y, width, height, outputRowPitch, + decodedAlphaValues, false); + } + } + } +} + +} // anonymous namespace + +void LoadETC1RGB8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, false); +} + +void LoadETC1RGB8ToBC1(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadETC2RGB8ToBC1(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, false); +} + +void LoadEACR11ToR8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, false); +} + +void LoadEACR11SToR8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadR11EACToR8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, true); +} + +void LoadEACRG11ToRG8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, false); +} + +void LoadEACRG11SToRG8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadRG11EACToRG8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, true); +} + +void LoadETC2RGB8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, false); +} + +void LoadETC2SRGB8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, false); +} + +void LoadETC2RGB8A1ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, true); +} + +void LoadETC2SRGB8A1ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadETC2RGB8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, true); +} + +void LoadETC2RGBA8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, false); +} + +void LoadETC2SRGBA8ToSRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch) +{ + LoadETC2RGBA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, + outputRowPitch, outputDepthPitch, true); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h new file mode 100644 index 0000000000..dc64e0461b --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage_etc.h @@ -0,0 +1,140 @@ +// +// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// loadimage_etc.h: Decodes ETC and EAC encoded textures. + +#ifndef LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_ +#define LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_ + +#include "libANGLE/angletypes.h" + +#include + +namespace rx +{ + +void LoadETC1RGB8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadETC1RGB8ToBC1(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadEACR11ToR8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadEACR11SToR8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadEACRG11ToRG8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadEACRG11SToRG8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadETC2RGB8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadETC2SRGB8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadETC2RGB8A1ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadETC2SRGB8A1ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadETC2RGBA8ToRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); + +void LoadETC2SRGBA8ToSRGBA8(size_t width, + size_t height, + size_t depth, + const uint8_t *input, + size_t inputRowPitch, + size_t inputDepthPitch, + uint8_t *output, + size_t outputRowPitch, + size_t outputDepthPitch); +} + +#endif // LIBANGLE_RENDERER_D3D_LOADIMAGE_ETC_H_ diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp index 12ee6a2b93..972f6a7a5a 100644 --- a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp +++ b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp @@ -8,13 +8,87 @@ #include "libANGLE/validationEGL.h" +#include "common/utilities.h" #include "libANGLE/Config.h" #include "libANGLE/Context.h" +#include "libANGLE/Device.h" #include "libANGLE/Display.h" +#include "libANGLE/Image.h" #include "libANGLE/Surface.h" #include +namespace +{ +size_t GetMaximumMipLevel(const gl::Context *context, GLenum target) +{ + const gl::Caps &caps = context->getCaps(); + + size_t maxDimension = 0; + switch (target) + { + case GL_TEXTURE_2D: + maxDimension = caps.max2DTextureSize; + break; + case GL_TEXTURE_CUBE_MAP: + maxDimension = caps.maxCubeMapTextureSize; + break; + case GL_TEXTURE_3D: + maxDimension = caps.max3DTextureSize; + break; + case GL_TEXTURE_2D_ARRAY: + maxDimension = caps.max2DTextureSize; + break; + default: + UNREACHABLE(); + } + + return gl::log2(static_cast(maxDimension)); +} + +bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::Texture *texture) +{ + size_t maxMip = GetMaximumMipLevel(context, texture->getTarget()); + for (size_t level = 1; level < maxMip; level++) + { + if (texture->getTarget() == GL_TEXTURE_CUBE_MAP) + { + for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; + face++) + { + if (texture->getInternalFormat(face, level) != GL_NONE) + { + return true; + } + } + } + else + { + if (texture->getInternalFormat(texture->getTarget(), level) != GL_NONE) + { + return true; + } + } + } + + return false; +} + +bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture) +{ + ASSERT(texture->getTarget() == GL_TEXTURE_CUBE_MAP); + for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; face++) + { + if (texture->getInternalFormat(face, 0) == GL_NONE) + { + return true; + } + } + + return false; +} +} + namespace egl { @@ -22,12 +96,17 @@ Error ValidateDisplay(const Display *display) { if (display == EGL_NO_DISPLAY) { - return Error(EGL_BAD_DISPLAY); + return Error(EGL_BAD_DISPLAY, "display is EGL_NO_DISPLAY."); + } + + if (!Display::isValidDisplay(display)) + { + return Error(EGL_BAD_DISPLAY, "display is not a valid display."); } if (!display->isInitialized()) { - return Error(EGL_NOT_INITIALIZED); + return Error(EGL_NOT_INITIALIZED, "display is not initialized."); } return Error(EGL_SUCCESS); @@ -81,6 +160,22 @@ Error ValidateContext(const Display *display, gl::Context *context) return Error(EGL_SUCCESS); } +Error ValidateImage(const Display *display, const Image *image) +{ + Error error = ValidateDisplay(display); + if (error.isError()) + { + return error; + } + + if (!display->isValidImage(image)) + { + return Error(EGL_BAD_PARAMETER, "image is not valid."); + } + + return Error(EGL_SUCCESS); +} + Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext, const AttributeMap& attributes) { @@ -115,6 +210,9 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context contextFlags = value; break; + case EGL_CONTEXT_OPENGL_DEBUG: + break; + case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR: // Only valid for OpenGL (non-ES) contexts return Error(EGL_BAD_ATTRIBUTE); @@ -150,6 +248,17 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context } break; + case EGL_CONTEXT_OPENGL_NO_ERROR_KHR: + if (!display->getExtensions().createContextNoError) + { + return Error(EGL_BAD_ATTRIBUTE, "Invalid Context attribute."); + } + if (value != EGL_TRUE && value != EGL_FALSE) + { + return Error(EGL_BAD_ATTRIBUTE, "Attribute must be EGL_TRUE or EGL_FALSE."); + } + break; + default: return Error(EGL_BAD_ATTRIBUTE); } @@ -248,6 +357,13 @@ Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWin } break; + case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE: + if (!displayExtensions.flexibleSurfaceCompatibility) + { + return Error(EGL_BAD_ATTRIBUTE); + } + break; + case EGL_WIDTH: case EGL_HEIGHT: if (!displayExtensions.windowFixedSize) @@ -267,12 +383,26 @@ Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWin } break; + case EGL_SURFACE_ORIENTATION_ANGLE: + if (!displayExtensions.surfaceOrientation) + { + return Error(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_surface_orientation is not enabled."); + } + break; + case EGL_VG_COLORSPACE: return Error(EGL_BAD_MATCH); case EGL_VG_ALPHA_FORMAT: return Error(EGL_BAD_MATCH); + case EGL_DIRECT_COMPOSITION_ANGLE: + if (!displayExtensions.directComposition) + { + return Error(EGL_BAD_ATTRIBUTE); + } + break; + default: return Error(EGL_BAD_ATTRIBUTE); } @@ -293,7 +423,9 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri { return error; } - + + const DisplayExtensions &displayExtensions = display->getExtensions(); + for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++) { EGLint attribute = attributeIter->first; @@ -344,6 +476,16 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri case EGL_VG_ALPHA_FORMAT: break; + case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE: + if (!displayExtensions.flexibleSurfaceCompatibility) + { + return Error( + EGL_BAD_ATTRIBUTE, + "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without " + "EGL_ANGLE_flexible_surface_compatibility support."); + } + break; + default: return Error(EGL_BAD_ATTRIBUTE); } @@ -354,6 +496,7 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri return Error(EGL_BAD_MATCH); } +#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // On Windows Store, we know the originating texture came from D3D11, so bypass this check const Caps &caps = display->getCaps(); EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE); @@ -377,6 +520,7 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri { return Error(EGL_BAD_MATCH); } +#endif return Error(EGL_SUCCESS); } @@ -454,6 +598,16 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E case EGL_MIPMAP_TEXTURE: break; + case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE: + if (!displayExtensions.flexibleSurfaceCompatibility) + { + return Error( + EGL_BAD_ATTRIBUTE, + "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used without " + "EGL_ANGLE_flexible_surface_compatibility support."); + } + break; + default: return Error(EGL_BAD_ATTRIBUTE); } @@ -488,16 +642,418 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E return Error(EGL_BAD_ATTRIBUTE); } -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // On Windows Store, we know the originating texture came from D3D11, so bypass this check const Caps &caps = display->getCaps(); if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) { return Error(EGL_BAD_MATCH); } -#endif } return Error(EGL_SUCCESS); } +Error ValidateCompatibleConfigs(const Display *display, + const Config *config1, + const Surface *surface, + const Config *config2, + EGLint surfaceType) +{ + + if (!surface->flexibleSurfaceCompatibilityRequested()) + { + // Config compatibility is defined in section 2.2 of the EGL 1.5 spec + + bool colorBufferCompat = config1->colorBufferType == config2->colorBufferType; + if (!colorBufferCompat) + { + return Error(EGL_BAD_MATCH, "Color buffer types are not compatible."); + } + + bool colorCompat = + config1->redSize == config2->redSize && config1->greenSize == config2->greenSize && + config1->blueSize == config2->blueSize && config1->alphaSize == config2->alphaSize && + config1->luminanceSize == config2->luminanceSize; + if (!colorCompat) + { + return Error(EGL_BAD_MATCH, "Color buffer sizes are not compatible."); + } + + bool dsCompat = config1->depthSize == config2->depthSize && + config1->stencilSize == config2->stencilSize; + if (!dsCompat) + { + return Error(EGL_BAD_MATCH, "Depth-stencil buffer types are not compatible."); + } + } + + bool surfaceTypeCompat = (config1->surfaceType & config2->surfaceType & surfaceType) != 0; + if (!surfaceTypeCompat) + { + return Error(EGL_BAD_MATCH, "Surface types are not compatible."); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreateImageKHR(const Display *display, + gl::Context *context, + EGLenum target, + EGLClientBuffer buffer, + const AttributeMap &attributes) +{ + Error error = ValidateContext(display, context); + if (error.isError()) + { + return error; + } + + const DisplayExtensions &displayExtensions = display->getExtensions(); + + if (!displayExtensions.imageBase && !displayExtensions.image) + { + // It is out of spec what happens when calling an extension function when the extension is + // not available. + // EGL_BAD_DISPLAY seems like a reasonable error. + return Error(EGL_BAD_DISPLAY, "EGL_KHR_image not supported."); + } + + // TODO(geofflang): Complete validation from EGL_KHR_image_base: + // If the resource specified by , , , and is itself an + // EGLImage sibling, the error EGL_BAD_ACCESS is generated. + + for (AttributeMap::const_iterator attributeIter = attributes.begin(); + attributeIter != attributes.end(); attributeIter++) + { + EGLint attribute = attributeIter->first; + EGLint value = attributeIter->second; + + switch (attribute) + { + case EGL_IMAGE_PRESERVED_KHR: + switch (value) + { + case EGL_TRUE: + case EGL_FALSE: + break; + + default: + return Error(EGL_BAD_PARAMETER, + "EGL_IMAGE_PRESERVED_KHR must be EGL_TRUE or EGL_FALSE."); + } + break; + + case EGL_GL_TEXTURE_LEVEL_KHR: + if (!displayExtensions.glTexture2DImage && + !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage) + { + return Error(EGL_BAD_PARAMETER, + "EGL_GL_TEXTURE_LEVEL_KHR cannot be used without " + "KHR_gl_texture_*_image support."); + } + + if (value < 0) + { + return Error(EGL_BAD_PARAMETER, "EGL_GL_TEXTURE_LEVEL_KHR cannot be negative."); + } + break; + + case EGL_GL_TEXTURE_ZOFFSET_KHR: + if (!displayExtensions.glTexture3DImage) + { + return Error(EGL_BAD_PARAMETER, + "EGL_GL_TEXTURE_ZOFFSET_KHR cannot be used without " + "KHR_gl_texture_3D_image support."); + } + break; + + default: + return Error(EGL_BAD_PARAMETER, "invalid attribute: 0x%X", attribute); + } + } + + switch (target) + { + case EGL_GL_TEXTURE_2D_KHR: + { + if (!displayExtensions.glTexture2DImage) + { + return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_2D_image not supported."); + } + + if (buffer == 0) + { + return Error(EGL_BAD_PARAMETER, + "buffer cannot reference a 2D texture with the name 0."); + } + + const gl::Texture *texture = + context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); + if (texture == nullptr || texture->getTarget() != GL_TEXTURE_2D) + { + return Error(EGL_BAD_PARAMETER, "target is not a 2D texture."); + } + + if (texture->getBoundSurface() != nullptr) + { + return Error(EGL_BAD_ACCESS, "texture has a surface bound to it."); + } + + EGLint level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0); + if (texture->getWidth(GL_TEXTURE_2D, static_cast(level)) == 0 || + texture->getHeight(GL_TEXTURE_2D, static_cast(level)) == 0) + { + return Error(EGL_BAD_PARAMETER, + "target 2D texture does not have a valid size at specified level."); + } + + if (level > 0 && (!texture->isMipmapComplete() || + static_cast(level) >= texture->getMipCompleteLevels())) + { + return Error(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero."); + } + + if (level == 0 && !texture->isMipmapComplete() && + TextureHasNonZeroMipLevelsSpecified(context, texture)) + { + return Error(EGL_BAD_PARAMETER, + "if level is zero and the texture is incomplete, it must have no mip " + "levels specified except zero."); + } + } + break; + + case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR: + case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR: + case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR: + case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR: + case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR: + case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR: + { + if (!displayExtensions.glTextureCubemapImage) + { + return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_cubemap_image not supported."); + } + + if (buffer == 0) + { + return Error(EGL_BAD_PARAMETER, + "buffer cannot reference a cubemap texture with the name 0."); + } + + const gl::Texture *texture = + context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); + if (texture == nullptr || texture->getTarget() != GL_TEXTURE_CUBE_MAP) + { + return Error(EGL_BAD_PARAMETER, "target is not a cubemap texture."); + } + + if (texture->getBoundSurface() != nullptr) + { + return Error(EGL_BAD_ACCESS, "texture has a surface bound to it."); + } + + EGLint level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0); + GLenum cubeMapFace = egl_gl::EGLCubeMapTargetToGLCubeMapTarget(target); + if (texture->getWidth(cubeMapFace, static_cast(level)) == 0 || + texture->getHeight(cubeMapFace, static_cast(level)) == 0) + { + return Error(EGL_BAD_PARAMETER, + "target cubemap texture does not have a valid size at specified level " + "and face."); + } + + if (level > 0 && (!texture->isMipmapComplete() || + static_cast(level) >= texture->getMipCompleteLevels())) + { + return Error(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero."); + } + + if (level == 0 && !texture->isMipmapComplete() && + TextureHasNonZeroMipLevelsSpecified(context, texture)) + { + return Error(EGL_BAD_PARAMETER, + "if level is zero and the texture is incomplete, it must have no mip " + "levels specified except zero."); + } + + if (level == 0 && !texture->isMipmapComplete() && + CubeTextureHasUnspecifiedLevel0Face(texture)) + { + return Error(EGL_BAD_PARAMETER, + "if level is zero and the texture is incomplete, it must have all of " + "its faces specified at level zero."); + } + } + break; + + case EGL_GL_TEXTURE_3D_KHR: + { + if (!displayExtensions.glTexture3DImage) + { + return Error(EGL_BAD_PARAMETER, "KHR_gl_texture_3D_image not supported."); + } + + if (buffer == 0) + { + return Error(EGL_BAD_PARAMETER, + "buffer cannot reference a 3D texture with the name 0."); + } + + const gl::Texture *texture = + context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); + if (texture == nullptr || texture->getTarget() != GL_TEXTURE_3D) + { + return Error(EGL_BAD_PARAMETER, "target is not a 3D texture."); + } + + if (texture->getBoundSurface() != nullptr) + { + return Error(EGL_BAD_ACCESS, "texture has a surface bound to it."); + } + + EGLint level = attributes.get(EGL_GL_TEXTURE_LEVEL_KHR, 0); + EGLint zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET_KHR, 0); + if (texture->getWidth(GL_TEXTURE_3D, static_cast(level)) == 0 || + texture->getHeight(GL_TEXTURE_3D, static_cast(level)) == 0 || + texture->getDepth(GL_TEXTURE_3D, static_cast(level)) == 0) + { + return Error(EGL_BAD_PARAMETER, + "target 3D texture does not have a valid size at specified level."); + } + + if (static_cast(zOffset) >= + texture->getDepth(GL_TEXTURE_3D, static_cast(level))) + { + return Error(EGL_BAD_PARAMETER, + "target 3D texture does not have enough layers for the specified Z " + "offset at the specified level."); + } + + if (level > 0 && (!texture->isMipmapComplete() || + static_cast(level) >= texture->getMipCompleteLevels())) + { + return Error(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero."); + } + + if (level == 0 && !texture->isMipmapComplete() && + TextureHasNonZeroMipLevelsSpecified(context, texture)) + { + return Error(EGL_BAD_PARAMETER, + "if level is zero and the texture is incomplete, it must have no mip " + "levels specified except zero."); + } + } + break; + + case EGL_GL_RENDERBUFFER_KHR: + { + if (!displayExtensions.glRenderbufferImage) + { + return Error(EGL_BAD_PARAMETER, "KHR_gl_renderbuffer_image not supported."); + } + + if (attributes.contains(EGL_GL_TEXTURE_LEVEL_KHR)) + { + return Error(EGL_BAD_PARAMETER, + "EGL_GL_TEXTURE_LEVEL_KHR cannot be used in conjunction with a " + "renderbuffer target."); + } + + if (buffer == 0) + { + return Error(EGL_BAD_PARAMETER, + "buffer cannot reference a renderbuffer with the name 0."); + } + + const gl::Renderbuffer *renderbuffer = + context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); + if (renderbuffer == nullptr) + { + return Error(EGL_BAD_PARAMETER, "target is not a renderbuffer."); + } + + if (renderbuffer->getSamples() > 0) + { + return Error(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled."); + } + } + break; + + default: + return Error(EGL_BAD_PARAMETER, "invalid target: 0x%X", target); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateDestroyImageKHR(const Display *display, const Image *image) +{ + Error error = ValidateImage(display, image); + if (error.isError()) + { + return error; + } + + if (!display->getExtensions().imageBase && !display->getExtensions().image) + { + // It is out of spec what happens when calling an extension function when the extension is + // not available. + // EGL_BAD_DISPLAY seems like a reasonable error. + return Error(EGL_BAD_DISPLAY); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateCreateDeviceANGLE(EGLint device_type, + void *native_device, + const EGLAttrib *attrib_list) +{ + const ClientExtensions &clientExtensions = Display::getClientExtensions(); + if (!clientExtensions.deviceCreation) + { + return Error(EGL_BAD_ACCESS, "Device creation extension not active"); + } + + if (attrib_list != nullptr && attrib_list[0] != EGL_NONE) + { + return Error(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter"); + } + + switch (device_type) + { + case EGL_D3D11_DEVICE_ANGLE: + if (!clientExtensions.deviceCreationD3D11) + { + return Error(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active"); + } + break; + default: + return Error(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter"); + } + + return Error(EGL_SUCCESS); +} + +Error ValidateReleaseDeviceANGLE(Device *device) +{ + const ClientExtensions &clientExtensions = Display::getClientExtensions(); + if (!clientExtensions.deviceCreation) + { + return Error(EGL_BAD_ACCESS, "Device creation extension not active"); + } + + if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device)) + { + return Error(EGL_BAD_DEVICE_EXT, "Invalid device parameter"); + } + + Display *owningDisplay = device->getOwningDisplay(); + if (owningDisplay != nullptr) + { + return Error(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice"); + } + + return Error(EGL_SUCCESS); +} } diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.h b/src/3rdparty/angle/src/libANGLE/validationEGL.h index 4daff791fd..eaafddc20d 100644 --- a/src/3rdparty/angle/src/libANGLE/validationEGL.h +++ b/src/3rdparty/angle/src/libANGLE/validationEGL.h @@ -23,7 +23,9 @@ namespace egl class AttributeMap; struct Config; +class Device; class Display; +class Image; class Surface; // Object validation @@ -31,6 +33,7 @@ Error ValidateDisplay(const Display *display); Error ValidateSurface(const Display *display, Surface *surface); Error ValidateConfig(const Display *display, const Config *config); Error ValidateContext(const Display *display, gl::Context *context); +Error ValidateImage(const Display *display, const Image *image); // Entry point validation Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext, @@ -43,7 +46,24 @@ Error ValidateCreatePbufferSurface(Display *display, Config *config, const Attri Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer, Config *config, const AttributeMap& attributes); +Error ValidateCreateImageKHR(const Display *display, + gl::Context *context, + EGLenum target, + EGLClientBuffer buffer, + const AttributeMap &attributes); +Error ValidateDestroyImageKHR(const Display *display, const Image *image); +Error ValidateCreateDeviceANGLE(EGLint device_type, + void *native_device, + const EGLAttrib *attrib_list); +Error ValidateReleaseDeviceANGLE(Device *device); + +// Other validation +Error ValidateCompatibleConfigs(const Display *display, + const Config *config1, + const Surface *surface, + const Config *config2, + EGLint surfaceType); } #endif // LIBANGLE_VALIDATIONEGL_H_ diff --git a/src/3rdparty/angle/src/libANGLE/validationES.cpp b/src/3rdparty/angle/src/libANGLE/validationES.cpp index d267cbf2e6..12c76120bd 100644 --- a/src/3rdparty/angle/src/libANGLE/validationES.cpp +++ b/src/3rdparty/angle/src/libANGLE/validationES.cpp @@ -10,22 +10,90 @@ #include "libANGLE/validationES2.h" #include "libANGLE/validationES3.h" #include "libANGLE/Context.h" +#include "libANGLE/Display.h" #include "libANGLE/Texture.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/formatutils.h" +#include "libANGLE/Image.h" #include "libANGLE/Query.h" #include "libANGLE/Program.h" #include "libANGLE/Uniform.h" #include "libANGLE/TransformFeedback.h" #include "libANGLE/VertexArray.h" -#include "libANGLE/renderer/BufferImpl.h" #include "common/mathutil.h" #include "common/utilities.h" namespace gl { +const char *g_ExceedsMaxElementErrorMessage = "Element value exceeds maximum element index."; + +namespace +{ +bool ValidateDrawAttribs(ValidationContext *context, GLint primcount, GLint maxVertex) +{ + const gl::State &state = context->getState(); + const gl::Program *program = state.getProgram(); + + const VertexArray *vao = state.getVertexArray(); + const auto &vertexAttribs = vao->getVertexAttributes(); + size_t maxEnabledAttrib = vao->getMaxEnabledAttribute(); + for (size_t attributeIndex = 0; attributeIndex < maxEnabledAttrib; ++attributeIndex) + { + const VertexAttribute &attrib = vertexAttribs[attributeIndex]; + if (program->isAttribLocationActive(attributeIndex) && attrib.enabled) + { + gl::Buffer *buffer = attrib.buffer.get(); + + if (buffer) + { + GLint64 attribStride = static_cast(ComputeVertexAttributeStride(attrib)); + GLint64 maxVertexElement = 0; + + if (attrib.divisor > 0) + { + maxVertexElement = + static_cast(primcount) / static_cast(attrib.divisor); + } + else + { + maxVertexElement = static_cast(maxVertex); + } + + // If we're drawing zero vertices, we have enough data. + if (maxVertexElement > 0) + { + // Note: Last vertex element does not take the full stride! + GLint64 attribSize = + static_cast(ComputeVertexAttributeTypeSize(attrib)); + GLint64 attribDataSize = (maxVertexElement - 1) * attribStride + attribSize; + + // [OpenGL ES 3.0.2] section 2.9.4 page 40: + // We can return INVALID_OPERATION if our vertex attribute does not have + // enough backing data. + if (attribDataSize > buffer->getSize()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + } + else if (attrib.pointer == NULL) + { + // This is an application error that would normally result in a crash, + // but we catch it and return an error + context->recordError(Error( + GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer.")); + return false; + } + } + } + + return true; +} + +} // anonymous namespace bool ValidCap(const Context *context, GLenum cap) { @@ -41,15 +109,21 @@ bool ValidCap(const Context *context, GLenum cap) case GL_BLEND: case GL_DITHER: return true; + case GL_PRIMITIVE_RESTART_FIXED_INDEX: case GL_RASTERIZER_DISCARD: return (context->getClientVersion() >= 3); + + case GL_DEBUG_OUTPUT_SYNCHRONOUS: + case GL_DEBUG_OUTPUT: + return context->getExtensions().debug; + default: return false; } } -bool ValidTextureTarget(const Context *context, GLenum target) +bool ValidTextureTarget(const ValidationContext *context, GLenum target) { switch (target) { @@ -66,11 +140,37 @@ bool ValidTextureTarget(const Context *context, GLenum target) } } +bool ValidTexture2DTarget(const ValidationContext *context, GLenum target) +{ + switch (target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: + return true; + + default: + return false; + } +} + +bool ValidTexture3DTarget(const ValidationContext *context, GLenum target) +{ + switch (target) + { + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + return (context->getClientVersion() >= 3); + + default: + return false; + } +} + // This function differs from ValidTextureTarget in that the target must be // usable as the destination of a 2D operation-- so a cube face is valid, but // GL_TEXTURE_CUBE_MAP is not. // Note: duplicate of IsInternalTextureTarget -bool ValidTexture2DDestinationTarget(const Context *context, GLenum target) +bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target) { switch (target) { @@ -82,9 +182,18 @@ bool ValidTexture2DDestinationTarget(const Context *context, GLenum target) case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: return true; - case GL_TEXTURE_2D_ARRAY: + default: + return false; + } +} + +bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target) +{ + switch (target) + { case GL_TEXTURE_3D: - return (context->getClientVersion() >= 3); + case GL_TEXTURE_2D_ARRAY: + return true; default: return false; } @@ -114,7 +223,7 @@ bool ValidBufferTarget(const Context *context, GLenum target) case GL_PIXEL_PACK_BUFFER: case GL_PIXEL_UNPACK_BUFFER: - return context->getExtensions().pixelBufferObject; + return (context->getExtensions().pixelBufferObject || context->getClientVersion() >= 3); case GL_COPY_READ_BUFFER: case GL_COPY_WRITE_BUFFER: @@ -129,55 +238,79 @@ bool ValidBufferTarget(const Context *context, GLenum target) bool ValidBufferParameter(const Context *context, GLenum pname) { + const Extensions &extensions = context->getExtensions(); + switch (pname) { case GL_BUFFER_USAGE: case GL_BUFFER_SIZE: return true; + case GL_BUFFER_ACCESS_OES: + return extensions.mapBuffer; + + case GL_BUFFER_MAPPED: + static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal."); + return (context->getClientVersion() >= 3) || extensions.mapBuffer || extensions.mapBufferRange; + // GL_BUFFER_MAP_POINTER is a special case, and may only be // queried with GetBufferPointerv case GL_BUFFER_ACCESS_FLAGS: - case GL_BUFFER_MAPPED: case GL_BUFFER_MAP_OFFSET: case GL_BUFFER_MAP_LENGTH: - return (context->getClientVersion() >= 3); + return (context->getClientVersion() >= 3) || extensions.mapBufferRange; default: return false; } } -bool ValidMipLevel(const Context *context, GLenum target, GLint level) +bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level) { + const auto &caps = context->getCaps(); size_t maxDimension = 0; switch (target) { - case GL_TEXTURE_2D: maxDimension = context->getCaps().max2DTextureSize; break; + case GL_TEXTURE_2D: + maxDimension = caps.max2DTextureSize; + break; case GL_TEXTURE_CUBE_MAP: case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxDimension = context->getCaps().maxCubeMapTextureSize; break; - case GL_TEXTURE_3D: maxDimension = context->getCaps().max3DTextureSize; break; - case GL_TEXTURE_2D_ARRAY: maxDimension = context->getCaps().max2DTextureSize; break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + maxDimension = caps.maxCubeMapTextureSize; + break; + case GL_TEXTURE_3D: + maxDimension = caps.max3DTextureSize; + break; + case GL_TEXTURE_2D_ARRAY: + maxDimension = caps.max2DTextureSize; + break; default: UNREACHABLE(); } - return level <= gl::log2(maxDimension); + return level <= gl::log2(static_cast(maxDimension)); } -bool ValidImageSize(const Context *context, GLenum target, GLint level, - GLsizei width, GLsizei height, GLsizei depth) +bool ValidImageSizeParameters(const Context *context, + GLenum target, + GLint level, + GLsizei width, + GLsizei height, + GLsizei depth, + bool isSubImage) { if (level < 0 || width < 0 || height < 0 || depth < 0) { return false; } - if (!context->getExtensions().textureNPOT && + // TexSubImage parameters can be NPOT without textureNPOT extension, + // as long as the destination texture is POT. + if (!isSubImage && !context->getExtensions().textureNPOT && (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))) { return false; @@ -191,7 +324,28 @@ bool ValidImageSize(const Context *context, GLenum target, GLint level, return true; } -bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height) +bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat) +{ + // List of compressed format that require that the texture size is smaller than or a multiple of + // the compressed block size. + switch (internalFormat) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: + return true; + + default: + return false; + } +} + +bool ValidCompressedImageSize(const ValidationContext *context, + GLenum internalFormat, + GLsizei width, + GLsizei height) { const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); if (!formatInfo.compressed) @@ -199,12 +353,22 @@ bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLs return false; } - if (width < 0 || (static_cast(width) > formatInfo.compressedBlockWidth && width % formatInfo.compressedBlockWidth != 0) || - height < 0 || (static_cast(height) > formatInfo.compressedBlockHeight && height % formatInfo.compressedBlockHeight != 0)) + if (width < 0 || height < 0) { return false; } + if (CompressedTextureFormatRequiresExactSize(internalFormat)) + { + if ((static_cast(width) > formatInfo.compressedBlockWidth && + width % formatInfo.compressedBlockWidth != 0) || + (static_cast(height) > formatInfo.compressedBlockHeight && + height % formatInfo.compressedBlockHeight != 0)) + { + return false; + } + } + return true; } @@ -220,33 +384,57 @@ bool ValidQueryType(const Context *context, GLenum queryType) return true; case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return (context->getClientVersion() >= 3); + case GL_TIME_ELAPSED_EXT: + return context->getExtensions().disjointTimerQuery; default: return false; } } -bool ValidProgram(Context *context, GLuint id) +Program *GetValidProgram(Context *context, GLuint id) { // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the // error INVALID_VALUE if the provided name is not the name of either a shader or program object and // INVALID_OPERATION if the provided name identifies an object that is not the expected type." - if (context->getProgram(id) != NULL) - { - return true; - } - else if (context->getShader(id) != NULL) + Program *validProgram = context->getProgram(id); + + if (!validProgram) { - // ID is the wrong type - context->recordError(Error(GL_INVALID_OPERATION)); - return false; + if (context->getShader(id)) + { + context->recordError( + Error(GL_INVALID_OPERATION, "Expected a program name, but found a shader name")); + } + else + { + context->recordError(Error(GL_INVALID_VALUE, "Program name is not valid")); + } } - else + + return validProgram; +} + +Shader *GetValidShader(Context *context, GLuint id) +{ + // See ValidProgram for spec details. + + Shader *validShader = context->getShader(id); + + if (!validShader) { - // No shader/program object has this ID - context->recordError(Error(GL_INVALID_VALUE)); - return false; + if (context->getProgram(id)) + { + context->recordError( + Error(GL_INVALID_OPERATION, "Expected a shader name, but found a program name")); + } + else + { + context->recordError(Error(GL_INVALID_VALUE, "Shader name is invalid")); + } } + + return validShader; } bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment) @@ -343,9 +531,9 @@ bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum tar ASSERT(samples == 0 || context->getExtensions().framebufferMultisample); // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal - // to MAX_SAMPLES_ANGLE (Context::getExtensions().maxSamples) otherwise GL_INVALID_VALUE is + // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is // generated. - if (static_cast(samples) > context->getExtensions().maxSamples) + if (static_cast(samples) > context->getCaps().maxSamples) { context->recordError(Error(GL_INVALID_VALUE)); return false; @@ -354,11 +542,15 @@ bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum tar // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create // the specified storage. This is different than ES 3.0 in which a sample number higher // than the maximum sample number supported by this format generates a GL_INVALID_VALUE. - const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); - if (static_cast(samples) > formatCaps.getMaxSamples()) + // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3. + if (context->getClientVersion() >= 3) { - context->recordError(Error(GL_OUT_OF_MEMORY)); - return false; + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (static_cast(samples) > formatCaps.getMaxSamples()) + { + context->recordError(Error(GL_OUT_OF_MEMORY)); + return false; + } } return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height); @@ -374,11 +566,11 @@ bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum targ } gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); - if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) + ASSERT(framebuffer); + if (framebuffer->id() == 0) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments")); return false; } @@ -403,44 +595,23 @@ bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum targ return true; } -static bool IsPartialBlit(gl::Context *context, gl::FramebufferAttachment *readBuffer, gl::FramebufferAttachment *writeBuffer, - GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) -{ - if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || - dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() || - srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight()) - { - return true; - } - else if (context->getState().isScissorTestEnabled()) - { - const Rectangle &scissor = context->getState().getScissor(); - - return scissor.x > 0 || scissor.y > 0 || - scissor.width < writeBuffer->getWidth() || - scissor.height < writeBuffer->getHeight(); - } - else - { - return false; - } -} - -bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, - GLenum filter, bool fromAngleExtension) +bool ValidateBlitFramebufferParameters(gl::Context *context, + GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter) { switch (filter) { case GL_NEAREST: break; case GL_LINEAR: - if (fromAngleExtension) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } break; default: context->recordError(Error(GL_INVALID_ENUM)); @@ -460,13 +631,6 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint return false; } - if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)) - { - ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."); - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the // color buffer, leaving only nearest being unfiltered from above if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST) @@ -477,17 +641,12 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id()) { - if (fromAngleExtension) - { - ERR("Blits with the same source and destination framebuffer are not supported by this " - "implementation."); - } context->recordError(Error(GL_INVALID_OPERATION)); return false; } - gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); - gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); + const gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); + const gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); if (!readFramebuffer || !drawFramebuffer) { @@ -517,39 +676,68 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (mask & GL_COLOR_BUFFER_BIT) { - gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer(); - gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); + const gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer(); + const gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); + const Extensions &extensions = context->getExtensions(); if (readColorBuffer && drawColorBuffer) { GLenum readInternalFormat = readColorBuffer->getInternalFormat(); const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat); - for (GLuint i = 0; i < context->getCaps().maxColorAttachments; i++) + for (size_t drawbufferIdx = 0; + drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx) { - if (drawFramebuffer->isEnabledColorAttachment(i)) + const FramebufferAttachment *attachment = + drawFramebuffer->getDrawBuffer(drawbufferIdx); + if (attachment) { - GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getInternalFormat(); + GLenum drawInternalFormat = attachment->getInternalFormat(); const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat); // The GL ES 3.0.2 spec (pg 193) states that: // 1) If the read buffer is fixed point format, the draw buffer must be as well // 2) If the read buffer is an unsigned integer format, the draw buffer must be as well // 3) If the read buffer is a signed integer format, the draw buffer must be as well - if ( (readFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || readFormatInfo.componentType == GL_SIGNED_NORMALIZED) && - !(drawFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || drawFormatInfo.componentType == GL_SIGNED_NORMALIZED)) + // Changes with EXT_color_buffer_float: + // Case 1) is changed to fixed point OR floating point + GLenum readComponentType = readFormatInfo.componentType; + GLenum drawComponentType = drawFormatInfo.componentType; + bool readFixedPoint = (readComponentType == GL_UNSIGNED_NORMALIZED || + readComponentType == GL_SIGNED_NORMALIZED); + bool drawFixedPoint = (drawComponentType == GL_UNSIGNED_NORMALIZED || + drawComponentType == GL_SIGNED_NORMALIZED); + + if (extensions.colorBufferFloat) { - context->recordError(Error(GL_INVALID_OPERATION)); + bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT); + bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT); + + if (readFixedOrFloat != drawFixedOrFloat) + { + context->recordError(Error(GL_INVALID_OPERATION, + "If the read buffer contains fixed-point or " + "floating-point values, the draw buffer " + "must as well.")); + return false; + } + } + else if (readFixedPoint != drawFixedPoint) + { + context->recordError(Error(GL_INVALID_OPERATION, + "If the read buffer contains fixed-point " + "values, the draw buffer must as well.")); return false; } - if (readFormatInfo.componentType == GL_UNSIGNED_INT && drawFormatInfo.componentType != GL_UNSIGNED_INT) + if (readComponentType == GL_UNSIGNED_INT && + drawComponentType != GL_UNSIGNED_INT) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - if (readFormatInfo.componentType == GL_INT && drawFormatInfo.componentType != GL_INT) + if (readComponentType == GL_INT && drawComponentType != GL_INT) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -568,53 +756,6 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint context->recordError(Error(GL_INVALID_OPERATION)); return false; } - - if (fromAngleExtension) - { - FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer(); - if (!readColorAttachment || - (!(readColorAttachment->type() == GL_TEXTURE && readColorAttachment->getTextureImageIndex()->type == GL_TEXTURE_2D) && - readColorAttachment->type() != GL_RENDERBUFFER && - readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - for (GLuint colorAttachment = 0; colorAttachment < context->getCaps().maxColorAttachments; ++colorAttachment) - { - if (drawFramebuffer->isEnabledColorAttachment(colorAttachment)) - { - FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment); - ASSERT(attachment); - - if (!(attachment->type() == GL_TEXTURE && attachment->getTextureImageIndex()->type == GL_TEXTURE_2D) && - attachment->type() != GL_RENDERBUFFER && - attachment->type() != GL_FRAMEBUFFER_DEFAULT) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - - // Return an error if the destination formats do not match - if (attachment->getInternalFormat() != readColorBuffer->getInternalFormat()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - } - - int readSamples = readFramebuffer->getSamples(context->getData()); - - if (readSamples != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer, - srcX0, srcY0, srcX1, srcY1, - dstX0, dstY0, dstX1, dstY1)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } } } @@ -624,8 +765,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint { if (mask & masks[i]) { - gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]); - gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]); + const gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]); + const gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]); if (readBuffer && drawBuffer) { @@ -640,23 +781,6 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint context->recordError(Error(GL_INVALID_OPERATION)); return false; } - - if (fromAngleExtension) - { - if (IsPartialBlit(context, readBuffer, drawBuffer, - srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) - { - ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted - return false; - } - - if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } } } } @@ -886,10 +1010,22 @@ bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname) } } -bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels) +bool ValidateReadPixels(Context *context, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLvoid *pixels) { - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + if (width < 0 || height < 0) + { + context->recordError(Error(GL_INVALID_VALUE, "width and height must be positive")); + return false; + } + + Framebuffer *framebuffer = context->getState().getReadFramebuffer(); ASSERT(framebuffer); if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) @@ -926,35 +1062,99 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize return false; } + return true; +} + +bool ValidateReadnPixelsEXT(Context *context, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLsizei bufSize, + GLvoid *pixels) +{ + if (bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE, "bufSize must be a positive number")); + return false; + } + GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); - GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(), 0); + GLsizei outputPitch = + sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(), + context->getState().getPackRowLength()); // sized query sanity check - if (bufSize) + int requiredSize = outputPitch * height; + if (requiredSize > bufSize) { - int requiredSize = outputPitch * height; - if (requiredSize > *bufSize) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateReadPixels(context, x, y, width, height, format, type, pixels); +} + +bool ValidateGenQueriesBase(gl::Context *context, GLsizei n, const GLuint *ids) +{ + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE, "Query count < 0")); + return false; + } + + return true; +} + +bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids) +{ + if (!context->getExtensions().occlusionQueryBoolean && + !context->getExtensions().disjointTimerQuery) + { + context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled")); + return false; + } + + return ValidateGenQueriesBase(context, n, ids); +} + +bool ValidateDeleteQueriesBase(gl::Context *context, GLsizei n, const GLuint *ids) +{ + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE, "Query count < 0")); + return false; } return true; } -bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) +bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids) +{ + if (!context->getExtensions().occlusionQueryBoolean && + !context->getExtensions().disjointTimerQuery) + { + context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled")); + return false; + } + + return ValidateDeleteQueriesBase(context, n, ids); +} + +bool ValidateBeginQueryBase(gl::Context *context, GLenum target, GLuint id) { if (!ValidQueryType(context, target)) { - context->recordError(Error(GL_INVALID_ENUM)); + context->recordError(Error(GL_INVALID_ENUM, "Invalid query target")); return false; } if (id == 0) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_OPERATION, "Query id is 0")); return false; } @@ -973,9 +1173,12 @@ bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) // b) There are no active queries for the requested target (and in the case // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, // no query may be active for either if glBeginQuery targets either. + + // TODO(ewell): I think this needs to be changed for timer and occlusion queries to work at the + // same time if (context->getState().isQueryActive()) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_OPERATION, "Other query is active")); return false; } @@ -984,45 +1187,219 @@ bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) // check that name was obtained with glGenQueries if (!queryObject) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_OPERATION, "Invalid query id")); return false; } // check for type mismatch if (queryObject->getType() != target) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_OPERATION, "Query type does not match target")); return false; } return true; } -bool ValidateEndQuery(gl::Context *context, GLenum target) +bool ValidateBeginQueryEXT(gl::Context *context, GLenum target, GLuint id) +{ + if (!context->getExtensions().occlusionQueryBoolean && + !context->getExtensions().disjointTimerQuery) + { + context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled")); + return false; + } + + return ValidateBeginQueryBase(context, target, id); +} + +bool ValidateEndQueryBase(gl::Context *context, GLenum target) { if (!ValidQueryType(context, target)) { - context->recordError(Error(GL_INVALID_ENUM)); + context->recordError(Error(GL_INVALID_ENUM, "Invalid query target")); return false; } const Query *queryObject = context->getState().getActiveQuery(target); - if (queryObject == NULL) + if (queryObject == nullptr) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_OPERATION, "Query target not active")); return false; } return true; } -static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType, - GLint location, GLsizei count, LinkedUniform **uniformOut) +bool ValidateEndQueryEXT(gl::Context *context, GLenum target) { - if (count < 0) + if (!context->getExtensions().occlusionQueryBoolean && + !context->getExtensions().disjointTimerQuery) { - context->recordError(Error(GL_INVALID_VALUE)); + context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled")); + return false; + } + + return ValidateEndQueryBase(context, target); +} + +bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target) +{ + if (!context->getExtensions().disjointTimerQuery) + { + context->recordError(Error(GL_INVALID_OPERATION, "Disjoint timer query not enabled")); + return false; + } + + if (target != GL_TIMESTAMP_EXT) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid query target")); + return false; + } + + Query *queryObject = context->getQuery(id, true, target); + if (queryObject == nullptr) + { + context->recordError(Error(GL_INVALID_OPERATION, "Invalid query id")); + return false; + } + + if (context->getState().isQueryActive(queryObject)) + { + context->recordError(Error(GL_INVALID_OPERATION, "Query is active")); + return false; + } + + return true; +} + +bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname) +{ + if (!ValidQueryType(context, target) && target != GL_TIMESTAMP_EXT) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid query type")); + return false; + } + + switch (pname) + { + case GL_CURRENT_QUERY_EXT: + if (target == GL_TIMESTAMP_EXT) + { + context->recordError( + Error(GL_INVALID_ENUM, "Cannot use current query for timestamp")); + return false; + } + break; + case GL_QUERY_COUNTER_BITS_EXT: + if (!context->getExtensions().disjointTimerQuery || + (target != GL_TIMESTAMP_EXT && target != GL_TIME_ELAPSED_EXT)) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid pname")); + return false; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM, "Invalid pname")); + return false; + } + + return true; +} + +bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params) +{ + if (!context->getExtensions().occlusionQueryBoolean && + !context->getExtensions().disjointTimerQuery) + { + context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled")); + return false; + } + + return ValidateGetQueryivBase(context, target, pname); +} + +bool ValidateGetQueryObjectValueBase(Context *context, GLuint id, GLenum pname) +{ + Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + context->recordError(Error(GL_INVALID_OPERATION, "Query does not exist")); + return false; + } + + if (context->getState().isQueryActive(queryObject)) + { + context->recordError(Error(GL_INVALID_OPERATION, "Query currently active")); + return false; + } + + switch (pname) + { + case GL_QUERY_RESULT_EXT: + case GL_QUERY_RESULT_AVAILABLE_EXT: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM, "Invalid pname enum")); + return false; + } + + return true; +} + +bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params) +{ + if (!context->getExtensions().disjointTimerQuery) + { + context->recordError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled")); + return false; + } + return ValidateGetQueryObjectValueBase(context, id, pname); +} + +bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params) +{ + if (!context->getExtensions().disjointTimerQuery && + !context->getExtensions().occlusionQueryBoolean) + { + context->recordError(Error(GL_INVALID_OPERATION, "Query extension not enabled")); + return false; + } + return ValidateGetQueryObjectValueBase(context, id, pname); +} + +bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params) +{ + if (!context->getExtensions().disjointTimerQuery) + { + context->recordError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled")); + return false; + } + return ValidateGetQueryObjectValueBase(context, id, pname); +} + +bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params) +{ + if (!context->getExtensions().disjointTimerQuery) + { + context->recordError(Error(GL_INVALID_OPERATION, "Timer query extension not enabled")); + return false; + } + return ValidateGetQueryObjectValueBase(context, id, pname); +} + +static bool ValidateUniformCommonBase(gl::Context *context, + GLenum targetUniformType, + GLint location, + GLsizei count, + const LinkedUniform **uniformOut) +{ + if (count < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); return false; } @@ -1045,16 +1422,16 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform return false; } - LinkedUniform *uniform = program->getUniformByLocation(location); + const LinkedUniform &uniform = program->getUniformByLocation(location); // attempting to write an array to a non-array uniform is an INVALID_OPERATION - if (uniform->elementCount() == 1 && count > 1) + if (!uniform.isArray() && count > 1) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - *uniformOut = uniform; + *uniformOut = &uniform; return true; } @@ -1067,7 +1444,7 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G return false; } - LinkedUniform *uniform = NULL; + const LinkedUniform *uniform = nullptr; if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform)) { return false; @@ -1102,7 +1479,7 @@ bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint locati return false; } - LinkedUniform *uniform = NULL; + const LinkedUniform *uniform = nullptr; if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform)) { return false; @@ -1162,7 +1539,7 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, return false; } - FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); + const FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); if (!attachment) { context->recordError(Error(GL_INVALID_OPERATION)); @@ -1184,17 +1561,21 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, return true; } -bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, - GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, - GLint border, GLenum *textureFormatOut) +bool ValidateCopyTexImageParametersBase(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border, + GLenum *textureFormatOut) { - - if (!ValidTexture2DDestinationTarget(context, target)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0) { context->recordError(Error(GL_INVALID_VALUE)); @@ -1219,14 +1600,15 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi return false; } - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); return false; } - if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples(context->getData()) != 0) + const auto &state = context->getState(); + if (state.getReadFramebuffer()->id() != 0 && framebuffer->getSamples(context->getData()) != 0) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1263,14 +1645,15 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi return false; } - gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); + gl::Texture *texture = + state.getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target); if (!texture) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - if (texture->isImmutable() && !isSubImage) + if (texture->getImmutableFormat() && !isSubImage) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -1326,7 +1709,10 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi return true; } -static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsizei maxVertex, GLsizei primcount) +static bool ValidateDrawBase(ValidationContext *context, + GLenum mode, + GLsizei count, + GLsizei primcount) { switch (mode) { @@ -1358,17 +1744,27 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz return false; } - const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); - if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || - state.getStencilRef() != state.getStencilBackRef() || - depthStencilState.stencilMask != depthStencilState.stencilBackMask) + if (context->getLimitations().noSeparateStencilRefsAndMasks) { - // Note: these separate values are not supported in WebGL, due to D3D's limitations. - // See Section 6.10 of the WebGL 1.0 spec - ERR("This ANGLE implementation does not support separate front/back stencil " - "writemasks, reference values, or stencil mask values."); - context->recordError(Error(GL_INVALID_OPERATION)); - return false; + const Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); + const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer(); + GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0; + GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1; + const DepthStencilState &depthStencilState = state.getDepthStencilState(); + if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) != + (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) || + state.getStencilRef() != state.getStencilBackRef() || + (depthStencilState.stencilMask & minimumRequiredStencilMask) != + (depthStencilState.stencilBackMask & minimumRequiredStencilMask)) + { + // Note: these separate values are not supported in WebGL, due to D3D's limitations. See + // Section 6.10 of the WebGL 1.0 spec + ERR( + "This ANGLE implementation does not support separate front/back stencil " + "writemasks, reference values, or stencil mask values."); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } } const gl::Framebuffer *fbo = state.getDrawFramebuffer(); @@ -1391,74 +1787,29 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz return false; } - // Buffer validations - const VertexArray *vao = state.getVertexArray(); - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) - { - const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); - bool attribActive = (program->getSemanticIndex(attributeIndex) != -1); - if (attribActive && attrib.enabled) - { - gl::Buffer *buffer = attrib.buffer.get(); - - if (buffer) - { - GLint64 attribStride = static_cast(ComputeVertexAttributeStride(attrib)); - GLint64 maxVertexElement = 0; - - if (attrib.divisor > 0) - { - maxVertexElement = static_cast(primcount) / static_cast(attrib.divisor); - } - else - { - maxVertexElement = static_cast(maxVertex); - } - - GLint64 attribDataSize = maxVertexElement * attribStride; - - // [OpenGL ES 3.0.2] section 2.9.4 page 40: - // We can return INVALID_OPERATION if our vertex attribute does not have - // enough backing data. - if (attribDataSize > buffer->getSize()) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - else if (attrib.pointer == NULL) - { - // This is an application error that would normally result in a crash, - // but we catch it and return an error - context->recordError(Error(GL_INVALID_OPERATION, "An enabled vertex array has no buffer and no pointer.")); - return false; - } - } - } - // Uniform buffer validation for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++) { - const gl::UniformBlock *uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex); + const gl::UniformBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex); GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex); - const gl::Buffer *uniformBuffer = state.getIndexedUniformBuffer(blockBinding); + const OffsetBindingPointer &uniformBuffer = + state.getIndexedUniformBuffer(blockBinding); - if (!uniformBuffer) + if (uniformBuffer.get() == nullptr) { // undefined behaviour context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer.")); return false; } - size_t uniformBufferSize = state.getIndexedUniformBufferSize(blockBinding); - + size_t uniformBufferSize = uniformBuffer.getSize(); if (uniformBufferSize == 0) { // Bind the whole buffer. - uniformBufferSize = uniformBuffer->getSize(); + uniformBufferSize = static_cast(uniformBuffer->getSize()); } - if (uniformBufferSize < uniformBlock->dataSize) + if (uniformBufferSize < uniformBlock.dataSize) { // undefined behaviour context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.")); @@ -1480,8 +1831,8 @@ bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei coun const State &state = context->getState(); gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused() && - curTransformFeedback->getDrawMode() != mode) + if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused() && + curTransformFeedback->getPrimitiveMode() != mode) { // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode // that does not match the current transform feedback object's draw mode (if transform feedback @@ -1490,7 +1841,12 @@ bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei coun return false; } - if (!ValidateDrawBase(context, mode, count, count, primcount)) + if (!ValidateDrawBase(context, mode, count, primcount)) + { + return false; + } + + if (!ValidateDrawAttribs(context, primcount, count)) { return false; } @@ -1523,11 +1879,10 @@ static bool ValidateDrawInstancedANGLE(Context *context) gl::Program *program = state.getProgram(); const VertexArray *vao = state.getVertexArray(); - for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) { const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex); - bool active = (program->getSemanticIndex(attributeIndex) != -1); - if (active && attrib.divisor == 0) + if (program->isAttribLocationActive(attributeIndex) && attrib.divisor == 0) { return true; } @@ -1548,8 +1903,13 @@ bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first return ValidateDrawArraysInstanced(context, mode, first, count, primcount); } -bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut) +bool ValidateDrawElements(ValidationContext *context, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei primcount, + IndexRange *indexRangeOut) { switch (type) { @@ -1557,7 +1917,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t case GL_UNSIGNED_SHORT: break; case GL_UNSIGNED_INT: - if (!context->getExtensions().elementIndexUint) + if (context->getClientVersion() < 3 && !context->getExtensions().elementIndexUint) { context->recordError(Error(GL_INVALID_ENUM)); return false; @@ -1571,7 +1931,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t const State &state = context->getState(); gl::TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); - if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + if (curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused()) { // It is an invalid operation to call DrawElements, DrawRangeElements or DrawElementsInstanced // while transform feedback is active, (3.0.2, section 2.14, pg 86) @@ -1587,7 +1947,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t } const gl::VertexArray *vao = state.getVertexArray(); - gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); if (!indices && !elementArrayBuffer) { context->recordError(Error(GL_INVALID_OPERATION)); @@ -1623,45 +1983,56 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t return false; } + if (!ValidateDrawBase(context, mode, count, primcount)) + { + return false; + } + // Use max index to validate if our vertex buffers are large enough for the pull. // TODO: offer fast path, with disabled index validation. // TODO: also disable index checking on back-ends that are robust to out-of-range accesses. if (elementArrayBuffer) { uintptr_t offset = reinterpret_cast(indices); - if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut)) + Error error = + elementArrayBuffer->getIndexRange(type, static_cast(offset), count, + state.isPrimitiveRestartEnabled(), indexRangeOut); + if (error.isError()) { - rx::BufferImpl *bufferImpl = elementArrayBuffer->getImplementation(); - const uint8_t *dataPointer = NULL; - Error error = bufferImpl->getData(&dataPointer); - if (error.isError()) - { - context->recordError(error); - return false; - } - - const uint8_t *offsetPointer = dataPointer + offset; - *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count); - elementArrayBuffer->getIndexRangeCache()->addRange(type, offset, count, *indexRangeOut); + context->recordError(error); + return false; } } else { - *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count); + *indexRangeOut = ComputeIndexRange(type, indices, count, state.isPrimitiveRestartEnabled()); } - if (!ValidateDrawBase(context, mode, count, static_cast(indexRangeOut->end), primcount)) + // If we use an index greater than our maximum supported index range, return an error. + // The ES3 spec does not specify behaviour here, it is undefined, but ANGLE should always + // return an error if possible here. + if (static_cast(indexRangeOut->end) >= context->getCaps().maxElementIndex) { + context->recordError(Error(GL_INVALID_OPERATION, g_ExceedsMaxElementErrorMessage)); return false; } - return true; + if (!ValidateDrawAttribs(context, primcount, static_cast(indexRangeOut->end))) + { + return false; + } + + // No op if there are no real indices in the index data (all are primitive restart). + return (indexRangeOut->vertexIndexCount > 0); } bool ValidateDrawElementsInstanced(Context *context, - GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount, - rx::RangeUI *indexRangeOut) + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei primcount, + IndexRange *indexRangeOut) { if (primcount < 0) { @@ -1678,8 +2049,13 @@ bool ValidateDrawElementsInstanced(Context *context, return (primcount > 0); } -bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut) +bool ValidateDrawElementsInstancedANGLE(Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei primcount, + IndexRange *indexRangeOut) { if (!ValidateDrawInstancedANGLE(context)) { @@ -1721,11 +2097,11 @@ bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum atta } const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); + ASSERT(framebuffer); - if (framebufferHandle == 0 || !framebuffer) + if (framebuffer->id() == 0) { - context->recordError(Error(GL_INVALID_OPERATION)); + context->recordError(Error(GL_INVALID_OPERATION, "Cannot change default FBO's attachments")); return false; } @@ -1735,8 +2111,8 @@ bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum atta bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { - // Attachments are required to be bound to level 0 in ES2 - if (context->getClientVersion() < 3 && level != 0) + // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap extension + if (context->getClientVersion() < 3 && !context->getExtensions().fboRenderMipmap && level != 0) { context->recordError(Error(GL_INVALID_VALUE)); return false; @@ -1815,13 +2191,12 @@ bool ValidateGetUniformBase(Context *context, GLuint program, GLint location) return false; } - if (!ValidProgram(context, program)) + gl::Program *programObject = GetValidProgram(context, program); + if (!programObject) { return false; } - gl::Program *programObject = context->getProgram(program); - if (!programObject || !programObject->isLinked()) { context->recordError(Error(GL_INVALID_OPERATION)); @@ -1858,8 +2233,8 @@ static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint loca ASSERT(programObject); // sized queries -- ensure the provided buffer is large enough - LinkedUniform *uniform = programObject->getUniformByLocation(location); - size_t requiredBytes = VariableExternalSize(uniform->type); + const LinkedUniform &uniform = programObject->getUniformByLocation(location); + size_t requiredBytes = VariableExternalSize(uniform.type); if (static_cast(bufSize) < requiredBytes) { context->recordError(Error(GL_INVALID_OPERATION)); @@ -1879,4 +2254,382 @@ bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, return ValidateSizedGetUniform(context, program, location, bufSize); } +bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments, + const GLenum *attachments, bool defaultFramebuffer) +{ + if (numAttachments < 0) + { + context->recordError(Error(GL_INVALID_VALUE, "numAttachments must not be less than zero")); + return false; + } + + for (GLsizei i = 0; i < numAttachments; ++i) + { + if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) + { + if (defaultFramebuffer) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound")); + return false; + } + + if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments) + { + context->recordError(Error(GL_INVALID_OPERATION, + "Requested color attachment is greater than the maximum supported color attachments")); + return false; + } + } + else + { + switch (attachments[i]) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + case GL_DEPTH_STENCIL_ATTACHMENT: + if (defaultFramebuffer) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is bound")); + return false; + } + break; + case GL_COLOR: + case GL_DEPTH: + case GL_STENCIL: + if (!defaultFramebuffer) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment when the default framebuffer is not bound")); + return false; + } + break; + default: + context->recordError(Error(GL_INVALID_ENUM, "Invalid attachment")); + return false; + } + } + } + + return true; +} + +bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker) +{ + // Note that debug marker calls must not set error state + + if (length < 0) + { + return false; + } + + if (marker == nullptr) + { + return false; + } + + return true; +} + +bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker) +{ + // Note that debug marker calls must not set error state + + if (length < 0) + { + return false; + } + + if (length > 0 && marker == nullptr) + { + return false; + } + + return true; } + +bool ValidateEGLImageTargetTexture2DOES(Context *context, + egl::Display *display, + GLenum target, + egl::Image *image) +{ + if (!context->getExtensions().eglImage && !context->getExtensions().eglImageExternal) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + switch (target) + { + case GL_TEXTURE_2D: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM, "invalid texture target.")); + return false; + } + + if (!display->isValidImage(image)) + { + context->recordError(Error(GL_INVALID_VALUE, "EGL image is not valid.")); + return false; + } + + if (image->getSamples() > 0) + { + context->recordError(Error(GL_INVALID_OPERATION, + "cannot create a 2D texture from a multisampled EGL image.")); + return false; + } + + const TextureCaps &textureCaps = context->getTextureCaps().get(image->getInternalFormat()); + if (!textureCaps.texturable) + { + context->recordError(Error(GL_INVALID_OPERATION, + "EGL image internal format is not supported as a texture.")); + return false; + } + + return true; +} + +bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context, + egl::Display *display, + GLenum target, + egl::Image *image) +{ + if (!context->getExtensions().eglImage) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + switch (target) + { + case GL_RENDERBUFFER: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM, "invalid renderbuffer target.")); + return false; + } + + if (!display->isValidImage(image)) + { + context->recordError(Error(GL_INVALID_VALUE, "EGL image is not valid.")); + return false; + } + + const TextureCaps &textureCaps = context->getTextureCaps().get(image->getInternalFormat()); + if (!textureCaps.renderable) + { + context->recordError(Error( + GL_INVALID_OPERATION, "EGL image internal format is not supported as a renderbuffer.")); + return false; + } + + return true; +} + +bool ValidateBindVertexArrayBase(Context *context, GLuint array) +{ + if (!context->isVertexArrayGenerated(array)) + { + // The default VAO should always exist + ASSERT(array != 0); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateDeleteVertexArraysBase(Context *context, GLsizei n) +{ + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + return true; +} + +bool ValidateGenVertexArraysBase(Context *context, GLsizei n) +{ + if (n < 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + return true; +} + +bool ValidateProgramBinaryBase(Context *context, + GLuint program, + GLenum binaryFormat, + const void *binary, + GLint length) +{ + Program *programObject = GetValidProgram(context, program); + if (programObject == nullptr) + { + return false; + } + + const std::vector &programBinaryFormats = context->getCaps().programBinaryFormats; + if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == + programBinaryFormats.end()) + { + context->recordError(Error(GL_INVALID_ENUM, "Program binary format is not valid.")); + return false; + } + + return true; +} + +bool ValidateGetProgramBinaryBase(Context *context, + GLuint program, + GLsizei bufSize, + GLsizei *length, + GLenum *binaryFormat, + void *binary) +{ + Program *programObject = GetValidProgram(context, program); + if (programObject == nullptr) + { + return false; + } + + if (!programObject->isLinked()) + { + context->recordError(Error(GL_INVALID_OPERATION, "Program is not linked.")); + return false; + } + + return true; +} + +bool ValidateCopyTexImage2D(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) +{ + if (context->getClientVersion() < 3) + { + return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0, + 0, x, y, width, height, border); + } + + ASSERT(context->getClientVersion() == 3); + return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0, + 0, x, y, width, height, border); +} + +bool ValidateFramebufferRenderbuffer(Context *context, + GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer) +{ + if (!ValidFramebufferTarget(target) || + (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateFramebufferRenderbufferParameters(context, target, attachment, + renderbuffertarget, renderbuffer); +} + +bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs) +{ + // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS + if (n < 0 || static_cast(n) > context->getCaps().maxDrawBuffers) + { + context->recordError( + Error(GL_INVALID_VALUE, "n must be non-negative and no greater than MAX_DRAW_BUFFERS")); + return false; + } + + ASSERT(context->getState().getDrawFramebuffer()); + GLuint frameBufferId = context->getState().getDrawFramebuffer()->id(); + GLuint maxColorAttachment = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments; + + // This should come first before the check for the default frame buffer + // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM + // rather than INVALID_OPERATION + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + { + const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; + + if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK && + (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0_EXT || + bufs[colorAttachment] >= maxColorAttachment)) + { + // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi + // In the 3.0 specs, the error should return GL_INVALID_OPERATION. + // When we move to 3.1 specs, we should change the error to be GL_INVALID_ENUM + context->recordError(Error(GL_INVALID_OPERATION, "Invalid buffer value")); + return false; + } + else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment && + frameBufferId != 0) + { + // INVALID_OPERATION-GL is bound to buffer and ith argument + // is not COLOR_ATTACHMENTi or NONE + context->recordError( + Error(GL_INVALID_OPERATION, "Ith value does not match COLOR_ATTACHMENTi or NONE")); + return false; + } + } + + // INVALID_OPERATION is generated if GL is bound to the default framebuffer + // and n is not 1 or bufs is bound to value other than BACK and NONE + if (frameBufferId == 0) + { + if (n != 1) + { + context->recordError(Error(GL_INVALID_OPERATION, + "n must be 1 when GL is bound to the default framebuffer")); + return false; + } + + if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) + { + context->recordError(Error( + GL_INVALID_OPERATION, + "Only NONE or BACK are valid values when drawing to the default framebuffer")); + return false; + } + } + + return true; +} + +bool ValidateCopyTexSubImage2D(Context *context, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + if (context->getClientVersion() < 3) + { + return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, + yoffset, x, y, width, height, 0); + } + + return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset, + yoffset, 0, x, y, width, height, 0); +} + +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/validationES.h b/src/3rdparty/angle/src/libANGLE/validationES.h index b0ccd8eecc..5d8486a6ab 100644 --- a/src/3rdparty/angle/src/libANGLE/validationES.h +++ b/src/3rdparty/angle/src/libANGLE/validationES.h @@ -14,22 +14,51 @@ #include #include -namespace gl +namespace egl { +class Display; +class Image; +} +namespace gl +{ class Context; +class Program; +class Shader; +class ValidationContext; bool ValidCap(const Context *context, GLenum cap); -bool ValidTextureTarget(const Context *context, GLenum target); -bool ValidTexture2DDestinationTarget(const Context *context, GLenum target); +bool ValidTextureTarget(const ValidationContext *context, GLenum target); +bool ValidTexture2DTarget(const ValidationContext *context, GLenum target); +bool ValidTexture3DTarget(const ValidationContext *context, GLenum target); +bool ValidTexture2DDestinationTarget(const ValidationContext *context, GLenum target); +bool ValidTexture3DDestinationTarget(const ValidationContext *context, GLenum target); bool ValidFramebufferTarget(GLenum target); bool ValidBufferTarget(const Context *context, GLenum target); bool ValidBufferParameter(const Context *context, GLenum pname); -bool ValidMipLevel(const Context *context, GLenum target, GLint level); -bool ValidImageSize(const Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth); -bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height); +bool ValidMipLevel(const ValidationContext *context, GLenum target, GLint level); +bool ValidImageSizeParameters(const Context *context, + GLenum target, + GLint level, + GLsizei width, + GLsizei height, + GLsizei depth, + bool isSubImage); +bool ValidCompressedImageSize(const ValidationContext *context, + GLenum internalFormat, + GLsizei width, + GLsizei height); bool ValidQueryType(const Context *context, GLenum queryType); -bool ValidProgram(Context *context, GLuint id); + +// Returns valid program if id is a valid program name +// Errors INVALID_OPERATION if valid shader is given and returns NULL +// Errors INVALID_VALUE otherwise and returns NULL +Program *GetValidProgram(Context *context, GLuint id); + +// Returns valid shader if id is a valid shader name +// Errors INVALID_OPERATION if valid program is given and returns NULL +// Errors INVALID_VALUE otherwise and returns NULL +Shader *GetValidShader(Context *context, GLuint id); bool ValidateAttachmentTarget(Context *context, GLenum attachment); bool ValidateRenderbufferStorageParametersBase(Context *context, GLenum target, GLsizei samples, @@ -40,9 +69,17 @@ bool ValidateRenderbufferStorageParametersANGLE(Context *context, GLenum target, bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -bool ValidateBlitFramebufferParameters(Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, - GLenum filter, bool fromAngleExtension); +bool ValidateBlitFramebufferParameters(Context *context, + GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter); bool ValidateGetVertexAttribParameters(Context *context, GLenum pname); @@ -50,11 +87,40 @@ bool ValidateTexParamParameters(Context *context, GLenum pname, GLint param); bool ValidateSamplerObjectParameter(Context *context, GLenum pname); -bool ValidateReadPixelsParameters(Context *context, GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels); - -bool ValidateBeginQuery(Context *context, GLenum target, GLuint id); -bool ValidateEndQuery(Context *context, GLenum target); +bool ValidateReadPixels(Context *context, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLvoid *pixels); +bool ValidateReadnPixelsEXT(Context *context, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLenum format, + GLenum type, + GLsizei bufSize, + GLvoid *pixels); + +bool ValidateGenQueriesBase(gl::Context *context, GLsizei n, const GLuint *ids); +bool ValidateGenQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids); +bool ValidateDeleteQueriesBase(gl::Context *context, GLsizei n, const GLuint *ids); +bool ValidateDeleteQueriesEXT(gl::Context *context, GLsizei n, const GLuint *ids); +bool ValidateBeginQueryBase(Context *context, GLenum target, GLuint id); +bool ValidateBeginQueryEXT(Context *context, GLenum target, GLuint id); +bool ValidateEndQueryBase(Context *context, GLenum target); +bool ValidateEndQueryEXT(Context *context, GLenum target); +bool ValidateQueryCounterEXT(Context *context, GLuint id, GLenum target); +bool ValidateGetQueryivBase(Context *context, GLenum target, GLenum pname); +bool ValidateGetQueryivEXT(Context *context, GLenum target, GLenum pname, GLint *params); +bool ValidateGetQueryObjectValueBase(Context *context, GLenum target, GLenum pname); +bool ValidateGetQueryObjectivEXT(Context *context, GLuint id, GLenum pname, GLint *params); +bool ValidateGetQueryObjectuivEXT(Context *context, GLuint id, GLenum pname, GLuint *params); +bool ValidateGetQueryObjecti64vEXT(Context *context, GLuint id, GLenum pname, GLint64 *params); +bool ValidateGetQueryObjectui64vEXT(Context *context, GLuint id, GLenum pname, GLuint64 *params); bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count); bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, GLsizei count, @@ -62,26 +128,57 @@ bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams); -bool ValidateCopyTexImageParametersBase(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, - GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, - GLint border, GLenum *textureInternalFormatOut); +bool ValidateCopyTexImageParametersBase(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border, + GLenum *textureInternalFormatOut); bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); bool ValidateDrawArraysInstancedANGLE(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); -bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid* indices, GLsizei primcount, rx::RangeUI *indexRangeOut); - -bool ValidateDrawElementsInstanced(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut); -bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount, rx::RangeUI *indexRangeOut); +bool ValidateDrawElements(ValidationContext *context, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei primcount, + IndexRange *indexRangeOut); + +bool ValidateDrawElementsInstanced(Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei primcount, + IndexRange *indexRangeOut); +bool ValidateDrawElementsInstancedANGLE(Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const GLvoid *indices, + GLsizei primcount, + IndexRange *indexRangeOut); bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment, GLuint texture, GLint level); bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +bool ValidateFramebufferRenderbuffer(Context *context, + GLenum target, + GLenum attachment, + GLenum renderbuffertarget, + GLuint renderbuffer); bool ValidateGetUniformBase(Context *context, GLuint program, GLint location); bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params); @@ -89,6 +186,59 @@ bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLin bool ValidateGetnUniformfvEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLfloat* params); bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location, GLsizei bufSize, GLint* params); -} +bool ValidateDiscardFramebufferBase(Context *context, GLenum target, GLsizei numAttachments, + const GLenum *attachments, bool defaultFramebuffer); + +bool ValidateInsertEventMarkerEXT(Context *context, GLsizei length, const char *marker); +bool ValidatePushGroupMarkerEXT(Context *context, GLsizei length, const char *marker); + +bool ValidateEGLImageTargetTexture2DOES(Context *context, + egl::Display *display, + GLenum target, + egl::Image *image); +bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context, + egl::Display *display, + GLenum target, + egl::Image *image); + +bool ValidateBindVertexArrayBase(Context *context, GLuint array); +bool ValidateDeleteVertexArraysBase(Context *context, GLsizei n); +bool ValidateGenVertexArraysBase(Context *context, GLsizei n); + +bool ValidateProgramBinaryBase(Context *context, + GLuint program, + GLenum binaryFormat, + const void *binary, + GLint length); +bool ValidateGetProgramBinaryBase(Context *context, + GLuint program, + GLsizei bufSize, + GLsizei *length, + GLenum *binaryFormat, + void *binary); + +bool ValidateCopyTexImage2D(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border); +bool ValidateDrawBuffersBase(ValidationContext *context, GLsizei n, const GLenum *bufs); +bool ValidateCopyTexSubImage2D(Context *context, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height); + +// Error messages shared here for use in testing. +extern const char *g_ExceedsMaxElementErrorMessage; +} // namespace gl #endif // LIBANGLE_VALIDATION_ES_H_ diff --git a/src/3rdparty/angle/src/libANGLE/validationES2.cpp b/src/3rdparty/angle/src/libANGLE/validationES2.cpp index 9eece1b54a..2e5b955e99 100644 --- a/src/3rdparty/angle/src/libANGLE/validationES2.cpp +++ b/src/3rdparty/angle/src/libANGLE/validationES2.cpp @@ -21,6 +21,42 @@ namespace gl { +namespace +{ + +bool IsPartialBlit(gl::Context *context, + const FramebufferAttachment *readBuffer, + const FramebufferAttachment *writeBuffer, + GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1) +{ + const Extents &writeSize = writeBuffer->getSize(); + const Extents &readSize = readBuffer->getSize(); + + if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width || + dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height) + { + return true; + } + + if (context->getState().isScissorTestEnabled()) + { + const Rectangle &scissor = context->getState().getScissor(); + return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width || + scissor.height < writeSize.height; + } + + return false; +} + +} // anonymous namespace + bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) @@ -31,7 +67,7 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, return false; } - if (!ValidImageSize(context, target, level, width, height, 1)) + if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage)) { context->recordError(Error(GL_INVALID_VALUE)); return false; @@ -110,7 +146,7 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, } else { - if (texture->isImmutable()) + if (texture->getImmutableFormat()) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -124,23 +160,10 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, return false; } - GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat; - const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat); - - if (isCompressed != actualFormatInfo.compressed) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - if (isCompressed) { - if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - + GLenum actualInternalFormat = + isSubImage ? texture->getInternalFormat(target, level) : internalformat; switch (actualInternalFormat) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: @@ -165,8 +188,29 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, return false; } break; + case GL_ETC1_RGB8_OES: + if (!context->getExtensions().compressedETC1RGB8Texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: + if (!context->getExtensions().lossyETCDecode) + { + context->recordError( + Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported")); + return false; + } + break; default: - context->recordError(Error(GL_INVALID_ENUM)); + context->recordError(Error( + GL_INVALID_ENUM, "internalformat is not a supported compressed internal format")); + return false; + } + if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) + { + context->recordError(Error(GL_INVALID_OPERATION)); return false; } } @@ -350,6 +394,33 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, return false; } break; + case GL_ETC1_RGB8_OES: + if (context->getExtensions().compressedETC1RGB8Texture) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: + if (context->getExtensions().lossyETCDecode) + { + context->recordError( + Error(GL_INVALID_OPERATION, + "ETC1_RGB8_LOSSY_DECODE_ANGLE can't work with this type.")); + return false; + } + else + { + context->recordError( + Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported.")); + return false; + } + break; case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_OES: if (!context->getExtensions().depthTextures) @@ -395,21 +466,34 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, return true; } - - -bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, - GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, +bool ValidateES2CopyTexImageParameters(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, GLint border) { GLenum textureInternalFormat = GL_NONE; + if (!ValidTexture2DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid texture target")); + return false; + } + if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat)) { return false; } - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + const gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat(); const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat); GLenum textureFormat = internalFormatInfo.format; @@ -502,6 +586,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + case GL_ETC1_RGB8_OES: + case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: context->recordError(Error(GL_INVALID_OPERATION)); return false; case GL_DEPTH_COMPONENT: @@ -642,6 +728,32 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le return false; } break; + case GL_ETC1_RGB8_OES: + if (context->getExtensions().compressedETC1RGB8Texture) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + else + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: + if (context->getExtensions().lossyETCDecode) + { + context->recordError(Error(GL_INVALID_OPERATION, + "ETC1_RGB8_LOSSY_DECODE_ANGLE can't be copied to.")); + return false; + } + else + { + context->recordError( + Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported.")); + return false; + } + break; case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT32_OES: @@ -759,6 +871,21 @@ bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei le return false; } break; + case GL_ETC1_RGB8_OES: + if (!context->getExtensions().compressedETC1RGB8Texture) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + break; + case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE: + if (!context->getExtensions().lossyETCDecode) + { + context->recordError( + Error(GL_INVALID_ENUM, "ANGLE_lossy_etc_decode extension is not supported.")); + return false; + } + break; case GL_RGBA32F_EXT: case GL_RGB32F_EXT: case GL_ALPHA32F_EXT: @@ -824,7 +951,7 @@ bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei le return false; } - if (texture->isImmutable()) + if (texture->getImmutableFormat()) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -879,4 +1006,751 @@ bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type) return true; } +bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments, + const GLenum *attachments) +{ + if (!context->getExtensions().discardFramebuffer) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + bool defaultFramebuffer = false; + + switch (target) + { + case GL_FRAMEBUFFER: + defaultFramebuffer = (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0); + break; + default: + context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target")); + return false; + } + + return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer); +} + +bool ValidateBindVertexArrayOES(Context *context, GLuint array) +{ + if (!context->getExtensions().vertexArrayObject) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + return ValidateBindVertexArrayBase(context, array); +} + +bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n) +{ + if (!context->getExtensions().vertexArrayObject) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + return ValidateDeleteVertexArraysBase(context, n); +} + +bool ValidateGenVertexArraysOES(Context *context, GLsizei n) +{ + if (!context->getExtensions().vertexArrayObject) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + return ValidateGenVertexArraysBase(context, n); +} + +bool ValidateIsVertexArrayOES(Context *context) +{ + if (!context->getExtensions().vertexArrayObject) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + return true; +} + +bool ValidateProgramBinaryOES(Context *context, + GLuint program, + GLenum binaryFormat, + const void *binary, + GLint length) +{ + if (!context->getExtensions().getProgramBinary) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length); +} + +bool ValidateGetProgramBinaryOES(Context *context, + GLuint program, + GLsizei bufSize, + GLsizei *length, + GLenum *binaryFormat, + void *binary) +{ + if (!context->getExtensions().getProgramBinary) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary); +} + +static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication) +{ + switch (source) + { + case GL_DEBUG_SOURCE_API: + case GL_DEBUG_SOURCE_SHADER_COMPILER: + case GL_DEBUG_SOURCE_WINDOW_SYSTEM: + case GL_DEBUG_SOURCE_OTHER: + // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted + return !mustBeThirdPartyOrApplication; + + case GL_DEBUG_SOURCE_THIRD_PARTY: + case GL_DEBUG_SOURCE_APPLICATION: + return true; + + default: + return false; + } +} + +static bool ValidDebugType(GLenum type) +{ + switch (type) + { + case GL_DEBUG_TYPE_ERROR: + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: + case GL_DEBUG_TYPE_PERFORMANCE: + case GL_DEBUG_TYPE_PORTABILITY: + case GL_DEBUG_TYPE_OTHER: + case GL_DEBUG_TYPE_MARKER: + case GL_DEBUG_TYPE_PUSH_GROUP: + case GL_DEBUG_TYPE_POP_GROUP: + return true; + + default: + return false; + } +} + +static bool ValidDebugSeverity(GLenum severity) +{ + switch (severity) + { + case GL_DEBUG_SEVERITY_HIGH: + case GL_DEBUG_SEVERITY_MEDIUM: + case GL_DEBUG_SEVERITY_LOW: + case GL_DEBUG_SEVERITY_NOTIFICATION: + return true; + + default: + return false; + } +} + +bool ValidateDebugMessageControlKHR(Context *context, + GLenum source, + GLenum type, + GLenum severity, + GLsizei count, + const GLuint *ids, + GLboolean enabled) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + if (!ValidDebugSource(source, false) && source != GL_DONT_CARE) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source.")); + return false; + } + + if (!ValidDebugType(type) && type != GL_DONT_CARE) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type.")); + return false; + } + + if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity.")); + return false; + } + + if (count > 0) + { + if (source == GL_DONT_CARE || type == GL_DONT_CARE) + { + context->recordError(Error( + GL_INVALID_OPERATION, + "If count is greater than zero, source and severity cannot be GL_DONT_CARE.")); + return false; + } + + if (severity != GL_DONT_CARE) + { + context->recordError( + Error(GL_INVALID_OPERATION, + "If count is greater than zero, severity must be GL_DONT_CARE.")); + return false; + } + } + + return true; +} + +bool ValidateDebugMessageInsertKHR(Context *context, + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar *buf) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + if (!context->getState().getDebug().isOutputEnabled()) + { + // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do + // not generate an error. + return false; + } + + if (!ValidDebugSeverity(severity)) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid debug severity.")); + return false; + } + + if (!ValidDebugType(type)) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid debug type.")); + return false; + } + + if (!ValidDebugSource(source, true)) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source.")); + return false; + } + + size_t messageLength = (length < 0) ? strlen(buf) : length; + if (messageLength > context->getExtensions().maxDebugMessageLength) + { + context->recordError( + Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.")); + return false; + } + + return true; +} + +bool ValidateDebugMessageCallbackKHR(Context *context, + GLDEBUGPROCKHR callback, + const void *userParam) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + return true; +} + +bool ValidateGetDebugMessageLogKHR(Context *context, + GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + if (bufSize < 0 && messageLog != nullptr) + { + context->recordError( + Error(GL_INVALID_VALUE, "bufSize must be positive if messageLog is not null.")); + return false; + } + + return true; +} + +bool ValidatePushDebugGroupKHR(Context *context, + GLenum source, + GLuint id, + GLsizei length, + const GLchar *message) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + if (!ValidDebugSource(source, true)) + { + context->recordError(Error(GL_INVALID_ENUM, "Invalid debug source.")); + return false; + } + + size_t messageLength = (length < 0) ? strlen(message) : length; + if (messageLength > context->getExtensions().maxDebugMessageLength) + { + context->recordError( + Error(GL_INVALID_VALUE, "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.")); + return false; + } + + size_t currentStackSize = context->getState().getDebug().getGroupStackDepth(); + if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth) + { + context->recordError( + Error(GL_STACK_OVERFLOW, + "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.")); + return false; + } + + return true; +} + +bool ValidatePopDebugGroupKHR(Context *context) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + size_t currentStackSize = context->getState().getDebug().getGroupStackDepth(); + if (currentStackSize <= 1) + { + context->recordError(Error(GL_STACK_UNDERFLOW, "Cannot pop the default debug group.")); + return false; + } + + return true; +} + +static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name) +{ + switch (identifier) + { + case GL_BUFFER: + if (context->getBuffer(name) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid buffer.")); + return false; + } + return true; + + case GL_SHADER: + if (context->getShader(name) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid shader.")); + return false; + } + return true; + + case GL_PROGRAM: + if (context->getProgram(name) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid program.")); + return false; + } + return true; + + case GL_VERTEX_ARRAY: + if (context->getVertexArray(name) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid vertex array.")); + return false; + } + return true; + + case GL_QUERY: + if (context->getQuery(name) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid query.")); + return false; + } + return true; + + case GL_TRANSFORM_FEEDBACK: + if (context->getTransformFeedback(name) == nullptr) + { + context->recordError( + Error(GL_INVALID_VALUE, "name is not a valid transform feedback.")); + return false; + } + return true; + + case GL_SAMPLER: + if (context->getSampler(name) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sampler.")); + return false; + } + return true; + + case GL_TEXTURE: + if (context->getTexture(name) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid texture.")); + return false; + } + return true; + + case GL_RENDERBUFFER: + if (context->getRenderbuffer(name) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid renderbuffer.")); + return false; + } + return true; + + case GL_FRAMEBUFFER: + if (context->getFramebuffer(name) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid framebuffer.")); + return false; + } + return true; + + default: + context->recordError(Error(GL_INVALID_ENUM, "Invalid identifier.")); + return false; + } + + return true; +} + +bool ValidateObjectLabelKHR(Context *context, + GLenum identifier, + GLuint name, + GLsizei length, + const GLchar *label) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + if (!ValidateObjectIdentifierAndName(context, identifier, name)) + { + return false; + } + + size_t labelLength = (length < 0) ? strlen(label) : length; + if (labelLength > context->getExtensions().maxLabelLength) + { + context->recordError( + Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH.")); + return false; + } + + return true; +} + +bool ValidateGetObjectLabelKHR(Context *context, + GLenum identifier, + GLuint name, + GLsizei bufSize, + GLsizei *length, + GLchar *label) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + if (bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative.")); + return false; + } + + if (!ValidateObjectIdentifierAndName(context, identifier, name)) + { + return false; + } + + // Can no-op if bufSize is zero. + return bufSize > 0; +} + +static bool ValidateObjectPtrName(Context *context, const void *ptr) +{ + if (context->getFenceSync(reinterpret_cast(const_cast(ptr))) == nullptr) + { + context->recordError(Error(GL_INVALID_VALUE, "name is not a valid sync.")); + return false; + } + + return true; +} + +bool ValidateObjectPtrLabelKHR(Context *context, + const void *ptr, + GLsizei length, + const GLchar *label) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + if (!ValidateObjectPtrName(context, ptr)) + { + return false; + } + + size_t labelLength = (length < 0) ? strlen(label) : length; + if (labelLength > context->getExtensions().maxLabelLength) + { + context->recordError( + Error(GL_INVALID_VALUE, "Label length is larger than GL_MAX_LABEL_LENGTH.")); + return false; + } + + return true; +} + +bool ValidateGetObjectPtrLabelKHR(Context *context, + const void *ptr, + GLsizei bufSize, + GLsizei *length, + GLchar *label) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + if (bufSize < 0) + { + context->recordError(Error(GL_INVALID_VALUE, "bufSize cannot be negative.")); + return false; + } + + if (!ValidateObjectPtrName(context, ptr)) + { + return false; + } + + // Can no-op if bufSize is zero. + return bufSize > 0; +} + +bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params) +{ + if (!context->getExtensions().debug) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not enabled")); + return false; + } + + // TODO: represent this in Context::getQueryParameterInfo. + switch (pname) + { + case GL_DEBUG_CALLBACK_FUNCTION: + case GL_DEBUG_CALLBACK_USER_PARAM: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM, "Invalid pname.")); + return false; + } + + return true; +} + +bool ValidateBlitFramebufferANGLE(Context *context, + GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter) +{ + if (!context->getExtensions().framebufferBlit) + { + context->recordError(Error(GL_INVALID_OPERATION, "Blit extension not available.")); + return false; + } + + if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0) + { + // TODO(jmadill): Determine if this should be available on other implementations. + context->recordError(Error( + GL_INVALID_OPERATION, + "Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.")); + return false; + } + + if (filter == GL_LINEAR) + { + context->recordError(Error(GL_INVALID_ENUM, "Linear blit not supported in this extension")); + return false; + } + + const Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); + const Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); + + if (mask & GL_COLOR_BUFFER_BIT) + { + const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer(); + const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer(); + + if (readColorAttachment && drawColorAttachment) + { + if (!(readColorAttachment->type() == GL_TEXTURE && + readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) && + readColorAttachment->type() != GL_RENDERBUFFER && + readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + for (size_t drawbufferIdx = 0; + drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx) + { + const FramebufferAttachment *attachment = + drawFramebuffer->getDrawBuffer(drawbufferIdx); + if (attachment) + { + if (!(attachment->type() == GL_TEXTURE && + attachment->getTextureImageIndex().type == GL_TEXTURE_2D) && + attachment->type() != GL_RENDERBUFFER && + attachment->type() != GL_FRAMEBUFFER_DEFAULT) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + // Return an error if the destination formats do not match + if (attachment->getInternalFormat() != readColorAttachment->getInternalFormat()) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + } + + int readSamples = readFramebuffer->getSamples(context->getData()); + + if (readSamples != 0 && + IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0, + srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + } + + GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT}; + GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT}; + for (size_t i = 0; i < 2; i++) + { + if (mask & masks[i]) + { + const FramebufferAttachment *readBuffer = + readFramebuffer->getAttachment(attachments[i]); + const FramebufferAttachment *drawBuffer = + drawFramebuffer->getAttachment(attachments[i]); + + if (readBuffer && drawBuffer) + { + if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1)) + { + // only whole-buffer copies are permitted + ERR( + "Only whole-buffer depth and stencil blits are supported by this " + "implementation."); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + } + } + } + + return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, + dstX1, dstY1, mask, filter); +} + +bool ValidateClear(ValidationContext *context, GLbitfield mask) +{ + const Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); + ASSERT(framebufferObject); + + if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) + { + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + return true; +} + +bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs) +{ + if (!context->getExtensions().drawBuffers) + { + context->recordError(Error(GL_INVALID_OPERATION, "Extension not supported.")); + return false; + } + + return ValidateDrawBuffersBase(context, n, bufs); } + +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/validationES2.h b/src/3rdparty/angle/src/libANGLE/validationES2.h index b9c1fd3bc4..1b2cf13f60 100644 --- a/src/3rdparty/angle/src/libANGLE/validationES2.h +++ b/src/3rdparty/angle/src/libANGLE/validationES2.h @@ -10,18 +10,28 @@ #define LIBANGLE_VALIDATION_ES2_H_ #include +#include namespace gl { - class Context; +class ValidationContext; bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); -bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, - GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, +bool ValidateES2CopyTexImageParameters(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, GLint border); bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, @@ -29,6 +39,96 @@ bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei le bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type); -} +bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments, + const GLenum *attachments); + +bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs); + +bool ValidateBindVertexArrayOES(Context *context, GLuint array); +bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n); +bool ValidateGenVertexArraysOES(Context *context, GLsizei n); +bool ValidateIsVertexArrayOES(Context *context); + +bool ValidateProgramBinaryOES(Context *context, + GLuint program, + GLenum binaryFormat, + const void *binary, + GLint length); +bool ValidateGetProgramBinaryOES(Context *context, + GLuint program, + GLsizei bufSize, + GLsizei *length, + GLenum *binaryFormat, + void *binary); + +// GL_KHR_debug +bool ValidateDebugMessageControlKHR(Context *context, + GLenum source, + GLenum type, + GLenum severity, + GLsizei count, + const GLuint *ids, + GLboolean enabled); +bool ValidateDebugMessageInsertKHR(Context *context, + GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar *buf); +bool ValidateDebugMessageCallbackKHR(Context *context, + GLDEBUGPROCKHR callback, + const void *userParam); +bool ValidateGetDebugMessageLogKHR(Context *context, + GLuint count, + GLsizei bufSize, + GLenum *sources, + GLenum *types, + GLuint *ids, + GLenum *severities, + GLsizei *lengths, + GLchar *messageLog); +bool ValidatePushDebugGroupKHR(Context *context, + GLenum source, + GLuint id, + GLsizei length, + const GLchar *message); +bool ValidatePopDebugGroupKHR(Context *context); +bool ValidateObjectLabelKHR(Context *context, + GLenum identifier, + GLuint name, + GLsizei length, + const GLchar *label); +bool ValidateGetObjectLabelKHR(Context *context, + GLenum identifier, + GLuint name, + GLsizei bufSize, + GLsizei *length, + GLchar *label); +bool ValidateObjectPtrLabelKHR(Context *context, + const void *ptr, + GLsizei length, + const GLchar *label); +bool ValidateGetObjectPtrLabelKHR(Context *context, + const void *ptr, + GLsizei bufSize, + GLsizei *length, + GLchar *label); +bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params); +bool ValidateBlitFramebufferANGLE(Context *context, + GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter); + +bool ValidateClear(ValidationContext *context, GLbitfield mask); + +} // namespace gl #endif // LIBANGLE_VALIDATION_ES2_H_ diff --git a/src/3rdparty/angle/src/libANGLE/validationES3.cpp b/src/3rdparty/angle/src/libANGLE/validationES3.cpp index e141bb6ece..e08e5d261b 100644 --- a/src/3rdparty/angle/src/libANGLE/validationES3.cpp +++ b/src/3rdparty/angle/src/libANGLE/validationES3.cpp @@ -131,6 +131,15 @@ ES3FormatCombinationSet BuildES3FormatSet() InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE ); InsertES3FormatCombo(&set, GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE ); InsertES3FormatCombo(&set, GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RG, GL_RG, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_UNSIGNED_BYTE ); + InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT ); + InsertES3FormatCombo(&set, GL_RED, GL_RED, GL_HALF_FLOAT_OES ); + InsertES3FormatCombo(&set, GL_DEPTH_STENCIL, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 ); // Depth stencil formats InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT ); @@ -145,6 +154,8 @@ ES3FormatCombinationSet BuildES3FormatSet() InsertES3FormatCombo(&set, GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE ); // From GL_OES_texture_float + InsertES3FormatCombo(&set, GL_RGBA, GL_RGBA, GL_FLOAT ); + InsertES3FormatCombo(&set, GL_RGB, GL_RGB, GL_FLOAT ); InsertES3FormatCombo(&set, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT ); InsertES3FormatCombo(&set, GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT ); InsertES3FormatCombo(&set, GL_ALPHA, GL_ALPHA, GL_FLOAT ); @@ -186,44 +197,19 @@ ES3FormatCombinationSet BuildES3FormatSet() // From GL_ANGLE_depth_texture InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES ); - // Compressed formats - // From ES 3.0.1 spec, table 3.16 - // | Internal format | Format | Type | - // | | | | - InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE); - - - // From GL_EXT_texture_compression_dxt1 - InsertES3FormatCombo(&set, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE); - InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE); - - // From GL_ANGLE_texture_compression_dxt3 - InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE); - - // From GL_ANGLE_texture_compression_dxt5 - InsertES3FormatCombo(&set, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE); - return set; } static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type) { - // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid - // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d) + // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a + // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE + // error instead of a GL_INVALID_ENUM error. As this validation function is only called in + // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error. const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) { - context->recordError(Error(GL_INVALID_ENUM)); + context->recordError(Error(GL_INVALID_VALUE)); return false; } @@ -276,18 +262,25 @@ static bool ValidateTexImageFormatCombination(gl::Context *context, GLenum inter return true; } -bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, - GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, const GLvoid *pixels) +bool ValidateES3TexImageParametersBase(Context *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isCompressed, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels) { - if (!ValidTexture2DDestinationTarget(context, target)) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - // Validate image size - if (!ValidImageSize(context, target, level, width, height, depth)) + if (!ValidImageSizeParameters(context, target, level, width, height, depth, isSubImage)) { context->recordError(Error(GL_INVALID_VALUE)); return false; @@ -354,7 +347,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, case GL_TEXTURE_2D_ARRAY: if (static_cast(width) > (caps.max2DTextureSize >> level) || static_cast(height) > (caps.max2DTextureSize >> level) || - static_cast(depth) > (caps.maxArrayTextureLayers >> level)) + static_cast(depth) > caps.maxArrayTextureLayers) { context->recordError(Error(GL_INVALID_VALUE)); return false; @@ -373,7 +366,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, return false; } - if (texture->isImmutable() && !isSubImage) + if (texture->getImmutableFormat() && !isSubImage) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -384,13 +377,20 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat); if (isCompressed) { + if (!actualFormatInfo.compressed) + { + context->recordError(Error( + GL_INVALID_ENUM, "internalformat is not a supported compressed internal format.")); + return false; + } + if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - if (!actualFormatInfo.compressed) + if (!actualFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) { context->recordError(Error(GL_INVALID_ENUM)); return false; @@ -511,6 +511,62 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, return true; } +bool ValidateES3TexImage2DParameters(Context *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isCompressed, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels) +{ + if (!ValidTexture2DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed, + isSubImage, xoffset, yoffset, zoffset, width, height, + depth, border, format, type, pixels); +} + +bool ValidateES3TexImage3DParameters(Context *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isCompressed, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels) +{ + if (!ValidTexture3DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed, + isSubImage, xoffset, yoffset, zoffset, width, height, + depth, border, format, type, pixels); +} + struct EffectiveInternalFormatInfo { GLenum mEffectiveFormat; @@ -795,9 +851,19 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen return false; } -bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, - bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, - GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +bool ValidateES3CopyTexImageParametersBase(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) { GLenum textureInternalFormat; if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, @@ -807,7 +873,9 @@ bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint le return false; } - gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + const auto &state = context->getState(); + const gl::Framebuffer *framebuffer = state.getReadFramebuffer(); + GLuint readFramebufferID = framebuffer->id(); if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE) { @@ -815,20 +883,19 @@ bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint le return false; } - if (context->getState().getReadFramebuffer()->id() != 0 && - framebuffer->getSamples(context->getData()) != 0) + if (readFramebufferID != 0 && framebuffer->getSamples(context->getData()) != 0) { context->recordError(Error(GL_INVALID_OPERATION)); return false; } - gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer(); + const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer(); GLenum colorbufferInternalFormat = source->getInternalFormat(); if (isSubImage) { if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat, - context->getState().getReadFramebuffer()->id())) + readFramebufferID)) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -837,7 +904,7 @@ bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint le else { if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat, - context->getState().getReadFramebuffer()->id())) + readFramebufferID)) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -848,8 +915,63 @@ bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint le return (width > 0 && height > 0); } -bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, - GLsizei width, GLsizei height, GLsizei depth) +bool ValidateES3CopyTexImage2DParameters(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) +{ + if (!ValidTexture2DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage, + xoffset, yoffset, zoffset, x, y, width, height, + border); +} + +bool ValidateES3CopyTexImage3DParameters(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border) +{ + if (!ValidTexture3DDestinationTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateES3CopyTexImageParametersBase(context, target, level, internalformat, isSubImage, + xoffset, yoffset, zoffset, x, y, width, height, + border); +} + +bool ValidateES3TexStorageParametersBase(Context *context, + GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth) { if (width < 1 || height < 1 || depth < 1 || levels < 1) { @@ -857,7 +979,13 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le return false; } - if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1) + GLsizei maxDim = std::max(width, height); + if (target != GL_TEXTURE_2D_ARRAY) + { + maxDim = std::max(maxDim, depth); + } + + if (levels > gl::log2(maxDim) + 1) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -919,7 +1047,7 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le break; default: - context->recordError(Error(GL_INVALID_ENUM)); + UNREACHABLE(); return false; } @@ -930,7 +1058,7 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le return false; } - if (texture->isImmutable()) + if (texture->getImmutableFormat()) { context->recordError(Error(GL_INVALID_OPERATION)); return false; @@ -952,6 +1080,108 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le return true; } +bool ValidateES3TexStorage2DParameters(Context *context, + GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth) +{ + if (!ValidTexture2DTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width, + height, depth); +} + +bool ValidateES3TexStorage3DParameters(Context *context, + GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth) +{ + if (!ValidTexture3DTarget(context, target)) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateES3TexStorageParametersBase(context, target, levels, internalformat, width, + height, depth); +} + +bool ValidateGenQueries(gl::Context *context, GLsizei n, const GLuint *ids) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0")); + return false; + } + + return ValidateGenQueriesBase(context, n, ids); +} + +bool ValidateDeleteQueries(gl::Context *context, GLsizei n, const GLuint *ids) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0")); + return false; + } + + return ValidateDeleteQueriesBase(context, n, ids); +} + +bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0")); + return false; + } + + return ValidateBeginQueryBase(context, target, id); +} + +bool ValidateEndQuery(gl::Context *context, GLenum target) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0")); + return false; + } + + return ValidateEndQueryBase(context, target); +} + +bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0")); + return false; + } + + return ValidateGetQueryivBase(context, target, pname); +} + +bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION, "GLES version < 3.0")); + return false; + } + + return ValidateGetQueryObjectValueBase(context, id, pname); +} + bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { @@ -1132,9 +1362,15 @@ bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum targe return true; } -bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, - const GLenum* attachments) +bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments, + const GLenum *attachments) { + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION, "Operation only supported on ES 3.0 and above")); + return false; + } + bool defaultFramebuffer = false; switch (target) @@ -1147,59 +1383,14 @@ bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GL defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0; break; default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - for (int i = 0; i < numAttachments; ++i) - { - if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) - { - if (defaultFramebuffer) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - - if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments) - { - context->recordError(Error(GL_INVALID_OPERATION)); - return false; - } - } - else - { - switch (attachments[i]) - { - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - case GL_DEPTH_STENCIL_ATTACHMENT: - if (defaultFramebuffer) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - case GL_COLOR: - case GL_DEPTH: - case GL_STENCIL: - if (!defaultFramebuffer) - { - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - break; - default: - context->recordError(Error(GL_INVALID_ENUM)); - return false; - } - } + context->recordError(Error(GL_INVALID_ENUM, "Invalid framebuffer target")); + return false; } - return true; + return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments, defaultFramebuffer); } -bool ValidateClearBuffer(Context *context) +bool ValidateClearBuffer(ValidationContext *context) { if (context->getClientVersion() < 3) { @@ -1279,4 +1470,315 @@ bool ValidateReadBuffer(Context *context, GLenum src) return true; } +bool ValidateCompressedTexImage3D(Context *context, + GLenum target, + GLint level, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLsizei imageSize, + const GLvoid *data) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (imageSize < 0 || + static_cast(imageSize) != + formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + + // 3D texture target validation + if (target != GL_TEXTURE_3D && target != GL_TEXTURE_2D_ARRAY) + { + context->recordError( + Error(GL_INVALID_ENUM, "Must specify a valid 3D texture destination target")); + return false; + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImage3DParameters(context, target, level, internalformat, true, false, 0, 0, + 0, width, height, depth, border, GL_NONE, GL_NONE, data)) + { + return false; + } + + return true; } + +bool ValidateBindVertexArray(Context *context, GLuint array) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateBindVertexArrayBase(context, array); +} + +bool ValidateDeleteVertexArrays(Context *context, GLsizei n) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateDeleteVertexArraysBase(context, n); +} + +bool ValidateGenVertexArrays(Context *context, GLsizei n) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateGenVertexArraysBase(context, n); +} + +bool ValidateIsVertexArray(Context *context) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return true; +} + +bool ValidateProgramBinary(Context *context, + GLuint program, + GLenum binaryFormat, + const void *binary, + GLint length) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length); +} + +bool ValidateGetProgramBinary(Context *context, + GLuint program, + GLsizei bufSize, + GLsizei *length, + GLenum *binaryFormat, + void *binary) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary); +} + +bool ValidateProgramParameter(Context *context, GLuint program, GLenum pname, GLint value) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + if (GetValidProgram(context, program) == nullptr) + { + return false; + } + + switch (pname) + { + case GL_PROGRAM_BINARY_RETRIEVABLE_HINT: + break; + + default: + context->recordError(Error(GL_INVALID_ENUM, "Invalid pname: 0x%X", pname)); + return false; + } + + return true; +} + +bool ValidateBlitFramebuffer(Context *context, + GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, + dstX1, dstY1, mask, filter); +} + +bool ValidateClearBufferiv(ValidationContext *context, + GLenum buffer, + GLint drawbuffer, + const GLint *value) +{ + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || + static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + case GL_STENCIL: + if (drawbuffer != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateClearBuffer(context); +} + +bool ValidateClearBufferuiv(ValidationContext *context, + GLenum buffer, + GLint drawbuffer, + const GLuint *value) +{ + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || + static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateClearBuffer(context); +} + +bool ValidateClearBufferfv(ValidationContext *context, + GLenum buffer, + GLint drawbuffer, + const GLfloat *value) +{ + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || + static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + case GL_DEPTH: + if (drawbuffer != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateClearBuffer(context); +} + +bool ValidateClearBufferfi(ValidationContext *context, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil) +{ + switch (buffer) + { + case GL_DEPTH_STENCIL: + if (drawbuffer != 0) + { + context->recordError(Error(GL_INVALID_VALUE)); + return false; + } + break; + + default: + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + + return ValidateClearBuffer(context); +} + +bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION, "Context does not support GLES3.")); + return false; + } + + return ValidateDrawBuffersBase(context, n, bufs); +} + +bool ValidateCopyTexSubImage3D(Context *context, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height) +{ + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; + } + + return ValidateES3CopyTexImage3DParameters(context, target, level, GL_NONE, true, xoffset, + yoffset, zoffset, x, y, width, height, 0); +} + +} // namespace gl diff --git a/src/3rdparty/angle/src/libANGLE/validationES3.h b/src/3rdparty/angle/src/libANGLE/validationES3.h index 517cb5d27f..7bc657790a 100644 --- a/src/3rdparty/angle/src/libANGLE/validationES3.h +++ b/src/3rdparty/angle/src/libANGLE/validationES3.h @@ -13,19 +13,145 @@ namespace gl { - class Context; - -bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, - GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, const GLvoid *pixels); - -bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, - bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, - GLsizei width, GLsizei height, GLint border); - -bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, - GLsizei width, GLsizei height, GLsizei depth); +class ValidationContext; + +bool ValidateES3TexImageParametersBase(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isCompressed, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels); + +bool ValidateES3TexStorageParameters(Context *context, + GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth); + +bool ValidateES3TexImage2DParameters(Context *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isCompressed, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels); + +bool ValidateES3TexImage3DParameters(Context *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isCompressed, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLenum format, + GLenum type, + const GLvoid *pixels); + +bool ValidateES3CopyTexImageParametersBase(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border); + +bool ValidateES3CopyTexImage2DParameters(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border); + +bool ValidateES3CopyTexImage3DParameters(ValidationContext *context, + GLenum target, + GLint level, + GLenum internalformat, + bool isSubImage, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height, + GLint border); + +bool ValidateES3TexStorageParametersBase(Context *context, + GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth); + +bool ValidateES3TexStorage2DParameters(Context *context, + GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth); + +bool ValidateES3TexStorage3DParameters(Context *context, + GLenum target, + GLsizei levels, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth); + +bool ValidateGenQueries(Context *context, GLsizei n, const GLuint *ids); + +bool ValidateDeleteQueries(Context *context, GLsizei n, const GLuint *ids); + +bool ValidateBeginQuery(Context *context, GLenum target, GLuint id); + +bool ValidateEndQuery(Context *context, GLenum target); + +bool ValidateGetQueryiv(Context *context, GLenum target, GLenum pname, GLint *params); + +bool ValidateGetQueryObjectuiv(Context *context, GLuint id, GLenum pname, GLuint *params); bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); @@ -35,15 +161,83 @@ bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum form bool ValidateES3RenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, - const GLenum* attachments); +bool ValidateInvalidateFramebuffer(Context *context, GLenum target, GLsizei numAttachments, + const GLenum *attachments); -bool ValidateClearBuffer(Context *context); +bool ValidateClearBuffer(ValidationContext *context); bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params); bool ValidateReadBuffer(Context *context, GLenum mode); -} +bool ValidateCompressedTexImage3D(Context *context, + GLenum target, + GLint level, + GLenum internalformat, + GLsizei width, + GLsizei height, + GLsizei depth, + GLint border, + GLsizei imageSize, + const GLvoid *data); + +bool ValidateBindVertexArray(Context *context, GLuint array); +bool ValidateDeleteVertexArrays(Context *context, GLsizei n); +bool ValidateGenVertexArrays(Context *context, GLsizei n); +bool ValidateIsVertexArray(Context *context); + +bool ValidateProgramBinary(Context *context, + GLuint program, + GLenum binaryFormat, + const void *binary, + GLint length); +bool ValidateGetProgramBinary(Context *context, + GLuint program, + GLsizei bufSize, + GLsizei *length, + GLenum *binaryFormat, + void *binary); +bool ValidateProgramParameter(Context *context, GLuint program, GLenum pname, GLint value); +bool ValidateBlitFramebuffer(Context *context, + GLint srcX0, + GLint srcY0, + GLint srcX1, + GLint srcY1, + GLint dstX0, + GLint dstY0, + GLint dstX1, + GLint dstY1, + GLbitfield mask, + GLenum filter); +bool ValidateClearBufferiv(ValidationContext *context, + GLenum buffer, + GLint drawbuffer, + const GLint *value); +bool ValidateClearBufferuiv(ValidationContext *context, + GLenum buffer, + GLint drawbuffer, + const GLuint *value); +bool ValidateClearBufferfv(ValidationContext *context, + GLenum buffer, + GLint drawbuffer, + const GLfloat *value); +bool ValidateClearBufferfi(ValidationContext *context, + GLenum buffer, + GLint drawbuffer, + GLfloat depth, + GLint stencil); +bool ValidateDrawBuffers(ValidationContext *context, GLsizei n, const GLenum *bufs); +bool ValidateCopyTexSubImage3D(Context *context, + GLenum target, + GLint level, + GLint xoffset, + GLint yoffset, + GLint zoffset, + GLint x, + GLint y, + GLsizei width, + GLsizei height); + +} // namespace gl #endif // LIBANGLE_VALIDATION_ES3_H_ -- cgit v1.2.3