From 0a7aebadfbb3534284546aa3ca8612314c08f136 Mon Sep 17 00:00:00 2001 From: Miguel Costa Date: Tue, 26 Jun 2018 16:56:45 +0200 Subject: Update ANGLE to chromium/3280 Change-Id: I0802c0d7486f772d361f87a544d6c5af937f4ca1 Reviewed-by: Friedemann Kleint --- .../src/libANGLE/renderer/d3d/d3d11/Blit11.cpp | 2486 ++++++++---- .../angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h | 230 +- .../src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp | 1379 ++++--- .../src/libANGLE/renderer/d3d/d3d11/Buffer11.h | 174 +- .../src/libANGLE/renderer/d3d/d3d11/Clear11.cpp | 1152 +++--- .../src/libANGLE/renderer/d3d/d3d11/Clear11.h | 105 +- .../src/libANGLE/renderer/d3d/d3d11/Context11.cpp | 405 ++ .../src/libANGLE/renderer/d3d/d3d11/Context11.h | 155 + .../renderer/d3d/d3d11/DebugAnnotator11.cpp | 47 +- .../libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h | 6 +- .../src/libANGLE/renderer/d3d/d3d11/Fence11.cpp | 107 +- .../src/libANGLE/renderer/d3d/d3d11/Fence11.h | 11 +- .../libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp | 461 ++- .../libANGLE/renderer/d3d/d3d11/Framebuffer11.h | 78 +- .../src/libANGLE/renderer/d3d/d3d11/Image11.cpp | 591 +-- .../src/libANGLE/renderer/d3d/d3d11/Image11.h | 67 +- .../libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp | 62 +- .../libANGLE/renderer/d3d/d3d11/IndexBuffer11.h | 23 +- .../renderer/d3d/d3d11/InputLayoutCache.cpp | 464 +-- .../libANGLE/renderer/d3d/d3d11/InputLayoutCache.h | 142 +- .../src/libANGLE/renderer/d3d/d3d11/NativeWindow.h | 97 - .../libANGLE/renderer/d3d/d3d11/NativeWindow11.h | 38 + .../renderer/d3d/d3d11/PixelTransfer11.cpp | 205 +- .../libANGLE/renderer/d3d/d3d11/PixelTransfer11.h | 34 +- .../renderer/d3d/d3d11/ProgramPipeline11.cpp | 24 + .../renderer/d3d/d3d11/ProgramPipeline11.h | 27 + .../src/libANGLE/renderer/d3d/d3d11/Query11.cpp | 363 +- .../src/libANGLE/renderer/d3d/d3d11/Query11.h | 47 +- .../renderer/d3d/d3d11/RenderStateCache.cpp | 521 +-- .../libANGLE/renderer/d3d/d3d11/RenderStateCache.h | 137 +- .../libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp | 359 +- .../libANGLE/renderer/d3d/d3d11/RenderTarget11.h | 90 +- .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 4140 ++++++++++---------- .../src/libANGLE/renderer/d3d/d3d11/Renderer11.h | 573 +-- .../renderer/d3d/d3d11/ResourceManager11.cpp | 533 +++ .../renderer/d3d/d3d11/ResourceManager11.h | 366 ++ .../renderer/d3d/d3d11/ShaderExecutable11.cpp | 111 +- .../renderer/d3d/d3d11/ShaderExecutable11.h | 45 +- .../libANGLE/renderer/d3d/d3d11/StateManager11.cpp | 2817 +++++++++++-- .../libANGLE/renderer/d3d/d3d11/StateManager11.h | 484 ++- .../renderer/d3d/d3d11/StreamProducerNV12.cpp | 102 + .../renderer/d3d/d3d11/StreamProducerNV12.h | 44 + .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 756 ++-- .../src/libANGLE/renderer/d3d/d3d11/SwapChain11.h | 123 +- .../renderer/d3d/d3d11/TextureStorage11.cpp | 3713 +++++++++--------- .../libANGLE/renderer/d3d/d3d11/TextureStorage11.h | 555 ++- .../renderer/d3d/d3d11/TransformFeedback11.cpp | 124 + .../renderer/d3d/d3d11/TransformFeedback11.h | 60 + .../src/libANGLE/renderer/d3d/d3d11/Trim11.cpp | 9 +- .../angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h | 4 +- .../libANGLE/renderer/d3d/d3d11/VertexArray11.cpp | 413 ++ .../libANGLE/renderer/d3d/d3d11/VertexArray11.h | 82 +- .../libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp | 149 +- .../libANGLE/renderer/d3d/d3d11/VertexBuffer11.h | 25 +- .../src/libANGLE/renderer/d3d/d3d11/copyvertex.inl | 45 +- .../renderer/d3d/d3d11/dxgi_format_data.json | 118 + .../renderer/d3d/d3d11/dxgi_format_map_autogen.cpp | 516 +++ .../renderer/d3d/d3d11/dxgi_support_data.json | 623 +-- .../renderer/d3d/d3d11/dxgi_support_table.cpp | 1902 +++++++-- .../renderer/d3d/d3d11/dxgi_support_table.h | 5 + .../libANGLE/renderer/d3d/d3d11/formatutils11.cpp | 1142 +++--- .../libANGLE/renderer/d3d/d3d11/formatutils11.h | 56 +- .../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 | 2667 ++++++++----- .../libANGLE/renderer/d3d/d3d11/renderer11_utils.h | 375 +- .../renderer/d3d/d3d11/shaders/Clear11.hlsl | 644 ++- .../renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl | 131 + .../d3d/d3d11/shaders/Passthrough2D11.hlsl | 11 + .../d3d/d3d11/shaders/ResolveDepthStencil.hlsl | 56 + .../shaders/compiled/passthroughrgba2dms11ps.h | 155 + .../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 | 1199 +++--- .../renderer/d3d/d3d11/texture_format_map.json | 78 + .../renderer/d3d/d3d11/texture_format_table.cpp | 35 + .../renderer/d3d/d3d11/texture_format_table.h | 89 +- .../d3d/d3d11/texture_format_table_autogen.cpp | 3037 +++++++------- .../d3d/d3d11/texture_format_table_utils.h | 85 + .../renderer/d3d/d3d11/win32/NativeWindow.cpp | 220 -- .../d3d/d3d11/win32/NativeWindow11Win32.cpp | 217 + .../renderer/d3d/d3d11/win32/NativeWindow11Win32.h | 53 + .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 67 +- .../d3d/d3d11/winrt/CoreWindowNativeWindow.h | 48 +- .../d3d/d3d11/winrt/InspectableNativeWindow.cpp | 131 +- .../d3d/d3d11/winrt/InspectableNativeWindow.h | 38 +- .../d3d/d3d11/winrt/NativeWindow11WinRT.cpp | 126 + .../renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h | 51 + .../d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp | 63 +- .../d3d/d3d11/winrt/SwapChainPanelNativeWindow.h | 10 +- 95 files changed, 24668 insertions(+), 18417 deletions(-) create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/gen_load_functions_table.cpp delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h delete 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/shaders/MultiplyAlpha.hlsl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h delete 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_map.json create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h delete mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp create mode 100644 src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11') 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 e951e13408..f032e888f1 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp @@ -10,112 +10,404 @@ #include +#include "common/utilities.h" #include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.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/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" #include "third_party/trace_event/trace_event.h" +namespace rx +{ + +namespace +{ + +// Include inline shaders in the anonymous namespace to make sure no symbols are exported #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrougha2d11ps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_luma_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_lumaalpha_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_pm_rgba_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_luma_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_lumaalpha_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftof_um_rgba_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pm_rgba_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_pt_rgba_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgb_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/multiplyalpha_ftou_um_rgba_ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h" + +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepth11_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvedepthstencil11_vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/resolvestencil11_ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" -namespace rx +void StretchedBlitNearest_RowByRow(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + size_t pixelSize, + const uint8_t *sourceData, + uint8_t *destData) { + int srcHeightSubOne = (sourceArea.height - 1); + size_t copySize = pixelSize * destArea.width; + size_t srcOffset = sourceArea.x * pixelSize; + size_t destOffset = destArea.x * pixelSize; -namespace + for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++) + { + 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 = static_cast( + gl::clamp(sourceArea.y + floor(yPerc * srcHeightSubOne + 0.5f), 0, srcHeightSubOne)); + unsigned int writeRow = y; + + const uint8_t *sourceRow = sourceData + readRow * sourceRowPitch + srcOffset; + uint8_t *destRow = destData + writeRow * destRowPitch + destOffset; + memcpy(destRow, sourceRow, copySize); + } +} + +void StretchedBlitNearest_PixelByPixel(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) { + auto xMax = clippedDestArea.x + clippedDestArea.width; + auto yMax = clippedDestArea.y + clippedDestArea.height; -DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource) + for (int writeRow = clippedDestArea.y; writeRow < yMax; writeRow++) + { + // Interpolate using the original source rectangle to determine which row to sample from + // while clamping to the edges + float yPerc = static_cast(writeRow - destArea.y) / (destArea.height - 1); + float yRounded = floor(yPerc * (sourceArea.height - 1) + 0.5f); + unsigned int readRow = + static_cast(gl::clamp(sourceArea.y + yRounded, 0, sourceSize.height - 1)); + + for (int writeColumn = clippedDestArea.x; writeColumn < xMax; writeColumn++) + { + // Interpolate the original source rectangle to determine which column to sample + // from while clamping to the edges + float xPerc = static_cast(writeColumn - destArea.x) / (destArea.width - 1); + float xRounded = floor(xPerc * (sourceArea.width - 1) + 0.5f); + unsigned int readColumn = static_cast( + gl::clamp(sourceArea.x + xRounded, 0, sourceSize.height - 1)); + + const uint8_t *sourcePixel = + sourceData + readRow * sourceRowPitch + readColumn * srcPixelStride + readOffset; + + uint8_t *destPixel = + destData + writeRow * destRowPitch + writeColumn * destPixelStride + writeOffset; + + memcpy(destPixel, sourcePixel, copySize); + } + } +} + +void StretchedBlitNearest(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clipRect, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) { - ID3D11Texture2D *texture = d3d11::DynamicCastComObject(resource); - if (!texture) + gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); + gl::ClipRectangle(clippedDestArea, clipRect, &clippedDestArea); + + // Determine if entire rows can be copied at once instead of each individual pixel. There + // must be no out of bounds lookups, whole rows copies, and no scale. + if (sourceArea.width == clippedDestArea.width && sourceArea.x >= 0 && + sourceArea.x + sourceArea.width <= sourceSize.width && copySize == srcPixelStride && + copySize == destPixelStride) + { + StretchedBlitNearest_RowByRow(sourceArea, destArea, clippedDestArea, sourceSize, + sourceRowPitch, destRowPitch, srcPixelStride, sourceData, + destData); + } + else { - return DXGI_FORMAT_UNKNOWN; + StretchedBlitNearest_PixelByPixel(sourceArea, destArea, clippedDestArea, sourceSize, + sourceRowPitch, destRowPitch, readOffset, writeOffset, + copySize, srcPixelStride, destPixelStride, sourceData, + destData); } +} - D3D11_TEXTURE2D_DESC desc; - texture->GetDesc(&desc); +using DepthStencilLoader = void(const float *, uint8_t *); - SafeRelease(texture); +void LoadDepth16(const float *source, uint8_t *dest) +{ + uint32_t convertedDepth = gl::floatToNormalized<16, uint32_t>(source[0]); + memcpy(dest, &convertedDepth, 2u); +} - return desc.Format; +void LoadDepth24(const float *source, uint8_t *dest) +{ + uint32_t convertedDepth = gl::floatToNormalized<24, uint32_t>(source[0]); + memcpy(dest, &convertedDepth, 3u); } -ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context, - ID3D11Resource *source, unsigned int subresource, - const gl::Extents &size, unsigned int cpuAccessFlags) +void LoadStencilHelper(const float *source, uint8_t *dest) { - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = size.width; - stagingDesc.Height = size.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = GetTextureFormat(source); - stagingDesc.SampleDesc.Count = 1; - stagingDesc.SampleDesc.Quality = 0; - stagingDesc.Usage = D3D11_USAGE_STAGING; - stagingDesc.CPUAccessFlags = cpuAccessFlags; - stagingDesc.MiscFlags = 0; - stagingDesc.BindFlags = 0; - - ID3D11Texture2D *stagingTexture = nullptr; - HRESULT result = device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture); - if (FAILED(result)) + uint32_t convertedStencil = gl::getShiftedData<8, 0>(static_cast(source[1])); + memcpy(dest, &convertedStencil, 1u); +} + +void LoadStencil8(const float *source, uint8_t *dest) +{ + // STENCIL_INDEX8 is implemented with D24S8, with the depth bits unused. Writes zero for safety. + float zero = 0.0f; + LoadDepth24(&zero, &dest[0]); + LoadStencilHelper(source, &dest[3]); +} + +void LoadDepth24Stencil8(const float *source, uint8_t *dest) +{ + LoadDepth24(source, &dest[0]); + LoadStencilHelper(source, &dest[3]); +} + +void LoadDepth32F(const float *source, uint8_t *dest) +{ + memcpy(dest, source, sizeof(float)); +} + +void LoadDepth32FStencil8(const float *source, uint8_t *dest) +{ + LoadDepth32F(source, &dest[0]); + LoadStencilHelper(source, &dest[4]); +} + +template +void CopyDepthStencil(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) +{ + // No stretching or subregions are supported, only full blits. + ASSERT(sourceArea == destArea); + ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height && + sourceSize.depth == 1); + ASSERT(clippedDestArea.width == sourceSize.width && + clippedDestArea.height == sourceSize.height); + ASSERT(readOffset == 0 && writeOffset == 0); + ASSERT(destArea.x == 0 && destArea.y == 0); + + for (int row = 0; row < destArea.height; ++row) + { + for (int column = 0; column < destArea.width; ++column) + { + ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride; + const float *sourcePixel = reinterpret_cast(sourceData + offset); + + uint8_t *destPixel = destData + row * destRowPitch + column * destPixelStride; + + loader(sourcePixel, destPixel); + } + } +} + +void Depth32FStencil8ToDepth32F(const float *source, float *dest) +{ + *dest = *source; +} + +void Depth24Stencil8ToDepth32F(const uint32_t *source, float *dest) +{ + uint32_t normDepth = source[0] & 0x00FFFFFF; + float floatDepth = gl::normalizedToFloat<24>(normDepth); + *dest = floatDepth; +} + +void BlitD24S8ToD32F(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) +{ + // No stretching or subregions are supported, only full blits. + ASSERT(sourceArea == destArea); + ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height && + sourceSize.depth == 1); + ASSERT(clippedDestArea.width == sourceSize.width && + clippedDestArea.height == sourceSize.height); + ASSERT(readOffset == 0 && writeOffset == 0); + ASSERT(destArea.x == 0 && destArea.y == 0); + + for (int row = 0; row < destArea.height; ++row) { - ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result); - return nullptr; + for (int column = 0; column < destArea.width; ++column) + { + ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride; + const uint32_t *sourcePixel = reinterpret_cast(sourceData + offset); + + float *destPixel = + reinterpret_cast(destData + row * destRowPitch + column * destPixelStride); + + Depth24Stencil8ToDepth32F(sourcePixel, destPixel); + } } +} - context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, nullptr); +void BlitD32FS8ToD32F(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clippedDestArea, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData) +{ + // No stretching or subregions are supported, only full blits. + ASSERT(sourceArea == destArea); + ASSERT(sourceSize.width == sourceArea.width && sourceSize.height == sourceArea.height && + sourceSize.depth == 1); + ASSERT(clippedDestArea.width == sourceSize.width && + clippedDestArea.height == sourceSize.height); + ASSERT(readOffset == 0 && writeOffset == 0); + ASSERT(destArea.x == 0 && destArea.y == 0); + + for (int row = 0; row < destArea.height; ++row) + { + for (int column = 0; column < destArea.width; ++column) + { + ptrdiff_t offset = row * sourceRowPitch + column * srcPixelStride; + const float *sourcePixel = reinterpret_cast(sourceData + offset); + float *destPixel = + reinterpret_cast(destData + row * destRowPitch + column * destPixelStride); - return stagingTexture; + Depth32FStencil8ToDepth32F(sourcePixel, destPixel); + } + } +} + +Blit11::BlitConvertFunction *GetCopyDepthStencilFunction(GLenum internalFormat) +{ + switch (internalFormat) + { + case GL_DEPTH_COMPONENT16: + return &CopyDepthStencil; + case GL_DEPTH_COMPONENT24: + return &CopyDepthStencil; + case GL_DEPTH_COMPONENT32F: + return &CopyDepthStencil; + case GL_STENCIL_INDEX8: + return &CopyDepthStencil; + case GL_DEPTH24_STENCIL8: + return &CopyDepthStencil; + case GL_DEPTH32F_STENCIL8: + return &CopyDepthStencil; + default: + UNREACHABLE(); + return nullptr; + } } -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) +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; @@ -128,37 +420,49 @@ inline void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &s *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height); } -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, +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); + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, + &u2, &v2); - d3d11::PositionTexCoordVertex *vertices = static_cast(outVertices); + d3d11::PositionTexCoordVertex *vertices = + static_cast(outVertices); d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); - *outStride = sizeof(d3d11::PositionTexCoordVertex); + *outStride = sizeof(d3d11::PositionTexCoordVertex); *outVertexCount = 4; - *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; } -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, +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); float x1, y1, x2, y2, u1, v1, u2, v2; - GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, + &u2, &v2); - d3d11::PositionLayerTexCoord3DVertex *vertices = static_cast(outVertices); + d3d11::PositionLayerTexCoord3DVertex *vertices = + static_cast(outVertices); for (int i = 0; i < destSize.depth; i++) { @@ -173,24 +477,38 @@ void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth); } - *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex); + *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex); *outVertexCount = destSize.depth * 6; - *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; } -inline unsigned int GetSwizzleIndex(GLenum swizzle) +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; + 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; @@ -213,30 +531,50 @@ D3D11_BLEND_DESC GetAlphaMaskBlendStateDesc() 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 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 }, +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 +DXGI_FORMAT GetStencilSRVFormat(const d3d11::Format &formatSet) +{ + switch (formatSet.texFormat) + { + case DXGI_FORMAT_R32G8X24_TYPELESS: + return DXGI_FORMAT_X32_TYPELESS_G8X24_UINT; + case DXGI_FORMAT_R24G8_TYPELESS: + return DXGI_FORMAT_X24_TYPELESS_G8_UINT; + default: + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } +} + +} // namespace + +Blit11::Shader::Shader() = default; + +Blit11::Shader::Shader(Shader &&other) = default; + +Blit11::Shader::~Shader() = default; + +Blit11::Shader &Blit11::Shader::operator=(Blit11::Shader &&other) = default; Blit11::Blit11(Renderer11 *renderer) : mRenderer(renderer), mResourcesInitialized(false), - mVertexBuffer(nullptr), - mPointSampler(nullptr), - mLinearSampler(nullptr), - mScissorEnabledRasterizerState(nullptr), - mScissorDisabledRasterizerState(nullptr), - mDepthStencilState(nullptr), + mVertexBuffer(), + mPointSampler(), + mLinearSampler(), + mScissorEnabledRasterizerState(), + mScissorDisabledRasterizerState(), + mDepthStencilState(), mQuad2DIL(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, @@ -254,516 +592,552 @@ Blit11::Blit11(Renderer11 *renderer) 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) + mSwizzleCB(), + mResolveDepthStencilVS(g_VS_ResolveDepthStencil, + ArraySize(g_VS_ResolveDepthStencil), + "Blit11::mResolveDepthStencilVS"), + mResolveDepthPS(g_PS_ResolveDepth, ArraySize(g_PS_ResolveDepth), "Blit11::mResolveDepthPS"), + mResolveDepthStencilPS(g_PS_ResolveDepthStencil, + ArraySize(g_PS_ResolveDepthStencil), + "Blit11::mResolveDepthStencilPS"), + mResolveStencilPS(g_PS_ResolveStencil, + ArraySize(g_PS_ResolveStencil), + "Blit11::mResolveStencilPS"), + mStencilSRV(), + mResolvedDepthStencilRTView() { } 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); + return gl::NoError(); } TRACE_EVENT0("gpu.angle", "Blit11::initResources"); - HRESULT result; - ID3D11Device *device = mRenderer->getDevice(); - D3D11_BUFFER_DESC vbDesc; 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; + 6 * mRenderer->getNativeCaps().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, 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"); + ANGLE_TRY(mRenderer->allocateResource(vbDesc, &mVertexBuffer)); + mVertexBuffer.setDebugName("Blit11 vertex buffer"); D3D11_SAMPLER_DESC pointSamplerDesc; - pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; - pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - pointSamplerDesc.MipLODBias = 0.0f; - pointSamplerDesc.MaxAnisotropy = 0; + pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; + pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.MipLODBias = 0.0f; + pointSamplerDesc.MaxAnisotropy = 0; pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; pointSamplerDesc.BorderColor[0] = 0.0f; pointSamplerDesc.BorderColor[1] = 0.0f; pointSamplerDesc.BorderColor[2] = 0.0f; pointSamplerDesc.BorderColor[3] = 0.0f; - pointSamplerDesc.MinLOD = 0.0f; - pointSamplerDesc.MaxLOD = FLT_MAX; + pointSamplerDesc.MinLOD = 0.0f; + pointSamplerDesc.MaxLOD = FLT_MAX; - 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"); + ANGLE_TRY(mRenderer->allocateResource(pointSamplerDesc, &mPointSampler)); + mPointSampler.setDebugName("Blit11 point sampler"); D3D11_SAMPLER_DESC linearSamplerDesc; - linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - linearSamplerDesc.MipLODBias = 0.0f; - linearSamplerDesc.MaxAnisotropy = 0; + linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.MipLODBias = 0.0f; + linearSamplerDesc.MaxAnisotropy = 0; linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; linearSamplerDesc.BorderColor[0] = 0.0f; linearSamplerDesc.BorderColor[1] = 0.0f; linearSamplerDesc.BorderColor[2] = 0.0f; linearSamplerDesc.BorderColor[3] = 0.0f; - linearSamplerDesc.MinLOD = 0.0f; - linearSamplerDesc.MaxLOD = FLT_MAX; + linearSamplerDesc.MinLOD = 0.0f; + linearSamplerDesc.MaxLOD = FLT_MAX; - 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"); + ANGLE_TRY(mRenderer->allocateResource(linearSamplerDesc, &mLinearSampler)); + mLinearSampler.setDebugName("Blit11 linear sampler"); // Use a rasterizer state that will not cull so that inverted quads will not be culled D3D11_RASTERIZER_DESC rasterDesc; - rasterDesc.FillMode = D3D11_FILL_SOLID; - rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_NONE; rasterDesc.FrontCounterClockwise = FALSE; - rasterDesc.DepthBias = 0; - rasterDesc.SlopeScaledDepthBias = 0.0f; - rasterDesc.DepthBiasClamp = 0.0f; - rasterDesc.DepthClipEnable = TRUE; - rasterDesc.MultisampleEnable = FALSE; + rasterDesc.DepthBias = 0; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.MultisampleEnable = FALSE; rasterDesc.AntialiasedLineEnable = FALSE; 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"); + ANGLE_TRY(mRenderer->allocateResource(rasterDesc, &mScissorEnabledRasterizerState)); + mScissorEnabledRasterizerState.setDebugName("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"); + ANGLE_TRY(mRenderer->allocateResource(rasterDesc, &mScissorDisabledRasterizerState)); + mScissorDisabledRasterizerState.setDebugName("Blit11 no scissoring rasterizer state"); D3D11_DEPTH_STENCIL_DESC depthStencilDesc; - depthStencilDesc.DepthEnable = true; - depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; - depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; - depthStencilDesc.StencilEnable = FALSE; - depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; - depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; - depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.DepthEnable = TRUE; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; - depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - - result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - freeResources(); - return gl::Error(GL_OUT_OF_MEMORY, - "Failed to create blit depth stencil state, HRESULT: 0x%X", result); - } - d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state"); + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + ANGLE_TRY(mRenderer->allocateResource(depthStencilDesc, &mDepthStencilState)); + mDepthStencilState.setDebugName("Blit11 depth stencil state"); D3D11_BUFFER_DESC swizzleBufferDesc; - swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4; - swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC; - swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - swizzleBufferDesc.MiscFlags = 0; + swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4; + swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + swizzleBufferDesc.MiscFlags = 0; swizzleBufferDesc.StructureByteStride = 0; - 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"); + ANGLE_TRY(mRenderer->allocateResource(swizzleBufferDesc, &mSwizzleCB)); + mSwizzleCB.setDebugName("Blit11 swizzle constant buffer"); mResourcesInitialized = true; - return gl::Error(GL_NO_ERROR); -} - -void Blit11::freeResources() -{ - SafeRelease(mVertexBuffer); - SafeRelease(mPointSampler); - SafeRelease(mLinearSampler); - SafeRelease(mScissorEnabledRasterizerState); - SafeRelease(mScissorDisabledRasterizerState); - SafeRelease(mDepthStencilState); - SafeRelease(mSwizzleCB); - - mResourcesInitialized = false; + return gl::NoError(); } // static -Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension) +Blit11::BlitShaderType Blit11::GetBlitShaderType(GLenum destinationFormat, + GLenum sourceFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension) { if (dimension == SHADER_3D) { + ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha); + 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; + 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; + 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) { + ASSERT(!unpackPremultiplyAlpha && !unpackUnmultiplyAlpha); + 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; + 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) + bool floatToIntBlit = + !gl::IsIntegerFormat(sourceFormat) && gl::IsIntegerFormat(destinationFormat); + if (unpackPremultiplyAlpha != unpackUnmultiplyAlpha || floatToIntBlit) { - 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; + switch (destinationFormat) + { + case GL_RGBA: + case GL_BGRA_EXT: + ASSERT(!floatToIntBlit); + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_PREMULTIPLY + : BLITSHADER_2D_RGBAF_UNMULTIPLY; + + case GL_RGB: + case GL_RG: + case GL_RED: + ASSERT(!floatToIntBlit); + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_PREMULTIPLY + : BLITSHADER_2D_RGBF_UNMULTIPLY; + + case GL_RGBA_INTEGER: + if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha) + { + return BLITSHADER_2D_RGBAF_TOUI; + } + else + { + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY + : BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY; + } + + case GL_RGB_INTEGER: + case GL_RG_INTEGER: + case GL_RED_INTEGER: + if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha) + { + return BLITSHADER_2D_RGBF_TOUI; + } + else + { + return unpackPremultiplyAlpha ? BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY + : BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY; + } + case GL_LUMINANCE: + ASSERT(!floatToIntBlit); + return unpackPremultiplyAlpha ? BLITSHADER_2D_LUMAF_PREMULTIPLY + : BLITSHADER_2D_LUMAF_UNMULTIPLY; + case GL_LUMINANCE_ALPHA: + ASSERT(!floatToIntBlit); + return unpackPremultiplyAlpha ? BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY + : BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY; + case GL_ALPHA: + ASSERT(!floatToIntBlit); + return BLITSHADER_2D_ALPHA; + 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; + } } } } // static -Blit11::SwizzleShaderType Blit11::GetSwizzleShaderType(GLenum type, D3D11_SRV_DIMENSION dimensionality) +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: + 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; - } - default: - UNREACHABLE(); - return SWIZZLESHADER_INVALID; } } -Blit11::ShaderSupport Blit11::getShaderSupport(const Shader &shader) +gl::Error Blit11::getShaderSupport(const Shader &shader, Blit11::ShaderSupport *supportOut) { - ID3D11Device *device = mRenderer->getDevice(); - ShaderSupport support; - if (shader.dimension == SHADER_2D) { - support.inputLayout = mQuad2DIL.resolve(device); - support.vertexShader = mQuad2DVS.resolve(device); - support.geometryShader = nullptr; - support.vertexWriteFunction = Write2DVertices; + ANGLE_TRY(mQuad2DIL.resolve(mRenderer)); + ANGLE_TRY(mQuad2DVS.resolve(mRenderer)); + supportOut->inputLayout = &mQuad2DIL.getObj(); + supportOut->vertexShader = &mQuad2DVS.getObj(); + supportOut->geometryShader = nullptr; + supportOut->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; + ANGLE_TRY(mQuad3DIL.resolve(mRenderer)); + ANGLE_TRY(mQuad3DVS.resolve(mRenderer)); + ANGLE_TRY(mQuad3DGS.resolve(mRenderer)); + supportOut->inputLayout = &mQuad2DIL.getObj(); + supportOut->vertexShader = &mQuad3DVS.getObj(); + supportOut->geometryShader = &mQuad3DGS.getObj(); + supportOut->vertexWriteFunction = Write3DVertices; } - return support; + return gl::NoError(); } -gl::Error Blit11::swizzleTexture(ID3D11ShaderResourceView *source, - ID3D11RenderTargetView *dest, +gl::Error Blit11::swizzleTexture(const gl::Context *context, + const d3d11::SharedSRV &source, + const d3d11::RenderTargetView &dest, const gl::Extents &size, - GLenum swizzleRed, - GLenum swizzleGreen, - GLenum swizzleBlue, - GLenum swizzleAlpha) + const gl::SwizzleState &swizzleTarget) { - gl::Error error = initResources(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(initResources()); HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; - source->GetDesc(&sourceSRVDesc); + source.get()->GetDesc(&sourceSRVDesc); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); - const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); + GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format); + if (componentType == GL_NONE) + { + // We're swizzling the depth component of a depth-stencil texture. + switch (sourceSRVDesc.Format) + { + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + componentType = GL_UNSIGNED_NORMALIZED; + break; + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + componentType = GL_FLOAT; + break; + default: + UNREACHABLE(); + break; + } + } GLenum shaderType = GL_NONE; - switch (sourceFormatInfo.componentType) + switch (componentType) { - case GL_UNSIGNED_NORMALIZED: - case GL_SIGNED_NORMALIZED: - case GL_FLOAT: - shaderType = GL_FLOAT; - break; - case GL_INT: - shaderType = GL_INT; - break; - case GL_UNSIGNED_INT: - shaderType = GL_UNSIGNED_INT; - break; - default: - UNREACHABLE(); - break; + case GL_UNSIGNED_NORMALIZED: + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + shaderType = GL_FLOAT; + break; + case GL_INT: + shaderType = GL_INT; + break; + case GL_UNSIGNED_INT: + shaderType = GL_UNSIGNED_INT; + break; + default: + UNREACHABLE(); + break; } const Shader *shader = nullptr; - error = getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getSwizzleShader(shaderType, sourceSRVDesc.ViewDimension, &shader)); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; - result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + result = + deviceContext->Map(mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for swizzle, HRESULT: 0x%X.", result); + return gl::OutOfMemory() << "Failed to map internal vertex buffer for swizzle, " + << gl::FmtHR(result); } - const ShaderSupport &support = getShaderSupport(*shader); + ShaderSupport support; + ANGLE_TRY(getShaderSupport(*shader, &support)); - UINT stride = 0; - UINT startIdx = 0; + UINT stride = 0; UINT drawCount = 0; D3D11_PRIMITIVE_TOPOLOGY topology; gl::Box area(0, 0, 0, size.width, size.height, size.depth); - support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology); + support.vertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, + &topology); - deviceContext->Unmap(mVertexBuffer, 0); + deviceContext->Unmap(mVertexBuffer.get(), 0); // Set constant buffer - result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + result = deviceContext->Map(mSwizzleCB.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal constant buffer for swizzle, HRESULT: 0x%X.", result); + return gl::OutOfMemory() << "Failed to map internal constant buffer for swizzle, " + << gl::FmtHR(result); } - unsigned int *swizzleIndices = reinterpret_cast(mappedResource.pData); - swizzleIndices[0] = GetSwizzleIndex(swizzleRed); - swizzleIndices[1] = GetSwizzleIndex(swizzleGreen); - swizzleIndices[2] = GetSwizzleIndex(swizzleBlue); - swizzleIndices[3] = GetSwizzleIndex(swizzleAlpha); + unsigned int *swizzleIndices = reinterpret_cast(mappedResource.pData); + swizzleIndices[0] = GetSwizzleIndex(swizzleTarget.swizzleRed); + swizzleIndices[1] = GetSwizzleIndex(swizzleTarget.swizzleGreen); + swizzleIndices[2] = GetSwizzleIndex(swizzleTarget.swizzleBlue); + swizzleIndices[3] = GetSwizzleIndex(swizzleTarget.swizzleAlpha); - deviceContext->Unmap(mSwizzleCB, 0); + deviceContext->Unmap(mSwizzleCB.get(), 0); + + StateManager11 *stateManager = mRenderer->getStateManager(); // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0); // Apply constant buffer - deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB); + stateManager->setPixelConstantBuffer(0, &mSwizzleCB); // Apply state - deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); - deviceContext->RSSetState(mScissorDisabledRasterizerState); + stateManager->setSimpleBlendState(nullptr); + stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF); + stateManager->setRasterizerState(&mScissorDisabledRasterizerState); // Apply shaders - deviceContext->IASetInputLayout(support.inputLayout); - deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(support.vertexShader, nullptr, 0); - - deviceContext->PSSetShader(shader->pixelShader, nullptr, 0); - deviceContext->GSSetShader(support.geometryShader, nullptr, 0); + stateManager->setInputLayout(support.inputLayout); + stateManager->setPrimitiveTopology(topology); - // Unset the currently bound shader resource to avoid conflicts - auto stateManager = mRenderer->getStateManager(); - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + stateManager->setDrawShaders(support.vertexShader, support.geometryShader, + &shader->pixelShader); // Apply render target - mRenderer->setOneTimeRenderTarget(dest); + stateManager->setRenderTarget(dest.get(), nullptr); // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - 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 - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + stateManager->setSimpleViewport(size); - // Apply samplers - deviceContext->PSSetSamplers(0, 1, &mPointSampler); + // Apply textures and sampler + stateManager->setSimplePixelTextureAndSampler(source, mPointSampler); // Draw the quad deviceContext->Draw(drawCount, 0); - // Unbind textures and render targets and vertex buffer - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); - - mRenderer->unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = nullptr; - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, +gl::Error Blit11::copyTexture(const gl::Context *context, + const d3d11::SharedSRV &source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, + GLenum sourceFormat, + const d3d11::RenderTargetView &dest, const gl::Box &destArea, const gl::Extents &destSize, const gl::Rectangle *scissor, GLenum destFormat, GLenum filter, - bool maskOffAlpha) + bool maskOffAlpha, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) { - gl::Error error = initResources(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(initResources()); HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); @@ -771,635 +1145,1009 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, // Determine if the source format is a signed integer format, the destFormat will already // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned. D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; - source->GetDesc(&sourceSRVDesc); + source.get()->GetDesc(&sourceSRVDesc); + + GLenum componentType = d3d11::GetComponentType(sourceSRVDesc.Format); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); + ASSERT(componentType != GL_NONE); + ASSERT(componentType != GL_SIGNED_NORMALIZED); + bool isSigned = (componentType == GL_INT); - bool isSigned = (internalFormatInfo.componentType == GL_INT); - ShaderDimension dimension = (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D; + ShaderDimension dimension = + (sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D) ? SHADER_3D : SHADER_2D; const Shader *shader = nullptr; - error = getBlitShader(destFormat, isSigned, dimension, &shader); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getBlitShader(destFormat, sourceFormat, isSigned, unpackPremultiplyAlpha, + unpackUnmultiplyAlpha, dimension, &shader)); - const ShaderSupport &support = getShaderSupport(*shader); + ShaderSupport support; + ANGLE_TRY(getShaderSupport(*shader, &support)); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; - result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + result = + deviceContext->Map(mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result); + return gl::OutOfMemory() << "Failed to map internal vertex buffer for texture copy, " + << gl::FmtHR(result); } - UINT stride = 0; - UINT startIdx = 0; + UINT stride = 0; UINT drawCount = 0; D3D11_PRIMITIVE_TOPOLOGY topology; support.vertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride, &drawCount, &topology); - deviceContext->Unmap(mVertexBuffer, 0); + deviceContext->Unmap(mVertexBuffer.get(), 0); + + StateManager11 *stateManager = mRenderer->getStateManager(); // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0); // Apply state if (maskOffAlpha) { - ID3D11BlendState *blendState = mAlphaMaskBlendState.resolve(mRenderer->getDevice()); - ASSERT(blendState); - deviceContext->OMSetBlendState(blendState, nullptr, 0xFFFFFFF); + ANGLE_TRY(mAlphaMaskBlendState.resolve(mRenderer)); + stateManager->setSimpleBlendState(&mAlphaMaskBlendState.getObj()); } else { - deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); + stateManager->setSimpleBlendState(nullptr); } - deviceContext->OMSetDepthStencilState(nullptr, 0xFFFFFFFF); + stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF); if (scissor) { - D3D11_RECT scissorRect; - scissorRect.left = scissor->x; - scissorRect.right = scissor->x + scissor->width; - scissorRect.top = scissor->y; - scissorRect.bottom = scissor->y + scissor->height; - - deviceContext->RSSetScissorRects(1, &scissorRect); - deviceContext->RSSetState(mScissorEnabledRasterizerState); + stateManager->setSimpleScissorRect(*scissor); + stateManager->setRasterizerState(&mScissorEnabledRasterizerState); } else { - deviceContext->RSSetState(mScissorDisabledRasterizerState); + stateManager->setRasterizerState(&mScissorDisabledRasterizerState); } // Apply shaders - deviceContext->IASetInputLayout(support.inputLayout); - deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(support.vertexShader, nullptr, 0); - - deviceContext->PSSetShader(shader->pixelShader, nullptr, 0); - deviceContext->GSSetShader(support.geometryShader, nullptr, 0); + stateManager->setInputLayout(support.inputLayout); + stateManager->setPrimitiveTopology(topology); - // Unset the currently bound shader resource to avoid conflicts - auto stateManager = mRenderer->getStateManager(); - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + stateManager->setDrawShaders(support.vertexShader, support.geometryShader, + &shader->pixelShader); // Apply render target - mRenderer->setOneTimeRenderTarget(dest); + stateManager->setRenderTarget(dest.get(), nullptr); // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - 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 - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source); - - // Apply samplers - ID3D11SamplerState *sampler = nullptr; + stateManager->setSimpleViewport(destSize); + + // Apply texture and sampler switch (filter) { - case GL_NEAREST: sampler = mPointSampler; break; - case GL_LINEAR: sampler = mLinearSampler; break; - - default: - UNREACHABLE(); - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, unknown blit filter mode."); + case GL_NEAREST: + stateManager->setSimplePixelTextureAndSampler(source, mPointSampler); + break; + case GL_LINEAR: + stateManager->setSimplePixelTextureAndSampler(source, mLinearSampler); + break; + + default: + UNREACHABLE(); + return gl::InternalError() << "Internal error, unknown blit filter mode."; } - deviceContext->PSSetSamplers(0, 1, &sampler); // Draw the quad deviceContext->Draw(drawCount, 0); - // Unbind textures and render targets and vertex buffer - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); - - mRenderer->unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = nullptr; - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit11::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, +gl::Error Blit11::copyStencil(const gl::Context *context, + const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, const gl::Rectangle *scissor) { - return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, - dest, destSubresource, destArea, destSize, - scissor, true); + return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest, + destSubresource, destArea, destSize, scissor, true); } -gl::Error Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, +gl::Error Blit11::copyDepth(const gl::Context *context, + const d3d11::SharedSRV &source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const d3d11::DepthStencilView &dest, + const gl::Box &destArea, + const gl::Extents &destSize, const gl::Rectangle *scissor) { - gl::Error error = initResources(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(initResources()); HRESULT result; ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; - result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + result = + deviceContext->Map(mVertexBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for texture copy, HRESULT: 0x%X.", result); + return gl::OutOfMemory() << "Failed to map internal vertex buffer for texture copy, " + << gl::FmtHR(result); } - UINT stride = 0; - UINT startIdx = 0; + UINT stride = 0; UINT drawCount = 0; D3D11_PRIMITIVE_TOPOLOGY topology; - Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, - &stride, &drawCount, &topology); + Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, &stride, + &drawCount, &topology); - deviceContext->Unmap(mVertexBuffer, 0); + deviceContext->Unmap(mVertexBuffer.get(), 0); + + StateManager11 *stateManager = mRenderer->getStateManager(); // Apply vertex buffer - deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + stateManager->setSingleVertexBuffer(&mVertexBuffer, stride, 0); // Apply state - deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF); + stateManager->setSimpleBlendState(nullptr); + stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF); if (scissor) { - D3D11_RECT scissorRect; - scissorRect.left = scissor->x; - scissorRect.right = scissor->x + scissor->width; - scissorRect.top = scissor->y; - scissorRect.bottom = scissor->y + scissor->height; - - deviceContext->RSSetScissorRects(1, &scissorRect); - deviceContext->RSSetState(mScissorEnabledRasterizerState); + stateManager->setSimpleScissorRect(*scissor); + stateManager->setRasterizerState(&mScissorEnabledRasterizerState); } else { - deviceContext->RSSetState(mScissorDisabledRasterizerState); + stateManager->setRasterizerState(&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"); - } + ANGLE_TRY(mQuad2DIL.resolve(mRenderer)); + ANGLE_TRY(mQuad2DVS.resolve(mRenderer)); + ANGLE_TRY(mDepthPS.resolve(mRenderer)); // Apply shaders - deviceContext->IASetInputLayout(mQuad2DIL.resolve(device)); - deviceContext->IASetPrimitiveTopology(topology); - deviceContext->VSSetShader(quad2DVS, nullptr, 0); + stateManager->setInputLayout(&mQuad2DIL.getObj()); + stateManager->setPrimitiveTopology(topology); - deviceContext->PSSetShader(mDepthPS.resolve(device), nullptr, 0); - deviceContext->GSSetShader(nullptr, nullptr, 0); - - // Unset the currently bound shader resource to avoid conflicts - auto stateManager = mRenderer->getStateManager(); - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); + stateManager->setDrawShaders(&mQuad2DVS.getObj(), nullptr, &mDepthPS.getObj()); // Apply render target - deviceContext->OMSetRenderTargets(0, nullptr, dest); + stateManager->setRenderTarget(nullptr, dest.get()); // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - 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 - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, source); + stateManager->setSimpleViewport(destSize); - // Apply samplers - deviceContext->PSSetSamplers(0, 1, &mPointSampler); + // Apply texture and sampler + stateManager->setSimplePixelTextureAndSampler(source, mPointSampler); // Draw the quad deviceContext->Draw(drawCount, 0); - // Unbind textures and render targets and vertex buffer - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, nullptr); - - mRenderer->unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = nullptr; - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit11::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, +gl::Error Blit11::copyDepthStencil(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, const gl::Rectangle *scissor) { - return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, - dest, destSubresource, destArea, destSize, - scissor, false); + return copyDepthStencilImpl(source, sourceSubresource, sourceArea, sourceSize, dest, + destSubresource, destArea, destSize, scissor, false); } -gl::Error Blit11::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) +gl::Error Blit11::copyDepthStencilImpl(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &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; - } + auto srcDXGIFormat = source.getFormat(); + const auto &srcSizeInfo = d3d11::GetDXGIFormatSizeInfo(srcDXGIFormat); + unsigned int srcPixelSize = srcSizeInfo.pixelBytes; + unsigned int copyOffset = 0; + unsigned int copySize = srcPixelSize; + auto destDXGIFormat = dest.getFormat(); + const auto &destSizeInfo = d3d11::GetDXGIFormatSizeInfo(destDXGIFormat); + unsigned int destPixelSize = destSizeInfo.pixelBytes; - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ASSERT(srcDXGIFormat == destDXGIFormat || destDXGIFormat == DXGI_FORMAT_R32_TYPELESS); - ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ); - // HACK: Create the destination staging buffer as a read/write texture so ID3D11DevicContext::UpdateSubresource can be called - // using it's mapped data as a source - ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE); + if (stencilOnly) + { + const auto &srcFormat = source.getFormatSet().format(); + + // Stencil channel should be right after the depth channel. Some views to depth/stencil + // resources have red channel for depth, in which case the depth channel bit width is in + // redBits. + ASSERT((srcFormat.redBits != 0) != (srcFormat.depthBits != 0)); + GLuint depthBits = srcFormat.redBits + srcFormat.depthBits; + // Known formats have either 24 or 32 bits of depth. + ASSERT(depthBits == 24 || depthBits == 32); + copyOffset = depthBits / 8; + + // Stencil is assumed to be 8-bit - currently this is true for all possible formats. + copySize = 1; + } - if (!sourceStaging || !destStaging) + if (srcDXGIFormat != destDXGIFormat) { - SafeRelease(sourceStaging); - SafeRelease(destStaging); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging textures for depth stencil blit."); + if (srcDXGIFormat == DXGI_FORMAT_R24G8_TYPELESS) + { + ASSERT(sourceArea == destArea && sourceSize == destSize && scissor == nullptr); + return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, + destSubresource, destArea, destSize, scissor, copyOffset, + copyOffset, copySize, srcPixelSize, destPixelSize, + BlitD24S8ToD32F); + } + ASSERT(srcDXGIFormat == DXGI_FORMAT_R32G8X24_TYPELESS); + return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, + destSubresource, destArea, destSize, scissor, copyOffset, copyOffset, + copySize, srcPixelSize, destPixelSize, BlitD32FS8ToD32F); } - DXGI_FORMAT format = GetTextureFormat(source); - ASSERT(format == GetTextureFormat(dest)); + return copyAndConvert(source, sourceSubresource, sourceArea, sourceSize, dest, destSubresource, + destArea, destSize, scissor, copyOffset, copyOffset, copySize, + srcPixelSize, destPixelSize, StretchedBlitNearest); +} - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); - unsigned int pixelSize = dxgiFormatInfo.pixelBytes; - unsigned int copyOffset = 0; - unsigned int copySize = pixelSize; - if (stencilOnly) - { - copyOffset = dxgiFormatInfo.depthBits / 8; - copySize = dxgiFormatInfo.stencilBits / 8; +gl::Error Blit11::copyAndConvertImpl(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &destStaging, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + size_t readOffset, + size_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + BlitConvertFunction *convertFunction) +{ + ANGLE_TRY(initResources()); - // It would be expensive to have non-byte sized stencil sizes since it would - // require reading from the destination, currently there aren't any though. - ASSERT(dxgiFormatInfo.stencilBits % 8 == 0 && - dxgiFormatInfo.depthBits % 8 == 0); - } + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + TextureHelper11 sourceStaging; + ANGLE_TRY_RESULT(mRenderer->createStagingTexture(ResourceType::Texture2D, source.getFormatSet(), + sourceSize, StagingAccess::READ), + sourceStaging); + + deviceContext->CopySubresourceRegion(sourceStaging.get(), 0, 0, 0, 0, source.get(), + sourceSubresource, nullptr); D3D11_MAPPED_SUBRESOURCE sourceMapping; - HRESULT result = deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping); + HRESULT result = deviceContext->Map(sourceStaging.get(), 0, D3D11_MAP_READ, 0, &sourceMapping); if (FAILED(result)) { - SafeRelease(sourceStaging); - SafeRelease(destStaging); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal source staging texture for depth stencil blit, HRESULT: 0x%X.", result); + return gl::OutOfMemory() + << "Failed to map internal source staging texture for depth stencil blit, " + << gl::FmtHR(result); } D3D11_MAPPED_SUBRESOURCE destMapping; - result = deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping); + result = deviceContext->Map(destStaging.get(), 0, D3D11_MAP_WRITE, 0, &destMapping); if (FAILED(result)) { - deviceContext->Unmap(sourceStaging, 0); - SafeRelease(sourceStaging); - SafeRelease(destStaging); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal destination staging texture for depth stencil blit, HRESULT: 0x%X.", result); + deviceContext->Unmap(sourceStaging.get(), 0); + return gl::OutOfMemory() + << "Failed to map internal destination staging texture for depth stencil blit, " + << gl::FmtHR(result); } - gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); - // Clip dest area to the destination size - gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea); + gl::Rectangle clipRect = gl::Rectangle(0, 0, destSize.width, destSize.height); // Clip dest area to the scissor if (scissor) { - gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea); + gl::ClipRectangle(clipRect, *scissor, &clipRect); } - // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is - // no out of bounds lookups required, the entire pixel is copied and no stretching - bool wholeRowCopy = sourceArea.width == clippedDestArea.width && - sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width && - copySize == pixelSize; + convertFunction(sourceArea, destArea, clipRect, sourceSize, sourceMapping.RowPitch, + destMapping.RowPitch, readOffset, writeOffset, copySize, srcPixelStride, + destPixelStride, static_cast(sourceMapping.pData), + static_cast(destMapping.pData)); - for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++) - { - float yPerc = static_cast(y - destArea.y) / (destArea.height - 1); + deviceContext->Unmap(sourceStaging.get(), 0); + deviceContext->Unmap(destStaging.get(), 0); - // Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges - 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) - { - void *sourceRow = reinterpret_cast(sourceMapping.pData) + - readRow * sourceMapping.RowPitch + - sourceArea.x * pixelSize; + return gl::NoError(); +} - void *destRow = reinterpret_cast(destMapping.pData) + - writeRow * destMapping.RowPitch + - destArea.x * pixelSize; +gl::Error Blit11::copyAndConvert(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + size_t readOffset, + size_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + BlitConvertFunction *convertFunction) +{ + ANGLE_TRY(initResources()); - memcpy(destRow, sourceRow, pixelSize * destArea.width); - } - else - { - for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++) - { - float xPerc = static_cast(x - destArea.x) / (destArea.width - 1); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges - unsigned int readColumn = static_cast(gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1)); - unsigned int writeColumn = x; + // HACK: Create the destination staging buffer as a read/write texture so + // ID3D11DevicContext::UpdateSubresource can be called + // using it's mapped data as a source + TextureHelper11 destStaging; + ANGLE_TRY_RESULT(mRenderer->createStagingTexture(ResourceType::Texture2D, dest.getFormatSet(), + destSize, StagingAccess::READ_WRITE), + destStaging); - void *sourcePixel = reinterpret_cast(sourceMapping.pData) + - readRow * sourceMapping.RowPitch + - readColumn * pixelSize + - copyOffset; + deviceContext->CopySubresourceRegion(destStaging.get(), 0, 0, 0, 0, dest.get(), destSubresource, + nullptr); - void *destPixel = reinterpret_cast(destMapping.pData) + - writeRow * destMapping.RowPitch + - writeColumn * pixelSize + - copyOffset; + ANGLE_TRY(copyAndConvertImpl(source, sourceSubresource, sourceArea, sourceSize, destStaging, + destArea, destSize, scissor, readOffset, writeOffset, copySize, + srcPixelStride, destPixelStride, convertFunction)); - memcpy(destPixel, sourcePixel, copySize); - } - } + // Work around timeouts/TDRs in older NVIDIA drivers. + if (mRenderer->getWorkarounds().depthStencilBlitExtraCopy) + { + D3D11_MAPPED_SUBRESOURCE mapped; + deviceContext->Map(destStaging.get(), 0, D3D11_MAP_READ, 0, &mapped); + deviceContext->UpdateSubresource(dest.get(), destSubresource, nullptr, mapped.pData, + mapped.RowPitch, mapped.DepthPitch); + deviceContext->Unmap(destStaging.get(), 0); + } + else + { + deviceContext->CopySubresourceRegion(dest.get(), destSubresource, 0, 0, 0, + destStaging.get(), 0, nullptr); } - // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion - // according to MSDN. - 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, nullptr); - - SafeRelease(sourceStaging); - SafeRelease(destStaging); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void Blit11::addBlitShaderToMap(BlitShaderType blitShaderType, ShaderDimension dimension, ID3D11PixelShader *ps) +gl::Error Blit11::addBlitShaderToMap(BlitShaderType blitShaderType, + ShaderDimension dimension, + const ShaderData &shaderData, + const char *name) { ASSERT(mBlitShaderMap.find(blitShaderType) == mBlitShaderMap.end()); - ASSERT(ps); + + d3d11::PixelShader ps; + ANGLE_TRY(mRenderer->allocateResource(shaderData, &ps)); + ps.setDebugName(name); Shader shader; - shader.dimension = dimension; - shader.pixelShader = ps; + shader.dimension = dimension; + shader.pixelShader = std::move(ps); - mBlitShaderMap[blitShaderType] = shader; + mBlitShaderMap[blitShaderType] = std::move(shader); + return gl::NoError(); } -void Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, ShaderDimension dimension, ID3D11PixelShader *ps) +gl::Error Blit11::addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, + ShaderDimension dimension, + const ShaderData &shaderData, + const char *name) { ASSERT(mSwizzleShaderMap.find(swizzleShaderType) == mSwizzleShaderMap.end()); - ASSERT(ps); + + d3d11::PixelShader ps; + ANGLE_TRY(mRenderer->allocateResource(shaderData, &ps)); + ps.setDebugName(name); Shader shader; - shader.dimension = dimension; - shader.pixelShader = ps; + shader.dimension = dimension; + shader.pixelShader = std::move(ps); - mSwizzleShaderMap[swizzleShaderType] = shader; + mSwizzleShaderMap[swizzleShaderType] = std::move(shader); + return gl::NoError(); } void Blit11::clearShaderMap() { - for (auto &blitShader : mBlitShaderMap) - { - SafeRelease(blitShader.second.pixelShader); - } mBlitShaderMap.clear(); - - for (auto &swizzleShader : mSwizzleShaderMap) - { - SafeRelease(swizzleShader.second.pixelShader); - } mSwizzleShaderMap.clear(); } -gl::Error Blit11::getBlitShader(GLenum destFormat, bool isSigned, ShaderDimension dimension, const Shader **shader) +gl::Error Blit11::getBlitShader(GLenum destFormat, + GLenum sourceFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension, + const Shader **shader) { - BlitShaderType blitShaderType = GetBlitShaderType(destFormat, isSigned, dimension); + BlitShaderType blitShaderType = + GetBlitShaderType(destFormat, sourceFormat, isSigned, unpackPremultiplyAlpha, + unpackUnmultiplyAlpha, dimension); if (blitShaderType == BLITSHADER_INVALID) { - return gl::Error(GL_INVALID_OPERATION, "Internal blit shader type mismatch"); + return gl::InternalError() << "Internal blit shader type mismatch"; } auto blitShaderIt = mBlitShaderMap.find(blitShaderType); if (blitShaderIt != mBlitShaderMap.end()) { *shader = &blitShaderIt->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } 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(); - return gl::Error(GL_INVALID_OPERATION, "Internal error"); + case BLITSHADER_2D_RGBAF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGBA2D), + "Blit11 2D RGBA pixel shader")); + break; + case BLITSHADER_2D_BGRAF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGBA2D), + "Blit11 2D BGRA pixel shader")); + break; + case BLITSHADER_2D_RGBF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGB2D), + "Blit11 2D RGB pixel shader")); + break; + case BLITSHADER_2D_RGF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRG2D), + "Blit11 2D RG pixel shader")); + break; + case BLITSHADER_2D_RF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_PassthroughR2D), + "Blit11 2D R pixel shader")); + break; + case BLITSHADER_2D_ALPHA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_PassthroughA2D), + "Blit11 2D alpha pixel shader")); + break; + case BLITSHADER_2D_LUMA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughLum2D), + "Blit11 2D lum pixel shader")); + break; + case BLITSHADER_2D_LUMAALPHA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughLumAlpha2D), + "Blit11 2D luminance alpha pixel shader")); + break; + case BLITSHADER_2D_RGBAUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGBA2DUI), + "Blit11 2D RGBA UI pixel shader")); + break; + case BLITSHADER_2D_RGBAI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGBA2DI), + "Blit11 2D RGBA I pixel shader")); + break; + case BLITSHADER_2D_RGBUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGB2DUI), + "Blit11 2D RGB UI pixel shader")); + break; + case BLITSHADER_2D_RGBI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRGB2DI), + "Blit11 2D RGB I pixel shader")); + break; + case BLITSHADER_2D_RGUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRG2DUI), + "Blit11 2D RG UI pixel shader")); + break; + case BLITSHADER_2D_RGI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughRG2DI), + "Blit11 2D RG I pixel shader")); + break; + case BLITSHADER_2D_RUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughR2DUI), + "Blit11 2D R UI pixel shader")); + break; + case BLITSHADER_2D_RI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_PassthroughR2DI), + "Blit11 2D R I pixel shader")); + break; + case BLITSHADER_3D_RGBAF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3D), + "Blit11 3D RGBA pixel shader")); + break; + case BLITSHADER_3D_RGBAUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3DUI), + "Blit11 3D UI RGBA pixel shader")); + break; + case BLITSHADER_3D_RGBAI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3DI), + "Blit11 3D I RGBA pixel shader")); + break; + case BLITSHADER_3D_BGRAF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3D), + "Blit11 3D BGRA pixel shader")); + break; + case BLITSHADER_3D_RGBF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGB3D), + "Blit11 3D RGB pixel shader")); + break; + case BLITSHADER_3D_RGBUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGB3DUI), + "Blit11 3D RGB UI pixel shader")); + break; + case BLITSHADER_3D_RGBI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGB3DI), + "Blit11 3D RGB I pixel shader")); + break; + case BLITSHADER_3D_RGF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRG3D), + "Blit11 3D RG pixel shader")); + break; + case BLITSHADER_3D_RGUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRG3DUI), + "Blit11 3D RG UI pixel shader")); + break; + case BLITSHADER_3D_RGI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRG3DI), + "Blit11 3D RG I pixel shader")); + break; + case BLITSHADER_3D_RF: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, ShaderData(g_PS_PassthroughR3D), + "Blit11 3D R pixel shader")); + break; + case BLITSHADER_3D_RUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughR3DUI), + "Blit11 3D R UI pixel shader")); + break; + case BLITSHADER_3D_RI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughR3DI), + "Blit11 3D R I pixel shader")); + break; + case BLITSHADER_3D_ALPHA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughRGBA3D), + "Blit11 3D alpha pixel shader")); + break; + case BLITSHADER_3D_LUMA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughLum3D), + "Blit11 3D luminance pixel shader")); + break; + case BLITSHADER_3D_LUMAALPHA: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_3D, + ShaderData(g_PS_PassthroughLumAlpha3D), + "Blit11 3D luminance alpha pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_PM_RGBA), + "Blit11 2D RGBA premultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_UM_RGBA), + "Blit11 2D RGBA unmultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBF_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_PM_RGB), + "Blit11 2D RGB premultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBF_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_UM_RGB), + "Blit11 2D RGB unmultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_TOUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PT_RGBA), + "Blit11 2D RGBA to uint pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PM_RGBA), + "Blit11 2D RGBA to uint premultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_UM_RGBA), + "Blit11 2D RGBA to uint unmultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBF_TOUI: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PT_RGB), + "Blit11 2D RGB to uint pixel shader")); + break; + + case BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_PM_RGB), + "Blit11 2D RGB to uint premultiply pixel shader")); + break; + + case BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoU_UM_RGB), + "Blit11 2D RGB to uint unmultiply pixel shader")); + break; + case BLITSHADER_2D_LUMAF_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_PM_LUMA), + "Blit11 2D LUMA premultiply pixel shader")); + break; + case BLITSHADER_2D_LUMAF_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, ShaderData(g_PS_FtoF_UM_LUMA), + "Blit11 2D LUMA unmultiply pixel shader")); + break; + case BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_FtoF_PM_LUMAALPHA), + "Blit11 2D LUMAALPHA premultiply pixel shader")); + break; + case BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY: + ANGLE_TRY(addBlitShaderToMap(blitShaderType, SHADER_2D, + ShaderData(g_PS_FtoF_UM_LUMAALPHA), + "Blit11 2D LUMAALPHA unmultiply pixel shader")); + break; + + default: + UNREACHABLE(); + return gl::InternalError() << "Internal error"; } blitShaderIt = mBlitShaderMap.find(blitShaderType); ASSERT(blitShaderIt != mBlitShaderMap.end()); *shader = &blitShaderIt->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Blit11::getSwizzleShader(GLenum type, D3D11_SRV_DIMENSION viewDimension, const Shader **shader) +gl::Error Blit11::getSwizzleShader(GLenum type, + D3D11_SRV_DIMENSION viewDimension, + const Shader **shader) { SwizzleShaderType swizzleShaderType = GetSwizzleShaderType(type, viewDimension); if (swizzleShaderType == SWIZZLESHADER_INVALID) { - return gl::Error(GL_INVALID_OPERATION, "Swizzle shader type not found"); + return gl::InternalError() << "Swizzle shader type not found"; } auto swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType); if (swizzleShaderIt != mSwizzleShaderMap.end()) { *shader = &swizzleShaderIt->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // Swizzling shaders (OpenGL ES 3+) ASSERT(mRenderer->isES3Capable()); - ID3D11Device *device = mRenderer->getDevice(); - switch (swizzleShaderType) { - 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"); + case SWIZZLESHADER_2D_FLOAT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, + ShaderData(g_PS_SwizzleF2D), + "Blit11 2D F swizzle pixel shader")); + break; + case SWIZZLESHADER_2D_UINT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, + ShaderData(g_PS_SwizzleUI2D), + "Blit11 2D UI swizzle pixel shader")); + break; + case SWIZZLESHADER_2D_INT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_2D, + ShaderData(g_PS_SwizzleI2D), + "Blit11 2D I swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_FLOAT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleF2DArray), + "Blit11 2D Cube F swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_UINT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleUI2DArray), + "Blit11 2D Cube UI swizzle pixel shader")); + break; + case SWIZZLESHADER_CUBE_INT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleI2DArray), + "Blit11 2D Cube I swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_FLOAT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleF3D), + "Blit11 3D F swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_UINT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleUI3D), + "Blit11 3D UI swizzle pixel shader")); + break; + case SWIZZLESHADER_3D_INT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleI3D), + "Blit11 3D I swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_FLOAT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleF2DArray), + "Blit11 2D Array F swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_UINT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleUI2DArray), + "Blit11 2D Array UI swizzle pixel shader")); + break; + case SWIZZLESHADER_ARRAY_INT: + ANGLE_TRY(addSwizzleShaderToMap(swizzleShaderType, SHADER_3D, + ShaderData(g_PS_SwizzleI2DArray), + "Blit11 2D Array I swizzle pixel shader")); + break; + default: + UNREACHABLE(); + return gl::InternalError() << "Internal error"; } swizzleShaderIt = mSwizzleShaderMap.find(swizzleShaderType); ASSERT(swizzleShaderIt != mSwizzleShaderMap.end()); *shader = &swizzleShaderIt->second; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } +gl::ErrorOrResult Blit11::resolveDepth(const gl::Context *context, + RenderTarget11 *depth) +{ + ANGLE_TRY(initResources()); + + // Multisampled depth stencil SRVs are not available in feature level 10.0 + ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0); + + const auto &extents = depth->getExtents(); + auto *deviceContext = mRenderer->getDeviceContext(); + auto *stateManager = mRenderer->getStateManager(); + + ANGLE_TRY(initResolveDepthOnly(depth->getFormatSet(), extents)); + + ANGLE_TRY(mResolveDepthStencilVS.resolve(mRenderer)); + ANGLE_TRY(mResolveDepthPS.resolve(mRenderer)); + + // Apply the necessary state changes to the D3D11 immediate device context. + stateManager->setInputLayout(nullptr); + stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr, + &mResolveDepthPS.getObj()); + stateManager->setRasterizerState(nullptr); + stateManager->setDepthStencilState(&mDepthStencilState, 0xFFFFFFFF); + stateManager->setRenderTargets(nullptr, 0, mResolvedDepthDSView.get()); + stateManager->setSimpleBlendState(nullptr); + stateManager->setSimpleViewport(extents); + + // Set the viewport + stateManager->setShaderResourceShared(gl::SAMPLER_PIXEL, 0, &depth->getShaderResourceView()); + + // Trigger the blit on the GPU. + deviceContext->Draw(6, 0); + + return mResolvedDepth; } + +gl::Error Blit11::initResolveDepthOnly(const d3d11::Format &format, const gl::Extents &extents) +{ + if (mResolvedDepth.valid() && extents == mResolvedDepth.getExtents() && + format.texFormat == mResolvedDepth.getFormat()) + { + return gl::NoError(); + } + + D3D11_TEXTURE2D_DESC textureDesc; + textureDesc.Width = extents.width; + textureDesc.Height = extents.height; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = format.texFormat; + textureDesc.SampleDesc.Count = 1; + textureDesc.SampleDesc.Quality = 0; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; + textureDesc.CPUAccessFlags = 0; + textureDesc.MiscFlags = 0; + + ANGLE_TRY(mRenderer->allocateTexture(textureDesc, format, &mResolvedDepth)); + mResolvedDepth.setDebugName("Blit11::mResolvedDepth"); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Flags = 0; + dsvDesc.Format = format.dsvFormat; + dsvDesc.Texture2D.MipSlice = 0; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, mResolvedDepth.get(), &mResolvedDepthDSView)); + mResolvedDepthDSView.setDebugName("Blit11::mResolvedDepthDSView"); + + // Possibly D3D11 bug or undefined behaviour: Clear the DSV so that our first render + // works as expected. Otherwise the results of the first use seem to be incorrect. + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->ClearDepthStencilView(mResolvedDepthDSView.get(), D3D11_CLEAR_DEPTH, 1.0f, 0); + + return gl::NoError(); +} + +gl::Error Blit11::initResolveDepthStencil(const gl::Extents &extents) +{ + // Check if we need to recreate depth stencil view + if (mResolvedDepthStencil.valid() && extents == mResolvedDepthStencil.getExtents()) + { + ASSERT(mResolvedDepthStencil.getFormat() == DXGI_FORMAT_R32G32_FLOAT); + return gl::NoError(); + } + + if (mResolvedDepthStencil.valid()) + { + releaseResolveDepthStencilResources(); + } + + const auto &formatSet = d3d11::Format::Get(GL_RG32F, mRenderer->getRenderer11DeviceCaps()); + + D3D11_TEXTURE2D_DESC textureDesc; + textureDesc.Width = extents.width; + textureDesc.Height = extents.height; + textureDesc.MipLevels = 1; + textureDesc.ArraySize = 1; + textureDesc.Format = formatSet.texFormat; + textureDesc.SampleDesc.Count = 1; + textureDesc.SampleDesc.Quality = 0; + textureDesc.Usage = D3D11_USAGE_DEFAULT; + textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET; + textureDesc.CPUAccessFlags = 0; + textureDesc.MiscFlags = 0; + + ANGLE_TRY(mRenderer->allocateTexture(textureDesc, formatSet, &mResolvedDepthStencil)); + mResolvedDepthStencil.setDebugName("Blit11::mResolvedDepthStencil"); + + ANGLE_TRY(mRenderer->allocateResourceNoDesc(mResolvedDepthStencil.get(), + &mResolvedDepthStencilRTView)); + mResolvedDepthStencilRTView.setDebugName("Blit11::mResolvedDepthStencilRTView"); + + return gl::NoError(); +} + +gl::ErrorOrResult Blit11::resolveStencil(const gl::Context *context, + RenderTarget11 *depthStencil, + bool alsoDepth) +{ + ANGLE_TRY(initResources()); + + // Multisampled depth stencil SRVs are not available in feature level 10.0 + ASSERT(mRenderer->getRenderer11DeviceCaps().featureLevel > D3D_FEATURE_LEVEL_10_0); + + const auto &extents = depthStencil->getExtents(); + + ANGLE_TRY(initResolveDepthStencil(extents)); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + auto *stateManager = mRenderer->getStateManager(); + ID3D11Resource *stencilResource = depthStencil->getTexture().get(); + + // Check if we need to re-create the stencil SRV. + if (mStencilSRV.valid()) + { + ID3D11Resource *priorResource = nullptr; + mStencilSRV.get()->GetResource(&priorResource); + + if (stencilResource != priorResource) + { + mStencilSRV.reset(); + } + + SafeRelease(priorResource); + } + + if (!mStencilSRV.valid()) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srViewDesc; + srViewDesc.Format = GetStencilSRVFormat(depthStencil->getFormatSet()); + srViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + + ANGLE_TRY(mRenderer->allocateResource(srViewDesc, stencilResource, &mStencilSRV)); + mStencilSRV.setDebugName("Blit11::mStencilSRV"); + } + + // Notify the Renderer that all state should be invalidated. + ANGLE_TRY(mResolveDepthStencilVS.resolve(mRenderer)); + + // Resolving the depth buffer works by sampling the depth in the shader using a SRV, then + // writing to the resolved depth buffer using SV_Depth. We can't use this method for stencil + // because SV_StencilRef isn't supported until HLSL 5.1/D3D11.3. + const d3d11::PixelShader *pixelShader = nullptr; + if (alsoDepth) + { + ANGLE_TRY(mResolveDepthStencilPS.resolve(mRenderer)); + pixelShader = &mResolveDepthStencilPS.getObj(); + } + else + { + ANGLE_TRY(mResolveStencilPS.resolve(mRenderer)); + pixelShader = &mResolveStencilPS.getObj(); + } + + // Apply the necessary state changes to the D3D11 immediate device context. + stateManager->setInputLayout(nullptr); + stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + stateManager->setDrawShaders(&mResolveDepthStencilVS.getObj(), nullptr, pixelShader); + stateManager->setRasterizerState(nullptr); + stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF); + stateManager->setRenderTarget(mResolvedDepthStencilRTView.get(), nullptr); + stateManager->setSimpleBlendState(nullptr); + + // Set the viewport + stateManager->setSimpleViewport(extents); + stateManager->setShaderResourceShared(gl::SAMPLER_PIXEL, 0, + &depthStencil->getShaderResourceView()); + stateManager->setShaderResource(gl::SAMPLER_PIXEL, 1, &mStencilSRV); + + // Trigger the blit on the GPU. + deviceContext->Draw(6, 0); + + gl::Box copyBox(0, 0, 0, extents.width, extents.height, 1); + + TextureHelper11 dest; + ANGLE_TRY_RESULT( + mRenderer->createStagingTexture(ResourceType::Texture2D, depthStencil->getFormatSet(), + extents, StagingAccess::READ_WRITE), + dest); + + const auto ©Function = GetCopyDepthStencilFunction(depthStencil->getInternalFormat()); + const auto &dsFormatSet = depthStencil->getFormatSet(); + const auto &dsDxgiInfo = d3d11::GetDXGIFormatSizeInfo(dsFormatSet.texFormat); + + ANGLE_TRY(copyAndConvertImpl(mResolvedDepthStencil, 0, copyBox, extents, dest, copyBox, extents, + nullptr, 0, 0, 0, 8u, dsDxgiInfo.pixelBytes, copyFunction)); + + // Return the resolved depth texture, which the caller must Release. + return dest; +} + +void Blit11::releaseResolveDepthStencilResources() +{ + mStencilSRV.reset(); + mResolvedDepthStencilRTView.reset(); +} + +} // namespace rx 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 906616131e..14078f9db8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h @@ -10,8 +10,9 @@ #define LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ #include "common/angleutils.h" -#include "libANGLE/angletypes.h" #include "libANGLE/Error.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include @@ -26,36 +27,84 @@ class Blit11 : angle::NonCopyable explicit Blit11(Renderer11 *renderer); ~Blit11(); - gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, - GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + gl::Error swizzleTexture(const gl::Context *context, + const d3d11::SharedSRV &source, + const d3d11::RenderTargetView &dest, + const gl::Extents &size, + const gl::SwizzleState &swizzleTarget); - gl::Error copyTexture(ID3D11ShaderResourceView *source, + gl::Error copyTexture(const gl::Context *context, + const d3d11::SharedSRV &source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11RenderTargetView *dest, + GLenum sourceFormat, + const d3d11::RenderTargetView &dest, const gl::Box &destArea, const gl::Extents &destSize, const gl::Rectangle *scissor, GLenum destFormat, GLenum filter, - bool maskOffAlpha); + bool maskOffAlpha, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha); - 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, + gl::Error copyStencil(const gl::Context *context, + const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, const gl::Rectangle *scissor); - gl::Error copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, - ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, + gl::Error copyDepth(const gl::Context *context, + const d3d11::SharedSRV &source, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const d3d11::DepthStencilView &dest, + const gl::Box &destArea, + const gl::Extents &destSize, const gl::Rectangle *scissor); - 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, + gl::Error copyDepthStencil(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, const gl::Rectangle *scissor); + gl::ErrorOrResult resolveDepth(const gl::Context *context, + RenderTarget11 *depth); + + gl::ErrorOrResult resolveStencil(const gl::Context *context, + RenderTarget11 *depthStencil, + bool alsoDepth); + + using BlitConvertFunction = void(const gl::Box &sourceArea, + const gl::Box &destArea, + const gl::Rectangle &clipRect, + const gl::Extents &sourceSize, + unsigned int sourceRowPitch, + unsigned int destRowPitch, + ptrdiff_t readOffset, + ptrdiff_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + const uint8_t *sourceData, + uint8_t *destData); + private: enum BlitShaderType { BLITSHADER_INVALID, + + // Passthrough shaders BLITSHADER_2D_RGBAF, BLITSHADER_2D_BGRAF, BLITSHADER_2D_RGBF, @@ -88,6 +137,27 @@ class Blit11 : angle::NonCopyable BLITSHADER_3D_ALPHA, BLITSHADER_3D_LUMA, BLITSHADER_3D_LUMAALPHA, + + // Multiply alpha shaders + BLITSHADER_2D_RGBAF_PREMULTIPLY, + BLITSHADER_2D_RGBAF_UNMULTIPLY, + + BLITSHADER_2D_RGBF_PREMULTIPLY, + BLITSHADER_2D_RGBF_UNMULTIPLY, + + BLITSHADER_2D_RGBAF_TOUI, + BLITSHADER_2D_RGBAF_TOUI_PREMULTIPLY, + BLITSHADER_2D_RGBAF_TOUI_UNMULTIPLY, + + BLITSHADER_2D_RGBF_TOUI, + BLITSHADER_2D_RGBF_TOUI_PREMULTIPLY, + BLITSHADER_2D_RGBF_TOUI_UNMULTIPLY, + + BLITSHADER_2D_LUMAF_PREMULTIPLY, + BLITSHADER_2D_LUMAF_UNMULTIPLY, + + BLITSHADER_2D_LUMAALPHAF_PREMULTIPLY, + BLITSHADER_2D_LUMAALPHAF_UNMULTIPLY }; enum SwizzleShaderType @@ -107,9 +177,13 @@ class Blit11 : angle::NonCopyable 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, + 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); enum ShaderDimension @@ -120,38 +194,102 @@ class Blit11 : angle::NonCopyable struct Shader { + Shader(); + Shader(Shader &&other); + ~Shader(); + Shader &operator=(Shader &&other); + ShaderDimension dimension; - ID3D11PixelShader *pixelShader; + d3d11::PixelShader pixelShader; }; struct ShaderSupport { - ID3D11InputLayout *inputLayout; - ID3D11VertexShader *vertexShader; - ID3D11GeometryShader *geometryShader; + const d3d11::InputLayout *inputLayout; + const d3d11::VertexShader *vertexShader; + const d3d11::GeometryShader *geometryShader; WriteVertexFunction vertexWriteFunction; }; gl::Error initResources(); - void freeResources(); - ShaderSupport getShaderSupport(const Shader &shader); + gl::Error getShaderSupport(const Shader &shader, ShaderSupport *supportOut); - static BlitShaderType GetBlitShaderType(GLenum destinationFormat, bool isSigned, ShaderDimension dimension); + static BlitShaderType GetBlitShaderType(GLenum destinationFormat, + GLenum sourceFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + 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); - - 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(SwizzleShaderType swizzleShaderType, ShaderDimension dimension, ID3D11PixelShader *ps); + gl::Error copyDepthStencilImpl(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + bool stencilOnly); + + gl::Error copyAndConvertImpl(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &destStaging, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + size_t readOffset, + size_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + BlitConvertFunction *convertFunction); + + gl::Error copyAndConvert(const TextureHelper11 &source, + unsigned int sourceSubresource, + const gl::Box &sourceArea, + const gl::Extents &sourceSize, + const TextureHelper11 &dest, + unsigned int destSubresource, + const gl::Box &destArea, + const gl::Extents &destSize, + const gl::Rectangle *scissor, + size_t readOffset, + size_t writeOffset, + size_t copySize, + size_t srcPixelStride, + size_t destPixelStride, + BlitConvertFunction *convertFunction); + + gl::Error addBlitShaderToMap(BlitShaderType blitShaderType, + ShaderDimension dimension, + const ShaderData &shaderData, + const char *name); + + gl::Error getBlitShader(GLenum destFormat, + GLenum sourceFormat, + bool isSigned, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + ShaderDimension dimension, + const Shader **shaderOut); + gl::Error getSwizzleShader(GLenum type, + D3D11_SRV_DIMENSION viewDimension, + const Shader **shaderOut); + + gl::Error addSwizzleShaderToMap(SwizzleShaderType swizzleShaderType, + ShaderDimension dimension, + const ShaderData &shaderData, + const char *name); void clearShaderMap(); + void releaseResolveDepthStencilResources(); + gl::Error initResolveDepthOnly(const d3d11::Format &format, const gl::Extents &extents); + gl::Error initResolveDepthStencil(const gl::Extents &extents); Renderer11 *mRenderer; @@ -159,12 +297,12 @@ class Blit11 : angle::NonCopyable std::map mSwizzleShaderMap; bool mResourcesInitialized; - ID3D11Buffer *mVertexBuffer; - ID3D11SamplerState *mPointSampler; - ID3D11SamplerState *mLinearSampler; - ID3D11RasterizerState *mScissorEnabledRasterizerState; - ID3D11RasterizerState *mScissorDisabledRasterizerState; - ID3D11DepthStencilState *mDepthStencilState; + d3d11::Buffer mVertexBuffer; + d3d11::SamplerState mPointSampler; + d3d11::SamplerState mLinearSampler; + d3d11::RasterizerState mScissorEnabledRasterizerState; + d3d11::RasterizerState mScissorDisabledRasterizerState; + d3d11::DepthStencilState mDepthStencilState; d3d11::LazyInputLayout mQuad2DIL; d3d11::LazyShader mQuad2DVS; @@ -176,9 +314,19 @@ class Blit11 : angle::NonCopyable d3d11::LazyBlendState mAlphaMaskBlendState; - ID3D11Buffer *mSwizzleCB; + d3d11::Buffer mSwizzleCB; + + d3d11::LazyShader mResolveDepthStencilVS; + d3d11::LazyShader mResolveDepthPS; + d3d11::LazyShader mResolveDepthStencilPS; + d3d11::LazyShader mResolveStencilPS; + d3d11::ShaderResourceView mStencilSRV; + TextureHelper11 mResolvedDepthStencil; + d3d11::RenderTargetView mResolvedDepthStencilRTView; + TextureHelper11 mResolvedDepth; + d3d11::DepthStencilView mResolvedDepthDSView; }; -} +} // namespace rx -#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_ 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 0d5dc08b03..2317c9abdb 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp @@ -13,10 +13,14 @@ #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/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/renderer_utils.h" + +namespace rx +{ namespace { @@ -27,41 +31,41 @@ 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 -} D3D11_MAP_FLAG; -#endif -namespace rx -{ -PackPixelsParams::PackPixelsParams() - : format(GL_NONE), type(GL_NONE), outputPitch(0), packBuffer(nullptr), offset(0) +enum class CopyResult { -} + RECREATED, + NOT_RECREATED, +}; -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) +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 } +} // anonymous namespace + namespace gl_d3d11 { -D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) +D3D11_MAP GetD3DMapTypeFromBits(BufferUsage usage, GLbitfield access) { bool readBit = ((access & GL_MAP_READ_BIT) != 0); bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0); @@ -77,7 +81,8 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) } else if (writeBit && !readBit) { - return D3D11_MAP_WRITE; + // Special case for uniform storage - we only allow full buffer updates. + return usage == BUFFER_USAGE_UNIFORM ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE; } else if (writeBit && readBit) { @@ -89,7 +94,7 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) return D3D11_MAP_READ; } } -} +} // namespace gl_d3d11 // Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points // - vertex/transform feedback buffers @@ -106,16 +111,22 @@ class Buffer11::BufferStorage : angle::NonCopyable size_t getSize() const { return mBufferSize; } void setDataRevision(DataRevision rev) { mRevision = rev; } - virtual bool isMappable() const = 0; + virtual bool isCPUAccessible(GLbitfield access) const = 0; + + virtual bool isGPUAccessible() const = 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 gl::ErrorOrResult copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) = 0; + virtual gl::Error resize(const gl::Context *context, size_t size, bool preserveData) = 0; - virtual uint8_t *map(size_t offset, size_t length, GLbitfield access) = 0; - virtual void unmap() = 0; + virtual gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) = 0; + virtual void unmap() = 0; gl::Error setData(const uint8_t *data, size_t offset, size_t size); @@ -133,28 +144,41 @@ class Buffer11::BufferStorage : angle::NonCopyable class Buffer11::NativeStorage : public Buffer11::BufferStorage { public: - NativeStorage(Renderer11 *renderer, BufferUsage usage); + NativeStorage(Renderer11 *renderer, + BufferUsage usage, + const OnBufferDataDirtyChannel *onStorageChanged); ~NativeStorage() override; - bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; } + bool isCPUAccessible(GLbitfield access) const override; + + bool isGPUAccessible() const override { return true; } - ID3D11Buffer *getNativeStorage() const { return mNativeStorage; } - bool copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) override; - gl::Error resize(size_t size, bool preserveData) override; + const d3d11::Buffer &getBuffer() const { return mBuffer; } + gl::ErrorOrResult copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override; - uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) override; void unmap() override; + gl::ErrorOrResult getSRVForFormat(DXGI_FORMAT srvFormat); + private: - static void fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, + static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize); + void clearSRVs(); - ID3D11Buffer *mNativeStorage; + d3d11::Buffer mBuffer; + const OnBufferDataDirtyChannel *mOnStorageChanged; + std::map mBufferResourceViews; }; // A emulated indexed buffer storage represents an underlying D3D11 buffer for data @@ -166,28 +190,32 @@ class Buffer11::EmulatedIndexedStorage : public Buffer11::BufferStorage EmulatedIndexedStorage(Renderer11 *renderer); ~EmulatedIndexedStorage() override; - bool isMappable() const override { return true; } + bool isCPUAccessible(GLbitfield access) const override { return true; } + + bool isGPUAccessible() const override { return false; } - ID3D11Buffer *getNativeStorage(); + gl::ErrorOrResult getBuffer(SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex); - bool copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) override; + gl::ErrorOrResult copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; - gl::Error resize(size_t size, bool preserveData) override; + gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override; - uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) 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 + d3d11::Buffer mBuffer; // contains expanded data for use by D3D + angle::MemoryBuffer mMemoryBuffer; // original data (not expanded) + angle::MemoryBuffer mIndicesMemoryBuffer; // indices data }; // Pack storage represents internal storage for pack buffers. We implement pack buffers @@ -198,24 +226,32 @@ class Buffer11::PackStorage : public Buffer11::BufferStorage explicit PackStorage(Renderer11 *renderer); ~PackStorage() override; - bool isMappable() const override { return true; } - bool copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) override; - gl::Error resize(size_t size, bool preserveData) override; + bool isCPUAccessible(GLbitfield access) const override { return true; } - uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + bool isGPUAccessible() const override { return false; } + + gl::ErrorOrResult copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override; + + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) override; void unmap() override; - gl::Error packPixels(const gl::FramebufferAttachment &readAttachment, + gl::Error packPixels(const gl::Context *context, + const gl::FramebufferAttachment &readAttachment, const PackPixelsParams ¶ms); private: gl::Error flushQueuedPackCommand(); TextureHelper11 mStagingTexture; - MemoryBuffer mMemoryBuffer; + angle::MemoryBuffer mMemoryBuffer; std::unique_ptr mQueuedPackCommand; PackPixelsParams mPackParams; bool mDataModified; @@ -230,37 +266,46 @@ class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage explicit SystemMemoryStorage(Renderer11 *renderer); ~SystemMemoryStorage() override {} - bool isMappable() const override { return true; } - bool copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) override; - gl::Error resize(size_t size, bool preserveData) override; + bool isCPUAccessible(GLbitfield access) const override { return true; } + + bool isGPUAccessible() const override { return false; } - uint8_t *map(size_t offset, size_t length, GLbitfield access) override; + gl::ErrorOrResult copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) override; + gl::Error resize(const gl::Context *context, size_t size, bool preserveData) override; + + gl::Error map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) override; void unmap() override; - MemoryBuffer *getSystemCopy() { return &mSystemCopy; } + angle::MemoryBuffer *getSystemCopy() { return &mSystemCopy; } protected: - MemoryBuffer mSystemCopy; + angle::MemoryBuffer mSystemCopy; }; -Buffer11::Buffer11(Renderer11 *renderer) - : BufferD3D(renderer), +Buffer11::Buffer11(const gl::BufferState &state, Renderer11 *renderer) + : BufferD3D(state, renderer), mRenderer(renderer), mSize(0), mMappedStorage(nullptr), - mBufferStorages(BUFFER_USAGE_COUNT, nullptr), + mBufferStorages({}), + mLatestBufferStorage(nullptr), + mDeallocThresholds({}), + mIdleness({}), mConstantBufferStorageAdditionalSize(0), - mMaxConstantBufferLruCount(0), - mReadUsageCount(0) + mMaxConstantBufferLruCount(0) { } Buffer11::~Buffer11() { - for (auto &storage : mBufferStorages) + for (BufferStorage *&storage : mBufferStorages) { SafeDelete(storage); } @@ -273,79 +318,74 @@ Buffer11::~Buffer11() mRenderer->onBufferDelete(this); } -gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) +gl::Error Buffer11::setData(const gl::Context *context, + gl::BufferBinding target, + const void *data, + size_t size, + gl::BufferUsage usage) { - gl::Error error = setSubData(data, size, 0); - if (error.isError()) - { - return error; - } - - updateD3DBufferUsage(usage); - return error; + updateD3DBufferUsage(context, usage); + ANGLE_TRY(setSubData(context, target, data, size, 0)); + return gl::NoError(); } -gl::Error Buffer11::getData(const uint8_t **outData) +gl::Error Buffer11::getData(const gl::Context *context, const uint8_t **outData) { SystemMemoryStorage *systemMemoryStorage = nullptr; - gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); - - if (error.isError()) - { - *outData = nullptr; - return error; - } - - mReadUsageCount = 0; + ANGLE_TRY_RESULT(getSystemMemoryStorage(context), systemMemoryStorage); ASSERT(systemMemoryStorage->getSize() >= mSize); *outData = systemMemoryStorage->getSystemCopy()->data(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Buffer11::getSystemMemoryStorage(SystemMemoryStorage **storageOut) +gl::ErrorOrResult Buffer11::getSystemMemoryStorage( + const gl::Context *context) { - BufferStorage *memStorageUntyped = getBufferStorage(BUFFER_USAGE_SYSTEM_MEMORY); - - if (memStorageUntyped == nullptr) - { - // TODO(jmadill): convert all to errors - return gl::Error(GL_OUT_OF_MEMORY); - } - - *storageOut = GetAs(memStorageUntyped); - return gl::Error(GL_NO_ERROR); + BufferStorage *storage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_SYSTEM_MEMORY), storage); + return GetAs(storage); } -gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) +gl::Error Buffer11::setSubData(const gl::Context *context, + gl::BufferBinding target, + const void *data, + size_t size, + size_t offset) { size_t requiredSize = size + offset; if (data && size > 0) { // Use system memory storage for dynamic buffers. - + // Try using a constant storage for constant buffers BufferStorage *writeBuffer = nullptr; - if (supportsDirectBinding()) + if (target == gl::BufferBinding::Uniform) { - writeBuffer = getStagingStorage(); - - if (!writeBuffer) + // If we are a very large uniform buffer, keep system memory storage around so that we + // aren't forced to read back from a constant buffer. We also check the workaround for + // Intel - this requires us to use system memory so we don't end up having to copy from + // a constant buffer to a staging buffer. + // TODO(jmadill): Use Context caps. + if (offset == 0 && size >= mSize && + size <= static_cast(mRenderer->getNativeCaps().maxUniformBlockSize) && + !mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers) + { + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_UNIFORM), writeBuffer); + } + else { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer."); + ANGLE_TRY_RESULT(getSystemMemoryStorage(context), writeBuffer); } } + else if (supportsDirectBinding()) + { + ANGLE_TRY_RESULT(getStagingStorage(context), writeBuffer); + } else { - SystemMemoryStorage *systemMemoryStorage = nullptr; - gl::Error error = getSystemMemoryStorage(&systemMemoryStorage); - if (error.isError()) - { - return error; - } - - writeBuffer = systemMemoryStorage; + ANGLE_TRY_RESULT(getSystemMemoryStorage(context), writeBuffer); } ASSERT(writeBuffer); @@ -355,24 +395,25 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) if (writeBuffer->getSize() < requiredSize) { bool preserveData = (offset > 0); - gl::Error error = writeBuffer->resize(requiredSize, preserveData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(writeBuffer->resize(context, requiredSize, preserveData)); } - writeBuffer->setData(static_cast(data), offset, size); - writeBuffer->setDataRevision(writeBuffer->getDataRevision() + 1); + ANGLE_TRY(writeBuffer->setData(static_cast(data), offset, size)); + onStorageUpdate(writeBuffer); + + // Notify any vertex arrays that we have dirty data. + // TODO(jmadill): Use a more fine grained notification for data updates. + mDirectBroadcastChannel.signal(context); } mSize = std::max(mSize, requiredSize); - invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + invalidateStaticData(context); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Buffer11::copySubData(BufferImpl *source, +gl::Error Buffer11::copySubData(const gl::Context *context, + BufferImpl *source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) @@ -380,28 +421,32 @@ gl::Error Buffer11::copySubData(BufferImpl *source, Buffer11 *sourceBuffer = GetAs(source); ASSERT(sourceBuffer != nullptr); - BufferStorage *copyDest = getLatestBufferStorage(); + BufferStorage *copyDest = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(context), copyDest); + if (!copyDest) { - copyDest = getStagingStorage(); + ANGLE_TRY_RESULT(getStagingStorage(context), copyDest); } - BufferStorage *copySource = sourceBuffer->getLatestBufferStorage(); + BufferStorage *copySource = nullptr; + ANGLE_TRY_RESULT(sourceBuffer->getLatestBufferStorage(context), copySource); - if (!copySource || !copyDest) + if (!copySource) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer."); + ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(context), copySource); } - // If copying to/from a pixel pack buffer, we must have a staging or - // pack buffer partner, because other native buffers can't be mapped - if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable()) + ASSERT(copySource && copyDest); + + // A staging buffer is needed if there is no cpu-cpu or gpu-gpu copy path avaiable. + if (!copyDest->isGPUAccessible() && !copySource->isCPUAccessible(GL_MAP_READ_BIT)) { - copySource = sourceBuffer->getStagingStorage(); + ANGLE_TRY_RESULT(sourceBuffer->getStagingStorage(context), copySource); } - else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable()) + else if (!copySource->isGPUAccessible() && !copyDest->isCPUAccessible(GL_MAP_WRITE_BIT)) { - copyDest = getStagingStorage(); + ANGLE_TRY_RESULT(getStagingStorage(context), copyDest); } // D3D11 does not allow overlapped copies until 11.1, and only if the @@ -411,36 +456,48 @@ gl::Error Buffer11::copySubData(BufferImpl *source, { if (copySource->getUsage() == BUFFER_USAGE_STAGING) { - copySource = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + copySource); } else { - copySource = getStagingStorage(); + ANGLE_TRY_RESULT(getStagingStorage(context), copySource); } } - copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset); - copyDest->setDataRevision(copyDest->getDataRevision() + 1); + CopyResult copyResult = CopyResult::NOT_RECREATED; + ANGLE_TRY_RESULT(copyDest->copyFromStorage(context, copySource, sourceOffset, size, destOffset), + copyResult); + onStorageUpdate(copyDest); mSize = std::max(mSize, destOffset + size); - invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + invalidateStaticData(context); + + // Also notify that direct buffers are dirty. + mDirectBroadcastChannel.signal(context); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Buffer11::map(GLenum access, GLvoid **mapPtr) +gl::Error Buffer11::map(const gl::Context *context, GLenum access, void **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); + return mapRange(context, 0, mSize, GL_MAP_WRITE_BIT, mapPtr); } -gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) +gl::Error Buffer11::mapRange(const gl::Context *context, + size_t offset, + size_t length, + GLbitfield access, + void **mapPtr) { ASSERT(!mMappedStorage); - BufferStorage *latestStorage = getLatestBufferStorage(); + BufferStorage *latestStorage = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(context), latestStorage); + if (latestStorage && (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || latestStorage->getUsage() == BUFFER_USAGE_STAGING)) { @@ -449,34 +506,32 @@ gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GL } else { - // Fall back to using the staging buffer if the latest storage does - // not exist or is not CPU-accessible. - mMappedStorage = getStagingStorage(); + // Fall back to using the staging buffer if the latest storage does not exist or is not + // CPU-accessible. + ANGLE_TRY_RESULT(getStagingStorage(context), mMappedStorage); } if (!mMappedStorage) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer."); + return gl::OutOfMemory() << "Failed to allocate mappable internal buffer."; } if ((access & GL_MAP_WRITE_BIT) > 0) { // 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); + onStorageUpdate(mMappedStorage); + invalidateStaticData(context); } - uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access); - if (!mappedBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer."); - } + uint8_t *mappedBuffer = nullptr; + ANGLE_TRY(mMappedStorage->map(offset, length, access, &mappedBuffer)); + ASSERT(mappedBuffer); - *mapPtr = static_cast(mappedBuffer); - return gl::Error(GL_NO_ERROR); + *mapPtr = static_cast(mappedBuffer); + return gl::NoError(); } -gl::Error Buffer11::unmap(GLboolean *result) +gl::Error Buffer11::unmap(const gl::Context *context, GLboolean *result) { ASSERT(mMappedStorage); mMappedStorage->unmap(); @@ -485,168 +540,171 @@ gl::Error Buffer11::unmap(GLboolean *result) // TODO: detect if we had corruption. if so, return false. *result = GL_TRUE; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void Buffer11::markTransformFeedbackUsage() +gl::Error Buffer11::markTransformFeedbackUsage(const gl::Context *context) { - BufferStorage *transformFeedbackStorage = - getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + BufferStorage *transformFeedbackStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + transformFeedbackStorage); if (transformFeedbackStorage) { - transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); + onStorageUpdate(transformFeedbackStorage); } - invalidateStaticData(D3D_BUFFER_INVALIDATE_WHOLE_CACHE); + invalidateStaticData(context); + return gl::NoError(); } -void Buffer11::markBufferUsage() +void Buffer11::updateDeallocThreshold(BufferUsage usage) { - mReadUsageCount++; + // The following strategy was tuned on the Oort online benchmark (http://oortonline.gl/) + // as well as a custom microbenchmark (IndexConversionPerfTest.Run/index_range_d3d11) + + // First readback: 8 unmodified uses before we free buffer memory. + // After that, double the threshold each time until we reach the max. + if (mDeallocThresholds[usage] == 0) + { + mDeallocThresholds[usage] = 8; + } + else if (mDeallocThresholds[usage] < std::numeric_limits::max() / 2u) + { + mDeallocThresholds[usage] *= 2u; + } + else + { + mDeallocThresholds[usage] = std::numeric_limits::max(); + } +} - // Free the system memory storage if we decide it isn't being used very often. - const unsigned int usageLimit = 5; +// Free the storage if we decide it isn't being used very often. +gl::Error Buffer11::checkForDeallocation(const gl::Context *context, BufferUsage usage) +{ + mIdleness[usage]++; - BufferStorage *&sysMemUsage = mBufferStorages[BUFFER_USAGE_SYSTEM_MEMORY]; - if (mReadUsageCount > usageLimit && sysMemUsage != nullptr) + BufferStorage *&storage = mBufferStorages[usage]; + if (storage != nullptr && mIdleness[usage] > mDeallocThresholds[usage]) { - if (getLatestBufferStorage() != sysMemUsage) + BufferStorage *latestStorage = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(context), latestStorage); + if (latestStorage != storage) { - SafeDelete(sysMemUsage); + SafeDelete(storage); } } + + return gl::NoError(); } -ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) +// Keep system memory when we are using it for the canonical version of data. +bool Buffer11::canDeallocateSystemMemory() const { - markBufferUsage(); - - BufferStorage *bufferStorage = getBufferStorage(usage); - - if (!bufferStorage) + // Must keep system memory on Intel. + if (mRenderer->getWorkarounds().useSystemMemoryForConstantBuffers) { - // Storage out-of-memory - return nullptr; + return false; } - return GetAs(bufferStorage)->getNativeStorage(); + return (!mBufferStorages[BUFFER_USAGE_UNIFORM] || + mSize <= mRenderer->getNativeCaps().maxUniformBlockSize); } -ID3D11Buffer *Buffer11::getEmulatedIndexedBuffer(SourceIndexData *indexInfo, - const TranslatedAttribute *attribute) +void Buffer11::markBufferUsage(BufferUsage usage) { - markBufferUsage(); - - assert(indexInfo != nullptr); - assert(attribute != nullptr); + mIdleness[usage] = 0; +} - BufferStorage *bufferStorage = getBufferStorage(BUFFER_USAGE_EMULATED_INDEXED_VERTEX); - if (!bufferStorage) +gl::Error Buffer11::garbageCollection(const gl::Context *context, BufferUsage currentUsage) +{ + if (currentUsage != BUFFER_USAGE_SYSTEM_MEMORY && canDeallocateSystemMemory()) { - // Storage out-of-memory - return nullptr; + ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_SYSTEM_MEMORY)); } - EmulatedIndexedStorage *emulatedStorage = GetAs(bufferStorage); - if (!emulatedStorage->update(indexInfo, attribute)) + if (currentUsage != BUFFER_USAGE_STAGING) { - // Storage out-of-memory - return nullptr; + ANGLE_TRY(checkForDeallocation(context, BUFFER_USAGE_STAGING)); } - return emulatedStorage->getNativeStorage(); + return gl::NoError(); } -ID3D11Buffer *Buffer11::getConstantBufferRange(GLintptr offset, GLsizeiptr size) +gl::ErrorOrResult Buffer11::getBuffer(const gl::Context *context, BufferUsage usage) { - markBufferUsage(); + BufferStorage *storage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, usage), storage); + return GetAs(storage)->getBuffer().get(); +} - BufferStorage *bufferStorage; +gl::ErrorOrResult Buffer11::getEmulatedIndexedBuffer( + const gl::Context *context, + SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex) +{ + ASSERT(indexInfo); - if (offset == 0) - { - bufferStorage = getBufferStorage(BUFFER_USAGE_UNIFORM); - } - else - { - bufferStorage = getConstantBufferRangeStorage(offset, size); - } + BufferStorage *untypedStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), + untypedStorage); - if (!bufferStorage) - { - // Storage out-of-memory - return nullptr; - } + EmulatedIndexedStorage *emulatedStorage = GetAs(untypedStorage); + + const d3d11::Buffer *nativeStorage = nullptr; + ANGLE_TRY_RESULT(emulatedStorage->getBuffer(indexInfo, attribute, startVertex), nativeStorage); - return GetAs(bufferStorage)->getNativeStorage(); + return nativeStorage->get(); } -ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) +gl::Error Buffer11::getConstantBufferRange(const gl::Context *context, + GLintptr offset, + GLsizeiptr size, + const d3d11::Buffer **bufferOut, + UINT *firstConstantOut, + UINT *numConstantsOut) { - BufferStorage *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK); + BufferStorage *bufferStorage = nullptr; - if (!storage) + if (offset == 0 || mRenderer->getRenderer11DeviceCaps().supportsConstantBufferOffsets) { - // Storage out-of-memory - return nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_UNIFORM), bufferStorage); + CalculateConstantBufferParams(offset, size, firstConstantOut, numConstantsOut); } - - ID3D11Buffer *buffer = GetAs(storage)->getNativeStorage(); - - auto bufferSRVIt = mBufferResourceViews.find(srvFormat); - - if (bufferSRVIt != mBufferResourceViews.end()) + else { - if (bufferSRVIt->second.first == buffer) - { - return bufferSRVIt->second.second; - } - else - { - // The underlying buffer has changed since the SRV was created: recreate the SRV. - SafeRelease(bufferSRVIt->second.second); - } + ANGLE_TRY_RESULT(getConstantBufferRangeStorage(context, offset, size), bufferStorage); + *firstConstantOut = 0; + *numConstantsOut = 0; } - ID3D11Device *device = mRenderer->getDevice(); - ID3D11ShaderResourceView *bufferSRV = nullptr; - - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(srvFormat); + *bufferOut = &GetAs(bufferStorage)->getBuffer(); - D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; - bufferSRVDesc.Buffer.ElementOffset = 0; - 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); - ASSERT(SUCCEEDED(result)); - - mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV); + return gl::NoError(); +} - return bufferSRV; +gl::ErrorOrResult Buffer11::getSRV(const gl::Context *context, + DXGI_FORMAT srvFormat) +{ + BufferStorage *storage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_PIXEL_UNPACK), storage); + NativeStorage *nativeStorage = GetAs(storage); + return nativeStorage->getSRVForFormat(srvFormat); } -gl::Error Buffer11::packPixels(const gl::FramebufferAttachment &readAttachment, +gl::Error Buffer11::packPixels(const gl::Context *context, + const gl::FramebufferAttachment &readAttachment, const PackPixelsParams ¶ms) { - PackStorage *packStorage = getPackStorage(); - BufferStorage *latestStorage = getLatestBufferStorage(); + PackStorage *packStorage = nullptr; + ANGLE_TRY_RESULT(getPackStorage(context), packStorage); - if (packStorage) - { - gl::Error error = packStorage->packPixels(readAttachment, params); - if (error.isError()) - { - return error; - } - packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1); - } + ASSERT(packStorage); + ANGLE_TRY(packStorage->packPixels(context, readAttachment, params)); + onStorageUpdate(packStorage); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } size_t Buffer11::getTotalCPUBufferMemoryBytes() const @@ -662,48 +720,56 @@ size_t Buffer11::getTotalCPUBufferMemoryBytes() const return allocationSize; } -Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage) +gl::ErrorOrResult Buffer11::getBufferStorage(const gl::Context *context, + BufferUsage usage) { ASSERT(0 <= usage && usage < BUFFER_USAGE_COUNT); BufferStorage *&newStorage = mBufferStorages[usage]; if (!newStorage) { - if (usage == BUFFER_USAGE_PIXEL_PACK) - { - newStorage = new PackStorage(mRenderer); - } - else if (usage == BUFFER_USAGE_SYSTEM_MEMORY) - { - newStorage = new SystemMemoryStorage(mRenderer); - } - else if (usage == BUFFER_USAGE_EMULATED_INDEXED_VERTEX) - { - newStorage = new EmulatedIndexedStorage(mRenderer); - } - else - { - // buffer is not allocated, create it - newStorage = new NativeStorage(mRenderer, usage); - } + newStorage = allocateStorage(usage); } + markBufferUsage(usage); + // resize buffer if (newStorage->getSize() < mSize) { - if (newStorage->resize(mSize, true).isError()) - { - // Out of memory error - return nullptr; - } + ANGLE_TRY(newStorage->resize(context, mSize, true)); } - updateBufferStorage(newStorage, 0, mSize); + ASSERT(newStorage); + + ANGLE_TRY(updateBufferStorage(context, newStorage, 0, mSize)); + ANGLE_TRY(garbageCollection(context, usage)); return newStorage; } -Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset, GLsizeiptr size) +Buffer11::BufferStorage *Buffer11::allocateStorage(BufferUsage usage) +{ + updateDeallocThreshold(usage); + switch (usage) + { + case BUFFER_USAGE_PIXEL_PACK: + return new PackStorage(mRenderer); + case BUFFER_USAGE_SYSTEM_MEMORY: + return new SystemMemoryStorage(mRenderer); + case BUFFER_USAGE_EMULATED_INDEXED_VERTEX: + return new EmulatedIndexedStorage(mRenderer); + case BUFFER_USAGE_INDEX: + case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: + return new NativeStorage(mRenderer, usage, &mDirectBroadcastChannel); + default: + return new NativeStorage(mRenderer, usage, nullptr); + } +} + +gl::ErrorOrResult Buffer11::getConstantBufferRangeStorage( + const gl::Context *context, + GLintptr offset, + GLsizeiptr size) { BufferStorage *newStorage; @@ -714,7 +780,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset if (!cacheEntry->storage) { - cacheEntry->storage = new NativeStorage(mRenderer, BUFFER_USAGE_UNIFORM); + cacheEntry->storage = allocateStorage(BUFFER_USAGE_UNIFORM); cacheEntry->lruCount = ++mMaxConstantBufferLruCount; } @@ -722,6 +788,8 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset newStorage = cacheEntry->storage; } + markBufferUsage(BUFFER_USAGE_UNIFORM); + if (newStorage->getSize() < static_cast(size)) { size_t maximumAllowedAdditionalSize = 2 * getSize(); @@ -733,8 +801,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset auto iter = std::min_element(std::begin(mConstantBufferRangeStoragesCache), std::end(mConstantBufferRangeStoragesCache), [](const ConstantBufferCache::value_type &a, - const ConstantBufferCache::value_type &b) - { + const ConstantBufferCache::value_type &b) { return a.second.lruCount < b.second.lruCount; }); @@ -746,12 +813,7 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset mConstantBufferRangeStoragesCache.erase(iter); } - if (newStorage->resize(size, false).isError()) - { - // Out of memory error - return nullptr; - } - + ANGLE_TRY(newStorage->resize(context, size, false)); mConstantBufferStorageAdditionalSize += sizeDelta; // We don't copy the old data when resizing the constant buffer because the data may be @@ -760,103 +822,148 @@ Buffer11::BufferStorage *Buffer11::getConstantBufferRangeStorage(GLintptr offset newStorage->setDataRevision(0); } - updateBufferStorage(newStorage, offset, size); - + ANGLE_TRY(updateBufferStorage(context, newStorage, offset, size)); + ANGLE_TRY(garbageCollection(context, BUFFER_USAGE_UNIFORM)); return newStorage; } -void Buffer11::updateBufferStorage(BufferStorage *storage, size_t sourceOffset, size_t storageSize) +gl::Error Buffer11::updateBufferStorage(const gl::Context *context, + BufferStorage *storage, + size_t sourceOffset, + size_t storageSize) { - BufferStorage *latestBuffer = getLatestBufferStorage(); - 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 && - storage->getUsage() != BUFFER_USAGE_STAGING && - (!latestBuffer->isMappable() || !storage->isMappable())) - { - NativeStorage *stagingBuffer = getStagingStorage(); + BufferStorage *latestBuffer = nullptr; + ANGLE_TRY_RESULT(getLatestBufferStorage(context), latestBuffer); - stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0); - stagingBuffer->setDataRevision(latestBuffer->getDataRevision()); - - latestBuffer = stagingBuffer; - } + ASSERT(storage); - // if copyFromStorage returns true, the D3D buffer has been recreated - // and we should update our serial - if (storage->copyFromStorage(latestBuffer, sourceOffset, storageSize, 0)) - { - updateSerial(); - } - storage->setDataRevision(latestBuffer->getDataRevision()); + if (!latestBuffer) + { + onStorageUpdate(storage); + return gl::NoError(); } -} -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 = nullptr; - DataRevision latestRevision = 0; - for (auto &storage : mBufferStorages) + if (latestBuffer->getDataRevision() <= storage->getDataRevision()) { - if (storage && (!latestStorage || storage->getDataRevision() > latestRevision)) - { - latestStorage = storage; - latestRevision = storage->getDataRevision(); - } + return gl::NoError(); } - // resize buffer - if (latestStorage && latestStorage->getSize() < mSize) + // 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 && + storage->getUsage() != BUFFER_USAGE_STAGING && + (!latestBuffer->isCPUAccessible(GL_MAP_READ_BIT) || + !storage->isCPUAccessible(GL_MAP_WRITE_BIT))) { - if (latestStorage->resize(mSize, true).isError()) - { - // Out of memory error - return nullptr; - } + NativeStorage *stagingBuffer = nullptr; + ANGLE_TRY_RESULT(getStagingStorage(context), stagingBuffer); + + CopyResult copyResult = CopyResult::NOT_RECREATED; + ANGLE_TRY_RESULT( + stagingBuffer->copyFromStorage(context, latestBuffer, 0, latestBuffer->getSize(), 0), + copyResult); + onCopyStorage(stagingBuffer, latestBuffer); + + latestBuffer = stagingBuffer; } - return latestStorage; + CopyResult copyResult = CopyResult::NOT_RECREATED; + ANGLE_TRY_RESULT(storage->copyFromStorage(context, latestBuffer, sourceOffset, storageSize, 0), + copyResult); + // If the D3D buffer has been recreated, we should update our serial. + if (copyResult == CopyResult::RECREATED) + { + updateSerial(); + } + onCopyStorage(storage, latestBuffer); + return gl::NoError(); } -Buffer11::NativeStorage *Buffer11::getStagingStorage() +gl::ErrorOrResult Buffer11::getLatestBufferStorage( + const gl::Context *context) const { - BufferStorage *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING); - - if (!stagingStorage) + // resize buffer + if (mLatestBufferStorage && mLatestBufferStorage->getSize() < mSize) { - // Out-of-memory - return nullptr; + ANGLE_TRY(mLatestBufferStorage->resize(context, mSize, true)); } - return GetAs(stagingStorage); + return mLatestBufferStorage; } -Buffer11::PackStorage *Buffer11::getPackStorage() +gl::ErrorOrResult Buffer11::getStagingStorage(const gl::Context *context) { - BufferStorage *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK); - - if (!packStorage) - { - // Out-of-memory - return nullptr; - } + BufferStorage *stagingStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_STAGING), stagingStorage); + return GetAs(stagingStorage); +} +gl::ErrorOrResult Buffer11::getPackStorage(const gl::Context *context) +{ + BufferStorage *packStorage = nullptr; + ANGLE_TRY_RESULT(getBufferStorage(context, BUFFER_USAGE_PIXEL_PACK), packStorage); return GetAs(packStorage); } +size_t Buffer11::getSize() const +{ + return mSize; +} + bool Buffer11::supportsDirectBinding() const { // Do not support direct buffers for dynamic data. The streaming buffer // offers better performance for data which changes every frame. - // Check for absence of static buffer interfaces to detect dynamic data. - return (mStaticVertexBuffer && mStaticIndexBuffer); + return (mUsage == D3DBufferUsage::STATIC); +} + +void Buffer11::initializeStaticData(const gl::Context *context) +{ + BufferD3D::initializeStaticData(context); + + // Notify when static data changes. + mStaticBroadcastChannel.signal(context); } +void Buffer11::invalidateStaticData(const gl::Context *context) +{ + BufferD3D::invalidateStaticData(context); + + // Notify when static data changes. + mStaticBroadcastChannel.signal(context); +} + +OnBufferDataDirtyChannel *Buffer11::getStaticBroadcastChannel() +{ + return &mStaticBroadcastChannel; +} + +OnBufferDataDirtyChannel *Buffer11::getDirectBroadcastChannel() +{ + return &mDirectBroadcastChannel; +} + +void Buffer11::onCopyStorage(BufferStorage *dest, BufferStorage *source) +{ + ASSERT(source && mLatestBufferStorage); + dest->setDataRevision(source->getDataRevision()); + + // Only update the latest buffer storage if our usage index is lower. See comment in header. + if (dest->getUsage() < mLatestBufferStorage->getUsage()) + { + mLatestBufferStorage = dest; + } +} + +void Buffer11::onStorageUpdate(BufferStorage *updatedStorage) +{ + updatedStorage->setDataRevision(updatedStorage->getDataRevision() + 1); + mLatestBufferStorage = updatedStorage; +} + +// Buffer11::BufferStorage implementation + Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) : mRenderer(renderer), mRevision(0), mUsage(usage), mBufferSize(0) { @@ -864,113 +971,118 @@ Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage) gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size) { - ASSERT(isMappable()); + ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT)); - uint8_t *writePointer = map(offset, size, GL_MAP_WRITE_BIT); - if (!writePointer) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer."); - } + // Uniform storage can have a different internal size than the buffer size. Ensure we don't + // overflow. + size_t mapSize = std::min(size, mBufferSize - offset); + + uint8_t *writePointer = nullptr; + ANGLE_TRY(map(offset, mapSize, GL_MAP_WRITE_BIT, &writePointer)); - memcpy(writePointer, data, size); + memcpy(writePointer, data, mapSize); unmap(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage) - : BufferStorage(renderer, usage), mNativeStorage(nullptr) +// Buffer11::NativeStorage implementation + +Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, + BufferUsage usage, + const OnBufferDataDirtyChannel *onStorageChanged) + : BufferStorage(renderer, usage), mBuffer(), mOnStorageChanged(onStorageChanged) { } Buffer11::NativeStorage::~NativeStorage() { - SafeRelease(mNativeStorage); + clearSRVs(); } -// 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::isCPUAccessible(GLbitfield access) const { - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + if ((access & GL_MAP_READ_BIT) != 0) + { + // Read is more exclusive than write mappability. + return (mUsage == BUFFER_USAGE_STAGING); + } + ASSERT((access & GL_MAP_WRITE_BIT) != 0); + return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_UNIFORM); +} +// Returns true if it recreates the direct buffer +gl::ErrorOrResult Buffer11::NativeStorage::copyFromStorage(const gl::Context *context, + BufferStorage *source, + size_t sourceOffset, + size_t size, + size_t destOffset) +{ size_t requiredSize = destOffset + size; - bool createBuffer = !mNativeStorage || mBufferSize < requiredSize; + bool createBuffer = !mBuffer.valid() || mBufferSize < requiredSize; // (Re)initialize D3D buffer if needed + bool preserveData = (destOffset > 0); if (createBuffer) { - bool preserveData = (destOffset > 0); - resize(requiredSize, preserveData); + ANGLE_TRY(resize(context, requiredSize, preserveData)); + } + + size_t clampedSize = size; + if (mUsage == BUFFER_USAGE_UNIFORM) + { + clampedSize = std::min(clampedSize, mBufferSize - destOffset); } if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK || source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY) { - ASSERT(source->isMappable()); - - uint8_t *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource); - ASSERT(SUCCEEDED(hr)); - if (FAILED(hr)) - { - source->unmap(); - return false; - } + ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT) && isCPUAccessible(GL_MAP_WRITE_BIT)); - uint8_t *destPointer = static_cast(mappedResource.pData) + destOffset; + // Uniform buffers must be mapped with write/discard. + ASSERT(!(preserveData && mUsage == BUFFER_USAGE_UNIFORM)); - // Offset bounds are validated at the API layer - ASSERT(sourceOffset + size <= destOffset + mBufferSize); - memcpy(destPointer, sourcePointer, size); + uint8_t *sourcePointer = nullptr; + ANGLE_TRY(source->map(sourceOffset, clampedSize, GL_MAP_READ_BIT, &sourcePointer)); - context->Unmap(mNativeStorage, 0); + auto err = setData(sourcePointer, destOffset, clampedSize); source->unmap(); + ANGLE_TRY(err); } else { D3D11_BOX srcBox; srcBox.left = static_cast(sourceOffset); - srcBox.right = static_cast(sourceOffset + size); + srcBox.right = static_cast(sourceOffset + clampedSize); srcBox.top = 0; srcBox.bottom = 1; srcBox.front = 0; srcBox.back = 1; - ID3D11Buffer *sourceBuffer = GetAs(source)->getNativeStorage(); + const d3d11::Buffer *sourceBuffer = &GetAs(source)->getBuffer(); - context->CopySubresourceRegion(mNativeStorage, 0, static_cast(destOffset), 0, - 0, sourceBuffer, 0, &srcBox); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->CopySubresourceRegion(mBuffer.get(), 0, + static_cast(destOffset), 0, 0, + sourceBuffer->get(), 0, &srcBox); } - return createBuffer; + return createBuffer ? CopyResult::RECREATED : CopyResult::NOT_RECREATED; } -gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) +gl::Error Buffer11::NativeStorage::resize(const gl::Context *context, + size_t size, + bool preserveData) { - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - D3D11_BUFFER_DESC bufferDesc; - fillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast(size)); - - ID3D11Buffer *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); - } + FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast(size)); - d3d11::SetDebugName(newBuffer, "Buffer11::NativeStorage"); + d3d11::Buffer newBuffer; + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &newBuffer)); + newBuffer.setDebugName("Buffer11::NativeStorage"); - if (mNativeStorage && preserveData) + if (mBuffer.valid() && preserveData) { // We don't call resize if the buffer is big enough already. ASSERT(mBufferSize <= size); @@ -983,19 +1095,30 @@ gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData) srcBox.front = 0; srcBox.back = 1; - context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->CopySubresourceRegion(newBuffer.get(), 0, 0, 0, 0, mBuffer.get(), 0, + &srcBox); } // No longer need the old buffer - SafeRelease(mNativeStorage); - mNativeStorage = newBuffer; + mBuffer = std::move(newBuffer); mBufferSize = bufferDesc.ByteWidth; - return gl::Error(GL_NO_ERROR); + // Free the SRVs. + clearSRVs(); + + // Notify that the storage has changed. + if (mOnStorageChanged) + { + mOnStorageChanged->signal(context); + } + + return gl::NoError(); } -void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, +// static +void Buffer11::NativeStorage::FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize) @@ -1030,6 +1153,13 @@ void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, bufferDesc->CPUAccessFlags = 0; break; + case BUFFER_USAGE_INDIRECT: + bufferDesc->MiscFlags = D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = 0; + bufferDesc->CPUAccessFlags = 0; + break; + case BUFFER_USAGE_PIXEL_UNPACK: bufferDesc->Usage = D3D11_USAGE_DEFAULT; bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; @@ -1044,9 +1174,12 @@ void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, // 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); + + // Note: it seems that D3D11 allows larger buffers on some platforms, but not all. + // (Windows 10 seems to allow larger constant buffers, but not Windows 7) bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, - static_cast(renderer->getRendererCaps().maxUniformBlockSize)); + static_cast(renderer->getNativeCaps().maxUniformBlockSize)); break; default: @@ -1054,67 +1187,146 @@ void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC *bufferDesc, } } -uint8_t *Buffer11::NativeStorage::map(size_t offset, size_t length, GLbitfield access) +gl::Error Buffer11::NativeStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) { - ASSERT(mUsage == BUFFER_USAGE_STAGING); + ASSERT(isCPUAccessible(access)); 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(mUsage, 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); + HRESULT result = context->Map(mBuffer.get(), 0, d3dMapType, d3dMapFlag, &mappedResource); ASSERT(SUCCEEDED(result)); if (FAILED(result)) { - return nullptr; + return gl::OutOfMemory() << "Failed to map native storage in Buffer11::NativeStorage::map"; } - return static_cast(mappedResource.pData) + offset; + ASSERT(mappedResource.pData); + *mapPointerOut = static_cast(mappedResource.pData) + offset; + return gl::NoError(); } void Buffer11::NativeStorage::unmap() { - ASSERT(mUsage == BUFFER_USAGE_STAGING); + ASSERT(isCPUAccessible(GL_MAP_WRITE_BIT) || isCPUAccessible(GL_MAP_READ_BIT)); ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - context->Unmap(mNativeStorage, 0); + context->Unmap(mBuffer.get(), 0); +} + +gl::ErrorOrResult Buffer11::NativeStorage::getSRVForFormat( + DXGI_FORMAT srvFormat) +{ + auto bufferSRVIt = mBufferResourceViews.find(srvFormat); + + if (bufferSRVIt != mBufferResourceViews.end()) + { + return &bufferSRVIt->second; + } + + const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(srvFormat); + + D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; + bufferSRVDesc.Buffer.ElementOffset = 0; + bufferSRVDesc.Buffer.ElementWidth = static_cast(mBufferSize) / dxgiFormatInfo.pixelBytes; + bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + bufferSRVDesc.Format = srvFormat; + + ANGLE_TRY(mRenderer->allocateResource(bufferSRVDesc, mBuffer.get(), + &mBufferResourceViews[srvFormat])); + + return &mBufferResourceViews[srvFormat]; +} + +void Buffer11::NativeStorage::clearSRVs() +{ + mBufferResourceViews.clear(); } +// Buffer11::EmulatedIndexStorage implementation + Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer) - : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mNativeStorage(nullptr) + : BufferStorage(renderer, BUFFER_USAGE_EMULATED_INDEXED_VERTEX), mBuffer() { } Buffer11::EmulatedIndexedStorage::~EmulatedIndexedStorage() { - SafeRelease(mNativeStorage); } -ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage() +gl::ErrorOrResult Buffer11::EmulatedIndexedStorage::getBuffer( + SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex) { - if (!mNativeStorage) + // 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 (!mBuffer.valid() || indexInfo->srcIndicesChanged) + { + mBuffer.reset(); + + // 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 gl::OutOfMemory() << "Error resizing index memory buffer in " + "Buffer11::EmulatedIndexedStorage::getBuffer"; + } + + memcpy(mIndicesMemoryBuffer.data(), indexInfo->srcIndices, indicesDataSize); + + indexInfo->srcIndicesChanged = false; + } + + if (!mBuffer.valid()) { + unsigned int offset = 0; + ANGLE_TRY_RESULT(attribute.computeOffset(startVertex), offset); + // Expand the memory storage upon request and cache the results. unsigned int expandedDataSize = - static_cast((mIndexInfo.srcCount * mAttributeStride) + mAttributeOffset); - MemoryBuffer expandedData; + static_cast((indexInfo->srcCount * attribute.stride) + offset); + angle::MemoryBuffer expandedData; if (!expandedData.resize(expandedDataSize)) { - return nullptr; + return gl::OutOfMemory() + << "Error resizing buffer in Buffer11::EmulatedIndexedStorage::getBuffer"; } // Clear the contents of the allocated buffer ZeroMemory(expandedData.data(), expandedDataSize); uint8_t *curr = expandedData.data(); - const uint8_t *ptr = static_cast(mIndexInfo.srcIndices); + const uint8_t *ptr = static_cast(indexInfo->srcIndices); // Ensure that we start in the correct place for the emulated data copy operation to // maintain offset behaviors. - curr += mAttributeOffset; + curr += offset; ReadIndexValueFunction readIndexValue = ReadIndexValueFromIndices; - switch (mIndexInfo.srcIndexType) + switch (indexInfo->srcIndexType) { case GL_UNSIGNED_INT: readIndexValue = ReadIndexValueFromIndices; @@ -1128,17 +1340,15 @@ ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage() } // Iterate over the cached index data and copy entries indicated into the emulated buffer. - for (GLuint i = 0; i < mIndexInfo.srcCount; i++) + for (GLuint i = 0; i < indexInfo->srcCount; i++) { GLuint idx = readIndexValue(ptr, i); - memcpy(curr, mMemoryBuffer.data() + (mAttributeStride * idx), mAttributeStride); - curr += mAttributeStride; + memcpy(curr, mMemoryBuffer.data() + (attribute.stride * idx), attribute.stride); + curr += attribute.stride; } // 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; @@ -1149,99 +1359,53 @@ ID3D11Buffer *Buffer11::EmulatedIndexedStorage::getNativeStorage() 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"); + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &subResourceData, &mBuffer)); + mBuffer.setDebugName("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; + return &mBuffer; } -bool Buffer11::EmulatedIndexedStorage::copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) +gl::ErrorOrResult Buffer11::EmulatedIndexedStorage::copyFromStorage( + const gl::Context *context, + 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(source->isCPUAccessible(GL_MAP_READ_BIT)); + uint8_t *sourceData = nullptr; + ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData)); ASSERT(destOffset + size <= mMemoryBuffer.size()); memcpy(mMemoryBuffer.data() + destOffset, sourceData, size); source->unmap(); - return true; + return CopyResult::RECREATED; } -gl::Error Buffer11::EmulatedIndexedStorage::resize(size_t size, bool preserveData) +gl::Error Buffer11::EmulatedIndexedStorage::resize(const gl::Context *context, + size_t size, + bool preserveData) { if (mMemoryBuffer.size() < size) { if (!mMemoryBuffer.resize(size)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize EmulatedIndexedStorage"); + return gl::OutOfMemory() << "Failed to resize EmulatedIndexedStorage"; } mBufferSize = size; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -uint8_t *Buffer11::EmulatedIndexedStorage::map(size_t offset, size_t length, GLbitfield access) +gl::Error Buffer11::EmulatedIndexedStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) { ASSERT(!mMemoryBuffer.empty() && offset + length <= mMemoryBuffer.size()); - return mMemoryBuffer.data() + offset; + *mapPointerOut = mMemoryBuffer.data() + offset; + return gl::NoError(); } void Buffer11::EmulatedIndexedStorage::unmap() @@ -1249,6 +1413,8 @@ void Buffer11::EmulatedIndexedStorage::unmap() // No-op } +// Buffer11::PackStorage implementation + Buffer11::PackStorage::PackStorage(Renderer11 *renderer) : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK), mStagingTexture(), mDataModified(false) { @@ -1258,32 +1424,42 @@ Buffer11::PackStorage::~PackStorage() { } -bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source, - size_t sourceOffset, - size_t size, - size_t destOffset) +gl::ErrorOrResult Buffer11::PackStorage::copyFromStorage(const gl::Context *context, + 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 - UNREACHABLE(); - return false; + ANGLE_TRY(flushQueuedPackCommand()); + + // For all use cases of pack buffers, we must copy through a readable buffer. + ASSERT(source->isCPUAccessible(GL_MAP_READ_BIT)); + uint8_t *sourceData = nullptr; + ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData)); + ASSERT(destOffset + size <= mMemoryBuffer.size()); + memcpy(mMemoryBuffer.data() + destOffset, sourceData, size); + source->unmap(); + return CopyResult::NOT_RECREATED; } -gl::Error Buffer11::PackStorage::resize(size_t size, bool preserveData) +gl::Error Buffer11::PackStorage::resize(const gl::Context *context, size_t size, bool preserveData) { if (size != mBufferSize) { if (!mMemoryBuffer.resize(size)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer storage."); + return gl::OutOfMemory() << "Failed to resize internal buffer storage."; } mBufferSize = size; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield access) +gl::Error Buffer11::PackStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) { ASSERT(offset + length <= getSize()); // TODO: fast path @@ -1291,15 +1467,12 @@ uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield acc // and if D3D packs the staging texture memory identically to how we would fill // the pack buffer according to the current pack state. - gl::Error error = flushQueuedPackCommand(); - if (error.isError()) - { - return nullptr; - } + ANGLE_TRY(flushQueuedPackCommand()); mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); - return mMemoryBuffer.data() + offset; + *mapPointerOut = mMemoryBuffer.data() + offset; + return gl::NoError(); } void Buffer11::PackStorage::unmap() @@ -1307,42 +1480,29 @@ void Buffer11::PackStorage::unmap() // No-op } -gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &readAttachment, +gl::Error Buffer11::PackStorage::packPixels(const gl::Context *context, + const gl::FramebufferAttachment &readAttachment, const PackPixelsParams ¶ms) { - gl::Error error = flushQueuedPackCommand(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(flushQueuedPackCommand()); RenderTarget11 *renderTarget = nullptr; - error = readAttachment.getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - - ID3D11Resource *renderTargetResource = renderTarget->getTexture(); - ASSERT(renderTargetResource); + ANGLE_TRY(readAttachment.getRenderTarget(context, &renderTarget)); + const TextureHelper11 &srcTexture = renderTarget->getTexture(); + ASSERT(srcTexture.valid()); 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() || + if (!mStagingTexture.get() || mStagingTexture.getFormat() != srcTexture.getFormat() || mStagingTexture.getExtents() != srcTextureSize) { - auto textureOrError = - CreateStagingTexture(srcTexture.getTextureType(), srcTexture.getFormat(), - srcTextureSize, mRenderer->getDevice()); - if (textureOrError.isError()) - { - return textureOrError.getError(); - } - mStagingTexture = std::move(textureOrError.getResult()); + ANGLE_TRY_RESULT( + mRenderer->createStagingTexture(srcTexture.getTextureType(), srcTexture.getFormatSet(), + srcTextureSize, StagingAccess::READ), + mStagingTexture); } // ReadPixels from multisampled FBOs isn't supported in current GL @@ -1357,17 +1517,17 @@ gl::Error Buffer11::PackStorage::packPixels(const gl::FramebufferAttachment &rea // Select the correct layer from a 3D attachment srcBox.front = 0; - if (mStagingTexture.getTextureType() == GL_TEXTURE_3D) + if (mStagingTexture.is3D()) { srcBox.front = static_cast(readAttachment.layer()); } srcBox.back = srcBox.front + 1; // Asynchronous copy - immediateContext->CopySubresourceRegion(mStagingTexture.getResource(), 0, 0, 0, 0, - srcTexture.getResource(), srcSubresource, &srcBox); + immediateContext->CopySubresourceRegion(mStagingTexture.get(), 0, 0, 0, 0, srcTexture.get(), + srcSubresource, &srcBox); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Buffer11::PackStorage::flushQueuedPackCommand() @@ -1376,58 +1536,65 @@ gl::Error Buffer11::PackStorage::flushQueuedPackCommand() if (mQueuedPackCommand) { - gl::Error error = - mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); + ANGLE_TRY( + mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data())); mQueuedPackCommand.reset(nullptr); - if (error.isError()) - { - return error; - } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } +// Buffer11::SystemMemoryStorage implementation + 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) +gl::ErrorOrResult Buffer11::SystemMemoryStorage::copyFromStorage( + const gl::Context *context, + 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(source->isCPUAccessible(GL_MAP_READ_BIT)); + uint8_t *sourceData = nullptr; + ANGLE_TRY(source->map(sourceOffset, size, GL_MAP_READ_BIT, &sourceData)); ASSERT(destOffset + size <= mSystemCopy.size()); memcpy(mSystemCopy.data() + destOffset, sourceData, size); source->unmap(); - return true; + return CopyResult::RECREATED; } -gl::Error Buffer11::SystemMemoryStorage::resize(size_t size, bool preserveData) +gl::Error Buffer11::SystemMemoryStorage::resize(const gl::Context *context, + size_t size, + bool preserveData) { if (mSystemCopy.size() < size) { if (!mSystemCopy.resize(size)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize SystemMemoryStorage"); + return gl::OutOfMemory() << "Failed to resize SystemMemoryStorage"; } mBufferSize = size; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -uint8_t *Buffer11::SystemMemoryStorage::map(size_t offset, size_t length, GLbitfield access) +gl::Error Buffer11::SystemMemoryStorage::map(size_t offset, + size_t length, + GLbitfield access, + uint8_t **mapPointerOut) { ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size()); - return mSystemCopy.data() + offset; + *mapPointerOut = mSystemCopy.data() + offset; + return gl::NoError(); } void Buffer11::SystemMemoryStorage::unmap() { // No-op } -} +} // namespace rx 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 a748db57ae..ddbeeb90d2 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h @@ -9,10 +9,12 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ +#include #include #include "libANGLE/angletypes.h" #include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" namespace gl { @@ -21,69 +23,92 @@ class FramebufferAttachment; namespace rx { +struct PackPixelsParams; class Renderer11; struct SourceIndexData; struct TranslatedAttribute; +// The order of this enum governs priority of 'getLatestBufferStorage'. enum BufferUsage { + BUFFER_USAGE_SYSTEM_MEMORY, BUFFER_USAGE_STAGING, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, BUFFER_USAGE_INDEX, + // TODO: possibly share this buffer type with shader storage buffers. + BUFFER_USAGE_INDIRECT, BUFFER_USAGE_PIXEL_UNPACK, BUFFER_USAGE_PIXEL_PACK, BUFFER_USAGE_UNIFORM, - BUFFER_USAGE_SYSTEM_MEMORY, BUFFER_USAGE_EMULATED_INDEXED_VERTEX, BUFFER_USAGE_COUNT, }; -struct PackPixelsParams -{ - PackPixelsParams(); - PackPixelsParams(const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, - const gl::PixelPackState &pack, ptrdiff_t offset); - - gl::Rectangle area; - GLenum format; - GLenum type; - GLuint outputPitch; - gl::Buffer *packBuffer; - gl::PixelPackState pack; - ptrdiff_t offset; -}; - typedef size_t DataRevision; class Buffer11 : public BufferD3D { public: - Buffer11(Renderer11 *renderer); - virtual ~Buffer11(); - - 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(const gl::FramebufferAttachment &readAttachment, + Buffer11(const gl::BufferState &state, Renderer11 *renderer); + ~Buffer11() override; + + gl::ErrorOrResult getBuffer(const gl::Context *context, BufferUsage usage); + gl::ErrorOrResult getEmulatedIndexedBuffer(const gl::Context *context, + SourceIndexData *indexInfo, + const TranslatedAttribute &attribute, + GLint startVertex); + gl::Error getConstantBufferRange(const gl::Context *context, + GLintptr offset, + GLsizeiptr size, + const d3d11::Buffer **bufferOut, + UINT *firstConstantOut, + UINT *numConstantsOut); + gl::ErrorOrResult getSRV(const gl::Context *context, + DXGI_FORMAT srvFormat); + bool isMapped() const { return mMappedStorage != nullptr; } + gl::Error packPixels(const gl::Context *context, + 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; + size_t getSize() const override; + bool supportsDirectBinding() const override; + gl::Error getData(const gl::Context *context, const uint8_t **outData) override; + void initializeStaticData(const gl::Context *context) override; + void invalidateStaticData(const gl::Context *context) override; // BufferImpl implementation - virtual gl::Error setData(const void* data, size_t size, GLenum usage); - 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(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(); + gl::Error setData(const gl::Context *context, + gl::BufferBinding target, + const void *data, + size_t size, + gl::BufferUsage usage) override; + gl::Error setSubData(const gl::Context *context, + gl::BufferBinding target, + const void *data, + size_t size, + size_t offset) override; + gl::Error copySubData(const gl::Context *context, + BufferImpl *source, + GLintptr sourceOffset, + GLintptr destOffset, + GLsizeiptr size) override; + gl::Error map(const gl::Context *context, GLenum access, void **mapPtr) override; + gl::Error mapRange(const gl::Context *context, + size_t offset, + size_t length, + GLbitfield access, + void **mapPtr) override; + gl::Error unmap(const gl::Context *context, GLboolean *result) override; + gl::Error markTransformFeedbackUsage(const gl::Context *context) override; + + // We use two set of dirty events. Static buffers are marked dirty whenever + // data changes, because they must be re-translated. Direct buffers only need to be + // updated when the underlying ID3D11Buffer pointer changes - hopefully far less often. + OnBufferDataDirtyChannel *getStaticBroadcastChannel(); + OnBufferDataDirtyChannel *getDirectBroadcastChannel(); private: class BufferStorage; @@ -92,21 +117,61 @@ class Buffer11 : public BufferD3D class PackStorage; class SystemMemoryStorage; - Renderer11 *mRenderer; - size_t mSize; - - BufferStorage *mMappedStorage; - - std::vector mBufferStorages; - struct ConstantBufferCacheEntry { - ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) { } + ConstantBufferCacheEntry() : storage(nullptr), lruCount(0) {} BufferStorage *storage; unsigned int lruCount; }; + void markBufferUsage(BufferUsage usage); + gl::Error garbageCollection(const gl::Context *context, BufferUsage currentUsage); + gl::ErrorOrResult getStagingStorage(const gl::Context *context); + gl::ErrorOrResult getPackStorage(const gl::Context *context); + gl::ErrorOrResult getSystemMemoryStorage(const gl::Context *context); + + gl::Error updateBufferStorage(const gl::Context *context, + BufferStorage *storage, + size_t sourceOffset, + size_t storageSize); + gl::ErrorOrResult getBufferStorage(const gl::Context *context, + BufferUsage usage); + gl::ErrorOrResult getLatestBufferStorage(const gl::Context *context) const; + + gl::ErrorOrResult getConstantBufferRangeStorage(const gl::Context *context, + GLintptr offset, + GLsizeiptr size); + + BufferStorage *allocateStorage(BufferUsage usage); + void updateDeallocThreshold(BufferUsage usage); + + // Free the storage if we decide it isn't being used very often. + gl::Error checkForDeallocation(const gl::Context *context, BufferUsage usage); + + // For some cases of uniform buffer storage, we can't deallocate system memory storage. + bool canDeallocateSystemMemory() const; + + // Updates data revisions and latest storage. + void onCopyStorage(BufferStorage *dest, BufferStorage *source); + void onStorageUpdate(BufferStorage *updatedStorage); + + Renderer11 *mRenderer; + size_t mSize; + + BufferStorage *mMappedStorage; + + // Buffer storages are sorted by usage. It's important that the latest buffer storage picks + // the lowest usage in the case where two storages are tied on data revision - this ensures + // we never do anything dangerous like map a uniform buffer over a staging or system memory + // copy. + std::array mBufferStorages; + BufferStorage *mLatestBufferStorage; + + // These two arrays are used to track when to free unused storage. + std::array mDeallocThresholds; + std::array mIdleness; + // 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. @@ -115,25 +180,10 @@ class Buffer11 : public BufferD3D size_t mConstantBufferStorageAdditionalSize; unsigned int mMaxConstantBufferLruCount; - typedef std::pair BufferSRVPair; - std::map mBufferResourceViews; - - unsigned int mReadUsageCount; - - 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(); + OnBufferDataDirtyChannel mStaticBroadcastChannel; + OnBufferDataDirtyChannel mDirectBroadcastChannel; }; -} +} // namespace rx -#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ +#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_ 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 cd95c65d1c..f9dda0aeb4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp @@ -1,4 +1,4 @@ -// + // 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. @@ -20,624 +20,814 @@ #include "third_party/trace_event/trace_event.h" // Precompiled shaders -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11_fl9vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewgs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11multiviewvs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clear11vs.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/cleardepth11ps.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h" - -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h" - -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h" -#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps1.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps2.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps3.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps4.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps5.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps6.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps7.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps8.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps1.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps2.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps3.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps4.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps5.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps6.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps7.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps8.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps1.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps2.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps3.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps4.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps5.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps6.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps7.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps8.h" namespace rx { +namespace +{ +constexpr uint32_t g_ConstantBufferSize = sizeof(RtvDsvClearInfo); +constexpr uint32_t g_VertexSize = sizeof(d3d11::PositionVertex); + +// Updates color, depth and alpha components of cached CB if necessary. +// Returns true if any constants are updated, false otherwise. template -static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangle *scissor, const gl::Color &color, float depth, void *buffer) +bool UpdateDataCache(RtvDsvClearInfo *dataCache, + const gl::Color &color, + const float *zValue, + const uint32_t numRtvs, + const uint8_t writeMask) { - d3d11::PositionDepthColorVertex *vertices = reinterpret_cast*>(buffer); + bool cacheDirty = false; + + if (numRtvs > 0) + { + const bool writeRGB = (writeMask & ~D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0; + if (writeRGB && memcmp(&dataCache->r, &color.red, sizeof(T) * 3) != 0) + { + dataCache->r = color.red; + dataCache->g = color.green; + dataCache->b = color.blue; + cacheDirty = true; + } - float depthClear = gl::clamp01(depth); - float left = -1.0f; - float right = 1.0f; - float top = -1.0f; - float bottom = 1.0f; + const bool writeAlpha = (writeMask & D3D11_COLOR_WRITE_ENABLE_ALPHA) != 0; + if (writeAlpha && (dataCache->a != color.alpha)) + { + dataCache->a = color.alpha; + cacheDirty = true; + } + } - // Clip the quad coordinates to the scissor if needed - if (scissor != nullptr) + if (zValue) { - 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); - top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) / float(framebufferSize.height)) * 2.0f - 1.0f); - bottom = std::min(bottom, ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f); + const float clampedZValue = gl::clamp01(*zValue); + + if (clampedZValue != dataCache->z) + { + dataCache->z = clampedZValue; + cacheDirty = true; + } } - d3d11::SetPositionDepthColorVertex(vertices + 0, left, bottom, depthClear, color); - d3d11::SetPositionDepthColorVertex(vertices + 1, left, top, depthClear, color); - d3d11::SetPositionDepthColorVertex(vertices + 2, right, bottom, depthClear, color); - d3d11::SetPositionDepthColorVertex(vertices + 3, right, top, depthClear, color); + return cacheDirty; } -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) +bool AllOffsetsAreNonNegative(const std::vector &viewportOffsets) { - D3D11_INPUT_ELEMENT_DESC quadLayout[] = + for (size_t i = 0u; i < viewportOffsets.size(); ++i) { - { "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 }, - }; - - inputLayout = new d3d11::LazyInputLayout(quadLayout, 2, vsByteCode, vsSize, inputLayoutName); + const auto &offset = viewportOffsets[i]; + if (offset.x < 0 || offset.y < 0) + { + return false; + } + } + return true; } - -Clear11::ClearShader::~ClearShader() +} // anonymous namespace + +#define CLEARPS(Index) \ + d3d11::LazyShader(g_PS_Clear##Index, ArraySize(g_PS_Clear##Index), \ + "Clear11 PS " ANGLE_STRINGIFY(Index)) + +Clear11::ShaderManager::ShaderManager() + : mIl9(), + mVs9(g_VS_Clear_FL9, ArraySize(g_VS_Clear_FL9), "Clear11 VS FL9"), + mPsFloat9(g_PS_ClearFloat_FL9, ArraySize(g_PS_ClearFloat_FL9), "Clear11 PS FloatFL9"), + mVs(g_VS_Clear, ArraySize(g_VS_Clear), "Clear11 VS"), + mVsMultiview(g_VS_Multiview_Clear, ArraySize(g_VS_Multiview_Clear), "Clear11 VS Multiview"), + mGsMultiview(g_GS_Multiview_Clear, ArraySize(g_GS_Multiview_Clear), "Clear11 GS Multiview"), + mPsDepth(g_PS_ClearDepth, ArraySize(g_PS_ClearDepth), "Clear11 PS Depth"), + mPsFloat{{CLEARPS(Float1), CLEARPS(Float2), CLEARPS(Float3), CLEARPS(Float4), CLEARPS(Float5), + CLEARPS(Float6), CLEARPS(Float7), CLEARPS(Float8)}}, + mPsUInt{{CLEARPS(Uint1), CLEARPS(Uint2), CLEARPS(Uint3), CLEARPS(Uint4), CLEARPS(Uint5), + CLEARPS(Uint6), CLEARPS(Uint7), CLEARPS(Uint8)}}, + mPsSInt{{CLEARPS(Sint1), CLEARPS(Sint2), CLEARPS(Sint3), CLEARPS(Sint4), CLEARPS(Sint5), + CLEARPS(Sint6), CLEARPS(Sint7), CLEARPS(Sint8)}} { - SafeDelete(inputLayout); - vertexShader.release(); - pixelShader.release(); } -Clear11::Clear11(Renderer11 *renderer) - : mRenderer(renderer), - mClearBlendStates(StructLessThan), - mFloatClearShader(nullptr), - mUintClearShader(nullptr), - mIntClearShader(nullptr), - mClearDepthStencilStates(StructLessThan), - mVertexBuffer(nullptr), - mRasterizerState(nullptr) +#undef CLEARPS + +Clear11::ShaderManager::~ShaderManager() { - TRACE_EVENT0("gpu.angle", "Clear11::Clear11"); +} - HRESULT result; - ID3D11Device *device = renderer->getDevice(); +gl::Error Clear11::ShaderManager::getShadersAndLayout(Renderer11 *renderer, + const INT clearType, + const uint32_t numRTs, + const bool hasLayeredLayout, + const d3d11::InputLayout **il, + const d3d11::VertexShader **vs, + const d3d11::GeometryShader **gs, + const d3d11::PixelShader **ps) +{ + if (renderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + { + ASSERT(clearType == GL_FLOAT); - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; + ANGLE_TRY(mVs9.resolve(renderer)); + ANGLE_TRY(mPsFloat9.resolve(renderer)); - result = device->CreateBuffer(&vbDesc, nullptr, &mVertexBuffer); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); + if (!mIl9.valid()) + { + const D3D11_INPUT_ELEMENT_DESC ilDesc[] = { + {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}}; - D3D11_RASTERIZER_DESC rsDesc; - rsDesc.FillMode = D3D11_FILL_SOLID; - rsDesc.CullMode = D3D11_CULL_NONE; - rsDesc.FrontCounterClockwise = FALSE; - rsDesc.DepthBias = 0; - rsDesc.DepthBiasClamp = 0.0f; - rsDesc.SlopeScaledDepthBias = 0.0f; - rsDesc.DepthClipEnable = TRUE; - rsDesc.ScissorEnable = FALSE; - rsDesc.MultisampleEnable = FALSE; - rsDesc.AntialiasedLineEnable = FALSE; + InputElementArray ilDescArray(ilDesc); + ShaderData vertexShader(g_VS_Clear_FL9); - result = device->CreateRasterizerState(&rsDesc, &mRasterizerState); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); + ANGLE_TRY(renderer->allocateResource(ilDescArray, &vertexShader, &mIl9)); + } - if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + *vs = &mVs9.getObj(); + *gs = nullptr; + *il = &mIl9; + *ps = &mPsFloat9.getObj(); + return gl::NoError(); + } + if (!hasLayeredLayout) { - 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"); + ANGLE_TRY(mVs.resolve(renderer)); + *vs = &mVs.getObj(); + *gs = nullptr; } else { - 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"); + // For layered framebuffers we have to use the multi-view versions of the VS and GS. + ANGLE_TRY(mVsMultiview.resolve(renderer)); + ANGLE_TRY(mGsMultiview.resolve(renderer)); + *vs = &mVsMultiview.getObj(); + *gs = &mGsMultiview.getObj(); + } + + *il = nullptr; + + if (numRTs == 0) + { + ANGLE_TRY(mPsDepth.resolve(renderer)); + *ps = &mPsDepth.getObj(); + return gl::NoError(); } - if (renderer->isES3Capable()) + switch (clearType) { - 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"); + case GL_FLOAT: + ANGLE_TRY(mPsFloat[numRTs - 1].resolve(renderer)); + *ps = &mPsFloat[numRTs - 1].getObj(); + break; + case GL_UNSIGNED_INT: + ANGLE_TRY(mPsUInt[numRTs - 1].resolve(renderer)); + *ps = &mPsUInt[numRTs - 1].getObj(); + break; + case GL_INT: + ANGLE_TRY(mPsSInt[numRTs - 1].resolve(renderer)); + *ps = &mPsSInt[numRTs - 1].getObj(); + break; + default: + UNREACHABLE(); + break; } + + return gl::NoError(); +} + +Clear11::Clear11(Renderer11 *renderer) + : mRenderer(renderer), + mResourcesInitialized(false), + mScissorEnabledRasterizerState(), + mScissorDisabledRasterizerState(), + mShaderManager(), + mConstantBuffer(), + mVertexBuffer(), + mShaderData({}) +{ } Clear11::~Clear11() { - for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++) +} + +gl::Error Clear11::ensureResourcesInitialized() +{ + if (mResourcesInitialized) { - SafeRelease(i->second); + return gl::NoError(); } - mClearBlendStates.clear(); - SafeDelete(mFloatClearShader); - SafeDelete(mUintClearShader); - SafeDelete(mIntClearShader); + TRACE_EVENT0("gpu.angle", "Clear11::ensureResourcesInitialized"); + + static_assert((sizeof(RtvDsvClearInfo) == sizeof(RtvDsvClearInfo)), + "Size of rx::RtvDsvClearInfo is not equal to rx::RtvDsvClearInfo"); + + static_assert( + (sizeof(RtvDsvClearInfo) == sizeof(RtvDsvClearInfo)), + "Size of rx::RtvDsvClearInfo is not equal to rx::RtvDsvClearInfo"); - for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++) + static_assert((sizeof(RtvDsvClearInfo) % 16 == 0), + "The size of RtvDsvClearInfo should be a multiple of 16bytes."); + + // Create Rasterizer States + D3D11_RASTERIZER_DESC rsDesc; + rsDesc.FillMode = D3D11_FILL_SOLID; + rsDesc.CullMode = D3D11_CULL_NONE; + rsDesc.FrontCounterClockwise = FALSE; + rsDesc.DepthBias = 0; + rsDesc.DepthBiasClamp = 0.0f; + rsDesc.SlopeScaledDepthBias = 0.0f; + rsDesc.DepthClipEnable = TRUE; + rsDesc.ScissorEnable = FALSE; + rsDesc.MultisampleEnable = FALSE; + rsDesc.AntialiasedLineEnable = FALSE; + + ANGLE_TRY(mRenderer->allocateResource(rsDesc, &mScissorDisabledRasterizerState)); + mScissorDisabledRasterizerState.setDebugName("Clear11 Rasterizer State with scissor disabled"); + + rsDesc.ScissorEnable = TRUE; + ANGLE_TRY(mRenderer->allocateResource(rsDesc, &mScissorEnabledRasterizerState)); + mScissorEnabledRasterizerState.setDebugName("Clear11 Rasterizer State with scissor enabled"); + + // Initialize Depthstencil state with defaults + mDepthStencilStateKey.depthTest = false; + mDepthStencilStateKey.depthMask = false; + mDepthStencilStateKey.depthFunc = GL_ALWAYS; + mDepthStencilStateKey.stencilWritemask = static_cast(-1); + mDepthStencilStateKey.stencilBackWritemask = static_cast(-1); + mDepthStencilStateKey.stencilBackMask = 0; + mDepthStencilStateKey.stencilTest = false; + mDepthStencilStateKey.stencilMask = 0; + mDepthStencilStateKey.stencilFail = GL_REPLACE; + mDepthStencilStateKey.stencilPassDepthFail = GL_REPLACE; + mDepthStencilStateKey.stencilPassDepthPass = GL_REPLACE; + mDepthStencilStateKey.stencilFunc = GL_ALWAYS; + mDepthStencilStateKey.stencilBackFail = GL_REPLACE; + mDepthStencilStateKey.stencilBackPassDepthFail = GL_REPLACE; + mDepthStencilStateKey.stencilBackPassDepthPass = GL_REPLACE; + mDepthStencilStateKey.stencilBackFunc = GL_ALWAYS; + + // Initialize BlendStateKey with defaults + mBlendStateKey.blendState.blend = false; + mBlendStateKey.blendState.sourceBlendRGB = GL_ONE; + mBlendStateKey.blendState.sourceBlendAlpha = GL_ONE; + mBlendStateKey.blendState.destBlendRGB = GL_ZERO; + mBlendStateKey.blendState.destBlendAlpha = GL_ZERO; + mBlendStateKey.blendState.blendEquationRGB = GL_FUNC_ADD; + mBlendStateKey.blendState.blendEquationAlpha = GL_FUNC_ADD; + mBlendStateKey.blendState.sampleAlphaToCoverage = false; + mBlendStateKey.blendState.dither = true; + + mResourcesInitialized = true; + return gl::NoError(); +} + +bool Clear11::useVertexBuffer() const +{ + return (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3); +} + +gl::Error Clear11::ensureConstantBufferCreated() +{ + if (mConstantBuffer.valid()) { - SafeRelease(i->second); + return gl::NoError(); } - mClearDepthStencilStates.clear(); - SafeRelease(mVertexBuffer); - SafeRelease(mRasterizerState); + // Create constant buffer for color & depth data + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = g_ConstantBufferSize; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = &mShaderData; + initialData.SysMemPitch = g_ConstantBufferSize; + initialData.SysMemSlicePitch = g_ConstantBufferSize; + + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &initialData, &mConstantBuffer)); + mConstantBuffer.setDebugName("Clear11 Constant Buffer"); + return gl::NoError(); } -gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData) +gl::Error Clear11::ensureVertexBufferCreated() { - const auto &colorAttachments = fboData.getColorAttachments(); - const auto &drawBufferStates = fboData.getDrawBufferStates(); - const auto *depthAttachment = fboData.getDepthAttachment(); - const auto *stencilAttachment = fboData.getStencilAttachment(); + ASSERT(useVertexBuffer()); + + if (mVertexBuffer.valid()) + { + return gl::NoError(); + } + + // Create vertex buffer with vertices for a quad covering the entire surface + + static_assert((sizeof(d3d11::PositionVertex) % 16) == 0, + "d3d11::PositionVertex should be a multiple of 16 bytes"); + const d3d11::PositionVertex vbData[6] = {{-1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, 0.0f, 1.0f}, + {-1.0f, -1.0f, 0.0f, 1.0f}, {-1.0f, 1.0f, 0.0f, 1.0f}, + {1.0f, 1.0f, 0.0f, 1.0f}, {1.0f, -1.0f, 0.0f, 1.0f}}; + + const UINT vbSize = sizeof(vbData); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = vbSize; + bufferDesc.Usage = D3D11_USAGE_IMMUTABLE; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = 0; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + D3D11_SUBRESOURCE_DATA initialData; + initialData.pSysMem = vbData; + initialData.SysMemPitch = vbSize; + initialData.SysMemSlicePitch = initialData.SysMemPitch; + + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &initialData, &mVertexBuffer)); + mVertexBuffer.setDebugName("Clear11 Vertex Buffer"); + return gl::NoError(); +} - ASSERT(colorAttachments.size() == drawBufferStates.size()); +gl::Error Clear11::clearFramebuffer(const gl::Context *context, + const ClearParameters &clearParams, + const gl::FramebufferState &fboData) +{ + ANGLE_TRY(ensureResourcesInitialized()); // Iterate over the color buffers which require clearing and determine if they can be // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView. // This requires: - // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer - // render targets as expected but does not work the other way around) + // 1) The render target is being cleared to a float value (will be cast to integer when clearing + // integer render targets as expected but does not work the other way around) // 2) The format of the render target has no color channels that are currently masked out. - // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. + // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special + // work. // // If these conditions are met, and: // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView. // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available. - // Otherwise draw a quad. + // Otherwise perform a shader based clear. // - // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView - // by checking if the stencil write mask covers the entire stencil. + // Also determine if the DSV can be cleared withID3D11DeviceContext::ClearDepthStencilView by + // checking if the stencil write mask covers the entire stencil. // - // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color - // attribute. + // To clear the remaining buffers, a shader based clear is performed: + // - The appropriate ShaderManagers (VS & PS) for the clearType is set + // - A CB containing the clear color and Z values is bound + // - An IL and VB are bound (for FL93 and below) + // - ScissorRect/Raststate/Viewport set as required + // - Blendstate set containing appropriate colorMasks + // - DepthStencilState set with appropriate parameters for a z or stencil clear if required + // - Color and/or Z buffers to be cleared are bound + // - Primitive covering entire clear area is drawn gl::Extents framebufferSize; - const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment(); - if (colorAttachment != nullptr) - { - framebufferSize = colorAttachment->getSize(); - } - else if (depthAttachment != nullptr) - { - framebufferSize = depthAttachment->getSize(); - } - else if (stencilAttachment != nullptr) + const auto *depthStencilAttachment = fboData.getDepthOrStencilAttachment(); + if (depthStencilAttachment != nullptr) { - framebufferSize = stencilAttachment->getSize(); + framebufferSize = depthStencilAttachment->getSize(); } else { - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + const gl::FramebufferAttachment *colorAttachment = fboData.getFirstColorAttachment(); + + if (!colorAttachment) + { + UNREACHABLE(); + return gl::InternalError(); + } + + framebufferSize = colorAttachment->getSize(); } - if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || - clearParams.scissor.y >= framebufferSize.height || - clearParams.scissor.x + clearParams.scissor.width <= 0 || - clearParams.scissor.y + clearParams.scissor.height <= 0)) + const bool isSideBySideFBO = + (fboData.getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE); + bool needScissoredClear = false; + std::vector scissorRects; + if (clearParams.scissorEnabled) { - // Scissor is enabled and the scissor rectangle is outside the renderbuffer - return gl::Error(GL_NO_ERROR); - } + const std::vector *viewportOffsets = fboData.getViewportOffsets(); + ASSERT(viewportOffsets != nullptr); + ASSERT(AllOffsetsAreNonNegative(*fboData.getViewportOffsets())); - bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || - clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || - clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); + if (clearParams.scissor.x >= framebufferSize.width || + clearParams.scissor.y >= framebufferSize.height || clearParams.scissor.width == 0 || + clearParams.scissor.height == 0) + { + // The check assumes that the viewport offsets are not negative as according to the + // ANGLE_multiview spec. + // Scissor rect is outside the renderbuffer or is an empty rect. + return gl::NoError(); + } - std::vector maskedClearRenderTargets; - RenderTarget11* maskedClearDepthStencil = nullptr; + if (isSideBySideFBO) + { + // We always have to do a scissor clear for side-by-side framebuffers. + needScissoredClear = true; + } + else + { + // Because the viewport offsets can generate scissor rectangles within the framebuffer's + // bounds, we can do this check only for non-side-by-side framebuffers. + if (clearParams.scissor.x + clearParams.scissor.width <= 0 || + clearParams.scissor.y + clearParams.scissor.height <= 0) + { + // Scissor rect is outside the renderbuffer. + return gl::NoError(); + } + needScissoredClear = + clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || + clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || + clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height; + } - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); -#if defined(ANGLE_ENABLE_D3D11_1) + if (needScissoredClear) + { + // Apply viewport offsets to compute the final scissor rectangles. This is valid also + // for non-side-by-side framebuffers, because the default viewport offset is {0,0}. + const size_t numViews = viewportOffsets->size(); + scissorRects.reserve(numViews); + for (size_t i = 0u; i < numViews; ++i) + { + const gl::Offset &offset = (*viewportOffsets)[i]; + D3D11_RECT rect; + int x = clearParams.scissor.x + offset.x; + int y = clearParams.scissor.y + offset.y; + rect.left = x; + rect.right = x + clearParams.scissor.width; + rect.top = y; + rect.bottom = y + clearParams.scissor.height; + scissorRects.emplace_back(rect); + } + } + } + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); -#endif - ID3D11Device *device = mRenderer->getDevice(); - for (size_t colorAttachmentIndex = 0; colorAttachmentIndex < colorAttachments.size(); - colorAttachmentIndex++) + std::array rtvs; + std::array rtvMasks = {}; + + uint32_t numRtvs = 0; + const uint8_t colorMask = + gl_d3d11::ConvertColorMask(clearParams.colorMaskRed, clearParams.colorMaskGreen, + clearParams.colorMaskBlue, clearParams.colorMaskAlpha); + + const auto &colorAttachments = fboData.getColorAttachments(); + for (auto colorAttachmentIndex : fboData.getEnabledDrawBuffers()) { const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachmentIndex]; - if (clearParams.clearColor[colorAttachmentIndex] && attachment.isAttached() && - drawBufferStates[colorAttachmentIndex] != GL_NONE) + if (!clearParams.clearColor[colorAttachmentIndex]) { - RenderTarget11 *renderTarget = nullptr; - gl::Error error = attachment.getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } + continue; + } - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment.getInternalFormat()); + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(attachment.getRenderTarget(context, &renderTarget)); - 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).", - colorAttachmentIndex, attachment.getInternalFormat()); - } + const gl::InternalFormat &formatInfo = *attachment.getFormat().info; - if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && - (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && - (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && - (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) - { - // Every channel either does not exist in the render target or is masked out - continue; - } - 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) || - (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) - { - // A masked clear is required, or a scissored clear is required and ID3D11DeviceContext1::ClearView is unavailable - MaskedRenderTarget maskAndRt; - bool clearColor = clearParams.clearColor[colorAttachmentIndex]; - maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); - maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); - maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); - maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); - maskAndRt.renderTarget = renderTarget; - maskedClearRenderTargets.push_back(maskAndRt); - } - else - { - // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is possible + if (clearParams.colorType == 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 " + << colorAttachmentIndex << " has internal format " << attachment.getFormat() + << ")."; + } - ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); - if (!framebufferRTV) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); - } + if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) && + (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) && + (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) && + (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha)) + { + // Every channel either does not exist in the render target or is masked out + continue; + } - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); + const auto &framebufferRTV = renderTarget->getRenderTargetView(); + ASSERT(framebufferRTV.valid()); - // Check if the actual format has a channel that the internal format does not and set them to the - // default values - 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), - ((formatInfo.blueBits == 0 && dxgiFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), - ((formatInfo.alphaBits == 0 && dxgiFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), - }; + if ((!(mRenderer->getRenderer11DeviceCaps().supportsClearView) && needScissoredClear) || + clearParams.colorType != GL_FLOAT || + (formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) + { + rtvs[numRtvs] = framebufferRTV.get(); + rtvMasks[numRtvs] = gl_d3d11::GetColorMask(formatInfo) & colorMask; + numRtvs++; + } + else + { + // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is + // possible + + const auto &nativeFormat = renderTarget->getFormatSet().format(); + + // Check if the actual format has a channel that the internal format does not and + // set them to the default values + float clearValues[4] = { + ((formatInfo.redBits == 0 && nativeFormat.redBits > 0) ? 0.0f + : clearParams.colorF.red), + ((formatInfo.greenBits == 0 && nativeFormat.greenBits > 0) + ? 0.0f + : clearParams.colorF.green), + ((formatInfo.blueBits == 0 && nativeFormat.blueBits > 0) ? 0.0f + : clearParams.colorF.blue), + ((formatInfo.alphaBits == 0 && nativeFormat.alphaBits > 0) + ? 1.0f + : clearParams.colorF.alpha), + }; + + if (formatInfo.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.colorF.alpha >= 0.5f) ? 1.0f : 0.0f; + } - if (dxgiFormatInfo.alphaBits == 1) + if (needScissoredClear) + { + // We shouldn't reach here if deviceContext1 is unavailable. + ASSERT(deviceContext1); + // There must be at least one scissor rectangle. + ASSERT(!scissorRects.empty()); + deviceContext1->ClearView(framebufferRTV.get(), clearValues, scissorRects.data(), + static_cast(scissorRects.size())); + if (mRenderer->getWorkarounds().callClearTwice) { - // 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; + deviceContext1->ClearView(framebufferRTV.get(), clearValues, + scissorRects.data(), + static_cast(scissorRects.size())); } - -#if defined(ANGLE_ENABLE_D3D11_1) - if (needScissoredClear) - { - // We shouldn't reach here if deviceContext1 is unavailable. - ASSERT(deviceContext1); - - D3D11_RECT rect; - rect.left = clearParams.scissor.x; - rect.right = clearParams.scissor.x + clearParams.scissor.width; - rect.top = clearParams.scissor.y; - rect.bottom = clearParams.scissor.y + clearParams.scissor.height; - - deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1); - } - else -#endif + } + else + { + deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues); + if (mRenderer->getWorkarounds().callClearTwice) { - deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); + deviceContext->ClearRenderTargetView(framebufferRTV.get(), clearValues); } } } } + ID3D11DepthStencilView *dsv = nullptr; + if (clearParams.clearDepth || clearParams.clearStencil) { - const gl::FramebufferAttachment *attachment = (depthAttachment != nullptr) ? depthAttachment : stencilAttachment; - ASSERT(attachment != nullptr); + RenderTarget11 *depthStencilRenderTarget = nullptr; - RenderTarget11 *renderTarget = nullptr; - gl::Error error = attachment->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } + ASSERT(depthStencilAttachment != nullptr); + ANGLE_TRY(depthStencilAttachment->getRenderTarget(context, &depthStencilRenderTarget)); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat()); + dsv = depthStencilRenderTarget->getDepthStencilView().get(); + ASSERT(dsv != nullptr); - unsigned int stencilUnmasked = (stencilAttachment != nullptr) ? (1 << dxgiFormatInfo.stencilBits) - 1 : 0; - bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + const auto &nativeFormat = depthStencilRenderTarget->getFormatSet().format(); + const auto *stencilAttachment = fboData.getStencilAttachment(); - if (needScissoredClear || needMaskedStencilClear) - { - maskedClearDepthStencil = renderTarget; - } - else + uint32_t stencilUnmasked = + (stencilAttachment != nullptr) ? (1 << nativeFormat.stencilBits) - 1 : 0; + bool needMaskedStencilClear = + clearParams.clearStencil && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + if (!needScissoredClear && !needMaskedStencilClear) { - ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); - } + const UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | + (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); + const FLOAT depthClear = gl::clamp01(clearParams.depthValue); + const UINT8 stencilClear = clearParams.stencilValue & 0xFF; - UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | - (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); - FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); - UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; + deviceContext->ClearDepthStencilView(dsv, clearFlags, depthClear, stencilClear); - deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); + dsv = nullptr; } } - if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) + if (numRtvs == 0 && dsv == nullptr) { - // To clear the render targets and depth stencil in one pass: - // - // Render a quad clipped to the scissor rectangle which draws the clear color and a blend - // state that will perform the required color masking. - // - // The quad's depth is equal to the depth clear value with a depth stencil state that - // will enable or disable depth test/writes if the depth buffer should be cleared or not. - // - // The rasterizer state's stencil is set to always pass or fail based on if the stencil - // should be cleared or not with a stencil write mask of the stencil clear value. - // - // ====================================================================================== - // - // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- - // buffer that is not normalized fixed point or floating point with floating point values - // are undefined so we can just write floats to them and D3D11 will bit cast them to - // integers. - // - // Also, we don't have to worry about attempting to clear a normalized fixed/floating point - // buffer with integer values because there is no gl API call which would allow it, - // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to - // be a compatible clear type. - - // Bind all the render targets which need clearing - ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers); - std::vector rtvs(maskedClearRenderTargets.size()); - for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) - { - RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; - ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); - if (!rtv) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); - } + return gl::NoError(); + } - rtvs[i] = rtv; - } - ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : nullptr; + // Clear the remaining render targets and depth stencil in one pass by rendering a quad: + // + // IA/VS: Vertices containing position and color members are passed through to the next stage. + // The vertex position has XY coordinates equal to clip extents and a Z component equal to the + // Z clear value. The vertex color contains the clear color. + // + // Rasterizer: Viewport scales the VS output over the entire surface and depending on whether + // or not scissoring is enabled the appropriate scissor rect and rasterizerState with or without + // the scissor test enabled is set as well. + // + // DepthStencilTest: DepthTesting, DepthWrites, StencilMask and StencilWrites will be enabled or + // disabled or set depending on what the input depthStencil clear parameters are. Since the PS + // is not writing out depth or rejecting pixels, this should happen prior to the PS stage. + // + // PS: Will write out the color values passed through from the previous stage to all outputs. + // + // OM: BlendState will perform the required color masking and output to RTV(s). + + // + // ====================================================================================== + // + // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- + // buffer that is not normalized fixed point or floating point with floating point values + // are undefined so we can just write floats to them and D3D11 will bit cast them to + // integers. + // + // Also, we don't have to worry about attempting to clear a normalized fixed/floating point + // buffer with integer values because there is no gl API call which would allow it, + // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to + // be a compatible clear type. - ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); - const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - const UINT sampleMask = 0xFFFFFFFF; + ASSERT(numRtvs <= mRenderer->getNativeCaps().maxDrawBuffers); - ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); - const UINT stencilClear = clearParams.stencilClearValue & 0xFF; + // Setup BlendStateKey parameters + mBlendStateKey.blendState.colorMaskRed = clearParams.colorMaskRed; + mBlendStateKey.blendState.colorMaskGreen = clearParams.colorMaskGreen; + mBlendStateKey.blendState.colorMaskBlue = clearParams.colorMaskBlue; + mBlendStateKey.blendState.colorMaskAlpha = clearParams.colorMaskAlpha; + mBlendStateKey.rtvMax = numRtvs; + memcpy(mBlendStateKey.rtvMasks, &rtvMasks[0], sizeof(mBlendStateKey.rtvMasks)); - // Set the vertices - UINT vertexStride = 0; - const UINT startIdx = 0; - ClearShader *shader = nullptr; - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal masked clear vertex buffer, HRESULT: 0x%X.", result); - } + // Get BlendState + const d3d11::BlendState *blendState = nullptr; + ANGLE_TRY(mRenderer->getBlendState(mBlendStateKey, &blendState)); - 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; - break; + const d3d11::DepthStencilState *dsState = nullptr; + const float *zValue = nullptr; - case GL_UNSIGNED_INT: - ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); - vertexStride = sizeof(d3d11::PositionDepthColorVertex); - shader = mUintClearShader; - break; + if (dsv) + { + // Setup DepthStencilStateKey + mDepthStencilStateKey.depthTest = clearParams.clearDepth; + mDepthStencilStateKey.depthMask = clearParams.clearDepth; + mDepthStencilStateKey.stencilWritemask = clearParams.stencilWriteMask; + mDepthStencilStateKey.stencilTest = clearParams.clearStencil; + + // Get DepthStencilState + ANGLE_TRY(mRenderer->getDepthStencilState(mDepthStencilStateKey, &dsState)); + zValue = clearParams.clearDepth ? &clearParams.depthValue : nullptr; + } - case GL_INT: - ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); - vertexStride = sizeof(d3d11::PositionDepthColorVertex); - shader = mIntClearShader; - break; + bool dirtyCb = false; - default: + // Compare the input color/z values against the CB cache and update it if necessary + switch (clearParams.colorType) + { + case GL_FLOAT: + dirtyCb = UpdateDataCache(reinterpret_cast *>(&mShaderData), + clearParams.colorF, zValue, numRtvs, colorMask); + break; + case GL_UNSIGNED_INT: + dirtyCb = UpdateDataCache(reinterpret_cast *>(&mShaderData), + clearParams.colorUI, zValue, numRtvs, colorMask); + break; + case GL_INT: + dirtyCb = UpdateDataCache(reinterpret_cast *>(&mShaderData), + clearParams.colorI, zValue, numRtvs, colorMask); + break; + default: UNREACHABLE(); break; - } - - deviceContext->Unmap(mVertexBuffer, 0); - - // Set the viewport to be the same size as the framebuffer - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = static_cast(framebufferSize.width); - viewport.Height = static_cast(framebufferSize.height); - viewport.MinDepth = 0; - viewport.MaxDepth = 1; - deviceContext->RSSetViewports(1, &viewport); - - // Apply state - deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); - deviceContext->OMSetDepthStencilState(dsState, stencilClear); - deviceContext->RSSetState(mRasterizerState); - - // Apply shaders - 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(static_cast(rtvs.size()), - (rtvs.empty() ? nullptr : &rtvs[0]), dsv); - - // Draw the clear quad - deviceContext->Draw(4, 0); - - // Clean up - mRenderer->markAllStateDirty(); } - return gl::Error(GL_NO_ERROR); -} + ANGLE_TRY(ensureConstantBufferCreated()); -ID3D11BlendState *Clear11::getBlendState(const std::vector& rts) -{ - ClearBlendInfo blendKey = {}; - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + if (dirtyCb) { - if (i < rts.size()) - { - RenderTarget11 *rt = rts[i].renderTarget; - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat()); - - blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits > 0); - blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0); - blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits > 0); - blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0); - } - else + // Update the constant buffer with the updated cache contents + // TODO(Shahmeer): Consider using UpdateSubresource1 D3D11_COPY_DISCARD where possible. + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, + &mappedResource); + if (FAILED(result)) { - blendKey.maskChannels[i][0] = false; - blendKey.maskChannels[i][1] = false; - blendKey.maskChannels[i][2] = false; - blendKey.maskChannels[i][3] = false; + return gl::OutOfMemory() << "Clear11: Failed to map CB, " << gl::FmtHR(result); } - } - ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey); - if (i != mClearBlendStates.end()) - { - return i->second; + memcpy(mappedResource.pData, &mShaderData, g_ConstantBufferSize); + deviceContext->Unmap(mConstantBuffer.get(), 0); } - else - { - D3D11_BLEND_DESC blendDesc = { 0 }; - blendDesc.AlphaToCoverageEnable = FALSE; - blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE; - for (unsigned int j = 0; j < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; j++) - { - blendDesc.RenderTarget[j].BlendEnable = FALSE; - blendDesc.RenderTarget[j].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[j][0], - blendKey.maskChannels[j][1], - blendKey.maskChannels[j][2], - blendKey.maskChannels[j][3]); - } + auto *stateManager = mRenderer->getStateManager(); - ID3D11Device *device = mRenderer->getDevice(); - ID3D11BlendState* blendState = nullptr; - HRESULT result = device->CreateBlendState(&blendDesc, &blendState); - if (FAILED(result) || !blendState) - { - ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); - return nullptr; - } + // Set the viewport to be the same size as the framebuffer. + stateManager->setSimpleViewport(framebufferSize); - mClearBlendStates[blendKey] = blendState; + // Apply state + stateManager->setSimpleBlendState(blendState); - return blendState; - } -} + const UINT stencilValue = clearParams.stencilValue & 0xFF; + stateManager->setDepthStencilState(dsState, stencilValue); -ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &clearParams) -{ - ClearDepthStencilInfo dsKey = { 0 }; - dsKey.clearDepth = clearParams.clearDepth; - dsKey.clearStencil = clearParams.clearStencil; - dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF; + if (needScissoredClear) + { + stateManager->setRasterizerState(&mScissorEnabledRasterizerState); + } + else + { + stateManager->setRasterizerState(&mScissorDisabledRasterizerState); + } - ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey); - if (i != mClearDepthStencilStates.end()) + // Get Shaders + const d3d11::VertexShader *vs = nullptr; + const d3d11::GeometryShader *gs = nullptr; + const d3d11::InputLayout *il = nullptr; + const d3d11::PixelShader *ps = nullptr; + const bool hasLayeredLayout = + (fboData.getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE); + ANGLE_TRY(mShaderManager.getShadersAndLayout(mRenderer, clearParams.colorType, numRtvs, + hasLayeredLayout, &il, &vs, &gs, &ps)); + + // Apply Shaders + stateManager->setDrawShaders(vs, gs, ps); + stateManager->setPixelConstantBuffer(0, &mConstantBuffer); + + // Bind IL & VB if needed + stateManager->setIndexBuffer(nullptr, DXGI_FORMAT_UNKNOWN, 0); + stateManager->setInputLayout(il); + + if (useVertexBuffer()) { - return i->second; + ANGLE_TRY(ensureVertexBufferCreated()); + stateManager->setSingleVertexBuffer(&mVertexBuffer, g_VertexSize, 0); } else { - D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; - dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE; - dsDesc.DepthWriteMask = dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; - dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; - dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE; - dsDesc.StencilReadMask = 0; - dsDesc.StencilWriteMask = dsKey.stencilWriteMask; - dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; - dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DepthStencilState* dsState = nullptr; - HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState); - if (FAILED(result) || !dsState) - { - ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - return nullptr; - } + stateManager->setSingleVertexBuffer(nullptr, 0, 0); + } - mClearDepthStencilStates[dsKey] = dsState; + stateManager->setPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - return dsState; + // Apply render targets + stateManager->setRenderTargets(&rtvs[0], numRtvs, dsv); + + // If scissors are necessary to be applied, then the number of clears is the number of scissor + // rects. If no scissors are necessary, then a single full-size clear is enough. + size_t necessaryNumClears = needScissoredClear ? scissorRects.size() : 1u; + for (size_t i = 0u; i < necessaryNumClears; ++i) + { + if (needScissoredClear) + { + ASSERT(i < scissorRects.size()); + stateManager->setScissorRectD3D(scissorRects[i]); + } + // Draw the fullscreen quad. + if (!hasLayeredLayout || isSideBySideFBO) + { + deviceContext->Draw(6, 0); + } + else + { + ASSERT(hasLayeredLayout); + deviceContext->DrawInstanced(6, static_cast(fboData.getNumViews()), 0, 0); + } } -} + return gl::NoError(); } + +} // namespace rx 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 3ff73c85d1..a09812c42b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h @@ -23,6 +23,14 @@ class Renderer11; class RenderTarget11; struct ClearParameters; +template +struct RtvDsvClearInfo +{ + T r, g, b, a; + float z; + float c1padding[3]; +}; + class Clear11 : angle::NonCopyable { public: @@ -30,68 +38,63 @@ class Clear11 : angle::NonCopyable ~Clear11(); // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. - gl::Error clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData); + gl::Error clearFramebuffer(const gl::Context *context, + const ClearParameters &clearParams, + const gl::FramebufferState &fboData); private: - struct MaskedRenderTarget - { - bool colorMask[4]; - RenderTarget11 *renderTarget; - }; - - ID3D11BlendState *getBlendState(const std::vector &rts); - ID3D11DepthStencilState *getDepthStencilState(const ClearParameters &clearParams); - - struct ClearShader final : public angle::NonCopyable + class ShaderManager final : angle::NonCopyable { - 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; + public: + ShaderManager(); + ~ShaderManager(); + gl::Error getShadersAndLayout(Renderer11 *renderer, + const INT clearType, + const uint32_t numRTs, + const bool hasLayeredLayout, + const d3d11::InputLayout **il, + const d3d11::VertexShader **vs, + const d3d11::GeometryShader **gs, + const d3d11::PixelShader **ps); + + private: + constexpr static size_t kNumShaders = D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; + + d3d11::InputLayout mIl9; + d3d11::LazyShader mVs9; + d3d11::LazyShader mPsFloat9; + d3d11::LazyShader mVs; + d3d11::LazyShader mVsMultiview; + d3d11::LazyShader mGsMultiview; + d3d11::LazyShader mPsDepth; + std::array, kNumShaders> mPsFloat; + std::array, kNumShaders> mPsUInt; + std::array, kNumShaders> mPsSInt; }; - template - static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE(&vsByteCode)[vsSize], const BYTE(&psByteCode)[psSize]); - - struct ClearBlendInfo - { - bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; - }; - typedef bool(*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &); - typedef std::map ClearBlendStateMap; - - struct ClearDepthStencilInfo - { - bool clearDepth; - bool clearStencil; - UINT8 stencilWriteMask; - }; - typedef bool(*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &); - typedef std::map ClearDepthStencilStateMap; + bool useVertexBuffer() const; + gl::Error ensureConstantBufferCreated(); + gl::Error ensureVertexBufferCreated(); + gl::Error ensureResourcesInitialized(); Renderer11 *mRenderer; + bool mResourcesInitialized; - ClearBlendStateMap mClearBlendStates; - - ClearShader *mFloatClearShader; - ClearShader *mUintClearShader; - ClearShader *mIntClearShader; + // States + d3d11::RasterizerState mScissorEnabledRasterizerState; + d3d11::RasterizerState mScissorDisabledRasterizerState; + gl::DepthStencilState mDepthStencilStateKey; + d3d11::BlendStateKey mBlendStateKey; - ClearDepthStencilStateMap mClearDepthStencilStates; + // Shaders and shader resources + ShaderManager mShaderManager; + d3d11::Buffer mConstantBuffer; + d3d11::Buffer mVertexBuffer; - ID3D11Buffer *mVertexBuffer; - ID3D11RasterizerState *mRasterizerState; + // Buffer data and draw parameters + RtvDsvClearInfo mShaderData; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp new file mode 100644 index 0000000000..b79dd3603a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp @@ -0,0 +1,405 @@ +// +// Copyright 2016 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. +// +// Context11: +// D3D11-specific functionality associated with a GL Context. +// + +#include "libANGLE/renderer/d3d/d3d11/Context11.h" + +#include "common/string_utils.h" +#include "libANGLE/Context.h" +#include "libANGLE/MemoryProgramCache.h" +#include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/SamplerD3D.h" +#include "libANGLE/renderer/d3d/ShaderD3D.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Fence11.h" +#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" +#include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/StateManager11.h" +#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" + +namespace rx +{ + +Context11::Context11(const gl::ContextState &state, Renderer11 *renderer) + : ContextImpl(state), mRenderer(renderer) +{ +} + +Context11::~Context11() +{ +} + +gl::Error Context11::initialize() +{ + return gl::NoError(); +} + +CompilerImpl *Context11::createCompiler() +{ + if (mRenderer->getRenderer11DeviceCaps().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); + } +} + +ShaderImpl *Context11::createShader(const gl::ShaderState &data) +{ + return new ShaderD3D(data, mRenderer->getWorkarounds(), mRenderer->getNativeExtensions()); +} + +ProgramImpl *Context11::createProgram(const gl::ProgramState &data) +{ + return new ProgramD3D(data, mRenderer); +} + +FramebufferImpl *Context11::createFramebuffer(const gl::FramebufferState &data) +{ + return new Framebuffer11(data, mRenderer); +} + +TextureImpl *Context11::createTexture(const gl::TextureState &state) +{ + switch (state.getTarget()) + { + case GL_TEXTURE_2D: + return new TextureD3D_2D(state, mRenderer); + case GL_TEXTURE_CUBE_MAP: + return new TextureD3D_Cube(state, mRenderer); + case GL_TEXTURE_3D: + return new TextureD3D_3D(state, mRenderer); + case GL_TEXTURE_2D_ARRAY: + return new TextureD3D_2DArray(state, mRenderer); + case GL_TEXTURE_EXTERNAL_OES: + return new TextureD3D_External(state, mRenderer); + case GL_TEXTURE_2D_MULTISAMPLE: + return new TextureD3D_2DMultisample(state, mRenderer); + break; + default: + UNREACHABLE(); + } + + return nullptr; +} + +RenderbufferImpl *Context11::createRenderbuffer() +{ + return new RenderbufferD3D(mRenderer); +} + +BufferImpl *Context11::createBuffer(const gl::BufferState &state) +{ + Buffer11 *buffer = new Buffer11(state, mRenderer); + mRenderer->onBufferCreate(buffer); + return buffer; +} + +VertexArrayImpl *Context11::createVertexArray(const gl::VertexArrayState &data) +{ + return new VertexArray11(data); +} + +QueryImpl *Context11::createQuery(GLenum type) +{ + return new Query11(mRenderer, type); +} + +FenceNVImpl *Context11::createFenceNV() +{ + return new FenceNV11(mRenderer); +} + +SyncImpl *Context11::createSync() +{ + return new Sync11(mRenderer); +} + +TransformFeedbackImpl *Context11::createTransformFeedback(const gl::TransformFeedbackState &state) +{ + return new TransformFeedback11(state, mRenderer); +} + +SamplerImpl *Context11::createSampler(const gl::SamplerState &state) +{ + return new SamplerD3D(state); +} + +ProgramPipelineImpl *Context11::createProgramPipeline(const gl::ProgramPipelineState &data) +{ + return new ProgramPipeline11(data); +} + +std::vector Context11::createPaths(GLsizei) +{ + return std::vector(); +} + +gl::Error Context11::flush(const gl::Context *context) +{ + return mRenderer->flush(); +} + +gl::Error Context11::finish(const gl::Context *context) +{ + return mRenderer->finish(); +} + +gl::Error Context11::drawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawArrays(context, mode, first, count, 0); +} + +gl::Error Context11::drawArraysInstanced(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawArrays(context, mode, first, count, instanceCount); +} + +gl::Error Context11::drawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawElements(context, mode, count, type, indices, 0); +} + +gl::Error Context11::drawElementsInstanced(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawElements(context, mode, count, type, indices, instances); +} + +gl::Error Context11::drawRangeElements(const gl::Context *context, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void *indices) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawElements(context, mode, count, type, indices, 0); +} + +gl::Error Context11::drawArraysIndirect(const gl::Context *context, + GLenum mode, + const void *indirect) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawArraysIndirect(context, mode, indirect); +} + +gl::Error Context11::drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect) +{ + ANGLE_TRY(prepareForDrawCall(context, mode)); + return mRenderer->drawElementsIndirect(context, mode, type, indirect); +} + +GLenum Context11::getResetStatus() +{ + return mRenderer->getResetStatus(); +} + +std::string Context11::getVendorString() const +{ + return mRenderer->getVendorString(); +} + +std::string Context11::getRendererDescription() const +{ + return mRenderer->getRendererDescription(); +} + +void Context11::insertEventMarker(GLsizei length, const char *marker) +{ + auto optionalString = angle::WidenString(static_cast(length), marker); + if (optionalString.valid()) + { + mRenderer->getAnnotator()->setMarker(optionalString.value().data()); + } +} + +void Context11::pushGroupMarker(GLsizei length, const char *marker) +{ + auto optionalString = angle::WidenString(static_cast(length), marker); + if (optionalString.valid()) + { + mRenderer->getAnnotator()->beginEvent(optionalString.value().data()); + } +} + +void Context11::popGroupMarker() +{ + mRenderer->getAnnotator()->endEvent(); +} + +void Context11::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) +{ + // Fall through to the EXT_debug_marker functions + pushGroupMarker(length, message); +} + +void Context11::popDebugGroup() +{ + // Fall through to the EXT_debug_marker functions + popGroupMarker(); +} + +void Context11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) +{ + mRenderer->getStateManager()->syncState(context, dirtyBits); +} + +GLint Context11::getGPUDisjoint() +{ + return mRenderer->getGPUDisjoint(); +} + +GLint64 Context11::getTimestamp() +{ + return mRenderer->getTimestamp(); +} + +void Context11::onMakeCurrent(const gl::Context *context) +{ + ANGLE_SWALLOW_ERR(mRenderer->getStateManager()->onMakeCurrent(context)); +} + +const gl::Caps &Context11::getNativeCaps() const +{ + return mRenderer->getNativeCaps(); +} + +const gl::TextureCapsMap &Context11::getNativeTextureCaps() const +{ + return mRenderer->getNativeTextureCaps(); +} + +const gl::Extensions &Context11::getNativeExtensions() const +{ + return mRenderer->getNativeExtensions(); +} + +const gl::Limitations &Context11::getNativeLimitations() const +{ + return mRenderer->getNativeLimitations(); +} + +gl::Error Context11::dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) +{ + return mRenderer->dispatchCompute(context, numGroupsX, numGroupsY, numGroupsZ); +} + +gl::Error Context11::triggerDrawCallProgramRecompilation(const gl::Context *context, + GLenum drawMode) +{ + const auto &glState = context->getGLState(); + const auto *va11 = GetImplAs(glState.getVertexArray()); + const auto *drawFBO = glState.getDrawFramebuffer(); + gl::Program *program = glState.getProgram(); + ProgramD3D *programD3D = GetImplAs(program); + + programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState); + programD3D->updateCachedOutputLayout(context, drawFBO); + + bool recompileVS = !programD3D->hasVertexExecutableForCachedInputLayout(); + bool recompileGS = !programD3D->hasGeometryExecutableForPrimitiveType(drawMode); + bool recompilePS = !programD3D->hasPixelExecutableForCachedOutputLayout(); + + if (!recompileVS && !recompileGS && !recompilePS) + { + return gl::NoError(); + } + + // Load the compiler if necessary and recompile the programs. + ANGLE_TRY(mRenderer->ensureHLSLCompilerInitialized()); + + gl::InfoLog infoLog; + + if (recompileVS) + { + ShaderExecutableD3D *vertexExe = nullptr; + ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, &infoLog)); + if (!programD3D->hasVertexExecutableForCachedInputLayout()) + { + ASSERT(infoLog.getLength() > 0); + ERR() << "Dynamic recompilation error log: " << infoLog.str(); + return gl::InternalError() + << "Error compiling dynamic vertex executable:" << infoLog.str(); + } + } + + if (recompileGS) + { + ShaderExecutableD3D *geometryExe = nullptr; + ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe, + &infoLog)); + if (!programD3D->hasGeometryExecutableForPrimitiveType(drawMode)) + { + ASSERT(infoLog.getLength() > 0); + ERR() << "Dynamic recompilation error log: " << infoLog.str(); + return gl::InternalError() + << "Error compiling dynamic geometry executable:" << infoLog.str(); + } + } + + if (recompilePS) + { + ShaderExecutableD3D *pixelExe = nullptr; + ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, &infoLog)); + if (!programD3D->hasPixelExecutableForCachedOutputLayout()) + { + ASSERT(infoLog.getLength() > 0); + ERR() << "Dynamic recompilation error log: " << infoLog.str(); + return gl::InternalError() + << "Error compiling dynamic pixel executable:" << infoLog.str(); + } + } + + // Refresh the program cache entry. + if (mMemoryProgramCache) + { + mMemoryProgramCache->updateProgram(context, program); + } + + return gl::NoError(); +} + +gl::Error Context11::prepareForDrawCall(const gl::Context *context, GLenum drawMode) +{ + ANGLE_TRY(mRenderer->getStateManager()->updateState(context, drawMode)); + return gl::NoError(); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h new file mode 100644 index 0000000000..dd99111b19 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h @@ -0,0 +1,155 @@ +// +// Copyright 2016 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. +// +// Context11: +// D3D11-specific functionality associated with a GL Context. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_ + +#include "libANGLE/renderer/ContextImpl.h" + +namespace rx +{ +class Renderer11; + +class Context11 : public ContextImpl +{ + public: + Context11(const gl::ContextState &state, Renderer11 *renderer); + ~Context11() override; + + gl::Error initialize() override; + + // Shader creation + CompilerImpl *createCompiler() override; + ShaderImpl *createShader(const gl::ShaderState &data) override; + ProgramImpl *createProgram(const gl::ProgramState &data) override; + + // Framebuffer creation + FramebufferImpl *createFramebuffer(const gl::FramebufferState &data) override; + + // Texture creation + TextureImpl *createTexture(const gl::TextureState &state) override; + + // Renderbuffer creation + RenderbufferImpl *createRenderbuffer() override; + + // Buffer creation + BufferImpl *createBuffer(const gl::BufferState &state) override; + + // Vertex Array creation + VertexArrayImpl *createVertexArray(const gl::VertexArrayState &data) override; + + // Query and Fence creation + QueryImpl *createQuery(GLenum type) override; + FenceNVImpl *createFenceNV() override; + SyncImpl *createSync() override; + + // Transform Feedback creation + TransformFeedbackImpl *createTransformFeedback( + const gl::TransformFeedbackState &state) override; + + // Sampler object creation + SamplerImpl *createSampler(const gl::SamplerState &state) override; + + // Program Pipeline object creation + ProgramPipelineImpl *createProgramPipeline(const gl::ProgramPipelineState &data) override; + + // Path object creation. + std::vector createPaths(GLsizei) override; + + // Flush and finish. + gl::Error flush(const gl::Context *context) override; + gl::Error finish(const gl::Context *context) override; + + // Drawing methods. + gl::Error drawArrays(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count) override; + gl::Error drawArraysInstanced(const gl::Context *context, + GLenum mode, + GLint first, + GLsizei count, + GLsizei instanceCount) override; + + gl::Error drawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices) override; + gl::Error drawElementsInstanced(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances) override; + gl::Error drawRangeElements(const gl::Context *context, + GLenum mode, + GLuint start, + GLuint end, + GLsizei count, + GLenum type, + const void *indices) override; + gl::Error drawArraysIndirect(const gl::Context *context, + GLenum mode, + const void *indirect) override; + gl::Error drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect) override; + + // Device loss + GLenum getResetStatus() override; + + // Vendor and description strings. + std::string getVendorString() const override; + std::string getRendererDescription() const override; + + // EXT_debug_marker + void insertEventMarker(GLsizei length, const char *marker) override; + void pushGroupMarker(GLsizei length, const char *marker) override; + void popGroupMarker() override; + + // KHR_debug + void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override; + void popDebugGroup() override; + + // State sync with dirty bits. + void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) override; + + // Disjoint timer queries + GLint getGPUDisjoint() override; + GLint64 getTimestamp() override; + + // Context switching + void onMakeCurrent(const gl::Context *context) override; + + // Caps queries + const gl::Caps &getNativeCaps() const override; + const gl::TextureCapsMap &getNativeTextureCaps() const override; + const gl::Extensions &getNativeExtensions() const override; + const gl::Limitations &getNativeLimitations() const override; + + Renderer11 *getRenderer() const { return mRenderer; } + + gl::Error dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) override; + + gl::Error triggerDrawCallProgramRecompilation(const gl::Context *context, GLenum drawMode); + + private: + gl::Error prepareForDrawCall(const gl::Context *context, GLenum drawMode); + + Renderer11 *mRenderer; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_CONTEXT11_H_ 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 1c35ab45cc..1e70363e11 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp @@ -27,9 +27,7 @@ DebugAnnotator11::~DebugAnnotator11() { if (mInitialized) { -#if defined(ANGLE_ENABLE_D3D11_1) SafeRelease(mUserDefinedAnnotation); -#endif #if !defined(ANGLE_ENABLE_WINDOWS_STORE) FreeLibrary(mD3d11Module); @@ -43,9 +41,7 @@ void DebugAnnotator11::beginEvent(const wchar_t *eventName) if (mUserDefinedAnnotation != nullptr) { -#if defined(ANGLE_ENABLE_D3D11_1) mUserDefinedAnnotation->BeginEvent(eventName); -#endif } } @@ -55,9 +51,7 @@ void DebugAnnotator11::endEvent() if (mUserDefinedAnnotation != nullptr) { -#if defined(ANGLE_ENABLE_D3D11_1) mUserDefinedAnnotation->EndEvent(); -#endif } } @@ -67,16 +61,14 @@ void DebugAnnotator11::setMarker(const wchar_t *markerName) if (mUserDefinedAnnotation != nullptr) { -#if defined(ANGLE_ENABLE_D3D11_1) mUserDefinedAnnotation->SetMarker(markerName); -#endif } } bool DebugAnnotator11::getStatus() { #if defined(ANGLE_ENABLE_WINDOWS_STORE) -#if (NTDDI_VERSION == NTDDI_WIN10) + static_assert(NTDDI_VERSION >= NTDDI_WIN10, "GetStatus only works on Win10 and above"); initializeDevice(); if (mUserDefinedAnnotation != nullptr) @@ -85,38 +77,6 @@ bool DebugAnnotator11::getStatus() } return true; // Default if initializeDevice() failed -#elif defined(_DEBUG) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) - static bool underCapture = true; - - // 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. - - // 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); - } - - 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; @@ -141,14 +101,13 @@ void DebugAnnotator11::initializeDevice() HRESULT hr = E_FAIL; // 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); + hr = D3D11CreateDevice(nullptr, 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); -#endif 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 d1a0f7fd2e..62662c49ae 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h @@ -9,14 +9,12 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_ -#include "common/debug.h" - -struct ID3DUserDefinedAnnotation; +#include "libANGLE/LoggingAnnotator.h" namespace rx { -class DebugAnnotator11 : public gl::DebugAnnotator +class DebugAnnotator11 : public angle::LoggingAnnotator { public: DebugAnnotator11(); 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 53fac65f2a..082f28d794 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp @@ -4,7 +4,8 @@ // found in the LICENSE file. // -// Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. +// Fence11.cpp: Defines the rx::FenceNV11 and rx::Sync11 classes which implement +// rx::FenceNVImpl and rx::SyncImpl. #include "libANGLE/renderer/d3d/d3d11/Fence11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" @@ -14,28 +15,30 @@ namespace rx { +static const int kDeviceLostCheckPeriod = 64; + // // Template helpers for set and test operations. // -template +template gl::Error FenceSetHelper(FenceClass *fence) { if (!fence->mQuery) { D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.Query = D3D11_QUERY_EVENT; queryDesc.MiscFlags = 0; HRESULT result = fence->mRenderer->getDevice()->CreateQuery(&queryDesc, &fence->mQuery); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to create event query, " << gl::FmtHR(result); } } fence->mRenderer->getDeviceContext()->End(fence->mQuery); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } template @@ -44,30 +47,24 @@ gl::Error FenceTestHelper(FenceClass *fence, bool flushCommandBuffer, GLboolean ASSERT(fence->mQuery); UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH); - HRESULT result = fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, NULL, 0, getDataFlags); + HRESULT result = + fence->mRenderer->getDeviceContext()->GetData(fence->mQuery, nullptr, 0, getDataFlags); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get query data, result: 0x%X.", result); - } - else if (fence->mRenderer->isDeviceLost()) - { - return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while querying result of an event query."); + return gl::OutOfMemory() << "Failed to get query data, " << gl::FmtHR(result); } ASSERT(result == S_OK || result == S_FALSE); *outFinished = ((result == S_OK) ? GL_TRUE : GL_FALSE); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // // FenceNV11 // -FenceNV11::FenceNV11(Renderer11 *renderer) - : FenceNVImpl(), - mRenderer(renderer), - mQuery(NULL) +FenceNV11::FenceNV11(Renderer11 *renderer) : FenceNVImpl(), mRenderer(renderer), mQuery(nullptr) { } @@ -89,22 +86,26 @@ gl::Error FenceNV11::test(GLboolean *outFinished) gl::Error FenceNV11::finish() { GLboolean finished = GL_FALSE; + + int loopCount = 0; while (finished != GL_TRUE) { - gl::Error error = FenceTestHelper(this, true, &finished); - if (error.isError()) + loopCount++; + ANGLE_TRY(FenceTestHelper(this, true, &finished)); + + if (loopCount % kDeviceLostCheckPeriod == 0 && mRenderer->testDeviceLost()) { - return error; + return gl::OutOfMemory() << "Device was lost while querying result of an event query."; } ScheduleYield(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } // -// FenceSync11 +// Sync11 // // Important note on accurate timers in Windows: @@ -118,38 +119,34 @@ gl::Error FenceNV11::finish() // We still opt to use QPC. In the present and moving forward, most newer systems will not suffer // from buggy implementations. -FenceSync11::FenceSync11(Renderer11 *renderer) - : FenceSyncImpl(), - mRenderer(renderer), - mQuery(NULL) +Sync11::Sync11(Renderer11 *renderer) : SyncImpl(), mRenderer(renderer), mQuery(nullptr) { LARGE_INTEGER counterFreqency = {}; - BOOL success = QueryPerformanceFrequency(&counterFreqency); - UNUSED_ASSERTION_VARIABLE(success); + BOOL success = QueryPerformanceFrequency(&counterFreqency); ASSERT(success); mCounterFrequency = counterFreqency.QuadPart; } -FenceSync11::~FenceSync11() +Sync11::~Sync11() { SafeRelease(mQuery); } -gl::Error FenceSync11::set(GLenum condition, GLbitfield flags) +gl::Error Sync11::set(GLenum condition, GLbitfield flags) { ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE && flags == 0); return FenceSetHelper(this); } -gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) +gl::Error Sync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) { ASSERT(outResult); bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0); GLboolean result = GL_FALSE; - gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result); + gl::Error error = FenceTestHelper(this, flushCommandBuffer, &result); if (error.isError()) { *outResult = GL_WAIT_FAILED; @@ -159,28 +156,34 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou if (result == GL_TRUE) { *outResult = GL_ALREADY_SIGNALED; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } if (timeout == 0) { *outResult = GL_TIMEOUT_EXPIRED; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } LARGE_INTEGER currentCounter = {}; - BOOL success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); + BOOL success = QueryPerformanceCounter(¤tCounter); ASSERT(success); - LONGLONG timeoutInSeconds = static_cast(timeout) * static_cast(1000000ll); - LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; + LONGLONG timeoutInSeconds = static_cast(timeout / 1000000000ull); + LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; + // Extremely unlikely, but if mCounterFrequency is large enough, endCounter can wrap + if (endCounter < currentCounter.QuadPart) + { + endCounter = MAXLONGLONG; + } + + int loopCount = 0; while (currentCounter.QuadPart < endCounter && !result) { + loopCount++; ScheduleYield(); success = QueryPerformanceCounter(¤tCounter); - UNUSED_ASSERTION_VARIABLE(success); ASSERT(success); error = FenceTestHelper(this, flushCommandBuffer, &result); @@ -189,6 +192,12 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou *outResult = GL_WAIT_FAILED; return error; } + + if ((loopCount % kDeviceLostCheckPeriod) == 0 && mRenderer->testDeviceLost()) + { + *outResult = GL_WAIT_FAILED; + return gl::OutOfMemory() << "Device was lost while querying result of an event query."; + } } if (currentCounter.QuadPart >= endCounter) @@ -200,32 +209,32 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou *outResult = GL_CONDITION_SATISFIED; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error FenceSync11::serverWait(GLbitfield flags, GLuint64 timeout) +gl::Error Sync11::serverWait(GLbitfield flags, GLuint64 timeout) { // Because our API is currently designed to be called from a single thread, we don't need to do - // extra work for a server-side fence. GPU commands issued after the fence is created will always - // be processed after the fence is signaled. - return gl::Error(GL_NO_ERROR); + // extra work for a server-side fence. GPU commands issued after the fence is created will + // always be processed after the fence is signaled. + return gl::NoError(); } -gl::Error FenceSync11::getStatus(GLint *outResult) +gl::Error Sync11::getStatus(GLint *outResult) { GLboolean result = GL_FALSE; - gl::Error error = FenceTestHelper(this, false, &result); + gl::Error error = FenceTestHelper(this, false, &result); if (error.isError()) { - // The spec does not specify any way to report errors during the status test (e.g. device lost) - // so we report the fence is unblocked in case of error or signaled. + // The spec does not specify any way to report errors during the status test (e.g. device + // lost) so we report the fence is unblocked in case of error or signaled. *outResult = GL_SIGNALED; return error; } *outResult = (result ? GL_SIGNALED : GL_UNSIGNALED); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -} // namespace rx +} // namespace rx 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 595978885b..4168df5365 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h @@ -4,13 +4,14 @@ // found in the LICENSE file. // -// Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl. +// Fence11.h: Defines the rx::FenceNV11 and rx::Sync11 classes which implement rx::FenceNVImpl +// and rx::SyncImpl. #ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_ #include "libANGLE/renderer/FenceNVImpl.h" -#include "libANGLE/renderer/FenceSyncImpl.h" +#include "libANGLE/renderer/SyncImpl.h" namespace rx { @@ -34,11 +35,11 @@ class FenceNV11 : public FenceNVImpl ID3D11Query *mQuery; }; -class FenceSync11 : public FenceSyncImpl +class Sync11 : public SyncImpl { public: - explicit FenceSync11(Renderer11 *renderer); - ~FenceSync11() override; + explicit Sync11(Renderer11 *renderer); + ~Sync11() override; gl::Error set(GLenum condition, GLbitfield flags) override; gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) override; 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 186a035902..02326d7b50 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp @@ -8,94 +8,119 @@ #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" +#include "common/bitset_utils.h" #include "common/debug.h" +#include "libANGLE/Context.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/FramebufferAttachment.h" +#include "libANGLE/Texture.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" #include "libANGLE/renderer/d3d/d3d11/Buffer11.h" #include "libANGLE/renderer/d3d/d3d11/Clear11.h" -#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.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/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/renderer/d3d/TextureD3D.h" -#include "libANGLE/Framebuffer.h" -#include "libANGLE/FramebufferAttachment.h" -#include "libANGLE/Texture.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +using namespace angle; namespace rx { -Framebuffer11::Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer) - : FramebufferD3D(data, renderer), mRenderer(renderer) +namespace { - ASSERT(mRenderer != nullptr); -} - -Framebuffer11::~Framebuffer11() +gl::Error MarkAttachmentsDirty(const gl::Context *context, + const gl::FramebufferAttachment *attachment) { -} - -static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *attachment) -{ - if (attachment && attachment->type() == GL_TEXTURE) + if (attachment->type() == GL_TEXTURE) { gl::Texture *texture = attachment->getTexture(); TextureD3D *textureD3D = GetImplAs(texture); TextureStorage *texStorage = nullptr; - gl::Error error = textureD3D->getNativeTexture(&texStorage); - if (error.isError()) - { - return error; - } + ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage)); if (texStorage) { TextureStorage11 *texStorage11 = GetAs(texStorage); ASSERT(texStorage11); - texStorage11->invalidateSwizzleCacheLevel(attachment->mipLevel()); + texStorage11->markLevelDirty(attachment->mipLevel()); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer11::invalidateSwizzles() const +void UpdateCachedRenderTarget(const gl::Context *context, + const gl::FramebufferAttachment *attachment, + RenderTarget11 *&cachedRenderTarget, + OnRenderTargetDirtyBinding *channelBinding) { - for (const auto &colorAttachment : mData.getColorAttachments()) + RenderTarget11 *newRenderTarget = nullptr; + if (attachment) { - if (colorAttachment.isAttached()) + // TODO(jmadill): Don't swallow this error. + gl::Error error = attachment->getRenderTarget(context, &newRenderTarget); + if (error.isError()) { - gl::Error error = InvalidateAttachmentSwizzles(&colorAttachment); - if (error.isError()) - { - return error; - } + ERR() << "Internal rendertarget error: " << error; } } + if (newRenderTarget != cachedRenderTarget) + { + OnRenderTargetDirtyChannel *channel = + (newRenderTarget ? newRenderTarget->getBroadcastChannel() : nullptr); + channelBinding->bind(channel); + cachedRenderTarget = newRenderTarget; + } +} +} // anonymous namespace + +Framebuffer11::Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer) + : FramebufferD3D(data, renderer), + mRenderer(renderer), + mCachedDepthStencilRenderTarget(nullptr), + mDepthStencilRenderTargetDirty(this, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) +{ + ASSERT(mRenderer != nullptr); + mCachedColorRenderTargets.fill(nullptr); + for (size_t colorIndex = 0; colorIndex < data.getColorAttachments().size(); ++colorIndex) + { + mColorRenderTargetsDirty.emplace_back(this, colorIndex); + } +} - gl::Error error = InvalidateAttachmentSwizzles(mData.getDepthAttachment()); - if (error.isError()) +Framebuffer11::~Framebuffer11() +{ +} + +gl::Error Framebuffer11::markAttachmentsDirty(const gl::Context *context) const +{ + const auto &colorAttachments = mState.getColorAttachments(); + for (size_t drawBuffer : mState.getEnabledDrawBuffers()) { - return error; + const gl::FramebufferAttachment &colorAttachment = colorAttachments[drawBuffer]; + ASSERT(colorAttachment.isAttached()); + ANGLE_TRY(MarkAttachmentsDirty(context, &colorAttachment)); } - error = InvalidateAttachmentSwizzles(mData.getStencilAttachment()); - if (error.isError()) + const gl::FramebufferAttachment *dsAttachment = mState.getDepthOrStencilAttachment(); + if (dsAttachment) { - return error; + ANGLE_TRY(MarkAttachmentsDirty(context, dsAttachment)); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clearParams) +gl::Error Framebuffer11::clearImpl(const gl::Context *context, const ClearParameters &clearParams) { Clear11 *clearer = mRenderer->getClearer(); - gl::Error error(GL_NO_ERROR); - const gl::FramebufferAttachment *colorAttachment = mData.getFirstColorAttachment(); + const gl::FramebufferAttachment *colorAttachment = mState.getFirstColorAttachment(); if (clearParams.scissorEnabled == true && colorAttachment != nullptr && UsePresentPathFast(mRenderer, colorAttachment)) { @@ -107,46 +132,43 @@ gl::Error Framebuffer11::clear(const gl::Data &data, const ClearParameters &clea presentPathFastClearParams.scissor.y = framebufferSize.height - presentPathFastClearParams.scissor.y - presentPathFastClearParams.scissor.height; - error = clearer->clearFramebuffer(presentPathFastClearParams, mData); + ANGLE_TRY(clearer->clearFramebuffer(context, presentPathFastClearParams, mState)); } else { - error = clearer->clearFramebuffer(clearParams, mData); + ANGLE_TRY(clearer->clearFramebuffer(context, clearParams, mState)); } - if (error.isError()) - { - return error; - } - - error = invalidateSwizzles(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(markAttachmentsDirty(context)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer11::invalidate(size_t count, const GLenum *attachments) +gl::Error Framebuffer11::invalidate(const gl::Context *context, + size_t count, + const GLenum *attachments) { - return invalidateBase(count, attachments, false); + return invalidateBase(context, count, attachments, false); } -gl::Error Framebuffer11::discard(size_t count, const GLenum *attachments) +gl::Error Framebuffer11::discard(const gl::Context *context, + size_t count, + const GLenum *attachments) { - return invalidateBase(count, attachments, true); + return invalidateBase(context, count, attachments, true); } -gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, bool useEXTBehavior) const +gl::Error Framebuffer11::invalidateBase(const gl::Context *context, + size_t count, + const GLenum *attachments, + bool useEXTBehavior) const { -#if defined(ANGLE_ENABLE_D3D11_1) ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); if (!deviceContext1) { // DiscardView() is only supported on ID3D11DeviceContext1 - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } bool foundDepth = false; @@ -175,37 +197,14 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, ASSERT((attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) || (attachments[i] == GL_COLOR)); - RenderTarget11 *renderTarget = nullptr; - ID3D11View *colorView = nullptr; - gl::Error error(GL_NO_ERROR); - size_t colorAttachmentID = 0; - - if (attachments[i] == GL_COLOR) - { - colorAttachmentID = 0; - } - else + size_t colorIndex = + (attachments[i] == GL_COLOR ? 0u : (attachments[i] - GL_COLOR_ATTACHMENT0)); + const gl::FramebufferAttachment *colorAttachment = + mState.getColorAttachment(colorIndex); + if (colorAttachment) { - colorAttachmentID = attachments[i] - GL_COLOR_ATTACHMENT0; + ANGLE_TRY(invalidateAttachment(context, colorAttachment)); } - - 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); - } - } - break; } } @@ -222,7 +221,7 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, discardDepth = foundDepth; // Don't bother discarding the stencil buffer if the depth buffer will already do it - discardStencil = foundStencil && (!discardDepth || mData.getDepthAttachment() == nullptr); + discardStencil = foundStencil && (!discardDepth || mState.getDepthAttachment() == nullptr); } else { @@ -230,94 +229,86 @@ gl::Error Framebuffer11::invalidateBase(size_t count, const GLenum *attachments, // 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)); + discardDepth = (foundDepth && foundStencil) || + (foundDepth && (mState.getStencilAttachment() == nullptr)); + discardStencil = (foundStencil && (mState.getDepthAttachment() == nullptr)); } - if (discardDepth && mData.getDepthAttachment()) + if (discardDepth && mState.getDepthAttachment()) { - RenderTarget11 *renderTarget = nullptr; - ID3D11View *depthView = nullptr; - gl::Error error(GL_NO_ERROR); - - error = mData.getDepthAttachment()->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - - depthView = renderTarget->getDepthStencilView(); - - if (depthView != nullptr) - { - deviceContext1->DiscardView(depthView); - } + ANGLE_TRY(invalidateAttachment(context, mState.getDepthAttachment())); } - if (discardStencil && mData.getStencilAttachment()) + if (discardStencil && mState.getStencilAttachment()) { - RenderTarget11 *renderTarget = nullptr; - ID3D11View *stencilView = nullptr; - gl::Error error(GL_NO_ERROR); - - error = mData.getStencilAttachment()->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - - stencilView = renderTarget->getDepthStencilView(); - - if (stencilView != nullptr) - { - deviceContext1->DiscardView(stencilView); - } + ANGLE_TRY(invalidateAttachment(context, mState.getStencilAttachment())); } -#endif // ANGLE_ENABLE_D3D11_1 - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Framebuffer11::invalidateSub(size_t, const GLenum *, const gl::Rectangle &) +gl::Error Framebuffer11::invalidateSub(const gl::Context *context, + 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); + return gl::NoError(); } -gl::Error Framebuffer11::readPixelsImpl(const gl::Rectangle &area, +gl::Error Framebuffer11::invalidateAttachment(const gl::Context *context, + const gl::FramebufferAttachment *attachment) const +{ + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); + ASSERT(deviceContext1); + ASSERT(attachment && attachment->isAttached()); + + RenderTarget11 *renderTarget = nullptr; + ANGLE_TRY(attachment->getRenderTarget(context, &renderTarget)); + const auto &rtv = renderTarget->getRenderTargetView(); + + if (rtv.valid()) + { + deviceContext1->DiscardView(rtv.get()); + } + + return gl::NoError(); +} + +gl::Error Framebuffer11::readPixelsImpl(const gl::Context *context, + const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, - uint8_t *pixels) const + uint8_t *pixels) { - const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment(); ASSERT(readAttachment); - gl::Buffer *packBuffer = pack.pixelBuffer.get(); + gl::Buffer *packBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack); 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)); + packBuffer, reinterpret_cast(pixels)); - return packBufferStorage->packPixels(*readAttachment, packParams); + return packBufferStorage->packPixels(context, *readAttachment, packParams); } - return mRenderer->readFromAttachment(*readAttachment, area, format, type, + return mRenderer->readFromAttachment(context, *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) +gl::Error Framebuffer11::blitImpl(const gl::Context *context, + const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + const gl::Rectangle *scissor, + bool blitRenderTarget, + bool blitDepth, + bool blitStencil, + GLenum filter, + const gl::Framebuffer *sourceFramebuffer) { if (blitRenderTarget) { @@ -325,15 +316,11 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang ASSERT(readBuffer); RenderTargetD3D *readRenderTarget = nullptr; - gl::Error error = readBuffer->getRenderTarget(&readRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget)); ASSERT(readRenderTarget); - const auto &colorAttachments = mData.getColorAttachments(); - const auto &drawBufferStates = mData.getDrawBufferStates(); + const auto &colorAttachments = mState.getColorAttachments(); + const auto &drawBufferStates = mState.getDrawBufferStates(); for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) { @@ -343,11 +330,7 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang drawBufferStates[colorAttachment] != GL_NONE) { RenderTargetD3D *drawRenderTarget = nullptr; - error = drawBuffer.getRenderTarget(&drawRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(drawBuffer.getRenderTarget(context, &drawRenderTarget)); ASSERT(drawRenderTarget); const bool invertColorSource = UsePresentPathFast(mRenderer, readBuffer); @@ -368,13 +351,9 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang actualDestArea.height = -destArea.height; } - error = mRenderer->blitRenderbufferRect(actualSourceArea, actualDestArea, - readRenderTarget, drawRenderTarget, filter, - scissor, blitRenderTarget, false, false); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mRenderer->blitRenderbufferRect( + context, actualSourceArea, actualDestArea, readRenderTarget, drawRenderTarget, + filter, scissor, blitRenderTarget, false, false)); } } } @@ -385,46 +364,144 @@ gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectang ASSERT(readBuffer); RenderTargetD3D *readRenderTarget = nullptr; - gl::Error error = readBuffer->getRenderTarget(&readRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(readBuffer->getRenderTarget(context, &readRenderTarget)); ASSERT(readRenderTarget); - const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment(); + const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment(); ASSERT(drawBuffer); RenderTargetD3D *drawRenderTarget = nullptr; - error = drawBuffer->getRenderTarget(&drawRenderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(drawBuffer->getRenderTarget(context, &drawRenderTarget)); ASSERT(drawRenderTarget); - error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget, filter, scissor, - false, blitDepth, blitStencil); - if (error.isError()) + ANGLE_TRY(mRenderer->blitRenderbufferRect(context, sourceArea, destArea, readRenderTarget, + drawRenderTarget, filter, scissor, false, + blitDepth, blitStencil)); + } + + ANGLE_TRY(markAttachmentsDirty(context)); + return gl::NoError(); +} + +GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +{ + RenderTarget11 *renderTarget11 = GetAs(renderTarget); + return renderTarget11->getFormatSet().format().fboImplementationInternalFormat; +} + +void Framebuffer11::updateColorRenderTarget(const gl::Context *context, size_t colorIndex) +{ + UpdateCachedRenderTarget(context, mState.getColorAttachment(colorIndex), + mCachedColorRenderTargets[colorIndex], + &mColorRenderTargetsDirty[colorIndex]); +} + +void Framebuffer11::updateDepthStencilRenderTarget(const gl::Context *context) +{ + UpdateCachedRenderTarget(context, mState.getDepthOrStencilAttachment(), + mCachedDepthStencilRenderTarget, &mDepthStencilRenderTargetDirty); +} + +void Framebuffer11::syncState(const gl::Context *context, + const gl::Framebuffer::DirtyBits &dirtyBits) +{ + const auto &mergedDirtyBits = dirtyBits | mInternalDirtyBits; + mInternalDirtyBits.reset(); + + for (auto dirtyBit : mergedDirtyBits) + { + switch (dirtyBit) { - return error; + case gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT: + case gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT: + updateDepthStencilRenderTarget(context); + break; + case gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS: + case gl::Framebuffer::DIRTY_BIT_READ_BUFFER: + break; + case gl::Framebuffer::DIRTY_BIT_DEFAULT_WIDTH: + case gl::Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT: + case gl::Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES: + case gl::Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS: + break; + default: + { + ASSERT(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 && + dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX); + size_t colorIndex = + static_cast(dirtyBit - gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0); + updateColorRenderTarget(context, colorIndex); + break; + } } } - gl::Error error = invalidateSwizzles(); - if (error.isError()) + // We should not have dirtied any additional state during our sync. + ASSERT(!mInternalDirtyBits.any()); + + FramebufferD3D::syncState(context, dirtyBits); + + // Call this last to allow the state manager to take advantage of the cached render targets. + mRenderer->getStateManager()->invalidateRenderTarget(); + + // Call this to syncViewport for framebuffer default parameters. + if (mState.getDefaultWidth() != 0 || mState.getDefaultHeight() != 0) + { + mRenderer->getStateManager()->invalidateViewport(context); + } +} + +void Framebuffer11::signal(size_t channelID, const gl::Context *context) +{ + if (channelID == gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) + { + // Stencil is redundant in this case. + mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT); + mCachedDepthStencilRenderTarget = nullptr; + } + else { - return error; + mInternalDirtyBits.set(gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 + channelID); + mCachedColorRenderTargets[channelID] = nullptr; } - return gl::Error(GL_NO_ERROR); + // Notify the context we need to re-validate the RenderTarget. + // TODO(jmadill): Check that we're the active draw framebuffer. + mRenderer->getStateManager()->invalidateRenderTarget(); } -GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const +gl::Error Framebuffer11::getSamplePosition(size_t index, GLfloat *xy) const { - RenderTarget11 *renderTarget11 = GetAs(renderTarget); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget11->getDXGIFormat()); - return dxgiFormatInfo.internalFormat; + const gl::FramebufferAttachment *attachment = mState.getFirstNonNullAttachment(); + ASSERT(attachment); + GLsizei sampleCount = attachment->getSamples(); + + d3d11_gl::GetSamplePosition(sampleCount, index, xy); + return gl::NoError(); +} + +bool Framebuffer11::hasAnyInternalDirtyBit() const +{ + return mInternalDirtyBits.any(); +} + +void Framebuffer11::syncInternalState(const gl::Context *context) +{ + syncState(context, gl::Framebuffer::DirtyBits()); } +RenderTarget11 *Framebuffer11::getFirstRenderTarget() const +{ + ASSERT(mInternalDirtyBits.none()); + for (auto *renderTarget : mCachedColorRenderTargets) + { + if (renderTarget) + { + return renderTarget; + } + } + + return mCachedDepthStencilRenderTarget; } + +} // namespace rx 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 c8a33ec7e5..afdda299b9 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h @@ -10,43 +10,93 @@ #define LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_ #include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/signal_utils.h" namespace rx { class Renderer11; -class Framebuffer11 : public FramebufferD3D +class Framebuffer11 : public FramebufferD3D, public OnRenderTargetDirtyReceiver { public: - Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer); - virtual ~Framebuffer11(); + Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer); + ~Framebuffer11() 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 discard(const gl::Context *context, size_t count, const GLenum *attachments) override; + gl::Error invalidate(const gl::Context *context, + size_t count, + const GLenum *attachments) override; + gl::Error invalidateSub(const gl::Context *context, + size_t count, + const GLenum *attachments, + const gl::Rectangle &area) override; // Invalidate the cached swizzles of all bound texture attachments. - gl::Error invalidateSwizzles() const; + gl::Error markAttachmentsDirty(const gl::Context *context) const; + + void syncState(const gl::Context *context, + const gl::Framebuffer::DirtyBits &dirtyBits) override; + + const RenderTargetArray &getCachedColorRenderTargets() const + { + return mCachedColorRenderTargets; + } + const RenderTarget11 *getCachedDepthStencilRenderTarget() const + { + return mCachedDepthStencilRenderTarget; + } + + RenderTarget11 *getFirstRenderTarget() const; + + bool hasAnyInternalDirtyBit() const; + void syncInternalState(const gl::Context *context); + + void signal(size_t channelID, const gl::Context *context) override; + + gl::Error getSamplePosition(size_t index, GLfloat *xy) const override; private: - gl::Error clear(const gl::Data &data, const ClearParameters &clearParams) override; + gl::Error clearImpl(const gl::Context *context, const ClearParameters &clearParams) override; - gl::Error readPixelsImpl(const gl::Rectangle &area, + gl::Error readPixelsImpl(const gl::Context *context, + const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, - uint8_t *pixels) const override; + uint8_t *pixels) 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 blitImpl(const gl::Context *context, + 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; + gl::Error invalidateBase(const gl::Context *context, + size_t count, + const GLenum *attachments, + bool useEXTBehavior) const; + gl::Error invalidateAttachment(const gl::Context *context, + const gl::FramebufferAttachment *attachment) const; GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override; + void updateColorRenderTarget(const gl::Context *context, size_t colorIndex); + void updateDepthStencilRenderTarget(const gl::Context *context); + Renderer11 *const mRenderer; + RenderTargetArray mCachedColorRenderTargets; + RenderTarget11 *mCachedDepthStencilRenderTarget; + + std::vector mColorRenderTargetsDirty; + OnRenderTargetDirtyBinding mDepthStencilRenderTargetDirty; + + gl::Framebuffer::DirtyBits mInternalDirtyBits; }; } 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 c52092d81e..bd921f1935 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp @@ -26,10 +26,10 @@ namespace rx Image11::Image11(Renderer11 *renderer) : mRenderer(renderer), mDXGIFormat(DXGI_FORMAT_UNKNOWN), - mStagingTexture(NULL), + mStagingTexture(), mStagingSubresource(0), mRecoverFromStorage(false), - mAssociatedStorage(NULL), + mAssociatedStorage(nullptr), mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()), mRecoveredFromStorageCount(0) { @@ -41,55 +41,106 @@ Image11::~Image11() releaseStagingTexture(); } -gl::Error Image11::generateMipmap(Image11 *dest, Image11 *src) +// static +gl::Error Image11::GenerateMipmap(const gl::Context *context, + Image11 *dest, + Image11 *src, + const Renderer11DeviceCaps &rendererCaps) { ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(src->getDXGIFormat()); - ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL); - D3D11_MAPPED_SUBRESOURCE destMapped; - gl::Error error = dest->map(D3D11_MAP_WRITE, &destMapped); + ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped)); + + D3D11_MAPPED_SUBRESOURCE srcMapped; + gl::Error error = src->map(context, D3D11_MAP_READ, &srcMapped); if (error.isError()) { + dest->unmap(); return error; } + const uint8_t *sourceData = reinterpret_cast(srcMapped.pData); + uint8_t *destData = reinterpret_cast(destMapped.pData); + + auto mipGenerationFunction = + d3d11::Format::Get(src->getInternalFormat(), rendererCaps).format().mipGenerationFunction; + mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), sourceData, + srcMapped.RowPitch, srcMapped.DepthPitch, destData, destMapped.RowPitch, + destMapped.DepthPitch); + + dest->unmap(); + src->unmap(); + + dest->markDirty(); + + return gl::NoError(); +} + +// static +gl::Error Image11::CopyImage(const gl::Context *context, + Image11 *dest, + Image11 *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const Renderer11DeviceCaps &rendererCaps) +{ + D3D11_MAPPED_SUBRESOURCE destMapped; + ANGLE_TRY(dest->map(context, D3D11_MAP_WRITE, &destMapped)); + D3D11_MAPPED_SUBRESOURCE srcMapped; - error = src->map(D3D11_MAP_READ, &srcMapped); + gl::Error error = source->map(context, D3D11_MAP_READ, &srcMapped); if (error.isError()) { dest->unmap(); return error; } - const uint8_t *sourceData = reinterpret_cast(srcMapped.pData); - uint8_t *destData = reinterpret_cast(destMapped.pData); + const auto &sourceFormat = + d3d11::Format::Get(source->getInternalFormat(), rendererCaps).format(); + GLuint sourcePixelBytes = + gl::GetSizedInternalFormatInfo(sourceFormat.fboImplementationInternalFormat).pixelBytes; + + GLenum destUnsizedFormat = gl::GetUnsizedFormat(dest->getInternalFormat()); + const auto &destFormat = d3d11::Format::Get(dest->getInternalFormat(), rendererCaps).format(); + const auto &destFormatInfo = + gl::GetSizedInternalFormatInfo(destFormat.fboImplementationInternalFormat); + GLuint destPixelBytes = destFormatInfo.pixelBytes; - dxgiFormatInfo.mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), - sourceData, srcMapped.RowPitch, srcMapped.DepthPitch, - destData, destMapped.RowPitch, destMapped.DepthPitch); + const uint8_t *sourceData = reinterpret_cast(srcMapped.pData) + + sourceRect.x * sourcePixelBytes + sourceRect.y * srcMapped.RowPitch; + uint8_t *destData = reinterpret_cast(destMapped.pData) + + destOffset.x * destPixelBytes + destOffset.y * destMapped.RowPitch; + + CopyImageCHROMIUM(sourceData, srcMapped.RowPitch, sourcePixelBytes, + sourceFormat.colorReadFunction, destData, destMapped.RowPitch, destPixelBytes, + destFormat.colorWriteFunction, destUnsizedFormat, + destFormatInfo.componentType, sourceRect.width, sourceRect.height, + unpackFlipY, unpackPremultiplyAlpha, unpackUnmultiplyAlpha); dest->unmap(); - src->unmap(); + source->unmap(); dest->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } bool Image11::isDirty() const { - // If mDirty is true - // 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) + // If mDirty is true 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) AND robust resource initialization is not enabled then isDirty should + // still return false. + if (mDirty && !mStagingTexture.valid() && !mRecoverFromStorage) { const Renderer11DeviceCaps &deviceCaps = mRenderer->getRenderer11DeviceCaps(); - const d3d11::TextureFormat formatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, deviceCaps); + const auto &formatInfo = d3d11::Format::Get(mInternalFormat, deviceCaps); if (formatInfo.dataInitializerFunction == nullptr) { return false; @@ -99,92 +150,69 @@ bool Image11::isDirty() const return mDirty; } -gl::Error Image11::copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion) +gl::Error Image11::copyToStorage(const gl::Context *context, + TextureStorage *storage, + const gl::ImageIndex &index, + const gl::Box ®ion) { 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. - // We allow the Image11 to copy its data to/from TextureStorage once. - // This accounts for an app making a late call to glGenerateMipmap. + // 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. We allow the Image11 to copy its data to/from TextureStorage once. This + // accounts for an app making a late call to glGenerateMipmap. bool attemptToReleaseStagingTexture = (mRecoveredFromStorageCount < 2); if (attemptToReleaseStagingTexture) { - // If another image is relying on this Storage for its data, then we must let it recover its data before we overwrite it. - gl::Error error = storage11->releaseAssociatedImage(index, this); - if (error.isError()) - { - return error; - } + // If another image is relying on this Storage for its data, then we must let it recover its + // data before we overwrite it. + ANGLE_TRY(storage11->releaseAssociatedImage(context, index, this)); } - ID3D11Resource *stagingTexture = NULL; + const TextureHelper11 *stagingTexture = nullptr; unsigned int stagingSubresourceIndex = 0; - gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); - if (error.isError()) - { - return error; - } - - error = storage11->updateSubresourceLevel(stagingTexture, stagingSubresourceIndex, index, region); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex)); + ANGLE_TRY(storage11->updateSubresourceLevel(context, *stagingTexture, stagingSubresourceIndex, + index, region)); // Once the image data has been copied into the Storage, we can release it locally. if (attemptToReleaseStagingTexture) { storage11->associateImage(this, index); releaseStagingTexture(); - mRecoverFromStorage = true; - mAssociatedStorage = storage11; + mRecoverFromStorage = true; + mAssociatedStorage = storage11; mAssociatedImageIndex = index; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const +void Image11::verifyAssociatedStorageValid(TextureStorage11 *textureStorage) const { - return (mAssociatedStorage == textureStorage); + ASSERT(mAssociatedStorage == textureStorage); } -gl::Error Image11::recoverFromAssociatedStorage() +gl::Error Image11::recoverFromAssociatedStorage(const gl::Context *context) { if (mRecoverFromStorage) { - gl::Error error = createStagingTexture(); - if (error.isError()) - { - return error; - } - - bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedImageIndex, this); + ANGLE_TRY(createStagingTexture()); - // This means that the cached TextureStorage has been modified after this Image11 released its copy of its data. - // This should not have happened. The TextureStorage should have told this Image11 to recover its data before it was overwritten. - ASSERT(textureStorageCorrect); + mAssociatedStorage->verifyAssociatedImageValid(mAssociatedImageIndex, this); - if (textureStorageCorrect) - { - // CopySubResource from the Storage to the Staging texture - gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); - error = mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region); - if (error.isError()) - { - return error; - } - - mRecoveredFromStorageCount += 1; - } + // CopySubResource from the Storage to the Staging texture + gl::Box region(0, 0, 0, mWidth, mHeight, mDepth); + ANGLE_TRY(mAssociatedStorage->copySubresourceLevel( + context, mStagingTexture, mStagingSubresource, mAssociatedImageIndex, region)); + mRecoveredFromStorageCount += 1; // Reset all the recovery parameters, even if the texture storage association is broken. disassociateStorage(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void Image11::disassociateStorage() @@ -194,17 +222,18 @@ void Image11::disassociateStorage() // Make the texturestorage release the Image11 too mAssociatedStorage->disassociateImage(mAssociatedImageIndex, this); - mRecoverFromStorage = false; - mAssociatedStorage = NULL; + mRecoverFromStorage = false; + mAssociatedStorage = nullptr; mAssociatedImageIndex = gl::ImageIndex::MakeInvalid(); } } -bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) +bool Image11::redefine(GLenum target, + GLenum internalformat, + const gl::Extents &size, + bool forceRelease) { - if (mWidth != size.width || - mHeight != size.height || - mInternalFormat != internalformat || + if (mWidth != size.width || mHeight != size.height || mInternalFormat != internalformat || forceRelease) { // End the association with the TextureStorage, since that data will be out of date. @@ -212,19 +241,20 @@ bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents & disassociateStorage(); mRecoveredFromStorageCount = 0; - mWidth = size.width; - mHeight = size.height; - mDepth = size.depth; + mWidth = size.width; + mHeight = size.height; + mDepth = size.depth; mInternalFormat = internalformat; - mTarget = target; + mTarget = target; // compute the d3d format that will be used - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, mRenderer->getRenderer11DeviceCaps()); + const d3d11::Format &formatInfo = + d3d11::Format::Get(internalformat, mRenderer->getRenderer11DeviceCaps()); mDXGIFormat = formatInfo.texFormat; mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); releaseStagingTexture(); - mDirty = (formatInfo.dataInitializerFunction != NULL); + mDirty = (formatInfo.dataInitializerFunction != nullptr); return true; } @@ -241,119 +271,125 @@ DXGI_FORMAT Image11::getDXGIFormat() const return mDXGIFormat; } -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as +// format/type at input // into the target pixel rectangle. -gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) +gl::Error Image11::loadData(const gl::Context *context, + const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) { - 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, 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, mRenderer->getRenderer11DeviceCaps()); - LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type).loadFunction; + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); + GLuint inputRowPitch = 0; + ANGLE_TRY_RESULT( + formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength), + inputRowPitch); + GLuint inputDepthPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, unpack.imageHeight, inputRowPitch), + inputDepthPitch); + GLuint inputSkipBytes = 0; + ANGLE_TRY_RESULT( + formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages), + inputSkipBytes); + + const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); + GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; + + const d3d11::Format &d3dFormatInfo = + d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); + LoadImageFunction loadFunction = d3dFormatInfo.getLoadFunctions()(type).loadFunction; D3D11_MAPPED_SUBRESOURCE mappedImage; - gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); - if (error.isError()) - { - return error; - } + ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage)); - uint8_t *offsetMappedData = (reinterpret_cast(mappedImage.pData) + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + area.z * mappedImage.DepthPitch)); + 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) + inputSkipBytes, inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); unmap(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input) +gl::Error Image11::loadCompressedData(const gl::Context *context, + 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, 0); + const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0), inputRowPitch); + GLsizei inputDepthPitch = 0; + ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputRowPitch), inputDepthPitch); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); - GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; - GLuint outputBlockWidth = dxgiFormatInfo.blockWidth; - GLuint outputBlockHeight = dxgiFormatInfo.blockHeight; + const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); + GLuint outputPixelSize = dxgiFormatInfo.pixelBytes; + GLuint outputBlockWidth = dxgiFormatInfo.blockWidth; + GLuint outputBlockHeight = dxgiFormatInfo.blockHeight; ASSERT(area.x % outputBlockWidth == 0); ASSERT(area.y % outputBlockHeight == 0); - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); - LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE).loadFunction; + const d3d11::Format &d3dFormatInfo = + d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); + LoadImageFunction loadFunction = + d3dFormatInfo.getLoadFunctions()(GL_UNSIGNED_BYTE).loadFunction; D3D11_MAPPED_SUBRESOURCE mappedImage; - gl::Error error = map(D3D11_MAP_WRITE, &mappedImage); - if (error.isError()) - { - return error; - } + ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage)); - uint8_t* offsetMappedData = reinterpret_cast(mappedImage.pData) + ((area.y / outputBlockHeight) * mappedImage.RowPitch + - (area.x / outputBlockWidth) * outputPixelSize + - area.z * mappedImage.DepthPitch); + uint8_t *offsetMappedData = + reinterpret_cast(mappedImage.pData) + + ((area.y / outputBlockHeight) * mappedImage.RowPitch + + (area.x / outputBlockWidth) * outputPixelSize + area.z * mappedImage.DepthPitch); - loadFunction(area.width, area.height, area.depth, - reinterpret_cast(input), inputRowPitch, inputDepthPitch, - offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + loadFunction(area.width, area.height, area.depth, reinterpret_cast(input), + inputRowPitch, inputDepthPitch, offsetMappedData, mappedImage.RowPitch, + mappedImage.DepthPitch); unmap(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image11::copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) +gl::Error Image11::copyFromTexStorage(const gl::Context *context, + const gl::ImageIndex &imageIndex, + TextureStorage *source) { TextureStorage11 *storage11 = GetAs(source); - ID3D11Resource *resource = nullptr; - gl::Error error = storage11->getResource(&resource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *textureHelper = nullptr; + ANGLE_TRY(storage11->getResource(context, &textureHelper)); - UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex); - TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(resource); + UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex); gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth); - return copyWithoutConversion(gl::Offset(), sourceBox, textureHelper, subresourceIndex); + return copyWithoutConversion(gl::Offset(), sourceBox, *textureHelper, subresourceIndex); } -gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset, +gl::Error Image11::copyFromFramebuffer(const gl::Context *context, + const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *sourceFBO) { const gl::FramebufferAttachment *srcAttachment = sourceFBO->getReadColorbuffer(); ASSERT(srcAttachment); - const auto &d3d11Format = d3d11::GetTextureFormatInfo(srcAttachment->getInternalFormat(), - mRenderer->getRenderer11DeviceCaps()); + GLenum sourceInternalFormat = srcAttachment->getFormat().info->sizedInternalFormat; + const auto &d3d11Format = + d3d11::Format::Get(sourceInternalFormat, mRenderer->getRenderer11DeviceCaps()); - if (d3d11Format.texFormat == mDXGIFormat) + if (d3d11Format.texFormat == mDXGIFormat && sourceInternalFormat == mInternalFormat) { - RenderTargetD3D *renderTarget = nullptr; - gl::Error error = srcAttachment->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - - RenderTarget11 *rt11 = GetAs(renderTarget); - ASSERT(rt11->getTexture()); + RenderTarget11 *rt11 = nullptr; + ANGLE_TRY(srcAttachment->getRenderTarget(context, &rt11)); + ASSERT(rt11->getTexture().get()); - TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(rt11->getTexture()); + TextureHelper11 textureHelper = rt11->getTexture(); unsigned int sourceSubResource = rt11->getSubresourceIndex(); gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1); @@ -363,25 +399,47 @@ gl::Error Image11::copyFromFramebuffer(const gl::Offset &destOffset, // 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; - } + ANGLE_TRY(map(context, D3D11_MAP_WRITE, &mappedImage)); // determine the offset coordinate into the destination buffer - const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat); + const auto &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat); GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x; uint8_t *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * destOffset.y + rowOffset + destOffset.z * mappedImage.DepthPitch; - const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + const gl::InternalFormat &destFormatInfo = gl::GetSizedInternalFormatInfo(mInternalFormat); + const auto &destD3D11Format = + d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); + + auto loadFunction = destD3D11Format.getLoadFunctions()(destFormatInfo.type); + gl::Error error = gl::NoError(); + if (loadFunction.requiresConversion) + { + size_t bufferSize = destFormatInfo.pixelBytes * sourceArea.width * sourceArea.height; + angle::MemoryBuffer *memoryBuffer = nullptr; + error = mRenderer->getScratchMemoryBuffer(bufferSize, &memoryBuffer); + + if (!error.isError()) + { + GLuint memoryBufferRowPitch = destFormatInfo.pixelBytes * sourceArea.width; - error = mRenderer->readFromAttachment(*srcAttachment, sourceArea, formatInfo.format, - formatInfo.type, mappedImage.RowPitch, - gl::PixelPackState(), dataOffset); + error = mRenderer->readFromAttachment( + context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type, + memoryBufferRowPitch, gl::PixelPackState(), memoryBuffer->data()); + + loadFunction.loadFunction(sourceArea.width, sourceArea.height, 1, memoryBuffer->data(), + memoryBufferRowPitch, 0, dataOffset, mappedImage.RowPitch, + mappedImage.DepthPitch); + } + } + else + { + error = mRenderer->readFromAttachment( + context, *srcAttachment, sourceArea, destFormatInfo.format, destFormatInfo.type, + mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + } unmap(); mDirty = true; @@ -395,26 +453,23 @@ gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset, UINT sourceSubResource) { // No conversion needed-- use copyback fastpath - ID3D11Resource *stagingTexture = nullptr; + const TextureHelper11 *stagingTexture = nullptr; unsigned int stagingSubresourceIndex = 0; - gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex)); - ID3D11Device *device = mRenderer->getDevice(); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - UINT subresourceAfterResolve = sourceSubResource; - - ID3D11Resource *srcTex = nullptr; const gl::Extents &extents = textureHelper.getExtents(); - bool needResolve = - (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1); + 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; - if (needResolve) + if (textureHelper.is2D() && textureHelper.getSampleCount() > 1) { D3D11_TEXTURE2D_DESC resolveDesc; resolveDesc.Width = extents.width; @@ -429,80 +484,57 @@ gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset, 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; + d3d11::Texture2D resolveTex; + ANGLE_TRY(mRenderer->allocateResource(resolveDesc, &resolveTex)); - deviceContext->ResolveSubresource(srcTex, 0, textureHelper.getTexture2D(), + deviceContext->ResolveSubresource(resolveTex.get(), 0, textureHelper.get(), sourceSubResource, textureHelper.getFormat()); - subresourceAfterResolve = 0; + + deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex, + destOffset.x, destOffset.y, destOffset.z, + resolveTex.get(), 0, &srcBox); } else { - srcTex = textureHelper.getResource(); - } - - 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); + deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex, + destOffset.x, destOffset.y, destOffset.z, + textureHelper.get(), sourceSubResource, &srcBox); } mDirty = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image11::getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex) +gl::Error Image11::getStagingTexture(const TextureHelper11 **outStagingTexture, + unsigned int *outSubresourceIndex) { - gl::Error error = createStagingTexture(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(createStagingTexture()); - *outStagingTexture = mStagingTexture; + *outStagingTexture = &mStagingTexture; *outSubresourceIndex = mStagingSubresource; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void Image11::releaseStagingTexture() { - SafeRelease(mStagingTexture); + mStagingTexture.reset(); } gl::Error Image11::createStagingTexture() { - if (mStagingTexture) + if (mStagingTexture.valid()) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } ASSERT(mWidth > 0 && mHeight > 0 && mDepth > 0); const DXGI_FORMAT dxgiFormat = getDXGIFormat(); + const auto &formatInfo = + d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps()); - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - int lodOffset = 1; - GLsizei width = mWidth; + int lodOffset = 1; + GLsizei width = mWidth; GLsizei height = mHeight; // adjust size if needed for compressed textures @@ -510,80 +542,69 @@ gl::Error Image11::createStagingTexture() if (mTarget == GL_TEXTURE_3D) { - ID3D11Texture3D *newTexture = NULL; - D3D11_TEXTURE3D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.Depth = mDepth; - desc.MipLevels = lodOffset + 1; - desc.Format = dxgiFormat; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; + desc.Width = width; + desc.Height = height; + desc.Depth = mDepth; + desc.MipLevels = lodOffset + 1; + desc.Format = dxgiFormat; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; + desc.MiscFlags = 0; - if (d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()).dataInitializerFunction != NULL) + if (formatInfo.dataInitializerFunction != nullptr) { std::vector initialData; std::vector> textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, mDepth, - lodOffset + 1, &initialData, &textureData); + d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), + width, height, mDepth, lodOffset + 1, &initialData, + &textureData); - result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); + ANGLE_TRY( + mRenderer->allocateTexture(desc, formatInfo, initialData.data(), &mStagingTexture)); } else { - result = device->CreateTexture3D(&desc, NULL, &newTexture); + ANGLE_TRY(mRenderer->allocateTexture(desc, formatInfo, &mStagingTexture)); } - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result); - } - - mStagingTexture = newTexture; + mStagingTexture.setDebugName("Image11::StagingTexture3D"); mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); } - else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP) + else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || + mTarget == GL_TEXTURE_CUBE_MAP) { - ID3D11Texture2D *newTexture = NULL; - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = lodOffset + 1; - desc.ArraySize = 1; - desc.Format = dxgiFormat; - desc.SampleDesc.Count = 1; + desc.Width = width; + desc.Height = height; + desc.MipLevels = lodOffset + 1; + desc.ArraySize = 1; + desc.Format = dxgiFormat; + desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; - if (d3d11::GetTextureFormatInfo(mInternalFormat, mRenderer->getRenderer11DeviceCaps()).dataInitializerFunction != NULL) + if (formatInfo.dataInitializerFunction != nullptr) { std::vector initialData; std::vector> textureData; - d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), width, height, 1, - lodOffset + 1, &initialData, &textureData); + d3d11::GenerateInitialTextureData(mInternalFormat, mRenderer->getRenderer11DeviceCaps(), + width, height, 1, lodOffset + 1, &initialData, + &textureData); - result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); + ANGLE_TRY( + mRenderer->allocateTexture(desc, formatInfo, initialData.data(), &mStagingTexture)); } else { - result = device->CreateTexture2D(&desc, NULL, &newTexture); + ANGLE_TRY(mRenderer->allocateTexture(desc, formatInfo, &mStagingTexture)); } - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create staging texture, result: 0x%X.", result); - } - - mStagingTexture = newTexture; + mStagingTexture.setDebugName("Image11::StagingTexture2D"); mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); } else @@ -592,30 +613,22 @@ gl::Error Image11::createStagingTexture() } mDirty = false; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) +gl::Error Image11::map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) { // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. - gl::Error error = recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(recoverFromAssociatedStorage(context)); - ID3D11Resource *stagingTexture = NULL; - unsigned int subresourceIndex = 0; - error = getStagingTexture(&stagingTexture, &subresourceIndex); - if (error.isError()) - { - return error; - } + const TextureHelper11 *stagingTexture = nullptr; + unsigned int subresourceIndex = 0; + ANGLE_TRY(getStagingTexture(&stagingTexture, &subresourceIndex)); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - ASSERT(mStagingTexture); - HRESULT result = deviceContext->Map(stagingTexture, subresourceIndex, mapType, 0, map); + ASSERT(stagingTexture && stagingTexture->valid()); + HRESULT result = deviceContext->Map(stagingTexture->get(), subresourceIndex, mapType, 0, map); if (FAILED(result)) { @@ -624,20 +637,20 @@ gl::Error Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) { mRenderer->notifyDeviceLost(); } - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map staging texture, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to map staging texture, " << gl::FmtHR(result); } mDirty = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void Image11::unmap() { - if (mStagingTexture) + if (mStagingTexture.valid()) { ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - deviceContext->Unmap(mStagingTexture, mStagingSubresource); + deviceContext->Unmap(mStagingTexture.get(), mStagingSubresource); } } 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 a5fcec84f8..584d231b37 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h @@ -10,10 +10,10 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_ -#include "libANGLE/renderer/d3d/ImageD3D.h" -#include "libANGLE/ImageIndex.h" - #include "common/debug.h" +#include "libANGLE/ImageIndex.h" +#include "libANGLE/renderer/d3d/ImageD3D.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" namespace gl { @@ -25,37 +25,63 @@ namespace rx class Renderer11; class TextureHelper11; class TextureStorage11; +struct Renderer11DeviceCaps; class Image11 : public ImageD3D { public: Image11(Renderer11 *renderer); - virtual ~Image11(); - - static gl::Error generateMipmap(Image11 *dest, Image11 *src); - - virtual bool isDirty() const; - - virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box ®ion); + ~Image11() override; + + static gl::Error GenerateMipmap(const gl::Context *context, + Image11 *dest, + Image11 *src, + const Renderer11DeviceCaps &rendererCaps); + static gl::Error CopyImage(const gl::Context *context, + Image11 *dest, + Image11 *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha, + const Renderer11DeviceCaps &rendererCaps); + + bool isDirty() const override; + + gl::Error copyToStorage(const gl::Context *context, + TextureStorage *storage, + const gl::ImageIndex &index, + const gl::Box ®ion) override; bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override; DXGI_FORMAT getDXGIFormat() const; - 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); - - gl::Error copyFromTexStorage(const gl::ImageIndex &imageIndex, TextureStorage *source) override; - gl::Error copyFromFramebuffer(const gl::Offset &destOffset, + gl::Error loadData(const gl::Context *context, + const gl::Box &area, + const gl::PixelUnpackState &unpack, + GLenum type, + const void *input, + bool applySkipImages) override; + gl::Error loadCompressedData(const gl::Context *context, + const gl::Box &area, + const void *input) override; + + gl::Error copyFromTexStorage(const gl::Context *context, + const gl::ImageIndex &imageIndex, + TextureStorage *source) override; + gl::Error copyFromFramebuffer(const gl::Context *context, + const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) override; - gl::Error recoverFromAssociatedStorage(); - bool isAssociatedStorageValid(TextureStorage11* textureStorage) const; + gl::Error recoverFromAssociatedStorage(const gl::Context *context); + void verifyAssociatedStorageValid(TextureStorage11 *textureStorage) const; void disassociateStorage(); protected: - gl::Error map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); + gl::Error map(const gl::Context *context, D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); void unmap(); private: @@ -64,14 +90,15 @@ class Image11 : public ImageD3D const TextureHelper11 &textureHelper, UINT sourceSubResource); - gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex); + gl::Error getStagingTexture(const TextureHelper11 **outStagingTexture, + unsigned int *outSubresourceIndex); gl::Error createStagingTexture(); void releaseStagingTexture(); Renderer11 *mRenderer; DXGI_FORMAT mDXGIFormat; - ID3D11Resource *mStagingTexture; + TextureHelper11 mStagingTexture; unsigned int mStagingSubresource; bool mRecoverFromStorage; 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 a5e78a245d..a79fb71f71 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -14,28 +14,23 @@ namespace rx { -IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) + : mRenderer(renderer), mBuffer(), mBufferSize(0), mIndexType(GL_NONE), mDynamicUsage(false) { - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; } IndexBuffer11::~IndexBuffer11() { - SafeRelease(mBuffer); } gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) { - SafeRelease(mBuffer); + mBuffer.reset(); updateSerial(); if (bufferSize > 0) { - ID3D11Device* dxDevice = mRenderer->getDevice(); - D3D11_BUFFER_DESC bufferDesc; bufferDesc.ByteWidth = bufferSize; bufferDesc.Usage = D3D11_USAGE_DYNAMIC; @@ -44,19 +39,15 @@ gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, b bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 0; - HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); - } + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &mBuffer)); if (dynamic) { - d3d11::SetDebugName(mBuffer, "IndexBuffer11 (dynamic)"); + mBuffer.setDebugName("IndexBuffer11 (dynamic)"); } else { - d3d11::SetDebugName(mBuffer, "IndexBuffer11 (static)"); + mBuffer.setDebugName("IndexBuffer11 (static)"); } } @@ -64,45 +55,46 @@ gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, b mIndexType = indexType; mDynamicUsage = dynamic; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + return gl::OutOfMemory() << "Internal index buffer is not initialized."; } // Check for integer overflows and out-out-bounds map requests if (offset + size < offset || offset + size > mBufferSize) { - return gl::Error(GL_OUT_OF_MEMORY, "Index buffer map range is not inside the buffer."); + return gl::OutOfMemory() << "Index buffer map range is not inside the buffer."; } ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + HRESULT result = + dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result); + return gl::OutOfMemory() << "Failed to map internal index buffer, " << gl::FmtHR(result); } *outMappedMemory = reinterpret_cast(mappedResource.pData) + offset; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error IndexBuffer11::unmapBuffer() { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + return gl::OutOfMemory() << "Internal index buffer is not initialized."; } ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - dxContext->Unmap(mBuffer, 0); - return gl::Error(GL_NO_ERROR); + dxContext->Unmap(mBuffer.get(), 0); + return gl::NoError(); } GLenum IndexBuffer11::getIndexType() const @@ -123,29 +115,29 @@ gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) } else { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } gl::Error IndexBuffer11::discard() { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + return gl::OutOfMemory() << "Internal index buffer is not initialized."; } ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + HRESULT result = dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal index buffer, HRESULT: 0x%08x.", result); + return gl::OutOfMemory() << "Failed to map internal index buffer, " << gl::FmtHR(result); } - dxContext->Unmap(mBuffer, 0); + dxContext->Unmap(mBuffer.get(), 0); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } DXGI_FORMAT IndexBuffer11::getIndexFormat() const @@ -159,9 +151,9 @@ DXGI_FORMAT IndexBuffer11::getIndexFormat() const } } -ID3D11Buffer *IndexBuffer11::getBuffer() const +const d3d11::Buffer &IndexBuffer11::getBuffer() const { return mBuffer; } -} +} // namespace rx 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 e730377e00..7b5d744c02 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h @@ -10,6 +10,7 @@ #define LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ #include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" namespace rx { @@ -19,31 +20,31 @@ class IndexBuffer11 : public IndexBuffer { public: explicit IndexBuffer11(Renderer11 *const renderer); - virtual ~IndexBuffer11(); + ~IndexBuffer11() override; - virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) override; - virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual gl::Error unmapBuffer(); + gl::Error mapBuffer(unsigned int offset, unsigned int size, void **outMappedMemory) override; + gl::Error unmapBuffer() override; - virtual GLenum getIndexType() const; - virtual unsigned int getBufferSize() const; - virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); + GLenum getIndexType() const override; + unsigned int getBufferSize() const override; + gl::Error setSize(unsigned int bufferSize, GLenum indexType) override; - virtual gl::Error discard(); + gl::Error discard() override; DXGI_FORMAT getIndexFormat() const; - ID3D11Buffer *getBuffer() const; + const d3d11::Buffer &getBuffer() const; private: Renderer11 *const mRenderer; - ID3D11Buffer *mBuffer; + d3d11::Buffer mBuffer; unsigned int mBufferSize; GLenum mIndexType; bool mDynamicUsage; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_ 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 3a6d797ea6..a238f97b08 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -9,17 +9,22 @@ #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "common/bitset_utils.h" #include "common/utilities.h" +#include "libANGLE/Context.h" #include "libANGLE/Program.h" +#include "libANGLE/VertexArray.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/Context11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" #include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h" #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "third_party/murmurhash/MurmurHash3.h" namespace rx { @@ -32,24 +37,7 @@ size_t GetReservedBufferCount(bool usesPointSpriteEmulation) 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]; - - if (translatedAttribute->active) - { - inputLayout[attributeIndex] = gl::GetVertexFormatType( - *translatedAttribute->attribute, translatedAttribute->currentValueType); - } - } - return inputLayout; -} - -GLenum GetGLSLAttributeType(const std::vector &shaderAttributes, int index) +GLenum GetGLSLAttributeType(const std::vector &shaderAttributes, size_t index) { // Count matrices differently for (const sh::Attribute &attrib : shaderAttributes) @@ -61,8 +49,9 @@ GLenum GetGLSLAttributeType(const std::vector &shaderAttributes, GLenum transposedType = gl::TransposeMatrixType(attrib.type); int rows = gl::VariableRowCount(transposedType); + int intIndex = static_cast(index); - if (index >= attrib.location && index < attrib.location + rows) + if (intIndex >= attrib.location && intIndex < attrib.location + rows) { return transposedType; } @@ -72,8 +61,6 @@ GLenum GetGLSLAttributeType(const std::vector &shaderAttributes, return GL_NONE; } -const unsigned int kDefaultCacheSize = 1024; - struct PackedAttribute { uint8_t attribType; @@ -82,26 +69,18 @@ struct PackedAttribute uint8_t divisor; }; -Optional FindFirstNonInstanced(const SortedAttribArray &sortedAttributes, size_t maxIndex) -{ - for (size_t index = 0; index < maxIndex; ++index) - { - if (sortedAttributes[index]->divisor == 0) - { - return Optional(index); - } - } +} // anonymous namespace - return Optional::Invalid(); +PackedAttributeLayout::PackedAttributeLayout() : numAttributes(0), flags(0), attributeData({}) +{ } -} // anonymous namespace +PackedAttributeLayout::PackedAttributeLayout(const PackedAttributeLayout &other) = default; -void InputLayoutCache::PackedAttributeLayout::addAttributeData( - GLenum glType, - UINT semanticIndex, - gl::VertexFormatType vertexFormatType, - unsigned int divisor) +void PackedAttributeLayout::addAttributeData(GLenum glType, + UINT semanticIndex, + gl::VertexFormatType vertexFormatType, + unsigned int divisor) { gl::AttributeType attribType = gl::GetAttributeType(glType); @@ -121,139 +100,58 @@ void InputLayoutCache::PackedAttributeLayout::addAttributeData( attributeData[numAttributes++] = gl::bitCast(packedAttrib); } -bool InputLayoutCache::PackedAttributeLayout::operator<(const PackedAttributeLayout &other) const +bool 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; + return (numAttributes == other.numAttributes) && (flags == other.flags) && + (attributeData == other.attributeData); } -InputLayoutCache::InputLayoutCache() : mUnsortedAttributesCount(0), mCacheSize(kDefaultCacheSize) +InputLayoutCache::InputLayoutCache() + : mLayoutCache(kDefaultCacheSize * 2), mPointSpriteVertexBuffer(), mPointSpriteIndexBuffer() { - mCounter = 0; - mDevice = NULL; - mDeviceContext = NULL; - mCurrentIL = NULL; - - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = NULL; - mCurrentVertexStrides[i] = static_cast(-1); - mCurrentVertexOffsets[i] = static_cast(-1); - } - mPointSpriteVertexBuffer = NULL; - mPointSpriteIndexBuffer = NULL; } InputLayoutCache::~InputLayoutCache() { - clear(); -} - -void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) -{ - clear(); - mDevice = device; - mDeviceContext = context; - mFeatureLevel = device->GetFeatureLevel(); } void InputLayoutCache::clear() { - for (auto &layout : mLayoutMap) - { - SafeRelease(layout.second); - } - mLayoutMap.clear(); - SafeRelease(mPointSpriteVertexBuffer); - SafeRelease(mPointSpriteIndexBuffer); - markDirty(); -} - -void InputLayoutCache::markDirty() -{ - mCurrentIL = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = NULL; - mCurrentVertexStrides[i] = static_cast(-1); - mCurrentVertexOffsets[i] = static_cast(-1); - } - mUnsortedAttributesCount = 0; + mLayoutCache.Clear(); + mPointSpriteVertexBuffer.reset(); + mPointSpriteIndexBuffer.reset(); } gl::Error InputLayoutCache::applyVertexBuffers( - const std::vector &unsortedAttributes, + const gl::Context *context, + const std::vector ¤tAttributes, GLenum mode, - gl::Program *program, - TranslatedIndexData *indexInfo, - GLsizei numIndicesPerInstance) + GLint start, + bool isIndexedRendering) { - ASSERT(mDevice && mDeviceContext); - + Renderer11 *renderer = GetImplAs(context)->getRenderer(); + const gl::State &state = context->getGLState(); + auto *stateManager = renderer->getStateManager(); + gl::Program *program = state.getProgram(); ProgramD3D *programD3D = GetImplAs(program); bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS); - SortedIndexArray sortedSemanticIndices; - mSortedAttributes.fill(nullptr); - mUnsortedAttributesCount = unsortedAttributes.size(); - - programD3D->sortAttributesByLayout(unsortedAttributes, sortedSemanticIndices.data(), - mSortedAttributes.data()); - - // 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 (mSortedAttributes[0]->divisor > 0) - { - Optional firstNonInstancedIndex = - FindFirstNonInstanced(mSortedAttributes, unsortedAttributes.size()); - if (firstNonInstancedIndex.valid()) - { - size_t index = firstNonInstancedIndex.value(); - std::swap(mSortedAttributes[0], mSortedAttributes[index]); - std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]); - } - } - } - - gl::Error error = updateInputLayout(program, mode, mSortedAttributes, sortedSemanticIndices, - unsortedAttributes.size(), numIndicesPerInstance); - if (error.isError()) - { - return error; - } - - bool dirtyBuffers = false; - size_t minDiff = gl::MAX_VERTEX_ATTRIBS; - size_t maxDiff = 0; - // Note that if we use instance emulation, we reserve the first buffer slot. size_t reservedBuffers = GetReservedBufferCount(programUsesInstancedPointSprites); for (size_t attribIndex = 0; attribIndex < (gl::MAX_VERTEX_ATTRIBS - reservedBuffers); ++attribIndex) { - ID3D11Buffer *buffer = NULL; - UINT vertexStride = 0; - UINT vertexOffset = 0; + ID3D11Buffer *buffer = nullptr; + UINT vertexStride = 0; + UINT vertexOffset = 0; - const auto &attrib = *mSortedAttributes[attribIndex]; - - if (attribIndex < unsortedAttributes.size() && attrib.active) + if (attribIndex < currentAttributes.size()) { - VertexBuffer11 *vertexBuffer = GetAs(attrib.vertexBuffer); - Buffer11 *bufferStorage = attrib.storage ? GetAs(attrib.storage) : nullptr; + const auto &attrib = *currentAttributes[attribIndex]; + 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 @@ -261,18 +159,18 @@ gl::Error InputLayoutCache::applyVertexBuffers( // on the number of points indicated by the index list or how many duplicates are found on the index list. if (bufferStorage == nullptr) { - buffer = vertexBuffer->getBuffer(); + ASSERT(attrib.vertexBuffer.get()); + buffer = GetAs(attrib.vertexBuffer.get())->getBuffer().get(); } - else if (instancedPointSpritesActive && (indexInfo != nullptr)) + else if (instancedPointSpritesActive && isIndexedRendering) { + VertexArray11 *vao11 = GetImplAs(state.getVertexArray()); + ASSERT(vao11->isCachedIndexInfoValid()); + TranslatedIndexData *indexInfo = vao11->getCachedIndexInfo(); if (indexInfo->srcIndexData.srcBuffer != nullptr) { const uint8_t *bufferData = nullptr; - error = indexInfo->srcIndexData.srcBuffer->getData(&bufferData); - if (error.isError()) - { - return error; - } + ANGLE_TRY(indexInfo->srcIndexData.srcBuffer->getData(context, &bufferData)); ASSERT(bufferData != nullptr); ptrdiff_t offset = @@ -281,31 +179,24 @@ gl::Error InputLayoutCache::applyVertexBuffers( indexInfo->srcIndexData.srcIndices = bufferData + offset; } - buffer = bufferStorage->getEmulatedIndexedBuffer(&indexInfo->srcIndexData, &attrib); + ANGLE_TRY_RESULT(bufferStorage->getEmulatedIndexedBuffer( + context, &indexInfo->srcIndexData, attrib, start), + buffer); } else { - buffer = bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + ANGLE_TRY_RESULT( + bufferStorage->getBuffer(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + buffer); } vertexStride = attrib.stride; - vertexOffset = attrib.offset; + ANGLE_TRY_RESULT(attrib.computeOffset(start), vertexOffset); } size_t bufferIndex = reservedBuffers + attribIndex; - if (buffer != mCurrentBuffers[bufferIndex] || - vertexStride != mCurrentVertexStrides[bufferIndex] || - vertexOffset != mCurrentVertexOffsets[bufferIndex]) - { - dirtyBuffers = true; - minDiff = std::min(minDiff, bufferIndex); - maxDiff = std::max(maxDiff, bufferIndex); - - mCurrentBuffers[bufferIndex] = buffer; - mCurrentVertexStrides[bufferIndex] = vertexStride; - mCurrentVertexOffsets[bufferIndex] = vertexOffset; - } + stateManager->queueVertexBufferChange(bufferIndex, buffer, vertexStride, vertexOffset); } // Instanced PointSprite emulation requires two additional ID3D11Buffers. A vertex buffer needs @@ -317,10 +208,9 @@ gl::Error InputLayoutCache::applyVertexBuffers( // handle missing vertex data and will TDR the system. if (programUsesInstancedPointSprites) { - HRESULT result = S_OK; const UINT pointSpriteVertexStride = sizeof(float) * 5; - if (!mPointSpriteVertexBuffer) + if (!mPointSpriteVertexBuffer.valid()) { static const float pointSpriteVertices[] = { @@ -342,25 +232,16 @@ gl::Error InputLayoutCache::applyVertexBuffers( vertexBufferDesc.MiscFlags = 0; vertexBufferDesc.StructureByteStride = 0; - result = mDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &mPointSpriteVertexBuffer); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation vertex buffer, HRESULT: 0x%08x", result); - } + ANGLE_TRY(renderer->allocateResource(vertexBufferDesc, &vertexBufferData, + &mPointSpriteVertexBuffer)); } - 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)); + UINT stride = instancedPointSpritesActive ? pointSpriteVertexStride : 0; + stateManager->queueVertexBufferChange(0, mPointSpriteVertexBuffer.get(), stride, 0); - if (!mPointSpriteIndexBuffer) + if (!mPointSpriteIndexBuffer.valid()) { // Create an index buffer and set it for pointsprite rendering static const unsigned short pointSpriteIndices[] = @@ -377,12 +258,8 @@ gl::Error InputLayoutCache::applyVertexBuffers( indexBufferDesc.MiscFlags = 0; indexBufferDesc.StructureByteStride = 0; - result = mDevice->CreateBuffer(&indexBufferDesc, &indexBufferData, &mPointSpriteIndexBuffer); - if (FAILED(result)) - { - SafeRelease(mPointSpriteVertexBuffer); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation index buffer, HRESULT: 0x%08x", result); - } + ANGLE_TRY(renderer->allocateResource(indexBufferDesc, &indexBufferData, + &mPointSpriteIndexBuffer)); } if (instancedPointSpritesActive) @@ -391,51 +268,51 @@ gl::Error InputLayoutCache::applyVertexBuffers( // 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); + stateManager->setIndexBuffer(mPointSpriteIndexBuffer.get(), DXGI_FORMAT_R16_UINT, 0); } } - if (dirtyBuffers) - { - ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS); - mDeviceContext->IASetVertexBuffers( - static_cast(minDiff), static_cast(maxDiff - minDiff + 1), - mCurrentBuffers + minDiff, mCurrentVertexStrides + minDiff, - mCurrentVertexOffsets + minDiff); - } - - return gl::Error(GL_NO_ERROR); + stateManager->applyVertexBufferChanges(); + return gl::NoError(); } -gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId) +gl::Error InputLayoutCache::updateVertexOffsetsForPointSpritesEmulation( + Renderer11 *renderer, + const std::vector ¤tAttributes, + GLint startVertex, + GLsizei emulatedInstanceId) { + auto *stateManager = renderer->getStateManager(); + size_t reservedBuffers = GetReservedBufferCount(true); - for (size_t attribIndex = 0; attribIndex < mUnsortedAttributesCount; ++attribIndex) + for (size_t attribIndex = 0; attribIndex < currentAttributes.size(); ++attribIndex) { - const auto &attrib = *mSortedAttributes[attribIndex]; + const auto &attrib = *currentAttributes[attribIndex]; size_t bufferIndex = reservedBuffers + attribIndex; - if (attrib.active && attrib.divisor > 0) + if (attrib.divisor > 0) { - mCurrentVertexOffsets[bufferIndex] = - attrib.offset + (attrib.stride * (emulatedInstanceId / attrib.divisor)); + unsigned int offset = 0; + ANGLE_TRY_RESULT(attrib.computeOffset(startVertex), offset); + offset += (attrib.stride * (emulatedInstanceId / attrib.divisor)); + stateManager->queueVertexOffsetChange(bufferIndex, offset); } } - mDeviceContext->IASetVertexBuffers(0, gl::MAX_VERTEX_ATTRIBS, mCurrentBuffers, - mCurrentVertexStrides, mCurrentVertexOffsets); - - return gl::Error(GL_NO_ERROR); + stateManager->applyVertexBufferChanges(); + return gl::NoError(); } -gl::Error InputLayoutCache::updateInputLayout(gl::Program *program, - GLenum mode, - const SortedAttribArray &sortedAttributes, - const SortedIndexArray &sortedSemanticIndices, - size_t attribCount, - GLsizei numIndicesPerInstance) +gl::Error InputLayoutCache::updateInputLayout( + Renderer11 *renderer, + const gl::State &state, + const std::vector ¤tAttributes, + GLenum mode, + const AttribIndexArray &sortedSemanticIndices, + const DrawCallVertexParams &vertexParams) { - const std::vector &shaderAttributes = program->getAttributes(); + gl::Program *program = state.getProgram(); + const auto &shaderAttributes = program->getAttributes(); PackedAttributeLayout layout; ProgramD3D *programD3D = GetImplAs(program); @@ -453,90 +330,70 @@ gl::Error InputLayoutCache::updateInputLayout(gl::Program *program, layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_SPRITES_ACTIVE; } - if (numIndicesPerInstance > 0) + if (vertexParams.instances() > 0) { layout.flags |= PackedAttributeLayout::FLAG_INSTANCED_RENDERING_ACTIVE; } - const auto &semanticToLocation = programD3D->getAttributesByLayout(); + const auto &attribs = state.getVertexArray()->getVertexAttributes(); + const auto &bindings = state.getVertexArray()->getVertexBindings(); + const auto &locationToSemantic = programD3D->getAttribLocationToD3DSemantics(); + int divisorMultiplier = program->usesMultiview() ? program->getNumViews() : 1; - for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex) + for (size_t attribIndex : program->getActiveAttribLocationsMask()) { - 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]); + GLenum glslElementType = GetGLSLAttributeType(shaderAttributes, attribIndex); - layout.addAttributeData(glslElementType, sortedIndex, vertexFormatType, attrib.divisor); + const auto &attrib = attribs[attribIndex]; + const auto &binding = bindings[attrib.bindingIndex]; + int d3dSemantic = locationToSemantic[attribIndex]; + + const auto ¤tValue = + state.getVertexAttribCurrentValue(static_cast(attribIndex)); + gl::VertexFormatType vertexFormatType = gl::GetVertexFormatType(attrib, currentValue.Type); + + layout.addAttributeData(glslElementType, d3dSemantic, vertexFormatType, + binding.getDivisor() * divisorMultiplier); } - ID3D11InputLayout *inputLayout = nullptr; + const d3d11::InputLayout *inputLayout = nullptr; if (layout.numAttributes > 0 || layout.flags != 0) { - auto layoutMapIt = mLayoutMap.find(layout); - if (layoutMapIt != mLayoutMap.end()) + auto it = mLayoutCache.Get(layout); + if (it != mLayoutCache.end()) { - inputLayout = layoutMapIt->second; + inputLayout = &it->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); + angle::TrimCache(mLayoutCache.max_size() / 2, kGCLimit, "input layout", &mLayoutCache); - // 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); - } - } - } + d3d11::InputLayout newInputLayout; + ANGLE_TRY(createInputLayout(renderer, sortedSemanticIndices, currentAttributes, mode, + program, vertexParams, &newInputLayout)); - mLayoutMap[layout] = inputLayout; + auto insertIt = mLayoutCache.Put(layout, std::move(newInputLayout)); + inputLayout = &insertIt->second; } } - if (inputLayout != mCurrentIL) - { - mDeviceContext->IASetInputLayout(inputLayout); - mCurrentIL = inputLayout; - } - - return gl::Error(GL_NO_ERROR); + renderer->getStateManager()->setInputLayout(inputLayout); + return gl::NoError(); } -gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAttributes, - const SortedIndexArray &sortedSemanticIndices, - size_t attribCount, - GLenum mode, - gl::Program *program, - GLsizei numIndicesPerInstance, - ID3D11InputLayout **inputLayoutOut) +gl::Error InputLayoutCache::createInputLayout( + Renderer11 *renderer, + const AttribIndexArray &sortedSemanticIndices, + const std::vector ¤tAttributes, + GLenum mode, + gl::Program *program, + const DrawCallVertexParams &vertexParams, + d3d11::InputLayout *inputLayoutOut) { ProgramD3D *programD3D = GetImplAs(program); + auto featureLevel = renderer->getRenderer11DeviceCaps().featureLevel; bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation(); @@ -544,20 +401,17 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt unsigned int inputElementCount = 0; std::array inputElements; - for (size_t attribIndex = 0; attribIndex < attribCount; ++attribIndex) + for (size_t attribIndex = 0; attribIndex < currentAttributes.size(); ++attribIndex) { - const auto &attrib = *sortedAttributes[attribIndex]; + const auto &attrib = *currentAttributes[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); + const auto &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel); auto *inputElement = &inputElements[inputElementCount]; @@ -584,23 +438,28 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt // 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. + + GLsizei numIndicesPerInstance = 0; + if (vertexParams.instances() > 0) + { + // This may trigger an evaluation of the index range. + numIndicesPerInstance = vertexParams.vertexCount(); + } + 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) { - // 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 && currentAttributes[elementIndex]->divisor > 0) { - 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].InstanceDataStepRate = numIndicesPerInstance; } - inputElements[elementIndex].InputSlot++; } + inputElements[elementIndex].InputSlot++; } inputElements[inputElementCount].SemanticName = "SPRITEPOSITION"; @@ -622,28 +481,23 @@ gl::Error InputLayoutCache::createInputLayout(const SortedAttribArray &sortedAtt inputElementCount++; } - const gl::InputLayout &shaderInputLayout = GetInputLayout(sortedAttributes, attribCount); - ShaderExecutableD3D *shader = nullptr; - gl::Error error = - programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr); - if (error.isError()) - { - return error; - } + ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&shader, nullptr)); 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); - } + InputElementArray inputElementArray(inputElements.data(), inputElementCount); + ShaderData vertexShaderData(shader11->getFunction(), shader11->getLength()); - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(renderer->allocateResource(inputElementArray, &vertexShaderData, inputLayoutOut)); + return gl::NoError(); +} + +void InputLayoutCache::setCacheSize(size_t newCacheSize) +{ + // Forces a reset of the cache. + LayoutCache newCache(newCacheSize); + mLayoutCache.Swap(newCache); } } // 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 e208ae3c64..8d7c7dd0f0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h @@ -20,12 +20,55 @@ #include "common/angleutils.h" #include "libANGLE/Constants.h" #include "libANGLE/Error.h" +#include "libANGLE/SizedMRUCache.h" #include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" + +namespace rx +{ +class DrawCallVertexParams; +struct PackedAttributeLayout +{ + PackedAttributeLayout(); + PackedAttributeLayout(const PackedAttributeLayout &other); + + void addAttributeData(GLenum glType, + UINT semanticIndex, + gl::VertexFormatType vertexFormatType, + unsigned int divisor); + + bool operator==(const PackedAttributeLayout &other) const; + + enum Flags + { + FLAG_USES_INSTANCED_SPRITES = 0x1, + FLAG_INSTANCED_SPRITES_ACTIVE = 0x2, + FLAG_INSTANCED_RENDERING_ACTIVE = 0x4, + }; + + uint32_t numAttributes; + uint32_t flags; + std::array attributeData; +}; +} // namespace rx + +namespace std +{ +template <> +struct hash +{ + size_t operator()(const rx::PackedAttributeLayout &value) const + { + return angle::ComputeGenericHash(value); + } +}; +} // namespace std namespace gl { class Program; -} +} // namespace gl namespace rx { @@ -33,91 +76,58 @@ struct TranslatedAttribute; struct TranslatedIndexData; struct SourceIndexData; class ProgramD3D; - -using SortedAttribArray = std::array; -using SortedIndexArray = std::array; +class Renderer11; class InputLayoutCache : angle::NonCopyable { public: InputLayoutCache(); - virtual ~InputLayoutCache(); + ~InputLayoutCache(); - void initialize(ID3D11Device *device, ID3D11DeviceContext *context); void clear(); - void markDirty(); - gl::Error applyVertexBuffers(const std::vector &attributes, + gl::Error applyVertexBuffers(const gl::Context *context, + const std::vector ¤tAttributes, GLenum mode, - gl::Program *program, - TranslatedIndexData *indexInfo, - GLsizei numIndicesPerInstance); + GLint start, + bool isIndexedRendering); - gl::Error updateVertexOffsetsForPointSpritesEmulation(GLsizei emulatedInstanceId); + gl::Error updateVertexOffsetsForPointSpritesEmulation( + Renderer11 *renderer, + const std::vector ¤tAttributes, + GLint startVertex, + GLsizei emulatedInstanceId); // Useful for testing - void setCacheSize(unsigned int cacheSize) { mCacheSize = cacheSize; } - - private: - struct PackedAttributeLayout - { - PackedAttributeLayout() - : numAttributes(0), - flags(0) - { - } - - void addAttributeData(GLenum glType, - UINT semanticIndex, - gl::VertexFormatType vertexFormatType, - unsigned int divisor); - - bool operator<(const PackedAttributeLayout &other) const; - - enum Flags - { - 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]; - }; + void setCacheSize(size_t newCacheSize); - gl::Error updateInputLayout(gl::Program *program, + gl::Error updateInputLayout(Renderer11 *renderer, + const gl::State &state, + const std::vector ¤tAttributes, 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, + const AttribIndexArray &sortedSemanticIndices, + const DrawCallVertexParams &vertexParams); + + private: + gl::Error createInputLayout(Renderer11 *renderer, + const AttribIndexArray &sortedSemanticIndices, + const std::vector ¤tAttributes, GLenum mode, gl::Program *program, - GLsizei numIndicesPerInstance, - ID3D11InputLayout **inputLayoutOut); - - std::map mLayoutMap; + const DrawCallVertexParams &vertexParams, + d3d11::InputLayout *inputLayoutOut); - 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; + // Starting cache size. + static constexpr size_t kDefaultCacheSize = 1024; - ID3D11Buffer *mPointSpriteVertexBuffer; - ID3D11Buffer *mPointSpriteIndexBuffer; + // The cache tries to clean up this many states at once. + static constexpr size_t kGCLimit = 128; - unsigned int mCacheSize; - unsigned long long mCounter; + using LayoutCache = angle::base::HashingMRUCache; + LayoutCache mLayoutCache; - ID3D11Device *mDevice; - ID3D11DeviceContext *mDeviceContext; - D3D_FEATURE_LEVEL mFeatureLevel; + d3d11::Buffer mPointSpriteVertexBuffer; + d3d11::Buffer mPointSpriteIndexBuffer; }; } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h deleted file mode 100644 index 612b06bb10..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h +++ /dev/null @@ -1,97 +0,0 @@ -// -// Copyright (c) 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. -// - -// NativeWindow.h: Defines NativeWindow, a class for managing and -// performing operations on an EGLNativeWindowType. -// It is used for HWND (Desktop Windows) and IInspectable objects -//(Windows Store Applications). - -#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ -#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ - -#include "common/debug.h" -#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 -// and IDXGIFactory and the Windows Store NativeWindow -// implementation requires IDXGISwapChain1 and IDXGIFactory2. -#if defined(ANGLE_ENABLE_WINDOWS_STORE) -typedef IDXGISwapChain1 DXGISwapChain; -typedef IDXGIFactory2 DXGIFactory; - -#include -#include -#include -#include - -namespace rx -{ -class InspectableNativeWindow; -} - -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; - -#elif defined(ANGLE_ENABLE_D3D11) -typedef IDXGISwapChain DXGISwapChain; -typedef IDXGIFactory DXGIFactory; -#endif - -typedef interface IDCompositionDevice IDCompositionDevice; -typedef interface IDCompositionTarget IDCompositionTarget; -typedef interface IDCompositionVisual IDCompositionVisual; - -namespace rx -{ - -class NativeWindow -{ - public: - enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 }; - explicit NativeWindow(EGLNativeWindowType window, - const egl::Config *config, - bool directComposition); - - ~NativeWindow(); - bool initialize(); - bool getClientRect(LPRECT rect); - bool isIconic(); -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - RotationFlags rotationFlags() const; -#endif - static bool isValidNativeWindow(EGLNativeWindowType window); - -#if defined(ANGLE_ENABLE_D3D11) - HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory, - DXGI_FORMAT format, UINT width, UINT height, - DXGISwapChain** swapChain); -#endif - - 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 - -}; - -} - -#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h new file mode 100644 index 0000000000..ab234d4450 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow11.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11.h: Defines NativeWindow11, a class for managing and performing operations on an +// EGLNativeWindowType for the D3D11 renderer. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_ + +#include "common/debug.h" +#include "common/platform.h" + +#include "libANGLE/Config.h" +#include "libANGLE/renderer/d3d/NativeWindowD3D.h" + +namespace rx +{ + +class NativeWindow11 : public NativeWindowD3D +{ + public: + NativeWindow11(EGLNativeWindowType window) : NativeWindowD3D(window) {} + + virtual HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + UINT samples, + IDXGISwapChain **swapChain) = 0; + virtual void commitChange() = 0; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW11_H_ 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 dfc521f14f..7d7ecb0976 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -36,40 +36,25 @@ namespace rx PixelTransfer11::PixelTransfer11(Renderer11 *renderer) : mRenderer(renderer), mResourcesLoaded(false), - mBufferToTextureVS(NULL), - mBufferToTextureGS(NULL), - mParamsConstantBuffer(NULL), - mCopyRasterizerState(NULL), - mCopyDepthStencilState(NULL) + mBufferToTextureVS(), + mBufferToTextureGS(), + mParamsConstantBuffer(), + mCopyRasterizerState(), + mCopyDepthStencilState() { } PixelTransfer11::~PixelTransfer11() { - for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) - { - SafeRelease(shaderMapIt->second); - } - - mBufferToTexturePSMap.clear(); - - SafeRelease(mBufferToTextureVS); - SafeRelease(mBufferToTextureGS); - SafeRelease(mParamsConstantBuffer); - SafeRelease(mCopyRasterizerState); - SafeRelease(mCopyDepthStencilState); } gl::Error PixelTransfer11::loadResources() { if (mResourcesLoaded) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - HRESULT result = S_OK; - ID3D11Device *device = mRenderer->getDevice(); - D3D11_RASTERIZER_DESC rasterDesc; rasterDesc.FillMode = D3D11_FILL_SOLID; rasterDesc.CullMode = D3D11_CULL_NONE; @@ -82,12 +67,7 @@ gl::Error PixelTransfer11::loadResources() rasterDesc.MultisampleEnable = FALSE; rasterDesc.AntialiasedLineEnable = FALSE; - result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer rasterizer state, result: 0x%X.", result); - } + ANGLE_TRY(mRenderer->allocateResource(rasterDesc, &mCopyRasterizerState)); D3D11_DEPTH_STENCIL_DESC depthStencilDesc; depthStencilDesc.DepthEnable = true; @@ -105,12 +85,7 @@ gl::Error PixelTransfer11::loadResources() depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; - result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer depth stencil state, result: 0x%X.", result); - } + ANGLE_TRY(mRenderer->allocateResource(depthStencilDesc, &mCopyDepthStencilState)); D3D11_BUFFER_DESC constantBufferDesc = { 0 }; constantBufferDesc.ByteWidth = roundUp(sizeof(CopyShaderParams), 32u); @@ -120,38 +95,23 @@ gl::Error PixelTransfer11::loadResources() constantBufferDesc.MiscFlags = 0; constantBufferDesc.StructureByteStride = 0; - result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal pixel transfer constant buffer, result: 0x%X.", result); - } - d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer"); + ANGLE_TRY(mRenderer->allocateResource(constantBufferDesc, &mParamsConstantBuffer)); + mParamsConstantBuffer.setDebugName("PixelTransfer11 constant buffer"); // init shaders - mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS"); - if (!mBufferToTextureVS) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader."); - } + ANGLE_TRY(mRenderer->allocateResource(ShaderData(g_VS_BufferToTexture), &mBufferToTextureVS)); + mBufferToTextureVS.setDebugName("BufferToTexture VS"); - mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); - if (!mBufferToTextureGS) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader."); - } + ANGLE_TRY(mRenderer->allocateResource(ShaderData(g_GS_BufferToTexture), &mBufferToTextureGS)); + mBufferToTextureGS.setDebugName("BufferToTexture GS"); - gl::Error error = buildShaderMap(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(buildShaderMap()); StructZero(&mParamsData); mResourcesLoaded = true; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, @@ -162,7 +122,7 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons float texelCenterX = 0.5f / static_cast(destSize.width - 1); float texelCenterY = 0.5f / static_cast(destSize.height - 1); - unsigned int bytesPerPixel = gl::GetInternalFormatInfo(internalFormat).pixelBytes; + unsigned int bytesPerPixel = gl::GetSizedInternalFormatInfo(internalFormat).pixelBytes; unsigned int alignmentBytes = static_cast(unpack.alignment); unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); @@ -177,14 +137,15 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons parametersOut->FirstSlice = destArea.z; } -gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +gl::Error PixelTransfer11::copyBufferToTexture(const gl::Context *context, + const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea) { - gl::Error error = loadResources(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(loadResources()); gl::Extents destSize = destRenderTarget->getExtents(); @@ -192,114 +153,106 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac destArea.y >= 0 && destArea.y + destArea.height <= destSize.height && destArea.z >= 0 && destArea.z + destArea.depth <= destSize.depth ); - const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); + const gl::Buffer &sourceBuffer = + *context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack); ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); - ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); + const d3d11::PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); ASSERT(pixelShader); // The SRV must be in the proper read format, which may be different from the destination format // EG: for half float data, we can load full precision floats with implicit conversion - GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; - GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); + GLenum unsizedFormat = gl::GetUnsizedFormat(destinationFormat); + const gl::InternalFormat &sourceglFormatInfo = + gl::GetInternalFormatInfo(unsizedFormat, sourcePixelsType); - const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat, mRenderer->getRenderer11DeviceCaps()); + const d3d11::Format &sourceFormatInfo = d3d11::Format::Get( + sourceglFormatInfo.sizedInternalFormat, mRenderer->getRenderer11DeviceCaps()); DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat; ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); Buffer11 *bufferStorage11 = GetAs(sourceBuffer.getImplementation()); - ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat); - ASSERT(bufferSRV != NULL); + const d3d11::ShaderResourceView *bufferSRV = nullptr; + ANGLE_TRY_RESULT(bufferStorage11->getSRV(context, srvFormat), bufferSRV); + ASSERT(bufferSRV != nullptr); - ID3D11RenderTargetView *textureRTV = GetAs(destRenderTarget)->getRenderTargetView(); - ASSERT(textureRTV != NULL); + const d3d11::RenderTargetView &textureRTV = + GetAs(destRenderTarget)->getRenderTargetView(); + ASSERT(textureRTV.valid()); CopyShaderParams shaderParams; - setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams); + setBufferToTextureCopyParams(destArea, destSize, sourceglFormatInfo.sizedInternalFormat, unpack, + offset, &shaderParams); ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - ID3D11Buffer *nullBuffer = NULL; - UINT zero = 0; - // Are we doing a 2D or 3D copy? - ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); - auto stateManager = mRenderer->getStateManager(); + const auto *geometryShader = ((destSize.depth > 1) ? &mBufferToTextureGS : nullptr); + StateManager11 *stateManager = mRenderer->getStateManager(); - deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); - deviceContext->GSSetShader(geometryShader, NULL, 0); - deviceContext->PSSetShader(pixelShader, NULL, 0); + stateManager->setDrawShaders(&mBufferToTextureVS, geometryShader, pixelShader); stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, bufferSRV); - deviceContext->IASetInputLayout(NULL); - deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + stateManager->setInputLayout(nullptr); + stateManager->setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); - deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF); - deviceContext->RSSetState(mCopyRasterizerState); + stateManager->setSingleVertexBuffer(nullptr, 0, 0); + stateManager->setSimpleBlendState(nullptr); + stateManager->setDepthStencilState(&mCopyDepthStencilState, 0xFFFFFFFF); + stateManager->setRasterizerState(&mCopyRasterizerState); - mRenderer->setOneTimeRenderTarget(textureRTV); + stateManager->setRenderTarget(textureRTV.get(), nullptr); if (!StructEquals(mParamsData, shaderParams)) { - d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams); + d3d11::SetBufferData(deviceContext, mParamsConstantBuffer.get(), shaderParams); mParamsData = shaderParams; } - deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer); + stateManager->setVertexConstantBuffer(0, &mParamsConstantBuffer); // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = static_cast(destSize.width); - viewport.Height = static_cast(destSize.height); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); + stateManager->setSimpleViewport(destSize); UINT numPixels = (destArea.width * destArea.height * destArea.depth); deviceContext->Draw(numPixels, 0); - // Unbind textures and render targets and vertex buffer - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, NULL); - deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); - - mRenderer->markAllStateDirty(); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error PixelTransfer11::buildShaderMap() { - ID3D11Device *device = mRenderer->getDevice(); - - mBufferToTexturePSMap[GL_FLOAT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4F, "BufferToTexture RGBA ps"); - mBufferToTexturePSMap[GL_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4I, "BufferToTexture RGBA-I ps"); - mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps"); - - // Check that all the shaders were created successfully - for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) - { - if (shaderMapIt->second == NULL) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture pixel shader."); - } - } - - return gl::Error(GL_NO_ERROR); + d3d11::PixelShader bufferToTextureFloat; + d3d11::PixelShader bufferToTextureInt; + d3d11::PixelShader bufferToTextureUint; + + ANGLE_TRY( + mRenderer->allocateResource(ShaderData(g_PS_BufferToTexture_4F), &bufferToTextureFloat)); + ANGLE_TRY( + mRenderer->allocateResource(ShaderData(g_PS_BufferToTexture_4I), &bufferToTextureInt)); + ANGLE_TRY( + mRenderer->allocateResource(ShaderData(g_PS_BufferToTexture_4UI), &bufferToTextureUint)); + + bufferToTextureFloat.setDebugName("BufferToTexture RGBA ps"); + bufferToTextureInt.setDebugName("BufferToTexture RGBA-I ps"); + bufferToTextureUint.setDebugName("BufferToTexture RGBA-UI ps"); + + mBufferToTexturePSMap[GL_FLOAT] = std::move(bufferToTextureFloat); + mBufferToTexturePSMap[GL_INT] = std::move(bufferToTextureInt); + mBufferToTexturePSMap[GL_UNSIGNED_INT] = std::move(bufferToTextureUint); + + return gl::NoError(); } -ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const +const d3d11::PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const { - GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType; + GLenum componentType = gl::GetSizedInternalFormatInfo(internalFormat).componentType; if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED) { componentType = GL_FLOAT; } auto shaderMapIt = mBufferToTexturePSMap.find(componentType); - return (shaderMapIt == mBufferToTexturePSMap.end() ? NULL : shaderMapIt->second); + return (shaderMapIt == mBufferToTexturePSMap.end() ? nullptr : &shaderMapIt->second); } -} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h index 1672121ec7..a93544247e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h @@ -11,14 +11,14 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ -#include "libANGLE/Error.h" - -#include "common/platform.h" - #include #include +#include "common/platform.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" + namespace gl { @@ -45,8 +45,13 @@ class PixelTransfer11 // destRenderTarget: individual slice/layer of a target texture // destinationFormat/sourcePixelsType: determines shaders + shader parameters // destArea: the sub-section of destRenderTarget to copy to - gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + gl::Error copyBufferToTexture(const gl::Context *context, + const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea); private: @@ -68,22 +73,21 @@ class PixelTransfer11 gl::Error loadResources(); gl::Error buildShaderMap(); - ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const; + const d3d11::PixelShader *findBufferToTexturePS(GLenum internalFormat) const; Renderer11 *mRenderer; bool mResourcesLoaded; - std::map mBufferToTexturePSMap; - ID3D11VertexShader *mBufferToTextureVS; - ID3D11GeometryShader *mBufferToTextureGS; - ID3D11Buffer *mParamsConstantBuffer; + std::map mBufferToTexturePSMap; + d3d11::VertexShader mBufferToTextureVS; + d3d11::GeometryShader mBufferToTextureGS; + d3d11::Buffer mParamsConstantBuffer; CopyShaderParams mParamsData; - ID3D11RasterizerState *mCopyRasterizerState; - ID3D11DepthStencilState *mCopyDepthStencilState; - + d3d11::RasterizerState mCopyRasterizerState; + d3d11::DepthStencilState mCopyDepthStencilState; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp new file mode 100644 index 0000000000..c9554431e5 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.cpp @@ -0,0 +1,24 @@ +// +// Copyright 2017 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. +// +// ProgramPipelineNULL.cpp: +// Implements the class methods for ProgramPipeline11. +// + +#include "libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h" + +namespace rx +{ + +ProgramPipeline11::ProgramPipeline11(const gl::ProgramPipelineState &state) + : ProgramPipelineImpl(state) +{ +} + +ProgramPipeline11::~ProgramPipeline11() +{ +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h new file mode 100644 index 0000000000..cf838eec05 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ProgramPipeline11.h @@ -0,0 +1,27 @@ +// +// Copyright 2017 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. +// +// ProgramPipeline11.h: +// Defines the class interface for ProgramPipeline11, implementing ProgramPipelineImpl. +// + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_ + +#include "libANGLE/renderer/ProgramPipelineImpl.h" + +namespace rx +{ + +class ProgramPipeline11 : public ProgramPipelineImpl +{ + public: + ProgramPipeline11(const gl::ProgramPipelineState &state); + ~ProgramPipeline11() override; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_PROGRAMPIPELINE11_H_ 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 0a79b26df0..66b9476e7f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp @@ -7,146 +7,96 @@ // Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. #include "libANGLE/renderer/d3d/d3d11/Query11.h" -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" -#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" -#include "common/utilities.h" #include -#if defined(ANGLE_MINGW32_COMPAT) -typedef struct D3D11_QUERY_DATA_SO_STATISTICS { - UINT64 NumPrimitivesWritten; - UINT64 PrimitivesStorageNeeded; -} D3D11_QUERY_DATA_SO_STATISTICS; -#endif // ANGLE_MINGW32_COMPAT - -#ifndef ANGLE_D3D11_QDTD_AVAILABLE -typedef struct D3D11_QUERY_DATA_TIMESTAMP_DISJOINT { - UINT64 Frequency; - BOOL Disjoint; -} D3D11_QUERY_DATA_TIMESTAMP_DISJOINT; -#endif // MINGW32 +#include "common/utilities.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" -namespace rx +namespace { -Query11::Query11(Renderer11 *renderer, GLenum type) - : QueryImpl(type), - mResult(0), - mQueryFinished(false), - mRenderer(renderer), - mQuery(nullptr), - mTimestampBeginQuery(nullptr), - mTimestampEndQuery(nullptr) +GLuint64 MergeQueryResults(GLenum type, GLuint64 currentResult, GLuint64 newResult) { -} + switch (type) + { + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return (currentResult == GL_TRUE || newResult == GL_TRUE) ? GL_TRUE : GL_FALSE; -Query11::~Query11() -{ - SafeRelease(mQuery); - SafeRelease(mTimestampBeginQuery); - SafeRelease(mTimestampEndQuery); -} + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return currentResult + newResult; -gl::Error Query11::begin() -{ - if (mQuery == nullptr) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = gl_d3d11::ConvertQueryType(getType()); - queryDesc.MiscFlags = 0; + case GL_TIME_ELAPSED_EXT: + return currentResult + newResult; - ID3D11Device *device = mRenderer->getDevice(); + case GL_TIMESTAMP_EXT: + return newResult; - HRESULT result = device->CreateQuery(&queryDesc, &mQuery); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); - } + case GL_COMMANDS_COMPLETED_CHROMIUM: + return newResult; - // 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); - } - } + default: + UNREACHABLE(); + return 0; } +} - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); +} // anonymous namespace - context->Begin(mQuery); +namespace rx +{ - // 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); +Query11::QueryState::QueryState() : query(), beginTimestamp(), endTimestamp(), finished(false) +{ } -gl::Error Query11::end() +Query11::QueryState::~QueryState() { - ASSERT(mQuery); - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); +} - // If we are doing time elapsed query the end timestamp - if (getType() == GL_TIME_ELAPSED_EXT) - { - context->End(mTimestampEndQuery); - } +Query11::Query11(Renderer11 *renderer, GLenum type) + : QueryImpl(type), mResult(0), mResultSum(0), mRenderer(renderer) +{ + mActiveQuery = std::unique_ptr(new QueryState()); +} - context->End(mQuery); +Query11::~Query11() +{ + mRenderer->getStateManager()->onDeleteQueryObject(this); +} - mQueryFinished = false; - mResult = GL_FALSE; +gl::Error Query11::begin() +{ + mResultSum = 0; + mRenderer->getStateManager()->onBeginQuery(this); + return resume(); +} - return gl::Error(GL_NO_ERROR); +gl::Error Query11::end() +{ + return pause(); } 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); + mResultSum = 0; + mPendingQueries.push_back(std::unique_ptr(new QueryState())); + return gl::NoError(); } template gl::Error Query11::getResultBase(T *params) { - while (!mQueryFinished) - { - gl::Error error = testQuery(); - if (error.isError()) - { - return error; - } - - if (!mQueryFinished) - { - ScheduleYield(); - } - } + ASSERT(!mActiveQuery->query.valid()); + ANGLE_TRY(flush(true)); + ASSERT(mPendingQueries.empty()); + *params = static_cast(mResultSum); - ASSERT(mQueryFinished); - *params = static_cast(mResult); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Query11::getResult(GLint *params) @@ -171,105 +121,197 @@ gl::Error Query11::getResult(GLuint64 *params) gl::Error Query11::isResultAvailable(bool *available) { - gl::Error error = testQuery(); - if (error.isError()) + ANGLE_TRY(flush(false)); + + *available = mPendingQueries.empty(); + return gl::NoError(); +} + +gl::Error Query11::pause() +{ + if (mActiveQuery->query.valid()) { - return error; + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + GLenum queryType = getType(); + + // If we are doing time elapsed query the end timestamp + if (queryType == GL_TIME_ELAPSED_EXT) + { + context->End(mActiveQuery->endTimestamp.get()); + } + + context->End(mActiveQuery->query.get()); + + mPendingQueries.push_back(std::move(mActiveQuery)); + mActiveQuery = std::unique_ptr(new QueryState()); } - *available = mQueryFinished; + return flush(false); +} + +gl::Error Query11::resume() +{ + if (!mActiveQuery->query.valid()) + { + ANGLE_TRY(flush(false)); + + GLenum queryType = getType(); + D3D11_QUERY d3dQueryType = gl_d3d11::ConvertQueryType(queryType); - return gl::Error(GL_NO_ERROR); + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = d3dQueryType; + queryDesc.MiscFlags = 0; + + ANGLE_TRY(mRenderer->allocateResource(queryDesc, &mActiveQuery->query)); + + // If we are doing time elapsed we also need a query to actually query the timestamp + if (queryType == GL_TIME_ELAPSED_EXT) + { + D3D11_QUERY_DESC desc; + desc.Query = D3D11_QUERY_TIMESTAMP; + desc.MiscFlags = 0; + + ANGLE_TRY(mRenderer->allocateResource(desc, &mActiveQuery->beginTimestamp)); + ANGLE_TRY(mRenderer->allocateResource(desc, &mActiveQuery->endTimestamp)); + } + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + if (d3dQueryType != D3D11_QUERY_EVENT) + { + context->Begin(mActiveQuery->query.get()); + } + + // If we are doing time elapsed, query the begin timestamp + if (queryType == GL_TIME_ELAPSED_EXT) + { + context->End(mActiveQuery->beginTimestamp.get()); + } + } + + return gl::NoError(); } -gl::Error Query11::testQuery() +gl::Error Query11::flush(bool force) { - if (!mQueryFinished) + while (!mPendingQueries.empty()) { - ASSERT(mQuery); + QueryState *query = mPendingQueries.front().get(); + do + { + ANGLE_TRY(testQuery(query)); + if (!query->finished && !force) + { + return gl::NoError(); + } + } while (!query->finished); + + mResultSum = MergeQueryResults(getType(), mResultSum, mResult); + mPendingQueries.pop_front(); + } + + return gl::NoError(); +} + +gl::Error Query11::testQuery(QueryState *queryState) +{ + if (!queryState->finished) + { ID3D11DeviceContext *context = mRenderer->getDeviceContext(); switch (getType()) { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: { + ASSERT(queryState->query.valid()); UINT64 numPixels = 0; - HRESULT result = context->GetData(mQuery, &numPixels, sizeof(numPixels), 0); + HRESULT result = + context->GetData(queryState->query.get(), &numPixels, sizeof(numPixels), 0); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result); + return gl::OutOfMemory() + << "Failed to get the data of an internal query, " << gl::FmtHR(result); } if (result == S_OK) { - mQueryFinished = true; - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + queryState->finished = true; + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; } } break; - case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: { - D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 }; - HRESULT result = context->GetData(mQuery, &soStats, sizeof(soStats), 0); + ASSERT(queryState->query.valid()); + D3D11_QUERY_DATA_SO_STATISTICS soStats = {0}; + HRESULT result = + context->GetData(queryState->query.get(), &soStats, sizeof(soStats), 0); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get the data of an internal query, result: 0x%X.", result); + return gl::OutOfMemory() + << "Failed to get the data of an internal query, " << gl::FmtHR(result); } if (result == S_OK) { - mQueryFinished = true; - mResult = static_cast(soStats.NumPrimitivesWritten); + queryState->finished = true; + mResult = static_cast(soStats.NumPrimitivesWritten); } } break; case GL_TIME_ELAPSED_EXT: { + ASSERT(queryState->query.valid()); + ASSERT(queryState->beginTimestamp.valid()); + ASSERT(queryState->endTimestamp.valid()); D3D11_QUERY_DATA_TIMESTAMP_DISJOINT timeStats = {0}; - HRESULT result = context->GetData(mQuery, &timeStats, sizeof(timeStats), 0); + HRESULT result = + context->GetData(queryState->query.get(), &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); + return gl::OutOfMemory() + << "Failed to get the data of an internal query, " << gl::FmtHR(result); } if (result == S_OK) { UINT64 beginTime = 0; - HRESULT beginRes = - context->GetData(mTimestampBeginQuery, &beginTime, sizeof(UINT64), 0); + HRESULT beginRes = context->GetData(queryState->beginTimestamp.get(), + &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); + return gl::OutOfMemory() << "Failed to get the data of an internal query, " + << gl::FmtHR(beginRes); } UINT64 endTime = 0; - HRESULT endRes = - context->GetData(mTimestampEndQuery, &endTime, sizeof(UINT64), 0); + HRESULT endRes = context->GetData(queryState->endTimestamp.get(), &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); + return gl::OutOfMemory() << "Failed to get the data of an internal query, " + << gl::FmtHR(endRes); } if (beginRes == S_OK && endRes == S_OK) { - mQueryFinished = true; + queryState->finished = 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)) + + angle::CheckedNumeric checkedTime(endTime); + checkedTime -= beginTime; + checkedTime *= 1000000000ull; + checkedTime /= timeStats.Frequency; + if (checkedTime.IsValid()) { - mResult = ((endTime - beginTime) * 1000000000ull) / timeStats.Frequency; + mResult = checkedTime.ValueOrDie(); } else { @@ -288,23 +330,46 @@ gl::Error Query11::testQuery() // 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; + ASSERT(!queryState->query.valid()); + mResult = 0; + queryState->finished = true; } break; - default: - UNREACHABLE(); + case GL_COMMANDS_COMPLETED_CHROMIUM: + { + ASSERT(queryState->query.valid()); + BOOL completed = 0; + HRESULT result = + context->GetData(queryState->query.get(), &completed, sizeof(completed), 0); + if (FAILED(result)) + { + return gl::OutOfMemory() + << "Failed to get the data of an internal query, " << gl::FmtHR(result); + } + + if (result == S_OK) + { + queryState->finished = true; + ASSERT(completed == TRUE); + mResult = (completed == TRUE) ? GL_TRUE : GL_FALSE; + } + } break; + + default: + UNREACHABLE(); + break; } - if (!mQueryFinished && mRenderer->testDeviceLost()) + if (!queryState->finished && mRenderer->testDeviceLost()) { mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); + return gl::OutOfMemory() << "Failed to test get query result, device is lost."; } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -} +} // namespace rx 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 29a6e6f85d..a88a8892aa 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h @@ -9,7 +9,10 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_ +#include + #include "libANGLE/renderer/QueryImpl.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" namespace rx { @@ -19,31 +22,45 @@ class Query11 : public QueryImpl { public: Query11(Renderer11 *renderer, GLenum type); - virtual ~Query11(); + ~Query11() override; + + gl::Error begin() override; + gl::Error end() override; + gl::Error queryCounter() override; + gl::Error getResult(GLint *params) override; + gl::Error getResult(GLuint *params) override; + gl::Error getResult(GLint64 *params) override; + gl::Error getResult(GLuint64 *params) override; + gl::Error isResultAvailable(bool *available) override; - 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 getResult(GLint64 *params); - virtual gl::Error getResult(GLuint64 *params); - virtual gl::Error isResultAvailable(bool *available); + gl::Error pause(); + gl::Error resume(); private: - gl::Error testQuery(); + struct QueryState final : private angle::NonCopyable + { + QueryState(); + ~QueryState(); + + d3d11::Query query; + d3d11::Query beginTimestamp; + d3d11::Query endTimestamp; + bool finished; + }; + + gl::Error flush(bool force); + gl::Error testQuery(QueryState *queryState); template gl::Error getResultBase(T *params); GLuint64 mResult; - - bool mQueryFinished; + GLuint64 mResultSum; Renderer11 *mRenderer; - ID3D11Query *mQuery; - ID3D11Query *mTimestampBeginQuery; - ID3D11Query *mTimestampEndQuery; + + std::unique_ptr mActiveQuery; + std::deque> mPendingQueries; }; } 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 2ee25cfb6c..5b85196c2e 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp @@ -17,338 +17,180 @@ #include "libANGLE/renderer/d3d/FramebufferD3D.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" -#include "third_party/murmurhash/MurmurHash3.h" namespace rx { using namespace gl_d3d11; -template -static void ClearStateMap(mapType &map) -{ - for (typename mapType::iterator i = map.begin(); i != map.end(); i++) - { - SafeRelease(i->second.first); - } - map.clear(); -} - -// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState, -// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum -// number of unique states of each type an application can create is 4096 -const unsigned int RenderStateCache::kMaxBlendStates = 4096; -const unsigned int RenderStateCache::kMaxRasterizerStates = 4096; -const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096; -const unsigned int RenderStateCache::kMaxSamplerStates = 4096; - -RenderStateCache::RenderStateCache(Renderer11 *renderer) - : mRenderer(renderer), - mCounter(0), - mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), - mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), - mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), - mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates), - mDevice(NULL) +RenderStateCache::RenderStateCache() + : mBlendStateCache(kMaxStates), + mRasterizerStateCache(kMaxStates), + mDepthStencilStateCache(kMaxStates), + mSamplerStateCache(kMaxStates) { } RenderStateCache::~RenderStateCache() { - clear(); -} - -void RenderStateCache::initialize(ID3D11Device *device) -{ - clear(); - mDevice = device; } void RenderStateCache::clear() { - ClearStateMap(mBlendStateCache); - ClearStateMap(mRasterizerStateCache); - ClearStateMap(mDepthStencilStateCache); - ClearStateMap(mSamplerStateCache); + mBlendStateCache.Clear(); + mRasterizerStateCache.Clear(); + mDepthStencilStateCache.Clear(); + mSamplerStateCache.Clear(); } -std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) +// static +d3d11::BlendStateKey RenderStateCache::GetBlendStateKey(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState) { - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash); - return hash; -} + d3d11::BlendStateKey key; + FramebufferD3D *framebufferD3D = GetImplAs(framebuffer); + const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(context); + const UINT8 blendStateMask = + gl_d3d11::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, + blendState.colorMaskBlue, blendState.colorMaskAlpha); -bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b) -{ - return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; -} - -gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, - ID3D11BlendState **outBlendState) -{ - if (!mDevice) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); - } - - bool mrt = false; - - const FramebufferD3D *framebufferD3D = GetImplAs(framebuffer); - const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(); - - BlendStateKey key = {}; key.blendState = blendState; - for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) - { - const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment]; - auto rtChannels = key.rtChannels[colorAttachment]; + for (size_t i = 0; i < colorbuffers.size(); i++) + { + const gl::FramebufferAttachment *attachment = colorbuffers[i]; if (attachment) { - if (colorAttachment > 0) - { - mrt = true; - } - - rtChannels[0] = attachment->getRedSize() > 0; - rtChannels[1] = attachment->getGreenSize() > 0; - rtChannels[2] = attachment->getBlueSize() > 0; - rtChannels[3] = attachment->getAlphaSize() > 0; + key.rtvMax = static_cast(i) + 1; + key.rtvMasks[i] = + (gl_d3d11::GetColorMask(*attachment->getFormat().info)) & blendStateMask; } } - BlendStateMap::iterator keyIter = mBlendStateCache.find(key); + return key; +} + +gl::Error RenderStateCache::getBlendState(Renderer11 *renderer, + const d3d11::BlendStateKey &key, + const d3d11::BlendState **outBlendState) +{ + auto keyIter = mBlendStateCache.Get(key); if (keyIter != mBlendStateCache.end()) { - BlendStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outBlendState = state.first; - return gl::Error(GL_NO_ERROR); + *outBlendState = &keyIter->second; + return gl::NoError(); } - else - { - if (mBlendStateCache.size() >= kMaxBlendStates) - { - TRACE("Overflowed the limit of %u blend states, removing the least recently used " - "to make room.", kMaxBlendStates); - - BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin(); - for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - SafeRelease(leastRecentlyUsed->second.first); - mBlendStateCache.erase(leastRecentlyUsed); - } - // Create a new blend state and insert it into the cache - D3D11_BLEND_DESC blendDesc = { 0 }; - blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; - blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE; + TrimCache(kMaxStates, kGCLimit, "blend state", &mBlendStateCache); - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) - { - D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; - - rtBlend.BlendEnable = blendState.blend; - if (blendState.blend) - { - rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); - rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); - rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); - - rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); - rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); - rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); - } - - rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed, - key.rtChannels[i][1] && blendState.colorMaskGreen, - key.rtChannels[i][2] && blendState.colorMaskBlue, - key.rtChannels[i][3] && blendState.colorMaskAlpha); - } + // Create a new blend state and insert it into the cache + D3D11_BLEND_DESC blendDesc; + D3D11_RENDER_TARGET_BLEND_DESC &rtDesc0 = blendDesc.RenderTarget[0]; + const gl::BlendState &blendState = key.blendState; - ID3D11BlendState *dx11BlendState = NULL; - HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); - if (FAILED(result) || !dx11BlendState) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); - } + blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; + blendDesc.IndependentBlendEnable = key.rtvMax > 1 ? TRUE : FALSE; - mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); + rtDesc0 = {}; - *outBlendState = dx11BlendState; - return gl::Error(GL_NO_ERROR); + if (blendState.blend) + { + rtDesc0.BlendEnable = true; + rtDesc0.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); + rtDesc0.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); + rtDesc0.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); + rtDesc0.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); + rtDesc0.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); + rtDesc0.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); } -} -std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState) -{ - static const unsigned int seed = 0xABCDEF98; + rtDesc0.RenderTargetWriteMask = key.rtvMasks[0]; - std::size_t hash = 0; - MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash); - return hash; -} + for (unsigned int i = 1; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + blendDesc.RenderTarget[i] = rtDesc0; + blendDesc.RenderTarget[i].RenderTargetWriteMask = key.rtvMasks[i]; + } -bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b) -{ - return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; + d3d11::BlendState d3dBlendState; + ANGLE_TRY(renderer->allocateResource(blendDesc, &d3dBlendState)); + const auto &iter = mBlendStateCache.Put(key, std::move(d3dBlendState)); + + *outBlendState = &iter->second; + + return gl::NoError(); } -gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, +gl::Error RenderStateCache::getRasterizerState(Renderer11 *renderer, + const gl::RasterizerState &rasterState, + bool scissorEnabled, ID3D11RasterizerState **outRasterizerState) { - if (!mDevice) - { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); - } - - RasterizerStateKey key = {}; + d3d11::RasterizerStateKey key; key.rasterizerState = rasterState; - key.scissorEnabled = scissorEnabled; + key.scissorEnabled = scissorEnabled ? 1 : 0; - RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key); + auto keyIter = mRasterizerStateCache.Get(key); if (keyIter != mRasterizerStateCache.end()) { - RasterizerStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outRasterizerState = state.first; - return gl::Error(GL_NO_ERROR); + *outRasterizerState = keyIter->second.get(); + return gl::NoError(); } - else - { - if (mRasterizerStateCache.size() >= kMaxRasterizerStates) - { - TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used " - "to make room.", kMaxRasterizerStates); - - RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin(); - for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - SafeRelease(leastRecentlyUsed->second.first); - mRasterizerStateCache.erase(leastRecentlyUsed); - } - D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode); + TrimCache(kMaxStates, kGCLimit, "rasterizer state", &mRasterizerStateCache); - // Disable culling if drawing points - if (rasterState.pointDrawMode) - { - cullMode = D3D11_CULL_NONE; - } + D3D11_CULL_MODE cullMode = + gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode); - D3D11_RASTERIZER_DESC rasterDesc; - rasterDesc.FillMode = D3D11_FILL_SOLID; - rasterDesc.CullMode = cullMode; - rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE; - rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. - rasterDesc.DepthClipEnable = TRUE; - rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; - rasterDesc.MultisampleEnable = rasterState.multiSample; - rasterDesc.AntialiasedLineEnable = FALSE; - - if (rasterState.polygonOffsetFill) - { - rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; - rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits; - } - else - { - rasterDesc.SlopeScaledDepthBias = 0.0f; - rasterDesc.DepthBias = 0; - } - - ID3D11RasterizerState *dx11RasterizerState = NULL; - HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); - if (FAILED(result) || !dx11RasterizerState) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); - } - - mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++))); - - *outRasterizerState = dx11RasterizerState; - return gl::Error(GL_NO_ERROR); - } -} - -std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState) -{ - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash); - return hash; -} - -bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b) -{ - return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; -} - -gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &originalState, - bool disableDepth, - bool disableStencil, - ID3D11DepthStencilState **outDSState) -{ - if (!mDevice) + // Disable culling if drawing points + if (rasterState.pointDrawMode) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + cullMode = D3D11_CULL_NONE; } - gl::DepthStencilState glState = originalState; - if (disableDepth) + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = cullMode; + rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE : TRUE; + rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of + // zero will preform no clamping, must be tested though. + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; + rasterDesc.MultisampleEnable = rasterState.multiSample; + rasterDesc.AntialiasedLineEnable = FALSE; + + if (rasterState.polygonOffsetFill) { - glState.depthTest = false; - glState.depthMask = false; + rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; + rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits; } - - if (disableStencil) + else { - glState.stencilWritemask = 0; - glState.stencilBackWritemask = 0; - glState.stencilTest = false; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBias = 0; } - auto keyIter = mDepthStencilStateCache.find(glState); + d3d11::RasterizerState dx11RasterizerState; + ANGLE_TRY(renderer->allocateResource(rasterDesc, &dx11RasterizerState)); + *outRasterizerState = dx11RasterizerState.get(); + mRasterizerStateCache.Put(key, std::move(dx11RasterizerState)); + + return gl::NoError(); +} + +gl::Error RenderStateCache::getDepthStencilState(Renderer11 *renderer, + const gl::DepthStencilState &glState, + const d3d11::DepthStencilState **outDSState) +{ + auto keyIter = mDepthStencilStateCache.Get(glState); if (keyIter != mDepthStencilStateCache.end()) { - DepthStencilStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outDSState = state.first; - return gl::Error(GL_NO_ERROR); + *outDSState = &keyIter->second; + return gl::NoError(); } - if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) - { - TRACE( - "Overflowed the limit of %u depth stencil states, removing the least recently used " - "to make room.", - kMaxDepthStencilStates); - - auto leastRecentlyUsed = mDepthStencilStateCache.begin(); - for (auto i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - SafeRelease(leastRecentlyUsed->second.first); - mDepthStencilStateCache.erase(leastRecentlyUsed); - } + TrimCache(kMaxStates, kGCLimit, "depth stencil state", &mDepthStencilStateCache); D3D11_DEPTH_STENCIL_DESC dsDesc = {0}; dsDesc.DepthEnable = glState.depthTest ? TRUE : FALSE; @@ -366,107 +208,66 @@ gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &or 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); - } + d3d11::DepthStencilState dx11DepthStencilState; + ANGLE_TRY(renderer->allocateResource(dsDesc, &dx11DepthStencilState)); + const auto &iter = mDepthStencilStateCache.Put(glState, std::move(dx11DepthStencilState)); - mDepthStencilStateCache.insert( - std::make_pair(glState, std::make_pair(dx11DepthStencilState, mCounter++))); + *outDSState = &iter->second; - *outDSState = dx11DepthStencilState; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) +gl::Error RenderStateCache::getSamplerState(Renderer11 *renderer, + const gl::SamplerState &samplerState, + ID3D11SamplerState **outSamplerState) { - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash); - return hash; -} - -bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b) -{ - return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0; -} - -gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState) -{ - if (!mDevice) + auto keyIter = mSamplerStateCache.Get(samplerState); + if (keyIter != mSamplerStateCache.end()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); + *outSamplerState = keyIter->second.get(); + return gl::NoError(); } - SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState); - if (keyIter != mSamplerStateCache.end()) + TrimCache(kMaxStates, kGCLimit, "sampler state", &mSamplerStateCache); + + const auto &featureLevel = renderer->getRenderer11DeviceCaps().featureLevel; + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = + gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, + samplerState.maxAnisotropy, samplerState.compareMode); + samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); + samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); + samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR); + samplerDesc.MipLODBias = 0; + samplerDesc.MaxAnisotropy = + gl_d3d11::ConvertMaxAnisotropy(samplerState.maxAnisotropy, featureLevel); + samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc); + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = samplerState.minLod; + samplerDesc.MaxLOD = samplerState.maxLod; + + if (featureLevel <= D3D_FEATURE_LEVEL_9_3) { - SamplerStateCounterPair &state = keyIter->second; - state.second = mCounter++; - *outSamplerState = state.first; - return gl::Error(GL_NO_ERROR); + // 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. + ASSERT(samplerState.maxLod >= 999.9f); + + // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD + // workaround) should take account of this. + samplerDesc.MaxLOD = FLT_MAX; } - else - { - if (mSamplerStateCache.size() >= kMaxSamplerStates) - { - TRACE("Overflowed the limit of %u sampler states, removing the least recently used " - "to make room.", kMaxSamplerStates); - - SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin(); - for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - SafeRelease(leastRecentlyUsed->second.first); - mSamplerStateCache.erase(leastRecentlyUsed); - } - D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, - samplerState.maxAnisotropy, samplerState.compareMode); - samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); - samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); - samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR); - samplerDesc.MipLODBias = 0; - samplerDesc.MaxAnisotropy = static_cast(samplerState.maxAnisotropy); - samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc); - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = samplerState.minLod; - samplerDesc.MaxLOD = samplerState.maxLod; - - 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. - ASSERT(samplerState.maxLod >= 999.9f); - - // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD workaround) should take account of this. - samplerDesc.MaxLOD = FLT_MAX; - } + d3d11::SamplerState dx11SamplerState; + ANGLE_TRY(renderer->allocateResource(samplerDesc, &dx11SamplerState)); + *outSamplerState = dx11SamplerState.get(); + mSamplerStateCache.Put(samplerState, std::move(dx11SamplerState)); - ID3D11SamplerState *dx11SamplerState = NULL; - HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); - if (FAILED(result) || !dx11SamplerState) - { - return gl::Error(GL_OUT_OF_MEMORY, "Unable to create a ID3D11SamplerState, HRESULT: 0x%X.", result); - } - - mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++))); - - *outSamplerState = dx11SamplerState; - return gl::Error(GL_NO_ERROR); - } + return gl::NoError(); } -} +} // namespace rx 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 82cb13903c..7501e83fc4 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h @@ -10,9 +10,11 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ #define LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ -#include "libANGLE/angletypes.h" -#include "libANGLE/Error.h" #include "common/angleutils.h" +#include "libANGLE/Error.h" +#include "libANGLE/SizedMRUCache.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #include @@ -21,6 +23,42 @@ namespace gl class Framebuffer; } +namespace std +{ +template <> +struct hash +{ + size_t operator()(const rx::d3d11::BlendStateKey &key) const + { + return angle::ComputeGenericHash(key); + } +}; + +template <> +struct hash +{ + size_t operator()(const rx::d3d11::RasterizerStateKey &key) const + { + return angle::ComputeGenericHash(key); + } +}; + +template <> +struct hash +{ + size_t operator()(const gl::DepthStencilState &key) const + { + return angle::ComputeGenericHash(key); + } +}; + +template <> +struct hash +{ + size_t operator()(const gl::SamplerState &key) const { return angle::ComputeGenericHash(key); } +}; +} // namespace std + namespace rx { class Renderer11; @@ -28,87 +66,58 @@ class Renderer11; class RenderStateCache : angle::NonCopyable { public: - RenderStateCache(Renderer11 *renderer); + RenderStateCache(); virtual ~RenderStateCache(); - void initialize(ID3D11Device *device); void clear(); - 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, - bool disableDepth, - bool disableStencil, - ID3D11DepthStencilState **outDSState); - gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState); + static d3d11::BlendStateKey GetBlendStateKey(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState); + gl::Error getBlendState(Renderer11 *renderer, + const d3d11::BlendStateKey &key, + const d3d11::BlendState **outBlendState); + gl::Error getRasterizerState(Renderer11 *renderer, + const gl::RasterizerState &rasterState, + bool scissorEnabled, + ID3D11RasterizerState **outRasterizerState); + gl::Error getDepthStencilState(Renderer11 *renderer, + const gl::DepthStencilState &dsState, + const d3d11::DepthStencilState **outDSState); + gl::Error getSamplerState(Renderer11 *renderer, + const gl::SamplerState &samplerState, + ID3D11SamplerState **outSamplerState); private: - Renderer11 *mRenderer; - unsigned long long mCounter; + // MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState, + // ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum + // number of unique states of each type an application can create is 4096 + // TODO(ShahmeerEsmail): Revisit the cache sizes to make sure they are appropriate for most + // scenarios. + static constexpr unsigned int kMaxStates = 4096; + + // The cache tries to clean up this many states at once. + static constexpr unsigned int kGCLimit = 128; // Blend state cache - struct BlendStateKey - { - gl::BlendState blendState; - bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; - }; - static std::size_t hashBlendState(const BlendStateKey &blendState); - static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b); - static const unsigned int kMaxBlendStates; - - typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &); - typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &); - typedef std::pair BlendStateCounterPair; - typedef std::unordered_map BlendStateMap; + using BlendStateMap = angle::base::HashingMRUCache; BlendStateMap mBlendStateCache; // Rasterizer state cache - struct RasterizerStateKey - { - gl::RasterizerState rasterizerState; - bool scissorEnabled; - }; - static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState); - static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b); - static const unsigned int kMaxRasterizerStates; - - typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &); - typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &); - typedef std::pair RasterizerStateCounterPair; - typedef std::unordered_map RasterizerStateMap; + using RasterizerStateMap = + angle::base::HashingMRUCache; RasterizerStateMap mRasterizerStateCache; // Depth stencil state cache - static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState); - static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b); - static const unsigned int kMaxDepthStencilStates; - - typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &); - typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &); - typedef std::pair DepthStencilStateCounterPair; - typedef std::unordered_map DepthStencilStateMap; + using DepthStencilStateMap = + angle::base::HashingMRUCache; DepthStencilStateMap mDepthStencilStateCache; // Sample state cache - static std::size_t hashSamplerState(const gl::SamplerState &samplerState); - static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b); - static const unsigned int kMaxSamplerStates; - - typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &); - typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &); - typedef std::pair SamplerStateCounterPair; - typedef std::unordered_map SamplerStateMap; + using SamplerStateMap = angle::base::HashingMRUCache; SamplerStateMap mSamplerStateCache; - - ID3D11Device *mDevice; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_ 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 cdfcacc287..594a382a72 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp @@ -18,7 +18,9 @@ namespace rx { -static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) +namespace +{ +bool GetTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) { ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject(resource); if (texture1D) @@ -62,7 +64,7 @@ static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLeve return false; } -static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) +unsigned int GetRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; view->GetDesc(&rtvDesc); @@ -72,58 +74,58 @@ static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11Rende switch (rtvDesc.ViewDimension) { - case D3D11_RTV_DIMENSION_TEXTURE1D: - mipSlice = rtvDesc.Texture1D.MipSlice; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: - mipSlice = rtvDesc.Texture1DArray.MipSlice; - arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2D: - mipSlice = rtvDesc.Texture2D.MipSlice; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: - mipSlice = rtvDesc.Texture2DArray.MipSlice; - arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2DMS: - mipSlice = 0; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: - mipSlice = 0; - arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_TEXTURE3D: - mipSlice = rtvDesc.Texture3D.MipSlice; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_UNKNOWN: - case D3D11_RTV_DIMENSION_BUFFER: - UNIMPLEMENTED(); - break; - - default: - UNREACHABLE(); - break; + case D3D11_RTV_DIMENSION_TEXTURE1D: + mipSlice = rtvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + mipSlice = rtvDesc.Texture1DArray.MipSlice; + arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2D: + mipSlice = rtvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + mipSlice = rtvDesc.Texture2DArray.MipSlice; + arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE3D: + mipSlice = rtvDesc.Texture3D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_UNKNOWN: + case D3D11_RTV_DIMENSION_BUFFER: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; } unsigned int mipLevels, samples; - getTextureProperties(resource, &mipLevels, &samples); + GetTextureProperties(resource, &mipLevels, &samples); return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); } -static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) +unsigned int GetDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) { D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; view->GetDesc(&dsvDesc); @@ -133,157 +135,170 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth switch (dsvDesc.ViewDimension) { - case D3D11_DSV_DIMENSION_TEXTURE1D: - mipSlice = dsvDesc.Texture1D.MipSlice; - arraySlice = 0; - break; - - case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: - mipSlice = dsvDesc.Texture1DArray.MipSlice; - arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2D: - mipSlice = dsvDesc.Texture2D.MipSlice; - arraySlice = 0; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: - mipSlice = dsvDesc.Texture2DArray.MipSlice; - arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2DMS: - mipSlice = 0; - arraySlice = 0; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: - mipSlice = 0; - arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; - break; - - case D3D11_DSV_DIMENSION_UNKNOWN: - UNIMPLEMENTED(); - break; - - default: - UNREACHABLE(); - break; + case D3D11_DSV_DIMENSION_TEXTURE1D: + mipSlice = dsvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: + mipSlice = dsvDesc.Texture1DArray.MipSlice; + arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2D: + mipSlice = dsvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + mipSlice = dsvDesc.Texture2DArray.MipSlice; + arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_UNKNOWN: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; } unsigned int mipLevels, samples; - getTextureProperties(resource, &mipLevels, &samples); + GetTextureProperties(resource, &mipLevels, &samples); return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); } -TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) - : mWidth(width), +GLenum GetSurfaceRTFormat(bool depth, SwapChain11 *swapChain) +{ + return (depth ? swapChain->getDepthBufferInternalFormat() + : swapChain->getRenderTargetInternalFormat()); +} + +const d3d11::Format &GetSurfaceFormatSet(bool depth, SwapChain11 *swapChain, Renderer11 *renderer) +{ + return d3d11::Format::Get(GetSurfaceRTFormat(depth, swapChain), + renderer->getRenderer11DeviceCaps()); +} + +} // anonymous namespace + +RenderTarget11::RenderTarget11(const d3d11::Format &formatSet) : mFormatSet(formatSet) +{ +} + +RenderTarget11::~RenderTarget11() +{ + ASSERT(mBroadcastChannel.empty()); +} + +void RenderTarget11::signalDirty(const gl::Context *context) +{ + mBroadcastChannel.signal(context); + + // Clear the list. We can't do this in the receiver because it would mutate during iteration. + mBroadcastChannel.reset(); +} + +TextureRenderTarget11::TextureRenderTarget11(d3d11::RenderTargetView &&rtv, + const TextureHelper11 &resource, + const d3d11::SharedSRV &srv, + const d3d11::SharedSRV &blitSRV, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples) + : RenderTarget11(formatSet), + mWidth(width), mHeight(height), mDepth(depth), mInternalFormat(internalFormat), - mDXGIFormat(DXGI_FORMAT_UNKNOWN), mSamples(samples), mSubresourceIndex(0), mTexture(resource), - mRenderTarget(rtv), - mDepthStencil(NULL), - mShaderResource(srv) + mRenderTarget(std::move(rtv)), + mDepthStencil(), + mShaderResource(srv.makeCopy()), + mBlitShaderResource(blitSRV.makeCopy()) { - if (mTexture) - { - mTexture->AddRef(); - } - - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - if (mShaderResource) - { - mShaderResource->AddRef(); - } - - if (mRenderTarget && mTexture) + if (mRenderTarget.valid() && mTexture.valid()) { - mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); - - D3D11_RENDER_TARGET_VIEW_DESC desc; - mRenderTarget->GetDesc(&desc); - mDXGIFormat = desc.Format; + mSubresourceIndex = GetRTVSubresourceIndex(mTexture.get(), mRenderTarget.get()); } + ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0); } -TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples) - : mWidth(width), +TextureRenderTarget11::TextureRenderTarget11(d3d11::DepthStencilView &&dsv, + const TextureHelper11 &resource, + const d3d11::SharedSRV &srv, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples) + : RenderTarget11(formatSet), + mWidth(width), mHeight(height), mDepth(depth), mInternalFormat(internalFormat), - mDXGIFormat(DXGI_FORMAT_UNKNOWN), mSamples(samples), mSubresourceIndex(0), mTexture(resource), - mRenderTarget(NULL), - mDepthStencil(dsv), - mShaderResource(srv) + mRenderTarget(), + mDepthStencil(std::move(dsv)), + mShaderResource(srv.makeCopy()), + mBlitShaderResource() { - if (mTexture) + if (mDepthStencil.valid() && mTexture.valid()) { - mTexture->AddRef(); - } - - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - if (mShaderResource) - { - mShaderResource->AddRef(); - } - - if (mDepthStencil && mTexture) - { - mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); - - D3D11_DEPTH_STENCIL_VIEW_DESC desc; - mDepthStencil->GetDesc(&desc); - mDXGIFormat = desc.Format; + mSubresourceIndex = GetDSVSubresourceIndex(mTexture.get(), mDepthStencil.get()); } + ASSERT(mFormatSet.formatID != angle::Format::ID::NONE || mWidth == 0 || mHeight == 0); } TextureRenderTarget11::~TextureRenderTarget11() { - SafeRelease(mTexture); - SafeRelease(mRenderTarget); - SafeRelease(mDepthStencil); - SafeRelease(mShaderResource); } -ID3D11Resource *TextureRenderTarget11::getTexture() const +const TextureHelper11 &TextureRenderTarget11::getTexture() const { return mTexture; } -ID3D11RenderTargetView *TextureRenderTarget11::getRenderTargetView() const +const d3d11::RenderTargetView &TextureRenderTarget11::getRenderTargetView() const { return mRenderTarget; } -ID3D11DepthStencilView *TextureRenderTarget11::getDepthStencilView() const +const d3d11::DepthStencilView &TextureRenderTarget11::getDepthStencilView() const { return mDepthStencil; } -ID3D11ShaderResourceView *TextureRenderTarget11::getShaderResourceView() const +const d3d11::SharedSRV &TextureRenderTarget11::getShaderResourceView() const { return mShaderResource; } +const d3d11::SharedSRV &TextureRenderTarget11::getBlitShaderResourceView() const +{ + return mBlitShaderResource; +} + GLsizei TextureRenderTarget11::getWidth() const { return mWidth; @@ -314,14 +329,11 @@ unsigned int TextureRenderTarget11::getSubresourceIndex() const return mSubresourceIndex; } -DXGI_FORMAT TextureRenderTarget11::getDXGIFormat() const -{ - return mDXGIFormat; -} - -SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth) - : mSwapChain(swapChain), - mRenderer(renderer), +SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, + Renderer11 *renderer, + bool depth) + : RenderTarget11(GetSurfaceFormatSet(depth, swapChain, renderer)), + mSwapChain(swapChain), mDepth(depth) { ASSERT(mSwapChain); @@ -348,43 +360,46 @@ GLsizei SurfaceRenderTarget11::getDepth() const GLenum SurfaceRenderTarget11::getInternalFormat() const { - return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetRenderTargetInternalFormat()); + return GetSurfaceRTFormat(mDepth, mSwapChain); } GLsizei SurfaceRenderTarget11::getSamples() const { - // Our EGL surfaces do not support multisampling. - return 0; + return mSwapChain->getSamples(); } -ID3D11Resource *SurfaceRenderTarget11::getTexture() const +const TextureHelper11 &SurfaceRenderTarget11::getTexture() const { return (mDepth ? mSwapChain->getDepthStencilTexture() : mSwapChain->getOffscreenTexture()); } -ID3D11RenderTargetView *SurfaceRenderTarget11::getRenderTargetView() const +const d3d11::RenderTargetView &SurfaceRenderTarget11::getRenderTargetView() const { - return (mDepth ? NULL : mSwapChain->getRenderTarget()); + ASSERT(!mDepth); + return mSwapChain->getRenderTarget(); } -ID3D11DepthStencilView *SurfaceRenderTarget11::getDepthStencilView() const +const d3d11::DepthStencilView &SurfaceRenderTarget11::getDepthStencilView() const { - return (mDepth ? mSwapChain->getDepthStencil() : NULL); + ASSERT(mDepth); + return mSwapChain->getDepthStencil(); } -ID3D11ShaderResourceView *SurfaceRenderTarget11::getShaderResourceView() const +const d3d11::SharedSRV &SurfaceRenderTarget11::getShaderResourceView() const { - return (mDepth ? mSwapChain->getDepthStencilShaderResource() : mSwapChain->getRenderTargetShaderResource()); + return (mDepth ? mSwapChain->getDepthStencilShaderResource() + : mSwapChain->getRenderTargetShaderResource()); } -unsigned int SurfaceRenderTarget11::getSubresourceIndex() const +const d3d11::SharedSRV &SurfaceRenderTarget11::getBlitShaderResourceView() const { - return 0; + // The SurfaceRenderTargetView format should always be such that the normal SRV works for blits. + return getShaderResourceView(); } -DXGI_FORMAT SurfaceRenderTarget11::getDXGIFormat() const +unsigned int SurfaceRenderTarget11::getSubresourceIndex() const { - return d3d11::GetTextureFormatInfo(getInternalFormat(), mRenderer->getRenderer11DeviceCaps()).texFormat; + return 0; } -} +} // namespace rx 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 d47b237c09..db49cac9f5 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h @@ -11,6 +11,9 @@ #define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ #include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" namespace rx { @@ -20,28 +23,51 @@ class Renderer11; class RenderTarget11 : public RenderTargetD3D { public: - RenderTarget11() { } - virtual ~RenderTarget11() { } + RenderTarget11(const d3d11::Format &formatSet); + ~RenderTarget11() override; - virtual ID3D11Resource *getTexture() const = 0; - virtual ID3D11RenderTargetView *getRenderTargetView() const = 0; - virtual ID3D11DepthStencilView *getDepthStencilView() const = 0; - virtual ID3D11ShaderResourceView *getShaderResourceView() const = 0; + virtual const TextureHelper11 &getTexture() const = 0; + virtual const d3d11::RenderTargetView &getRenderTargetView() const = 0; + virtual const d3d11::DepthStencilView &getDepthStencilView() const = 0; + virtual const d3d11::SharedSRV &getShaderResourceView() const = 0; + virtual const d3d11::SharedSRV &getBlitShaderResourceView() const = 0; virtual unsigned int getSubresourceIndex() const = 0; - virtual DXGI_FORMAT getDXGIFormat() const = 0; + void signalDirty(const gl::Context *context) override; + OnRenderTargetDirtyChannel *getBroadcastChannel() { return &mBroadcastChannel; } + + const d3d11::Format &getFormatSet() const { return mFormatSet; } + + protected: + OnRenderTargetDirtyChannel mBroadcastChannel; + const d3d11::Format &mFormatSet; }; class TextureRenderTarget11 : public RenderTarget11 { public: // TextureRenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them - TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); - TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, - GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples); - virtual ~TextureRenderTarget11(); + TextureRenderTarget11(d3d11::RenderTargetView &&rtv, + const TextureHelper11 &resource, + const d3d11::SharedSRV &srv, + const d3d11::SharedSRV &blitSRV, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples); + TextureRenderTarget11(d3d11::DepthStencilView &&dsv, + const TextureHelper11 &resource, + const d3d11::SharedSRV &srv, + GLenum internalFormat, + const d3d11::Format &formatSet, + GLsizei width, + GLsizei height, + GLsizei depth, + GLsizei samples); + ~TextureRenderTarget11() override; GLsizei getWidth() const override; GLsizei getHeight() const override; @@ -49,35 +75,37 @@ class TextureRenderTarget11 : public RenderTarget11 GLenum getInternalFormat() const override; GLsizei getSamples() const override; - ID3D11Resource *getTexture() const override; - ID3D11RenderTargetView *getRenderTargetView() const override; - ID3D11DepthStencilView *getDepthStencilView() const override; - ID3D11ShaderResourceView *getShaderResourceView() const override; + const TextureHelper11 &getTexture() const override; + const d3d11::RenderTargetView &getRenderTargetView() const override; + const d3d11::DepthStencilView &getDepthStencilView() const override; + const d3d11::SharedSRV &getShaderResourceView() const override; + const d3d11::SharedSRV &getBlitShaderResourceView() const override; unsigned int getSubresourceIndex() const override; - DXGI_FORMAT getDXGIFormat() const override; - private: GLsizei mWidth; GLsizei mHeight; GLsizei mDepth; GLenum mInternalFormat; - DXGI_FORMAT mDXGIFormat; GLsizei mSamples; unsigned int mSubresourceIndex; - ID3D11Resource *mTexture; - ID3D11RenderTargetView *mRenderTarget; - ID3D11DepthStencilView *mDepthStencil; - ID3D11ShaderResourceView *mShaderResource; + TextureHelper11 mTexture; + d3d11::RenderTargetView mRenderTarget; + d3d11::DepthStencilView mDepthStencil; + d3d11::SharedSRV mShaderResource; + + // Shader resource view to use with internal blit shaders. Not set for depth/stencil render + // targets. + d3d11::SharedSRV mBlitShaderResource; }; class SurfaceRenderTarget11 : public RenderTarget11 { public: SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth); - virtual ~SurfaceRenderTarget11(); + ~SurfaceRenderTarget11() override; GLsizei getWidth() const override; GLsizei getHeight() const override; @@ -85,21 +113,19 @@ class SurfaceRenderTarget11 : public RenderTarget11 GLenum getInternalFormat() const override; GLsizei getSamples() const override; - ID3D11Resource *getTexture() const override; - ID3D11RenderTargetView *getRenderTargetView() const override; - ID3D11DepthStencilView *getDepthStencilView() const override; - ID3D11ShaderResourceView *getShaderResourceView() const override; + const TextureHelper11 &getTexture() const override; + const d3d11::RenderTargetView &getRenderTargetView() const override; + const d3d11::DepthStencilView &getDepthStencilView() const override; + const d3d11::SharedSRV &getShaderResourceView() const override; + const d3d11::SharedSRV &getBlitShaderResourceView() const override; unsigned int getSubresourceIndex() const override; - DXGI_FORMAT getDXGIFormat() const override; - private: SwapChain11 *mSwapChain; - Renderer11 *mRenderer; bool mDepth; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_ 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 5118bdbe9c..b0ef9abddc 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -9,56 +9,64 @@ #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" #include +#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/Context.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/histogram_macros.h" #include "libANGLE/renderer/d3d/CompilerD3D.h" +#include "libANGLE/renderer/d3d/DeviceD3D.h" +#include "libANGLE/renderer/d3d/DisplayD3D.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/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/Context11.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/StreamProducerNV12.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/TransformFeedback11.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/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 "libANGLE/renderer/d3d/d3d11/dxgi_support_table.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "libANGLE/renderer/renderer_utils.h" #include "third_party/trace_event/trace_event.h" +#ifdef ANGLE_ENABLE_WINDOWS_STORE +#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h" +#else +#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h" +#endif + // 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. @@ -72,12 +80,6 @@ #define ANGLE_SKIP_DXGI_1_2_CHECK 0 #endif -#ifdef _DEBUG -// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples -// and conformance tests. to enable all warnings, remove this define. -#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 -#endif - namespace rx { @@ -89,25 +91,6 @@ enum MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 }; -#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 - enum ANGLEFeatureLevel { ANGLE_FEATURE_LEVEL_INVALID, @@ -123,14 +106,18 @@ ANGLEFeatureLevel GetANGLEFeatureLevel(D3D_FEATURE_LEVEL d3dFeatureLevel) { switch (d3dFeatureLevel) { - 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; + 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; + case D3D_FEATURE_LEVEL_11_1: + return ANGLE_FEATURE_LEVEL_11_1; + default: + return ANGLE_FEATURE_LEVEL_INVALID; } } @@ -144,7 +131,7 @@ void SetLineLoopIndices(GLuint *dest, size_t count) } template -void CopyLineLoopIndices(const GLvoid *indices, GLuint *dest, size_t count) +void CopyLineLoopIndices(const void *indices, GLuint *dest, size_t count) { const T *srcPtr = static_cast(indices); for (size_t i = 0; i < count; ++i) @@ -165,7 +152,7 @@ void SetTriangleFanIndices(GLuint *destPtr, size_t numTris) } template -void CopyLineLoopIndicesWithRestart(const GLvoid *indices, +void CopyLineLoopIndicesWithRestart(const void *indices, size_t count, GLenum indexType, std::vector *bufferOut) @@ -206,7 +193,7 @@ void CopyLineLoopIndicesWithRestart(const GLvoid *indices, } } -void GetLineLoopIndices(const GLvoid *indices, +void GetLineLoopIndices(const void *indices, GLenum indexType, GLuint count, bool usePrimitiveRestartFixedIndex, @@ -257,7 +244,7 @@ void GetLineLoopIndices(const GLvoid *indices, } template -void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTris) +void CopyTriangleFanIndices(const void *indices, GLuint *destPtr, size_t numTris) { const T *srcPtr = static_cast(indices); @@ -270,7 +257,7 @@ void CopyTriangleFanIndices(const GLvoid *indices, GLuint *destPtr, size_t numTr } template -void CopyTriangleFanIndicesWithRestart(const GLvoid *indices, +void CopyTriangleFanIndicesWithRestart(const void *indices, GLuint indexCount, GLenum indexType, std::vector *bufferOut) @@ -314,7 +301,7 @@ void CopyTriangleFanIndicesWithRestart(const GLvoid *indices, } } -void GetTriFanIndices(const GLvoid *indices, +void GetTriFanIndices(const void *indices, GLenum indexType, GLuint count, bool usePrimitiveRestartFixedIndex, @@ -365,60 +352,135 @@ void GetTriFanIndices(const GLvoid *indices, } } +bool DrawCallNeedsTranslation(const gl::Context *context, GLenum mode) +{ + const auto &glState = context->getGLState(); + const gl::VertexArray *vertexArray = glState.getVertexArray(); + VertexArray11 *vertexArray11 = GetImplAs(vertexArray); + // Direct drawing doesn't support dynamic attribute storage since it needs the first and count + // to translate when applyVertexBuffer. GL_LINE_LOOP and GL_TRIANGLE_FAN are not supported + // either since we need to simulate them in D3D. + if (vertexArray11->hasActiveDynamicAttrib(context) || mode == GL_LINE_LOOP || + mode == GL_TRIANGLE_FAN) + { + return true; + } + + ProgramD3D *programD3D = GetImplAs(glState.getProgram()); + if (InstancedPointSpritesActive(programD3D, mode)) + { + return true; + } + + return false; +} + +bool IsArrayRTV(ID3D11RenderTargetView *rtv) +{ + D3D11_RENDER_TARGET_VIEW_DESC desc; + rtv->GetDesc(&desc); + if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE1DARRAY && + desc.Texture1DArray.ArraySize > 1) + return true; + if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DARRAY && + desc.Texture2DArray.ArraySize > 1) + return true; + if (desc.ViewDimension == D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY && + desc.Texture2DMSArray.ArraySize > 1) + return true; + return false; +} + +int GetAdjustedInstanceCount(const gl::Program *program, int instanceCount) +{ + if (!program->usesMultiview()) + { + return instanceCount; + } + if (instanceCount == 0) + { + return program->getNumViews(); + } + return program->getNumViews() * instanceCount; +} + +const uint32_t ScratchMemoryBufferLifetime = 1000; + +void PopulateFormatDeviceCaps(ID3D11Device *device, + DXGI_FORMAT format, + UINT *outSupport, + UINT *outMaxSamples) +{ + if (FAILED(device->CheckFormatSupport(format, outSupport))) + { + *outSupport = 0; + } + + *outMaxSamples = 0; + for (UINT sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; sampleCount *= 2) + { + UINT qualityCount = 0; + if (FAILED(device->CheckMultisampleQualityLevels(format, sampleCount, &qualityCount)) || + qualityCount == 0) + { + break; + } + + *outMaxSamples = sampleCount; + } +} + +bool CullsEverything(const gl::State &glState) +{ + return (glState.getRasterizerState().cullFace && + glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack); +} + } // anonymous namespace +Renderer11DeviceCaps::Renderer11DeviceCaps() = default; + Renderer11::Renderer11(egl::Display *display) : RendererD3D(display), - mStateCache(this), + mCreateDebugDevice(false), + mStateCache(), mStateManager(this), - mLastHistogramUpdateTime(ANGLEPlatformCurrent()->monotonicallyIncreasingTime()) -#if !defined(ANGLE_MINGW32_COMPAT) - ,mDebug(nullptr) -#endif + mLastHistogramUpdateTime( + ANGLEPlatformCurrent()->monotonicallyIncreasingTime(ANGLEPlatformCurrent())), + mDebug(nullptr), + mScratchMemoryBuffer(ScratchMemoryBufferLifetime), + mAnnotator(nullptr) { - mVertexDataManager = NULL; - mIndexDataManager = NULL; - - mLineLoopIB = NULL; - mTriangleFanIB = NULL; - mAppliedIBChanged = false; + mLineLoopIB = nullptr; + mTriangleFanIB = nullptr; - mBlit = NULL; - mPixelTransfer = NULL; + mBlit = nullptr; + mPixelTransfer = nullptr; - mClear = NULL; + mClear = nullptr; - mTrim = NULL; + mTrim = nullptr; - mSyncQuery = NULL; - - mRenderer11DeviceCaps.supportsClearView = 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; + mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = false; + mRenderer11DeviceCaps.supportsDXGI1_2 = false; + mRenderer11DeviceCaps.B5G6R5support = 0; + mRenderer11DeviceCaps.B4G4R4A4support = 0; + mRenderer11DeviceCaps.B5G5R5A1support = 0; + + mD3d11Module = nullptr; + mDxgiModule = nullptr; + mDCompModule = nullptr; mCreatedWithDeviceEXT = false; mEGLDevice = nullptr; - mDevice = NULL; - mDeviceContext = NULL; - mDeviceContext1 = NULL; - mDxgiAdapter = NULL; - mDxgiFactory = NULL; - - mDriverConstantBufferVS = NULL; - mDriverConstantBufferPS = NULL; - - mAppliedVertexShader = NULL; - mAppliedGeometryShader = NULL; - mAppliedPixelShader = NULL; - - mAppliedNumXFBBindings = static_cast(-1); + mDevice = nullptr; + mDeviceContext = nullptr; + mDeviceContext1 = nullptr; + mDeviceContext3 = nullptr; + mDxgiAdapter = nullptr; + mDxgiFactory = nullptr; ZeroMemory(&mAdapterDescription, sizeof(mAdapterDescription)); @@ -426,13 +488,21 @@ Renderer11::Renderer11(egl::Display *display) { 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); + EGLint requestedMajorVersion = static_cast( + attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE)); + EGLint requestedMinorVersion = static_cast( + attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE)); if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 11) { + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + // This could potentially lead to failed context creation if done on a system + // without the platform update which installs DXGI 1.2. Currently, for Chrome users + // D3D11 contexts are only created if the platform update is available, so this + // should not cause any issues. + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_1); + } if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 0) { mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_11_0); @@ -451,11 +521,7 @@ Renderer11::Renderer11(egl::Display *display) } } -#if defined(ANGLE_ENABLE_WINDOWS_STORE) - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) -#else if (requestedMajorVersion == 9 && requestedMinorVersion == 3) -#endif { if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) { @@ -473,8 +539,8 @@ Renderer11::Renderer11(egl::Display *display) #endif } - EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, - EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE); + EGLint requestedDeviceType = static_cast(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: @@ -497,9 +563,11 @@ Renderer11::Renderer11(egl::Display *display) UNREACHABLE(); } - const EGLenum presentPath = attributes.get(EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, - EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE); + const EGLenum presentPath = static_cast(attributes.get( + EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE, EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE)); mPresentPathFastEnabled = (presentPath == EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE); + + mCreateDebugDevice = ShouldUseDebugLayers(attributes); } else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT) { @@ -509,11 +577,22 @@ Renderer11::Renderer11(egl::Display *display) // Also set EGL_PLATFORM_ANGLE_ANGLE variables, in case they're used elsewhere in ANGLE // mAvailableFeatureLevels defaults to empty - mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN; + mRequestedDriverType = D3D_DRIVER_TYPE_UNKNOWN; mPresentPathFastEnabled = false; } - initializeDebugAnnotator(); +// 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(mAnnotator); + gl::InitializeDebugAnnotations(mAnnotator); } Renderer11::~Renderer11() @@ -529,20 +608,17 @@ egl::Error Renderer11::initialize() { HRESULT result = S_OK; - egl::Error error = initializeD3DDevice(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(initializeD3DDevice()); #if !defined(ANGLE_ENABLE_WINDOWS_STORE) #if !ANGLE_SKIP_DXGI_1_2_CHECK { 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. + // 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()); + HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId()); if (hwnd) { DWORD currentProcessId = GetCurrentProcessId(); @@ -557,13 +633,12 @@ egl::Error Renderer11::initialize() if (requireDXGI1_2) { - IDXGIDevice2 *dxgiDevice2 = NULL; - result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); + IDXGIDevice2 *dxgiDevice2 = nullptr; + 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."); + return egl::EglNotInitialized(D3D11_INIT_INCOMPATIBLE_DXGI) + << "DXGI 1.2 required to present to HWNDs owned by another process."; } SafeRelease(dxgiDevice2); } @@ -573,90 +648,83 @@ egl::Error Renderer11::initialize() { TRACE_EVENT0("gpu.angle", "Renderer11::initialize (ComQueries)"); - // Cast the DeviceContext to a DeviceContext1. + // Cast the DeviceContext to a DeviceContext1 and DeviceContext3. // 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) + // Don't error in this case- just don't use mDeviceContext1 or mDeviceContext3. mDeviceContext1 = d3d11::DynamicCastComObject(mDeviceContext); -#endif + mDeviceContext3 = d3d11::DynamicCastComObject(mDeviceContext); - IDXGIDevice *dxgiDevice = NULL; - result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice); + IDXGIDevice *dxgiDevice = nullptr; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice); if (FAILED(result)) { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_OTHER_ERROR, - "Could not query DXGI device."); + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) << "Could not query DXGI device."; } - result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&mDxgiAdapter); if (FAILED(result)) { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_OTHER_ERROR, - "Could not retrieve DXGI adapter"); + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) + << "Could not retrieve DXGI adapter"; } SafeRelease(dxgiDevice); -#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) + // 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 != nullptr) { DXGI_ADAPTER_DESC2 adapterDesc2 = {}; - result = dxgiAdapter2->GetDesc2(&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; + // 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; + mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory; + mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid; } } else -#endif { result = mDxgiAdapter->GetDesc(&mAdapterDescription); } -#if defined(ANGLE_ENABLE_D3D11_1) SafeRelease(dxgiAdapter2); -#endif if (FAILED(result)) { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_OTHER_ERROR, - "Could not read DXGI adaptor description."); + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) + << "Could not read DXGI adaptor description."; } memset(mDescription, 0, sizeof(mDescription)); wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); - result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); + result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void **)&mDxgiFactory); if (!mDxgiFactory || FAILED(result)) { - return egl::Error(EGL_NOT_INITIALIZED, - D3D11_INIT_OTHER_ERROR, - "Could not create DXGI factory."); + return egl::EglNotInitialized(D3D11_INIT_OTHER_ERROR) + << "Could not create DXGI factory."; } } -#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) + if (mCreateDebugDevice) { TRACE_EVENT0("gpu.angle", "Renderer11::initialize (HideWarnings)"); ID3D11InfoQueue *infoQueue; @@ -664,29 +732,33 @@ egl::Error Renderer11::initialize() if (SUCCEEDED(result)) { - D3D11_MESSAGE_ID hideMessages[] = - { - D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET - }; + D3D11_MESSAGE_ID hideMessages[] = { + D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET}; D3D11_INFO_QUEUE_FILTER filter = {}; filter.DenyList.NumIDs = static_cast(ArraySize(hideMessages)); - filter.DenyList.pIDList = hideMessages; + filter.DenyList.pIDList = hideMessages; infoQueue->AddStorageFilterEntries(&filter); SafeRelease(infoQueue); } } -#endif #if !defined(NDEBUG) mDebug = d3d11::DynamicCastComObject(mDevice); #endif -#endif // !ANGLE_MINGW32_COMPAT - initializeDevice(); + ANGLE_TRY(initializeDevice()); + + return egl::NoError(); +} - return egl::Error(EGL_SUCCESS); +HRESULT Renderer11::callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug) +{ + return createDevice( + nullptr, mRequestedDriverType, nullptr, debug ? D3D11_CREATE_DEVICE_DEBUG : 0, + mAvailableFeatureLevels.data(), static_cast(mAvailableFeatureLevels.size()), + D3D11_SDK_VERSION, &mDevice, &(mRenderer11DeviceCaps.featureLevel), &mDeviceContext); } egl::Error Renderer11::initializeD3DDevice() @@ -706,8 +778,8 @@ egl::Error Renderer11::initializeD3DDevice() if (mD3d11Module == nullptr || mDxgiModule == nullptr) { - return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, - "Could not load D3D11 or DXGI library."); + return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) + << "Could not load D3D11 or DXGI library."; } // create the D3D11 device @@ -717,68 +789,76 @@ egl::Error Renderer11::initializeD3DDevice() if (D3D11CreateDevice == nullptr) { - return egl::Error(EGL_NOT_INITIALIZED, D3D11_INIT_MISSING_DEP, - "Could not retrieve D3D11CreateDevice address."); + return egl::EglNotInitialized(D3D11_INIT_MISSING_DEP) + << "Could not retrieve D3D11CreateDevice address."; } } #endif -#ifdef _DEBUG + if (mCreateDebugDevice) { 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); - } + result = callD3D11CreateDevice(D3D11CreateDevice, true); - if (!mDevice || FAILED(result)) - { - ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u && + mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1) + { + // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG. + // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature + // levels to fall back on. + mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin()); + result = callD3D11CreateDevice(D3D11CreateDevice, true); + } + + if (!mDevice || FAILED(result)) + { + WARN() << "Failed creating Debug D3D11 device - falling back to release runtime."; + } } 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); + result = callD3D11CreateDevice(D3D11CreateDevice, false); + + if (result == E_INVALIDARG && mAvailableFeatureLevels.size() > 1u && + mAvailableFeatureLevels[0] == D3D_FEATURE_LEVEL_11_1) + { + // On older Windows platforms, D3D11.1 is not supported which returns E_INVALIDARG. + // Try again without passing D3D_FEATURE_LEVEL_11_1 in case we have other feature + // levels to fall back on. + mAvailableFeatureLevels.erase(mAvailableFeatureLevels.begin()); + result = callD3D11CreateDevice(D3D11CreateDevice, false); + } // 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."); + return egl::EglNotInitialized(D3D11_INIT_CREATEDEVICE_ERROR) + << "Could not create D3D11 device."; } } } else { // We should use the inputted D3D11 device instead - void *device = nullptr; - egl::Error error = mEGLDevice->getDevice(&device); - if (error.isError()) - { - return error; - } + void *device = nullptr; + ANGLE_TRY(mEGLDevice->getDevice(&device)); ID3D11Device *d3dDevice = reinterpret_cast(device); if (FAILED(d3dDevice->GetDeviceRemovedReason())) { - return egl::Error(EGL_NOT_INITIALIZED, "Inputted D3D11 device has been lost."); + return egl::EglNotInitialized() << "Inputted D3D11 device has been lost."; } 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."); + return egl::EglNotInitialized() + << "Inputted D3D11 device must be Feature Level 9_3 or greater."; } // The Renderer11 adds a ref to the inputted D3D11 device, like D3D11CreateDevice does. @@ -788,27 +868,24 @@ egl::Error Renderer11::initializeD3DDevice() mRenderer11DeviceCaps.featureLevel = mDevice->GetFeatureLevel(); } + mResourceManager11.setAllocationsInitialized(mCreateDebugDevice); + d3d11::SetDebugName(mDeviceContext, "DeviceContext"); - return egl::Error(EGL_SUCCESS); + return egl::NoError(); } // do any one-time device initialization // NOTE: this is also needed after a device lost/reset // to reset the scene status and ensure the default states are reset. -void Renderer11::initializeDevice() +egl::Error Renderer11::initializeDevice() { SCOPED_ANGLE_HISTOGRAM_TIMER("GPU.ANGLE.Renderer11InitializeDeviceMS"); TRACE_EVENT0("gpu.angle", "Renderer11::initializeDevice"); populateRenderer11DeviceCaps(); - mStateCache.initialize(mDevice); - mInputLayoutCache.initialize(mDevice, mDeviceContext); - - ASSERT(!mVertexDataManager && !mIndexDataManager); - mVertexDataManager = new VertexDataManager(this); - mIndexDataManager = new IndexDataManager(this, getRendererClass()); + mStateCache.clear(); ASSERT(!mBlit); mBlit = new Blit11(this); @@ -820,7 +897,8 @@ void Renderer11::initializeDevice() // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application // automatically when an application is suspended by the OS. This feature is currently // only supported for Windows Store applications. - EGLint enableAutoTrim = attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE); + EGLint enableAutoTrim = static_cast( + attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE)); if (enableAutoTrim == EGL_TRUE) { @@ -831,19 +909,12 @@ void Renderer11::initializeDevice() ASSERT(!mPixelTransfer); mPixelTransfer = new PixelTransfer11(this); - const gl::Caps &rendererCaps = getRendererCaps(); - - mStateManager.initialize(rendererCaps); - - mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); - mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits); - - mForceSetPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); - mCurPixelSamplerStates.resize(rendererCaps.maxTextureImageUnits); + const gl::Caps &rendererCaps = getNativeCaps(); - mStateManager.initialize(rendererCaps); - - markAllStateDirty(); + if (mStateManager.initialize(rendererCaps, getNativeExtensions()).isError()) + { + return egl::EglBadAlloc() << "Error initializing state manager."; + } // Gather stats on DXGI and D3D feature level ANGLE_HISTOGRAM_BOOLEAN("GPU.ANGLE.SupportsDXGI1_2", mRenderer11DeviceCaps.supportsDXGI1_2); @@ -859,57 +930,117 @@ void Renderer11::initializeDevice() angleFeatureLevel = ANGLE_FEATURE_LEVEL_11_1; } - ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3D11FeatureLevel", - angleFeatureLevel, + 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); + return egl::NoError(); } void Renderer11::populateRenderer11DeviceCaps() { HRESULT hr = S_OK; -#if defined(ANGLE_ENABLE_D3D11_1) + LARGE_INTEGER version; + hr = mDxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version); + if (FAILED(hr)) + { + mRenderer11DeviceCaps.driverVersion.reset(); + ERR() << "Error querying driver version from DXGI Adapter."; + } + else + { + mRenderer11DeviceCaps.driverVersion = version; + } + if (mDeviceContext1) { D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options; - HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)); + 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); + mRenderer11DeviceCaps.supportsConstantBufferOffsets = + (d3d11Options.ConstantBufferOffsetting != FALSE); } } -#endif - hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G6R5_UNORM, &(mRenderer11DeviceCaps.B5G6R5support)); - if (FAILED(hr)) + if (mDeviceContext3) { - mRenderer11DeviceCaps.B5G6R5support = 0; + D3D11_FEATURE_DATA_D3D11_OPTIONS3 d3d11Options3; + HRESULT result = mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &d3d11Options3, + sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS3)); + if (SUCCEEDED(result)) + { + mRenderer11DeviceCaps.supportsVpRtIndexWriteFromVertexShader = + (d3d11Options3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE); + } } - hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B4G4R4A4_UNORM, &(mRenderer11DeviceCaps.B4G4R4A4support)); - if (FAILED(hr)) + mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs = + mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_10_0; + + if (getWorkarounds().disableB5G6R5Support) { - mRenderer11DeviceCaps.B4G4R4A4support = 0; + mRenderer11DeviceCaps.B5G6R5support = 0; + mRenderer11DeviceCaps.B5G6R5maxSamples = 0; } - - hr = mDevice->CheckFormatSupport(DXGI_FORMAT_B5G5R5A1_UNORM, &(mRenderer11DeviceCaps.B5G5R5A1support)); - if (FAILED(hr)) + else { - mRenderer11DeviceCaps.B5G5R5A1support = 0; + PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G6R5_UNORM, + &mRenderer11DeviceCaps.B5G6R5support, + &mRenderer11DeviceCaps.B5G6R5maxSamples); } -#if defined(ANGLE_ENABLE_D3D11_1) + PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B4G4R4A4_UNORM, + &mRenderer11DeviceCaps.B4G4R4A4support, + &mRenderer11DeviceCaps.B4G4R4A4maxSamples); + PopulateFormatDeviceCaps(mDevice, DXGI_FORMAT_B5G5R5A1_UNORM, + &mRenderer11DeviceCaps.B5G5R5A1support, + &mRenderer11DeviceCaps.B5G5R5A1maxSamples); + IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject(mDxgiAdapter); mRenderer11DeviceCaps.supportsDXGI1_2 = (dxgiAdapter2 != nullptr); SafeRelease(dxgiAdapter2); +} + +gl::SupportedSampleSet Renderer11::generateSampleSetForEGLConfig( + const gl::TextureCaps &colorBufferFormatCaps, + const gl::TextureCaps &depthStencilBufferFormatCaps) const +{ + gl::SupportedSampleSet sampleCounts; + +#if 0 // Disabling support for multisampling with Qt5 as it's causing a crash in the D3D11 shaders. + + // Generate a new set from the set intersection of sample counts between the color and depth + // format caps. + std::set_intersection(colorBufferFormatCaps.sampleCounts.begin(), + colorBufferFormatCaps.sampleCounts.end(), + depthStencilBufferFormatCaps.sampleCounts.begin(), + depthStencilBufferFormatCaps.sampleCounts.end(), + std::inserter(sampleCounts, sampleCounts.begin())); + + // Format of GL_NONE results in no supported sample counts. + // Add back the color sample counts to the supported sample set. + if (depthStencilBufferFormatCaps.sampleCounts.empty()) + { + sampleCounts = colorBufferFormatCaps.sampleCounts; + } + else if (colorBufferFormatCaps.sampleCounts.empty()) + { + // Likewise, add back the depth sample counts to the supported sample set. + sampleCounts = depthStencilBufferFormatCaps.sampleCounts; + } + #endif + + // Always support 0 samples + sampleCounts.insert(0); + + return sampleCounts; } -egl::ConfigSet Renderer11::generateConfigs() const +egl::ConfigSet Renderer11::generateConfigs() { std::vector colorBufferFormats; @@ -920,6 +1051,14 @@ egl::ConfigSet Renderer11::generateConfigs() const // 24-bit supported formats colorBufferFormats.push_back(GL_RGB8_OES); + if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) + { + // Additional high bit depth formats added in D3D 10.0 + // https://msdn.microsoft.com/en-us/library/windows/desktop/bb173064.aspx + colorBufferFormats.push_back(GL_RGBA16F); + colorBufferFormats.push_back(GL_RGB10_A2); + } + if (!mPresentPathFastEnabled) { // 16-bit supported formats @@ -930,15 +1069,13 @@ egl::ConfigSet Renderer11::generateConfigs() const colorBufferFormats.push_back(GL_RGB565); } - static const GLenum depthStencilBufferFormats[] = - { - GL_NONE, - GL_DEPTH24_STENCIL8_OES, - GL_DEPTH_COMPONENT16, + static const GLenum depthStencilBufferFormats[] = { + GL_NONE, GL_DEPTH24_STENCIL8_OES, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16, + GL_STENCIL_INDEX8, }; - const gl::Caps &rendererCaps = getRendererCaps(); - const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps(); + const gl::Caps &rendererCaps = getNativeCaps(); + const gl::TextureCapsMap &rendererTextureCaps = getNativeTextureCaps(); const EGLint optimalSurfaceOrientation = mPresentPathFastEnabled ? 0 : EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE; @@ -946,7 +1083,8 @@ egl::ConfigSet Renderer11::generateConfigs() const egl::ConfigSet configs; for (GLenum colorBufferInternalFormat : colorBufferFormats) { - const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat); + const gl::TextureCaps &colorBufferFormatCaps = + rendererTextureCaps.get(colorBufferInternalFormat); if (!colorBufferFormatCaps.renderable) { continue; @@ -963,64 +1101,87 @@ egl::ConfigSet Renderer11::generateConfigs() const } const gl::InternalFormat &colorBufferFormatInfo = - gl::GetInternalFormatInfo(colorBufferInternalFormat); + gl::GetSizedInternalFormatInfo(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) + gl::GetSizedInternalFormatInfo(depthStencilBufferInternalFormat); + const gl::Version &maxVersion = getMaxSupportedESVersion(); + + const gl::SupportedSampleSet sampleCounts = + generateSampleSetForEGLConfig(colorBufferFormatCaps, depthStencilBufferFormatCaps); + + for (GLuint sampleCount : sampleCounts) { + 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) && (sampleCount <= 1)); + config.bindToTextureRGBA = (((colorBufferFormatInfo.format == GL_RGBA) || + (colorBufferFormatInfo.format == GL_BGRA_EXT)) && + (sampleCount <= 1)); + config.colorBufferType = EGL_RGB_BUFFER; + config.configCaveat = EGL_NONE; + config.configID = static_cast(configs.size() + 1); + + // PresentPathFast may not be conformant config.conformant = 0; - } + if (!mPresentPathFastEnabled) + { + // Can only support a conformant ES2 with feature level greater than 10.0. + if (mRenderer11DeviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0) + { + config.conformant |= EGL_OPENGL_ES2_BIT; + } + + // We can only support conformant ES3 on FL 10.1+ + if (maxVersion.major >= 3) + { + config.conformant |= EGL_OPENGL_ES3_BIT_KHR; + } + } + + 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.1 + config.renderableType = EGL_OPENGL_ES2_BIT; + if (maxVersion.major >= 3) + { + config.renderableType |= EGL_OPENGL_ES3_BIT_KHR; + } - 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); + config.sampleBuffers = (sampleCount == 0) ? 0 : 1; + config.samples = sampleCount; + 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; + config.colorComponentType = gl_egl::GLComponentTypeToEGLColorComponentType( + colorBufferFormatInfo.componentType); + + configs.add(config); + } } } @@ -1037,8 +1198,9 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions outExtensions->d3dShareHandleClientBuffer = true; outExtensions->surfaceD3DTexture2DShareHandle = true; } + outExtensions->d3dTextureClientBuffer = true; - outExtensions->keyedMutex = true; + outExtensions->keyedMutex = true; outExtensions->querySurfacePointer = true; outExtensions->windowFixedSize = true; @@ -1048,624 +1210,350 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions // 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->stream = true; + outExtensions->streamConsumerGLTexture = true; + outExtensions->streamConsumerGLTextureYUV = true; + // Not all D3D11 devices support NV12 textures + if (getNV12TextureSupport()) + { + outExtensions->streamProducerD3DTextureNV12 = true; + } + outExtensions->flexibleSurfaceCompatibility = true; outExtensions->directComposition = !!mDCompModule; + + // Contexts are virtualized so textures can be shared globally + outExtensions->displayTextureShareGroup = true; + + // getSyncValues requires direct composition. + outExtensions->getSyncValues = outExtensions->directComposition; + + // D3D11 can be used without a swap chain + outExtensions->surfacelessContext = true; + + // All D3D feature levels support robust resource init + outExtensions->robustResourceInitialization = true; } gl::Error Renderer11::flush() { mDeviceContext->Flush(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Renderer11::finish() { - HRESULT result; - - if (!mSyncQuery) + if (!mSyncQuery.valid()) { D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.Query = D3D11_QUERY_EVENT; queryDesc.MiscFlags = 0; - result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result); - } + ANGLE_TRY(allocateResource(queryDesc, &mSyncQuery)); } - mDeviceContext->End(mSyncQuery); - mDeviceContext->Flush(); + mDeviceContext->End(mSyncQuery.get()); + HRESULT result = S_OK; + unsigned int attempt = 0; do { - result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + unsigned int flushFrequency = 100; + UINT flags = (attempt % flushFrequency == 0) ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH; + attempt++; + + result = mDeviceContext->GetData(mSyncQuery.get(), nullptr, 0, flags); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result); + return gl::OutOfMemory() << "Failed to get event query data, " << gl::FmtHR(result); } - // Keep polling, but allow other threads to do something useful first - ScheduleYield(); + if (result == S_FALSE) + { + // Keep polling, but allow other threads to do something useful first + ScheduleYield(); + } if (testDeviceLost()) { mDisplay->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync."); + return gl::OutOfMemory() << "Device was lost while waiting for sync."; } - } - while (result == S_FALSE); + } while (result == S_FALSE); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, - HANDLE shareHandle, - GLenum backBufferFormat, - GLenum depthBufferFormat, - EGLint orientation) +bool Renderer11::isValidNativeWindow(EGLNativeWindowType window) const +{ +#ifdef ANGLE_ENABLE_WINDOWS_STORE + return NativeWindow11WinRT::IsValidNativeWindow(window); +#else + return NativeWindow11Win32::IsValidNativeWindow(window); +#endif +} + +NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window, + const egl::Config *config, + const egl::AttributeMap &attribs) const { - return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat, - orientation); +#ifdef ANGLE_ENABLE_WINDOWS_STORE + UNUSED_VARIABLE(attribs); + return new NativeWindow11WinRT(window, config->alphaSize > 0); +#else + return new NativeWindow11Win32( + window, config->alphaSize > 0, + attribs.get(EGL_DIRECT_COMPOSITION_ANGLE, EGL_FALSE) == EGL_TRUE); +#endif } -CompilerImpl *Renderer11::createCompiler() +egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration, + IUnknown *d3dTexture, + EGLint *width, + EGLint *height, + GLenum *fboFormat) const { - if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3) + ID3D11Texture2D *texture = d3d11::DynamicCastComObject(d3dTexture); + if (texture == nullptr) { - return new CompilerD3D(SH_HLSL_4_0_FL9_3_OUTPUT); + return egl::EglBadParameter() << "client buffer is not a ID3D11Texture2D"; } - else + + ID3D11Device *textureDevice = nullptr; + texture->GetDevice(&textureDevice); + if (textureDevice != mDevice) { - return new CompilerD3D(SH_HLSL_4_1_OUTPUT); + SafeRelease(texture); + return egl::EglBadParameter() << "Texture's device does not match."; } -} + SafeRelease(textureDevice); -void *Renderer11::getD3DDevice() -{ - return reinterpret_cast(mDevice); -} + D3D11_TEXTURE2D_DESC desc = {0}; + texture->GetDesc(&desc); + SafeRelease(texture); -gl::Error Renderer11::generateSwizzle(gl::Texture *texture) -{ - if (texture) + if (width) { - TextureD3D *textureD3D = GetImplAs(texture); - ASSERT(textureD3D); - - TextureStorage *texStorage = nullptr; - gl::Error error = textureD3D->getNativeTexture(&texStorage); - if (error.isError()) + *width = static_cast(desc.Width); + } + if (height) + { + *height = static_cast(desc.Height); + } + if (static_cast(desc.SampleDesc.Count) != configuration->samples) + { + // Both the texture and EGL config sample count may not be the same when multi-sampling + // is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore, + // we must only check for a invalid match when the EGL config is non-zero or the texture is + // not one. + if (configuration->samples != 0 || desc.SampleDesc.Count != 1) { - return error; + return egl::EglBadParameter() << "Texture's sample count does not match."; } + } + // From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer. + switch (desc.Format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + break; - if (texStorage) - { - 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; - } - } + default: + return egl::EglBadParameter() + << "Unknown client buffer texture format: " << desc.Format; + } + + if (fboFormat) + { + const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format); + *fboFormat = angleFormat.fboImplementationInternalFormat; } - return gl::Error(GL_NO_ERROR); + return egl::NoError(); } -gl::Error Renderer11::setSamplerState(gl::SamplerType type, - int index, - gl::Texture *texture, - const gl::SamplerState &samplerState) +egl::Error Renderer11::validateShareHandle(const egl::Config *config, + HANDLE shareHandle, + const egl::AttributeMap &attribs) const { - // Make sure to add the level offset for our tiny compressed texture workaround - TextureD3D *textureD3D = GetImplAs(texture); + if (shareHandle == nullptr) + { + return egl::EglBadParameter() << "NULL share handle."; + } - TextureStorage *storage = nullptr; - gl::Error error = textureD3D->getNativeTexture(&storage); - if (error.isError()) + ID3D11Resource *tempResource11 = nullptr; + HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource), + (void **)&tempResource11); + if (FAILED(result)) { - return error; + return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result); } - // Storage should exist, texture should be complete - ASSERT(storage); + ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject(tempResource11); + SafeRelease(tempResource11); - if (type == gl::SAMPLER_PIXEL) + if (texture2D == nullptr) { - ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); + return egl::EglBadParameter() + << "Failed to query ID3D11Texture2D object from share handle."; + } - if (mForceSetPixelSamplerStates[index] || - memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = NULL; - error = mStateCache.getSamplerState(samplerState, &dxSamplerState); - if (error.isError()) - { - return error; - } + D3D11_TEXTURE2D_DESC desc = {0}; + texture2D->GetDesc(&desc); + SafeRelease(texture2D); - ASSERT(dxSamplerState != NULL); - mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); + EGLint width = attribs.getAsInt(EGL_WIDTH, 0); + EGLint height = attribs.getAsInt(EGL_HEIGHT, 0); + ASSERT(width != 0 && height != 0); - mCurPixelSamplerStates[index] = samplerState; - } + const d3d11::Format &backbufferFormatInfo = + d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps()); - mForceSetPixelSamplerStates[index] = false; - } - else if (type == gl::SAMPLER_VERTEX) + if (desc.Width != static_cast(width) || desc.Height != static_cast(height) || + desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1) { - ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); - - if (mForceSetVertexSamplerStates[index] || - memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = NULL; - error = mStateCache.getSamplerState(samplerState, &dxSamplerState); - if (error.isError()) - { - return error; - } - - ASSERT(dxSamplerState != NULL); - mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); - - mCurVertexSamplerStates[index] = samplerState; - } - - mForceSetVertexSamplerStates[index] = false; + return egl::EglBadParameter() << "Invalid texture parameters in share handle texture."; } - else UNREACHABLE(); - return gl::Error(GL_NO_ERROR); + return egl::NoError(); } -gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow, + HANDLE shareHandle, + IUnknown *d3dTexture, + GLenum backBufferFormat, + GLenum depthBufferFormat, + EGLint orientation, + EGLint samples) { - ID3D11ShaderResourceView *textureSRV = NULL; - - if (texture) - { - TextureD3D *textureImpl = GetImplAs(texture); - - TextureStorage *texStorage = nullptr; - gl::Error error = textureImpl->getNativeTexture(&texStorage); - if (error.isError()) - { - return error; - } - - // Texture should be complete and have a storage - ASSERT(texStorage); - - TextureStorage11 *storage11 = GetAs(texStorage); - - // Make sure to add the level offset for our tiny compressed texture workaround - gl::TextureState textureState = texture->getTextureState(); - textureState.baseLevel += storage11->getTopLevel(); - - error = storage11->getSRV(textureState, &textureSRV); - if (error.isError()) - { - return error; - } - - // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly - // missing the shader resource view - ASSERT(textureSRV != NULL); - - textureImpl->resetDirty(); - } - - ASSERT((type == gl::SAMPLER_PIXEL && static_cast(index) < getRendererCaps().maxTextureImageUnits) || - (type == gl::SAMPLER_VERTEX && static_cast(index) < getRendererCaps().maxVertexTextureImageUnits)); - - mStateManager.setShaderResource(type, index, textureSRV); - - return gl::Error(GL_NO_ERROR); + return new SwapChain11(this, GetAs(nativeWindow), shareHandle, d3dTexture, + backBufferFormat, depthBufferFormat, orientation, samples); } -gl::Error Renderer11::setUniformBuffers(const gl::Data &data, - const std::vector &vertexUniformBuffers, - const std::vector &fragmentUniformBuffers) +void *Renderer11::getD3DDevice() { - for (size_t uniformBufferIndex = 0; uniformBufferIndex < vertexUniformBuffers.size(); uniformBufferIndex++) - { - GLint binding = vertexUniformBuffers[uniformBufferIndex]; - - if (binding == -1) - { - continue; - } - - const OffsetBindingPointer &uniformBuffer = - data.state->getIndexedUniformBuffer(binding); - GLintptr uniformBufferOffset = uniformBuffer.getOffset(); - GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); - - if (uniformBuffer.get() != nullptr) - { - Buffer11 *bufferStorage = GetImplAs(uniformBuffer.get()); - ID3D11Buffer *constantBuffer; - - if (mRenderer11DeviceCaps.supportsConstantBufferOffsets) - { - constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); - } - else - { - constantBuffer = bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize); - } - - if (!constantBuffer) - { - return gl::Error(GL_OUT_OF_MEMORY); - } + return reinterpret_cast(mDevice); +} - if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() || - mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset || - mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize) - { -#if defined(ANGLE_ENABLE_D3D11_1) - if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0) - { - UINT firstConstant = 0, numConstants = 0; - CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); - mDeviceContext1->VSSetConstantBuffers1( - getReservedVertexUniformBuffers() + - static_cast(uniformBufferIndex), - 1, &constantBuffer, &firstConstant, &numConstants); - } - else -#endif - { - mDeviceContext->VSSetConstantBuffers( - getReservedVertexUniformBuffers() + - static_cast(uniformBufferIndex), - 1, &constantBuffer); - } +bool Renderer11::applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count) +{ + D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; - mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); - mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset; - mCurrentConstantBufferVSSize[uniformBufferIndex] = uniformBufferSize; - } - } - } + GLsizei minCount = 0; - for (size_t uniformBufferIndex = 0; uniformBufferIndex < fragmentUniformBuffers.size(); uniformBufferIndex++) + switch (mode) { - GLint binding = fragmentUniformBuffers[uniformBufferIndex]; - - if (binding == -1) + case GL_POINTS: { - continue; - } + bool usesPointSize = GetImplAs(glState.getProgram())->usesPointSize(); - const OffsetBindingPointer &uniformBuffer = - data.state->getIndexedUniformBuffer(binding); - GLintptr uniformBufferOffset = uniformBuffer.getOffset(); - GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); - - if (uniformBuffer.get() != nullptr) - { - Buffer11 *bufferStorage = GetImplAs(uniformBuffer.get()); - ID3D11Buffer *constantBuffer; - - if (mRenderer11DeviceCaps.supportsConstantBufferOffsets) + // 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 (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused()) { - constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); - } - else - { - constantBuffer = bufferStorage->getConstantBufferRange(uniformBufferOffset, uniformBufferSize); + // Notify developers of risking undefined behavior. + WARN() << "Point rendering without writing to gl_PointSize."; + return false; } - if (!constantBuffer) + // If instanced pointsprites are enabled and the shader uses gl_PointSize, the topology + // must be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST. + if (usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation) { - return gl::Error(GL_OUT_OF_MEMORY); + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; } - - if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() || - mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset || - mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize) + else { -#if defined(ANGLE_ENABLE_D3D11_1) - if (mRenderer11DeviceCaps.supportsConstantBufferOffsets && uniformBufferSize != 0) - { - UINT firstConstant = 0, numConstants = 0; - CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants); - mDeviceContext1->PSSetConstantBuffers1( - getReservedFragmentUniformBuffers() + - static_cast(uniformBufferIndex), - 1, &constantBuffer, &firstConstant, &numConstants); - } - else -#endif - { - mDeviceContext->PSSetConstantBuffers( - getReservedFragmentUniformBuffers() + - static_cast(uniformBufferIndex), - 1, &constantBuffer); - } - - mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); - mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset; - mCurrentConstantBufferPSSize[uniformBufferIndex] = uniformBufferSize; + primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; } + minCount = 1; + break; } + case GL_LINES: + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; + minCount = 2; + break; + case GL_LINE_LOOP: + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; + minCount = 2; + break; + case GL_LINE_STRIP: + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; + minCount = 2; + break; + case GL_TRIANGLES: + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + minCount = CullsEverything(glState) ? std::numeric_limits::max() : 3; + break; + case GL_TRIANGLE_STRIP: + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + minCount = CullsEverything(glState) ? std::numeric_limits::max() : 3; + break; + // emulate fans via rewriting index buffer + case GL_TRIANGLE_FAN: + primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + minCount = CullsEverything(glState) ? std::numeric_limits::max() : 3; + break; + default: + UNREACHABLE(); + return false; } - return gl::Error(GL_NO_ERROR); -} - -gl::Error Renderer11::updateState(const gl::Data &data, GLenum drawMode) -{ - // 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()) - { - return error; - } - - // Set the present path state - const bool presentPathFastActive = - UsePresentPathFast(this, framebufferObject->getFirstColorbuffer()); - mStateManager.updatePresentPath(presentPathFastActive, - framebufferObject->getFirstColorbuffer()); - - // Setting viewport state - mStateManager.setViewport(data.caps, data.state->getViewport(), data.state->getNearPlane(), - data.state->getFarPlane()); - - // Setting scissor state - mStateManager.setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled()); - - // 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); - - error = mStateManager.setRasterizerState(rasterizer); - if (error.isError()) - { - return error; - } - - // Setting blend state - unsigned int mask = GetBlendSampleMask(data, samples); - error = mStateManager.setBlendState(framebufferObject, data.state->getBlendState(), - data.state->getBlendColor(), mask); - if (error.isError()) - { - return error; - } - - // Setting depth stencil state - error = mStateManager.setDepthStencilState(*data.state); - return error; -} - -void Renderer11::syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) -{ - mStateManager.syncState(state, bitmask); -} - -bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize) -{ - D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; - - GLsizei minCount = 0; - - switch (mode) - { - case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; - case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; - case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; - case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; - case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; - case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; - // emulate fans via rewriting index buffer - case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; - default: - UNREACHABLE(); - return false; - } - - // If instanced pointsprite emulation is being used and If gl_PointSize is used in the shader, - // GL_POINTS mode is expected to render pointsprites. - // Instanced PointSprite emulation requires that the topology to be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST. - if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation) - { - primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - } - - if (primitiveTopology != mCurrentPrimitiveTopology) - { - mDeviceContext->IASetPrimitiveTopology(primitiveTopology); - mCurrentPrimitiveTopology = primitiveTopology; - } + mStateManager.setPrimitiveTopology(primitiveTopology); return count >= minCount; } -gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer) +gl::Error Renderer11::drawArrays(const gl::Context *context, + GLenum mode, + GLint startVertex, + GLsizei count, + GLsizei instances) { - return mStateManager.syncFramebuffer(framebuffer); -} + const auto &glState = context->getGLState(); -gl::Error Renderer11::applyVertexBuffer(const gl::State &state, - GLenum mode, - GLint first, - GLsizei count, - GLsizei instances, - TranslatedIndexData *indexInfo) -{ - gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, &mTranslatedAttribCache, instances); - if (error.isError()) + if (!applyPrimitiveType(glState, mode, count)) { - return error; + return gl::NoError(); } - // If index information is passed, mark it with the current changed status. - if (indexInfo) - { - indexInfo->srcIndexData.srcIndicesChanged = mAppliedIBChanged; - } + DrawCallVertexParams vertexParams(startVertex, count, instances); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false)); - GLsizei numIndicesPerInstance = 0; - if (instances > 0) + if (glState.isTransformFeedbackActiveUnpaused()) { - numIndicesPerInstance = count; + ANGLE_TRY(markTransformFeedbackUsage(context)); } - return mInputLayoutCache.applyVertexBuffers(mTranslatedAttribCache, mode, state.getProgram(), - indexInfo, numIndicesPerInstance); -} -gl::Error Renderer11::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, - data.state->isPrimitiveRestartEnabled()); - if (error.isError()) - { - return error; - } + gl::Program *program = glState.getProgram(); + ASSERT(program != nullptr); + GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances); + ProgramD3D *programD3D = GetImplAs(program); - ID3D11Buffer *buffer = NULL; - DXGI_FORMAT bufferFormat = (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; - - if (indexInfo->storage) - { - Buffer11 *storage = GetAs(indexInfo->storage); - buffer = storage->getBuffer(BUFFER_USAGE_INDEX); - } - else - { - IndexBuffer11* indexBuffer = GetAs(indexInfo->indexBuffer); - buffer = indexBuffer->getBuffer(); - } - - mAppliedIBChanged = false; - if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset) - { - mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); - - mAppliedIB = buffer; - mAppliedIBFormat = bufferFormat; - mAppliedIBOffset = indexInfo->startOffset; - mAppliedIBChanged = true; - } - - return gl::Error(GL_NO_ERROR); -} - -void Renderer11::applyTransformFeedbackBuffers(const gl::State &state) -{ - size_t numXFBBindings = 0; - bool requiresUpdate = false; - - if (state.isTransformFeedbackActiveUnpaused()) - { - 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++) - { - const OffsetBindingPointer &binding = transformFeedback->getIndexedBuffer(i); - - ID3D11Buffer *d3dBuffer = NULL; - if (binding.get() != nullptr) - { - 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] || binding.getOffset() != mAppliedTFOffsets[i]) - { - requiresUpdate = true; - } - } - } - - if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings) - { - const gl::TransformFeedback *transformFeedback = state.getCurrentTransformFeedback(); - for (size_t i = 0; i < numXFBBindings; ++i) - { - const OffsetBindingPointer &binding = transformFeedback->getIndexedBuffer(i); - if (binding.get() != nullptr) - { - Buffer11 *storage = GetImplAs(binding.get()); - ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); - - mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != binding.getOffset()) ? - static_cast(binding.getOffset()) : -1; - mAppliedTFBuffers[i] = d3dBuffer; - } - else - { - mAppliedTFBuffers[i] = NULL; - mCurrentD3DOffsets[i] = 0; - } - mAppliedTFOffsets[i] = binding.getOffset(); - } - - mAppliedNumXFBBindings = numXFBBindings; - - mDeviceContext->SOSetTargets(static_cast(numXFBBindings), mAppliedTFBuffers, - mCurrentD3DOffsets); - } -} - -gl::Error Renderer11::drawArraysImpl(const gl::Data &data, - GLenum mode, - GLsizei count, - GLsizei instances) -{ - ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); - - if (programD3D->usesGeometryShader(mode) && data.state->isTransformFeedbackActiveUnpaused()) + if (programD3D->usesGeometryShader(mode) && glState.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); + mStateManager.setPixelShader(nullptr); - if (instances > 0) + if (adjustedInstanceCount > 0) { - mDeviceContext->DrawInstanced(count, instances, 0, 0); + mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0); } else { @@ -1673,709 +1561,481 @@ gl::Error Renderer11::drawArraysImpl(const gl::Data &data, } rx::ShaderExecutableD3D *pixelExe = nullptr; - gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe); - if (error.isError()) - { - return error; - } + ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr)); // Skip the draw call if rasterizer discard is enabled (or no fragment shader). - if (!pixelExe || data.state->getRasterizerState().rasterizerDiscard) + if (!pixelExe || glState.getRasterizerState().rasterizerDiscard) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - ID3D11PixelShader *pixelShader = GetAs(pixelExe)->getPixelShader(); - ASSERT(reinterpret_cast(pixelShader) == mAppliedPixelShader); - mDeviceContext->PSSetShader(pixelShader, NULL, 0); + mStateManager.setPixelShader(&GetAs(pixelExe)->getPixelShader()); // Retrieve the geometry shader. rx::ShaderExecutableD3D *geometryExe = nullptr; - error = - programD3D->getGeometryExecutableForPrimitiveType(data, mode, &geometryExe, nullptr); - if (error.isError()) - { - return error; - } + ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, mode, &geometryExe, + nullptr)); - ID3D11GeometryShader *geometryShader = - (geometryExe ? GetAs(geometryExe)->getGeometryShader() : NULL); - mAppliedGeometryShader = reinterpret_cast(geometryShader); - ASSERT(geometryShader); - mDeviceContext->GSSetShader(geometryShader, NULL, 0); + mStateManager.setGeometryShader( + &GetAs(geometryExe)->getGeometryShader()); - if (instances > 0) + if (adjustedInstanceCount > 0) { - mDeviceContext->DrawInstanced(count, instances, 0, 0); + mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0); } else { mDeviceContext->Draw(count, 0); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } if (mode == GL_LINE_LOOP) { - return drawLineLoop(data, count, GL_NONE, nullptr, nullptr, instances); + return drawLineLoop(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount); } if (mode == GL_TRIANGLE_FAN) { - return drawTriangleFan(data, count, GL_NONE, nullptr, 0, instances); + return drawTriangleFan(context, count, GL_NONE, nullptr, 0, adjustedInstanceCount); } bool useInstancedPointSpriteEmulation = programD3D->usesPointSize() && getWorkarounds().useInstancedPointSpriteEmulation; - if (instances > 0) + if (mode != GL_POINTS || !useInstancedPointSpriteEmulation) { - if (mode == GL_POINTS && useInstancedPointSpriteEmulation) + if (adjustedInstanceCount == 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); - } + mDeviceContext->Draw(count, 0); } else { - mDeviceContext->DrawInstanced(count, instances, 0, 0); + mDeviceContext->DrawInstanced(count, adjustedInstanceCount, 0, 0); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } + // This code should not be reachable by multi-view programs. + ASSERT(program->usesMultiview() == false); + // 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) + if (adjustedInstanceCount == 0) { mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + return gl::NoError(); } - else - { - mDeviceContext->Draw(count, 0); - } - return gl::Error(GL_NO_ERROR); -} -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(data, count, type, indices, &indexInfo, instances); - } - - if (mode == GL_TRIANGLE_FAN) - { - return drawTriangleFan(data, count, type, indices, minIndex, instances); - } - - const ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); - if (instances > 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++) { - 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. + ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i)); mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); } - else - { - mDeviceContext->DrawIndexed(count, 0, -minIndex); - } - return gl::Error(GL_NO_ERROR); + + // This required by updateVertexOffsets... above but is outside of the loop for speed. + mStateManager.invalidateVertexBuffer(); + return gl::NoError(); } -gl::Error Renderer11::drawLineLoop(const gl::Data &data, +gl::Error Renderer11::drawElements(const gl::Context *context, + GLenum mode, GLsizei count, GLenum type, - const GLvoid *indexPointer, - const TranslatedIndexData *indexInfo, - int instances) + const void *indices, + GLsizei instances) { - gl::VertexArray *vao = data.state->getVertexArray(); - gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + const auto &glState = context->getGLState(); - const GLvoid *indices = indexPointer; - - // Get the raw indices for an indexed draw - if (type != GL_NONE && elementArrayBuffer) + if (!applyPrimitiveType(glState, mode, count)) { - BufferD3D *storage = GetImplAs(elementArrayBuffer); - intptr_t offset = reinterpret_cast(indices); - - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) - { - return error; - } - - indices = bufferData + offset; + return gl::NoError(); } - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); - if (error.isError()) - { - SafeDelete(mLineLoopIB); - return error; - } - } + // Transform feedback is not allowed for DrawElements, this error should have been caught at the + // API validation layer. + ASSERT(!glState.isTransformFeedbackActiveUnpaused()); - // Checked by Renderer11::applyPrimitiveType - ASSERT(count >= 0); + const auto &lazyIndexRange = context->getParams(); - if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - } + bool usePrimitiveRestartWorkaround = + UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type); + DrawCallVertexParams vertexParams(!usePrimitiveRestartWorkaround, lazyIndexRange, 0, instances); - GetLineLoopIndices(indices, type, static_cast(count), - data.state->isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer); + ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange, + usePrimitiveRestartWorkaround)); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true)); - unsigned int spaceNeeded = - static_cast(sizeof(GLuint) * mScratchIndexDataBuffer.size()); - gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - if (error.isError()) - { - return error; - } + int startVertex = static_cast(vertexParams.firstVertex()); + int baseVertex = -startVertex; - void* mappedMemory = NULL; - unsigned int offset; - error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); - if (error.isError()) - { - return error; - } + const gl::Program *program = glState.getProgram(); + GLsizei adjustedInstanceCount = GetAdjustedInstanceCount(program, instances); - // Copy over the converted index data. - memcpy(mappedMemory, &mScratchIndexDataBuffer[0], - sizeof(GLuint) * mScratchIndexDataBuffer.size()); - - error = mLineLoopIB->unmapBuffer(); - if (error.isError()) - { - return error; - } - - IndexBuffer11 *indexBuffer = GetAs(mLineLoopIB->getIndexBuffer()); - ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); - DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); - - if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || - mAppliedIBOffset != offset) + if (mode == GL_LINE_LOOP) { - mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset); - mAppliedIB = d3dIndexBuffer; - mAppliedIBFormat = indexFormat; - mAppliedIBOffset = offset; + return drawLineLoop(context, count, type, indices, baseVertex, adjustedInstanceCount); } - 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 + if (mode == GL_TRIANGLE_FAN) { - mDeviceContext->DrawIndexed(indexCount, 0, baseVertexLocation); + return drawTriangleFan(context, count, type, indices, baseVertex, adjustedInstanceCount); } - return gl::Error(GL_NO_ERROR); -} + const ProgramD3D *programD3D = GetImplAs(glState.getProgram()); -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) + if (mode != GL_POINTS || !programD3D->usesInstancedPointSpriteEmulation()) { - BufferD3D *storage = GetImplAs(elementArrayBuffer); - intptr_t offset = reinterpret_cast(indices); - - const uint8_t *bufferData = NULL; - gl::Error error = storage->getData(&bufferData); - if (error.isError()) + if (adjustedInstanceCount == 0) { - return error; + mDeviceContext->DrawIndexed(count, 0, baseVertex); } - - indexPointer = bufferData + offset; - } - - if (!mTriangleFanIB) - { - mTriangleFanIB = new StreamingIndexBufferInterface(this); - gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); - if (error.isError()) + else { - SafeDelete(mTriangleFanIB); - return error; + mDeviceContext->DrawIndexedInstanced(count, adjustedInstanceCount, 0, baseVertex, 0); } + return gl::NoError(); } - // Checked by Renderer11::applyPrimitiveType - ASSERT(count >= 3); - - const GLuint numTris = count - 2; + // This code should not be reachable by multi-view programs. + ASSERT(program->usesMultiview() == false); - if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) + // 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. + // + // 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. + if (instances == 0) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); + mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0); + return gl::NoError(); } - GetTriFanIndices(indexPointer, type, count, data.state->isPrimitiveRestartEnabled(), - &mScratchIndexDataBuffer); + // 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 = vertexParams.vertexCount(); - const unsigned int spaceNeeded = - static_cast(mScratchIndexDataBuffer.size() * sizeof(unsigned int)); - gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - if (error.isError()) + // Each instance being rendered requires the inputlayout cache to reapply buffers and offsets. + for (GLsizei i = 0; i < instances; i++) { - return error; - } - - void *mappedMemory = nullptr; - unsigned int offset; - error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); - if (error.isError()) - { - return error; + ANGLE_TRY(mStateManager.updateVertexOffsetsForPointSpritesEmulation(startVertex, i)); + mDeviceContext->DrawIndexedInstanced(6, elementsToRender, 0, 0, 0); } + mStateManager.invalidateVertexBuffer(); + return gl::NoError(); +} - memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded); +gl::Error Renderer11::drawArraysIndirect(const gl::Context *context, + GLenum mode, + const void *indirect) +{ + const auto &glState = context->getGLState(); + ASSERT(!glState.isTransformFeedbackActiveUnpaused()); - error = mTriangleFanIB->unmapBuffer(); - if (error.isError()) + if (!applyPrimitiveType(glState, mode, std::numeric_limits::max() - 1)) { - return error; + return gl::NoError(); } - IndexBuffer11 *indexBuffer = GetAs(mTriangleFanIB->getIndexBuffer()); - ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); - DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect); + ASSERT(drawIndirectBuffer); + Buffer11 *storage = GetImplAs(drawIndirectBuffer); + uintptr_t offset = reinterpret_cast(indirect); - if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || - mAppliedIBOffset != offset) + if (!DrawCallNeedsTranslation(context, mode)) { - mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, offset); - mAppliedIB = d3dIndexBuffer; - mAppliedIBFormat = indexFormat; - mAppliedIBOffset = offset; + DrawCallVertexParams vertexParams(0, 0, 0); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false)); + ID3D11Buffer *buffer = nullptr; + ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer); + mDeviceContext->DrawInstancedIndirect(buffer, static_cast(offset)); + return gl::NoError(); } - UINT indexCount = static_cast(mScratchIndexDataBuffer.size()); + const uint8_t *bufferData = nullptr; + ANGLE_TRY(storage->getData(context, &bufferData)); + ASSERT(bufferData); + const gl::DrawArraysIndirectCommand *args = + reinterpret_cast(bufferData + offset); + GLuint count = args->count; + GLuint instances = args->instanceCount; + GLuint first = args->first; - if (instances > 0) + DrawCallVertexParams vertexParams(first, count, instances); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, false)); + + if (mode == GL_LINE_LOOP) { - mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, -minIndex, 0); + return drawLineLoop(context, count, GL_NONE, nullptr, 0, instances); } - else + if (mode == GL_TRIANGLE_FAN) { - mDeviceContext->DrawIndexed(indexCount, 0, -minIndex); + return drawTriangleFan(context, count, GL_NONE, nullptr, 0, instances); } - return gl::Error(GL_NO_ERROR); + mDeviceContext->DrawInstanced(count, instances, 0, 0); + return gl::NoError(); } -gl::Error Renderer11::applyShadersImpl(const gl::Data &data, GLenum drawMode) +gl::Error Renderer11::drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect) { - ProgramD3D *programD3D = GetImplAs(data.state->getProgram()); - const auto &inputLayout = programD3D->getCachedInputLayout(); + const auto &glState = context->getGLState(); + ASSERT(!glState.isTransformFeedbackActiveUnpaused()); - ShaderExecutableD3D *vertexExe = NULL; - gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr); - if (error.isError()) + if (!applyPrimitiveType(glState, mode, std::numeric_limits::max() - 1)) { - return error; + return gl::NoError(); } - const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer(); - ShaderExecutableD3D *pixelExe = NULL; - error = programD3D->getPixelExecutableForFramebuffer(drawFramebuffer, &pixelExe); - if (error.isError()) - { - return error; - } + gl::Buffer *drawIndirectBuffer = glState.getTargetBuffer(gl::BufferBinding::DrawIndirect); + ASSERT(drawIndirectBuffer); + Buffer11 *storage = GetImplAs(drawIndirectBuffer); + uintptr_t offset = reinterpret_cast(indirect); - ShaderExecutableD3D *geometryExe = nullptr; - error = - programD3D->getGeometryExecutableForPrimitiveType(data, drawMode, &geometryExe, nullptr); - if (error.isError()) + // TODO(jmadill): Remove the if statement and compute indirect parameters lazily. + bool usePrimitiveRestartWorkaround = + UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), type); + + if (!DrawCallNeedsTranslation(context, mode) && !IsStreamingIndexData(context, type)) { - return error; + ANGLE_TRY(mStateManager.applyIndexBuffer(context, nullptr, 0, type, gl::HasIndexRange(), + usePrimitiveRestartWorkaround)); + DrawCallVertexParams vertexParams(0, 0, 0); + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true)); + ID3D11Buffer *buffer = nullptr; + ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDIRECT), buffer); + mDeviceContext->DrawIndexedInstancedIndirect(buffer, static_cast(offset)); + return gl::NoError(); } - ID3D11VertexShader *vertexShader = (vertexExe ? GetAs(vertexExe)->getVertexShader() : NULL); + const uint8_t *bufferData = nullptr; + ANGLE_TRY(storage->getData(context, &bufferData)); + ASSERT(bufferData); - ID3D11PixelShader *pixelShader = NULL; - // Skip pixel shader if we're doing rasterizer discard. - bool rasterizerDiscard = data.state->getRasterizerState().rasterizerDiscard; - if (!rasterizerDiscard) - { - pixelShader = (pixelExe ? GetAs(pixelExe)->getPixelShader() : NULL); - } + const gl::DrawElementsIndirectCommand *cmd = + reinterpret_cast(bufferData + offset); + GLsizei count = cmd->count; + GLuint instances = cmd->primCount; + GLuint firstIndex = cmd->firstIndex; + GLint baseVertex = cmd->baseVertex; - ID3D11GeometryShader *geometryShader = NULL; - bool transformFeedbackActive = data.state->isTransformFeedbackActiveUnpaused(); - if (transformFeedbackActive) - { - geometryShader = (vertexExe ? GetAs(vertexExe)->getStreamOutShader() : NULL); - } - else - { - geometryShader = (geometryExe ? GetAs(geometryExe)->getGeometryShader() : NULL); - } + // TODO(jmadill): Fix const cast. + const gl::Type &typeInfo = gl::GetTypeInfo(type); + const void *indices = + reinterpret_cast(static_cast(firstIndex * typeInfo.bytes)); + gl::HasIndexRange lazyIndexRange(const_cast(context), count, type, indices); - bool dirtyUniforms = false; + ANGLE_TRY(mStateManager.applyIndexBuffer(context, indices, count, type, lazyIndexRange, + usePrimitiveRestartWorkaround)); - if (reinterpret_cast(vertexShader) != mAppliedVertexShader) - { - mDeviceContext->VSSetShader(vertexShader, NULL, 0); - mAppliedVertexShader = reinterpret_cast(vertexShader); - dirtyUniforms = true; - } + DrawCallVertexParams vertexParams(false, lazyIndexRange, baseVertex, instances); - if (reinterpret_cast(geometryShader) != mAppliedGeometryShader) - { - mDeviceContext->GSSetShader(geometryShader, NULL, 0); - mAppliedGeometryShader = reinterpret_cast(geometryShader); - dirtyUniforms = true; - } + ANGLE_TRY(mStateManager.applyVertexBuffer(context, mode, vertexParams, true)); - if (reinterpret_cast(pixelShader) != mAppliedPixelShader) + int baseVertexLocation = -static_cast(lazyIndexRange.getIndexRange().value().start); + + if (mode == GL_LINE_LOOP) { - mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mAppliedPixelShader = reinterpret_cast(pixelShader); - dirtyUniforms = true; + return drawLineLoop(context, count, type, indices, baseVertexLocation, instances); } - if (dirtyUniforms) + if (mode == GL_TRIANGLE_FAN) { - programD3D->dirtyAllUniforms(); + return drawTriangleFan(context, count, type, indices, baseVertexLocation, instances); } - return gl::Error(GL_NO_ERROR); + mDeviceContext->DrawIndexedInstanced(count, instances, 0, baseVertexLocation, 0); + return gl::NoError(); } -gl::Error Renderer11::applyUniforms(const ProgramD3D &programD3D, - GLenum drawMode, - const std::vector &uniformArray) +gl::Error Renderer11::drawLineLoop(const gl::Context *context, + GLsizei count, + GLenum type, + const void *indexPointer, + int baseVertex, + int instances) { - unsigned int totalRegisterCountVS = 0; - unsigned int totalRegisterCountPS = 0; + const gl::State &glState = context->getGLState(); + gl::VertexArray *vao = glState.getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); - bool vertexUniformsDirty = false; - bool pixelUniformsDirty = false; + const void *indices = indexPointer; - for (const D3DUniform *uniform : uniformArray) + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) { - if (uniform->isReferencedByVertexShader() && !uniform->isSampler()) - { - totalRegisterCountVS += uniform->registerCount; - vertexUniformsDirty = (vertexUniformsDirty || uniform->dirty); - } - - if (uniform->isReferencedByFragmentShader() && !uniform->isSampler()) - { - totalRegisterCountPS += uniform->registerCount; - pixelUniformsDirty = (pixelUniformsDirty || uniform->dirty); - } - } - - const UniformStorage11 *vertexUniformStorage = - GetAs(&programD3D.getVertexUniformStorage()); - const UniformStorage11 *fragmentUniformStorage = - GetAs(&programD3D.getFragmentUniformStorage()); - ASSERT(vertexUniformStorage); - ASSERT(fragmentUniformStorage); + BufferD3D *storage = GetImplAs(elementArrayBuffer); + intptr_t offset = reinterpret_cast(indices); - ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer(); - ID3D11Buffer *pixelConstantBuffer = fragmentUniformStorage->getConstantBuffer(); + const uint8_t *bufferData = nullptr; + ANGLE_TRY(storage->getData(context, &bufferData)); - float (*mapVS)[4] = NULL; - float (*mapPS)[4] = NULL; + indices = bufferData + offset; + } - if (totalRegisterCountVS > 0 && vertexUniformsDirty) + if (!mLineLoopIB) { - D3D11_MAPPED_SUBRESOURCE map = {0}; - HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - mapVS = (float(*)[4])map.pData; + mLineLoopIB = new StreamingIndexBufferInterface(this); + gl::Error error = + mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) + { + SafeDelete(mLineLoopIB); + return error; + } } - if (totalRegisterCountPS > 0 && pixelUniformsDirty) + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > + (std::numeric_limits::max() / sizeof(unsigned int))) { - D3D11_MAPPED_SUBRESOURCE map = {0}; - HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - mapPS = (float(*)[4])map.pData; + return gl::OutOfMemory() << "Failed to create a 32-bit looping index buffer for " + "GL_LINE_LOOP, too many indices required."; } - for (const D3DUniform *uniform : uniformArray) - { - if (uniform->isSampler()) - continue; + GetLineLoopIndices(indices, type, static_cast(count), + glState.isPrimitiveRestartEnabled(), &mScratchIndexDataBuffer); - unsigned int componentCount = (4 - uniform->registerElement); + unsigned int spaceNeeded = + static_cast(sizeof(GLuint) * mScratchIndexDataBuffer.size()); + ANGLE_TRY(mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)); - // we assume that uniforms from structs are arranged in struct order in our uniforms list. - // otherwise we would overwrite previously written regions of memory. + void *mappedMemory = nullptr; + unsigned int offset; + ANGLE_TRY(mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)); - if (uniform->isReferencedByVertexShader() && mapVS) - { - memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, - uniform->registerCount * sizeof(float) * componentCount); - } + // Copy over the converted index data. + memcpy(mappedMemory, &mScratchIndexDataBuffer[0], + sizeof(GLuint) * mScratchIndexDataBuffer.size()); - if (uniform->isReferencedByFragmentShader() && mapPS) - { - memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, - uniform->registerCount * sizeof(float) * componentCount); - } - } + ANGLE_TRY(mLineLoopIB->unmapBuffer()); - if (mapVS) - { - mDeviceContext->Unmap(vertexConstantBuffer, 0); - } + IndexBuffer11 *indexBuffer = GetAs(mLineLoopIB->getIndexBuffer()); + const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); - if (mapPS) - { - mDeviceContext->Unmap(pixelConstantBuffer, 0); - } + mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset); - if (mCurrentVertexConstantBuffer != vertexConstantBuffer) - { - mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); - mCurrentVertexConstantBuffer = vertexConstantBuffer; - } + UINT indexCount = static_cast(mScratchIndexDataBuffer.size()); - if (mCurrentPixelConstantBuffer != pixelConstantBuffer) + if (instances > 0) { - mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); - mCurrentPixelConstantBuffer = pixelConstantBuffer; + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0); } - - // Driver uniforms - if (!mDriverConstantBufferVS) + else { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants11); - constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = 0; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); - 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); + mDeviceContext->DrawIndexed(indexCount, 0, baseVertex); } - if (!mDriverConstantBufferPS) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants11); - constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = 0; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; + return gl::NoError(); +} - HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); - 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); - } +gl::Error Renderer11::drawTriangleFan(const gl::Context *context, + GLsizei count, + GLenum type, + const void *indices, + int baseVertex, + int instances) +{ + const gl::State &glState = context->getGLState(); + gl::VertexArray *vao = glState.getVertexArray(); + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); - const dx_VertexConstants11 &vertexConstants = mStateManager.getVertexConstants(); - if (memcmp(&vertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants11)) != 0) - { - ASSERT(mDriverConstantBufferVS != nullptr); - if (mDriverConstantBufferVS) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &vertexConstants, - 16, 0); - memcpy(&mAppliedVertexConstants, &vertexConstants, sizeof(dx_VertexConstants11)); - } - } + const void *indexPointer = indices; - const dx_PixelConstants11 &pixelConstants = mStateManager.getPixelConstants(); - if (memcmp(&pixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants11)) != 0) + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) { - ASSERT(mDriverConstantBufferPS != nullptr); - if (mDriverConstantBufferPS) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &pixelConstants, 16, - 0); - memcpy(&mAppliedPixelConstants, &pixelConstants, sizeof(dx_PixelConstants11)); - } + BufferD3D *storage = GetImplAs(elementArrayBuffer); + intptr_t offset = reinterpret_cast(indices); + + const uint8_t *bufferData = nullptr; + ANGLE_TRY(storage->getData(context, &bufferData)); + + indexPointer = bufferData + offset; } - // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary - if (programD3D.usesGeometryShader(drawMode)) + if (!mTriangleFanIB) { - // needed for the point sprite geometry shader - if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + mTriangleFanIB = new StreamingIndexBufferInterface(this); + gl::Error error = + mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) { - ASSERT(mDriverConstantBufferPS != nullptr); - if (mDriverConstantBufferPS) - { - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; - } + SafeDelete(mTriangleFanIB); + return error; } } - return gl::Error(GL_NO_ERROR); -} + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 3); -void Renderer11::markAllStateDirty() -{ - TRACE_EVENT0("gpu.angle", "Renderer11::markAllStateDirty"); + const GLuint numTris = count - 2; - for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId) + if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) { - mForceSetVertexSamplerStates[vsamplerId] = true; + return gl::OutOfMemory() << "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, " + "too many indices required."; } - for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId) - { - mForceSetPixelSamplerStates[fsamplerId] = true; - } + GetTriFanIndices(indexPointer, type, count, glState.isPrimitiveRestartEnabled(), + &mScratchIndexDataBuffer); - mStateManager.invalidateEverything(); + const unsigned int spaceNeeded = + static_cast(mScratchIndexDataBuffer.size() * sizeof(unsigned int)); + ANGLE_TRY(mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)); - mAppliedIB = NULL; - mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; - mAppliedIBOffset = 0; + void *mappedMemory = nullptr; + unsigned int offset; + ANGLE_TRY(mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)); - mAppliedVertexShader = angle::DirtyPointer; - mAppliedGeometryShader = angle::DirtyPointer; - mAppliedPixelShader = angle::DirtyPointer; + memcpy(mappedMemory, &mScratchIndexDataBuffer[0], spaceNeeded); - mAppliedNumXFBBindings = static_cast(-1); + ANGLE_TRY(mTriangleFanIB->unmapBuffer()); - for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) - { - mAppliedTFBuffers[i] = NULL; - mAppliedTFOffsets[i] = 0; - } + IndexBuffer11 *indexBuffer = GetAs(mTriangleFanIB->getIndexBuffer()); + const d3d11::Buffer &d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); - memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants11)); - memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants11)); + mStateManager.setIndexBuffer(d3dIndexBuffer.get(), indexFormat, offset); - mInputLayoutCache.markDirty(); + UINT indexCount = static_cast(mScratchIndexDataBuffer.size()); - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++) + if (instances > 0) { - mCurrentConstantBufferVS[i] = static_cast(-1); - mCurrentConstantBufferVSOffset[i] = 0; - mCurrentConstantBufferVSSize[i] = 0; - mCurrentConstantBufferPS[i] = static_cast(-1); - mCurrentConstantBufferPSOffset[i] = 0; - mCurrentConstantBufferPSSize[i] = 0; + mDeviceContext->DrawIndexedInstanced(indexCount, instances, 0, baseVertex, 0); + } + else + { + mDeviceContext->DrawIndexed(indexCount, 0, baseVertex); } - mCurrentVertexConstantBuffer = NULL; - mCurrentPixelConstantBuffer = NULL; - mCurrentGeometryConstantBuffer = NULL; - - mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + return gl::NoError(); } void Renderer11::releaseDeviceResources() { + mStateManager.deinitialize(); mStateCache.clear(); - mInputLayoutCache.clear(); - SafeDelete(mVertexDataManager); - SafeDelete(mIndexDataManager); SafeDelete(mLineLoopIB); SafeDelete(mTriangleFanIB); SafeDelete(mBlit); @@ -2383,9 +2043,9 @@ void Renderer11::releaseDeviceResources() SafeDelete(mTrim); SafeDelete(mPixelTransfer); - SafeRelease(mDriverConstantBufferVS); - SafeRelease(mDriverConstantBufferPS); - SafeRelease(mSyncQuery); + mSyncQuery.reset(); + + mCachedResolveTexture.reset(); } // set notify to true to broadcast a message to all contexts of the device loss @@ -2393,24 +2053,18 @@ bool Renderer11::testDeviceLost() { bool isLost = false; + if (!mDevice) + { + return true; + } + // GetRemovedReason is used to test if the device is removed HRESULT result = mDevice->GetDeviceRemovedReason(); - isLost = d3d11::isDeviceLostError(result); + isLost = d3d11::isDeviceLostError(result); if (isLost) { - // Log error if this is a new device lost event - if (mDeviceLost == false) - { - ERR("The D3D11 device was removed: 0x%08X", result); - } - - // ensure we note the device loss -- - // we'll probably get this done again by notifyDeviceLost - // but best to remember it! - // Note that we don't want to clear the device loss status here - // -- this needs to be done by resetDevice - mDeviceLost = true; + ERR() << "The D3D11 device was removed, " << gl::FmtHR(result); } return isLost; @@ -2419,27 +2073,24 @@ bool Renderer11::testDeviceLost() bool Renderer11::testDeviceResettable() { // determine if the device is resettable by creating a dummy device - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = + (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); - if (D3D11CreateDevice == NULL) + if (D3D11CreateDevice == nullptr) { return false; } - ID3D11Device* dummyDevice; + ID3D11Device *dummyDevice; D3D_FEATURE_LEVEL dummyFeatureLevel; - ID3D11DeviceContext* dummyContext; + ID3D11DeviceContext *dummyContext; + UINT flags = (mCreateDebugDevice ? D3D11_CREATE_DEVICE_DEBUG : 0); ASSERT(mRequestedDriverType != D3D_DRIVER_TYPE_UNKNOWN); HRESULT result = D3D11CreateDevice( - NULL, mRequestedDriverType, NULL, - #if defined(_DEBUG) - D3D11_CREATE_DEVICE_DEBUG, - #else - 0, - #endif - mAvailableFeatureLevels.data(), static_cast(mAvailableFeatureLevels.size()), - D3D11_SDK_VERSION, &dummyDevice, &dummyFeatureLevel, &dummyContext); + nullptr, mRequestedDriverType, nullptr, flags, mAvailableFeatureLevels.data(), + static_cast(mAvailableFeatureLevels.size()), D3D11_SDK_VERSION, &dummyDevice, + &dummyFeatureLevel, &dummyContext); if (!mDevice || FAILED(result)) { @@ -2456,6 +2107,14 @@ void Renderer11::release() { RendererD3D::cleanup(); + mScratchMemoryBuffer.clear(); + + if (mAnnotator != nullptr) + { + gl::UninitializeDebugAnnotations(); + SafeDelete(mAnnotator); + } + releaseDeviceResources(); if (!mCreatedWithDeviceEXT) @@ -2468,9 +2127,8 @@ void Renderer11::release() SafeRelease(mDxgiFactory); SafeRelease(mDxgiAdapter); -#if defined(ANGLE_ENABLE_D3D11_1) + SafeRelease(mDeviceContext3); SafeRelease(mDeviceContext1); -#endif if (mDeviceContext) { @@ -2480,26 +2138,24 @@ void Renderer11::release() } SafeRelease(mDevice); -#if !defined(ANGLE_MINGW32_COMPAT) SafeRelease(mDebug); -#endif if (mD3d11Module) { FreeLibrary(mD3d11Module); - mD3d11Module = NULL; + mD3d11Module = nullptr; } if (mDxgiModule) { FreeLibrary(mDxgiModule); - mDxgiModule = NULL; + mDxgiModule = nullptr; } if (mDCompModule) { FreeLibrary(mDCompModule); - mDCompModule = NULL; + mDCompModule = nullptr; } mCompiler.release(); @@ -2515,12 +2171,10 @@ bool Renderer11::resetDevice() if (result.isError()) { - ERR("Could not reinitialize D3D11 device: %08X", result.getCode()); + ERR() << "Could not reinitialize D3D11 device: " << result; return false; } - mDeviceLost = false; - return true; } @@ -2531,8 +2185,10 @@ std::string Renderer11::getRendererDescription() const rendererString << mDescription; rendererString << " Direct3D11"; - rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix(); - rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix(); + rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() + << getShaderModelSuffix(); + rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() + << getShaderModelSuffix(); return rendererString.str(); } @@ -2540,12 +2196,12 @@ std::string Renderer11::getRendererDescription() const DeviceIdentifier Renderer11::getAdapterIdentifier() const { // 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); + 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; } @@ -2605,7 +2261,7 @@ bool Renderer11::getShareHandleSupport() const // 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) + if (!getNativeExtensions().textureFormatBGRA8888) { mSupportsShareHandles = false; return false; @@ -2620,7 +2276,8 @@ bool Renderer11::getShareHandleSupport() const // Qt: we don't care about the 9_3 limitation #if 0 - // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains. + // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on + // RGBA8 textures/swapchains. if (mRenderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3) { mSupportsShareHandles = false; @@ -2668,15 +2325,34 @@ bool Renderer11::getShareHandleSupport() const return true; } +bool Renderer11::getNV12TextureSupport() const +{ + HRESULT result; + UINT formatSupport; + result = mDevice->CheckFormatSupport(DXGI_FORMAT_NV12, &formatSupport); + if (result == E_FAIL) + { + return false; + } + return (formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0; +} + int Renderer11::getMajorShaderModel() const { 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 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 - case D3D_FEATURE_LEVEL_9_3: return D3D10_SHADER_MAJOR_VERSION; // 4 - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + 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 + case D3D_FEATURE_LEVEL_10_0: + return D3D10_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_9_3: + return D3D10_SHADER_MAJOR_VERSION; // 4 + default: + UNREACHABLE(); + return 0; } } @@ -2684,11 +2360,18 @@ int Renderer11::getMinorShaderModel() const { 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 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 - case D3D_FEATURE_LEVEL_9_3: return D3D10_SHADER_MINOR_VERSION; // 0 - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + 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 + case D3D_FEATURE_LEVEL_10_0: + return D3D10_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_9_3: + return D3D10_SHADER_MINOR_VERSION; // 0 + default: + UNREACHABLE(); + return 0; } } @@ -2696,15 +2379,22 @@ std::string Renderer11::getShaderModelSuffix() const { switch (mRenderer11DeviceCaps.featureLevel) { - case D3D_FEATURE_LEVEL_11_0: return ""; - case D3D_FEATURE_LEVEL_10_1: return ""; - case D3D_FEATURE_LEVEL_10_0: return ""; - case D3D_FEATURE_LEVEL_9_3: return "_level_9_3"; - default: UNREACHABLE(); return ""; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return ""; + case D3D_FEATURE_LEVEL_10_1: + return ""; + case D3D_FEATURE_LEVEL_10_0: + return ""; + case D3D_FEATURE_LEVEL_9_3: + return "_level_9_3"; + default: + UNREACHABLE(); + return ""; } } -const WorkaroundsD3D &RendererD3D::getWorkarounds() const +const angle::WorkaroundsD3D &RendererD3D::getWorkarounds() const { if (!mWorkaroundsInitialized) { @@ -2715,42 +2405,31 @@ const WorkaroundsD3D &RendererD3D::getWorkarounds() const 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::Error Renderer11::copyImageInternal(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + RenderTargetD3D *destRenderTarget) { - const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); + const gl::FramebufferAttachment *colorAttachment = framebuffer->getReadColorbuffer(); + ASSERT(colorAttachment); - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); - if (error.isError()) - { - return error; - } + RenderTarget11 *sourceRenderTarget = nullptr; + ANGLE_TRY(colorAttachment->getRenderTarget(context, &sourceRenderTarget)); ASSERT(sourceRenderTarget); - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); - - TextureStorage11_2D *storage11 = GetAs(storage); - ASSERT(storage11); - - gl::ImageIndex index = gl::ImageIndex::Make2D(level); - RenderTargetD3D *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); + const d3d11::SharedSRV &source = sourceRenderTarget->getBlitShaderResourceView(); + ASSERT(source.valid()); - ID3D11RenderTargetView *dest = GetAs(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); + const d3d11::RenderTargetView &dest = + GetAs(destRenderTarget)->getRenderTargetView(); + ASSERT(dest.valid()); 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); + const bool invertSource = UsePresentPathFast(this, colorAttachment); if (invertSource) { sourceArea.y = sourceSize.height - sourceRect.y; @@ -2760,226 +2439,267 @@ gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl:: 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, false); - if (error.isError()) - { - return error; - } - - storage11->invalidateSwizzleCacheLevel(level); + // Use nearest filtering because source and destination are the same size for the direct copy. + // Convert to the unsized format before calling copyTexture. + GLenum sourceFormat = colorAttachment->getFormat().info->format; + ANGLE_TRY(mBlit->copyTexture(context, source, sourceArea, sourceSize, sourceFormat, dest, + destArea, destSize, nullptr, gl::GetUnsizedFormat(destFormat), + GL_NEAREST, false, false, false)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -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::Error Renderer11::copyImage2D(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) { - const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); + TextureStorage11_2D *storage11 = GetAs(storage); + ASSERT(storage11); - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(sourceRenderTarget); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); + ASSERT(destRenderTarget); + + ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, + destRenderTarget)); + + storage11->markLevelDirty(level); - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); + return gl::NoError(); +} +gl::Error Renderer11::copyImageCube(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum target, + GLint level) +{ TextureStorage11_Cube *storage11 = GetAs(storage); ASSERT(storage11); - gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); - RenderTargetD3D *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); ASSERT(destRenderTarget); - ID3D11RenderTargetView *dest = GetAs(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); + ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, + destRenderTarget)); - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + storage11->markLevelDirty(level); - const bool invertSource = UsePresentPathFast(this, colorbuffer); - if (invertSource) - { - sourceArea.y = sourceSize.height - sourceRect.y; - sourceArea.height = -sourceArea.height; - } + return gl::NoError(); +} - gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); +gl::Error Renderer11::copyImage3D(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) +{ + TextureStorage11_3D *storage11 = GetAs(storage); + ASSERT(storage11); - // 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, false); - if (error.isError()) - { - return error; - } + gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); + ASSERT(destRenderTarget); - storage11->invalidateSwizzleCacheLevel(level); + ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, + destRenderTarget)); - return gl::Error(GL_NO_ERROR); + storage11->markLevelDirty(level); + + return gl::NoError(); } -gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level) +gl::Error Renderer11::copyImage2DArray(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) { - const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); + TextureStorage11_2DArray *storage11 = GetAs(storage); + ASSERT(storage11); - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(sourceRenderTarget); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); + RenderTargetD3D *destRenderTarget = nullptr; + ANGLE_TRY(storage11->getRenderTarget(context, index, &destRenderTarget)); + ASSERT(destRenderTarget); - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); + ANGLE_TRY(copyImageInternal(context, framebuffer, sourceRect, destFormat, destOffset, + destRenderTarget)); + storage11->markLevelDirty(level); - TextureStorage11_3D *storage11 = GetAs(storage); - ASSERT(storage11); + return gl::NoError(); +} - gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z); - RenderTargetD3D *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); +gl::Error Renderer11::copyTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum destTarget, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + TextureD3D *sourceD3D = GetImplAs(source); - ID3D11RenderTargetView *dest = GetAs(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); + TextureStorage *sourceStorage = nullptr; + ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage)); - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + TextureStorage11_2D *sourceStorage11 = GetAs(sourceStorage); + ASSERT(sourceStorage11); - gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + TextureStorage11 *destStorage11 = GetAs(storage); + ASSERT(destStorage11); - // 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, false); - if (error.isError()) + // Check for fast path where a CopySubresourceRegion can be used. + if (unpackPremultiplyAlpha == unpackUnmultiplyAlpha && !unpackFlipY && + source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format == destFormat && + sourceStorage11->getFormatSet().texFormat == destStorage11->getFormatSet().texFormat) { - return error; - } + const TextureHelper11 *sourceResource = nullptr; + ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource)); - storage11->invalidateSwizzleCacheLevel(level); + gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel); + UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex); - return gl::Error(GL_NO_ERROR); -} + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(destStorage11->getResource(context, &destResource)); -gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level) -{ - const gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); - ASSERT(colorbuffer); + gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel); + UINT destSubresource = destStorage11->getSubresourceIndex(destIndex); - RenderTarget11 *sourceRenderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&sourceRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(sourceRenderTarget); + D3D11_BOX sourceBox{ + static_cast(sourceRect.x), + static_cast(sourceRect.y), + 0u, + static_cast(sourceRect.x + sourceRect.width), + static_cast(sourceRect.y + sourceRect.height), + 1u, + }; - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - ASSERT(source); + mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, destOffset.x, + destOffset.y, destOffset.z, sourceResource->get(), + sourceSubresource, &sourceBox); + } + else + { + const d3d11::SharedSRV *sourceSRV = nullptr; + ANGLE_TRY(sourceStorage11->getSRVLevels(context, sourceLevel, sourceLevel, &sourceSRV)); - TextureStorage11_2DArray *storage11 = GetAs(storage); - ASSERT(storage11); + gl::ImageIndex destIndex = gl::ImageIndex::MakeGeneric(destTarget, destLevel); + RenderTargetD3D *destRenderTargetD3D = nullptr; + ANGLE_TRY(destStorage11->getRenderTarget(context, destIndex, &destRenderTargetD3D)); - gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z); - RenderTargetD3D *destRenderTarget = NULL; - error = storage11->getRenderTarget(index, &destRenderTarget); - if (error.isError()) - { - return error; - } - ASSERT(destRenderTarget); + RenderTarget11 *destRenderTarget11 = GetAs(destRenderTargetD3D); - ID3D11RenderTargetView *dest = GetAs(destRenderTarget)->getRenderTargetView(); - ASSERT(dest); + const d3d11::RenderTargetView &destRTV = destRenderTarget11->getRenderTargetView(); + ASSERT(destRTV.valid()); - gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); - gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize( + static_cast(source->getWidth(source->getTarget(), sourceLevel)), + static_cast(source->getHeight(source->getTarget(), sourceLevel)), 1); + if (unpackFlipY) + { + sourceArea.y += sourceArea.height; + 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); + gl::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget11->getWidth(), destRenderTarget11->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, false); - if (error.isError()) - { - return error; + // Use nearest filtering because source and destination are the same size for the direct + // copy + GLenum sourceFormat = source->getFormat(GL_TEXTURE_2D, sourceLevel).info->format; + ANGLE_TRY(mBlit->copyTexture(context, *sourceSRV, sourceArea, sourceSize, sourceFormat, + destRTV, destArea, destSize, nullptr, destFormat, GL_NEAREST, + false, unpackPremultiplyAlpha, unpackUnmultiplyAlpha)); } - storage11->invalidateSwizzleCacheLevel(level); + destStorage11->markLevelDirty(destLevel); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void Renderer11::unapplyRenderTargets() +gl::Error Renderer11::copyCompressedTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) { - setOneTimeRenderTarget(NULL); -} + TextureStorage11_2D *destStorage11 = GetAs(storage); + ASSERT(destStorage11); -// When finished with this rendertarget, markAllStateDirty must be called. -void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) -{ - ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(destStorage11->getResource(context, &destResource)); - rtvArray[0] = renderTargetView; + gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel); + UINT destSubresource = destStorage11->getSubresourceIndex(destIndex); - mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, rtvArray, NULL); + TextureD3D *sourceD3D = GetImplAs(source); + ASSERT(sourceD3D); - // Do not preserve the serial for this one-time-use render target - for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++) - { - mAppliedRTVs[rtIndex] = angle::DirtyPointer; - } - mAppliedDSV = angle::DirtyPointer; + TextureStorage *sourceStorage = nullptr; + ANGLE_TRY(sourceD3D->getNativeTexture(context, &sourceStorage)); + + TextureStorage11_2D *sourceStorage11 = GetAs(sourceStorage); + ASSERT(sourceStorage11); + + const TextureHelper11 *sourceResource = nullptr; + ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource)); + + gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel); + UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex); + + mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0, + sourceResource->get(), sourceSubresource, nullptr); + + return gl::NoError(); } -gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) +gl::Error Renderer11::createRenderTarget(int width, + int height, + GLenum format, + GLsizei samples, + RenderTargetD3D **outRT) { - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format, mRenderer11DeviceCaps); + const d3d11::Format &formatInfo = d3d11::Format::Get(format, mRenderer11DeviceCaps); - const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format); - GLuint supportedSamples = textureCaps.getNearestSamples(samples); + const gl::TextureCaps &textureCaps = getNativeTextureCaps().get(format); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); if (width > 0 && height > 0) { // Create texture resource D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = formatInfo.texFormat; - desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = formatInfo.texFormat; + desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; // If a rendertarget or depthstencil format exists for this texture format, // we'll flag it to allow binding that way. Shader resource views are a little @@ -2987,110 +2707,105 @@ gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, G bool bindRTV = false, bindDSV = false, bindSRV = false; bindRTV = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); bindDSV = (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); - if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + bindSRV = (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN); + + bool isMultisampledDepthStencil = bindDSV && desc.SampleDesc.Count > 1; + if (isMultisampledDepthStencil && + !mRenderer11DeviceCaps.supportsMultisampledDepthStencilSRVs) { - // Multisample targets flagged for binding as depth stencil cannot also be - // flagged for binding as SRV, so make certain not to add the SRV flag for - // these targets. - bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); + bindSRV = false; } - desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | - (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | + desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | + (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); // The format must be either an RTV or a DSV ASSERT(bindRTV != bindDSV); - ID3D11Texture2D *texture = NULL; - HRESULT result = mDevice->CreateTexture2D(&desc, NULL, &texture); - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target texture, result: 0x%X.", result); - } + TextureHelper11 texture; + ANGLE_TRY(allocateTexture(desc, formatInfo, &texture)); - ID3D11ShaderResourceView *srv = NULL; + d3d11::SharedSRV srv; + d3d11::SharedSRV blitSRV; if (bindSRV) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = formatInfo.srvFormat; - srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; + srvDesc.Format = formatInfo.srvFormat; + srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D + : D3D11_SRV_DIMENSION_TEXTURE2DMS; srvDesc.Texture2D.MostDetailedMip = 0; - srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MipLevels = 1; - result = mDevice->CreateShaderResourceView(texture, &srvDesc, &srv); - if (FAILED(result)) + ANGLE_TRY(allocateResource(srvDesc, texture.get(), &srv)); + + if (formatInfo.blitSRVFormat != formatInfo.srvFormat) + { + D3D11_SHADER_RESOURCE_VIEW_DESC blitSRVDesc; + blitSRVDesc.Format = formatInfo.blitSRVFormat; + blitSRVDesc.ViewDimension = (supportedSamples == 0) + ? D3D11_SRV_DIMENSION_TEXTURE2D + : D3D11_SRV_DIMENSION_TEXTURE2DMS; + blitSRVDesc.Texture2D.MostDetailedMip = 0; + blitSRVDesc.Texture2D.MipLevels = 1; + + ANGLE_TRY(allocateResource(blitSRVDesc, texture.get(), &blitSRV)); + } + else { - ASSERT(result == E_OUTOFMEMORY); - SafeRelease(texture); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target shader resource view, result: 0x%X.", result); + blitSRV = srv.makeCopy(); } } if (bindDSV) { D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = formatInfo.dsvFormat; - dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Format = formatInfo.dsvFormat; + dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D + : D3D11_DSV_DIMENSION_TEXTURE2DMS; dsvDesc.Texture2D.MipSlice = 0; - dsvDesc.Flags = 0; - - ID3D11DepthStencilView *dsv = NULL; - result = mDevice->CreateDepthStencilView(texture, &dsvDesc, &dsv); - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - SafeRelease(texture); - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target depth stencil view, result: 0x%X.", result); - } + dsvDesc.Flags = 0; - *outRT = new TextureRenderTarget11(dsv, texture, srv, format, width, height, 1, supportedSamples); + d3d11::DepthStencilView dsv; + ANGLE_TRY(allocateResource(dsvDesc, texture.get(), &dsv)); - SafeRelease(dsv); + *outRT = new TextureRenderTarget11(std::move(dsv), texture, srv, format, formatInfo, + width, height, 1, supportedSamples); } else if (bindRTV) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = formatInfo.rtvFormat; - rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; + rtvDesc.Format = formatInfo.rtvFormat; + rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D + : D3D11_RTV_DIMENSION_TEXTURE2DMS; rtvDesc.Texture2D.MipSlice = 0; - ID3D11RenderTargetView *rtv = NULL; - result = mDevice->CreateRenderTargetView(texture, &rtvDesc, &rtv); - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - SafeRelease(texture); - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create render target render target view, result: 0x%X.", result); - } + d3d11::RenderTargetView rtv; + ANGLE_TRY(allocateResource(rtvDesc, texture.get(), &rtv)); - if (formatInfo.dataInitializerFunction != NULL) + if (formatInfo.dataInitializerFunction != nullptr) { - const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - mDeviceContext->ClearRenderTargetView(rtv, clearValues); + const float clearValues[4] = {0.0f, 0.0f, 0.0f, 1.0f}; + mDeviceContext->ClearRenderTargetView(rtv.get(), clearValues); } - *outRT = new TextureRenderTarget11(rtv, texture, srv, format, width, height, 1, supportedSamples); - - SafeRelease(rtv); + *outRT = new TextureRenderTarget11(std::move(rtv), texture, srv, blitSRV, format, + formatInfo, width, height, 1, supportedSamples); } else { UNREACHABLE(); } - - SafeRelease(texture); - SafeRelease(srv); } else { - *outRT = new TextureRenderTarget11(reinterpret_cast(NULL), NULL, NULL, format, width, height, 1, supportedSamples); + *outRT = new TextureRenderTarget11(d3d11::RenderTargetView(), TextureHelper11(), + d3d11::SharedSRV(), d3d11::SharedSRV(), format, + d3d11::Format::Get(GL_NONE, mRenderer11DeviceCaps), + width, height, 1, supportedSamples); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) @@ -3098,58 +2813,35 @@ gl::Error Renderer11::createRenderTargetCopy(RenderTargetD3D *source, RenderTarg ASSERT(source != nullptr); RenderTargetD3D *newRT = nullptr; - gl::Error error = createRenderTarget(source->getWidth(), source->getHeight(), - source->getInternalFormat(), source->getSamples(), &newRT); - if (error.isError()) - { - return error; - } + ANGLE_TRY(createRenderTarget(source->getWidth(), source->getHeight(), + source->getInternalFormat(), source->getSamples(), &newRT)); RenderTarget11 *source11 = GetAs(source); RenderTarget11 *dest11 = GetAs(newRT); - mDeviceContext->CopySubresourceRegion(dest11->getTexture(), dest11->getSubresourceIndex(), 0, 0, - 0, source11->getTexture(), + mDeviceContext->CopySubresourceRegion(dest11->getTexture().get(), dest11->getSubresourceIndex(), + 0, 0, 0, source11->getTexture().get(), source11->getSubresourceIndex(), nullptr); *outRT = newRT; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -FramebufferImpl *Renderer11::createFramebuffer(const gl::Framebuffer::Data &data) -{ - return new Framebuffer11(data, this); -} - -ShaderImpl *Renderer11::createShader(const gl::Shader::Data &data) -{ - return new ShaderD3D(data); -} - -ProgramImpl *Renderer11::createProgram(const gl::Program::Data &data) -{ - return new ProgramD3D(data, this); -} - -gl::Error Renderer11::loadExecutable(const void *function, +gl::Error Renderer11::loadExecutable(const uint8_t *function, size_t length, - ShaderType type, + gl::ShaderType type, const std::vector &streamOutVaryings, bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) { + ShaderData shaderData(function, length); + switch (type) { - case SHADER_VERTEX: + case gl::SHADER_VERTEX: { - ID3D11VertexShader *vertexShader = NULL; - ID3D11GeometryShader *streamOutShader = NULL; - - HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create vertex shader, result: 0x%X.", result); - } + d3d11::VertexShader vertexShader; + d3d11::GeometryShader streamOutShader; + ANGLE_TRY(allocateResource(shaderData, &vertexShader)); if (!streamOutVaryings.empty()) { @@ -3163,88 +2855,80 @@ gl::Error Renderer11::loadExecutable(const void *function, entry.SemanticName = streamOutVarying.semanticName.c_str(); entry.SemanticIndex = streamOutVarying.semanticIndex; entry.StartComponent = 0; - entry.ComponentCount = static_cast(streamOutVarying.componentCount); - entry.OutputSlot = static_cast( + entry.ComponentCount = static_cast(streamOutVarying.componentCount); + entry.OutputSlot = static_cast( (separatedOutputBuffers ? streamOutVarying.outputSlot : 0)); soDeclaration.push_back(entry); } - result = mDevice->CreateGeometryShaderWithStreamOutput( - function, static_cast(length), soDeclaration.data(), - static_cast(soDeclaration.size()), NULL, 0, 0, NULL, - &streamOutShader); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create steam output shader, result: 0x%X.", result); - } + ANGLE_TRY(allocateResource(shaderData, &soDeclaration, &streamOutShader)); } - *outExecutable = new ShaderExecutable11(function, length, vertexShader, streamOutShader); + *outExecutable = new ShaderExecutable11(function, length, std::move(vertexShader), + std::move(streamOutShader)); } break; - case SHADER_PIXEL: + case gl::SHADER_FRAGMENT: { - ID3D11PixelShader *pixelShader = NULL; - - HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create pixel shader, result: 0x%X.", result); - } - - *outExecutable = new ShaderExecutable11(function, length, pixelShader); + d3d11::PixelShader pixelShader; + ANGLE_TRY(allocateResource(shaderData, &pixelShader)); + *outExecutable = new ShaderExecutable11(function, length, std::move(pixelShader)); } break; - case SHADER_GEOMETRY: + case gl::SHADER_GEOMETRY: { - ID3D11GeometryShader *geometryShader = NULL; - - HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); - ASSERT(SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create geometry shader, result: 0x%X.", result); - } - - *outExecutable = new ShaderExecutable11(function, length, geometryShader); + d3d11::GeometryShader geometryShader; + ANGLE_TRY(allocateResource(shaderData, &geometryShader)); + *outExecutable = new ShaderExecutable11(function, length, std::move(geometryShader)); + } + break; + case gl::SHADER_COMPUTE: + { + d3d11::ComputeShader computeShader; + ANGLE_TRY(allocateResource(shaderData, &computeShader)); + *outExecutable = new ShaderExecutable11(function, length, std::move(computeShader)); } break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + default: + UNREACHABLE(); + return gl::InternalError(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, - ShaderType type, + gl::ShaderType type, const std::vector &streamOutVaryings, bool separatedOutputBuffers, - const D3DCompilerWorkarounds &workarounds, + const angle::CompilerWorkaroundsD3D &workarounds, ShaderExecutableD3D **outExectuable) { - const char *profileType = NULL; + std::stringstream profileStream; + switch (type) { - case SHADER_VERTEX: - profileType = "vs"; - break; - case SHADER_PIXEL: - profileType = "ps"; - break; - case SHADER_GEOMETRY: - profileType = "gs"; - break; - default: - UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + case gl::SHADER_VERTEX: + profileStream << "vs"; + break; + case gl::SHADER_FRAGMENT: + profileStream << "ps"; + break; + case gl::SHADER_GEOMETRY: + profileStream << "gs"; + break; + case gl::SHADER_COMPUTE: + profileStream << "cs"; + break; + default: + UNREACHABLE(); + return gl::InternalError(); } - std::string profile = FormatString("%s_%d_%d%s", profileType, getMajorShaderModel(), getMinorShaderModel(), getShaderModelSuffix().c_str()); + profileStream << "_" << getMajorShaderModel() << "_" << getMinorShaderModel() + << getShaderModelSuffix(); + std::string profile = profileStream.str(); UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; @@ -3260,11 +2944,12 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, if (workarounds.enableIEEEStrictness) flags |= D3DCOMPILE_IEEE_STRICTNESS; - // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders + // when it would otherwise pass with alternative options. // Try the default flags first and if compilation fails, try some alternatives. std::vector configs; - configs.push_back(CompileConfig(flags, "default" )); - configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation" )); + configs.push_back(CompileConfig(flags, "default")); + configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_VALIDATION, "skip validation")); configs.push_back(CompileConfig(flags | D3DCOMPILE_SKIP_OPTIMIZATION, "skip optimization")); if (getMajorShaderModel() == 4 && getShaderModelSuffix() != "") @@ -3276,26 +2961,26 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, CompileConfig(flags | D3DCOMPILE_AVOID_FLOW_CONTROL, "avoid flow control")); } - D3D_SHADER_MACRO loopMacros[] = { {"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0} }; + D3D_SHADER_MACRO loopMacros[] = {{"ANGLE_ENABLE_LOOP_FLATTEN", "1"}, {0, 0}}; - ID3DBlob *binary = NULL; + // TODO(jmadill): Use ComPtr? + ID3DBlob *binary = nullptr; std::string debugInfo; - gl::Error error = mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, &debugInfo); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mCompiler.compileToBinary(infoLog, shaderHLSL, profile, configs, loopMacros, &binary, + &debugInfo)); - // It's possible that binary is NULL if the compiler failed in all configurations. Set the executable to NULL - // and return GL_NO_ERROR to signify that there was a link error but the internal state is still OK. + // It's possible that binary is NULL if the compiler failed in all configurations. Set the + // executable to NULL and return GL_NO_ERROR to signify that there was a link error but the + // internal state is still OK. if (!binary) { - *outExectuable = NULL; - return gl::Error(GL_NO_ERROR); + *outExectuable = nullptr; + return gl::NoError(); } - error = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, - streamOutVaryings, separatedOutputBuffers, outExectuable); + gl::Error error = loadExecutable(reinterpret_cast(binary->GetBufferPointer()), + binary->GetBufferSize(), type, streamOutVaryings, + separatedOutputBuffers, outExectuable); SafeRelease(binary); if (error.isError()) @@ -3308,12 +2993,17 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, (*outExectuable)->appendDebugInfo(debugInfo); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +gl::Error Renderer11::ensureHLSLCompilerInitialized() +{ + return mCompiler.ensureInitialized(); } UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize) { - return new UniformStorage11(this, storageSize); + return new UniformStorage11(storageSize); } VertexBuffer *Renderer11::createVertexBuffer() @@ -3326,45 +3016,20 @@ IndexBuffer *Renderer11::createIndexBuffer() return new IndexBuffer11(this); } -BufferImpl *Renderer11::createBuffer() +StreamProducerImpl *Renderer11::createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) { - Buffer11 *buffer = new Buffer11(this); - mAliveBuffers.insert(buffer); - return buffer; -} - -VertexArrayImpl *Renderer11::createVertexArray(const gl::VertexArray::Data &data) -{ - return new VertexArray11(data); -} - -QueryImpl *Renderer11::createQuery(GLenum type) -{ - return new Query11(this, type); -} - -FenceNVImpl *Renderer11::createFenceNV() -{ - return new FenceNV11(this); -} - -FenceSyncImpl *Renderer11::createFenceSync() -{ - return new FenceSync11(this); -} - -TransformFeedbackImpl* Renderer11::createTransformFeedback() -{ - return new TransformFeedbackD3D(); + return new StreamProducerNV12(this); } bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const { - ASSERT(getRendererExtensions().pixelBufferObject); + ASSERT(getNativeExtensions().pixelBufferObject); - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); - const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat, mRenderer11DeviceCaps); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat); + const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat); + const d3d11::Format &d3d11FormatInfo = + d3d11::Format::Get(internalFormat, mRenderer11DeviceCaps); // sRGB formats do not work with D3D11 buffer SRVs if (internalFormatInfo.colorEncoding == GL_SRGB) @@ -3385,7 +3050,19 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const } // We don't support formats which we can't represent without conversion - if (dxgiFormatInfo.internalFormat != internalFormat) + if (d3d11FormatInfo.format().glInternalFormat != internalFormat) + { + return false; + } + + // Buffer SRV creation for this format was not working on Windows 10. + if (d3d11FormatInfo.texFormat == DXGI_FORMAT_B5G5R5A1_UNORM) + { + return false; + } + + // This format is not supported as a buffer SRV. + if (d3d11FormatInfo.texFormat == DXGI_FORMAT_A8_UNORM) { return false; } @@ -3393,11 +3070,17 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const return true; } -gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +gl::Error Renderer11::fastCopyBufferToTexture(const gl::Context *context, + const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea) { ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); - return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea); + return mPixelTransfer->copyBufferToTexture(context, unpack, offset, destRenderTarget, + destinationFormat, sourcePixelsType, destArea); } ImageD3D *Renderer11::createImage() @@ -3405,31 +3088,44 @@ ImageD3D *Renderer11::createImage() return new Image11(this); } -gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src) +gl::Error Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src) { Image11 *dest11 = GetAs(dest); - Image11 *src11 = GetAs(src); - return Image11::generateMipmap(dest11, src11); + Image11 *src11 = GetAs(src); + return Image11::GenerateMipmap(context, dest11, src11, mRenderer11DeviceCaps); } -gl::Error Renderer11::generateMipmapsUsingD3D(TextureStorage *storage, - const gl::TextureState &textureState) +gl::Error Renderer11::generateMipmapUsingD3D(const gl::Context *context, + 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; - } + const d3d11::SharedSRV *srv = nullptr; + ANGLE_TRY(storage11->getSRVLevels(context, textureState.getEffectiveBaseLevel(), + textureState.getEffectiveMaxLevel(), &srv)); + + mDeviceContext->GenerateMips(srv->get()); - mDeviceContext->GenerateMips(srv); + return gl::NoError(); +} - return gl::Error(GL_NO_ERROR); +gl::Error Renderer11::copyImage(const gl::Context *context, + ImageD3D *dest, + ImageD3D *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) +{ + Image11 *dest11 = GetAs(dest); + Image11 *src11 = GetAs(source); + return Image11::CopyImage(context, dest11, src11, sourceRect, destOffset, unpackFlipY, + unpackPremultiplyAlpha, unpackUnmultiplyAlpha, mRenderer11DeviceCaps); } TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain) @@ -3438,53 +3134,75 @@ TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain) return new TextureStorage11_2D(this, swapChain11); } -TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage) +TextureStorage *Renderer11::createTextureStorageEGLImage(EGLImageD3D *eglImage, + RenderTargetD3D *renderTargetD3D) { - return new TextureStorage11_EGLImage(this, eglImage); + return new TextureStorage11_EGLImage(this, eglImage, GetAs(renderTargetD3D)); } -TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) +TextureStorage *Renderer11::createTextureStorageExternal( + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) { - return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, hintLevelZeroOnly); + return new TextureStorage11_External(this, stream, desc); } -TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) +TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + int levels, + bool hintLevelZeroOnly) { - return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly); + return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, + hintLevelZeroOnly); } -TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, + bool renderTarget, + int size, + int levels, + bool hintLevelZeroOnly) { - return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, levels); + return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, + hintLevelZeroOnly); } -TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) { - return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); + return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, + levels); } -TextureImpl *Renderer11::createTexture(GLenum target) +TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) { - switch(target) - { - case GL_TEXTURE_2D: return new TextureD3D_2D(this); - case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); - case GL_TEXTURE_3D: return new TextureD3D_3D(this); - case GL_TEXTURE_2D_ARRAY: return new TextureD3D_2DArray(this); - default: - UNREACHABLE(); - } - - return NULL; + return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, + levels); } -RenderbufferImpl *Renderer11::createRenderbuffer() +TextureStorage *Renderer11::createTextureStorage2DMultisample(GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations) { - RenderbufferD3D *renderbuffer = new RenderbufferD3D(this); - return renderbuffer; + return new TextureStorage11_2DMultisample(this, internalformat, width, height, levels, samples, + fixedSampleLocations); } -gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAttachment, +gl::Error Renderer11::readFromAttachment(const gl::Context *context, + const gl::FramebufferAttachment &srcAttachment, const gl::Rectangle &sourceArea, GLenum format, GLenum type, @@ -3497,17 +3215,11 @@ gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAtt 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()); + RenderTarget11 *rt11 = nullptr; + ANGLE_TRY(srcAttachment.getRenderTarget(context, &rt11)); + ASSERT(rt11->getTexture().valid()); - TextureHelper11 textureHelper = TextureHelper11::MakeAndReference(rt11->getTexture()); + const TextureHelper11 &textureHelper = rt11->getTexture(); unsigned int sourceSubResource = rt11->getSubresourceIndex(); const gl::Extents &texSize = textureHelper.getExtents(); @@ -3535,52 +3247,42 @@ gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAtt if (safeArea.width == 0 || safeArea.height == 0) { // no work to do - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Extents safeSize(safeArea.width, safeArea.height, 1); - auto errorOrResult = CreateStagingTexture(textureHelper.getTextureType(), - textureHelper.getFormat(), safeSize, mDevice); - if (errorOrResult.isError()) - { - return errorOrResult.getError(); - } + TextureHelper11 stagingHelper; + ANGLE_TRY_RESULT( + createStagingTexture(textureHelper.getTextureType(), textureHelper.getFormatSet(), safeSize, + StagingAccess::READ), + stagingHelper); - 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) + if (textureHelper.is2D() && textureHelper.getSampleCount() > 1) { D3D11_TEXTURE2D_DESC resolveDesc; resolveDesc.Width = static_cast(texSize.width); resolveDesc.Height = static_cast(texSize.height); - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; resolveDesc.Format = textureHelper.getFormat(); - resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Count = 1; resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = D3D11_USAGE_DEFAULT; - resolveDesc.BindFlags = 0; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; - ID3D11Texture2D *resolveTex2D = nullptr; - HRESULT result = mDevice->CreateTexture2D(&resolveDesc, nullptr, &resolveTex2D); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, - "Renderer11::readTextureData failed to create internal resolve " - "texture for ReadPixels, HRESULT: 0x%X.", - result); - } + ANGLE_TRY( + allocateTexture(resolveDesc, textureHelper.getFormatSet(), &resolvedTextureHelper)); - mDeviceContext->ResolveSubresource(resolveTex2D, 0, textureHelper.getTexture2D(), + mDeviceContext->ResolveSubresource(resolvedTextureHelper.get(), 0, textureHelper.get(), sourceSubResource, textureHelper.getFormat()); - resolvedTextureHelper = TextureHelper11::MakeAndReference(resolveTex2D); sourceSubResource = 0; srcTexture = &resolvedTextureHelper; @@ -3594,132 +3296,66 @@ gl::Error Renderer11::readFromAttachment(const gl::FramebufferAttachment &srcAtt // Select the correct layer from a 3D attachment srcBox.front = 0; - if (textureHelper.getTextureType() == GL_TEXTURE_3D) + if (textureHelper.is3D()) { srcBox.front = static_cast(srcAttachment.layer()); } srcBox.back = srcBox.front + 1; - mDeviceContext->CopySubresourceRegion(stagingHelper.getResource(), 0, 0, 0, 0, - srcTexture->getResource(), sourceSubResource, &srcBox); - - if (invertTexture) - { - gl::PixelPackState invertTexturePack; - - // 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; - - PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, 0); - error = packPixels(stagingHelper, packParams, pixelsOut); + mDeviceContext->CopySubresourceRegion(stagingHelper.get(), 0, 0, 0, 0, srcTexture->get(), + sourceSubResource, &srcBox); - invertTexturePack.pixelBuffer.set(nullptr); - - return error; - } - else + gl::Buffer *packBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack); + if (!invertTexture) { - PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); + PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, packBuffer, 0); return packPixels(stagingHelper, packParams, pixelsOut); } + + // 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 + gl::PixelPackState invertTexturePack; + invertTexturePack.alignment = pack.alignment; + invertTexturePack.reverseRowOrder = !pack.reverseRowOrder; + + PackPixelsParams packParams(safeArea, format, type, outputPitch, invertTexturePack, packBuffer, + 0); + gl::Error error = packPixels(stagingHelper, packParams, pixelsOut); + ANGLE_TRY(error); + return gl::NoError(); } gl::Error Renderer11::packPixels(const TextureHelper11 &textureHelper, const PackPixelsParams ¶ms, uint8_t *pixelsOut) { - ID3D11Resource *readResource = textureHelper.getResource(); + ID3D11Resource *readResource = textureHelper.get(); D3D11_MAPPED_SUBRESOURCE mapping; HRESULT hr = mDeviceContext->Map(readResource, 0, D3D11_MAP_READ, 0, &mapping); if (FAILED(hr)) { ASSERT(hr == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal texture for reading, result: 0x%X.", hr); - } - - uint8_t *source; - int inputPitch; - if (params.pack.reverseRowOrder) - { - source = static_cast(mapping.pData) + mapping.RowPitch * (params.area.height - 1); - inputPitch = -static_cast(mapping.RowPitch); - } - else - { - source = static_cast(mapping.pData); - inputPitch = static_cast(mapping.RowPitch); - } - - 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) - { - uint8_t *dest = pixelsOut + params.offset; - for (int y = 0; y < params.area.height; y++) - { - memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourceFormatInfo.pixelBytes); - } + return gl::OutOfMemory() << "Failed to map internal texture for reading, " << gl::FmtHR(hr); } - else - { - ColorCopyFunction fastCopyFunc = - dxgiFormatInfo.getFastCopyFunction(params.format, params.type); - GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(params.format, params.type); - const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat); - - if (fastCopyFunc) - { - // Fast copy is possible through some special function - for (int y = 0; y < params.area.height; y++) - { - for (int x = 0; x < params.area.width; x++) - { - uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; - - fastCopyFunc(src, dest); - } - } - } - else - { - ColorReadFunction colorReadFunction = dxgiFormatInfo.colorReadFunction; - ColorWriteFunction colorWriteFunction = GetColorWriteFunction(params.format, params.type); - uint8_t temp[16]; // Maximum size of any Color type used. - static_assert(sizeof(temp) >= sizeof(gl::ColorF) && - sizeof(temp) >= sizeof(gl::ColorUI) && - sizeof(temp) >= sizeof(gl::ColorI), - "Unexpected size of gl::Color struct."); + uint8_t *source = static_cast(mapping.pData); + int inputPitch = static_cast(mapping.RowPitch); - for (int y = 0; y < params.area.height; y++) - { - for (int x = 0; x < params.area.width; x++) - { - uint8_t *dest = pixelsOut + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes; - const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; + const auto &formatInfo = textureHelper.getFormatSet(); + ASSERT(formatInfo.format().glInternalFormat != GL_NONE); - // readFunc and writeFunc will be using the same type of color, CopyTexImage - // will not allow the copy otherwise. - colorReadFunction(src, temp); - colorWriteFunction(temp, dest); - } - } - } - } + PackPixels(params, formatInfo.format(), inputPitch, source, pixelsOut); mDeviceContext->Unmap(readResource, 0); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, +gl::Error Renderer11::blitRenderbufferRect(const gl::Context *context, + const gl::Rectangle &readRectIn, const gl::Rectangle &drawRectIn, RenderTargetD3D *readRenderTarget, RenderTargetD3D *drawRenderTarget, @@ -3735,63 +3371,64 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, ASSERT(colorBlit != (depthBlit || stencilBlit)); RenderTarget11 *drawRenderTarget11 = GetAs(drawRenderTarget); - if (!drawRenderTarget) + if (!drawRenderTarget11) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal draw render target from the draw framebuffer."); + return gl::OutOfMemory() + << "Failed to retrieve the internal draw render target from the draw framebuffer."; } - ID3D11Resource *drawTexture = drawRenderTarget11->getTexture(); - unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); - ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView(); - ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView(); + const TextureHelper11 &drawTexture = drawRenderTarget11->getTexture(); + unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); RenderTarget11 *readRenderTarget11 = GetAs(readRenderTarget); - if (!readRenderTarget) + if (!readRenderTarget11) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target from the read framebuffer."); + return gl::OutOfMemory() + << "Failed to retrieve the internal read render target from the read framebuffer."; } - ID3D11Resource *readTexture = NULL; - ID3D11ShaderResourceView *readSRV = NULL; - unsigned int readSubresource = 0; - if (readRenderTarget->getSamples() > 0) + TextureHelper11 readTexture; + unsigned int readSubresource = 0; + d3d11::SharedSRV readSRV; + + if (readRenderTarget->isMultisampled()) { - ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture(); - ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject(unresolvedResource); + ANGLE_TRY_RESULT( + resolveMultisampledTexture(context, readRenderTarget11, depthBlit, stencilBlit), + readTexture); - if (unresolvedTexture) + if (!stencilBlit) { - readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex()); - readSubresource = 0; + const auto &readFormatSet = readTexture.getFormatSet(); - SafeRelease(unresolvedTexture); + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; + viewDesc.Format = readFormatSet.srvFormat; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + viewDesc.Texture2D.MipLevels = 1; + viewDesc.Texture2D.MostDetailedMip = 0; - HRESULT hresult = mDevice->CreateShaderResourceView(readTexture, NULL, &readSRV); - if (FAILED(hresult)) - { - SafeRelease(readTexture); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create shader resource view to resolve multisampled framebuffer."); - } + ANGLE_TRY(allocateResource(viewDesc, readTexture.get(), &readSRV)); } } else { - readTexture = readRenderTarget11->getTexture(); - readTexture->AddRef(); + ASSERT(readRenderTarget11); + readTexture = readRenderTarget11->getTexture(); readSubresource = readRenderTarget11->getSubresourceIndex(); - readSRV = readRenderTarget11->getShaderResourceView(); - readSRV->AddRef(); + readSRV = readRenderTarget11->getBlitShaderResourceView().makeCopy(); + if (!readSRV.valid()) + { + ASSERT(depthBlit || stencilBlit); + readSRV = readRenderTarget11->getShaderResourceView().makeCopy(); + } + ASSERT(readSRV.valid()); } - if (!readTexture || !readSRV) - { - SafeRelease(readTexture); - SafeRelease(readSRV); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the internal read render target view from the read render target."); - } + // Stencil blits don't use shaders. + ASSERT(readSRV.valid() || stencilBlit); - gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); - gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + const gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + const 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 @@ -3801,8 +3438,32 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, // by internally scaling the read and draw rectangles. gl::Rectangle readRect = readRectIn; gl::Rectangle drawRect = drawRectIn; - auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) + + auto flip = [](int val) { return val >= 0 ? 1 : -1; }; + + if (readRect.x > readSize.width && readRect.width < 0) + { + int delta = readRect.x - readSize.width; + readRect.x -= delta; + readRect.width += delta; + + int drawDelta = delta * flip(drawRect.width); + drawRect.x += drawDelta; + drawRect.width -= drawDelta; + } + + if (readRect.y > readSize.height && readRect.height < 0) { + int delta = readRect.y - readSize.height; + readRect.y -= delta; + readRect.height += delta; + + int drawDelta = delta * flip(drawRect.height); + drawRect.y += drawDelta; + drawRect.height -= drawDelta; + } + + auto readToDrawX = [&drawRectIn, &readRectIn](int readOffset) { double readToDrawScale = static_cast(drawRectIn.width) / static_cast(readRectIn.width); return static_cast(round(static_cast(readOffset) * readToDrawScale)); @@ -3818,8 +3479,7 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, drawRect.width -= drawOffset; } - auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) - { + auto readToDrawY = [&drawRectIn, &readRectIn](int readOffset) { double readToDrawScale = static_cast(drawRectIn.height) / static_cast(readRectIn.height); return static_cast(round(static_cast(readOffset) * readToDrawScale)); @@ -3853,24 +3513,41 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, drawRect.height += drawOffset; } - bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL); + if (readRect.x1() > readSize.width) + { + int delta = readRect.x1() - readSize.width; + readRect.width -= delta; + drawRect.width -= delta * flip(drawRect.width); + } + + if (readRect.y1() > readSize.height) + { + int delta = readRect.y1() - readSize.height; + readRect.height -= delta; + drawRect.height -= delta * flip(drawRect.height); + } + + bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, nullptr); - const auto &destFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()); - const auto &srcFormatInfo = gl::GetInternalFormatInfo(readRenderTarget->getInternalFormat()); - const auto &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat()); + const auto &destFormatInfo = + gl::GetSizedInternalFormatInfo(drawRenderTarget->getInternalFormat()); + const auto &srcFormatInfo = + gl::GetSizedInternalFormatInfo(readRenderTarget->getInternalFormat()); + const auto &formatSet = drawRenderTarget11->getFormatSet(); + const auto &nativeFormat = formatSet.format(); // 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.red = + (srcFormatInfo.redBits > 0) && (destFormatInfo.redBits == 0) && (nativeFormat.redBits > 0); colorMask.green = (srcFormatInfo.greenBits > 0) && (destFormatInfo.greenBits == 0) && - (dxgiFormatInfo.greenBits > 0); + (nativeFormat.greenBits > 0); colorMask.blue = (srcFormatInfo.blueBits > 0) && (destFormatInfo.blueBits == 0) && - (dxgiFormatInfo.blueBits > 0); + (nativeFormat.blueBits > 0); colorMask.alpha = (srcFormatInfo.alphaBits > 0) && (destFormatInfo.alphaBits == 0) && - (dxgiFormatInfo.alphaBits > 0); + (nativeFormat.alphaBits > 0); // We only currently support masking off the alpha channel. bool colorMaskingNeeded = colorMask.alpha; @@ -3884,18 +3561,19 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; - bool flipRequired = readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0; + bool flipRequired = + readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0; bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width || readRect.y < 0 || readRect.y + readRect.height > readSize.height || drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; - bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit); + bool partialDSBlit = + (nativeFormat.depthBits > 0 && depthBlit) != (nativeFormat.stencilBits > 0 && stencilBlit); - gl::Error result(GL_NO_ERROR); - - if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() && + if (readRenderTarget11->getFormatSet().formatID == + drawRenderTarget11->getFormatSet().formatID && !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && !colorMaskingNeeded && (!(depthBlit || stencilBlit) || wholeBufferCopy)) { @@ -3903,16 +3581,17 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, UINT dstY = drawRect.y; D3D11_BOX readBox; - readBox.left = readRect.x; - readBox.right = readRect.x + readRect.width; - readBox.top = readRect.y; + readBox.left = readRect.x; + readBox.right = readRect.x + readRect.width; + readBox.top = readRect.y; readBox.bottom = readRect.y + readRect.height; - readBox.front = 0; - readBox.back = 1; + readBox.front = 0; + readBox.back = 1; if (scissorNeeded) { - // drawRect is guaranteed to have positive width and height because stretchRequired is false. + // drawRect is guaranteed to have positive width and height because stretchRequired is + // false. ASSERT(drawRect.width >= 0 || drawRect.height >= 0); if (drawRect.x < scissor->x) @@ -3937,11 +3616,10 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox // We also require complete framebuffer copies for depth-stencil blit. - D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; + D3D11_BOX *pSrcBox = wholeBufferCopy ? nullptr : &readBox; - mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0, - readTexture, readSubresource, pSrcBox); - result = gl::Error(GL_NO_ERROR); + mDeviceContext->CopySubresourceRegion(drawTexture.get(), drawSubresource, dstX, dstY, 0, + readTexture.get(), readSubresource, pSrcBox); } else { @@ -3950,47 +3628,56 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRectIn, if (depthBlit && stencilBlit) { - result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, - drawTexture, drawSubresource, drawArea, drawSize, - scissor); + ANGLE_TRY(mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor)); } else if (depthBlit) { - result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize, - scissor); + const d3d11::DepthStencilView &drawDSV = drawRenderTarget11->getDepthStencilView(); + ASSERT(readSRV.valid()); + ANGLE_TRY(mBlit->copyDepth(context, readSRV, readArea, readSize, drawDSV, drawArea, + drawSize, scissor)); } else if (stencilBlit) { - result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize, - drawTexture, drawSubresource, drawArea, drawSize, - scissor); + ANGLE_TRY(mBlit->copyStencil(context, readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor)); } else { + const d3d11::RenderTargetView &drawRTV = drawRenderTarget11->getRenderTargetView(); + // 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, destFormatInfo.format, filter, maskOffAlpha); + ASSERT(readSRV.valid()); + ANGLE_TRY(mBlit->copyTexture( + context, readSRV, readArea, readSize, srcFormatInfo.format, drawRTV, drawArea, + drawSize, scissor, destFormatInfo.format, filter, maskOffAlpha, false, false)); } } - SafeRelease(readTexture); - SafeRelease(readSRV); - - return result; + return gl::NoError(); } bool Renderer11::isES3Capable() const { - return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel) > 2); -}; + return (d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel).major > 2); +} + +RendererClass Renderer11::getRendererClass() const +{ + return RENDERER_D3D11; +} void Renderer11::onSwap() { // Send histogram updates every half hour const double kHistogramUpdateInterval = 30 * 60; - const double currentTime = ANGLEPlatformCurrent()->monotonicallyIncreasingTime(); + auto *platform = ANGLEPlatformCurrent(); + const double currentTime = platform->monotonicallyIncreasingTime(platform); const double timeSinceLastUpdate = currentTime - mLastHistogramUpdateTime; if (timeSinceLastUpdate > kHistogramUpdateInterval) @@ -4005,7 +3692,7 @@ void Renderer11::updateHistograms() // Update the buffer CPU memory histogram { size_t sizeSum = 0; - for (auto &buffer : mAliveBuffers) + for (const Buffer11 *buffer : mAliveBuffers) { sizeSum += buffer->getTotalCPUBufferMemoryBytes(); } @@ -4015,53 +3702,71 @@ void Renderer11::updateHistograms() } } +void Renderer11::onBufferCreate(const Buffer11 *created) +{ + mAliveBuffers.insert(created); +} + void Renderer11::onBufferDelete(const Buffer11 *deleted) { mAliveBuffers.erase(deleted); } -ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) +gl::ErrorOrResult Renderer11::resolveMultisampledTexture( + const gl::Context *context, + RenderTarget11 *renderTarget, + bool depth, + bool stencil) { - D3D11_TEXTURE2D_DESC textureDesc; - source->GetDesc(&textureDesc); + if (depth && !stencil) + { + return mBlit->resolveDepth(context, renderTarget); + } - if (textureDesc.SampleDesc.Count > 1) + if (stencil) { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = textureDesc.Usage; - resolveDesc.BindFlags = textureDesc.BindFlags; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; + return mBlit->resolveStencil(context, renderTarget, depth); + } - ID3D11Texture2D *resolveTexture = NULL; - HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); - if (FAILED(result)) - { - ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); - return NULL; - } + const auto &formatSet = renderTarget->getFormatSet(); - mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); - return resolveTexture; - } - else + ASSERT(renderTarget->isMultisampled()); + const d3d11::SharedSRV &sourceSRV = renderTarget->getShaderResourceView(); + D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; + sourceSRV.get()->GetDesc(&sourceSRVDesc); + ASSERT(sourceSRVDesc.ViewDimension == D3D_SRV_DIMENSION_TEXTURE2DMS); + + if (!mCachedResolveTexture.valid() || + mCachedResolveTexture.getExtents().width != renderTarget->getWidth() || + mCachedResolveTexture.getExtents().height != renderTarget->getHeight() || + mCachedResolveTexture.getFormat() != formatSet.texFormat) { - source->AddRef(); - return source; + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = renderTarget->getWidth(); + resolveDesc.Height = renderTarget->getHeight(); + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = formatSet.texFormat; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ANGLE_TRY(allocateTexture(resolveDesc, formatSet, &mCachedResolveTexture)); } + + mDeviceContext->ResolveSubresource(mCachedResolveTexture.get(), 0, + renderTarget->getTexture().get(), + renderTarget->getSubresourceIndex(), formatSet.texFormat); + return mCachedResolveTexture; } bool Renderer11::getLUID(LUID *adapterLuid) const { adapterLuid->HighPart = 0; - adapterLuid->LowPart = 0; + adapterLuid->LowPart = 0; if (!mDxgiAdapter) { @@ -4078,45 +3783,70 @@ bool Renderer11::getLUID(LUID *adapterLuid) const return true; } -VertexConversionType Renderer11::getVertexConversionType(gl::VertexFormatType vertexFormatType) const +VertexConversionType Renderer11::getVertexConversionType( + gl::VertexFormatType vertexFormatType) const { - return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel).conversionType; + return d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel) + .conversionType; } GLenum Renderer11::getVertexComponentType(gl::VertexFormatType vertexFormatType) const { - return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel).nativeFormat).componentType; + const auto &format = + d3d11::GetVertexFormatInfo(vertexFormatType, mRenderer11DeviceCaps.featureLevel); + return d3d11::GetComponentType(format.nativeFormat); } -void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, - gl::Extensions *outExtensions, gl::Limitations *outLimitations) const +gl::ErrorOrResult Renderer11::getVertexSpaceRequired( + const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) const { - d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps, - outExtensions, outLimitations); -} + if (!attrib.enabled) + { + return 16u; + } -WorkaroundsD3D Renderer11::generateWorkarounds() const -{ - return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps.featureLevel); + unsigned int elementCount = 0; + const unsigned int divisor = binding.getDivisor(); + if (instances == 0 || divisor == 0) + { + elementCount = count; + } + else + { + // Round up to divisor, if possible + elementCount = UnsignedCeilDivide(static_cast(instances), divisor); + } + + gl::VertexFormatType formatType = gl::GetVertexFormatType(attrib); + const D3D_FEATURE_LEVEL featureLevel = mRenderer11DeviceCaps.featureLevel; + const d3d11::VertexFormat &vertexFormatInfo = + d3d11::GetVertexFormatInfo(formatType, featureLevel); + const d3d11::DXGIFormatSize &dxgiFormatInfo = + d3d11::GetDXGIFormatSizeInfo(vertexFormatInfo.nativeFormat); + unsigned int elementSize = dxgiFormatInfo.pixelBytes; + if (elementSize > std::numeric_limits::max() / elementCount) + { + return gl::OutOfMemory() << "New vertex buffer size would result in an overflow."; + } + + return elementSize * elementCount; } -void Renderer11::createAnnotator() +void Renderer11::generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, + gl::Extensions *outExtensions, + gl::Limitations *outLimitations) const { - // 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 + d3d11_gl::GenerateCaps(mDevice, mDeviceContext, mRenderer11DeviceCaps, outCaps, outTextureCaps, + outExtensions, outLimitations); } -gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) +angle::WorkaroundsD3D Renderer11::generateWorkarounds() const { - return mStateManager.clearTextures(samplerType, rangeStart, rangeEnd); + return d3d11::GenerateWorkarounds(mRenderer11DeviceCaps, mAdapterDescription); } egl::Error Renderer11::getEGLDevice(DeviceImpl **device) @@ -4136,6 +3866,224 @@ egl::Error Renderer11::getEGLDevice(DeviceImpl **device) } *device = static_cast(mEGLDevice); - return egl::Error(EGL_SUCCESS); + return egl::NoError(); +} + +ContextImpl *Renderer11::createContext(const gl::ContextState &state) +{ + return new Context11(state, this); +} + +FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::FramebufferState &state) +{ + return new Framebuffer11(state, this); +} + +gl::Error Renderer11::getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut) +{ + if (!mScratchMemoryBuffer.get(requestedSize, bufferOut)) + { + return gl::OutOfMemory() << "Failed to allocate internal buffer."; + } + return gl::NoError(); +} + +gl::Version Renderer11::getMaxSupportedESVersion() const +{ + return d3d11_gl::GetMaximumClientVersion(mRenderer11DeviceCaps.featureLevel); +} + +gl::DebugAnnotator *Renderer11::getAnnotator() +{ + return mAnnotator; +} + +gl::Error Renderer11::applyComputeShader(const gl::Context *context) +{ + ANGLE_TRY(ensureHLSLCompilerInitialized()); + + const auto &glState = context->getGLState(); + ProgramD3D *programD3D = GetImplAs(glState.getProgram()); + + ShaderExecutableD3D *computeExe = nullptr; + ANGLE_TRY(programD3D->getComputeExecutable(&computeExe)); + ASSERT(computeExe != nullptr); + + mStateManager.setComputeShader(&GetAs(computeExe)->getComputeShader()); + ANGLE_TRY(mStateManager.applyComputeUniforms(programD3D)); + + return gl::NoError(); +} + +gl::Error Renderer11::dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) +{ + ANGLE_TRY(mStateManager.updateStateForCompute(context, numGroupsX, numGroupsY, numGroupsZ)); + ANGLE_TRY(applyComputeShader(context)); + + mDeviceContext->Dispatch(numGroupsX, numGroupsY, numGroupsZ); + + return gl::NoError(); +} + +gl::ErrorOrResult Renderer11::createStagingTexture( + ResourceType textureType, + const d3d11::Format &formatSet, + const gl::Extents &size, + StagingAccess readAndWriteAccess) +{ + if (textureType == ResourceType::Texture2D) + { + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = size.width; + stagingDesc.Height = size.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = formatSet.texFormat; + 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; + + if (readAndWriteAccess == StagingAccess::READ_WRITE) + { + stagingDesc.CPUAccessFlags |= D3D11_CPU_ACCESS_WRITE; + } + + TextureHelper11 stagingTex; + ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex)); + return stagingTex; + } + ASSERT(textureType == ResourceType::Texture3D); + + D3D11_TEXTURE3D_DESC stagingDesc; + stagingDesc.Width = size.width; + stagingDesc.Height = size.height; + stagingDesc.Depth = 1; + stagingDesc.MipLevels = 1; + stagingDesc.Format = formatSet.texFormat; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + TextureHelper11 stagingTex; + ANGLE_TRY(allocateTexture(stagingDesc, formatSet, &stagingTex)); + return stagingTex; +} + +gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE2D_DESC &desc, + const d3d11::Format &format, + const D3D11_SUBRESOURCE_DATA *initData, + TextureHelper11 *textureOut) +{ + d3d11::Texture2D texture; + ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture)); + textureOut->init(std::move(texture), desc, format); + return gl::NoError(); +} + +gl::Error Renderer11::allocateTexture(const D3D11_TEXTURE3D_DESC &desc, + const d3d11::Format &format, + const D3D11_SUBRESOURCE_DATA *initData, + TextureHelper11 *textureOut) +{ + d3d11::Texture3D texture; + ANGLE_TRY(mResourceManager11.allocate(this, &desc, initData, &texture)); + textureOut->init(std::move(texture), desc, format); + return gl::NoError(); +} + +gl::Error Renderer11::getBlendState(const d3d11::BlendStateKey &key, + const d3d11::BlendState **outBlendState) +{ + return mStateCache.getBlendState(this, key, outBlendState); +} + +gl::Error Renderer11::getRasterizerState(const gl::RasterizerState &rasterState, + bool scissorEnabled, + ID3D11RasterizerState **outRasterizerState) +{ + return mStateCache.getRasterizerState(this, rasterState, scissorEnabled, outRasterizerState); } + +gl::Error Renderer11::getDepthStencilState(const gl::DepthStencilState &dsState, + const d3d11::DepthStencilState **outDSState) +{ + return mStateCache.getDepthStencilState(this, dsState, outDSState); +} + +gl::Error Renderer11::getSamplerState(const gl::SamplerState &samplerState, + ID3D11SamplerState **outSamplerState) +{ + return mStateCache.getSamplerState(this, samplerState, outSamplerState); +} + +gl::Error Renderer11::clearRenderTarget(RenderTargetD3D *renderTarget, + const gl::ColorF &clearColorValue, + const float clearDepthValue, + const unsigned int clearStencilValue) +{ + RenderTarget11 *rt11 = GetAs(renderTarget); + + if (rt11->getDepthStencilView().valid()) + { + const auto &format = rt11->getFormatSet(); + const UINT clearFlags = (format.format().depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) | + (format.format().stencilBits ? D3D11_CLEAR_STENCIL : 0); + mDeviceContext->ClearDepthStencilView(rt11->getDepthStencilView().get(), clearFlags, + clearDepthValue, + static_cast(clearStencilValue)); + return gl::NoError(); + } + + ASSERT(rt11->getRenderTargetView().valid()); + ID3D11RenderTargetView *rtv = rt11->getRenderTargetView().get(); + + // There are complications with some types of RTV and FL 9_3 with ClearRenderTargetView. + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476388(v=vs.85).aspx + ASSERT(mRenderer11DeviceCaps.featureLevel > D3D_FEATURE_LEVEL_9_3 || !IsArrayRTV(rtv)); + + const auto &d3d11Format = rt11->getFormatSet(); + const auto &glFormat = gl::GetSizedInternalFormatInfo(renderTarget->getInternalFormat()); + + gl::ColorF safeClearColor = clearColorValue; + + if (d3d11Format.format().alphaBits > 0 && glFormat.alphaBits == 0) + { + safeClearColor.alpha = 1.0f; + } + + mDeviceContext->ClearRenderTargetView(rtv, &safeClearColor.red); + return gl::NoError(); +} + +bool Renderer11::canSelectViewInVertexShader() const +{ + return !getWorkarounds().selectViewInGeometryShader && + getRenderer11DeviceCaps().supportsVpRtIndexWriteFromVertexShader; +} + +gl::Error Renderer11::markTransformFeedbackUsage(const gl::Context *context) +{ + const gl::State &glState = context->getGLState(); + const gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback(); + for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++) + { + const gl::OffsetBindingPointer &binding = + transformFeedback->getIndexedBuffer(i); + if (binding.get() != nullptr) + { + BufferD3D *bufferD3D = GetImplAs(binding.get()); + ANGLE_TRY(bufferD3D->markTransformFeedbackUsage(context)); + } + } + + return gl::NoError(); } + +} // namespace rx 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 b4e7761ffc..a8c24e681b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h @@ -14,13 +14,14 @@ #include "libANGLE/AttributeMap.h" #include "libANGLE/angletypes.h" #include "libANGLE/renderer/d3d/HLSLCompiler.h" -#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/ProgramD3D.h" #include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.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" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" #include "libANGLE/renderer/d3d/d3d11/StateManager11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" namespace gl { @@ -28,36 +29,46 @@ class FramebufferAttachment; struct ImageIndex; } -struct ID3D11DeviceContext1; - namespace rx { - -class VertexDataManager; -class IndexDataManager; -class StreamingIndexBufferInterface; class Blit11; class Buffer11; class Clear11; +class Context11; +class IndexDataManager; +struct PackPixelsParams; class PixelTransfer11; class RenderTarget11; +class StreamingIndexBufferInterface; class Trim11; -struct PackPixelsParams; +class VertexDataManager; struct Renderer11DeviceCaps { + 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 + bool supportsDXGI1_2; // Support for DXGI 1.2 + bool supportsClearView; // Support for ID3D11DeviceContext1::ClearView + bool supportsConstantBufferOffsets; // Support for Constant buffer offset + bool supportsVpRtIndexWriteFromVertexShader; // VP/RT can be selected in the Vertex Shader + // stage. + bool supportsMultisampledDepthStencilSRVs; // D3D feature level 10.0 no longer allows creation + // of textures with both the bind SRV and DSV flags + // when multisampled. Textures will need to be + // resolved before reading. crbug.com/656989 + UINT B5G6R5support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G6R5_UNORM + UINT B5G6R5maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B5G6R5_UNORM + UINT B4G4R4A4support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B4G4R4A4_UNORM + UINT B4G4R4A4maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B4G4R4A4_UNORM + UINT B5G5R5A1support; // Bitfield of D3D11_FORMAT_SUPPORT values for DXGI_FORMAT_B5G5R5A1_UNORM + UINT B5G5R5A1maxSamples; // Maximum number of samples supported by DXGI_FORMAT_B5G5R5A1_UNORM + Optional driverVersion; // Four-part driver version number. }; enum { - MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, + MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 }; @@ -103,172 +114,244 @@ class Renderer11 : public RendererD3D { public: explicit Renderer11(egl::Display *display); - virtual ~Renderer11(); + ~Renderer11() override; egl::Error initialize() override; - virtual bool resetDevice(); + bool resetDevice() override; - egl::ConfigSet generateConfigs() const override; + egl::ConfigSet generateConfigs() override; void generateDisplayExtensions(egl::DisplayExtensions *outExtensions) const override; - gl::Error flush() override; - gl::Error finish() override; + ContextImpl *createContext(const gl::ContextState &state) override; + + gl::Error flush(); + gl::Error finish(); - SwapChainD3D *createSwapChain(NativeWindow nativeWindow, + bool isValidNativeWindow(EGLNativeWindowType window) const override; + NativeWindowD3D *createNativeWindow(EGLNativeWindowType window, + const egl::Config *config, + const egl::AttributeMap &attribs) const override; + + SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow, HANDLE shareHandle, + IUnknown *d3dTexture, 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 std::vector &vertexUniformBuffers, - const std::vector &fragmentUniformBuffers) override; - - 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; - 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; + EGLint orientation, + EGLint samples) override; + egl::Error getD3DTextureInfo(const egl::Config *configuration, + IUnknown *d3dTexture, + EGLint *width, + EGLint *height, + GLenum *fboFormat) const override; + egl::Error validateShareHandle(const egl::Config *config, + HANDLE shareHandle, + const egl::AttributeMap &attribs) const override; + + bool applyPrimitiveType(const gl::State &glState, GLenum mode, GLsizei count); // lost device bool testDeviceLost() override; bool testDeviceResettable() override; - std::string getRendererDescription() const override; + std::string getRendererDescription() const; DeviceIdentifier getAdapterIdentifier() const override; - virtual unsigned int getReservedVertexUniformVectors() const; - virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getReservedVertexUniformBuffers() const; - virtual unsigned int getReservedFragmentUniformBuffers() const; + unsigned int getReservedVertexUniformVectors() const; + unsigned int getReservedFragmentUniformVectors() const; + unsigned int getReservedVertexUniformBuffers() const; + unsigned int getReservedFragmentUniformBuffers() const; bool getShareHandleSupport() const; - virtual int getMajorShaderModel() const; + bool getNV12TextureSupport() const; + + int getMajorShaderModel() const override; int getMinorShaderModel() const override; std::string getShaderModelSuffix() const override; // Pixel operations - virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level); - virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level); - virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - const gl::Offset &destOffset, TextureStorage *storage, GLint level); + gl::Error copyImage2D(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImageCube(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum target, + GLint level) override; + gl::Error copyImage3D(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + gl::Error copyImage2DArray(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLint level) override; + + gl::Error copyTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + TextureStorage *storage, + GLenum destTarget, + GLint destLevel, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) override; + gl::Error copyCompressedTexture(const gl::Context *context, + const gl::Texture *source, + GLint sourceLevel, + TextureStorage *storage, + GLint destLevel) override; // RenderTarget creation - virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT); + gl::Error createRenderTarget(int width, + int height, + GLenum format, + GLsizei samples, + RenderTargetD3D **outRT) override; gl::Error createRenderTargetCopy(RenderTargetD3D *source, RenderTargetD3D **outRT) override; - // Framebuffer creation - FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override; - - // Shader creation - ShaderImpl *createShader(const gl::Shader::Data &data) override; - ProgramImpl *createProgram(const gl::Program::Data &data) override; - // Shader operations - gl::Error loadExecutable(const void *function, + gl::Error loadExecutable(const uint8_t *function, size_t length, - ShaderType type, + gl::ShaderType type, const std::vector &streamOutVaryings, bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) override; gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, - ShaderType type, + gl::ShaderType type, const std::vector &streamOutVaryings, bool separatedOutputBuffers, - const D3DCompilerWorkarounds &workarounds, + const angle::CompilerWorkaroundsD3D &workarounds, ShaderExecutableD3D **outExectuable) override; + gl::Error ensureHLSLCompilerInitialized() 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); - virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - - // Texture creation - virtual TextureImpl *createTexture(GLenum target); - - // Renderbuffer creation - virtual RenderbufferImpl *createRenderbuffer(); - - // Buffer creation - virtual BufferImpl *createBuffer(); - virtual VertexBuffer *createVertexBuffer(); - virtual IndexBuffer *createIndexBuffer(); - - // Vertex Array creation - VertexArrayImpl *createVertexArray(const gl::VertexArray::Data &data) override; - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type); - virtual FenceNVImpl *createFenceNV(); - virtual FenceSyncImpl *createFenceSync(); - - // Transform Feedback creation - virtual TransformFeedbackImpl* createTransformFeedback(); + ImageD3D *createImage() override; + gl::Error generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *source) override; + gl::Error generateMipmapUsingD3D(const gl::Context *context, + TextureStorage *storage, + const gl::TextureState &textureState) override; + gl::Error copyImage(const gl::Context *context, + ImageD3D *dest, + ImageD3D *source, + const gl::Rectangle &sourceRect, + const gl::Offset &destOffset, + bool unpackFlipY, + bool unpackPremultiplyAlpha, + bool unpackUnmultiplyAlpha) override; + TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) override; + TextureStorage *createTextureStorageEGLImage(EGLImageD3D *eglImage, + RenderTargetD3D *renderTargetD3D) override; + TextureStorage *createTextureStorageExternal( + egl::Stream *stream, + const egl::Stream::GLTextureDescription &desc) override; + TextureStorage *createTextureStorage2D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + int levels, + bool hintLevelZeroOnly) override; + TextureStorage *createTextureStorageCube(GLenum internalformat, + bool renderTarget, + int size, + int levels, + bool hintLevelZeroOnly) override; + TextureStorage *createTextureStorage3D(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) override; + TextureStorage *createTextureStorage2DArray(GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) override; + TextureStorage *createTextureStorage2DMultisample(GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations) override; + + VertexBuffer *createVertexBuffer() override; + IndexBuffer *createIndexBuffer() override; + + // Stream Creation + StreamProducerImpl *createStreamProducerD3DTextureNV12( + egl::Stream::ConsumerType consumerType, + const egl::AttributeMap &attribs) override; // 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; } + IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + + gl::Error getBlendState(const d3d11::BlendStateKey &key, + const d3d11::BlendState **outBlendState); + gl::Error getRasterizerState(const gl::RasterizerState &rasterState, + bool scissorEnabled, + ID3D11RasterizerState **outRasterizerState); + gl::Error getDepthStencilState(const gl::DepthStencilState &dsState, + const d3d11::DepthStencilState **outDSState); + gl::Error getSamplerState(const gl::SamplerState &samplerState, + ID3D11SamplerState **outSamplerState); Blit11 *getBlitter() { return mBlit; } Clear11 *getClearer() { return mClear; } + gl::DebugAnnotator *getAnnotator(); // Buffer-to-texture and Texture-to-buffer copies - virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; - virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget, - GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + bool supportsFastCopyBufferToTexture(GLenum internalFormat) const override; + gl::Error fastCopyBufferToTexture(const gl::Context *context, + const gl::PixelUnpackState &unpack, + unsigned int offset, + RenderTargetD3D *destRenderTarget, + GLenum destinationFormat, + GLenum sourcePixelsType, + const gl::Box &destArea) override; - void markAllStateDirty(); - void unapplyRenderTargets(); - void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); gl::Error packPixels(const TextureHelper11 &textureHelper, const PackPixelsParams ¶ms, uint8_t *pixelsOut); bool getLUID(LUID *adapterLuid) const override; - VertexConversionType getVertexConversionType(gl::VertexFormatType vertexFormatType) const override; + VertexConversionType getVertexConversionType( + gl::VertexFormatType vertexFormatType) const override; GLenum getVertexComponentType(gl::VertexFormatType vertexFormatType) const override; - gl::Error readFromAttachment(const gl::FramebufferAttachment &srcAttachment, + // Warning: you should ensure binding really matches attrib.bindingIndex before using this + // function. + gl::ErrorOrResult getVertexSpaceRequired(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, + GLsizei count, + GLsizei instances) const override; + + gl::Error readFromAttachment(const gl::Context *context, + const gl::FramebufferAttachment &srcAttachment, const gl::Rectangle &sourceArea, GLenum format, GLenum type, @@ -276,145 +359,175 @@ class Renderer11 : public RendererD3D 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); + gl::Error blitRenderbufferRect(const gl::Context *context, + 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; - const Renderer11DeviceCaps &getRenderer11DeviceCaps() { return mRenderer11DeviceCaps; }; + const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; }; - RendererClass getRendererClass() const override { return RENDERER_D3D11; } - InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; } + RendererClass getRendererClass() const override; StateManager11 *getStateManager() { return &mStateManager; } void onSwap(); + void onBufferCreate(const Buffer11 *created); void onBufferDelete(const Buffer11 *deleted); 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; + gl::Error drawArrays(const gl::Context *context, + GLenum mode, + GLint startVertex, + GLsizei count, + GLsizei instances); - void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override; + gl::Error drawElements(const gl::Context *context, + GLenum mode, + GLsizei count, + GLenum type, + const void *indices, + GLsizei instances); + + gl::Error drawArraysIndirect(const gl::Context *context, GLenum mode, const void *indirect); + gl::Error drawElementsIndirect(const gl::Context *context, + GLenum mode, + GLenum type, + const void *indirect); + + // Necessary hack for default framebuffers in D3D. + FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &state) override; + + gl::Error getScratchMemoryBuffer(size_t requestedSize, angle::MemoryBuffer **bufferOut); + + gl::Version getMaxSupportedESVersion() const override; + + gl::Error dispatchCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ); + gl::Error applyComputeShader(const gl::Context *context); + + gl::ErrorOrResult createStagingTexture(ResourceType textureType, + const d3d11::Format &formatSet, + const gl::Extents &size, + StagingAccess readAndWriteAccess); + + template + gl::Error allocateResource(const DescT &desc, ResourceT *resourceOut) + { + return mResourceManager11.allocate(this, &desc, nullptr, resourceOut); + } + + template + gl::Error allocateResource(const DescT &desc, InitDataT *initData, ResourceT *resourceOut) + { + return mResourceManager11.allocate(this, &desc, initData, resourceOut); + } + + template + gl::Error allocateResourceNoDesc(InitDataT *initData, ResourceT *resourceOut) + { + return mResourceManager11.allocate(this, nullptr, initData, resourceOut); + } + + template + gl::Error allocateTexture(const DescT &desc, + const d3d11::Format &format, + TextureHelper11 *textureOut) + { + return allocateTexture(desc, format, nullptr, textureOut); + } + + gl::Error allocateTexture(const D3D11_TEXTURE2D_DESC &desc, + const d3d11::Format &format, + const D3D11_SUBRESOURCE_DATA *initData, + TextureHelper11 *textureOut); + + gl::Error allocateTexture(const D3D11_TEXTURE3D_DESC &desc, + const d3d11::Format &format, + const D3D11_SUBRESOURCE_DATA *initData, + TextureHelper11 *textureOut); + + gl::Error clearRenderTarget(RenderTargetD3D *renderTarget, + const gl::ColorF &clearColorValue, + const float clearDepthValue, + const unsigned int clearStencilValue) override; + + bool canSelectViewInVertexShader() const 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, + void generateCaps(gl::Caps *outCaps, + gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions, gl::Limitations *outLimitations) const override; - WorkaroundsD3D generateWorkarounds() const override; + angle::WorkaroundsD3D generateWorkarounds() const override; - gl::Error drawLineLoop(const gl::Data &data, + gl::Error drawLineLoop(const gl::Context *context, GLsizei count, GLenum type, - const GLvoid *indices, - const TranslatedIndexData *indexInfo, + const void *indices, + int baseVertex, int instances); - gl::Error drawTriangleFan(const gl::Data &data, + gl::Error drawTriangleFan(const gl::Context *context, GLsizei count, GLenum type, - const GLvoid *indices, - int minIndex, + const void *indices, + int baseVertex, int instances); - ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); + gl::ErrorOrResult resolveMultisampledTexture(const gl::Context *context, + RenderTarget11 *renderTarget, + bool depth, + bool stencil); void populateRenderer11DeviceCaps(); void updateHistograms(); - HMODULE mD3d11Module; - HMODULE mDxgiModule; - HMODULE mDCompModule; - std::vector mAvailableFeatureLevels; - D3D_DRIVER_TYPE mRequestedDriverType; - bool mCreatedWithDeviceEXT; - DeviceD3D *mEGLDevice; + gl::Error copyImageInternal(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::Rectangle &sourceRect, + GLenum destFormat, + const gl::Offset &destOffset, + RenderTargetD3D *destRenderTarget); - HLSLCompiler mCompiler; + gl::SupportedSampleSet generateSampleSetForEGLConfig( + const gl::TextureCaps &colorBufferFormatCaps, + const gl::TextureCaps &depthStencilBufferFormatCaps) const; + HRESULT callD3D11CreateDevice(PFN_D3D11_CREATE_DEVICE createDevice, bool debug); egl::Error initializeD3DDevice(); - void initializeDevice(); + egl::Error initializeDevice(); void releaseDeviceResources(); void release(); d3d11::ANGLED3D11DeviceType getDeviceType() const; - RenderStateCache mStateCache; + gl::Error markTransformFeedbackUsage(const gl::Context *context); - // current render target states - uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; - uintptr_t mAppliedDSV; + HMODULE mD3d11Module; + HMODULE mDxgiModule; + HMODULE mDCompModule; + std::vector mAvailableFeatureLevels; + D3D_DRIVER_TYPE mRequestedDriverType; + bool mCreateDebugDevice; + bool mCreatedWithDeviceEXT; + DeviceD3D *mEGLDevice; - // Currently applied sampler states - std::vector mForceSetVertexSamplerStates; - std::vector mCurVertexSamplerStates; + HLSLCompiler mCompiler; - std::vector mForceSetPixelSamplerStates; - std::vector mCurPixelSamplerStates; + RenderStateCache mStateCache; StateManager11 mStateManager; - // Currently applied primitive topology - D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; - - // Currently applied index buffer - ID3D11Buffer *mAppliedIB; - DXGI_FORMAT mAppliedIBFormat; - unsigned int mAppliedIBOffset; - bool mAppliedIBChanged; - - // Currently applied transform feedback buffers - size_t mAppliedNumXFBBindings; - ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers - // in use for streamout - GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified - // buffer offsets to transform feedback - // buffers - UINT mCurrentD3DOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the D3D buffer offsets, - // which may differ from GLs, due - // to different append behavior - - // Currently applied shaders - uintptr_t mAppliedVertexShader; - uintptr_t mAppliedGeometryShader; - uintptr_t mAppliedPixelShader; - - 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_PixelConstants11 mAppliedPixelConstants; - ID3D11Buffer *mDriverConstantBufferPS; - ID3D11Buffer *mCurrentPixelConstantBuffer; - unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; - GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; - GLsizeiptr mCurrentConstantBufferPSSize[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS]; - - ID3D11Buffer *mCurrentGeometryConstantBuffer; - - // Vertex, index and input layouts - VertexDataManager *mVertexDataManager; - IndexDataManager *mIndexDataManager; - InputLayoutCache mInputLayoutCache; - StreamingIndexBufferInterface *mLineLoopIB; StreamingIndexBufferInterface *mTriangleFanIB; @@ -429,10 +542,10 @@ class Renderer11 : public RendererD3D Trim11 *mTrim; // Sync query - ID3D11Query *mSyncQuery; + d3d11::Query mSyncQuery; // Created objects state tracking - std::set mAliveBuffers; + std::set mAliveBuffers; double mLastHistogramUpdateTime; @@ -440,18 +553,24 @@ class Renderer11 : public RendererD3D Renderer11DeviceCaps mRenderer11DeviceCaps; ID3D11DeviceContext *mDeviceContext; ID3D11DeviceContext1 *mDeviceContext1; + ID3D11DeviceContext3 *mDeviceContext3; IDXGIAdapter *mDxgiAdapter; DXGI_ADAPTER_DESC mAdapterDescription; char mDescription[128]; - DXGIFactory *mDxgiFactory; -#if !defined(ANGLE_MINGW32_COMPAT) + IDXGIFactory *mDxgiFactory; ID3D11Debug *mDebug; -#endif std::vector mScratchIndexDataBuffer; + angle::ScratchBuffer mScratchMemoryBuffer; + + gl::DebugAnnotator *mAnnotator; + mutable Optional mSupportsShareHandles; + ResourceManager11 mResourceManager11; + + TextureHelper11 mCachedResolveTexture; }; -} -#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ +} // namespace rx +#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp new file mode 100644 index 0000000000..c228380a34 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp @@ -0,0 +1,533 @@ +// +// Copyright 2017 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. +// +// ResourceManager11: +// Centralized point of allocation for all D3D11 Resources. + +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" + +#include "common/debug.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" + +namespace rx +{ + +namespace +{ + +constexpr uint8_t kDebugInitTextureDataValue = 0x48; +constexpr FLOAT kDebugColorInitClearValue[4] = {0.3f, 0.5f, 0.7f, 0.5f}; +constexpr FLOAT kDebugDepthInitValue = 0.2f; +constexpr UINT8 kDebugStencilInitValue = 3; + +uint64_t ComputeMippedMemoryUsage(unsigned int width, + unsigned int height, + unsigned int depth, + uint64_t pixelSize, + unsigned int mipLevels) +{ + uint64_t sizeSum = 0; + + for (unsigned int level = 0; level < mipLevels; ++level) + { + unsigned int mipWidth = std::max(width >> level, 1u); + unsigned int mipHeight = std::max(height >> level, 1u); + unsigned int mipDepth = std::max(depth >> level, 1u); + sizeSum += static_cast(mipWidth * mipHeight * mipDepth) * pixelSize; + } + + return sizeSum; +} + +uint64_t ComputeMemoryUsage(const D3D11_TEXTURE2D_DESC *desc) +{ + ASSERT(desc); + uint64_t pixelBytes = + static_cast(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes); + return ComputeMippedMemoryUsage(desc->Width, desc->Height, 1, pixelBytes, desc->MipLevels); +} + +uint64_t ComputeMemoryUsage(const D3D11_TEXTURE3D_DESC *desc) +{ + ASSERT(desc); + uint64_t pixelBytes = + static_cast(d3d11::GetDXGIFormatSizeInfo(desc->Format).pixelBytes); + return ComputeMippedMemoryUsage(desc->Width, desc->Height, desc->Depth, pixelBytes, + desc->MipLevels); +} + +uint64_t ComputeMemoryUsage(const D3D11_BUFFER_DESC *desc) +{ + ASSERT(desc); + return static_cast(desc->ByteWidth); +} + +template +uint64_t ComputeMemoryUsage(const T *desc) +{ + return 0; +} + +template +uint64_t ComputeGenericMemoryUsage(ID3D11DeviceChild *genericResource) +{ + auto *typedResource = static_cast *>(genericResource); + GetDescType desc; + typedResource->GetDesc(&desc); + return ComputeMemoryUsage(&desc); +} + +uint64_t ComputeGenericMemoryUsage(ResourceType resourceType, ID3D11DeviceChild *resource) +{ + switch (resourceType) + { + case ResourceType::Texture2D: + return ComputeGenericMemoryUsage(resource); + case ResourceType::Texture3D: + return ComputeGenericMemoryUsage(resource); + case ResourceType::Buffer: + return ComputeGenericMemoryUsage(resource); + + default: + return 0; + } +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_BLEND_DESC *desc, + void * /*initData*/, + ID3D11BlendState **blendState) +{ + return device->CreateBlendState(desc, blendState); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_BUFFER_DESC *desc, + const D3D11_SUBRESOURCE_DATA *initData, + ID3D11Buffer **buffer) +{ + return device->CreateBuffer(desc, initData, buffer); +} + +HRESULT CreateResource(ID3D11Device *device, + const ShaderData *desc, + void * /*initData*/, + ID3D11ComputeShader **resourceOut) +{ + return device->CreateComputeShader(desc->get(), desc->size(), nullptr, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_DEPTH_STENCIL_DESC *desc, + void * /*initData*/, + ID3D11DepthStencilState **resourceOut) +{ + return device->CreateDepthStencilState(desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_DEPTH_STENCIL_VIEW_DESC *desc, + ID3D11Resource *resource, + ID3D11DepthStencilView **resourceOut) +{ + return device->CreateDepthStencilView(resource, desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const ShaderData *desc, + const std::vector *initData, + ID3D11GeometryShader **resourceOut) +{ + if (initData) + { + return device->CreateGeometryShaderWithStreamOutput( + desc->get(), desc->size(), initData->data(), static_cast(initData->size()), + nullptr, 0, 0, nullptr, resourceOut); + } + else + { + return device->CreateGeometryShader(desc->get(), desc->size(), nullptr, resourceOut); + } +} + +HRESULT CreateResource(ID3D11Device *device, + const InputElementArray *desc, + const ShaderData *initData, + ID3D11InputLayout **resourceOut) +{ + return device->CreateInputLayout(desc->get(), static_cast(desc->size()), initData->get(), + initData->size(), resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const ShaderData *desc, + void * /*initData*/, + ID3D11PixelShader **resourceOut) +{ + return device->CreatePixelShader(desc->get(), desc->size(), nullptr, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_QUERY_DESC *desc, + void * /*initData*/, + ID3D11Query **resourceOut) +{ + return device->CreateQuery(desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_RASTERIZER_DESC *desc, + void * /*initData*/, + ID3D11RasterizerState **rasterizerState) +{ + return device->CreateRasterizerState(desc, rasterizerState); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_RENDER_TARGET_VIEW_DESC *desc, + ID3D11Resource *resource, + ID3D11RenderTargetView **renderTargetView) +{ + return device->CreateRenderTargetView(resource, desc, renderTargetView); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_SAMPLER_DESC *desc, + void * /*initData*/, + ID3D11SamplerState **resourceOut) +{ + return device->CreateSamplerState(desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_SHADER_RESOURCE_VIEW_DESC *desc, + ID3D11Resource *resource, + ID3D11ShaderResourceView **resourceOut) +{ + return device->CreateShaderResourceView(resource, desc, resourceOut); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_TEXTURE2D_DESC *desc, + const D3D11_SUBRESOURCE_DATA *initData, + ID3D11Texture2D **texture) +{ + return device->CreateTexture2D(desc, initData, texture); +} + +HRESULT CreateResource(ID3D11Device *device, + const D3D11_TEXTURE3D_DESC *desc, + const D3D11_SUBRESOURCE_DATA *initData, + ID3D11Texture3D **texture) +{ + return device->CreateTexture3D(desc, initData, texture); +} + +HRESULT CreateResource(ID3D11Device *device, + const ShaderData *desc, + void * /*initData*/, + ID3D11VertexShader **resourceOut) +{ + return device->CreateVertexShader(desc->get(), desc->size(), nullptr, resourceOut); +} + +DXGI_FORMAT GetTypedDepthStencilFormat(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_R16_TYPELESS: + return DXGI_FORMAT_D16_UNORM; + case DXGI_FORMAT_R24G8_TYPELESS: + return DXGI_FORMAT_D24_UNORM_S8_UINT; + case DXGI_FORMAT_R32_TYPELESS: + return DXGI_FORMAT_D32_FLOAT; + case DXGI_FORMAT_R32G8X24_TYPELESS: + return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + default: + return dxgiFormat; + } +} + +template +gl::Error ClearResource(Renderer11 *renderer, const DescT *desc, ResourceT *texture) +{ + // No-op. + return gl::NoError(); +} + +template <> +gl::Error ClearResource(Renderer11 *renderer, + const D3D11_TEXTURE2D_DESC *desc, + ID3D11Texture2D *texture) +{ + ID3D11DeviceContext *context = renderer->getDeviceContext(); + + if ((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) != 0) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Flags = 0; + dsvDesc.Format = GetTypedDepthStencilFormat(desc->Format); + + const auto &format = d3d11_angle::GetFormat(dsvDesc.Format); + UINT clearFlags = (format.depthBits > 0 ? D3D11_CLEAR_DEPTH : 0) | + (format.stencilBits > 0 ? D3D11_CLEAR_STENCIL : 0); + + // Must process each mip level individually. + for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel) + { + if (desc->SampleDesc.Count == 0) + { + dsvDesc.Texture2D.MipSlice = mipLevel; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + } + else + { + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + } + + d3d11::DepthStencilView dsv; + ANGLE_TRY(renderer->allocateResource(dsvDesc, texture, &dsv)); + + context->ClearDepthStencilView(dsv.get(), clearFlags, kDebugDepthInitValue, + kDebugStencilInitValue); + } + } + else + { + ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0); + d3d11::RenderTargetView rtv; + ANGLE_TRY(renderer->allocateResourceNoDesc(texture, &rtv)); + + context->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue); + } + + return gl::NoError(); +} + +template <> +gl::Error ClearResource(Renderer11 *renderer, + const D3D11_TEXTURE3D_DESC *desc, + ID3D11Texture3D *texture) +{ + ID3D11DeviceContext *context = renderer->getDeviceContext(); + + ASSERT((desc->BindFlags & D3D11_BIND_DEPTH_STENCIL) == 0); + ASSERT((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0); + + d3d11::RenderTargetView rtv; + ANGLE_TRY(renderer->allocateResourceNoDesc(texture, &rtv)); + + context->ClearRenderTargetView(rtv.get(), kDebugColorInitClearValue); + return gl::NoError(); +} + +#define ANGLE_RESOURCE_STRINGIFY_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) #RESTYPE, + +constexpr std::array kResourceTypeNames = { + {ANGLE_RESOURCE_TYPE_OP(Stringify, ANGLE_RESOURCE_STRINGIFY_OP)}}; +static_assert(kResourceTypeNames[NumResourceTypes - 1] != nullptr, + "All members must be initialized."); + +} // anonymous namespace + +// ResourceManager11 Implementation. +ResourceManager11::ResourceManager11() + : mInitializeAllocations(false), + mAllocatedResourceCounts({{}}), + mAllocatedResourceDeviceMemory({{}}) +{ +} + +ResourceManager11::~ResourceManager11() +{ + for (size_t count : mAllocatedResourceCounts) + { + ASSERT(count == 0); + } + + for (uint64_t memorySize : mAllocatedResourceDeviceMemory) + { + ASSERT(memorySize == 0); + } +} + +template +gl::Error ResourceManager11::allocate(Renderer11 *renderer, + const GetDescFromD3D11 *desc, + GetInitDataFromD3D11 *initData, + Resource11 *resourceOut) +{ + ID3D11Device *device = renderer->getDevice(); + T *resource = nullptr; + + GetInitDataFromD3D11 *shadowInitData = initData; + if (!shadowInitData && mInitializeAllocations) + { + shadowInitData = createInitDataIfNeeded(desc); + } + + HRESULT hr = CreateResource(device, desc, shadowInitData, &resource); + if (FAILED(hr)) + { + ASSERT(!resource); + if (d3d11::isDeviceLostError(hr)) + { + renderer->notifyDeviceLost(); + } + return gl::OutOfMemory() << "Error allocating " + << std::string(kResourceTypeNames[ResourceTypeIndex()]) << ". " + << gl::FmtHR(hr); + } + + if (!shadowInitData && mInitializeAllocations) + { + ANGLE_TRY(ClearResource(renderer, desc, resource)); + } + + ASSERT(resource); + incrResource(GetResourceTypeFromD3D11(), ComputeMemoryUsage(desc)); + *resourceOut = std::move(Resource11(resource, this)); + return gl::NoError(); +} + +void ResourceManager11::incrResource(ResourceType resourceType, uint64_t memorySize) +{ + size_t typeIndex = ResourceTypeIndex(resourceType); + + mAllocatedResourceCounts[typeIndex]++; + mAllocatedResourceDeviceMemory[typeIndex] += memorySize; + + // This checks for integer overflow. + ASSERT(mAllocatedResourceCounts[typeIndex] > 0); + ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize); +} + +void ResourceManager11::decrResource(ResourceType resourceType, uint64_t memorySize) +{ + size_t typeIndex = ResourceTypeIndex(resourceType); + + ASSERT(mAllocatedResourceCounts[typeIndex] > 0); + mAllocatedResourceCounts[typeIndex]--; + ASSERT(mAllocatedResourceDeviceMemory[typeIndex] >= memorySize); + mAllocatedResourceDeviceMemory[typeIndex] -= memorySize; +} + +void ResourceManager11::onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource) +{ + ASSERT(resource); + decrResource(resourceType, ComputeGenericMemoryUsage(resourceType, resource)); +} + +template <> +const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded( + const D3D11_TEXTURE2D_DESC *desc) +{ + ASSERT(desc); + + if ((desc->BindFlags & (D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_RENDER_TARGET)) != 0) + { + // This will be done using ClearView methods. + return nullptr; + } + + size_t requiredSize = static_cast(ComputeMemoryUsage(desc)); + if (mZeroMemory.size() < requiredSize) + { + mZeroMemory.resize(requiredSize); + mZeroMemory.fill(kDebugInitTextureDataValue); + } + + const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format); + + UINT subresourceCount = desc->MipLevels * desc->ArraySize; + if (mShadowInitData.size() < subresourceCount) + { + mShadowInitData.resize(subresourceCount); + } + + for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel) + { + for (UINT arrayIndex = 0; arrayIndex < desc->ArraySize; ++arrayIndex) + { + UINT subresourceIndex = D3D11CalcSubresource(mipLevel, arrayIndex, desc->MipLevels); + D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex]; + + UINT levelWidth = std::max(desc->Width >> mipLevel, 1u); + UINT levelHeight = std::max(desc->Height >> mipLevel, 1u); + + data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes; + data->SysMemSlicePitch = data->SysMemPitch * levelHeight; + data->pSysMem = mZeroMemory.data(); + } + } + + return mShadowInitData.data(); +} + +template <> +const D3D11_SUBRESOURCE_DATA *ResourceManager11::createInitDataIfNeeded( + const D3D11_TEXTURE3D_DESC *desc) +{ + ASSERT(desc); + + if ((desc->BindFlags & D3D11_BIND_RENDER_TARGET) != 0) + { + // This will be done using ClearView methods. + return nullptr; + } + + size_t requiredSize = static_cast(ComputeMemoryUsage(desc)); + if (mZeroMemory.size() < requiredSize) + { + mZeroMemory.resize(requiredSize); + mZeroMemory.fill(kDebugInitTextureDataValue); + } + + const auto &formatSizeInfo = d3d11::GetDXGIFormatSizeInfo(desc->Format); + + UINT subresourceCount = desc->MipLevels; + if (mShadowInitData.size() < subresourceCount) + { + mShadowInitData.resize(subresourceCount); + } + + for (UINT mipLevel = 0; mipLevel < desc->MipLevels; ++mipLevel) + { + UINT subresourceIndex = D3D11CalcSubresource(mipLevel, 0, desc->MipLevels); + D3D11_SUBRESOURCE_DATA *data = &mShadowInitData[subresourceIndex]; + + UINT levelWidth = std::max(desc->Width >> mipLevel, 1u); + UINT levelHeight = std::max(desc->Height >> mipLevel, 1u); + + data->SysMemPitch = levelWidth * formatSizeInfo.pixelBytes; + data->SysMemSlicePitch = data->SysMemPitch * levelHeight; + data->pSysMem = mZeroMemory.data(); + } + + return mShadowInitData.data(); +} + +template +GetInitDataFromD3D11 *ResourceManager11::createInitDataIfNeeded(const GetDescFromD3D11 *desc) +{ + // No-op. + return nullptr; +} + +void ResourceManager11::setAllocationsInitialized(bool initialize) +{ + mInitializeAllocations = initialize; +} + +#define ANGLE_INSTANTIATE_OP(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template \ +gl::Error \ + ResourceManager11::allocate(Renderer11 *, const DESCTYPE *, INITDATATYPE *, \ + Resource11 *); + +ANGLE_RESOURCE_TYPE_OP(Instantitate, ANGLE_INSTANTIATE_OP) +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h new file mode 100644 index 0000000000..0bdde9f8b6 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.h @@ -0,0 +1,366 @@ +// +// Copyright 2017 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. +// +// ResourceManager11: +// Centralized point of allocation for all D3D11 Resources. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_ + +#include +#include + +#include "common/MemoryBuffer.h" +#include "common/angleutils.h" +#include "common/debug.h" +#include "libANGLE/Error.h" +#include "libANGLE/renderer/renderer_utils.h" + +namespace rx +{ +// These two methods are declared here to prevent circular includes. +namespace d3d11 +{ +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + +template +HRESULT SetDebugName(angle::ComPtr &resource, const char *name) +{ + return SetDebugName(resource.Get(), name); +} +} // namespace d3d11 + +class Renderer11; +class ResourceManager11; +template +class SharedResource11; +class TextureHelper11; + +using InputElementArray = WrappedArray; +using ShaderData = WrappedArray; + +// Format: ResourceType, D3D11 type, DESC type, init data type. +#define ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ + OP(NAME, BlendState, ID3D11BlendState, D3D11_BLEND_DESC, void) \ + OP(NAME, Buffer, ID3D11Buffer, D3D11_BUFFER_DESC, const D3D11_SUBRESOURCE_DATA) \ + OP(NAME, ComputeShader, ID3D11ComputeShader, ShaderData, void) \ + OP(NAME, DepthStencilState, ID3D11DepthStencilState, D3D11_DEPTH_STENCIL_DESC, void) \ + OP(NAME, DepthStencilView, ID3D11DepthStencilView, D3D11_DEPTH_STENCIL_VIEW_DESC, \ + ID3D11Resource) \ + OP(NAME, GeometryShader, ID3D11GeometryShader, ShaderData, \ + const std::vector) \ + OP(NAME, InputLayout, ID3D11InputLayout, InputElementArray, const ShaderData) \ + OP(NAME, PixelShader, ID3D11PixelShader, ShaderData, void) \ + OP(NAME, Query, ID3D11Query, D3D11_QUERY_DESC, void) \ + OP(NAME, RasterizerState, ID3D11RasterizerState, D3D11_RASTERIZER_DESC, void) \ + OP(NAME, RenderTargetView, ID3D11RenderTargetView, D3D11_RENDER_TARGET_VIEW_DESC, \ + ID3D11Resource) \ + OP(NAME, SamplerState, ID3D11SamplerState, D3D11_SAMPLER_DESC, void) \ + OP(NAME, ShaderResourceView, ID3D11ShaderResourceView, D3D11_SHADER_RESOURCE_VIEW_DESC, \ + ID3D11Resource) \ + OP(NAME, Texture2D, ID3D11Texture2D, D3D11_TEXTURE2D_DESC, const D3D11_SUBRESOURCE_DATA) \ + OP(NAME, Texture3D, ID3D11Texture3D, D3D11_TEXTURE3D_DESC, const D3D11_SUBRESOURCE_DATA) \ + OP(NAME, VertexShader, ID3D11VertexShader, ShaderData, void) + +#define ANGLE_RESOURCE_TYPE_LIST(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) RESTYPE, + +enum class ResourceType +{ + ANGLE_RESOURCE_TYPE_OP(List, ANGLE_RESOURCE_TYPE_LIST) Last +}; + +#undef ANGLE_RESOURCE_TYPE_LIST + +constexpr size_t ResourceTypeIndex(ResourceType resourceType) +{ + return static_cast(resourceType); +} + +constexpr size_t NumResourceTypes = ResourceTypeIndex(ResourceType::Last); + +#define ANGLE_RESOURCE_TYPE_TO_D3D11(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template<> struct NAME \ + { \ + using Value = D3D11TYPE; \ + }; + +#define ANGLE_RESOURCE_TYPE_TO_DESC(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template<> struct NAME \ + { \ + using Value = DESCTYPE; \ + }; + +#define ANGLE_RESOURCE_TYPE_TO_INIT_DATA(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template<> struct NAME \ + { \ + using Value = INITDATATYPE; \ + }; + +#define ANGLE_RESOURCE_TYPE_TO_TYPE(NAME, OP) \ + template \ + struct NAME; \ + ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ + \ +template struct NAME \ + { \ + }; \ + \ +template using Get##NAME = typename NAME::Value; + +ANGLE_RESOURCE_TYPE_TO_TYPE(D3D11Type, ANGLE_RESOURCE_TYPE_TO_D3D11) +ANGLE_RESOURCE_TYPE_TO_TYPE(DescType, ANGLE_RESOURCE_TYPE_TO_DESC) +ANGLE_RESOURCE_TYPE_TO_TYPE(InitDataType, ANGLE_RESOURCE_TYPE_TO_INIT_DATA) + +#undef ANGLE_RESOURCE_TYPE_TO_D3D11 +#undef ANGLE_RESOURCE_TYPE_TO_DESC +#undef ANGLE_RESOURCE_TYPE_TO_INIT_DATA +#undef ANGLE_RESOURCE_TYPE_TO_TYPE + +#define ANGLE_TYPE_TO_RESOURCE_TYPE(NAME, OP) \ + template \ + struct NAME; \ + ANGLE_RESOURCE_TYPE_OP(NAME, OP) \ + \ +template struct NAME \ + { \ + }; \ + \ +template constexpr ResourceType Get##NAME() \ + { \ + return NAME::Value; \ + } + +#define ANGLE_D3D11_TO_RESOURCE_TYPE(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + \ +template<> struct NAME \ + { \ + static constexpr ResourceType Value = ResourceType::RESTYPE; \ + }; + +ANGLE_TYPE_TO_RESOURCE_TYPE(ResourceTypeFromD3D11, ANGLE_D3D11_TO_RESOURCE_TYPE) + +#undef ANGLE_D3D11_TO_RESOURCE_TYPE +#undef ANGLE_TYPE_TO_RESOURCE_TYPE + +template +using GetDescFromD3D11 = GetDescType::Value>; + +template +using GetInitDataFromD3D11 = GetInitDataType::Value>; + +template +constexpr size_t ResourceTypeIndex() +{ + return static_cast(GetResourceTypeFromD3D11()); +} + +template +struct TypedData +{ + TypedData() {} + ~TypedData(); + + T *object = nullptr; + ResourceManager11 *manager = nullptr; +}; + +// Smart pointer type. Wraps the resource and a factory for safe deletion. +template class Pointer, typename DataT> +class Resource11Base : angle::NonCopyable +{ + public: + T *get() const { return mData->object; } + T *const *getPointer() const { return &mData->object; } + + void setDebugName(const char *name) { d3d11::SetDebugName(mData->object, name); } + + void set(T *object) + { + ASSERT(!valid()); + mData->object = object; + } + + bool valid() const { return (mData->object != nullptr); } + + void reset() + { + if (valid()) + mData.reset(new DataT()); + } + + ResourceSerial getSerial() const + { + return ResourceSerial(reinterpret_cast(mData->object)); + } + + protected: + friend class TextureHelper11; + + Resource11Base() : mData(new DataT()) {} + + Resource11Base(Resource11Base &&movedObj) : mData(new DataT()) + { + std::swap(mData, movedObj.mData); + } + + virtual ~Resource11Base() { mData.reset(); } + + Resource11Base &operator=(Resource11Base &&movedObj) + { + std::swap(mData, movedObj.mData); + return *this; + } + + Pointer mData; +}; + +template +using UniquePtr = typename std::unique_ptr>; + +template +class Resource11 : public Resource11Base> +{ + public: + Resource11() {} + Resource11(Resource11 &&other) + : Resource11Base>(std::move(other)) + { + } + Resource11 &operator=(Resource11 &&other) + { + std::swap(this->mData, other.mData); + return *this; + } + + private: + template + friend class SharedResource11; + friend class ResourceManager11; + + Resource11(ResourceT *object, ResourceManager11 *manager) + { + this->mData->object = object; + this->mData->manager = manager; + } +}; + +template +class SharedResource11 : public Resource11Base> +{ + public: + SharedResource11() {} + SharedResource11(SharedResource11 &&movedObj) + : Resource11Base>(std::move(movedObj)) + { + } + + SharedResource11 &operator=(SharedResource11 &&other) + { + std::swap(this->mData, other.mData); + return *this; + } + + SharedResource11 makeCopy() const + { + SharedResource11 copy; + copy.mData = this->mData; + return std::move(copy); + } + + private: + friend class ResourceManager11; + SharedResource11(Resource11 &&obj) : Resource11Base>() + { + std::swap(this->mData->manager, obj.mData->manager); + + // Can't use std::swap because of ID3D11Resource. + auto temp = this->mData->object; + this->mData->object = obj.mData->object; + obj.mData->object = static_cast(temp); + } +}; + +class ResourceManager11 final : angle::NonCopyable +{ + public: + ResourceManager11(); + ~ResourceManager11(); + + template + gl::Error allocate(Renderer11 *renderer, + const GetDescFromD3D11 *desc, + GetInitDataFromD3D11 *initData, + Resource11 *resourceOut); + + template + gl::Error allocate(Renderer11 *renderer, + const GetDescFromD3D11 *desc, + GetInitDataFromD3D11 *initData, + SharedResource11 *sharedRes) + { + Resource11 res; + ANGLE_TRY(allocate(renderer, desc, initData, &res)); + *sharedRes = std::move(res); + return gl::NoError(); + } + + template + void onRelease(T *resource) + { + onReleaseGeneric(GetResourceTypeFromD3D11(), resource); + } + + void onReleaseGeneric(ResourceType resourceType, ID3D11DeviceChild *resource); + + void setAllocationsInitialized(bool initialize); + + private: + void incrResource(ResourceType resourceType, uint64_t memorySize); + void decrResource(ResourceType resourceType, uint64_t memorySize); + + template + GetInitDataFromD3D11 *createInitDataIfNeeded(const GetDescFromD3D11 *desc); + + bool mInitializeAllocations; + + std::array mAllocatedResourceCounts; + std::array mAllocatedResourceDeviceMemory; + angle::MemoryBuffer mZeroMemory; + + std::vector mShadowInitData; +}; + +template +TypedData::~TypedData() +{ + if (object) + { + // We can have a nullptr factory when holding passed-in resources. + if (manager) + { + manager->onRelease(object); + } + object->Release(); + } +} + +#define ANGLE_RESOURCE_TYPE_CLASS(NAME, RESTYPE, D3D11TYPE, DESCTYPE, INITDATATYPE) \ + using RESTYPE = Resource11; + +namespace d3d11 +{ +ANGLE_RESOURCE_TYPE_OP(ClassList, ANGLE_RESOURCE_TYPE_CLASS) + +using SharedSRV = SharedResource11; +} // namespace d3d11 + +#undef ANGLE_RESOURCE_TYPE_CLASS + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_RESOURCEFACTORY11_H_ 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 4da51afe49..73a530add0 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -13,86 +13,107 @@ namespace rx { -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) - : ShaderExecutableD3D(function, length) +ShaderExecutable11::ShaderExecutable11(const void *function, + size_t length, + d3d11::PixelShader &&executable) + : ShaderExecutableD3D(function, length), + mPixelExecutable(std::move(executable)), + mVertexExecutable(), + mGeometryExecutable(), + mStreamOutExecutable(), + mComputeExecutable() { - mPixelExecutable = executable; - mVertexExecutable = NULL; - mGeometryExecutable = NULL; - mStreamOutExecutable = NULL; } -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut) - : ShaderExecutableD3D(function, length) +ShaderExecutable11::ShaderExecutable11(const void *function, + size_t length, + d3d11::VertexShader &&executable, + d3d11::GeometryShader &&streamOut) + : ShaderExecutableD3D(function, length), + mPixelExecutable(), + mVertexExecutable(std::move(executable)), + mGeometryExecutable(), + mStreamOutExecutable(std::move(streamOut)), + mComputeExecutable() { - mVertexExecutable = executable; - mPixelExecutable = NULL; - mGeometryExecutable = NULL; - mStreamOutExecutable = streamOut; } -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) - : ShaderExecutableD3D(function, length) +ShaderExecutable11::ShaderExecutable11(const void *function, + size_t length, + d3d11::GeometryShader &&executable) + : ShaderExecutableD3D(function, length), + mPixelExecutable(), + mVertexExecutable(), + mGeometryExecutable(std::move(executable)), + mStreamOutExecutable(), + mComputeExecutable() +{ +} + +ShaderExecutable11::ShaderExecutable11(const void *function, + size_t length, + d3d11::ComputeShader &&executable) + : ShaderExecutableD3D(function, length), + mPixelExecutable(), + mVertexExecutable(), + mGeometryExecutable(), + mStreamOutExecutable(), + mComputeExecutable(std::move(executable)) { - mGeometryExecutable = executable; - mVertexExecutable = NULL; - mPixelExecutable = NULL; - mStreamOutExecutable = NULL; } ShaderExecutable11::~ShaderExecutable11() { - SafeRelease(mVertexExecutable); - SafeRelease(mPixelExecutable); - SafeRelease(mGeometryExecutable); - SafeRelease(mStreamOutExecutable); } -ID3D11VertexShader *ShaderExecutable11::getVertexShader() const +const d3d11::VertexShader &ShaderExecutable11::getVertexShader() const { return mVertexExecutable; } -ID3D11PixelShader *ShaderExecutable11::getPixelShader() const +const d3d11::PixelShader &ShaderExecutable11::getPixelShader() const { return mPixelExecutable; } -ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const +const d3d11::GeometryShader &ShaderExecutable11::getGeometryShader() const { return mGeometryExecutable; } -ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const +const d3d11::GeometryShader &ShaderExecutable11::getStreamOutShader() const { return mStreamOutExecutable; } -UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize) - : UniformStorageD3D(initialSize), - mConstantBuffer(NULL) +const d3d11::ComputeShader &ShaderExecutable11::getComputeShader() const { - ID3D11Device *d3d11Device = renderer->getDevice(); + return mComputeExecutable; +} - if (initialSize > 0) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = static_cast(initialSize); - constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(SUCCEEDED(result)); - } +UniformStorage11::UniformStorage11(size_t initialSize) + : UniformStorageD3D(initialSize), mConstantBuffer() +{ } UniformStorage11::~UniformStorage11() { - SafeRelease(mConstantBuffer); } +gl::Error UniformStorage11::getConstantBuffer(Renderer11 *renderer, const d3d11::Buffer **bufferOut) +{ + if (size() > 0 && !mConstantBuffer.valid()) + { + D3D11_BUFFER_DESC desc = {0}; + desc.ByteWidth = static_cast(size()); + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + + ANGLE_TRY(renderer->allocateResource(desc, &mConstantBuffer)); + } + + *bufferOut = &mConstantBuffer; + return gl::NoError(); } + +} // namespace rx 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 379f39fe53..3f417578a3 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h @@ -11,6 +11,7 @@ #define LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ #include "libANGLE/renderer/d3d/ShaderExecutableD3D.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" namespace rx { @@ -20,36 +21,42 @@ class UniformStorage11; class ShaderExecutable11 : public ShaderExecutableD3D { public: - ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); - ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut); - ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable); - - virtual ~ShaderExecutable11(); - - ID3D11PixelShader *getPixelShader() const; - ID3D11VertexShader *getVertexShader() const; - ID3D11GeometryShader *getGeometryShader() const; - ID3D11GeometryShader *getStreamOutShader() const; + ShaderExecutable11(const void *function, size_t length, d3d11::PixelShader &&executable); + ShaderExecutable11(const void *function, + size_t length, + d3d11::VertexShader &&executable, + d3d11::GeometryShader &&streamOut); + ShaderExecutable11(const void *function, size_t length, d3d11::GeometryShader &&executable); + ShaderExecutable11(const void *function, size_t length, d3d11::ComputeShader &&executable); + + ~ShaderExecutable11() override; + + const d3d11::PixelShader &getPixelShader() const; + const d3d11::VertexShader &getVertexShader() const; + const d3d11::GeometryShader &getGeometryShader() const; + const d3d11::GeometryShader &getStreamOutShader() const; + const d3d11::ComputeShader &getComputeShader() const; private: - ID3D11PixelShader *mPixelExecutable; - ID3D11VertexShader *mVertexExecutable; - ID3D11GeometryShader *mGeometryExecutable; - ID3D11GeometryShader *mStreamOutExecutable; + d3d11::PixelShader mPixelExecutable; + d3d11::VertexShader mVertexExecutable; + d3d11::GeometryShader mGeometryExecutable; + d3d11::GeometryShader mStreamOutExecutable; + d3d11::ComputeShader mComputeExecutable; }; class UniformStorage11 : public UniformStorageD3D { public: - UniformStorage11(Renderer11 *renderer, size_t initialSize); - virtual ~UniformStorage11(); + UniformStorage11(size_t initialSize); + ~UniformStorage11() override; - ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; } + gl::Error getConstantBuffer(Renderer11 *renderer, const d3d11::Buffer **bufferOut); private: - ID3D11Buffer *mConstantBuffer; + d3d11::Buffer mConstantBuffer; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp index aa34fd4de8..e9902d3f14 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp @@ -8,11 +8,22 @@ #include "libANGLE/renderer/d3d/d3d11/StateManager11.h" -#include "common/BitSetIterator.h" +#include "common/bitset_utils.h" #include "common/utilities.h" +#include "libANGLE/Context.h" +#include "libANGLE/Query.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/renderer/d3d/TextureD3D.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Context11.h" #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h" -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h" #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" +#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h" +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" namespace rx { @@ -22,15 +33,16 @@ namespace bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOURCE_VIEW_DESC desc) { unsigned mipLevel = index.mipIndex; - unsigned layerIndex = index.layerIndex; + GLint 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; + bool allLevels = (desc.Texture2D.MipLevels == std::numeric_limits::max()); + unsigned int maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip; + maxSrvMip = allLevels ? INT_MAX : maxSrvMip; unsigned mipMin = index.mipIndex; unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex; @@ -42,22 +54,25 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: { - unsigned maxSrvMip = + bool allLevels = (desc.Texture2DArray.MipLevels == std::numeric_limits::max()); + unsigned int maxSrvMip = desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip; - maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip; + maxSrvMip = allLevels ? 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; + desc.Texture2DArray.FirstArraySlice <= static_cast(layerIndex) && + static_cast(layerIndex) < maxSlice; } case D3D11_SRV_DIMENSION_TEXTURECUBE: { - unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip; - maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip; + bool allLevels = (desc.TextureCube.MipLevels == std::numeric_limits::max()); + unsigned int maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip; + maxSrvMip = allLevels ? INT_MAX : maxSrvMip; return gl::IsCubeMapTextureTarget(type) && desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; @@ -65,8 +80,9 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR case D3D11_SRV_DIMENSION_TEXTURE3D: { - unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip; - maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip; + bool allLevels = (desc.Texture3D.MipLevels == std::numeric_limits::max()); + unsigned int maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip; + maxSrvMip = allLevels ? INT_MAX : maxSrvMip; return type == GL_TEXTURE_3D && desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip; @@ -82,15 +98,97 @@ bool ImageIndexConflictsWithSRV(const gl::ImageIndex &index, D3D11_SHADER_RESOUR // Does *not* increment the resource ref count!! ID3D11Resource *GetViewResource(ID3D11View *view) { - ID3D11Resource *resource = NULL; + ID3D11Resource *resource = nullptr; ASSERT(view); view->GetResource(&resource); resource->Release(); return resource; } +int GetWrapBits(GLenum wrap) +{ + switch (wrap) + { + case GL_CLAMP_TO_EDGE: + return 0x1; + case GL_REPEAT: + return 0x2; + case GL_MIRRORED_REPEAT: + return 0x3; + default: + UNREACHABLE(); + return 0; + } +} + +Optional FindFirstNonInstanced( + const std::vector ¤tAttributes) +{ + for (size_t index = 0; index < currentAttributes.size(); ++index) + { + if (currentAttributes[index]->divisor == 0) + { + return Optional(index); + } + } + + return Optional::Invalid(); +} + +void SortAttributesByLayout(const gl::Program *program, + const std::vector &vertexArrayAttribs, + const std::vector ¤tValueAttribs, + AttribIndexArray *sortedD3DSemanticsOut, + std::vector *sortedAttributesOut) +{ + sortedAttributesOut->clear(); + + const auto &locationToSemantic = + GetImplAs(program)->getAttribLocationToD3DSemantics(); + + for (auto locationIndex : program->getActiveAttribLocationsMask()) + { + int d3dSemantic = locationToSemantic[locationIndex]; + if (sortedAttributesOut->size() <= static_cast(d3dSemantic)) + { + sortedAttributesOut->resize(d3dSemantic + 1); + } + + (*sortedD3DSemanticsOut)[d3dSemantic] = d3dSemantic; + + const auto *arrayAttrib = &vertexArrayAttribs[locationIndex]; + if (arrayAttrib->attribute && arrayAttrib->attribute->enabled) + { + (*sortedAttributesOut)[d3dSemantic] = arrayAttrib; + } + else + { + ASSERT(currentValueAttribs[locationIndex].attribute); + (*sortedAttributesOut)[d3dSemantic] = ¤tValueAttribs[locationIndex]; + } + } +} + +void UpdateUniformBuffer(ID3D11DeviceContext *deviceContext, + UniformStorage11 *storage, + const d3d11::Buffer *buffer) +{ + deviceContext->UpdateSubresource(buffer->get(), 0, nullptr, storage->getDataPointer(0, 0), 0, + 0); +} + } // anonymous namespace +// StateManager11::SRVCache Implementation. + +StateManager11::SRVCache::SRVCache() : mHighestUsedSRV(0) +{ +} + +StateManager11::SRVCache::~SRVCache() +{ +} + void StateManager11::SRVCache::update(size_t resourceIndex, ID3D11ShaderResourceView *srv) { ASSERT(resourceIndex < mCurrentSRVs.size()); @@ -128,27 +226,348 @@ void StateManager11::SRVCache::clear() mHighestUsedSRV = 0; } +// ShaderConstants11 implementation + +ShaderConstants11::ShaderConstants11() + : mVertexDirty(true), + mPixelDirty(true), + mComputeDirty(true), + mSamplerMetadataVSDirty(true), + mSamplerMetadataPSDirty(true), + mSamplerMetadataCSDirty(true) +{ +} + +ShaderConstants11::~ShaderConstants11() +{ +} + +void ShaderConstants11::init(const gl::Caps &caps) +{ + mSamplerMetadataVS.resize(caps.maxVertexTextureImageUnits); + mSamplerMetadataPS.resize(caps.maxTextureImageUnits); + mSamplerMetadataCS.resize(caps.maxComputeTextureImageUnits); +} + +size_t ShaderConstants11::getRequiredBufferSize(gl::SamplerType samplerType) const +{ + switch (samplerType) + { + case gl::SAMPLER_VERTEX: + return sizeof(Vertex) + mSamplerMetadataVS.size() * sizeof(SamplerMetadata); + case gl::SAMPLER_PIXEL: + return sizeof(Pixel) + mSamplerMetadataPS.size() * sizeof(SamplerMetadata); + case gl::SAMPLER_COMPUTE: + return sizeof(Compute) + mSamplerMetadataCS.size() * sizeof(SamplerMetadata); + default: + UNREACHABLE(); + return 0; + } +} + +void ShaderConstants11::markDirty() +{ + mVertexDirty = true; + mPixelDirty = true; + mComputeDirty = true; + mSamplerMetadataVSDirty = true; + mSamplerMetadataPSDirty = true; + mSamplerMetadataCSDirty = true; +} + +bool ShaderConstants11::updateSamplerMetadata(SamplerMetadata *data, const gl::Texture &texture) +{ + bool dirty = false; + unsigned int baseLevel = texture.getTextureState().getEffectiveBaseLevel(); + GLenum sizedFormat = + texture.getFormat(texture.getTarget(), baseLevel).info->sizedInternalFormat; + if (data->baseLevel != static_cast(baseLevel)) + { + data->baseLevel = static_cast(baseLevel); + dirty = true; + } + + // Some metadata is needed only for integer textures. We avoid updating the constant buffer + // unnecessarily by changing the data only in case the texture is an integer texture and + // the values have changed. + bool needIntegerTextureMetadata = false; + // internalFormatBits == 0 means a 32-bit texture in the case of integer textures. + int internalFormatBits = 0; + switch (sizedFormat) + { + case GL_RGBA32I: + case GL_RGBA32UI: + case GL_RGB32I: + case GL_RGB32UI: + case GL_RG32I: + case GL_RG32UI: + case GL_R32I: + case GL_R32UI: + needIntegerTextureMetadata = true; + break; + case GL_RGBA16I: + case GL_RGBA16UI: + case GL_RGB16I: + case GL_RGB16UI: + case GL_RG16I: + case GL_RG16UI: + case GL_R16I: + case GL_R16UI: + needIntegerTextureMetadata = true; + internalFormatBits = 16; + break; + case GL_RGBA8I: + case GL_RGBA8UI: + case GL_RGB8I: + case GL_RGB8UI: + case GL_RG8I: + case GL_RG8UI: + case GL_R8I: + case GL_R8UI: + needIntegerTextureMetadata = true; + internalFormatBits = 8; + break; + case GL_RGB10_A2UI: + needIntegerTextureMetadata = true; + internalFormatBits = 10; + break; + default: + break; + } + if (needIntegerTextureMetadata) + { + if (data->internalFormatBits != internalFormatBits) + { + data->internalFormatBits = internalFormatBits; + dirty = true; + } + // Pack the wrap values into one integer so we can fit all the metadata in one 4-integer + // vector. + GLenum wrapS = texture.getWrapS(); + GLenum wrapT = texture.getWrapT(); + GLenum wrapR = texture.getWrapR(); + int wrapModes = GetWrapBits(wrapS) | (GetWrapBits(wrapT) << 2) | (GetWrapBits(wrapR) << 4); + if (data->wrapModes != wrapModes) + { + data->wrapModes = wrapModes; + dirty = true; + } + } + + return dirty; +} + +void ShaderConstants11::setComputeWorkGroups(GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) +{ + mCompute.numWorkGroups[0] = numGroupsX; + mCompute.numWorkGroups[1] = numGroupsY; + mCompute.numWorkGroups[2] = numGroupsZ; + mComputeDirty = true; +} + +void ShaderConstants11::setMultiviewWriteToViewportIndex(GLfloat index) +{ + mVertex.multiviewWriteToViewportIndex = index; + mVertexDirty = true; + mPixel.multiviewWriteToViewportIndex = index; + mPixelDirty = true; +} + +void ShaderConstants11::onViewportChange(const gl::Rectangle &glViewport, + const D3D11_VIEWPORT &dxViewport, + bool is9_3, + bool presentPathFast) +{ + mVertexDirty = true; + mPixelDirty = true; + + // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders + // using viewAdjust (like the D3D9 renderer). + if (is9_3) + { + mVertex.viewAdjust[0] = static_cast((glViewport.width - dxViewport.Width) + + 2 * (glViewport.x - dxViewport.TopLeftX)) / + dxViewport.Width; + mVertex.viewAdjust[1] = static_cast((glViewport.height - dxViewport.Height) + + 2 * (glViewport.y - dxViewport.TopLeftY)) / + dxViewport.Height; + mVertex.viewAdjust[2] = static_cast(glViewport.width) / dxViewport.Width; + mVertex.viewAdjust[3] = static_cast(glViewport.height) / dxViewport.Height; + } + + mPixel.viewCoords[0] = glViewport.width * 0.5f; + mPixel.viewCoords[1] = glViewport.height * 0.5f; + mPixel.viewCoords[2] = glViewport.x + (glViewport.width * 0.5f); + mPixel.viewCoords[3] = glViewport.y + (glViewport.height * 0.5f); + + // Instanced pointsprite emulation requires ViewCoords to be defined in the + // the vertex shader. + mVertex.viewCoords[0] = mPixel.viewCoords[0]; + mVertex.viewCoords[1] = mPixel.viewCoords[1]; + mVertex.viewCoords[2] = mPixel.viewCoords[2]; + mVertex.viewCoords[3] = mPixel.viewCoords[3]; + + const float zNear = dxViewport.MinDepth; + const float zFar = dxViewport.MaxDepth; + + mPixel.depthFront[0] = (zFar - zNear) * 0.5f; + mPixel.depthFront[1] = (zNear + zFar) * 0.5f; + + mVertex.depthRange[0] = zNear; + mVertex.depthRange[1] = zFar; + mVertex.depthRange[2] = zFar - zNear; + + mPixel.depthRange[0] = zNear; + mPixel.depthRange[1] = zFar; + mPixel.depthRange[2] = zFar - zNear; + + mPixel.viewScale[0] = 1.0f; + mPixel.viewScale[1] = presentPathFast ? 1.0f : -1.0f; + // Updates to the multiviewWriteToViewportIndex member are to be handled whenever the draw + // framebuffer's layout is changed. + + mVertex.viewScale[0] = mPixel.viewScale[0]; + mVertex.viewScale[1] = mPixel.viewScale[1]; +} + +void ShaderConstants11::onSamplerChange(gl::SamplerType samplerType, + unsigned int samplerIndex, + const gl::Texture &texture) +{ + switch (samplerType) + { + case gl::SAMPLER_VERTEX: + if (updateSamplerMetadata(&mSamplerMetadataVS[samplerIndex], texture)) + { + mSamplerMetadataVSDirty = true; + } + break; + case gl::SAMPLER_PIXEL: + if (updateSamplerMetadata(&mSamplerMetadataPS[samplerIndex], texture)) + { + mSamplerMetadataPSDirty = true; + } + break; + case gl::SAMPLER_COMPUTE: + if (updateSamplerMetadata(&mSamplerMetadataCS[samplerIndex], texture)) + { + mSamplerMetadataCSDirty = true; + } + break; + default: + UNREACHABLE(); + break; + } +} + +gl::Error ShaderConstants11::updateBuffer(ID3D11DeviceContext *deviceContext, + gl::SamplerType samplerType, + const ProgramD3D &programD3D, + const d3d11::Buffer &driverConstantBuffer) +{ + bool dirty = false; + size_t dataSize = 0; + const uint8_t *data = nullptr; + const uint8_t *samplerData = nullptr; + + switch (samplerType) + { + case gl::SAMPLER_VERTEX: + dirty = mVertexDirty || mSamplerMetadataVSDirty; + dataSize = sizeof(Vertex); + data = reinterpret_cast(&mVertex); + samplerData = reinterpret_cast(mSamplerMetadataVS.data()); + mVertexDirty = false; + mSamplerMetadataVSDirty = false; + break; + case gl::SAMPLER_PIXEL: + dirty = mPixelDirty || mSamplerMetadataPSDirty; + dataSize = sizeof(Pixel); + data = reinterpret_cast(&mPixel); + samplerData = reinterpret_cast(mSamplerMetadataPS.data()); + mPixelDirty = false; + mSamplerMetadataPSDirty = false; + break; + case gl::SAMPLER_COMPUTE: + dirty = mComputeDirty || mSamplerMetadataCSDirty; + dataSize = sizeof(Compute); + data = reinterpret_cast(&mCompute); + samplerData = reinterpret_cast(mSamplerMetadataCS.data()); + mComputeDirty = false; + mSamplerMetadataCSDirty = false; + break; + default: + UNREACHABLE(); + break; + } + + ASSERT(driverConstantBuffer.valid()); + + if (!dirty) + { + return gl::NoError(); + } + + // Previous buffer contents are discarded, so we need to refresh the whole buffer. + D3D11_MAPPED_SUBRESOURCE mapping = {0}; + HRESULT result = + deviceContext->Map(driverConstantBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapping); + + if (FAILED(result)) + { + return gl::OutOfMemory() << "Internal error mapping constant buffer: " << gl::FmtHR(result); + } + + size_t samplerDataBytes = sizeof(SamplerMetadata) * programD3D.getUsedSamplerRange(samplerType); + + memcpy(mapping.pData, data, dataSize); + memcpy(reinterpret_cast(mapping.pData) + dataSize, samplerData, samplerDataBytes); + + deviceContext->Unmap(driverConstantBuffer.get(), 0); + + return gl::NoError(); +} + +static const GLenum QueryTypes[] = {GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE, + GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_TIME_ELAPSED_EXT, + GL_COMMANDS_COMPLETED_CHROMIUM}; + StateManager11::StateManager11(Renderer11 *renderer) : mRenderer(renderer), - mBlendStateIsDirty(false), + mInternalDirtyBits(), 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(), + mRenderTargetIsDirty(true), mCurPresentPathFastEnabled(false), mCurPresentPathFastColorBufferHeight(0), - mAppliedDSV(angle::DirtyPointer) + mDirtyCurrentValueAttribs(), + mCurrentValueAttribs(), + mCurrentInputLayout(), + mInputLayoutIsDirty(false), + mVertexAttribsNeedTranslation(false), + mDirtyVertexBufferRange(gl::MAX_VERTEX_ATTRIBS, 0), + mCurrentPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_UNDEFINED), + mDirtySwizzles(false), + mAppliedIB(nullptr), + mAppliedIBFormat(DXGI_FORMAT_UNKNOWN), + mAppliedIBOffset(0), + mIndexBufferIsDirty(false), + mVertexDataManager(renderer), + mIndexDataManager(renderer), + mIsMultiviewEnabled(false), + mEmptySerial(mRenderer->generateSerial()), + mIsTransformFeedbackCurrentlyActiveUnpaused(false) { mCurBlendState.blend = false; mCurBlendState.sourceBlendRGB = GL_ONE; @@ -182,64 +601,127 @@ StateManager11::StateManager11(Renderer11 *renderer) mCurRasterState.rasterizerDiscard = false; mCurRasterState.cullFace = false; - mCurRasterState.cullMode = GL_BACK; + mCurRasterState.cullMode = gl::CullFaceMode::Back; mCurRasterState.frontFace = GL_CCW; mCurRasterState.polygonOffsetFill = false; mCurRasterState.polygonOffsetFactor = 0.0f; mCurRasterState.polygonOffsetUnits = 0.0f; mCurRasterState.pointDrawMode = false; mCurRasterState.multiSample = false; + + // Start with all internal dirty bits set. + mInternalDirtyBits.set(); + + // Initially all current value attributes must be updated on first use. + mDirtyCurrentValueAttribs.set(); + + mCurrentVertexBuffers.fill(nullptr); + mCurrentVertexStrides.fill(std::numeric_limits::max()); + mCurrentVertexOffsets.fill(std::numeric_limits::max()); } StateManager11::~StateManager11() { } -void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized, - unsigned int stencilSize) +template +void StateManager11::setShaderResourceInternal(gl::SamplerType shaderType, + UINT resourceSlot, + const SRVType *srv) { - if (!depthStencilInitialized || stencilSize != mCurStencilSize) + 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)) { - mCurStencilSize = stencilSize; - mDepthStencilStateIsDirty = true; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ID3D11ShaderResourceView *srvPtr = srv ? srv->get() : nullptr; + if (shaderType == gl::SAMPLER_VERTEX) + { + deviceContext->VSSetShaderResources(resourceSlot, 1, &srvPtr); + } + else + { + deviceContext->PSSetShaderResources(resourceSlot, 1, &srvPtr); + } + + currentSRVs.update(resourceSlot, srvPtr); } } -void StateManager11::setViewportBounds(const int width, const int height) +void StateManager11::updateStencilSizeIfChanged(bool depthStencilInitialized, + unsigned int stencilSize) { - if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && - (mViewportBounds.width != width || mViewportBounds.height != height)) + if (!depthStencilInitialized || stencilSize != mCurStencilSize) { - mViewportBounds = gl::Extents(width, height, 1); - mViewportStateIsDirty = true; + mCurStencilSize = stencilSize; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } } -void StateManager11::updatePresentPath(bool presentPathFastActive, - const gl::FramebufferAttachment *framebufferAttachment) +void StateManager11::checkPresentPath(const gl::Context *context) { - const int colorBufferHeight = - framebufferAttachment ? framebufferAttachment->getSize().height : 0; + if (!mRenderer->presentPathFastEnabled()) + return; + + const auto *framebuffer = context->getGLState().getDrawFramebuffer(); + const auto *firstColorAttachment = framebuffer->getFirstColorbuffer(); + const bool presentPathFastActive = UsePresentPathFast(mRenderer, firstColorAttachment); + + const int colorBufferHeight = firstColorAttachment ? firstColorAttachment->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 + + // Scissor rect may need to be vertically inverted + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); + + // Cull Mode may need to be inverted + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); + + // Viewport may need to be vertically inverted + invalidateViewport(context); } } -void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) +gl::Error StateManager11::updateStateForCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ) +{ + mShaderConstants.setComputeWorkGroups(numGroupsX, numGroupsY, numGroupsZ); + + // TODO(jmadill): Use dirty bits. + const auto &glState = context->getGLState(); + auto *programD3D = GetImplAs(glState.getProgram()); + programD3D->updateSamplerMapping(); + + // TODO(jmadill): Use dirty bits. + ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_COMPUTE)); + + // TODO(jmadill): More complete implementation. + ANGLE_TRY(syncTextures(context)); + + // TODO(Xinghua): applyUniformBuffers for compute shader. + + return gl::NoError(); +} + +void StateManager11::syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) { if (!dirtyBits.any()) { return; } - for (unsigned int dirtyBit : angle::IterateBitSet(dirtyBits)) + const auto &state = context->getGLState(); + + for (auto dirtyBit : dirtyBits) { switch (dirtyBit) { @@ -249,7 +731,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; } @@ -261,27 +743,27 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; } case gl::State::DIRTY_BIT_BLEND_ENABLED: if (state.getBlendState().blend != mCurBlendState.blend) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: if (state.getBlendState().sampleAlphaToCoverage != mCurBlendState.sampleAlphaToCoverage) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; case gl::State::DIRTY_BIT_DITHER_ENABLED: if (state.getBlendState().dither != mCurBlendState.dither) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; case gl::State::DIRTY_BIT_COLOR_MASK: @@ -292,38 +774,38 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; } case gl::State::DIRTY_BIT_BLEND_COLOR: if (state.getBlendColor() != mCurBlendColor) { - mBlendStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); } break; case gl::State::DIRTY_BIT_DEPTH_MASK: if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_DEPTH_FUNC: if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: @@ -333,7 +815,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit depthStencil.stencilMask != mCurDepthStencilState.stencilMask || state.getStencilRef() != mCurStencilRef) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; } @@ -344,7 +826,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask || state.getStencilBackRef() != mCurStencilBackRef) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; } @@ -352,14 +834,14 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit if (state.getDepthStencilState().stencilWritemask != mCurDepthStencilState.stencilWritemask) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: if (state.getDepthStencilState().stencilBackWritemask != mCurDepthStencilState.stencilBackWritemask) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: @@ -370,7 +852,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit mCurDepthStencilState.stencilPassDepthFail || depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; } @@ -383,33 +865,33 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit depthStencil.stencilBackPassDepthPass != mCurDepthStencilState.stencilBackPassDepthPass) { - mDepthStencilStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); } break; } case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_CULL_FACE: if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_FRONT_FACE: if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: if (state.getRasterizerState().polygonOffsetFill != mCurRasterState.polygonOffsetFill) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_POLYGON_OFFSET: @@ -418,7 +900,7 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; } @@ -426,58 +908,150 @@ void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBit if (state.getRasterizerState().rasterizerDiscard != mCurRasterState.rasterizerDiscard) { - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); + + // Enabling/disabling rasterizer discard affects the pixel shader. + invalidateShaders(); } break; case gl::State::DIRTY_BIT_SCISSOR: if (state.getScissor() != mCurScissorRect) { - mScissorStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); } break; case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: if (state.isScissorTestEnabled() != mCurScissorEnabled) { - mScissorStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); // Rasterizer state update needs mCurScissorsEnabled and updates when it changes - mRasterizerStateIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); } break; case gl::State::DIRTY_BIT_DEPTH_RANGE: if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) { - mViewportStateIsDirty = true; + invalidateViewport(context); } break; case gl::State::DIRTY_BIT_VIEWPORT: if (state.getViewport() != mCurViewport) { - mViewportStateIsDirty = true; + invalidateViewport(context); + } + break; + case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: + invalidateRenderTarget(); + if (mIsMultiviewEnabled) + { + handleMultiviewDrawFramebufferChange(context); + } + break; + case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: + invalidateVertexBuffer(); + // Force invalidate the current value attributes, since the VertexArray11 keeps an + // internal cache of TranslatedAttributes, and they CurrentValue attributes are + // owned by the StateManager11/Context. + mDirtyCurrentValueAttribs.set(); + // Invalidate the cached index buffer. + mIndexBufferIsDirty = true; + break; + case gl::State::DIRTY_BIT_TEXTURE_BINDINGS: + invalidateTexturesAndSamplers(); + break; + case gl::State::DIRTY_BIT_SAMPLER_BINDINGS: + invalidateTexturesAndSamplers(); + break; + case gl::State::DIRTY_BIT_PROGRAM_EXECUTABLE: + { + mInternalDirtyBits.set(DIRTY_BIT_SHADERS); + invalidateVertexBuffer(); + invalidateRenderTarget(); + invalidateTexturesAndSamplers(); + invalidateProgramUniforms(); + invalidateProgramUniformBuffers(); + gl::VertexArray *vao = state.getVertexArray(); + if (mIsMultiviewEnabled && vao != nullptr) + { + // If ANGLE_multiview is enabled, the attribute divisor has to be updated for + // each binding. + VertexArray11 *vao11 = GetImplAs(vao); + const gl::Program *program = state.getProgram(); + int numViews = 1; + if (program != nullptr && program->usesMultiview()) + { + numViews = program->getNumViews(); + } + vao11->markAllAttributeDivisorsForAdjustment(numViews); } break; + } + case gl::State::DIRTY_BIT_CURRENT_VALUES: + { + for (auto attribIndex : state.getAndResetDirtyCurrentValues()) + { + invalidateCurrentValueAttrib(attribIndex); + } + } default: break; } } + + // TODO(jmadill): Input layout and vertex buffer state. } -gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer, - const gl::BlendState &blendState, - const gl::ColorF &blendColor, - unsigned int sampleMask) +void StateManager11::handleMultiviewDrawFramebufferChange(const gl::Context *context) { - if (!mBlendStateIsDirty && sampleMask == mCurSampleMask) + const auto &glState = context->getGLState(); + const gl::Framebuffer *drawFramebuffer = glState.getDrawFramebuffer(); + ASSERT(drawFramebuffer != nullptr); + + // Update viewport offsets. + const std::vector *attachmentViewportOffsets = + drawFramebuffer->getViewportOffsets(); + const std::vector &viewportOffsets = + attachmentViewportOffsets != nullptr + ? *attachmentViewportOffsets + : gl::FramebufferAttachment::GetDefaultViewportOffsetVector(); + if (mViewportOffsets != viewportOffsets) { - return gl::Error(GL_NO_ERROR); - } + mViewportOffsets = viewportOffsets; - ID3D11BlendState *dxBlendState = nullptr; - gl::Error error = - mRenderer->getStateCache().getBlendState(framebuffer, blendState, &dxBlendState); - if (error.isError()) + // Because new viewport offsets are to be applied, we have to mark the internal viewport and + // scissor state as dirty. + invalidateViewport(context); + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); + } + switch (drawFramebuffer->getMultiviewLayout()) { - return error; + case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE: + mShaderConstants.setMultiviewWriteToViewportIndex(1.0f); + break; + case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE: + // Because the base view index is applied as an offset to the 2D texture array when the + // RTV is created, we just have to pass a boolean to select which code path is to be + // used. + mShaderConstants.setMultiviewWriteToViewportIndex(0.0f); + break; + default: + // There is no need to update the value in the constant buffer if the active framebuffer + // object does not have a multiview layout. + break; } +} + +gl::Error StateManager11::syncBlendState(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask) +{ + const d3d11::BlendState *dxBlendState = nullptr; + const d3d11::BlendStateKey &key = + RenderStateCache::GetBlendStateKey(context, framebuffer, blendState); + + ANGLE_TRY(mRenderer->getBlendState(key, &dxBlendState)); ASSERT(dxBlendState != nullptr); @@ -500,62 +1074,53 @@ gl::Error StateManager11::setBlendState(const gl::Framebuffer *framebuffer, blendColors[3] = blendColor.alpha; } - mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState, blendColors, sampleMask); + mRenderer->getDeviceContext()->OMSetBlendState(dxBlendState->get(), blendColors, sampleMask); mCurBlendState = blendState; mCurBlendColor = blendColor; mCurSampleMask = sampleMask; - mBlendStateIsDirty = false; - - return error; + return gl::NoError(); } -gl::Error StateManager11::setDepthStencilState(const gl::State &glState) +gl::Error StateManager11::syncDepthStencilState(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()); + mCurDepthStencilState = glState.getDepthStencilState(); + mCurStencilRef = glState.getStencilRef(); + mCurStencilBackRef = glState.getStencilBackRef(); - // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState. - if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() && - disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() && - disableStencil == mCurDisableStencil.value()) + // get the maximum size of the stencil ref + unsigned int maxStencil = 0; + if (mCurDepthStencilState.stencilTest && mCurStencilSize > 0) { - return gl::Error(GL_NO_ERROR); + maxStencil = (1 << mCurStencilSize) - 1; } + ASSERT((mCurDepthStencilState.stencilWritemask & maxStencil) == + (mCurDepthStencilState.stencilBackWritemask & maxStencil)); + ASSERT(mCurStencilRef == mCurStencilBackRef); + ASSERT((mCurDepthStencilState.stencilMask & maxStencil) == + (mCurDepthStencilState.stencilBackMask & maxStencil)); - const auto &depthStencilState = glState.getDepthStencilState(); - int stencilRef = glState.getStencilRef(); - int stencilBackRef = glState.getStencilBackRef(); + gl::DepthStencilState modifiedGLState = glState.getDepthStencilState(); - // get the maximum size of the stencil ref - unsigned int maxStencil = 0; - if (depthStencilState.stencilTest && mCurStencilSize > 0) + ASSERT(mCurDisableDepth.valid() && mCurDisableStencil.valid()); + + if (mCurDisableDepth.value()) { - maxStencil = (1 << mCurStencilSize) - 1; + modifiedGLState.depthTest = false; + modifiedGLState.depthMask = false; } - 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()) + if (mCurDisableStencil.value()) { - return error; + modifiedGLState.stencilWritemask = 0; + modifiedGLState.stencilBackWritemask = 0; + modifiedGLState.stencilTest = false; } - ASSERT(dxDepthStencilState); + const d3d11::DepthStencilState *d3dState = nullptr; + ANGLE_TRY(mRenderer->getDepthStencilState(modifiedGLState, &d3dState)); + ASSERT(d3dState); // Max D3D11 stencil reference value is 0xFF, // corresponding to the max 8 bits in a stencil buffer @@ -565,30 +1130,21 @@ gl::Error StateManager11::setDepthStencilState(const gl::State &glState) "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); + UINT dxStencilRef = std::min(mCurStencilRef, 0xFFu); - mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); + mRenderer->getDeviceContext()->OMSetDepthStencilState(d3dState->get(), dxStencilRef); - mCurDepthStencilState = depthStencilState; - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; - mCurDisableDepth = disableDepth; - mCurDisableStencil = disableStencil; - - mDepthStencilStateIsDirty = false; - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterState) +gl::Error StateManager11::syncRasterizerState(const gl::Context *context, bool pointDrawMode) { - if (!mRasterizerStateIsDirty) - { - return gl::Error(GL_NO_ERROR); - } + // TODO: Remove pointDrawMode and multiSample from gl::RasterizerState. + gl::RasterizerState rasterState = context->getGLState().getRasterizerState(); + rasterState.pointDrawMode = pointDrawMode; + rasterState.multiSample = mCurRasterState.multiSample; ID3D11RasterizerState *dxRasterState = nullptr; - gl::Error error(GL_NO_ERROR); if (mCurPresentPathFastEnabled) { @@ -607,33 +1163,23 @@ gl::Error StateManager11::setRasterizerState(const gl::RasterizerState &rasterSt modifiedRasterState.frontFace = GL_CCW; } - error = mRenderer->getStateCache().getRasterizerState(modifiedRasterState, - mCurScissorEnabled, &dxRasterState); + ANGLE_TRY( + mRenderer->getRasterizerState(modifiedRasterState, mCurScissorEnabled, &dxRasterState)); } else { - error = mRenderer->getStateCache().getRasterizerState(rasterState, mCurScissorEnabled, - &dxRasterState); - } - - if (error.isError()) - { - return error; + ANGLE_TRY(mRenderer->getRasterizerState(rasterState, mCurScissorEnabled, &dxRasterState)); } mRenderer->getDeviceContext()->RSSetState(dxRasterState); - mCurRasterState = rasterState; - mRasterizerStateIsDirty = false; + mCurRasterState = rasterState; - return error; + return gl::NoError(); } -void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +void StateManager11::syncScissorRectangle(const gl::Rectangle &scissor, bool enabled) { - if (!mScissorStateIsDirty) - return; - int modifiedScissorY = scissor.y; if (mCurPresentPathFastEnabled) { @@ -642,37 +1188,41 @@ void StateManager11::setScissorRectangle(const gl::Rectangle &scissor, bool enab 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); + std::array rectangles; + const UINT numRectangles = static_cast(mViewportOffsets.size()); + for (UINT i = 0u; i < numRectangles; ++i) + { + D3D11_RECT &rect = rectangles[i]; + int x = scissor.x + mViewportOffsets[i].x; + int y = modifiedScissorY + mViewportOffsets[i].y; + rect.left = std::max(0, x); + rect.top = std::max(0, y); + rect.right = x + std::max(0, scissor.width); + rect.bottom = y + std::max(0, scissor.height); + } + mRenderer->getDeviceContext()->RSSetScissorRects(numRectangles, rectangles.data()); } mCurScissorRect = scissor; mCurScissorEnabled = enabled; - mScissorStateIsDirty = false; } -void StateManager11::setViewport(const gl::Caps *caps, - const gl::Rectangle &viewport, - float zNear, - float zFar) +void StateManager11::syncViewport(const gl::Context *context) { - 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); + const auto &glState = context->getGLState(); + gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + float actualZNear = gl::clamp01(glState.getNearPlane()); + float actualZFar = gl::clamp01(glState.getFarPlane()); + + const auto &caps = context->getCaps(); + 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) + bool is9_3 = mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3; + + if (is9_3) { // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget. dxMaxViewportBoundsX = static_cast(mViewportBounds.width); @@ -681,173 +1231,295 @@ void StateManager11::setViewport(const gl::Caps *caps, 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); + const auto &viewport = glState.getViewport(); + std::array dxViewports; + const UINT numRectangles = static_cast(mViewportOffsets.size()); - D3D11_VIEWPORT dxViewport; - dxViewport.TopLeftX = static_cast(dxViewportTopLeftX); + int dxViewportTopLeftX = 0; + int dxViewportTopLeftY = 0; + int dxViewportWidth = 0; + int dxViewportHeight = 0; - 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 + for (UINT i = 0u; i < numRectangles; ++i) { - dxViewport.TopLeftY = static_cast(dxViewportTopLeftY); - } + dxViewportTopLeftX = gl::clamp(viewport.x + mViewportOffsets[i].x, dxMinViewportBoundsX, + dxMaxViewportBoundsX); + dxViewportTopLeftY = gl::clamp(viewport.y + mViewportOffsets[i].y, dxMinViewportBoundsY, + dxMaxViewportBoundsY); + dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); + dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); + + D3D11_VIEWPORT &dxViewport = dxViewports[i]; + 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; + // The es 3.1 spec section 9.2 states that, "If there are no attachments, rendering + // will be limited to a rectangle having a lower left of (0, 0) and an upper right of + // (width, height), where width and height are the framebuffer object's default width + // and height." See http://anglebug.com/1594 + // If the Framebuffer has no color attachment and the default width or height is smaller + // than the current viewport, use the smaller of the two sizes. + // If framebuffer default width or height is 0, the params should not set. + if (!framebuffer->getFirstNonNullAttachment() && + (framebuffer->getDefaultWidth() || framebuffer->getDefaultHeight())) + { + dxViewport.Width = + static_cast(std::min(viewport.width, framebuffer->getDefaultWidth())); + dxViewport.Height = + static_cast(std::min(viewport.height, framebuffer->getDefaultHeight())); + } + else + { + dxViewport.Width = static_cast(dxViewportWidth); + dxViewport.Height = static_cast(dxViewportHeight); + } + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + } - mRenderer->getDeviceContext()->RSSetViewports(1, &dxViewport); + mRenderer->getDeviceContext()->RSSetViewports(numRectangles, dxViewports.data()); 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) + const D3D11_VIEWPORT adjustViewport = {static_cast(dxViewportTopLeftX), + static_cast(dxViewportTopLeftY), + static_cast(dxViewportWidth), + static_cast(dxViewportHeight), + actualZNear, + actualZFar}; + mShaderConstants.onViewportChange(viewport, adjustViewport, is9_3, mCurPresentPathFastEnabled); +} + +void StateManager11::invalidateRenderTarget() +{ + mRenderTargetIsDirty = true; +} + +void StateManager11::processFramebufferInvalidation(const gl::Context *context) +{ + if (!mRenderTargetIsDirty) { - 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; + return; } - 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); + ASSERT(context); - // 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]; + mRenderTargetIsDirty = false; + mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); - mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + // The pixel shader is dependent on the output layout. + invalidateShaders(); - 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; + // The D3D11 blend state is heavily dependent on the current render target. + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); - mPixelConstants.viewScale[0] = 1.0f; - mPixelConstants.viewScale[1] = mCurPresentPathFastEnabled ? 1.0f : -1.0f; - mPixelConstants.viewScale[2] = 1.0f; - mPixelConstants.viewScale[3] = 1.0f; + gl::Framebuffer *fbo = context->getGLState().getDrawFramebuffer(); + ASSERT(fbo); - mVertexConstants.viewScale[0] = mPixelConstants.viewScale[0]; - mVertexConstants.viewScale[1] = mPixelConstants.viewScale[1]; - mVertexConstants.viewScale[2] = mPixelConstants.viewScale[2]; - mVertexConstants.viewScale[3] = mPixelConstants.viewScale[3]; + // 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()); - mViewportStateIsDirty = false; -} + // Similarly we disable the stencil portion of the DS attachment if the app only binds depth. + bool disableStencil = (fbo->hasDepth() && !fbo->hasStencil()); -void StateManager11::invalidateRenderTarget() -{ - for (auto &appliedRTV : mAppliedRTVs) + if (!mCurDisableDepth.valid() || disableDepth != mCurDisableDepth.value() || + !mCurDisableStencil.valid() || disableStencil != mCurDisableStencil.value()) + { + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); + mCurDisableDepth = disableDepth; + mCurDisableStencil = disableStencil; + } + + bool multiSample = (fbo->getCachedSamples(context) != 0); + if (multiSample != mCurRasterState.multiSample) + { + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); + mCurRasterState.multiSample = multiSample; + } + + checkPresentPath(context); + + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) { - appliedRTV = angle::DirtyPointer; + const auto *firstAttachment = fbo->getFirstNonNullAttachment(); + if (firstAttachment) + { + const auto &size = firstAttachment->getSize(); + if (mViewportBounds.width != size.width || mViewportBounds.height != size.height) + { + mViewportBounds = gl::Extents(size.width, size.height, 1); + invalidateViewport(context); + } + } } - mAppliedDSV = angle::DirtyPointer; } -void StateManager11::invalidateEverything() +void StateManager11::invalidateBoundViews() { - 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) +void StateManager11::invalidateVertexBuffer() { - // TODO(jmadill): Use context caps? - UINT drawBuffers = mRenderer->getRendererCaps().maxDrawBuffers; + unsigned int limit = std::min(mRenderer->getNativeCaps().maxVertexAttributes, + gl::MAX_VERTEX_ATTRIBS); + mDirtyVertexBufferRange = gl::RangeUI(0, limit); + mInputLayoutIsDirty = true; + mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS); + invalidateVertexAttributeTranslation(); +} - // 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) +void StateManager11::invalidateViewport(const gl::Context *context) +{ + mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE); + + // Viewport affects the driver constants. + invalidateDriverUniforms(); +} + +void StateManager11::invalidateTexturesAndSamplers() +{ + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); + invalidateSwizzles(); + + // Texture state affects the driver uniforms (base level, etc). + invalidateDriverUniforms(); +} + +void StateManager11::invalidateSwizzles() +{ + mDirtySwizzles = true; +} + +void StateManager11::invalidateProgramUniforms() +{ + mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS); +} + +void StateManager11::invalidateDriverUniforms() +{ + mInternalDirtyBits.set(DIRTY_BIT_DRIVER_UNIFORMS); +} + +void StateManager11::invalidateProgramUniformBuffers() +{ + mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS); +} + +void StateManager11::invalidateConstantBuffer(unsigned int slot) +{ + if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER) + { + invalidateDriverUniforms(); + } + else if (slot == d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK) + { + invalidateProgramUniforms(); + } + else { - return false; + invalidateProgramUniformBuffers(); } +} - // The D3D11 blend state is heavily dependent on the current render target. - mBlendStateIsDirty = true; +void StateManager11::invalidateShaders() +{ + mInternalDirtyBits.set(DIRTY_BIT_SHADERS); +} + +void StateManager11::setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv) +{ + if ((rtv && unsetConflictingView(rtv)) || (dsv && unsetConflictingView(dsv))) + { + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); + } + + mRenderer->getDeviceContext()->OMSetRenderTargets(1, &rtv, dsv); + mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); +} + +void StateManager11::setRenderTargets(ID3D11RenderTargetView **rtvs, + UINT numRTVs, + ID3D11DepthStencilView *dsv) +{ + bool anyDirty = false; + + for (UINT rtvIndex = 0; rtvIndex < numRTVs; ++rtvIndex) + { + anyDirty = anyDirty || unsetConflictingView(rtvs[rtvIndex]); + } - for (UINT rtIndex = 0; rtIndex < drawBuffers; rtIndex++) + if (dsv) { - mAppliedRTVs[rtIndex] = reinterpret_cast(renderTargets[rtIndex]); + anyDirty = anyDirty || unsetConflictingView(dsv); } - mAppliedDSV = reinterpret_cast(depthStencil); - mRenderer->getDeviceContext()->OMSetRenderTargets(drawBuffers, renderTargets.data(), - depthStencil); - return true; + if (anyDirty) + { + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); + } + + mRenderer->getDeviceContext()->OMSetRenderTargets(numRTVs, (numRTVs > 0) ? rtvs : nullptr, dsv); + mInternalDirtyBits.set(DIRTY_BIT_RENDER_TARGET); } -void StateManager11::setRenderTarget(ID3D11RenderTargetView *renderTarget, - ID3D11DepthStencilView *depthStencil) +void StateManager11::invalidateVertexAttributeTranslation() { - mRenderer->getDeviceContext()->OMSetRenderTargets(1, &renderTarget, depthStencil); + mVertexAttribsNeedTranslation = true; } -void StateManager11::setShaderResource(gl::SamplerType shaderType, - UINT resourceSlot, - ID3D11ShaderResourceView *srv) +void StateManager11::onBeginQuery(Query11 *query) { - auto ¤tSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + mCurrentQueries.insert(query); +} - ASSERT(static_cast(resourceSlot) < currentSRVs.size()); - const SRVRecord &record = currentSRVs[resourceSlot]; +void StateManager11::onDeleteQueryObject(Query11 *query) +{ + mCurrentQueries.erase(query); +} - if (record.srv != reinterpret_cast(srv)) +gl::Error StateManager11::onMakeCurrent(const gl::Context *context) +{ + const gl::State &state = context->getGLState(); + + for (Query11 *query : mCurrentQueries) { - auto deviceContext = mRenderer->getDeviceContext(); - if (shaderType == gl::SAMPLER_VERTEX) - { - deviceContext->VSSetShaderResources(resourceSlot, 1, &srv); - } - else + ANGLE_TRY(query->pause()); + } + mCurrentQueries.clear(); + + for (GLenum queryType : QueryTypes) + { + gl::Query *query = state.getActiveQuery(queryType); + if (query != nullptr) { - deviceContext->PSSetShaderResources(resourceSlot, 1, &srv); + Query11 *query11 = GetImplAs(query); + ANGLE_TRY(query11->resume()); + mCurrentQueries.insert(query11); } - - currentSRVs.update(resourceSlot, srv); } + + return gl::NoError(); } gl::Error StateManager11::clearTextures(gl::SamplerType samplerType, @@ -856,185 +1528,1548 @@ gl::Error StateManager11::clearTextures(gl::SamplerType samplerType, { if (rangeStart == rangeEnd) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); - gl::Range clearRange(rangeStart, rangeStart); - clearRange.extend(std::min(rangeEnd, currentSRVs.highestUsed())); - + gl::Range clearRange(rangeStart, std::min(rangeEnd, currentSRVs.highestUsed())); if (clearRange.empty()) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } - auto deviceContext = mRenderer->getDeviceContext(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); if (samplerType == gl::SAMPLER_VERTEX) { - deviceContext->VSSetShaderResources(static_cast(rangeStart), - static_cast(rangeEnd - rangeStart), + deviceContext->VSSetShaderResources(static_cast(clearRange.low()), + static_cast(clearRange.length()), &mNullSRVs[0]); } else { - deviceContext->PSSetShaderResources(static_cast(rangeStart), - static_cast(rangeEnd - rangeStart), + deviceContext->PSSetShaderResources(static_cast(clearRange.low()), + static_cast(clearRange.length()), &mNullSRVs[0]); } - for (size_t samplerIndex = rangeStart; samplerIndex < rangeEnd; ++samplerIndex) + for (size_t samplerIndex : clearRange) { currentSRVs.update(samplerIndex, nullptr); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType, +bool StateManager11::unsetConflictingView(ID3D11View *view) +{ + uintptr_t resource = reinterpret_cast(GetViewResource(view)); + return unsetConflictingSRVs(gl::SAMPLER_VERTEX, resource, nullptr) || + unsetConflictingSRVs(gl::SAMPLER_PIXEL, resource, nullptr); +} + +bool StateManager11::unsetConflictingSRVs(gl::SamplerType samplerType, uintptr_t resource, - const gl::ImageIndex &index) + const gl::ImageIndex *index) { auto ¤tSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs); + bool foundOne = false; + for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex) { auto &record = currentSRVs[resourceIndex]; if (record.srv && record.resource == resource && - ImageIndexConflictsWithSRV(index, record.desc)) + (!index || ImageIndexConflictsWithSRV(*index, record.desc))) { - setShaderResource(samplerType, static_cast(resourceIndex), NULL); + setShaderResourceInternal( + samplerType, static_cast(resourceIndex), nullptr); + foundOne = true; } } + + return foundOne; +} + +void StateManager11::unsetConflictingAttachmentResources( + const gl::FramebufferAttachment *attachment, + ID3D11Resource *resource) +{ + // Unbind render target SRVs from the shader here to prevent D3D11 warnings. + if (attachment->type() == GL_TEXTURE) + { + uintptr_t resourcePtr = reinterpret_cast(resource); + const gl::ImageIndex &index = attachment->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, resourcePtr, &index); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, &index); + } + else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT) + { + uintptr_t resourcePtr = reinterpret_cast(resource); + unsetConflictingSRVs(gl::SAMPLER_VERTEX, resourcePtr, nullptr); + unsetConflictingSRVs(gl::SAMPLER_PIXEL, resourcePtr, nullptr); + } } -void StateManager11::initialize(const gl::Caps &caps) +gl::Error StateManager11::initialize(const gl::Caps &caps, const gl::Extensions &extensions) { mCurVertexSRVs.initialize(caps.maxVertexTextureImageUnits); mCurPixelSRVs.initialize(caps.maxTextureImageUnits); // Initialize cached NULL SRV block mNullSRVs.resize(caps.maxTextureImageUnits, nullptr); + + mCurrentValueAttribs.resize(caps.maxVertexAttributes); + + mForceSetVertexSamplerStates.resize(caps.maxVertexTextureImageUnits, true); + mForceSetPixelSamplerStates.resize(caps.maxTextureImageUnits, true); + mForceSetComputeSamplerStates.resize(caps.maxComputeTextureImageUnits, true); + + mCurVertexSamplerStates.resize(caps.maxVertexTextureImageUnits); + mCurPixelSamplerStates.resize(caps.maxTextureImageUnits); + mCurComputeSamplerStates.resize(caps.maxComputeTextureImageUnits); + + mShaderConstants.init(caps); + + mIsMultiviewEnabled = extensions.multiview; + mViewportOffsets.resize(1u); + + ANGLE_TRY(mVertexDataManager.initialize()); + + mCurrentAttributes.reserve(gl::MAX_VERTEX_ATTRIBS); + + return gl::NoError(); } -gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer) +void StateManager11::deinitialize() { - // 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; + mCurrentValueAttribs.clear(); + mInputLayoutCache.clear(); + mVertexDataManager.deinitialize(); + mIndexDataManager.deinitialize(); + + mDriverConstantBufferVS.reset(); + mDriverConstantBufferPS.reset(); + mDriverConstantBufferCS.reset(); +} - framebufferRTVs.fill(nullptr); +gl::Error StateManager11::syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer) +{ + Framebuffer11 *framebuffer11 = GetImplAs(framebuffer); - const Framebuffer11 *framebuffer11 = GetImplAs(framebuffer); - const gl::AttachmentList &colorbuffers = framebuffer11->getColorAttachmentsForRender(); + // Applies the render target surface, depth stencil surface, viewport rectangle and + // scissor rectangle to the renderer + ASSERT(framebuffer && !framebuffer->hasAnyDirtyBit() && framebuffer->cachedComplete()); - for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) + // 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 (framebuffer->id() == 0) { - const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; - - if (colorbuffer) + ASSERT(!framebuffer11->hasAnyInternalDirtyBit()); + const gl::Extents &size = framebuffer->getFirstColorbuffer()->getSize(); + if (size.width == 0 || size.height == 0) { - // 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); - } + return gl::NoError(); + } + } - // Extract the render target dimensions and view - RenderTarget11 *renderTarget = NULL; - gl::Error error = colorbuffer->getRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } - ASSERT(renderTarget); + RTVArray framebufferRTVs = {{}}; - framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); - ASSERT(framebufferRTVs[colorAttachment]); + const auto &colorRTs = framebuffer11->getCachedColorRenderTargets(); - if (missingColorRenderTarget) - { - renderTargetWidth = renderTarget->getWidth(); - renderTargetHeight = renderTarget->getHeight(); - renderTargetFormat = renderTarget->getDXGIFormat(); - missingColorRenderTarget = false; - } + size_t appliedRTIndex = 0; + bool skipInactiveRTs = mRenderer->getWorkarounds().mrtPerfWorkaround; + const auto &drawStates = framebuffer->getDrawBufferStates(); + gl::DrawBufferMask activeProgramOutputs = + context->getContextState().getState().getProgram()->getActiveOutputVariables(); + UINT maxExistingRT = 0; - // 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); - } + for (size_t rtIndex = 0; rtIndex < colorRTs.size(); ++rtIndex) + { + const RenderTarget11 *renderTarget = colorRTs[rtIndex]; + + // Skip inactive rendertargets if the workaround is enabled. + if (skipInactiveRTs && + (!renderTarget || drawStates[rtIndex] == GL_NONE || !activeProgramOutputs[rtIndex])) + { + continue; } - } - // 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()) + if (renderTarget) { - return error; + framebufferRTVs[appliedRTIndex] = renderTarget->getRenderTargetView().get(); + ASSERT(framebufferRTVs[appliedRTIndex]); + maxExistingRT = static_cast(appliedRTIndex) + 1; + + // Unset conflicting texture SRVs + const auto *attachment = framebuffer->getColorbuffer(rtIndex); + ASSERT(attachment); + unsetConflictingAttachmentResources(attachment, renderTarget->getTexture().get()); } - ASSERT(depthStencilRenderTarget); - framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); + appliedRTIndex++; + } + + // Get the depth stencil buffers + ID3D11DepthStencilView *framebufferDSV = nullptr; + const auto *depthStencilRenderTarget = framebuffer11->getCachedDepthStencilRenderTarget(); + if (depthStencilRenderTarget) + { + framebufferDSV = depthStencilRenderTarget->getDepthStencilView().get(); 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(); - } + // Unset conflicting texture SRVs + const auto *attachment = framebuffer->getDepthOrStencilbuffer(); + ASSERT(attachment); + unsetConflictingAttachmentResources(attachment, + depthStencilRenderTarget->getTexture().get()); + } + + // TODO(jmadill): Use context caps? + ASSERT(maxExistingRT <= static_cast(mRenderer->getNativeCaps().maxDrawBuffers)); + + // Apply the render target and depth stencil + mRenderer->getDeviceContext()->OMSetRenderTargets(maxExistingRT, framebufferRTVs.data(), + framebufferDSV); + + return gl::NoError(); +} + +void StateManager11::invalidateCurrentValueAttrib(size_t attribIndex) +{ + mDirtyCurrentValueAttribs.set(attribIndex); + mInternalDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_ATTRIBS); +} + +gl::Error StateManager11::syncCurrentValueAttribs(const gl::State &glState) +{ + const auto &activeAttribsMask = glState.getProgram()->getActiveAttribLocationsMask(); + const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs); + + if (!dirtyActiveAttribs.any()) + { + return gl::NoError(); + } + + const auto &vertexAttributes = glState.getVertexArray()->getVertexAttributes(); + const auto &vertexBindings = glState.getVertexArray()->getVertexBindings(); + mDirtyCurrentValueAttribs = (mDirtyCurrentValueAttribs & ~dirtyActiveAttribs); + + for (auto attribIndex : dirtyActiveAttribs) + { + if (vertexAttributes[attribIndex].enabled) + continue; + + const auto *attrib = &vertexAttributes[attribIndex]; + const auto ¤tValue = glState.getVertexAttribCurrentValue(attribIndex); + TranslatedAttribute *currentValueAttrib = &mCurrentValueAttribs[attribIndex]; + currentValueAttrib->currentValueType = currentValue.Type; + currentValueAttrib->attribute = attrib; + currentValueAttrib->binding = &vertexBindings[attrib->bindingIndex]; - // Unbind render target SRVs from the shader here to prevent D3D11 warnings. - if (depthStencil->type() == GL_TEXTURE) + mDirtyVertexBufferRange.extend(static_cast(attribIndex)); + mInputLayoutIsDirty = true; + + ANGLE_TRY(mVertexDataManager.storeCurrentValue(currentValue, currentValueAttrib, + static_cast(attribIndex))); + } + + return gl::NoError(); +} + +void StateManager11::setInputLayout(const d3d11::InputLayout *inputLayout) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + if (inputLayout == nullptr) + { + if (!mCurrentInputLayout.empty()) { - 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); + deviceContext->IASetInputLayout(nullptr); + mCurrentInputLayout.clear(); + mInputLayoutIsDirty = true; } } + else if (inputLayout->getSerial() != mCurrentInputLayout) + { + deviceContext->IASetInputLayout(inputLayout->get()); + mCurrentInputLayout = inputLayout->getSerial(); + mInputLayoutIsDirty = true; + } +} + +bool StateManager11::queueVertexBufferChange(size_t bufferIndex, + ID3D11Buffer *buffer, + UINT stride, + UINT offset) +{ + if (buffer != mCurrentVertexBuffers[bufferIndex] || + stride != mCurrentVertexStrides[bufferIndex] || + offset != mCurrentVertexOffsets[bufferIndex]) + { + mInputLayoutIsDirty = true; + mDirtyVertexBufferRange.extend(static_cast(bufferIndex)); + + mCurrentVertexBuffers[bufferIndex] = buffer; + mCurrentVertexStrides[bufferIndex] = stride; + mCurrentVertexOffsets[bufferIndex] = offset; + return true; + } + + return false; +} + +bool StateManager11::queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly) +{ + if (offsetOnly != mCurrentVertexOffsets[bufferIndex]) + { + mInputLayoutIsDirty = true; + mDirtyVertexBufferRange.extend(static_cast(bufferIndex)); + mCurrentVertexOffsets[bufferIndex] = offsetOnly; + return true; + } + return false; +} + +void StateManager11::applyVertexBufferChanges() +{ + if (mDirtyVertexBufferRange.empty()) + { + return; + } + + ASSERT(mDirtyVertexBufferRange.high() <= gl::MAX_VERTEX_ATTRIBS); + + UINT start = static_cast(mDirtyVertexBufferRange.low()); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->IASetVertexBuffers(start, static_cast(mDirtyVertexBufferRange.length()), + &mCurrentVertexBuffers[start], &mCurrentVertexStrides[start], + &mCurrentVertexOffsets[start]); + + mDirtyVertexBufferRange = gl::RangeUI(gl::MAX_VERTEX_ATTRIBS, 0); +} + +void StateManager11::setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset) +{ + ID3D11Buffer *native = buffer ? buffer->get() : nullptr; + if (queueVertexBufferChange(0, native, stride, offset)) + { + applyVertexBufferChanges(); + } +} + +gl::Error StateManager11::updateState(const gl::Context *context, GLenum drawMode) +{ + const auto &glState = context->getGLState(); + auto *programD3D = GetImplAs(glState.getProgram()); + + // TODO(jmadill): Use dirty bits. + processFramebufferInvalidation(context); + + // TODO(jmadill): Use dirty bits. + if (programD3D->updateSamplerMapping() == ProgramD3D::SamplerMapping::WasDirty) + { + invalidateTexturesAndSamplers(); + } + + // TODO(jmadill): Use dirty bits. + if (programD3D->areVertexUniformsDirty() || programD3D->areFragmentUniformsDirty()) + { + mInternalDirtyBits.set(DIRTY_BIT_PROGRAM_UNIFORMS); + } + + // Transform feedback affects the stream-out geometry shader. + // TODO(jmadill): Use dirty bits. + if (glState.isTransformFeedbackActiveUnpaused() != mIsTransformFeedbackCurrentlyActiveUnpaused) + { + mIsTransformFeedbackCurrentlyActiveUnpaused = glState.isTransformFeedbackActiveUnpaused(); + invalidateShaders(); + } + + // Swizzling can cause internal state changes with blit shaders. + if (mDirtySwizzles) + { + ANGLE_TRY(generateSwizzles(context)); + mDirtySwizzles = false; + } + + gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); + Framebuffer11 *framebuffer11 = GetImplAs(framebuffer); + ANGLE_TRY(framebuffer11->markAttachmentsDirty(context)); + + if (framebuffer11->hasAnyInternalDirtyBit()) + { + ASSERT(framebuffer->id() != 0); + framebuffer11->syncInternalState(context); + } + + bool pointDrawMode = (drawMode == GL_POINTS); + if (pointDrawMode != mCurRasterState.pointDrawMode) + { + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); + + // Changing from points to not points (or vice-versa) affects the geometry shader. + invalidateShaders(); + } + + // TODO(jiawei.shao@intel.com): This can be recomputed only on framebuffer or multisample mask + // state changes. + RenderTarget11 *firstRT = framebuffer11->getFirstRenderTarget(); + int samples = (firstRT ? firstRT->getSamples() : 0); + unsigned int sampleMask = GetBlendSampleMask(glState, samples); + if (sampleMask != mCurSampleMask) + { + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); + } + + // Changing the vertex attribute state can affect the vertex shader. + gl::VertexArray *vao = glState.getVertexArray(); + VertexArray11 *vao11 = GetImplAs(vao); + if (vao11->flushAttribUpdates(context)) + { + mInternalDirtyBits.set(DIRTY_BIT_SHADERS); + } - if (setRenderTargets(framebufferRTVs, framebufferDSV)) + auto dirtyBitsCopy = mInternalDirtyBits; + mInternalDirtyBits.reset(); + + for (auto dirtyBit : dirtyBitsCopy) { - setViewportBounds(renderTargetWidth, renderTargetHeight); + switch (dirtyBit) + { + case DIRTY_BIT_RENDER_TARGET: + ANGLE_TRY(syncFramebuffer(context, framebuffer)); + break; + case DIRTY_BIT_VIEWPORT_STATE: + syncViewport(context); + break; + case DIRTY_BIT_SCISSOR_STATE: + syncScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled()); + break; + case DIRTY_BIT_RASTERIZER_STATE: + ANGLE_TRY(syncRasterizerState(context, pointDrawMode)); + break; + case DIRTY_BIT_BLEND_STATE: + ANGLE_TRY(syncBlendState(context, framebuffer, glState.getBlendState(), + glState.getBlendColor(), sampleMask)); + break; + case DIRTY_BIT_DEPTH_STENCIL_STATE: + ANGLE_TRY(syncDepthStencilState(glState)); + break; + case DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE: + // TODO(jmadill): More fine-grained update. + ANGLE_TRY(syncTextures(context)); + break; + case DIRTY_BIT_PROGRAM_UNIFORMS: + ANGLE_TRY(applyUniforms(programD3D)); + break; + case DIRTY_BIT_DRIVER_UNIFORMS: + // This must happen after viewport sync; the viewport affects builtin uniforms. + ANGLE_TRY(applyDriverUniforms(*programD3D)); + break; + case DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS: + ANGLE_TRY(syncUniformBuffers(context, programD3D)); + break; + case DIRTY_BIT_SHADERS: + ANGLE_TRY(syncProgram(context, drawMode)); + break; + case DIRTY_BIT_CURRENT_VALUE_ATTRIBS: + ANGLE_TRY(syncCurrentValueAttribs(glState)); + break; + default: + UNREACHABLE(); + break; + } } - gl::Error error = framebuffer11->invalidateSwizzles(); - if (error.isError()) + ANGLE_TRY(syncTransformFeedbackBuffers(context)); + + // Check that we haven't set any dirty bits in the flushing of the dirty bits loop. + ASSERT(mInternalDirtyBits.none()); + + return gl::NoError(); +} + +void StateManager11::setShaderResourceShared(gl::SamplerType shaderType, + UINT resourceSlot, + const d3d11::SharedSRV *srv) +{ + setShaderResourceInternal(shaderType, resourceSlot, srv); + + // TODO(jmadill): Narrower dirty region. + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); +} + +void StateManager11::setShaderResource(gl::SamplerType shaderType, + UINT resourceSlot, + const d3d11::ShaderResourceView *srv) +{ + setShaderResourceInternal(shaderType, resourceSlot, srv); + + // TODO(jmadill): Narrower dirty region. + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); +} + +void StateManager11::setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology) +{ + if (primitiveTopology != mCurrentPrimitiveTopology) { - return error; + mRenderer->getDeviceContext()->IASetPrimitiveTopology(primitiveTopology); + mCurrentPrimitiveTopology = primitiveTopology; } +} - return gl::Error(GL_NO_ERROR); +void StateManager11::setDrawShaders(const d3d11::VertexShader *vertexShader, + const d3d11::GeometryShader *geometryShader, + const d3d11::PixelShader *pixelShader) +{ + setVertexShader(vertexShader); + setGeometryShader(geometryShader); + setPixelShader(pixelShader); +} + +void StateManager11::setVertexShader(const d3d11::VertexShader *shader) +{ + ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); + + if (serial != mAppliedVertexShader) + { + ID3D11VertexShader *appliedShader = shader ? shader->get() : nullptr; + mRenderer->getDeviceContext()->VSSetShader(appliedShader, nullptr, 0); + mAppliedVertexShader = serial; + invalidateShaders(); + } +} + +void StateManager11::setGeometryShader(const d3d11::GeometryShader *shader) +{ + ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); + + if (serial != mAppliedGeometryShader) + { + ID3D11GeometryShader *appliedShader = shader ? shader->get() : nullptr; + mRenderer->getDeviceContext()->GSSetShader(appliedShader, nullptr, 0); + mAppliedGeometryShader = serial; + invalidateShaders(); + } +} + +void StateManager11::setPixelShader(const d3d11::PixelShader *shader) +{ + ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); + + if (serial != mAppliedPixelShader) + { + ID3D11PixelShader *appliedShader = shader ? shader->get() : nullptr; + mRenderer->getDeviceContext()->PSSetShader(appliedShader, nullptr, 0); + mAppliedPixelShader = serial; + invalidateShaders(); + } +} + +void StateManager11::setComputeShader(const d3d11::ComputeShader *shader) +{ + ResourceSerial serial = shader ? shader->getSerial() : ResourceSerial(0); + + if (serial != mAppliedComputeShader) + { + ID3D11ComputeShader *appliedShader = shader ? shader->get() : nullptr; + mRenderer->getDeviceContext()->CSSetShader(appliedShader, nullptr, 0); + mAppliedComputeShader = serial; + // TODO(jmadill): Dirty bits for compute. + } +} + +void StateManager11::setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + auto ¤tSerial = mCurrentConstantBufferVS[slot]; + + mCurrentConstantBufferVSOffset[slot] = 0; + mCurrentConstantBufferVSSize[slot] = 0; + + if (buffer) + { + if (currentSerial != buffer->getSerial()) + { + deviceContext->VSSetConstantBuffers(slot, 1, buffer->getPointer()); + currentSerial = buffer->getSerial(); + invalidateConstantBuffer(slot); + } + } + else + { + if (!currentSerial.empty()) + { + ID3D11Buffer *nullBuffer = nullptr; + deviceContext->VSSetConstantBuffers(slot, 1, &nullBuffer); + currentSerial.clear(); + invalidateConstantBuffer(slot); + } + } +} + +void StateManager11::setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + auto ¤tSerial = mCurrentConstantBufferPS[slot]; + + mCurrentConstantBufferPSOffset[slot] = 0; + mCurrentConstantBufferPSSize[slot] = 0; + + if (buffer) + { + if (currentSerial != buffer->getSerial()) + { + deviceContext->PSSetConstantBuffers(slot, 1, buffer->getPointer()); + currentSerial = buffer->getSerial(); + invalidateConstantBuffer(slot); + } + } + else + { + if (!currentSerial.empty()) + { + ID3D11Buffer *nullBuffer = nullptr; + deviceContext->PSSetConstantBuffers(slot, 1, &nullBuffer); + currentSerial.clear(); + invalidateConstantBuffer(slot); + } + } +} + +void StateManager11::setDepthStencilState(const d3d11::DepthStencilState *depthStencilState, + UINT stencilRef) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (depthStencilState) + { + deviceContext->OMSetDepthStencilState(depthStencilState->get(), stencilRef); + } + else + { + deviceContext->OMSetDepthStencilState(nullptr, stencilRef); + } + + mInternalDirtyBits.set(DIRTY_BIT_DEPTH_STENCIL_STATE); +} + +void StateManager11::setSimpleBlendState(const d3d11::BlendState *blendState) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (blendState) + { + deviceContext->OMSetBlendState(blendState->get(), nullptr, 0xFFFFFFFF); + } + else + { + deviceContext->OMSetBlendState(nullptr, nullptr, 0xFFFFFFFF); + } + + mInternalDirtyBits.set(DIRTY_BIT_BLEND_STATE); +} + +void StateManager11::setRasterizerState(const d3d11::RasterizerState *rasterizerState) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (rasterizerState) + { + deviceContext->RSSetState(rasterizerState->get()); + } + else + { + deviceContext->RSSetState(nullptr); + } + + mInternalDirtyBits.set(DIRTY_BIT_RASTERIZER_STATE); +} + +void StateManager11::setSimpleViewport(const gl::Extents &extents) +{ + setSimpleViewport(extents.width, extents.height); +} + +void StateManager11::setSimpleViewport(int width, int height) +{ + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast(width); + viewport.Height = static_cast(height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + + mRenderer->getDeviceContext()->RSSetViewports(1, &viewport); + mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE); +} + +void StateManager11::setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv, + const d3d11::SamplerState &samplerState) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + setShaderResourceInternal(gl::SAMPLER_PIXEL, 0, &srv); + deviceContext->PSSetSamplers(0, 1, samplerState.getPointer()); + + mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE); + mForceSetPixelSamplerStates[0] = true; +} + +void StateManager11::setSimpleScissorRect(const gl::Rectangle &glRect) +{ + D3D11_RECT scissorRect; + scissorRect.left = glRect.x; + scissorRect.right = glRect.x + glRect.width; + scissorRect.top = glRect.y; + scissorRect.bottom = glRect.y + glRect.height; + setScissorRectD3D(scissorRect); +} + +void StateManager11::setScissorRectD3D(const D3D11_RECT &d3dRect) +{ + mRenderer->getDeviceContext()->RSSetScissorRects(1, &d3dRect); + mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE); +} + +// 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 StateManager11::applyTextures(const gl::Context *context, gl::SamplerType shaderType) +{ + const auto &glState = context->getGLState(); + const auto &caps = context->getCaps(); + ProgramD3D *programD3D = GetImplAs(glState.getProgram()); + + ASSERT(!programD3D->isSamplerMappingDirty()); + + // TODO(jmadill): Use the Program's sampler bindings. + const auto &completeTextures = glState.getCompleteTextureCache(); + + unsigned int samplerRange = programD3D->getUsedSamplerRange(shaderType); + for (unsigned int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) + { + GLint textureUnit = programD3D->getSamplerMapping(shaderType, samplerIndex, caps); + ASSERT(textureUnit != -1); + gl::Texture *texture = completeTextures[textureUnit]; + + // A nullptr texture indicates incomplete. + if (texture) + { + gl::Sampler *samplerObject = glState.getSampler(textureUnit); + + const gl::SamplerState &samplerState = + samplerObject ? samplerObject->getSamplerState() : texture->getSamplerState(); + + ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, texture, samplerState)); + ANGLE_TRY(setTexture(context, shaderType, samplerIndex, texture)); + } + else + { + GLenum textureType = programD3D->getSamplerTextureType(shaderType, samplerIndex); + + // Texture is not sampler complete or it is in use by the framebuffer. Bind the + // incomplete texture. + gl::Texture *incompleteTexture = nullptr; + ANGLE_TRY(mRenderer->getIncompleteTexture(context, textureType, &incompleteTexture)); + ANGLE_TRY(setSamplerState(context, shaderType, samplerIndex, incompleteTexture, + incompleteTexture->getSamplerState())); + ANGLE_TRY(setTexture(context, shaderType, samplerIndex, incompleteTexture)); + } + } + + // Set all the remaining textures to NULL + size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? caps.maxTextureImageUnits + : caps.maxVertexTextureImageUnits; + ANGLE_TRY(clearTextures(shaderType, samplerRange, samplerCount)); + + return gl::NoError(); +} + +gl::Error StateManager11::syncTextures(const gl::Context *context) +{ + ANGLE_TRY(applyTextures(context, gl::SAMPLER_VERTEX)); + ANGLE_TRY(applyTextures(context, gl::SAMPLER_PIXEL)); + return gl::NoError(); +} + +gl::Error StateManager11::setSamplerState(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &samplerState) +{ +#if !defined(NDEBUG) + // Storage should exist, texture should be complete. Only verified in Debug. + TextureD3D *textureD3D = GetImplAs(texture); + TextureStorage *storage = nullptr; + ANGLE_TRY(textureD3D->getNativeTexture(context, &storage)); + ASSERT(storage); +#endif // !defined(NDEBUG) + + auto *deviceContext = mRenderer->getDeviceContext(); + + if (type == gl::SAMPLER_PIXEL) + { + ASSERT(static_cast(index) < mRenderer->getNativeCaps().maxTextureImageUnits); + + if (mForceSetPixelSamplerStates[index] || + memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = nullptr; + ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState)); + + ASSERT(dxSamplerState != nullptr); + deviceContext->PSSetSamplers(index, 1, &dxSamplerState); + + mCurPixelSamplerStates[index] = samplerState; + } + + mForceSetPixelSamplerStates[index] = false; + } + else if (type == gl::SAMPLER_VERTEX) + { + ASSERT(static_cast(index) < + mRenderer->getNativeCaps().maxVertexTextureImageUnits); + + if (mForceSetVertexSamplerStates[index] || + memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = nullptr; + ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState)); + + ASSERT(dxSamplerState != nullptr); + deviceContext->VSSetSamplers(index, 1, &dxSamplerState); + + mCurVertexSamplerStates[index] = samplerState; + } + + mForceSetVertexSamplerStates[index] = false; + } + else if (type == gl::SAMPLER_COMPUTE) + { + ASSERT(static_cast(index) < + mRenderer->getNativeCaps().maxComputeTextureImageUnits); + + if (mForceSetComputeSamplerStates[index] || + memcmp(&samplerState, &mCurComputeSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = nullptr; + ANGLE_TRY(mRenderer->getSamplerState(samplerState, &dxSamplerState)); + + ASSERT(dxSamplerState != nullptr); + deviceContext->CSSetSamplers(index, 1, &dxSamplerState); + + mCurComputeSamplerStates[index] = samplerState; + } + + mForceSetComputeSamplerStates[index] = false; + } + else + UNREACHABLE(); + + // Sampler metadata that's passed to shaders in uniforms is stored separately from rest of the + // sampler state since having it in contiguous memory makes it possible to memcpy to a constant + // buffer, and it doesn't affect the state set by PSSetSamplers/VSSetSamplers. + mShaderConstants.onSamplerChange(type, index, *texture); + + return gl::NoError(); +} + +gl::Error StateManager11::setTexture(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture) +{ + const d3d11::SharedSRV *textureSRV = nullptr; + + if (texture) + { + TextureD3D *textureImpl = GetImplAs(texture); + + TextureStorage *texStorage = nullptr; + ANGLE_TRY(textureImpl->getNativeTexture(context, &texStorage)); + + // Texture should be complete and have a storage + ASSERT(texStorage); + + TextureStorage11 *storage11 = GetAs(texStorage); + + ANGLE_TRY(storage11->getSRV(context, texture->getTextureState(), &textureSRV)); + + // If we get an invalid SRV here, something went wrong in the texture class and we're + // unexpectedly missing the shader resource view. + ASSERT(textureSRV->valid()); + + textureImpl->resetDirty(); + } + + ASSERT( + (type == gl::SAMPLER_PIXEL && + static_cast(index) < mRenderer->getNativeCaps().maxTextureImageUnits) || + (type == gl::SAMPLER_VERTEX && + static_cast(index) < mRenderer->getNativeCaps().maxVertexTextureImageUnits)); + + setShaderResourceInternal(type, index, textureSRV); + return gl::NoError(); +} + +// Things that affect a program's dirtyness: +// 1. Directly changing the program executable -> triggered in StateManager11::syncState. +// 2. The vertex attribute layout -> triggered in VertexArray11::syncState/signal. +// 3. The fragment shader's rendertargets -> triggered in Framebuffer11::syncState/signal. +// 4. Enabling/disabling rasterizer discard. -> triggered in StateManager11::syncState. +// 5. Enabling/disabling transform feedback. -> checked in StateManager11::updateState. +// 6. An internal shader was used. -> triggered in StateManager11::set*Shader. +// 7. Drawing with/without point sprites. -> checked in StateManager11::updateState. +// TODO(jmadill): Use dirty bits for transform feedback. +gl::Error StateManager11::syncProgram(const gl::Context *context, GLenum drawMode) +{ + Context11 *context11 = GetImplAs(context); + ANGLE_TRY(context11->triggerDrawCallProgramRecompilation(context, drawMode)); + + const auto &glState = context->getGLState(); + const auto *va11 = GetImplAs(glState.getVertexArray()); + auto *programD3D = GetImplAs(glState.getProgram()); + + programD3D->updateCachedInputLayout(va11->getCurrentStateSerial(), glState); + + // Binaries must be compiled before the sync. + ASSERT(programD3D->hasVertexExecutableForCachedInputLayout()); + ASSERT(programD3D->hasGeometryExecutableForPrimitiveType(drawMode)); + ASSERT(programD3D->hasPixelExecutableForCachedOutputLayout()); + + ShaderExecutableD3D *vertexExe = nullptr; + ANGLE_TRY(programD3D->getVertexExecutableForCachedInputLayout(&vertexExe, nullptr)); + + ShaderExecutableD3D *pixelExe = nullptr; + ANGLE_TRY(programD3D->getPixelExecutableForCachedOutputLayout(&pixelExe, nullptr)); + + ShaderExecutableD3D *geometryExe = nullptr; + ANGLE_TRY(programD3D->getGeometryExecutableForPrimitiveType(context, drawMode, &geometryExe, + nullptr)); + + const d3d11::VertexShader *vertexShader = + (vertexExe ? &GetAs(vertexExe)->getVertexShader() : nullptr); + + // Skip pixel shader if we're doing rasterizer discard. + const d3d11::PixelShader *pixelShader = nullptr; + if (!glState.getRasterizerState().rasterizerDiscard) + { + pixelShader = (pixelExe ? &GetAs(pixelExe)->getPixelShader() : nullptr); + } + + const d3d11::GeometryShader *geometryShader = nullptr; + if (glState.isTransformFeedbackActiveUnpaused()) + { + geometryShader = + (vertexExe ? &GetAs(vertexExe)->getStreamOutShader() : nullptr); + } + else + { + geometryShader = + (geometryExe ? &GetAs(geometryExe)->getGeometryShader() : nullptr); + } + + setDrawShaders(vertexShader, geometryShader, pixelShader); + + // Explicitly clear the shaders dirty bit. + mInternalDirtyBits.reset(DIRTY_BIT_SHADERS); + + return gl::NoError(); +} + +gl::Error StateManager11::applyVertexBuffer(const gl::Context *context, + GLenum mode, + const DrawCallVertexParams &vertexParams, + bool isIndexedRendering) +{ + const auto &state = context->getGLState(); + const gl::VertexArray *vertexArray = state.getVertexArray(); + VertexArray11 *vertexArray11 = GetImplAs(vertexArray); + + if (mVertexAttribsNeedTranslation) + { + ANGLE_TRY(vertexArray11->updateDirtyAndDynamicAttribs(context, &mVertexDataManager, + vertexParams)); + mInputLayoutIsDirty = true; + + // Determine if we need to update attribs on the next draw. + mVertexAttribsNeedTranslation = (vertexArray11->hasActiveDynamicAttrib(context)); + } + + if (!mLastFirstVertex.valid() || mLastFirstVertex.value() != vertexParams.firstVertex()) + { + mLastFirstVertex = vertexParams.firstVertex(); + mInputLayoutIsDirty = true; + } + + if (!mInputLayoutIsDirty) + { + return gl::NoError(); + } + + const auto &vertexArrayAttribs = vertexArray11->getTranslatedAttribs(); + gl::Program *program = state.getProgram(); + + // Sort the attributes according to ensure we re-use similar input layouts. + AttribIndexArray sortedSemanticIndices; + SortAttributesByLayout(program, vertexArrayAttribs, mCurrentValueAttribs, + &sortedSemanticIndices, &mCurrentAttributes); + + auto featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel; + + // If we are using FL 9_3, make sure the first attribute is not instanced + if (featureLevel <= D3D_FEATURE_LEVEL_9_3 && !mCurrentAttributes.empty()) + { + if (mCurrentAttributes[0]->divisor > 0) + { + Optional firstNonInstancedIndex = FindFirstNonInstanced(mCurrentAttributes); + if (firstNonInstancedIndex.valid()) + { + size_t index = firstNonInstancedIndex.value(); + std::swap(mCurrentAttributes[0], mCurrentAttributes[index]); + std::swap(sortedSemanticIndices[0], sortedSemanticIndices[index]); + } + } + } + + // Update the applied input layout by querying the cache. + ANGLE_TRY(mInputLayoutCache.updateInputLayout(mRenderer, state, mCurrentAttributes, mode, + sortedSemanticIndices, vertexParams)); + + // Update the applied vertex buffers. + ANGLE_TRY(mInputLayoutCache.applyVertexBuffers(context, mCurrentAttributes, mode, + vertexParams.firstVertex(), isIndexedRendering)); + + // InputLayoutCache::applyVertexBuffers calls through to the Bufer11 to get the native vertex + // buffer (ID3D11Buffer *). Because we allocate these buffers lazily, this will trigger + // allocation. This in turn will signal that the buffer is dirty. Since we just resolved the + // dirty-ness in VertexArray11::updateDirtyAndDynamicAttribs, this can make us do a needless + // update on the second draw call. + // Hence we clear the flags here, after we've applied vertex data, since we know everything + // is clean. This is a bit of a hack. + vertexArray11->clearDirtyAndPromoteDynamicAttribs(context, vertexParams); + + mInputLayoutIsDirty = false; + return gl::NoError(); +} + +gl::Error StateManager11::applyIndexBuffer(const gl::Context *context, + const void *indices, + GLsizei count, + GLenum type, + const gl::HasIndexRange &lazyIndexRange, + bool usePrimitiveRestartWorkaround) +{ + const auto &glState = context->getGLState(); + gl::VertexArray *vao = glState.getVertexArray(); + VertexArray11 *vao11 = GetImplAs(vao); + + GLenum destElementType = + GetIndexTranslationDestType(type, lazyIndexRange, usePrimitiveRestartWorkaround); + + if (!vao11->updateElementArrayStorage(context, type, destElementType, indices) && + !mIndexBufferIsDirty) + { + // No streaming or index buffer application necessary. + return gl::NoError(); + } + + gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer().get(); + + TranslatedIndexData *indexInfo = vao11->getCachedIndexInfo(); + ANGLE_TRY(mIndexDataManager.prepareIndexData(context, type, destElementType, count, + elementArrayBuffer, indices, indexInfo)); + + ID3D11Buffer *buffer = nullptr; + DXGI_FORMAT bufferFormat = + (indexInfo->indexType == GL_UNSIGNED_INT) ? DXGI_FORMAT_R32_UINT : DXGI_FORMAT_R16_UINT; + + if (indexInfo->storage) + { + Buffer11 *storage = GetAs(indexInfo->storage); + ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_INDEX), buffer); + } + else + { + IndexBuffer11 *indexBuffer = GetAs(indexInfo->indexBuffer); + buffer = indexBuffer->getBuffer().get(); + } + + // Track dirty indices in the index range cache. + indexInfo->srcIndexData.srcIndicesChanged = + syncIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); + + mIndexBufferIsDirty = false; + + vao11->setCachedIndexInfoValid(); + return gl::NoError(); +} + +void StateManager11::setIndexBuffer(ID3D11Buffer *buffer, + DXGI_FORMAT indexFormat, + unsigned int offset) +{ + if (syncIndexBuffer(buffer, indexFormat, offset)) + { + mIndexBufferIsDirty = true; + } +} + +bool StateManager11::syncIndexBuffer(ID3D11Buffer *buffer, + DXGI_FORMAT indexFormat, + unsigned int offset) +{ + if (buffer != mAppliedIB || indexFormat != mAppliedIBFormat || offset != mAppliedIBOffset) + { + mRenderer->getDeviceContext()->IASetIndexBuffer(buffer, indexFormat, offset); + + mAppliedIB = buffer; + mAppliedIBFormat = indexFormat; + mAppliedIBOffset = offset; + return true; + } + + return false; +} + +// Vertex buffer is invalidated outside this function. +gl::Error StateManager11::updateVertexOffsetsForPointSpritesEmulation(GLint startVertex, + GLsizei emulatedInstanceId) +{ + return mInputLayoutCache.updateVertexOffsetsForPointSpritesEmulation( + mRenderer, mCurrentAttributes, startVertex, emulatedInstanceId); +} + +gl::Error StateManager11::generateSwizzle(const gl::Context *context, gl::Texture *texture) +{ + if (!texture) + { + return gl::NoError(); + } + + TextureD3D *textureD3D = GetImplAs(texture); + ASSERT(textureD3D); + + TextureStorage *texStorage = nullptr; + ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage)); + + if (texStorage) + { + TextureStorage11 *storage11 = GetAs(texStorage); + const gl::TextureState &textureState = texture->getTextureState(); + ANGLE_TRY(storage11->generateSwizzles(context, textureState.getSwizzleState())); + } + + return gl::NoError(); +} + +gl::Error StateManager11::generateSwizzlesForShader(const gl::Context *context, + gl::SamplerType type) +{ + const auto &glState = context->getGLState(); + ProgramD3D *programD3D = GetImplAs(glState.getProgram()); + + unsigned int samplerRange = programD3D->getUsedSamplerRange(type); + + for (unsigned int i = 0; i < samplerRange; i++) + { + GLenum textureType = programD3D->getSamplerTextureType(type, i); + GLint textureUnit = programD3D->getSamplerMapping(type, i, context->getCaps()); + if (textureUnit != -1) + { + gl::Texture *texture = glState.getSamplerTexture(textureUnit, textureType); + ASSERT(texture); + if (texture->getTextureState().swizzleRequired()) + { + ANGLE_TRY(generateSwizzle(context, texture)); + } + } + } + + return gl::NoError(); +} + +gl::Error StateManager11::generateSwizzles(const gl::Context *context) +{ + ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_VERTEX)); + ANGLE_TRY(generateSwizzlesForShader(context, gl::SAMPLER_PIXEL)); + return gl::NoError(); +} + +gl::Error StateManager11::applyUniforms(ProgramD3D *programD3D) +{ + UniformStorage11 *vertexUniformStorage = + GetAs(&programD3D->getVertexUniformStorage()); + UniformStorage11 *fragmentUniformStorage = + GetAs(&programD3D->getFragmentUniformStorage()); + ASSERT(vertexUniformStorage); + ASSERT(fragmentUniformStorage); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + const d3d11::Buffer *vertexConstantBuffer = nullptr; + ANGLE_TRY(vertexUniformStorage->getConstantBuffer(mRenderer, &vertexConstantBuffer)); + const d3d11::Buffer *pixelConstantBuffer = nullptr; + ANGLE_TRY(fragmentUniformStorage->getConstantBuffer(mRenderer, &pixelConstantBuffer)); + + if (vertexUniformStorage->size() > 0 && programD3D->areVertexUniformsDirty()) + { + UpdateUniformBuffer(deviceContext, vertexUniformStorage, vertexConstantBuffer); + } + + if (fragmentUniformStorage->size() > 0 && programD3D->areFragmentUniformsDirty()) + { + UpdateUniformBuffer(deviceContext, fragmentUniformStorage, pixelConstantBuffer); + } + + unsigned int slot = d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK; + + if (mCurrentConstantBufferVS[slot] != vertexConstantBuffer->getSerial()) + { + deviceContext->VSSetConstantBuffers(slot, 1, vertexConstantBuffer->getPointer()); + mCurrentConstantBufferVS[slot] = vertexConstantBuffer->getSerial(); + mCurrentConstantBufferVSOffset[slot] = 0; + mCurrentConstantBufferVSSize[slot] = 0; + } + + if (mCurrentConstantBufferPS[slot] != pixelConstantBuffer->getSerial()) + { + deviceContext->PSSetConstantBuffers(slot, 1, pixelConstantBuffer->getPointer()); + mCurrentConstantBufferPS[slot] = pixelConstantBuffer->getSerial(); + mCurrentConstantBufferPSOffset[slot] = 0; + mCurrentConstantBufferPSSize[slot] = 0; + } + + programD3D->markUniformsClean(); + + return gl::NoError(); +} + +gl::Error StateManager11::applyDriverUniforms(const ProgramD3D &programD3D) +{ + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (!mDriverConstantBufferVS.valid()) + { + size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_VERTEX); + + D3D11_BUFFER_DESC constantBufferDescription = {0}; + d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); + ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferVS)); + + ID3D11Buffer *driverVSConstants = mDriverConstantBufferVS.get(); + deviceContext->VSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, + &driverVSConstants); + } + + if (!mDriverConstantBufferPS.valid()) + { + size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_PIXEL); + + D3D11_BUFFER_DESC constantBufferDescription = {0}; + d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); + ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferPS)); + + ID3D11Buffer *driverVSConstants = mDriverConstantBufferPS.get(); + deviceContext->PSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, + &driverVSConstants); + } + + // Sampler metadata and driver constants need to coexist in the same constant buffer to conserve + // constant buffer slots. We update both in the constant buffer if needed. + ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_VERTEX, programD3D, + mDriverConstantBufferVS)); + ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_PIXEL, programD3D, + mDriverConstantBufferPS)); + + // needed for the point sprite geometry shader + // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it for ES3. + if (mRenderer->isES3Capable()) + { + if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS.getSerial()) + { + ASSERT(mDriverConstantBufferPS.valid()); + deviceContext->GSSetConstantBuffers(0, 1, mDriverConstantBufferPS.getPointer()); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS.getSerial(); + } + } + + return gl::NoError(); +} + +gl::Error StateManager11::applyComputeUniforms(ProgramD3D *programD3D) +{ + UniformStorage11 *computeUniformStorage = + GetAs(&programD3D->getComputeUniformStorage()); + ASSERT(computeUniformStorage); + + const d3d11::Buffer *constantBuffer = nullptr; + ANGLE_TRY(computeUniformStorage->getConstantBuffer(mRenderer, &constantBuffer)); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + if (computeUniformStorage->size() > 0 && programD3D->areComputeUniformsDirty()) + { + UpdateUniformBuffer(deviceContext, computeUniformStorage, constantBuffer); + programD3D->markUniformsClean(); + } + + if (mCurrentComputeConstantBuffer != constantBuffer->getSerial()) + { + deviceContext->CSSetConstantBuffers( + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK, 1, + constantBuffer->getPointer()); + mCurrentComputeConstantBuffer = constantBuffer->getSerial(); + } + + if (!mDriverConstantBufferCS.valid()) + { + size_t requiredSize = mShaderConstants.getRequiredBufferSize(gl::SAMPLER_COMPUTE); + + D3D11_BUFFER_DESC constantBufferDescription = {0}; + d3d11::InitConstantBufferDesc(&constantBufferDescription, requiredSize); + ANGLE_TRY(mRenderer->allocateResource(constantBufferDescription, &mDriverConstantBufferCS)); + ID3D11Buffer *buffer = mDriverConstantBufferCS.get(); + deviceContext->CSSetConstantBuffers(d3d11::RESERVED_CONSTANT_BUFFER_SLOT_DRIVER, 1, + &buffer); + } + + ANGLE_TRY(mShaderConstants.updateBuffer(deviceContext, gl::SAMPLER_COMPUTE, *programD3D, + mDriverConstantBufferCS)); + + return gl::NoError(); +} + +gl::Error StateManager11::syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D) +{ + unsigned int reservedVertex = mRenderer->getReservedVertexUniformBuffers(); + unsigned int reservedFragment = mRenderer->getReservedFragmentUniformBuffers(); + + programD3D->updateUniformBufferCache(context->getCaps(), reservedVertex, reservedFragment); + + const auto &vertexUniformBuffers = programD3D->getVertexUniformBufferCache(); + const auto &fragmentUniformBuffers = programD3D->getFragmentUniformBufferCache(); + const auto &glState = context->getGLState(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported(); + + for (size_t bufferIndex = 0; bufferIndex < vertexUniformBuffers.size(); bufferIndex++) + { + GLint binding = vertexUniformBuffers[bufferIndex]; + + if (binding == -1) + { + continue; + } + + const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = uniformBuffer.getOffset(); + GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); + + if (uniformBuffer.get() == nullptr) + { + continue; + } + + Buffer11 *bufferStorage = GetImplAs(uniformBuffer.get()); + const d3d11::Buffer *constantBuffer = nullptr; + UINT firstConstant = 0; + UINT numConstants = 0; + + ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset, + uniformBufferSize, &constantBuffer, + &firstConstant, &numConstants)); + + ASSERT(constantBuffer); + + if (mCurrentConstantBufferVS[bufferIndex] == constantBuffer->getSerial() && + mCurrentConstantBufferVSOffset[bufferIndex] == uniformBufferOffset && + mCurrentConstantBufferVSSize[bufferIndex] == uniformBufferSize) + { + continue; + } + + unsigned int appliedIndex = reservedVertex + static_cast(bufferIndex); + + if (firstConstant != 0 && uniformBufferSize != 0) + { + ASSERT(numConstants != 0); + deviceContext1->VSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(), + &firstConstant, &numConstants); + } + else + { + deviceContext->VSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer()); + } + + mCurrentConstantBufferVS[appliedIndex] = constantBuffer->getSerial(); + mCurrentConstantBufferVSOffset[appliedIndex] = uniformBufferOffset; + mCurrentConstantBufferVSSize[appliedIndex] = uniformBufferSize; + } + + for (size_t bufferIndex = 0; bufferIndex < fragmentUniformBuffers.size(); bufferIndex++) + { + GLint binding = fragmentUniformBuffers[bufferIndex]; + + if (binding == -1) + { + continue; + } + + const auto &uniformBuffer = glState.getIndexedUniformBuffer(binding); + GLintptr uniformBufferOffset = uniformBuffer.getOffset(); + GLsizeiptr uniformBufferSize = uniformBuffer.getSize(); + + if (uniformBuffer.get() == nullptr) + { + continue; + } + + Buffer11 *bufferStorage = GetImplAs(uniformBuffer.get()); + const d3d11::Buffer *constantBuffer = nullptr; + UINT firstConstant = 0; + UINT numConstants = 0; + + ANGLE_TRY(bufferStorage->getConstantBufferRange(context, uniformBufferOffset, + uniformBufferSize, &constantBuffer, + &firstConstant, &numConstants)); + + ASSERT(constantBuffer); + + if (mCurrentConstantBufferPS[bufferIndex] == constantBuffer->getSerial() && + mCurrentConstantBufferPSOffset[bufferIndex] == uniformBufferOffset && + mCurrentConstantBufferPSSize[bufferIndex] == uniformBufferSize) + { + continue; + } + + unsigned int appliedIndex = reservedFragment + static_cast(bufferIndex); + + if (firstConstant != 0 && uniformBufferSize != 0) + { + deviceContext1->PSSetConstantBuffers1(appliedIndex, 1, constantBuffer->getPointer(), + &firstConstant, &numConstants); + } + else + { + deviceContext->PSSetConstantBuffers(appliedIndex, 1, constantBuffer->getPointer()); + } + + mCurrentConstantBufferPS[appliedIndex] = constantBuffer->getSerial(); + mCurrentConstantBufferPSOffset[appliedIndex] = uniformBufferOffset; + mCurrentConstantBufferPSSize[appliedIndex] = uniformBufferSize; + } + + return gl::NoError(); +} + +gl::Error StateManager11::syncTransformFeedbackBuffers(const gl::Context *context) +{ + const auto &glState = context->getGLState(); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // If transform feedback is not active, unbind all buffers + if (!glState.isTransformFeedbackActiveUnpaused()) + { + if (mAppliedTFSerial != mEmptySerial) + { + deviceContext->SOSetTargets(0, nullptr, nullptr); + mAppliedTFSerial = mEmptySerial; + } + return gl::NoError(); + } + + gl::TransformFeedback *transformFeedback = glState.getCurrentTransformFeedback(); + TransformFeedback11 *tf11 = GetImplAs(transformFeedback); + if (mAppliedTFSerial == tf11->getSerial() && !tf11->isDirty()) + { + return gl::NoError(); + } + + const std::vector *soBuffers = nullptr; + ANGLE_TRY_RESULT(tf11->getSOBuffers(context), soBuffers); + const std::vector &soOffsets = tf11->getSOBufferOffsets(); + + deviceContext->SOSetTargets(tf11->getNumSOBuffers(), soBuffers->data(), soOffsets.data()); + + mAppliedTFSerial = tf11->getSerial(); + tf11->onApply(); + + return gl::NoError(); +} + +// DrawCallVertexParams implementation. +DrawCallVertexParams::DrawCallVertexParams(GLint firstVertex, + GLsizei vertexCount, + GLsizei instances) + : mHasIndexRange(nullptr), + mFirstVertex(firstVertex), + mVertexCount(vertexCount), + mInstances(instances), + mBaseVertex(0) +{ +} + +// Use when in a drawElements call. +DrawCallVertexParams::DrawCallVertexParams(bool firstVertexDefinitelyZero, + const gl::HasIndexRange &hasIndexRange, + GLint baseVertex, + GLsizei instances) + : mHasIndexRange(&hasIndexRange), + mFirstVertex(), + mVertexCount(0), + mInstances(instances), + mBaseVertex(baseVertex) +{ + if (firstVertexDefinitelyZero) + { + mFirstVertex = baseVertex; + } +} + +GLint DrawCallVertexParams::firstVertex() const +{ + if (!mFirstVertex.valid()) + { + ensureResolved(); + ASSERT(mFirstVertex.valid()); + } + return mFirstVertex.value(); +} + +GLsizei DrawCallVertexParams::vertexCount() const +{ + ensureResolved(); + return mVertexCount; +} + +GLsizei DrawCallVertexParams::instances() const +{ + return mInstances; +} + +void DrawCallVertexParams::ensureResolved() const +{ + if (mHasIndexRange) + { + ASSERT(!mFirstVertex.valid() || mFirstVertex == mBaseVertex); + + // Resolve the index range now if we need to. + const auto &indexRange = mHasIndexRange->getIndexRange().value(); + mFirstVertex = mBaseVertex + static_cast(indexRange.start); + mVertexCount = static_cast(indexRange.vertexCount()); + mHasIndexRange = nullptr; + } } } // 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 index f900882d7e..e48bc83a22 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h @@ -11,12 +11,15 @@ #include -#include "libANGLE/angletypes.h" -#include "libANGLE/Data.h" +#include "libANGLE/ContextState.h" #include "libANGLE/State.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/d3d/IndexDataManager.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libANGLE/renderer/d3d/d3d11/Query11.h" #include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h" #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" -#include "libANGLE/renderer/d3d/RendererD3D.h" namespace rx { @@ -24,20 +27,147 @@ namespace rx struct RenderTargetDesc; struct Renderer11DeviceCaps; -struct dx_VertexConstants11 +class ShaderConstants11 : angle::NonCopyable { - float depthRange[4]; - float viewAdjust[4]; - float viewCoords[4]; - float viewScale[4]; + public: + ShaderConstants11(); + ~ShaderConstants11(); + + void init(const gl::Caps &caps); + size_t getRequiredBufferSize(gl::SamplerType samplerType) const; + void markDirty(); + + void setComputeWorkGroups(GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ); + void setMultiviewWriteToViewportIndex(GLfloat index); + void onViewportChange(const gl::Rectangle &glViewport, + const D3D11_VIEWPORT &dxViewport, + bool is9_3, + bool presentPathFast); + void onSamplerChange(gl::SamplerType samplerType, + unsigned int samplerIndex, + const gl::Texture &texture); + + gl::Error updateBuffer(ID3D11DeviceContext *deviceContext, + gl::SamplerType samplerType, + const ProgramD3D &programD3D, + const d3d11::Buffer &driverConstantBuffer); + + private: + struct Vertex + { + Vertex() + : depthRange{.0f}, + viewAdjust{.0f}, + viewCoords{.0f}, + viewScale{.0f}, + multiviewWriteToViewportIndex{.0f}, + padding{.0f} + { + } + + float depthRange[4]; + float viewAdjust[4]; + float viewCoords[4]; + float viewScale[2]; + // multiviewWriteToViewportIndex is used to select either the side-by-side or layered + // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated + // whenever a multi-view draw framebuffer is made active. + float multiviewWriteToViewportIndex; + + // Added here to manually pad the struct. + float padding; + }; + + struct Pixel + { + Pixel() + : depthRange{.0f}, + viewCoords{.0f}, + depthFront{.0f}, + viewScale{.0f}, + multiviewWriteToViewportIndex(0), + padding(0) + { + } + + float depthRange[4]; + float viewCoords[4]; + float depthFront[4]; + float viewScale[2]; + // multiviewWriteToViewportIndex is used to select either the side-by-side or layered + // code-path in the GS. It's value, if set, is either 0.0f or 1.0f. The value is updated + // whenever a multi-view draw framebuffer is made active. + float multiviewWriteToViewportIndex; + + // Added here to manually pad the struct. + float padding; + }; + + struct Compute + { + Compute() : numWorkGroups{0u}, padding(0u) {} + unsigned int numWorkGroups[3]; + unsigned int padding; // This just pads the struct to 16 bytes + }; + + struct SamplerMetadata + { + SamplerMetadata() : baseLevel(0), internalFormatBits(0), wrapModes(0), padding(0) {} + + int baseLevel; + int internalFormatBits; + int wrapModes; + int padding; // This just pads the struct to 16 bytes + }; + + static_assert(sizeof(SamplerMetadata) == 16u, + "Sampler metadata struct must be one 4-vec / 16 bytes."); + + // Return true if dirty. + bool updateSamplerMetadata(SamplerMetadata *data, const gl::Texture &texture); + + Vertex mVertex; + bool mVertexDirty; + Pixel mPixel; + bool mPixelDirty; + Compute mCompute; + bool mComputeDirty; + + std::vector mSamplerMetadataVS; + bool mSamplerMetadataVSDirty; + std::vector mSamplerMetadataPS; + bool mSamplerMetadataPSDirty; + std::vector mSamplerMetadataCS; + bool mSamplerMetadataCSDirty; }; -struct dx_PixelConstants11 +class DrawCallVertexParams final : angle::NonCopyable { - float depthRange[4]; - float viewCoords[4]; - float depthFront[4]; - float viewScale[4]; + public: + // Use when in a drawArrays call. + DrawCallVertexParams(GLint firstVertex, GLsizei vertexCount, GLsizei instances); + + // Use when in a drawElements call. + DrawCallVertexParams(bool firstVertexDefinitelyZero, + const gl::HasIndexRange &hasIndexRange, + GLint baseVertex, + GLsizei instances); + + // It should be possible to also use an overload to handle the 'slow' indirect draw path. + // TODO(jmadill): Indirect draw slow path overload. + + GLint firstVertex() const; + GLsizei vertexCount() const; + GLsizei instances() const; + + private: + void ensureResolved() const; + + mutable const gl::HasIndexRange *mHasIndexRange; + mutable Optional mFirstVertex; + mutable GLsizei mVertexCount; + GLsizei mInstances; + GLint mBaseVertex; }; class StateManager11 final : angle::NonCopyable @@ -46,62 +176,221 @@ class StateManager11 final : angle::NonCopyable StateManager11(Renderer11 *renderer); ~StateManager11(); - void initialize(const gl::Caps &caps); - void syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits); + gl::Error initialize(const gl::Caps &caps, const gl::Extensions &extensions); + void deinitialize(); - gl::Error setBlendState(const gl::Framebuffer *framebuffer, - const gl::BlendState &blendState, - const gl::ColorF &blendColor, - unsigned int sampleMask); + void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits); - gl::Error setDepthStencilState(const gl::State &glState); + gl::Error updateStateForCompute(const gl::Context *context, + GLuint numGroupsX, + GLuint numGroupsY, + GLuint numGroupsZ); - gl::Error setRasterizerState(const gl::RasterizerState &rasterState); + void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); - void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + // These invalidations methods are called externally. - void setViewport(const gl::Caps *caps, const gl::Rectangle &viewport, float zNear, float zFar); + // Called from TextureStorage11. + void invalidateBoundViews(); - void updatePresentPath(bool presentPathFastActive, - const gl::FramebufferAttachment *framebufferAttachment); + // Called from VertexArray11::updateVertexAttribStorage. + void invalidateCurrentValueAttrib(size_t attribIndex); - const dx_VertexConstants11 &getVertexConstants() const { return mVertexConstants; } - const dx_PixelConstants11 &getPixelConstants() const { return mPixelConstants; } + // Checks are done on a framebuffer state change to trigger other state changes. + // The Context is allowed to be nullptr for these methods, when called in EGL init code. + void invalidateRenderTarget(); - void updateStencilSizeIfChanged(bool depthStencilInitialized, unsigned int stencilSize); + // Called by instanced point sprite emulation. + void invalidateVertexBuffer(); + + // Called by Framebuffer11::syncState for the default sized viewport. + void invalidateViewport(const gl::Context *context); + + // Called by TextureStorage11::markLevelDirty. + void invalidateSwizzles(); + + // Called by the Framebuffer11 and VertexArray11. + void invalidateShaders(); + // Called by VertexArray11 to trigger attribute translation. + void invalidateVertexAttributeTranslation(); + + void setRenderTarget(ID3D11RenderTargetView *rtv, ID3D11DepthStencilView *dsv); + void setRenderTargets(ID3D11RenderTargetView **rtvs, UINT numRtvs, ID3D11DepthStencilView *dsv); + + void onBeginQuery(Query11 *query); + void onDeleteQueryObject(Query11 *query); + gl::Error onMakeCurrent(const gl::Context *context); + + void setInputLayout(const d3d11::InputLayout *inputLayout); + + // TODO(jmadill): Migrate to d3d11::Buffer. + bool queueVertexBufferChange(size_t bufferIndex, + ID3D11Buffer *buffer, + UINT stride, + UINT offset); + bool queueVertexOffsetChange(size_t bufferIndex, UINT offsetOnly); + void applyVertexBufferChanges(); + + void setSingleVertexBuffer(const d3d11::Buffer *buffer, UINT stride, UINT offset); + + gl::Error updateState(const gl::Context *context, GLenum drawMode); + + void setShaderResourceShared(gl::SamplerType shaderType, + UINT resourceSlot, + const d3d11::SharedSRV *srv); void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, - ID3D11ShaderResourceView *srv); + const d3d11::ShaderResourceView *srv); + void setPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY primitiveTopology); + + void setDrawShaders(const d3d11::VertexShader *vertexShader, + const d3d11::GeometryShader *geometryShader, + const d3d11::PixelShader *pixelShader); + void setVertexShader(const d3d11::VertexShader *shader); + void setGeometryShader(const d3d11::GeometryShader *shader); + void setPixelShader(const d3d11::PixelShader *shader); + void setComputeShader(const d3d11::ComputeShader *shader); + void setVertexConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer); + void setPixelConstantBuffer(unsigned int slot, const d3d11::Buffer *buffer); + void setDepthStencilState(const d3d11::DepthStencilState *depthStencilState, UINT stencilRef); + void setSimpleBlendState(const d3d11::BlendState *blendState); + void setRasterizerState(const d3d11::RasterizerState *rasterizerState); + void setSimpleViewport(const gl::Extents &viewportExtents); + void setSimpleViewport(int width, int height); + void setSimplePixelTextureAndSampler(const d3d11::SharedSRV &srv, + const d3d11::SamplerState &samplerState); + void setSimpleScissorRect(const gl::Rectangle &glRect); + void setScissorRectD3D(const D3D11_RECT &d3dRect); + + // Not handled by an internal dirty bit because of the extra draw parameters. + gl::Error applyVertexBuffer(const gl::Context *context, + GLenum mode, + const DrawCallVertexParams &vertexParams, + bool isIndexedRendering); + + gl::Error applyIndexBuffer(const gl::Context *context, + const void *indices, + GLsizei count, + GLenum type, + const gl::HasIndexRange &lazyIndexRange, + bool usePrimitiveRestartWorkaround); + + void setIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset); + + gl::Error updateVertexOffsetsForPointSpritesEmulation(GLint startVertex, + GLsizei emulatedInstanceId); + + // TODO(jmadill): Should be private. + gl::Error applyComputeUniforms(ProgramD3D *programD3D); + + // Only used in testing. + InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; } + + private: + template + void setShaderResourceInternal(gl::SamplerType shaderType, + UINT resourceSlot, + const SRVType *srv); + + bool unsetConflictingView(ID3D11View *view); + bool unsetConflictingSRVs(gl::SamplerType shaderType, + uintptr_t resource, + const gl::ImageIndex *index); + void unsetConflictingAttachmentResources(const gl::FramebufferAttachment *attachment, + ID3D11Resource *resource); + + gl::Error syncBlendState(const gl::Context *context, + const gl::Framebuffer *framebuffer, + const gl::BlendState &blendState, + const gl::ColorF &blendColor, + unsigned int sampleMask); + + gl::Error syncDepthStencilState(const gl::State &glState); + + gl::Error syncRasterizerState(const gl::Context *context, bool pointDrawMode); + + void syncScissorRectangle(const gl::Rectangle &scissor, bool enabled); + + void syncViewport(const gl::Context *context); + + void checkPresentPath(const gl::Context *context); + + gl::Error syncFramebuffer(const gl::Context *context, gl::Framebuffer *framebuffer); + gl::Error syncProgram(const gl::Context *context, GLenum drawMode); + + gl::Error syncTextures(const gl::Context *context); + gl::Error applyTextures(const gl::Context *context, gl::SamplerType shaderType); + + gl::Error setSamplerState(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture, + const gl::SamplerState &sampler); + gl::Error setTexture(const gl::Context *context, + gl::SamplerType type, + int index, + gl::Texture *texture); + + // Faster than calling setTexture a jillion times gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd); + void handleMultiviewDrawFramebufferChange(const gl::Context *context); - gl::Error syncFramebuffer(const gl::Framebuffer *framebuffer); + gl::Error syncCurrentValueAttribs(const gl::State &glState); - void invalidateRenderTarget(); - void invalidateEverything(); - bool setRenderTargets(const RenderTargetArray &renderTargets, - ID3D11DepthStencilView *depthStencil); - void setRenderTarget(ID3D11RenderTargetView *renderTarget, - ID3D11DepthStencilView *depthStencil); + gl::Error generateSwizzle(const gl::Context *context, gl::Texture *texture); + gl::Error generateSwizzlesForShader(const gl::Context *context, gl::SamplerType type); + gl::Error generateSwizzles(const gl::Context *context); - private: - void unsetConflictingSRVs(gl::SamplerType shaderType, - uintptr_t resource, - const gl::ImageIndex &index); - void setViewportBounds(const int width, const int height); + gl::Error applyDriverUniforms(const ProgramD3D &programD3D); + gl::Error applyUniforms(ProgramD3D *programD3D); + + gl::Error syncUniformBuffers(const gl::Context *context, ProgramD3D *programD3D); + gl::Error syncTransformFeedbackBuffers(const gl::Context *context); + + // These are currently only called internally. + void invalidateTexturesAndSamplers(); + void invalidateDriverUniforms(); + void invalidateProgramUniforms(); + void invalidateProgramUniformBuffers(); + void invalidateConstantBuffer(unsigned int slot); + + // Called by the Framebuffer11 directly. + void processFramebufferInvalidation(const gl::Context *context); + + bool syncIndexBuffer(ID3D11Buffer *buffer, DXGI_FORMAT indexFormat, unsigned int offset); + + enum DirtyBitType + { + DIRTY_BIT_RENDER_TARGET, + DIRTY_BIT_VIEWPORT_STATE, + DIRTY_BIT_SCISSOR_STATE, + DIRTY_BIT_RASTERIZER_STATE, + DIRTY_BIT_BLEND_STATE, + DIRTY_BIT_DEPTH_STENCIL_STATE, + DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE, + DIRTY_BIT_PROGRAM_UNIFORMS, + DIRTY_BIT_DRIVER_UNIFORMS, + DIRTY_BIT_PROGRAM_UNIFORM_BUFFERS, + DIRTY_BIT_SHADERS, + DIRTY_BIT_CURRENT_VALUE_ATTRIBS, + DIRTY_BIT_INVALID, + DIRTY_BIT_MAX = DIRTY_BIT_INVALID, + }; + + using DirtyBits = angle::BitSet; Renderer11 *mRenderer; + // Internal dirty bits. + DirtyBits mInternalDirtyBits; + // 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; @@ -110,34 +399,35 @@ class StateManager11 final : angle::NonCopyable 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; + // The viewport offsets are guaranteed to be updated whenever the gl::State::DirtyBits are + // resolved and can be applied to the viewport and scissor whenever the internal viewport and + // scissor bits are resolved. + std::vector mViewportOffsets; + // Things needed in viewport state - dx_VertexConstants11 mVertexConstants; - dx_PixelConstants11 mPixelConstants; + ShaderConstants11 mShaderConstants; // Render target variables gl::Extents mViewportBounds; + bool mRenderTargetIsDirty; // EGL_ANGLE_experimental_present_path variables bool mCurPresentPathFastEnabled; int mCurPresentPathFastColorBufferHeight; - // Current RenderTarget state - std::array mAppliedRTVs; - uintptr_t mAppliedDSV; + // Queries that are currently active in this state + std::set mCurrentQueries; // Currently applied textures struct SRVRecord @@ -154,7 +444,8 @@ class StateManager11 final : angle::NonCopyable class SRVCache : angle::NonCopyable { public: - SRVCache() : mHighestUsedSRV(0) {} + SRVCache(); + ~SRVCache(); void initialize(size_t size) { mCurrentSRVs.resize(size); } @@ -175,6 +466,91 @@ class StateManager11 final : angle::NonCopyable // A block of NULL pointers, cached so we don't re-allocate every draw call std::vector mNullSRVs; + + // Current translations of "Current-Value" data - owned by Context, not VertexArray. + gl::AttributesMask mDirtyCurrentValueAttribs; + std::vector mCurrentValueAttribs; + + // Current applied input layout. + ResourceSerial mCurrentInputLayout; + bool mInputLayoutIsDirty; + bool mVertexAttribsNeedTranslation; + + // Current applied vertex states. + // TODO(jmadill): Figure out how to use ResourceSerial here. + std::array mCurrentVertexBuffers; + std::array mCurrentVertexStrides; + std::array mCurrentVertexOffsets; + gl::RangeUI mDirtyVertexBufferRange; + + // Currently applied primitive topology + D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; + + // Currently applied shaders + ResourceSerial mAppliedVertexShader; + ResourceSerial mAppliedGeometryShader; + ResourceSerial mAppliedPixelShader; + ResourceSerial mAppliedComputeShader; + + // Currently applied sampler states + std::vector mForceSetVertexSamplerStates; + std::vector mCurVertexSamplerStates; + + std::vector mForceSetPixelSamplerStates; + std::vector mCurPixelSamplerStates; + + std::vector mForceSetComputeSamplerStates; + std::vector mCurComputeSamplerStates; + + // Special dirty bit for swizzles. Since they use internal shaders, must be done in a pre-pass. + bool mDirtySwizzles; + + // Currently applied index buffer + ID3D11Buffer *mAppliedIB; + DXGI_FORMAT mAppliedIBFormat; + unsigned int mAppliedIBOffset; + bool mIndexBufferIsDirty; + + // Vertex, index and input layouts + VertexDataManager mVertexDataManager; + IndexDataManager mIndexDataManager; + InputLayoutCache mInputLayoutCache; + std::vector mCurrentAttributes; + Optional mLastFirstVertex; + + // ANGLE_multiview. + bool mIsMultiviewEnabled; + + // Driver Constants. + d3d11::Buffer mDriverConstantBufferVS; + d3d11::Buffer mDriverConstantBufferPS; + d3d11::Buffer mDriverConstantBufferCS; + + ResourceSerial mCurrentComputeConstantBuffer; + ResourceSerial mCurrentGeometryConstantBuffer; + + template + using VertexConstantBufferArray = + std::array; + + VertexConstantBufferArray mCurrentConstantBufferVS; + VertexConstantBufferArray mCurrentConstantBufferVSOffset; + VertexConstantBufferArray mCurrentConstantBufferVSSize; + + template + using FragmentConstantBufferArray = + std::array; + + FragmentConstantBufferArray mCurrentConstantBufferPS; + FragmentConstantBufferArray mCurrentConstantBufferPSOffset; + FragmentConstantBufferArray mCurrentConstantBufferPSSize; + + // Currently applied transform feedback buffers + Serial mAppliedTFSerial; + + Serial mEmptySerial; + + bool mIsTransformFeedbackCurrentlyActiveUnpaused; }; } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp new file mode 100644 index 0000000000..1981b5f7b2 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.cpp @@ -0,0 +1,102 @@ +// +// Copyright (c) 2016 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. +// + +// StreamProducerNV12.cpp: Implements the stream producer for NV12 textures + +#include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h" + +#include "common/utilities.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +namespace rx +{ + +StreamProducerNV12::StreamProducerNV12(Renderer11 *renderer) + : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mTextureWidth(0), mTextureHeight(0) +{ +} + +StreamProducerNV12::~StreamProducerNV12() +{ + SafeRelease(mTexture); +} + +egl::Error StreamProducerNV12::validateD3DNV12Texture(void *pointer) const +{ + ID3D11Texture2D *textureD3D = static_cast(pointer); + + // Check that the texture originated from our device + ID3D11Device *device; + textureD3D->GetDevice(&device); + if (device != mRenderer->getDevice()) + { + return egl::EglBadParameter() << "Texture not created on ANGLE D3D device"; + } + + // Get the description and validate it + D3D11_TEXTURE2D_DESC desc; + textureD3D->GetDesc(&desc); + if (desc.Format != DXGI_FORMAT_NV12) + { + return egl::EglBadParameter() << "Texture format not DXGI_FORMAT_NV12"; + } + if (desc.Width < 1 || desc.Height < 1) + { + return egl::EglBadParameter() << "Texture is of size 0"; + } + if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0) + { + return egl::EglBadParameter() << "Texture dimensions are not even"; + } + return egl::NoError(); +} + +void StreamProducerNV12::postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes) +{ + ASSERT(pointer != nullptr); + ID3D11Texture2D *textureD3D = static_cast(pointer); + + // Check that the texture originated from our device + ID3D11Device *device; + textureD3D->GetDevice(&device); + + // Get the description + D3D11_TEXTURE2D_DESC desc; + textureD3D->GetDesc(&desc); + + // Release the previous texture if there is one + SafeRelease(mTexture); + + mTexture = textureD3D; + mTexture->AddRef(); + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mArraySlice = static_cast(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0)); +} + +egl::Stream::GLTextureDescription StreamProducerNV12::getGLFrameDescription(int planeIndex) +{ + // The UV plane of NV12 textures has half the width/height of the Y plane + egl::Stream::GLTextureDescription desc; + desc.width = (planeIndex == 0) ? mTextureWidth : (mTextureWidth / 2); + desc.height = (planeIndex == 0) ? mTextureHeight : (mTextureHeight / 2); + desc.internalFormat = (planeIndex == 0) ? GL_R8 : GL_RG8; + desc.mipLevels = 0; + return desc; +} + +ID3D11Texture2D *StreamProducerNV12::getD3DTexture() +{ + return mTexture; +} + +UINT StreamProducerNV12::getArraySlice() +{ + return mArraySlice; +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h new file mode 100644 index 0000000000..304c9dfe53 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/StreamProducerNV12.h @@ -0,0 +1,44 @@ +// +// Copyright (c) 2016 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. +// + +// StreamProducerNV12.h: Interface for a NV12 texture stream producer + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_STREAM11_H_ + +#include "libANGLE/renderer/StreamProducerImpl.h" + +namespace rx +{ +class Renderer11; + +class StreamProducerNV12 : public StreamProducerImpl +{ + public: + StreamProducerNV12(Renderer11 *renderer); + ~StreamProducerNV12() override; + + egl::Error validateD3DNV12Texture(void *pointer) const override; + void postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes) override; + egl::Stream::GLTextureDescription getGLFrameDescription(int planeIndex) override; + + // Gets a pointer to the internal D3D texture + ID3D11Texture2D *getD3DTexture(); + + // Gets the slice index for the D3D texture that the frame is in + UINT getArraySlice(); + + private: + Renderer11 *mRenderer; + + ID3D11Texture2D *mTexture; + UINT mArraySlice; + UINT mTextureWidth; + UINT mTextureHeight; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_STREAM11_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 42c336c8cf..dcfd06484d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -11,9 +11,9 @@ #include #include "libANGLE/features.h" -#include "libANGLE/renderer/d3d/d3d11/formatutils11.h" -#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/formatutils11.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" @@ -21,6 +21,7 @@ // Precompiled shaders #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h" #include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h" +#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h" #ifdef ANGLE_ENABLE_KEYEDMUTEX #define ANGLE_RESOURCE_SHARE_TYPE D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX @@ -33,22 +34,30 @@ namespace rx namespace { -bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow nativeWindow, EGLint orientation) +// To avoid overflow in QPC to Microseconds calculations, since we multiply +// by kMicrosecondsPerSecond, then the QPC value should not exceed +// (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply. +static constexpr int64_t kQPCOverflowThreshold = 0x8637BD05AF7; +static constexpr int64_t kMicrosecondsPerSecond = 1000000; + +bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow11 *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()); + !(renderer->presentPathFastEnabled() && nativeWindow->getNativeWindow()); } } // anonymous namespace SwapChain11::SwapChain11(Renderer11 *renderer, - NativeWindow nativeWindow, + NativeWindow11 *nativeWindow, HANDLE shareHandle, + IUnknown *d3dTexture, GLenum backBufferFormat, GLenum depthBufferFormat, - EGLint orientation) - : SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat), + EGLint orientation, + EGLint samples) + : SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat), mRenderer(renderer), mWidth(-1), mHeight(-1), @@ -56,33 +65,42 @@ SwapChain11::SwapChain11(Renderer11 *renderer, mAppCreatedShareHandle(mShareHandle != nullptr), mSwapInterval(0), mPassThroughResourcesInit(false), + mNativeWindow(nativeWindow), mFirstSwap(true), mSwapChain(nullptr), -#if defined(ANGLE_ENABLE_D3D11_1) mSwapChain1(nullptr), -#endif mKeyedMutex(nullptr), - mBackBufferTexture(nullptr), - mBackBufferRTView(nullptr), - mBackBufferSRView(nullptr), + mBackBufferTexture(), + mBackBufferRTView(), + mBackBufferSRView(), 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), + mOffscreenTexture(), + mOffscreenRTView(), + mOffscreenSRView(), + mNeedsOffscreenTextureCopy(false), + mOffscreenTextureCopyForSRV(), + mDepthStencilTexture(), + mDepthStencilDSView(), + mDepthStencilSRView(), + mQuadVB(), + mPassThroughSampler(), + mPassThroughIL(), + mPassThroughVS(), + mPassThroughPS(), + mPassThroughRS(), mColorRenderTarget(this, renderer, false), - mDepthStencilRenderTarget(this, renderer, true) + mDepthStencilRenderTarget(this, renderer, true), + mEGLSamples(samples) { // Sanity check that if present path fast is active then we're using the default orientation ASSERT(!mRenderer->presentPathFastEnabled() || orientation == 0); + + // Get the performance counter + LARGE_INTEGER counterFreqency = {}; + BOOL success = QueryPerformanceFrequency(&counterFreqency); + ASSERT(success); + + mQPCFrequency = counterFreqency.QuadPart; } SwapChain11::~SwapChain11() @@ -92,52 +110,56 @@ SwapChain11::~SwapChain11() void SwapChain11::release() { -#if defined(ANGLE_ENABLE_D3D11_1) + // TODO(jmadill): Should probably signal that the RenderTarget is dirty. + SafeRelease(mSwapChain1); -#endif SafeRelease(mSwapChain); SafeRelease(mKeyedMutex); - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - SafeRelease(mBackBufferSRView); - SafeRelease(mOffscreenTexture); - SafeRelease(mOffscreenRTView); - SafeRelease(mOffscreenSRView); - SafeRelease(mDepthStencilTexture); - SafeRelease(mDepthStencilDSView); - SafeRelease(mDepthStencilSRView); - SafeRelease(mQuadVB); - SafeRelease(mPassThroughSampler); - SafeRelease(mPassThroughIL); - SafeRelease(mPassThroughVS); - SafeRelease(mPassThroughPS); - SafeRelease(mPassThroughRS); + mBackBufferTexture.reset(); + mBackBufferRTView.reset(); + mBackBufferSRView.reset(); + mOffscreenTexture.reset(); + mOffscreenRTView.reset(); + mOffscreenSRView.reset(); + mDepthStencilTexture.reset(); + mDepthStencilDSView.reset(); + mDepthStencilSRView.reset(); + mQuadVB.reset(); + mPassThroughSampler.reset(); + mPassThroughIL.reset(); + mPassThroughVS.reset(); + mPassThroughPS.reset(); + mPassThroughRS.reset(); if (!mAppCreatedShareHandle) { - mShareHandle = NULL; + mShareHandle = nullptr; } } void SwapChain11::releaseOffscreenColorBuffer() { - SafeRelease(mOffscreenTexture); - SafeRelease(mOffscreenRTView); - SafeRelease(mOffscreenSRView); + mOffscreenTexture.reset(); + mOffscreenRTView.reset(); + mOffscreenSRView.reset(); + mNeedsOffscreenTextureCopy = false; + mOffscreenTextureCopyForSRV.reset(); } void SwapChain11::releaseOffscreenDepthBuffer() { - SafeRelease(mDepthStencilTexture); - SafeRelease(mDepthStencilDSView); - SafeRelease(mDepthStencilSRView); + mDepthStencilTexture.reset(); + mDepthStencilDSView.reset(); + mDepthStencilSRView.reset(); } -EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHeight) +EGLint SwapChain11::resetOffscreenBuffers(const gl::Context *context, + int backbufferWidth, + int backbufferHeight) { if (mNeedsOffscreenTexture) { - EGLint result = resetOffscreenColorBuffer(backbufferWidth, backbufferHeight); + EGLint result = resetOffscreenColorBuffer(context, backbufferWidth, backbufferHeight); if (result != EGL_SUCCESS) { return result; @@ -156,117 +178,106 @@ EGLint SwapChain11::resetOffscreenBuffers(int backbufferWidth, int backbufferHei return EGL_SUCCESS; } -EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight) +EGLint SwapChain11::resetOffscreenColorBuffer(const gl::Context *context, + int backbufferWidth, + int backbufferHeight) { ASSERT(mNeedsOffscreenTexture); TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture"); ID3D11Device *device = mRenderer->getDevice(); - ASSERT(device != NULL); + ASSERT(device != nullptr); // D3D11 does not allow zero size textures ASSERT(backbufferWidth >= 1); ASSERT(backbufferHeight >= 1); // Preserve the render target content - ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; - if (previousOffscreenTexture) - { - previousOffscreenTexture->AddRef(); - } + TextureHelper11 previousOffscreenTexture(std::move(mOffscreenTexture)); const int previousWidth = mWidth; const int previousHeight = mHeight; releaseOffscreenColorBuffer(); - const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + const d3d11::Format &backbufferFormatInfo = + d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - // If the app passed in a share handle, open the resource - // See EGL_ANGLE_d3d_share_handle_client_buffer - if (mAppCreatedShareHandle) + // If the app passed in a share handle or D3D texture, open the resource + // See EGL_ANGLE_d3d_share_handle_client_buffer and EGL_ANGLE_d3d_texture_client_buffer + if (mAppCreatedShareHandle || mD3DTexture != nullptr) { - ID3D11Resource *tempResource11; - HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); + if (mAppCreatedShareHandle) + { + ID3D11Resource *tempResource11; + HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), + (void **)&tempResource11); + ASSERT(SUCCEEDED(result)); - if (FAILED(result)) + mOffscreenTexture.set(d3d11::DynamicCastComObject(tempResource11), + backbufferFormatInfo); + SafeRelease(tempResource11); + } + else if (mD3DTexture != nullptr) { - ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); - release(); - return EGL_BAD_PARAMETER; + mOffscreenTexture.set(d3d11::DynamicCastComObject(mD3DTexture), + backbufferFormatInfo); } - - result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); - SafeRelease(tempResource11); - - if (FAILED(result)) + else { - ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); - release(); - return EGL_BAD_PARAMETER; + UNREACHABLE(); } + ASSERT(mOffscreenTexture.valid()); + mOffscreenTexture.getDesc(&offscreenTextureDesc); - // Validate offscreen texture parameters - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - mOffscreenTexture->GetDesc(&offscreenTextureDesc); - - if (offscreenTextureDesc.Width != (UINT)backbufferWidth || - offscreenTextureDesc.Height != (UINT)backbufferHeight || - offscreenTextureDesc.Format != backbufferFormatInfo.texFormat || - offscreenTextureDesc.MipLevels != 1 || - offscreenTextureDesc.ArraySize != 1) + // Fail if the offscreen texture is not renderable. + if ((offscreenTextureDesc.BindFlags & D3D11_BIND_RENDER_TARGET) == 0) { - ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); + ERR() << "Could not use provided offscreen texture, texture not renderable."; release(); - return EGL_BAD_PARAMETER; + return EGL_BAD_SURFACE; } } else { - const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport(); + const bool useSharedResource = + !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport(); - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; offscreenTextureDesc.Width = backbufferWidth; offscreenTextureDesc.Height = backbufferHeight; - offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; + offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; - offscreenTextureDesc.SampleDesc.Count = 1; + offscreenTextureDesc.SampleDesc.Count = getD3DSamples(); offscreenTextureDesc.SampleDesc.Quality = 0; offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; offscreenTextureDesc.CPUAccessFlags = 0; offscreenTextureDesc.MiscFlags = useSharedResource ? ANGLE_RESOURCE_SHARE_TYPE : 0; - HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); - - if (FAILED(result)) + gl::Error err = mRenderer->allocateTexture(offscreenTextureDesc, backbufferFormatInfo, + &mOffscreenTexture); + if (err.isError()) { - ERR("Could not create offscreen texture: %08lX", result); + ERR() << "Could not create offscreen texture, " << err; release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } + return EGL_BAD_ALLOC; } - d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture"); + mOffscreenTexture.setDebugName("Offscreen back buffer texture"); // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client if (useSharedResource) { - IDXGIResource *offscreenTextureResource = NULL; - result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); + IDXGIResource *offscreenTextureResource = nullptr; + HRESULT result = mOffscreenTexture.get()->QueryInterface( + __uuidof(IDXGIResource), (void **)&offscreenTextureResource); // Fall back to no share handle on failure if (FAILED(result)) { - ERR("Could not query offscreen texture resource: %08lX", result); + ERR() << "Could not query offscreen texture resource, " << gl::FmtHR(result); } else { @@ -275,36 +286,49 @@ EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbuffe if (FAILED(result)) { - mShareHandle = NULL; - ERR("Could not get offscreen texture shared handle: %08lX", result); + mShareHandle = nullptr; + ERR() << "Could not get offscreen texture shared handle, " << gl::FmtHR(result); } } } } // This may return null if the original texture was created without a keyed mutex. - mKeyedMutex = d3d11::DynamicCastComObject(mOffscreenTexture); + mKeyedMutex = d3d11::DynamicCastComObject(mOffscreenTexture.get()); D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; - offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; - offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; + offscreenRTVDesc.ViewDimension = + (mEGLSamples <= 1) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; offscreenRTVDesc.Texture2D.MipSlice = 0; - HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); + gl::Error err = + mRenderer->allocateResource(offscreenRTVDesc, mOffscreenTexture.get(), &mOffscreenRTView); + ASSERT(!err.isError()); + mOffscreenRTView.setDebugName("Offscreen back buffer render target"); D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; - offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; - offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; + offscreenSRVDesc.ViewDimension = + (mEGLSamples <= 1) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; offscreenSRVDesc.Texture2D.MostDetailedMip = 0; offscreenSRVDesc.Texture2D.MipLevels = static_cast(-1); - result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); + if (offscreenTextureDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE) + { + err = mRenderer->allocateResource(offscreenSRVDesc, mOffscreenTexture.get(), + &mOffscreenSRView); + ASSERT(!err.isError()); + mOffscreenSRView.setDebugName("Offscreen back buffer shader resource"); + } + else + { + // Special case for external textures that cannot support sampling. Since internally we + // assume our SwapChain is always readable, we make a copy texture that is compatible. + mNeedsOffscreenTextureCopy = true; + } - if (previousOffscreenTexture != nullptr) + if (previousOffscreenTexture.valid()) { D3D11_BOX sourceBox = {0}; sourceBox.left = 0; @@ -316,14 +340,12 @@ EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbuffe ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); const int yoffset = std::max(backbufferHeight - previousHeight, 0); - deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, - previousOffscreenTexture, 0, &sourceBox); - - SafeRelease(previousOffscreenTexture); + deviceContext->CopySubresourceRegion(mOffscreenTexture.get(), 0, 0, yoffset, 0, + previousOffscreenTexture.get(), 0, &sourceBox); if (mSwapChain) { - swapRect(0, 0, backbufferWidth, backbufferHeight); + swapRect(context, 0, 0, backbufferWidth, backbufferHeight); } } @@ -336,21 +358,38 @@ EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbuffe if (mDepthBufferFormat != GL_NONE) { - const d3d11::TextureFormat &depthBufferFormatInfo = - d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps()); + const d3d11::Format &depthBufferFormatInfo = + d3d11::Format::Get(mDepthBufferFormat, mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE2D_DESC depthStencilTextureDesc; depthStencilTextureDesc.Width = backbufferWidth; depthStencilTextureDesc.Height = backbufferHeight; - depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; + depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; depthStencilTextureDesc.MipLevels = 1; depthStencilTextureDesc.ArraySize = 1; - depthStencilTextureDesc.SampleDesc.Count = 1; - depthStencilTextureDesc.SampleDesc.Quality = 0; + depthStencilTextureDesc.SampleDesc.Count = getD3DSamples(); depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + // If there is a multisampled offscreen color texture, the offscreen depth-stencil texture + // must also have the same quality value. + if (mOffscreenTexture.valid() && getD3DSamples() > 1) + { + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + mOffscreenTexture.getDesc(&offscreenTextureDesc); + depthStencilTextureDesc.SampleDesc.Quality = offscreenTextureDesc.SampleDesc.Quality; + } + else + { + depthStencilTextureDesc.SampleDesc.Quality = 0; + } + + // Only create an SRV if it is supported + bool depthStencilSRV = + depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN && + (mRenderer->getRenderer11DeviceCaps().supportsMultisampledDepthStencilSRVs || + depthStencilTextureDesc.SampleDesc.Count <= 1); + if (depthStencilSRV) { depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE; } @@ -358,58 +397,56 @@ EGLint SwapChain11::resetOffscreenDepthBuffer(int backbufferWidth, int backbuffe depthStencilTextureDesc.CPUAccessFlags = 0; depthStencilTextureDesc.MiscFlags = 0; - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = - device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture); - if (FAILED(result)) + gl::Error err = mRenderer->allocateTexture(depthStencilTextureDesc, depthBufferFormatInfo, + &mDepthStencilTexture); + if (err.isError()) { - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + ERR() << "Could not create depthstencil surface for new swap chain, " << err; release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } + return EGL_BAD_ALLOC; } - d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture"); + mDepthStencilTexture.setDebugName("Offscreen depth stencil texture"); D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc; - depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat; - depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat; + depthStencilDesc.ViewDimension = + (mEGLSamples <= 1) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; depthStencilDesc.Flags = 0; depthStencilDesc.Texture2D.MipSlice = 0; - result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); + err = mRenderer->allocateResource(depthStencilDesc, mDepthStencilTexture.get(), + &mDepthStencilDSView); + ASSERT(!err.isError()); + mDepthStencilDSView.setDebugName("Offscreen depth stencil view"); - if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) + if (depthStencilSRV) { D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; - depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; - depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; + depthStencilSRVDesc.ViewDimension = (mEGLSamples <= 1) + ? D3D11_SRV_DIMENSION_TEXTURE2D + : D3D11_SRV_DIMENSION_TEXTURE2DMS; depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; depthStencilSRVDesc.Texture2D.MipLevels = static_cast(-1); - result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource"); + err = mRenderer->allocateResource(depthStencilSRVDesc, mDepthStencilTexture.get(), + &mDepthStencilSRView); + ASSERT(!err.isError()); + mDepthStencilSRView.setDebugName("Offscreen depth stencil shader resource"); } } return EGL_SUCCESS; } -EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) +EGLint SwapChain11::resize(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight) { TRACE_EVENT0("gpu.angle", "SwapChain11::resize"); ID3D11Device *device = mRenderer->getDevice(); - if (device == NULL) + if (device == nullptr) { return EGL_BAD_ACCESS; } @@ -427,18 +464,19 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) } // Can only call resize if we have already created our swap buffer and resources - ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView && mBackBufferSRView); + ASSERT(mSwapChain && mBackBufferTexture.valid() && mBackBufferRTView.valid() && + mBackBufferSRView.valid()); - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - SafeRelease(mBackBufferSRView); + mBackBufferTexture.reset(); + mBackBufferRTView.reset(); + mBackBufferSRView.reset(); // Resize swap chain DXGI_SWAP_CHAIN_DESC desc; HRESULT result = mSwapChain->GetDesc(&desc); if (FAILED(result)) { - ERR("Error reading swap chain description: 0x%08X", result); + ERR() << "Error reading swap chain description, " << gl::FmtHR(result); release(); return EGL_BAD_ALLOC; } @@ -447,7 +485,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) if (FAILED(result)) { - ERR("Error resizing swap chain buffers: 0x%08X", result); + ERR() << "Error resizing swap chain buffers, " << gl::FmtHR(result); release(); if (d3d11::isDeviceLostError(result)) @@ -460,39 +498,64 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) } } - result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ID3D11Texture2D *backbufferTexture = nullptr; + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), + reinterpret_cast(&backbufferTexture)); ASSERT(SUCCEEDED(result)); 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->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); - ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) - { - d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource"); - } + const auto &format = + d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + mBackBufferTexture.set(backbufferTexture, format); + mBackBufferTexture.setDebugName("Back buffer texture"); + + gl::Error err = + mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferRTView); + ASSERT(!err.isError()); + mBackBufferRTView.setDebugName("Back buffer render target"); + + err = mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferSRView); + ASSERT(!err.isError()); + mBackBufferSRView.setDebugName("Back buffer shader resource"); } mFirstSwap = true; - return resetOffscreenBuffers(backbufferWidth, backbufferHeight); + return resetOffscreenBuffers(context, 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; + switch (mOffscreenRenderTargetFormat) + { + case GL_RGBA8: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGB8: + case GL_RGB565: + return DXGI_FORMAT_R8G8B8A8_UNORM; + + case GL_BGRA8_EXT: + return DXGI_FORMAT_B8G8R8A8_UNORM; + + case GL_RGB10_A2: + return DXGI_FORMAT_R10G10B10A2_UNORM; + + case GL_RGBA16F: + return DXGI_FORMAT_R16G16B16A16_FLOAT; + + default: + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } } -EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +EGLint SwapChain11::reset(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight, + EGLint swapInterval) { mSwapInterval = static_cast(swapInterval); if (mSwapInterval > 4) @@ -505,25 +568,23 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap // If the swap chain already exists, just resize if (mSwapChain != nullptr) { - return resize(backbufferWidth, backbufferHeight); + return resize(context, backbufferWidth, backbufferHeight); } TRACE_EVENT0("gpu.angle", "SwapChain11::reset"); ID3D11Device *device = mRenderer->getDevice(); - if (device == NULL) + if (device == nullptr) { return EGL_BAD_ACCESS; } // 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); + mBackBufferTexture.reset(); + mBackBufferRTView.reset(); // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains if (backbufferWidth < 1 || backbufferHeight < 1) @@ -532,15 +593,16 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap return EGL_SUCCESS; } - if (mNativeWindow.getNativeWindow()) + if (mNativeWindow->getNativeWindow()) { - HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(), - getSwapChainNativeFormat(), - backbufferWidth, backbufferHeight, &mSwapChain); + HRESULT result = mNativeWindow->createSwapChain( + device, mRenderer->getDxgiFactory(), getSwapChainNativeFormat(), backbufferWidth, + backbufferHeight, getD3DSamples(), &mSwapChain); if (FAILED(result)) { - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + ERR() << "Could not create additional swap chains or offscreen surfaces, " + << gl::FmtHR(result); release(); if (d3d11::isDeviceLostError(result)) @@ -555,27 +617,31 @@ 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"); - - result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); - - result = device->CreateShaderResourceView(mBackBufferTexture, nullptr, &mBackBufferSRView); + ID3D11Texture2D *backbufferTex = nullptr; + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), + reinterpret_cast(&backbufferTex)); ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mBackBufferSRView, "Back buffer shader resource view"); + const auto &format = + d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + mBackBufferTexture.set(backbufferTex, format); + mBackBufferTexture.setDebugName("Back buffer texture"); + + gl::Error err = + mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferRTView); + ASSERT(!err.isError()); + mBackBufferRTView.setDebugName("Back buffer render target"); + + err = mRenderer->allocateResourceNoDesc(mBackBufferTexture.get(), &mBackBufferSRView); + ASSERT(!err.isError()); + mBackBufferSRView.setDebugName("Back buffer shader resource view"); } mFirstSwap = true; - return resetOffscreenBuffers(backbufferWidth, backbufferHeight); + return resetOffscreenBuffers(context, backbufferWidth, backbufferHeight); } void SwapChain11::initPassThroughResources() @@ -588,11 +654,11 @@ void SwapChain11::initPassThroughResources() TRACE_EVENT0("gpu.angle", "SwapChain11::initPassThroughResources"); ID3D11Device *device = mRenderer->getDevice(); - ASSERT(device != NULL); + ASSERT(device != nullptr); // Make sure our resources are all not allocated, when we create - ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); - ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); + ASSERT(!mQuadVB.valid() && !mPassThroughSampler.valid()); + ASSERT(!mPassThroughIL.valid() && !mPassThroughVS.valid() && !mPassThroughPS.valid()); D3D11_BUFFER_DESC vbDesc; vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; @@ -602,9 +668,9 @@ void SwapChain11::initPassThroughResources() vbDesc.MiscFlags = 0; vbDesc.StructureByteStride = 0; - HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); + gl::Error err = mRenderer->allocateResource(vbDesc, &mQuadVB); + ASSERT(!err.isError()); + mQuadVB.setDebugName("Swap chain quad vertex buffer"); D3D11_SAMPLER_DESC samplerDesc; samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; @@ -621,9 +687,9 @@ void SwapChain11::initPassThroughResources() samplerDesc.MinLOD = 0; samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; - result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); + err = mRenderer->allocateResource(samplerDesc, &mPassThroughSampler); + ASSERT(!err.isError()); + mPassThroughSampler.setDebugName("Swap chain pass through sampler"); D3D11_INPUT_ELEMENT_DESC quadLayout[] = { @@ -631,17 +697,30 @@ void SwapChain11::initPassThroughResources() { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, }; - result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); + InputElementArray quadElements(quadLayout); + ShaderData vertexShaderData(g_VS_Passthrough2D); - result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); + err = mRenderer->allocateResource(quadElements, &vertexShaderData, &mPassThroughIL); + ASSERT(!err.isError()); + mPassThroughIL.setDebugName("Swap chain pass through layout"); - result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); + err = mRenderer->allocateResource(vertexShaderData, &mPassThroughVS); + ASSERT(!err.isError()); + mPassThroughVS.setDebugName("Swap chain pass through vertex shader"); + + if (mEGLSamples <= 1) + { + ShaderData pixelShaderData(g_PS_PassthroughRGBA2D); + err = mRenderer->allocateResource(pixelShaderData, &mPassThroughPS); + } + else + { + ShaderData pixelShaderData(g_PS_PassthroughRGBA2DMS); + err = mRenderer->allocateResource(pixelShaderData, &mPassThroughPS); + } + + ASSERT(!err.isError()); + mPassThroughPS.setDebugName("Swap chain pass through pixel shader"); // Use the default rasterizer state but without culling D3D11_RASTERIZER_DESC rasterizerDesc; @@ -655,26 +734,31 @@ void SwapChain11::initPassThroughResources() 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"); + + err = mRenderer->allocateResource(rasterizerDesc, &mPassThroughRS); + ASSERT(!err.isError()); + mPassThroughRS.setDebugName("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) +EGLint SwapChain11::swapRect(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) { if (mNeedsOffscreenTexture) { - EGLint result = copyOffscreenToBackbuffer(x, y, width, height); + EGLint result = copyOffscreenToBackbuffer(context, x, y, width, height); if (result != EGL_SUCCESS) { return result; } } - EGLint result = present(x, y, width, height); + EGLint result = present(context, x, y, width, height); if (result != EGL_SUCCESS) { return result; @@ -685,7 +769,11 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return EGL_SUCCESS; } -EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, EGLint height) +EGLint SwapChain11::copyOffscreenToBackbuffer(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) { if (!mSwapChain) { @@ -698,7 +786,8 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, // Set vertices D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + HRESULT result = + deviceContext->Map(mQuadVB.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { return EGL_BAD_ACCESS; @@ -716,7 +805,6 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, float v1 = y / float(height); float u2 = (x + width) / float(width); float v2 = (y + height) / float(height); - // Invert the quad vertices depending on the surface orientation. if ((mOrientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE) != 0) { @@ -732,60 +820,43 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(EGLint x, EGLint y, EGLint width, d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); - deviceContext->Unmap(mQuadVB, 0); + deviceContext->Unmap(mQuadVB.get(), 0); - static UINT stride = sizeof(d3d11::PositionTexCoordVertex); - static UINT startIdx = 0; - deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); - - // Apply state - deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + StateManager11 *stateManager = mRenderer->getStateManager(); - static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); + constexpr UINT stride = sizeof(d3d11::PositionTexCoordVertex); + stateManager->setSingleVertexBuffer(&mQuadVB, stride, 0); - deviceContext->RSSetState(mPassThroughRS); + // Apply state + stateManager->setDepthStencilState(nullptr, 0xFFFFFFFF); + stateManager->setSimpleBlendState(nullptr); + stateManager->setRasterizerState(&mPassThroughRS); // Apply shaders - deviceContext->IASetInputLayout(mPassThroughIL); - deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - deviceContext->VSSetShader(mPassThroughVS, NULL, 0); - deviceContext->PSSetShader(mPassThroughPS, NULL, 0); - deviceContext->GSSetShader(NULL, NULL, 0); + stateManager->setInputLayout(&mPassThroughIL); + stateManager->setPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + stateManager->setDrawShaders(&mPassThroughVS, nullptr, &mPassThroughPS); - // Apply render targets - mRenderer->setOneTimeRenderTarget(mBackBufferRTView); + // Apply render targets. Use the proxy context in display. + stateManager->setRenderTarget(mBackBufferRTView.get(), nullptr); // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = static_cast(width); - viewport.Height = static_cast(height); - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); + stateManager->setSimpleViewport(mWidth, mHeight); // Apply textures - auto stateManager = mRenderer->getStateManager(); - stateManager->setShaderResource(gl::SAMPLER_PIXEL, 0, mOffscreenSRView); - deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); + stateManager->setSimplePixelTextureAndSampler(mOffscreenSRView, 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) +EGLint SwapChain11::present(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) { if (!mSwapChain) { @@ -799,9 +870,9 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) 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) + // Dirty rect present is not supported with a multisampled swapchain. + if (mSwapChain1 != nullptr && mEGLSamples <= 1) { if (mFirstSwap) { @@ -818,7 +889,6 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) } } else -#endif { result = mSwapChain->Present(swapInterval, 0); } @@ -826,60 +896,111 @@ EGLint SwapChain11::present(EGLint x, EGLint y, EGLint width, EGLint height) mFirstSwap = false; // Some swapping mechanisms such as DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL unbind the current render - // target. Mark it dirty. + // target. Mark it dirty. Use the proxy context in display since there is none available. mRenderer->getStateManager()->invalidateRenderTarget(); if (result == DXGI_ERROR_DEVICE_REMOVED) { - ERR("Present failed: the D3D11 device was removed: 0x%08X", - mRenderer->getDevice()->GetDeviceRemovedReason()); + ERR() << "Present failed: the D3D11 device was removed, " + << gl::FmtHR(mRenderer->getDevice()->GetDeviceRemovedReason()); return EGL_CONTEXT_LOST; } else if (result == DXGI_ERROR_DEVICE_RESET) { - ERR("Present failed: the D3D11 device was reset from a bad command."); + ERR() << "Present failed: the D3D11 device was reset from a bad command."; return EGL_CONTEXT_LOST; } else if (FAILED(result)) { - ERR("Present failed with error code 0x%08X", result); + ERR() << "Present failed with " << gl::FmtHR(result); } - mNativeWindow.commitChange(); + mNativeWindow->commitChange(); return EGL_SUCCESS; } -ID3D11Texture2D *SwapChain11::getOffscreenTexture() +const TextureHelper11 &SwapChain11::getOffscreenTexture() { return mNeedsOffscreenTexture ? mOffscreenTexture : mBackBufferTexture; } -ID3D11RenderTargetView *SwapChain11::getRenderTarget() +const d3d11::RenderTargetView &SwapChain11::getRenderTarget() { return mNeedsOffscreenTexture ? mOffscreenRTView : mBackBufferRTView; } -ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() +const d3d11::SharedSRV &SwapChain11::getRenderTargetShaderResource() { - return mNeedsOffscreenTexture ? mOffscreenSRView : mBackBufferSRView; + if (!mNeedsOffscreenTexture) + { + ASSERT(mBackBufferSRView.valid()); + return mBackBufferSRView; + } + + if (!mNeedsOffscreenTextureCopy) + { + ASSERT(mOffscreenSRView.valid()); + return mOffscreenSRView; + } + + if (!mOffscreenTextureCopyForSRV.valid()) + { + const d3d11::Format &backbufferFormatInfo = + d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps()); + + D3D11_TEXTURE2D_DESC offscreenCopyDesc; + mOffscreenTexture.getDesc(&offscreenCopyDesc); + + offscreenCopyDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + offscreenCopyDesc.MiscFlags = 0; + offscreenCopyDesc.CPUAccessFlags = 0; + gl::Error err = mRenderer->allocateTexture(offscreenCopyDesc, backbufferFormatInfo, + &mOffscreenTextureCopyForSRV); + ASSERT(!err.isError()); + mOffscreenTextureCopyForSRV.setDebugName("Offscreen back buffer copy for SRV"); + + D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; + offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; + offscreenSRVDesc.ViewDimension = + (mEGLSamples <= 1) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; + offscreenSRVDesc.Texture2D.MostDetailedMip = 0; + offscreenSRVDesc.Texture2D.MipLevels = static_cast(-1); + + err = mRenderer->allocateResource(offscreenSRVDesc, mOffscreenTextureCopyForSRV.get(), + &mOffscreenSRView); + ASSERT(!err.isError()); + mOffscreenSRView.setDebugName("Offscreen back buffer shader resource"); + } + + // Need to copy the offscreen texture into the shader-readable copy, since it's external and + // we don't know if the copy is up-to-date. This works around the problem we have when the app + // passes in a texture that isn't shader-readable. + mRenderer->getDeviceContext()->CopyResource(mOffscreenTextureCopyForSRV.get(), + mOffscreenTexture.get()); + return mOffscreenSRView; } -ID3D11DepthStencilView *SwapChain11::getDepthStencil() +const d3d11::DepthStencilView &SwapChain11::getDepthStencil() { return mDepthStencilDSView; } -ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource() +const d3d11::SharedSRV &SwapChain11::getDepthStencilShaderResource() { return mDepthStencilSRView; } -ID3D11Texture2D *SwapChain11::getDepthStencilTexture() +const TextureHelper11 &SwapChain11::getDepthStencilTexture() { return mDepthStencilTexture; } +void *SwapChain11::getKeyedMutex() +{ + return mKeyedMutex; +} + void SwapChain11::recreate() { // possibly should use this method instead of reset @@ -890,4 +1011,61 @@ void *rx::SwapChain11::getDevice() return mRenderer->getDevice(); } +RenderTargetD3D *SwapChain11::getColorRenderTarget() +{ + return &mColorRenderTarget; +} + +RenderTargetD3D *SwapChain11::getDepthStencilRenderTarget() +{ + return &mDepthStencilRenderTarget; +} + +egl::Error SwapChain11::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) +{ + if (!mSwapChain) + { + return egl::EglNotInitialized() << "Swap chain uninitialized"; + } + + DXGI_FRAME_STATISTICS stats = {}; + HRESULT result = mSwapChain->GetFrameStatistics(&stats); + + if (FAILED(result)) + { + return egl::EglBadAlloc() << "Failed to get frame statistics, " << gl::FmtHR(result); + } + + // Conversion from DXGI_FRAME_STATISTICS to the output values: + // stats.SyncRefreshCount -> msc + // stats.PresentCount -> sbc + // stats.SyncQPCTime -> ust with conversion to microseconds via QueryPerformanceFrequency + *msc = stats.SyncRefreshCount; + *sbc = stats.PresentCount; + + LONGLONG syncQPCValue = stats.SyncQPCTime.QuadPart; + // If the QPC Value is below the overflow threshold, we proceed with + // simple multiply and divide. + if (syncQPCValue < kQPCOverflowThreshold) + { + *ust = syncQPCValue * kMicrosecondsPerSecond / mQPCFrequency; + } + else + { + // Otherwise, calculate microseconds in a round about manner to avoid + // overflow and precision issues. + int64_t wholeSeconds = syncQPCValue / mQPCFrequency; + int64_t leftoverTicks = syncQPCValue - (wholeSeconds * mQPCFrequency); + *ust = wholeSeconds * kMicrosecondsPerSecond + + leftoverTicks * kMicrosecondsPerSecond / mQPCFrequency; + } + + return egl::NoError(); +} + +UINT SwapChain11::getD3DSamples() const +{ + return (mEGLSamples == 0) ? 1 : mEGLSamples; } + +} // namespace rx 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 adcd07adb0..eca068210b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h @@ -16,39 +16,54 @@ namespace rx { class Renderer11; +class NativeWindow11; -class SwapChain11 : public SwapChainD3D +class SwapChain11 final : public SwapChainD3D { public: SwapChain11(Renderer11 *renderer, - NativeWindow nativeWindow, + NativeWindow11 *nativeWindow, HANDLE shareHandle, + IUnknown *d3dTexture, GLenum backBufferFormat, GLenum depthBufferFormat, - EGLint orientation); - virtual ~SwapChain11(); - - EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); - virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - virtual void recreate(); - - RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; } - RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; } - - virtual ID3D11Texture2D *getOffscreenTexture(); - virtual ID3D11RenderTargetView *getRenderTarget(); - virtual ID3D11ShaderResourceView *getRenderTargetShaderResource(); - - virtual ID3D11Texture2D *getDepthStencilTexture(); - virtual ID3D11DepthStencilView *getDepthStencil(); - virtual ID3D11ShaderResourceView *getDepthStencilShaderResource(); + EGLint orientation, + EGLint samples); + ~SwapChain11() override; + + EGLint resize(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight) override; + EGLint reset(const gl::Context *context, + EGLint backbufferWidth, + EGLint backbufferHeight, + EGLint swapInterval) override; + EGLint swapRect(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height) override; + void recreate() override; + + RenderTargetD3D *getColorRenderTarget() override; + RenderTargetD3D *getDepthStencilRenderTarget() override; + + const TextureHelper11 &getOffscreenTexture(); + const d3d11::RenderTargetView &getRenderTarget(); + const d3d11::SharedSRV &getRenderTargetShaderResource(); + + const TextureHelper11 &getDepthStencilTexture(); + const d3d11::DepthStencilView &getDepthStencil(); + const d3d11::SharedSRV &getDepthStencilShaderResource(); EGLint getWidth() const { return mWidth; } EGLint getHeight() const { return mHeight; } - void *getKeyedMutex() override { return mKeyedMutex; } + void *getKeyedMutex() override; + EGLint getSamples() const { return mEGLSamples; } + + void *getDevice() override; - virtual void *getDevice(); + egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override; private: void release(); @@ -56,14 +71,23 @@ class SwapChain11 : public SwapChainD3D void releaseOffscreenColorBuffer(); void releaseOffscreenDepthBuffer(); - EGLint resetOffscreenBuffers(int backbufferWidth, int backbufferHeight); - EGLint resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight); + EGLint resetOffscreenBuffers(const gl::Context *context, + int backbufferWidth, + int backbufferHeight); + EGLint resetOffscreenColorBuffer(const gl::Context *context, + 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); + EGLint copyOffscreenToBackbuffer(const gl::Context *context, + EGLint x, + EGLint y, + EGLint width, + EGLint height); + EGLint present(const gl::Context *context, EGLint x, EGLint y, EGLint width, EGLint height); + UINT getD3DSamples() const; Renderer11 *mRenderer; EGLint mWidth; @@ -73,36 +97,41 @@ class SwapChain11 : public SwapChainD3D unsigned int mSwapInterval; bool mPassThroughResourcesInit; + NativeWindow11 *mNativeWindow; // Handler for the Window that the surface is created for. + bool mFirstSwap; - DXGISwapChain *mSwapChain; -#if defined(ANGLE_ENABLE_D3D11_1) + IDXGISwapChain *mSwapChain; IDXGISwapChain1 *mSwapChain1; -#endif IDXGIKeyedMutex *mKeyedMutex; - ID3D11Texture2D *mBackBufferTexture; - ID3D11RenderTargetView *mBackBufferRTView; - ID3D11ShaderResourceView *mBackBufferSRView; + TextureHelper11 mBackBufferTexture; + d3d11::RenderTargetView mBackBufferRTView; + d3d11::SharedSRV mBackBufferSRView; const bool mNeedsOffscreenTexture; - ID3D11Texture2D *mOffscreenTexture; - ID3D11RenderTargetView *mOffscreenRTView; - ID3D11ShaderResourceView *mOffscreenSRView; - - ID3D11Texture2D *mDepthStencilTexture; - ID3D11DepthStencilView *mDepthStencilDSView; - ID3D11ShaderResourceView *mDepthStencilSRView; - - ID3D11Buffer *mQuadVB; - ID3D11SamplerState *mPassThroughSampler; - ID3D11InputLayout *mPassThroughIL; - ID3D11VertexShader *mPassThroughVS; - ID3D11PixelShader *mPassThroughPS; - ID3D11RasterizerState *mPassThroughRS; + TextureHelper11 mOffscreenTexture; + d3d11::RenderTargetView mOffscreenRTView; + d3d11::SharedSRV mOffscreenSRView; + bool mNeedsOffscreenTextureCopy; + TextureHelper11 mOffscreenTextureCopyForSRV; + + TextureHelper11 mDepthStencilTexture; + d3d11::DepthStencilView mDepthStencilDSView; + d3d11::SharedSRV mDepthStencilSRView; + + d3d11::Buffer mQuadVB; + d3d11::SamplerState mPassThroughSampler; + d3d11::InputLayout mPassThroughIL; + d3d11::VertexShader mPassThroughVS; + d3d11::PixelShader mPassThroughPS; + d3d11::RasterizerState mPassThroughRS; SurfaceRenderTarget11 mColorRenderTarget; SurfaceRenderTarget11 mDepthStencilRenderTarget; + + EGLint mEGLSamples; + LONGLONG mQPCFrequency; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_ 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 11b9f76464..b702450ded 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp @@ -5,7 +5,8 @@ // // TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived -// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 +// texture. #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h" @@ -21,6 +22,7 @@ #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/StreamProducerNV12.h" #include "libANGLE/renderer/d3d/d3d11/SwapChain11.h" #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" #include "libANGLE/renderer/d3d/EGLImageD3D.h" @@ -29,82 +31,79 @@ namespace rx { -TextureStorage11::SwizzleCacheValue::SwizzleCacheValue() - : swizzleRed(GL_INVALID_INDEX), - swizzleGreen(GL_INVALID_INDEX), - swizzleBlue(GL_INVALID_INDEX), - swizzleAlpha(GL_INVALID_INDEX) +namespace { + +void InvalidateRenderTarget(const gl::Context *context, RenderTarget11 *renderTarget) +{ + if (renderTarget) + { + renderTarget->signalDirty(context); + } } -TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha) - : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha) +RenderTarget11 *GetRenderTarget(std::unique_ptr *pointer) { + return pointer->get(); } -bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const +template +RenderTarget11 *GetRenderTarget(std::pair> *pair) { - return swizzleRed == other.swizzleRed && - swizzleGreen == other.swizzleGreen && - swizzleBlue == other.swizzleBlue && - swizzleAlpha == other.swizzleAlpha; + return pair->second.get(); } -bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const +template +void InvalidateRenderTargetContainer(const gl::Context *context, T *renderTargetContainer) { - return !(*this == other); + for (auto &rt : *renderTargetContainer) + { + InvalidateRenderTarget(context, GetRenderTarget(&rt)); + } } -TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle) - : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle) +} // anonymous namespace + +TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil) + : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle), dropStencil(dropStencil) { } bool TextureStorage11::SRVKey::operator<(const SRVKey &rhs) const { - return std::tie(baseLevel, mipLevels, swizzle) < std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle); + return std::tie(baseLevel, mipLevels, swizzle, dropStencil) < + std::tie(rhs.baseLevel, rhs.mipLevels, rhs.swizzle, rhs.dropStencil); } -TextureStorage11::TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags) +TextureStorage11::TextureStorage11(Renderer11 *renderer, + UINT bindFlags, + UINT miscFlags, + GLenum internalFormat) : mRenderer(renderer), mTopLevel(0), mMipLevels(0), - mInternalFormat(GL_NONE), - mTextureFormat(DXGI_FORMAT_UNKNOWN), - mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), - mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), - mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), + mFormatInfo(d3d11::Format::Get(internalFormat, mRenderer->getRenderer11DeviceCaps())), mTextureWidth(0), mTextureHeight(0), mTextureDepth(0), + mDropStencilTexture(), mBindFlags(bindFlags), mMiscFlags(miscFlags) { - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mLevelSRVs[i] = nullptr; - } } TextureStorage11::~TextureStorage11() { - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - SafeRelease(mLevelSRVs[level]); - } - - for (SRVCache::iterator i = mSrvCache.begin(); i != mSrvCache.end(); i++) - { - SafeRelease(i->second); - } mSrvCache.clear(); } -DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget) +DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + bool renderTarget) { UINT bindFlags = 0; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); + const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_SHADER_RESOURCE; @@ -121,16 +120,17 @@ DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, const Rendere return bindFlags; } -DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat, const Renderer11DeviceCaps &renderer11DeviceCaps, bool renderTarget, int levels) +DWORD TextureStorage11::GetTextureMiscFlags(GLenum internalFormat, + const Renderer11DeviceCaps &renderer11DeviceCaps, + bool renderTarget, + int levels) { UINT miscFlags = 0; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); + const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); if (renderTarget && levels > 1) { - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); - - if (dxgiFormatInfo.nativeMipmapSupport(renderer11DeviceCaps.featureLevel)) + if (d3d11::SupportsMipGen(formatInfo.texFormat, renderer11DeviceCaps.featureLevel)) { miscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; } @@ -151,6 +151,8 @@ UINT TextureStorage11::getMiscFlags() const int TextureStorage11::getTopLevel() const { + // Applying top level is meant to be encapsulated inside TextureStorage11. + UNREACHABLE(); return mTopLevel; } @@ -189,24 +191,35 @@ int TextureStorage11::getLevelDepth(int mipLevel) const return std::max(static_cast(mTextureDepth) >> mipLevel, 1); } +gl::Error TextureStorage11::getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + return getResource(context, outResource); +} + UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const { - UINT mipSlice = static_cast(index.mipIndex + mTopLevel); - UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); + UINT mipSlice = static_cast(index.mipIndex + mTopLevel); + UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); ASSERT(subresource != std::numeric_limits::max()); return subresource; } -gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState, - ID3D11ShaderResourceView **outSRV) +gl::Error TextureStorage11::getSRV(const gl::Context *context, + const gl::TextureState &textureState, + const d3d11::SharedSRV **outSRV) { - bool swizzleRequired = textureState.swizzleRequired(); - bool mipmapping = gl::IsMipmapFiltered(textureState.samplerState); - unsigned int mipLevels = mipmapping ? (textureState.maxLevel - textureState.baseLevel + 1) : 1; + // Make sure to add the level offset for our tiny compressed texture workaround + const GLuint effectiveBaseLevel = textureState.getEffectiveBaseLevel(); + bool swizzleRequired = textureState.swizzleRequired(); + bool mipmapping = gl::IsMipmapFiltered(textureState.getSamplerState()); + unsigned int mipLevels = + mipmapping ? (textureState.getEffectiveMaxLevel() - effectiveBaseLevel + 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 - textureState.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 - effectiveBaseLevel); if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) { @@ -217,89 +230,133 @@ gl::Error TextureStorage11::getSRV(const gl::TextureState &textureState, 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; - } + ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1)); } if (swizzleRequired) { - verifySwizzleExists(textureState.swizzleRed, textureState.swizzleGreen, - textureState.swizzleBlue, textureState.swizzleAlpha); + verifySwizzleExists(textureState.getSwizzleState()); + } + + // We drop the stencil when sampling from the SRV if three conditions hold: + // 1. the drop stencil workaround is enabled. + bool workaround = mRenderer->getWorkarounds().emulateTinyStencilTextures; + // 2. this is a stencil texture. + bool hasStencil = (mFormatInfo.format().stencilBits > 0); + // 3. the texture has a 1x1 or 2x2 mip. + int effectiveTopLevel = effectiveBaseLevel + mipLevels - 1; + bool hasSmallMips = + (getLevelWidth(effectiveTopLevel) <= 2 || getLevelHeight(effectiveTopLevel) <= 2); + + bool useDropStencil = (workaround && hasStencil && hasSmallMips); + SRVKey key(effectiveBaseLevel, mipLevels, swizzleRequired, useDropStencil); + if (useDropStencil) + { + // Ensure drop texture gets created. + DropStencil result = DropStencil::CREATED; + ANGLE_TRY_RESULT(ensureDropStencilTexture(context), result); + + // Clear the SRV cache if necessary. + // TODO(jmadill): Re-use find query result. + auto srvEntry = mSrvCache.find(key); + if (result == DropStencil::CREATED && srvEntry != mSrvCache.end()) + { + mSrvCache.erase(key); + } } - SRVKey key(textureState.baseLevel, mipLevels, swizzleRequired); + ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV)); + + return gl::NoError(); +} + +gl::Error TextureStorage11::getCachedOrCreateSRV(const gl::Context *context, + const SRVKey &key, + const d3d11::SharedSRV **outSRV) +{ auto iter = mSrvCache.find(key); if (iter != mSrvCache.end()) { - *outSRV = iter->second; - return gl::Error(GL_NO_ERROR); + *outSRV = &iter->second; + return gl::NoError(); } - ID3D11Resource *texture = nullptr; - if (swizzleRequired) + const TextureHelper11 *texture = nullptr; + DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN; + + if (key.swizzle) { - gl::Error error = getSwizzleTexture(&texture); - if (error.isError()) - { - return error; - } + const auto &swizzleFormat = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); + ASSERT(!key.dropStencil || swizzleFormat.format().stencilBits == 0); + ANGLE_TRY(getSwizzleTexture(&texture)); + format = swizzleFormat.srvFormat; } - else + else if (key.dropStencil) { - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } + ASSERT(mDropStencilTexture.valid()); + texture = &mDropStencilTexture; + format = DXGI_FORMAT_R32_FLOAT; } - - ID3D11ShaderResourceView *srv = nullptr; - DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); - gl::Error error = createSRV(textureState.baseLevel, mipLevels, format, texture, &srv); - if (error.isError()) + else { - return error; + ANGLE_TRY(getResource(context, &texture)); + format = mFormatInfo.srvFormat; } - mSrvCache.insert(std::make_pair(key, srv)); - *outSRV = srv; + d3d11::SharedSRV srv; + + ANGLE_TRY(createSRV(context, key.baseLevel, key.mipLevels, format, *texture, &srv)); - return gl::Error(GL_NO_ERROR); + const auto &insertIt = mSrvCache.insert(std::make_pair(key, std::move(srv))); + *outSRV = &insertIt.first->second; + + return gl::NoError(); } -gl::Error TextureStorage11::getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV) +gl::Error TextureStorage11::getSRVLevel(const gl::Context *context, + int mipLevel, + bool blitSRV, + const d3d11::SharedSRV **outSRV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - if (!mLevelSRVs[mipLevel]) + auto &levelSRVs = (blitSRV) ? mLevelBlitSRVs : mLevelSRVs; + auto &otherLevelSRVs = (blitSRV) ? mLevelSRVs : mLevelBlitSRVs; + + if (!levelSRVs[mipLevel].valid()) { - ID3D11Resource *resource = NULL; - gl::Error error = getResource(&resource); - if (error.isError()) + // Only create a different SRV for blit if blit format is different from regular srv format + if (otherLevelSRVs[mipLevel].valid() && mFormatInfo.srvFormat == mFormatInfo.blitSRVFormat) { - return error; + levelSRVs[mipLevel] = otherLevelSRVs[mipLevel].makeCopy(); } - - error = createSRV(mipLevel, 1, mShaderResourceFormat, resource, &mLevelSRVs[mipLevel]); - if (error.isError()) + else { - return error; + const TextureHelper11 *resource = nullptr; + ANGLE_TRY(getResource(context, &resource)); + + DXGI_FORMAT resourceFormat = + blitSRV ? mFormatInfo.blitSRVFormat : mFormatInfo.srvFormat; + ANGLE_TRY( + createSRV(context, mipLevel, 1, resourceFormat, *resource, &levelSRVs[mipLevel])); } } - *outSRV = mLevelSRVs[mipLevel]; + *outSRV = &levelSRVs[mipLevel]; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11ShaderResourceView **outSRV) +gl::Error TextureStorage11::getSRVLevels(const gl::Context *context, + GLint baseLevel, + GLint maxLevel, + const d3d11::SharedSRV **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) + // 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) @@ -310,245 +367,218 @@ gl::Error TextureStorage11::getSRVLevels(GLint baseLevel, GLint maxLevel, ID3D11 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); + ANGLE_TRY(useLevelZeroWorkaroundTexture(context, mipLevels == 1)); } - ID3D11Resource *texture = nullptr; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } + // TODO(jmadill): Assert we don't need to drop stencil. - ID3D11ShaderResourceView *srv = nullptr; - error = createSRV(baseLevel, mipLevels, mShaderResourceFormat, texture, &srv); - if (error.isError()) - { - return error; - } + SRVKey key(baseLevel, mipLevels, false, false); + ANGLE_TRY(getCachedOrCreateSRV(context, key, outSRV)); - mSrvCache[key] = srv; - *outSRV = srv; + return gl::NoError(); +} - return gl::Error(GL_NO_ERROR); +const d3d11::Format &TextureStorage11::getFormatSet() const +{ + return mFormatInfo; } -gl::Error TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +gl::Error TextureStorage11::generateSwizzles(const gl::Context *context, + const gl::SwizzleState &swizzleTarget) { - SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); for (int level = 0; level < getLevelCount(); level++) { // Check if the swizzle for this level is out of date if (mSwizzleCache[level] != swizzleTarget) { // Need to re-render the swizzle for this level - ID3D11ShaderResourceView *sourceSRV = NULL; - gl::Error error = getSRVLevel(level, &sourceSRV); - if (error.isError()) - { - return error; - } + const d3d11::SharedSRV *sourceSRV = nullptr; + ANGLE_TRY(getSRVLevel(context, level, true, &sourceSRV)); - ID3D11RenderTargetView *destRTV = NULL; - error = getSwizzleRenderTarget(level, &destRTV); - if (error.isError()) - { - return error; - } + const d3d11::RenderTargetView *destRTV; + ANGLE_TRY(getSwizzleRenderTarget(level, &destRTV)); gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); Blit11 *blitter = mRenderer->getBlitter(); - error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); - if (error.isError()) - { - return error; - } + ANGLE_TRY(blitter->swizzleTexture(context, *sourceSRV, *destRTV, size, swizzleTarget)); mSwizzleCache[level] = swizzleTarget; } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel) +void TextureStorage11::markLevelDirty(int mipLevel) { - if (mipLevel >= 0 && static_cast(mipLevel) < ArraySize(mSwizzleCache)) + if (mipLevel >= 0 && static_cast(mipLevel) < mSwizzleCache.size()) + { + // The default constructor of SwizzleState has GL_INVALID_INDEX for all channels which is + // not a valid swizzle combination + if (mSwizzleCache[mipLevel] != gl::SwizzleState()) + { + // TODO(jmadill): Invalidate specific swizzle. + mRenderer->getStateManager()->invalidateSwizzles(); + mSwizzleCache[mipLevel] = gl::SwizzleState(); + } + } + + if (mDropStencilTexture.valid()) { - // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a - // valid swizzle combination - mSwizzleCache[mipLevel] = SwizzleCacheValue(); + mDropStencilTexture.reset(); } } -void TextureStorage11::invalidateSwizzleCache() +void TextureStorage11::markDirty() { - for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++) + for (size_t mipLevel = 0; mipLevel < mSwizzleCache.size(); ++mipLevel) { - invalidateSwizzleCacheLevel(mipLevel); + markLevelDirty(static_cast(mipLevel)); } } -gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource, - const gl::ImageIndex &index, const gl::Box ©Area) +gl::Error TextureStorage11::updateSubresourceLevel(const gl::Context *context, + const TextureHelper11 &srcTexture, + unsigned int sourceSubresource, + const gl::ImageIndex &index, + const gl::Box ©Area) { - ASSERT(srcTexture); + ASSERT(srcTexture.valid()); - GLint level = index.mipIndex; + const GLint level = index.mipIndex; - invalidateSwizzleCacheLevel(level); + markLevelDirty(level); gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); - bool fullCopy = copyArea.x == 0 && - copyArea.y == 0 && - copyArea.z == 0 && - copyArea.width == texSize.width && - copyArea.height == texSize.height && - copyArea.depth == texSize.depth; + bool fullCopy = copyArea.x == 0 && copyArea.y == 0 && copyArea.z == 0 && + copyArea.width == texSize.width && copyArea.height == texSize.height && + copyArea.depth == texSize.depth; - ID3D11Resource *dstTexture = NULL; - gl::Error error(GL_NO_ERROR); + const TextureHelper11 *dstTexture = nullptr; - // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should - // update the mipmapped texture, even if mapmaps are currently disabled. + // If the zero-LOD workaround is active and we want to update a level greater than zero, then we + // should update the mipmapped texture, even if mapmaps are currently disabled. if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - error = getMippedResource(&dstTexture); + ANGLE_TRY(getMippedResource(context, &dstTexture)); } else { - error = getResource(&dstTexture); - } - - if (error.isError()) - { - return error; + ANGLE_TRY(getResource(context, &dstTexture)); } unsigned int dstSubresource = getSubresourceIndex(index); - ASSERT(dstTexture); + ASSERT(dstTexture->valid()); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); - if (!fullCopy && (dxgiFormatInfo.depthBits > 0 || dxgiFormatInfo.stencilBits > 0)) + const d3d11::DXGIFormatSize &dxgiFormatSizeInfo = + d3d11::GetDXGIFormatSizeInfo(mFormatInfo.texFormat); + if (!fullCopy && mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) { // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead - Blit11 *blitter = mRenderer->getBlitter(); - + Blit11 *blitter = mRenderer->getBlitter(); return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, - dstTexture, dstSubresource, copyArea, texSize, - NULL); + *dstTexture, dstSubresource, copyArea, texSize, nullptr); } - else - { - D3D11_BOX srcBox; - srcBox.left = copyArea.x; - srcBox.top = copyArea.y; - srcBox.right = copyArea.x + roundUp(static_cast(copyArea.width), dxgiFormatInfo.blockWidth); - srcBox.bottom = copyArea.y + roundUp(static_cast(copyArea.height), dxgiFormatInfo.blockHeight); - srcBox.front = copyArea.z; - srcBox.back = copyArea.z + copyArea.depth; - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + D3D11_BOX srcBox; + srcBox.left = copyArea.x; + srcBox.top = copyArea.y; + srcBox.right = + copyArea.x + roundUp(static_cast(copyArea.width), dxgiFormatSizeInfo.blockWidth); + srcBox.bottom = + copyArea.y + roundUp(static_cast(copyArea.height), dxgiFormatSizeInfo.blockHeight); + srcBox.front = copyArea.z; + srcBox.back = copyArea.z + copyArea.depth; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, - srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox); - return gl::Error(GL_NO_ERROR); - } + deviceContext->CopySubresourceRegion(dstTexture->get(), dstSubresource, copyArea.x, copyArea.y, + copyArea.z, srcTexture.get(), sourceSubresource, + fullCopy ? nullptr : &srcBox); + return gl::NoError(); } -gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, - const gl::ImageIndex &index, const gl::Box ®ion) +gl::Error TextureStorage11::copySubresourceLevel(const gl::Context *context, + const TextureHelper11 &dstTexture, + unsigned int dstSubresource, + const gl::ImageIndex &index, + const gl::Box ®ion) { - ASSERT(dstTexture); + ASSERT(dstTexture.valid()); - ID3D11Resource *srcTexture = NULL; - gl::Error error(GL_NO_ERROR); + const TextureHelper11 *srcTexture = nullptr; - // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should - // update the mipmapped texture, even if mapmaps are currently disabled. + // If the zero-LOD workaround is active and we want to update a level greater than zero, then we + // should update the mipmapped texture, even if mapmaps are currently disabled. if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - error = getMippedResource(&srcTexture); + ANGLE_TRY(getMippedResource(context, &srcTexture)); } else { - error = getResource(&srcTexture); - } - - if (error.isError()) - { - return error; + ANGLE_TRY(getResource(context, &srcTexture)); } - ASSERT(srcTexture); + ASSERT(srcTexture->valid()); unsigned int srcSubresource = getSubresourceIndex(index); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox should be NULL. + // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox + // should be nullptr. D3D11_BOX srcBox; - D3D11_BOX *pSrcBox = NULL; + D3D11_BOX *pSrcBox = nullptr; 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 - // textures on 9_3. - ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).depthBits == 0); - ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).stencilBits == 0); - srcBox.left = region.x; - srcBox.right = region.x + region.width; - srcBox.top = region.y; - srcBox.bottom = region.y + region.height; - srcBox.front = region.z; - srcBox.back = region.z + region.depth; - pSrcBox = &srcBox; + GLsizei width = region.width; + GLsizei height = region.height; + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, nullptr); + + // Keep srcbox as nullptr if we're dealing with tiny mips of compressed textures. + if (width == region.width && height == region.height) + { + // 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 textures on 9_3. + ASSERT(mFormatInfo.dsvFormat == DXGI_FORMAT_UNKNOWN); + srcBox.left = region.x; + srcBox.right = region.x + region.width; + srcBox.top = region.y; + srcBox.bottom = region.y + region.height; + srcBox.front = region.z; + srcBox.back = region.z + region.depth; + pSrcBox = &srcBox; + } } - context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z, - srcTexture, srcSubresource, pSrcBox); + deviceContext->CopySubresourceRegion(dstTexture.get(), dstSubresource, region.x, region.y, + region.z, srcTexture->get(), srcSubresource, pSrcBox); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) +gl::Error TextureStorage11::generateMipmap(const gl::Context *context, + const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) { ASSERT(sourceIndex.layerIndex == destIndex.layerIndex); - invalidateSwizzleCacheLevel(destIndex.mipIndex); + markLevelDirty(destIndex.mipIndex); - RenderTargetD3D *source = NULL; - gl::Error error = getRenderTarget(sourceIndex, &source); - if (error.isError()) - { - return error; - } + RenderTargetD3D *source = nullptr; + ANGLE_TRY(getRenderTarget(context, sourceIndex, &source)); - RenderTargetD3D *dest = NULL; - error = getRenderTarget(destIndex, &dest); - if (error.isError()) - { - return error; - } + RenderTargetD3D *dest = nullptr; + ANGLE_TRY(getRenderTarget(context, destIndex, &dest)); - ID3D11ShaderResourceView *sourceSRV = GetAs(source)->getShaderResourceView(); - ID3D11RenderTargetView *destRTV = GetAs(dest)->getRenderTargetView(); + RenderTarget11 *rt11 = GetAs(source); + const d3d11::SharedSRV &sourceSRV = rt11->getBlitShaderResourceView(); + const d3d11::RenderTargetView &destRTV = rt11->getRenderTargetView(); gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); @@ -557,90 +587,75 @@ 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, false); + GLenum format = gl::GetUnsizedFormat(source->getInternalFormat()); + return blitter->copyTexture(context, sourceSRV, sourceArea, sourceSize, format, destRTV, + destArea, destSize, nullptr, format, GL_LINEAR, false, false, + false); } -void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +void TextureStorage11::verifySwizzleExists(const gl::SwizzleState &swizzleState) { - SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); for (unsigned int level = 0; level < mMipLevels; level++) { - ASSERT(mSwizzleCache[level] == swizzleTarget); + ASSERT(mSwizzleCache[level] == swizzleState); } } 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++; - } - } + markDirty(); + mSrvCache.clear(); - for (size_t level = 0; level < ArraySize(mLevelSRVs); level++) + for (size_t level = 0; level < mLevelSRVs.size(); level++) { - SafeRelease(mLevelSRVs[level]); + mLevelSRVs[level].reset(); + mLevelBlitSRVs[level].reset(); } } -gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage11::copyToStorage(const gl::Context *context, TextureStorage *destStorage) { ASSERT(destStorage); - ID3D11Resource *sourceResouce = NULL; - gl::Error error = getResource(&sourceResouce); - if (error.isError()) - { - return error; - } + const TextureHelper11 *sourceResouce = nullptr; + ANGLE_TRY(getResource(context, &sourceResouce)); - TextureStorage11 *dest11 = GetAs(destStorage); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + TextureStorage11 *dest11 = GetAs(destStorage); + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - immediateContext->CopyResource(destResource, sourceResouce); + immediateContext->CopyResource(destResource->get(), sourceResouce->get()); - dest11->invalidateSwizzleCache(); + dest11->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type, - const gl::PixelUnpackState &unpack, const uint8_t *pixelData) +gl::Error TextureStorage11::setData(const gl::Context *context, + const gl::ImageIndex &index, + ImageD3D *image, + const gl::Box *destBox, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixelData) { ASSERT(!image->isDirty()); - ID3D11Resource *resource = NULL; - gl::Error error = getResource(&resource); - if (error.isError()) - { - return error; - } - ASSERT(resource); + markLevelDirty(index.mipIndex); + + const TextureHelper11 *resource = nullptr; + ANGLE_TRY(getResource(context, &resource)); + ASSERT(resource && resource->valid()); UINT destSubresource = getSubresourceIndex(index); - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(image->getInternalFormat()); + const gl::InternalFormat &internalFormatInfo = + gl::GetInternalFormatInfo(image->getInternalFormat(), type); - gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), getLevelDepth(index.mipIndex)); - bool fullUpdate = (destBox == NULL || *destBox == levelBox); + gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), + getLevelDepth(index.mipIndex)); + bool fullUpdate = (destBox == nullptr || *destBox == levelBox); ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate); // TODO(jmadill): Handle compressed formats @@ -649,36 +664,44 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image // with compressed formats in the calling logic. ASSERT(!internalFormatInfo.compressed); - int width = destBox ? destBox->width : static_cast(image->getWidth()); - 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, unpack.imageHeight); - GLsizei srcSkipBytes = internalFormatInfo.computeSkipPixels( - srcRowPitch, srcDepthPitch, unpack.skipImages, unpack.skipRows, unpack.skipPixels); - - const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps()); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat); - - size_t outputPixelSize = dxgiFormatInfo.pixelBytes; + const int imageWidth = static_cast(image->getWidth()); + const int width = destBox ? destBox->width : imageWidth; + const int imageHeight = static_cast(image->getHeight()); + const int height = destBox ? destBox->height : imageHeight; + const int imageDepth = static_cast(image->getDepth()); + const int depth = destBox ? destBox->depth : imageDepth; + if (imageWidth < width || imageHeight < height || imageDepth < depth) + fullUpdate = true; + GLuint srcRowPitch = 0; + ANGLE_TRY_RESULT( + internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength), + srcRowPitch); + GLuint srcDepthPitch = 0; + ANGLE_TRY_RESULT(internalFormatInfo.computeDepthPitch(height, unpack.imageHeight, srcRowPitch), + srcDepthPitch); + GLuint srcSkipBytes = 0; + ANGLE_TRY_RESULT( + internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()), + srcSkipBytes); + + const d3d11::Format &d3d11Format = + d3d11::Format::Get(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps()); + const d3d11::DXGIFormatSize &dxgiFormatInfo = + d3d11::GetDXGIFormatSizeInfo(d3d11Format.texFormat); + + const size_t outputPixelSize = dxgiFormatInfo.pixelBytes; UINT bufferRowPitch = static_cast(outputPixelSize) * width; UINT bufferDepthPitch = bufferRowPitch * height; - size_t neededSize = bufferDepthPitch * depth; - MemoryBuffer *conversionBuffer = nullptr; + const size_t neededSize = bufferDepthPitch * depth; + angle::MemoryBuffer *conversionBuffer = nullptr; const uint8_t *data = nullptr; - d3d11::LoadImageFunctionInfo loadFunctionInfo = d3d11Format.loadFunctions.at(type); + LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(type); if (loadFunctionInfo.requiresConversion) { - error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer); - if (error.isError()) - { - return error; - } - + ANGLE_TRY(mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer)); loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch, srcDepthPitch, conversionBuffer->data(), bufferRowPitch, bufferDepthPitch); @@ -698,264 +721,233 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image ASSERT(destBox); D3D11_BOX destD3DBox; - destD3DBox.left = destBox->x; - destD3DBox.right = destBox->x + destBox->width; - destD3DBox.top = destBox->y; + destD3DBox.left = destBox->x; + destD3DBox.right = destBox->x + destBox->width; + destD3DBox.top = destBox->y; destD3DBox.bottom = destBox->y + destBox->height; - destD3DBox.front = destBox->z; - destD3DBox.back = destBox->z + destBox->depth; + destD3DBox.front = destBox->z; + destD3DBox.back = destBox->z + destBox->depth; - immediateContext->UpdateSubresource(resource, destSubresource, &destD3DBox, data, + immediateContext->UpdateSubresource(resource->get(), destSubresource, &destD3DBox, data, bufferRowPitch, bufferDepthPitch); } else { - immediateContext->UpdateSubresource(resource, destSubresource, NULL, data, bufferRowPitch, - bufferDepthPitch); + immediateContext->UpdateSubresource(resource->get(), destSubresource, nullptr, data, + bufferRowPitch, bufferDepthPitch); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); +} + +gl::ErrorOrResult TextureStorage11::ensureDropStencilTexture( + const gl::Context *context) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "Drop stencil texture not implemented."; } TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, 0), + : TextureStorage11(renderer, + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, + 0, + swapchain->getRenderTargetInternalFormat()), mTexture(swapchain->getOffscreenTexture()), - mLevelZeroTexture(NULL), - mLevelZeroRenderTarget(NULL), + mLevelZeroTexture(), + mLevelZeroRenderTarget(nullptr), mUseLevelZeroTexture(false), - mSwizzleTexture(NULL) + mSwizzleTexture() { - mTexture->AddRef(); - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mAssociatedImages[i] = NULL; - mRenderTarget[i] = NULL; - mSwizzleRenderTargets[i] = NULL; + mAssociatedImages[i] = nullptr; + mRenderTarget[i] = nullptr; } D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - mMipLevels = texDesc.MipLevels; - mTextureFormat = texDesc.Format; - mTextureWidth = texDesc.Width; + mTexture.getDesc(&texDesc); + mMipLevels = texDesc.MipLevels; + mTextureWidth = texDesc.Width; mTextureHeight = texDesc.Height; - mTextureDepth = 1; - - mInternalFormat = swapchain->GetRenderTargetInternalFormat(); - - ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srv->GetDesc(&srvDesc); - mShaderResourceFormat = srvDesc.Format; - - ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - offscreenRTV->GetDesc(&rtvDesc); - mRenderTargetFormat = rtvDesc.Format; - - 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; - - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; -} - -TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) - : TextureStorage11(renderer, - GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), - GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels)), - mTexture(NULL), - mLevelZeroTexture(NULL), - mLevelZeroRenderTarget(NULL), - mUseLevelZeroTexture(false), - mSwizzleTexture(NULL) + mTextureDepth = 1; + mHasKeyedMutex = (texDesc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0; +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, + GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + int levels, + bool hintLevelZeroOnly) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, + renderer->getRenderer11DeviceCaps(), + renderTarget, + levels), + internalformat), + mTexture(), + mHasKeyedMutex(false), + mLevelZeroTexture(), + mLevelZeroRenderTarget(nullptr), + mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1), + mSwizzleTexture() { for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - mAssociatedImages[i] = NULL; - mRenderTarget[i] = NULL; - mSwizzleRenderTargets[i] = NULL; + mAssociatedImages[i] = nullptr; + mRenderTarget[i] = nullptr; } - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); - mMipLevels = mTopLevel + levels; - mTextureWidth = width; + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); + mMipLevels = mTopLevel + levels; + mTextureWidth = width; mTextureHeight = height; - mTextureDepth = 1; + mTextureDepth = 1; - if (hintLevelZeroOnly && levels > 1) - { - //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. - ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); - mUseLevelZeroTexture = true; - } + // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround); } -TextureStorage11_2D::~TextureStorage11_2D() +gl::Error TextureStorage11_2D::onDestroy(const gl::Context *context) { for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - if (mAssociatedImages[i] != NULL) + if (mAssociatedImages[i] != nullptr) { - bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); + mAssociatedImages[i]->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - gl::Error error = mAssociatedImages[i]->recoverFromAssociatedStorage(); - if (error.isError()) - { - // TODO: Find a way to report this back to the context - } - } + // We must let the Images recover their data before we delete it from the + // TextureStorage. + ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context)); } } - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); - - SafeRelease(mLevelZeroTexture); - SafeDelete(mLevelZeroRenderTarget); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + if (mHasKeyedMutex) { - SafeDelete(mRenderTarget[i]); - SafeRelease(mSwizzleRenderTargets[i]); + // If the keyed mutex is released that will unbind it and cause the state cache to become + // desynchronized. + mRenderer->getStateManager()->invalidateBoundViews(); } + + // Invalidate RenderTargets. + InvalidateRenderTargetContainer(context, &mRenderTarget); + InvalidateRenderTarget(context, mLevelZeroRenderTarget.get()); + + return gl::NoError(); +} + +TextureStorage11_2D::~TextureStorage11_2D() +{ } -gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage11_2D::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) { ASSERT(destStorage); - TextureStorage11_2D *dest11 = GetAs(destStorage); + TextureStorage11_2D *dest11 = GetAs(destStorage); + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - - // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage. - if (mTexture) + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the + // corresponding textures in destStorage. + if (mTexture.valid()) { - gl::Error error = dest11->useLevelZeroWorkaroundTexture(false); - if (error.isError()) - { - return error; - } + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - immediateContext->CopyResource(destResource, mTexture); + immediateContext->CopyResource(destResource->get(), mTexture.get()); } - if (mLevelZeroTexture) + if (mLevelZeroTexture.valid()) { - gl::Error error = dest11->useLevelZeroWorkaroundTexture(true); - if (error.isError()) - { - return error; - } + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - immediateContext->CopyResource(destResource, mLevelZeroTexture); + immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get()); } + + return gl::NoError(); } - else - { - ID3D11Resource *sourceResouce = NULL; - gl::Error error = getResource(&sourceResouce); - if (error.isError()) - { - return error; - } - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *sourceResouce = nullptr; + ANGLE_TRY(getResource(context, &sourceResouce)); - ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - immediateContext->CopyResource(destResource, sourceResouce); - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - dest11->invalidateSwizzleCache(); + immediateContext->CopyResource(destResource->get(), sourceResouce->get()); + dest11->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) { + bool lastSetting = mUseLevelZeroTexture; + if (useLevelZeroTexture && mMipLevels > 1) { - if (!mUseLevelZeroTexture && mTexture) + if (!mUseLevelZeroTexture && mTexture.valid()) { - gl::Error error = ensureTextureExists(1); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(1)); // Pull data back from the mipped texture if necessary. - ASSERT(mLevelZeroTexture); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - context->CopySubresourceRegion(mLevelZeroTexture, 0, 0, 0, 0, mTexture, 0, NULL); + ASSERT(mLevelZeroTexture.valid()); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(), 0, 0, 0, 0, + mTexture.get(), 0, nullptr); } mUseLevelZeroTexture = true; } else { - if (mUseLevelZeroTexture && mLevelZeroTexture) + if (mUseLevelZeroTexture && mLevelZeroTexture.valid()) { - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(mMipLevels)); // Pull data back from the level zero texture if necessary. - ASSERT(mTexture); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - context->CopySubresourceRegion(mTexture, 0, 0, 0, 0, mLevelZeroTexture, 0, NULL); + ASSERT(mTexture.valid()); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->CopySubresourceRegion(mTexture.get(), 0, 0, 0, 0, + mLevelZeroTexture.get(), 0, nullptr); } mUseLevelZeroTexture = false; } - return gl::Error(GL_NO_ERROR); + if (lastSetting != mUseLevelZeroTexture) + { + // Mark everything as dirty to be conservative. + if (mLevelZeroRenderTarget) + { + mLevelZeroRenderTarget->signalDirty(context); + } + for (auto &renderTarget : mRenderTarget) + { + if (renderTarget) + { + renderTarget->signalDirty(context); + } + } + } + + return gl::NoError(); } -void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index) +void TextureStorage11_2D::associateImage(Image11 *image, const gl::ImageIndex &index) { - GLint level = index.mipIndex; + const GLint level = index.mipIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); @@ -965,539 +957,569 @@ void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &i } } -bool TextureStorage11_2D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_2D::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) { - GLint level = index.mipIndex; - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - // This validation check should never return false. It means the Image/TextureStorage association is broken. - bool retValue = (mAssociatedImages[level] == expectedImage); - ASSERT(retValue); - return retValue; - } + const GLint level = index.mipIndex; - return false; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + ASSERT(mAssociatedImages[level] == expectedImage); } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_2D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) { - GLint level = index.mipIndex; + const GLint level = index.mipIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - ASSERT(mAssociatedImages[level] == expectedImage); - - if (mAssociatedImages[level] == expectedImage) - { - mAssociatedImages[level] = NULL; - } - } + ASSERT(mAssociatedImages[level] == expectedImage); + mAssociatedImages[level] = nullptr; } -// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image +// recover its data before ending the association. +gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) { - GLint level = index.mipIndex; + const GLint level = index.mipIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) { // No need to let the old Image recover its data, if it is also the incoming Image. - if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) + if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage) { - // Ensure that the Image is still associated with this TextureStorage. This should be true. - bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); + // Ensure that the Image is still associated with this TextureStorage. + mAssociatedImages[level]->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to nullptr too. + ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_2D::getResource(const gl::Context *context, + const TextureHelper11 **outResource) { if (mUseLevelZeroTexture && mMipLevels > 1) { - gl::Error error = ensureTextureExists(1); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(1)); - *outResource = mLevelZeroTexture; - return gl::Error(GL_NO_ERROR); + *outResource = &mLevelZeroTexture; + return gl::NoError(); } - else - { - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); - } + ANGLE_TRY(ensureTextureExists(mMipLevels)); + + *outResource = &mTexture; + return gl::NoError(); } -gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_2D::getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) { // This shouldn't be called unless the zero max LOD workaround is active. ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(mMipLevels)); - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + *outResource = &mTexture; + return gl::NoError(); } gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels) { // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. - bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false; - ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround + ? (mipLevels == 1) && (mMipLevels > 1) + : false; + TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; // if the width or height is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation - if (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0) { ASSERT(mipLevels > 0); - ID3D11Device *device = mRenderer->getDevice(); - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; // Compressed texture size constraints? - desc.Height = mTextureHeight; - desc.MipLevels = mipLevels; - desc.ArraySize = 1; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; // Compressed texture size constraints? + desc.Height = mTextureHeight; + desc.MipLevels = mipLevels; + desc.ArraySize = 1; + desc.Format = mFormatInfo.texFormat; + desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = getMiscFlags(); - - HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D texture storage, result: 0x%X.", result); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = getMiscFlags(); - d3d11::SetDebugName(*outputTexture, "TexStorage2D.Texture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, outputTexture)); + outputTexture->setDebugName("TexStorage2D.Texture"); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage11_2D::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { ASSERT(!index.hasLayer()); - int level = index.mipIndex; + const int level = index.mipIndex; ASSERT(level >= 0 && level < getLevelCount()); - // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of the GLES 2.0 spec, page 113 of version 2.0.25). - // Other parts of TextureStorage11_2D could create RTVs on non-zero levels of the texture (e.g. generateMipmap). - // 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->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0)); - - if (!mRenderTarget[level]) + // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of + // the GLES 2.0 spec, page 113 of version 2.0.25). Other parts of TextureStorage11_2D could + // create RTVs on non-zero levels of the texture (e.g. generateMipmap). + // 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->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3 && level > 0)); + ASSERT(outRT); + if (mRenderTarget[level]) { - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - - ID3D11ShaderResourceView *srv = NULL; - error = getSRVLevel(level, &srv); - if (error.isError()) - { - return error; - } + *outRT = mRenderTarget[level].get(); + return gl::NoError(); + } - if (mUseLevelZeroTexture) - { - if (!mLevelZeroRenderTarget) - { - ID3D11Device *device = mRenderer->getDevice(); + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) + { + ASSERT(index.mipIndex == 0); + ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true)); + } - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = mTopLevel + level; + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); - ID3D11RenderTargetView *rtv; - HRESULT result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv); + const d3d11::SharedSRV *srv = nullptr; + ANGLE_TRY(getSRVLevel(context, level, false, &srv)); - if (result == E_OUTOFMEMORY) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } - ASSERT(SUCCEEDED(result)); + const d3d11::SharedSRV *blitSRV = nullptr; + ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV)); - mLevelZeroRenderTarget = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + if (mUseLevelZeroTexture) + { + if (!mLevelZeroRenderTarget) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - } + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture.get(), &rtv)); - ASSERT(outRT); - *outRT = mLevelZeroRenderTarget; - return gl::Error(GL_NO_ERROR); + mLevelZeroRenderTarget.reset(new TextureRenderTarget11( + std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(), + mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level), + getLevelHeight(level), 1, 0)); } - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - ID3D11Device *device = mRenderer->getDevice(); + *outRT = mLevelZeroRenderTarget.get(); + return gl::NoError(); + } - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = mTopLevel + level; + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; - ID3D11RenderTargetView *rtv; - HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } + mRenderTarget[level].reset(new TextureRenderTarget11( + std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0)); - mRenderTarget[level] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + *outRT = mRenderTarget[level].get(); + return gl::NoError(); + } - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - ID3D11Device *device = mRenderer->getDevice(); + ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2D.MipSlice = mTopLevel + level; - dsvDesc.Flags = 0; + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mFormatInfo.dsvFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = mTopLevel + level; + dsvDesc.Flags = 0; - ID3D11DepthStencilView *dsv; - HRESULT result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); + d3d11::DepthStencilView dsv; + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv)); - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY,"Failed to create internal depth stencil view for texture storage, result: 0x%X.", result); - } + mRenderTarget[level].reset(new TextureRenderTarget11( + std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0)); - mRenderTarget[level] = new TextureRenderTarget11(dsv, texture, srv, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); + *outRT = mRenderTarget[level].get(); + return gl::NoError(); +} - // RenderTarget will take ownership of these resources - SafeRelease(dsv); - } - else - { - UNREACHABLE(); - } - } - - ASSERT(outRT); - *outRT = mRenderTarget[level]; - return gl::Error(GL_NO_ERROR); -} - -gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const +gl::Error TextureStorage11_2D::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { ASSERT(outSRV); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2D.MipLevels = mipLevels; + srvDesc.Texture2D.MipLevels = mipLevels; - ID3D11Resource *srvTexture = texture; + const TextureHelper11 *srvTexture = &texture; if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) { ASSERT(mTopLevel == 0); ASSERT(baseLevel == 0); - // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture. + // This code also assumes that the incoming texture equals either mLevelZeroTexture or + // mTexture. if (mipLevels == 1 && mMipLevels > 1) { // We must use a SRV on the level-zero-only texture. - ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture); - srvTexture = mLevelZeroTexture; + ANGLE_TRY(ensureTextureExists(1)); + srvTexture = &mLevelZeroTexture; } else { ASSERT(mipLevels == static_cast(mMipLevels)); - ASSERT(mTexture != NULL && texture == mTexture); - srvTexture = mTexture; + ASSERT(mTexture.valid() && texture == mTexture); + srvTexture = &mTexture; } } - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(srvTexture, &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, "TexStorage2D.SRV"); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, srvTexture->get(), outSRV)); + outSRV->setDebugName("TexStorage2D.SRV"); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2D::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_2D::getSwizzleTexture(const TextureHelper11 **outTexture) { ASSERT(outTexture); - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = 1; - desc.Format = mSwizzleTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 1; + desc.Format = format.texFormat; + 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); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; - d3d11::SetDebugName(mSwizzleTexture, "TexStorage2D.SwizzleTexture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorage2D.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } -gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; + 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); - } + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &mSwizzleRenderTargets[mipLevel])); } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRTV = &mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); } -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) +gl::ErrorOrResult TextureStorage11_2D::ensureDropStencilTexture( + const gl::Context *context) { - 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 + if (mDropStencilTexture.valid()) { - mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; + return DropStencil::ALREADY_EXISTS; } - ID3D11DepthStencilView *dsv = renderTarget11->getDepthStencilView(); - if (dsv != nullptr) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsv->GetDesc(&dsvDesc); - mDepthStencilFormat = dsvDesc.Format; - } - else - { - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - } + D3D11_TEXTURE2D_DESC dropDesc = {}; + dropDesc.ArraySize = 1; + dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; + dropDesc.CPUAccessFlags = 0; + dropDesc.Format = DXGI_FORMAT_R32_TYPELESS; + dropDesc.Height = mTextureHeight; + dropDesc.MipLevels = mMipLevels; + dropDesc.MiscFlags = 0; + dropDesc.SampleDesc.Count = 1; + dropDesc.SampleDesc.Quality = 0; + dropDesc.Usage = D3D11_USAGE_DEFAULT; + dropDesc.Width = mTextureWidth; + + const auto &format = + d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps()); + ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture)); + mDropStencilTexture.setDebugName("TexStorage2D.DropStencil"); + + ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::Make2D(0, mMipLevels))); - 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; + return DropStencil::CREATED; } -TextureStorage11_EGLImage::~TextureStorage11_EGLImage() +TextureStorage11_External::TextureStorage11_External( + Renderer11 *renderer, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &glDesc) + : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat) { - SafeRelease(mSwizzleTexture); - for (size_t i = 0; i < mSwizzleRenderTargets.size(); i++) - { - SafeRelease(mSwizzleRenderTargets[i]); - } + ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11TextureNV12); + StreamProducerNV12 *producer = static_cast(stream->getImplementation()); + mTexture.set(producer->getD3DTexture(), mFormatInfo); + mSubresourceIndex = producer->getArraySlice(); + mTexture.get()->AddRef(); + mMipLevels = 1; + + D3D11_TEXTURE2D_DESC desc; + mTexture.getDesc(&desc); + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = 1; + mHasKeyedMutex = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX) != 0; } -gl::Error TextureStorage11_EGLImage::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_External::onDestroy(const gl::Context *context) { - gl::Error error = checkForUpdatedRenderTarget(); - if (error.isError()) + if (mHasKeyedMutex) { - return error; + // If the keyed mutex is released that will unbind it and cause the state cache to become + // desynchronized. + mRenderer->getStateManager()->invalidateBoundViews(); } - RenderTarget11 *renderTarget11 = nullptr; - error = getImageRenderTarget(&renderTarget11); - if (error.isError()) - { - return error; - } + return gl::NoError(); +} + +TextureStorage11_External::~TextureStorage11_External() +{ +} + +gl::Error TextureStorage11_External::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) +{ + UNIMPLEMENTED(); + return gl::NoError(); +} + +void TextureStorage11_External::associateImage(Image11 *image, const gl::ImageIndex &index) +{ + ASSERT(index.mipIndex == 0); + mAssociatedImage = image; +} + +void TextureStorage11_External::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + ASSERT(index.mipIndex == 0 && mAssociatedImage == expectedImage); +} - *outResource = renderTarget11->getTexture(); - return gl::Error(GL_NO_ERROR); +void TextureStorage11_External::disassociateImage(const gl::ImageIndex &index, + Image11 *expectedImage) +{ + ASSERT(index.mipIndex == 0); + ASSERT(mAssociatedImage == expectedImage); + mAssociatedImage = nullptr; } -gl::Error TextureStorage11_EGLImage::getSRV(const gl::TextureState &textureState, - ID3D11ShaderResourceView **outSRV) +gl::Error TextureStorage11_External::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) { - gl::Error error = checkForUpdatedRenderTarget(); - if (error.isError()) + ASSERT(index.mipIndex == 0); + + if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage) { - return error; + mAssociatedImage->verifyAssociatedStorageValid(this); + + ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context)); } - return TextureStorage11::getSRV(textureState, outSRV); + return gl::NoError(); +} + +gl::Error TextureStorage11_External::getResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + *outResource = &mTexture; + return gl::NoError(); +} + +gl::Error TextureStorage11_External::getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + *outResource = &mTexture; + return gl::NoError(); +} + +gl::Error TextureStorage11_External::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + // Render targets are not supported for external textures + UNREACHABLE(); + return gl::InternalError(); +} + +gl::Error TextureStorage11_External::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) +{ + // Since external textures are treates as non-mipmapped textures, we ignore mipmap levels and + // use the specified subresource ID the storage was created with. + ASSERT(mipLevels == 1); + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + // subresource index is equal to the mip level for 2D textures + srvDesc.Texture2DArray.MostDetailedMip = 0; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = mSubresourceIndex; + srvDesc.Texture2DArray.ArraySize = 1; + + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorage2D.SRV"); + + return gl::NoError(); +} + +gl::Error TextureStorage11_External::getSwizzleTexture(const TextureHelper11 **outTexture) +{ + UNIMPLEMENTED(); + return gl::InternalError(); +} + +gl::Error TextureStorage11_External::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) +{ + UNIMPLEMENTED(); + return gl::InternalError(); +} + +TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer, + EGLImageD3D *eglImage, + RenderTarget11 *renderTarget11) + : TextureStorage11(renderer, + D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, + 0, + renderTarget11->getInternalFormat()), + mImage(eglImage), + mCurrentRenderTarget(0), + mSwizzleTexture(), + mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) +{ + mCurrentRenderTarget = reinterpret_cast(renderTarget11); + + mMipLevels = 1; + mTextureWidth = renderTarget11->getWidth(); + mTextureHeight = renderTarget11->getHeight(); + mTextureDepth = 1; +} + +TextureStorage11_EGLImage::~TextureStorage11_EGLImage() +{ +} + +gl::Error TextureStorage11_EGLImage::getResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + ANGLE_TRY(checkForUpdatedRenderTarget(context)); + + RenderTarget11 *renderTarget11 = nullptr; + ANGLE_TRY(getImageRenderTarget(context, &renderTarget11)); + *outResource = &renderTarget11->getTexture(); + return gl::NoError(); +} + +gl::Error TextureStorage11_EGLImage::getSRV(const gl::Context *context, + const gl::TextureState &textureState, + const d3d11::SharedSRV **outSRV) +{ + ANGLE_TRY(checkForUpdatedRenderTarget(context)); + return TextureStorage11::getSRV(context, textureState, outSRV); } -gl::Error TextureStorage11_EGLImage::getMippedResource(ID3D11Resource **) +gl::Error TextureStorage11_EGLImage::getMippedResource(const gl::Context *context, + const TextureHelper11 **) { // 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); + return gl::InternalError(); } -gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::ImageIndex &index, +gl::Error TextureStorage11_EGLImage::getRenderTarget(const gl::Context *context, + 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; - } + ANGLE_TRY(checkForUpdatedRenderTarget(context)); - return mImage->getRenderTarget(outRT); + return mImage->getRenderTarget(context, outRT); } -gl::Error TextureStorage11_EGLImage::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage11_EGLImage::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) { - ID3D11Resource *sourceResouce = nullptr; - gl::Error error = getResource(&sourceResouce); - if (error.isError()) - { - return error; - } + const TextureHelper11 *sourceResouce = nullptr; + ANGLE_TRY(getResource(context, &sourceResouce)); ASSERT(destStorage); TextureStorage11_2D *dest11 = GetAs(destStorage); - ID3D11Resource *destResource = nullptr; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - immediateContext->CopyResource(destResource, sourceResouce); + immediateContext->CopyResource(destResource->get(), sourceResouce->get()); - dest11->invalidateSwizzleCache(); + dest11->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void TextureStorage11_EGLImage::associateImage(Image11 *, const gl::ImageIndex &) @@ -1508,36 +1530,37 @@ void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &, Image1 { } -bool TextureStorage11_EGLImage::isAssociatedImageValid(const gl::ImageIndex &, Image11 *) +void TextureStorage11_EGLImage::verifyAssociatedImageValid(const gl::ImageIndex &, Image11 *) { - return false; } -gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::ImageIndex &, Image11 *) +gl::Error TextureStorage11_EGLImage::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &, + Image11 *) { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(bool) +gl::Error TextureStorage11_EGLImage::useLevelZeroWorkaroundTexture(const gl::Context *context, bool) { UNREACHABLE(); - return gl::Error(GL_INVALID_OPERATION); + return gl::InternalError(); } -gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_EGLImage::getSwizzleTexture(const TextureHelper11 **outTexture) { ASSERT(outTexture); - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE2D_DESC desc; desc.Width = mTextureWidth; desc.Height = mTextureHeight; desc.MipLevels = mMipLevels; desc.ArraySize = 1; - desc.Format = mSwizzleTextureFormat; + desc.Format = format.texFormat; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; @@ -1545,68 +1568,43 @@ gl::Error TextureStorage11_EGLImage::getSwizzleTexture(ID3D11Resource **outTextu 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"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorageEGLImage.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } gl::Error TextureStorage11_EGLImage::getSwizzleRenderTarget(int mipLevel, - ID3D11RenderTargetView **outRTV) + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; 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); - } + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &mSwizzleRenderTargets[mipLevel])); } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRTV = &mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); } -gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget() +gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget(const gl::Context *context) { RenderTarget11 *renderTarget11 = nullptr; - gl::Error error = getImageRenderTarget(&renderTarget11); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getImageRenderTarget(context, &renderTarget11)); if (mCurrentRenderTarget != reinterpret_cast(renderTarget11)) { @@ -1614,14 +1612,15 @@ gl::Error TextureStorage11_EGLImage::checkForUpdatedRenderTarget() mCurrentRenderTarget = reinterpret_cast(renderTarget11); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel, +gl::Error TextureStorage11_EGLImage::createSRV(const gl::Context *context, + int baseLevel, int mipLevels, DXGI_FORMAT format, - ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { ASSERT(baseLevel == 0); ASSERT(mipLevels == 1); @@ -1637,163 +1636,129 @@ gl::Error TextureStorage11_EGLImage::createSRV(int baseLevel, 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"); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorageEGLImage.SRV"); } else { RenderTarget11 *renderTarget = nullptr; - gl::Error error = getImageRenderTarget(&renderTarget); - if (error.isError()) - { - return error; - } + ANGLE_TRY(getImageRenderTarget(context, &renderTarget)); ASSERT(texture == renderTarget->getTexture()); - *outSRV = renderTarget->getShaderResourceView(); - (*outSRV)->AddRef(); + *outSRV = renderTarget->getShaderResourceView().makeCopy(); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_EGLImage::getImageRenderTarget(RenderTarget11 **outRT) const +gl::Error TextureStorage11_EGLImage::getImageRenderTarget(const gl::Context *context, + RenderTarget11 **outRT) const { RenderTargetD3D *renderTargetD3D = nullptr; - gl::Error error = mImage->getRenderTarget(&renderTargetD3D); - if (error.isError()) - { - return error; - } - + ANGLE_TRY(mImage->getRenderTarget(context, &renderTargetD3D)); *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->getRenderer11DeviceCaps(), renderTarget), - GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels)) + return gl::NoError(); +} + +TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, + GLenum internalformat, + bool renderTarget, + int size, + int levels, + bool hintLevelZeroOnly) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, + renderer->getRenderer11DeviceCaps(), + renderTarget, + levels), + internalformat), + mTexture(), + mLevelZeroTexture(), + mUseLevelZeroTexture(hintLevelZeroOnly && levels > 1), + mSwizzleTexture() { - mTexture = NULL; - mSwizzleTexture = NULL; - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - mSwizzleRenderTargets[level] = NULL; - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++) { - mAssociatedImages[face][level] = NULL; - mRenderTarget[face][level] = NULL; + mAssociatedImages[face][level] = nullptr; + mRenderTarget[face][level] = nullptr; } } - mLevelZeroTexture = NULL; - mUseLevelZeroTexture = false; - - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++) { - mLevelZeroRenderTarget[face] = NULL; + mLevelZeroRenderTarget[face] = nullptr; } - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - // adjust size if needed for compressed textures int height = size; - d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel); + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &size, &height, &mTopLevel); - mMipLevels = mTopLevel + levels; - mTextureWidth = size; + mMipLevels = mTopLevel + levels; + mTextureWidth = size; mTextureHeight = size; - mTextureDepth = 1; + mTextureDepth = 1; - if (hintLevelZeroOnly && levels > 1) - { - //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. - ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); - mUseLevelZeroTexture = true; - } + // The LevelZeroOnly hint should only be true if the zero max LOD workaround is active. + ASSERT(!mUseLevelZeroTexture || mRenderer->getWorkarounds().zeroMaxLodWorkaround); } -TextureStorage11_Cube::~TextureStorage11_Cube() +gl::Error TextureStorage11_Cube::onDestroy(const gl::Context *context) { for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) { - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + for (unsigned int face = 0; face < gl::CUBE_FACE_COUNT; face++) { - if (mAssociatedImages[face][level] != NULL) + if (mAssociatedImages[face][level] != nullptr) { - bool imageAssociationCorrect = mAssociatedImages[face][level]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - mAssociatedImages[face][level]->recoverFromAssociatedStorage(); - } + mAssociatedImages[face][level]->verifyAssociatedStorageValid(this); + + // We must let the Images recover their data before we delete it from the + // TextureStorage. + ANGLE_TRY(mAssociatedImages[face][level]->recoverFromAssociatedStorage(context)); } } } - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); - SafeRelease(mLevelZeroTexture); - - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) + for (auto &faceRenderTargets : mRenderTarget) { - SafeDelete(mLevelZeroRenderTarget[face]); + InvalidateRenderTargetContainer(context, &faceRenderTargets); } + InvalidateRenderTargetContainer(context, &mLevelZeroRenderTarget); - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - SafeRelease(mSwizzleRenderTargets[level]); - for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++) - { - SafeDelete(mRenderTarget[face][level]); - } - } + return gl::NoError(); +} + +TextureStorage11_Cube::~TextureStorage11_Cube() +{ } UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const { - if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && index.mipIndex == 0) + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && + index.mipIndex == 0) { - UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); + UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); UINT subresource = D3D11CalcSubresource(0, arraySlice, 1); ASSERT(subresource != std::numeric_limits::max()); return subresource; } else { - UINT mipSlice = static_cast(index.mipIndex + mTopLevel); - UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); + UINT mipSlice = static_cast(index.mipIndex + mTopLevel); + UINT arraySlice = static_cast(index.hasLayer() ? index.layerIndex : 0); UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels); ASSERT(subresource != std::numeric_limits::max()); return subresource; } } -gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage) +gl::Error TextureStorage11_Cube::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) { ASSERT(destStorage); @@ -1803,87 +1768,63 @@ gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage) { ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage. - if (mTexture) + // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the + // corresponding textures in destStorage. + if (mTexture.valid()) { - gl::Error error = dest11->useLevelZeroWorkaroundTexture(false); - if (error.isError()) - { - return error; - } + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, false)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - immediateContext->CopyResource(destResource, mTexture); + immediateContext->CopyResource(destResource->get(), mTexture.get()); } - if (mLevelZeroTexture) + if (mLevelZeroTexture.valid()) { - gl::Error error = dest11->useLevelZeroWorkaroundTexture(true); - if (error.isError()) - { - return error; - } + ANGLE_TRY(dest11->useLevelZeroWorkaroundTexture(context, true)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); - immediateContext->CopyResource(destResource, mLevelZeroTexture); + immediateContext->CopyResource(destResource->get(), mLevelZeroTexture.get()); } } else { - ID3D11Resource *sourceResouce = NULL; - gl::Error error = getResource(&sourceResouce); - if (error.isError()) - { - return error; - } + const TextureHelper11 *sourceResouce = nullptr; + ANGLE_TRY(getResource(context, &sourceResouce)); - ID3D11Resource *destResource = NULL; - error = dest11->getResource(&destResource); - if (error.isError()) - { - return error; - } + const TextureHelper11 *destResource = nullptr; + ANGLE_TRY(dest11->getResource(context, &destResource)); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); - immediateContext->CopyResource(destResource, sourceResouce); + immediateContext->CopyResource(destResource->get(), sourceResouce->get()); } - dest11->invalidateSwizzleCache(); + dest11->markDirty(); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) +gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) { if (useLevelZeroTexture && mMipLevels > 1) { - if (!mUseLevelZeroTexture && mTexture) + if (!mUseLevelZeroTexture && mTexture.valid()) { - gl::Error error = ensureTextureExists(1); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(1)); // Pull data back from the mipped texture if necessary. - ASSERT(mLevelZeroTexture); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + ASSERT(mLevelZeroTexture.valid()); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); for (int face = 0; face < 6; face++) { - context->CopySubresourceRegion(mLevelZeroTexture, D3D11CalcSubresource(0, face, 1), 0, 0, 0, mTexture, face * mMipLevels, NULL); + deviceContext->CopySubresourceRegion(mLevelZeroTexture.get(), + D3D11CalcSubresource(0, face, 1), 0, 0, 0, + mTexture.get(), face * mMipLevels, nullptr); } } @@ -1891,346 +1832,286 @@ gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZero } else { - if (mUseLevelZeroTexture && mLevelZeroTexture) + if (mUseLevelZeroTexture && mLevelZeroTexture.valid()) { - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } + ANGLE_TRY(ensureTextureExists(mMipLevels)); // Pull data back from the level zero texture if necessary. - ASSERT(mTexture); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + ASSERT(mTexture.valid()); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); for (int face = 0; face < 6; face++) { - context->CopySubresourceRegion(mTexture, D3D11CalcSubresource(0, face, mMipLevels), 0, 0, 0, mLevelZeroTexture, face, NULL); + deviceContext->CopySubresourceRegion(mTexture.get(), + D3D11CalcSubresource(0, face, mMipLevels), 0, + 0, 0, mLevelZeroTexture.get(), face, nullptr); } } mUseLevelZeroTexture = false; } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index) +void TextureStorage11_Cube::associateImage(Image11 *image, const gl::ImageIndex &index) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); + ASSERT(0 <= layerTarget && layerTarget < static_cast(gl::CUBE_FACE_COUNT)); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) + if (0 <= layerTarget && layerTarget < static_cast(gl::CUBE_FACE_COUNT)) { mAssociatedImages[layerTarget][level] = image; } } } -bool TextureStorage11_Cube::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_Cube::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) - { - // This validation check should never return false. It means the Image/TextureStorage association is broken. - bool retValue = (mAssociatedImages[layerTarget][level] == expectedImage); - ASSERT(retValue); - return retValue; - } - } - - return false; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < static_cast(gl::CUBE_FACE_COUNT)); + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_Cube::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) - { - ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); - - if (mAssociatedImages[layerTarget][level] == expectedImage) - { - mAssociatedImages[layerTarget][level] = NULL; - } - } - } + ASSERT(0 <= layerTarget && layerTarget < static_cast(gl::CUBE_FACE_COUNT)); + ASSERT(mAssociatedImages[layerTarget][level] == expectedImage); + mAssociatedImages[layerTarget][level] = nullptr; } -// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image +// recover its data before ending the association. +gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - ASSERT(0 <= layerTarget && layerTarget < CUBE_FACE_COUNT); + ASSERT(0 <= layerTarget && layerTarget < static_cast(gl::CUBE_FACE_COUNT)); if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) { - if (0 <= layerTarget && layerTarget < CUBE_FACE_COUNT) + if (0 <= layerTarget && layerTarget < static_cast(gl::CUBE_FACE_COUNT)) { // No need to let the old Image recover its data, if it is also the incoming Image. - if (mAssociatedImages[layerTarget][level] != NULL && mAssociatedImages[layerTarget][level] != incomingImage) + if (mAssociatedImages[layerTarget][level] != nullptr && + mAssociatedImages[layerTarget][level] != incomingImage) { - // Ensure that the Image is still associated with this TextureStorage. This should be true. - bool imageAssociationCorrect = mAssociatedImages[layerTarget][level]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } + // Ensure that the Image is still associated with this TextureStorage. + mAssociatedImages[layerTarget][level]->verifyAssociatedStorageValid(this); + + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to nullptr too. + ANGLE_TRY( + mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(context)); } } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_Cube::getResource(const gl::Context *context, + const TextureHelper11 **outResource) { if (mUseLevelZeroTexture && mMipLevels > 1) { - gl::Error error = ensureTextureExists(1); - if (error.isError()) - { - return error; - } - - *outResource = mLevelZeroTexture; - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(ensureTextureExists(1)); + *outResource = &mLevelZeroTexture; + return gl::NoError(); } else { - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } - - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(ensureTextureExists(mMipLevels)); + *outResource = &mTexture; + return gl::NoError(); } } -gl::Error TextureStorage11_Cube::getMippedResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_Cube::getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) { // This shouldn't be called unless the zero max LOD workaround is active. ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround); - gl::Error error = ensureTextureExists(mMipLevels); - if (error.isError()) - { - return error; - } - - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(ensureTextureExists(mMipLevels)); + *outResource = &mTexture; + return gl::NoError(); } gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels) { // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture. - bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false; - ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; + bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround + ? (mipLevels == 1) && (mMipLevels > 1) + : false; + TextureHelper11 *outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture; // if the size is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation - if (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0) + if (!outputTexture->valid() && mTextureWidth > 0 && mTextureHeight > 0) { ASSERT(mMipLevels > 0); - ID3D11Device *device = mRenderer->getDevice(); - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mipLevels; - desc.ArraySize = CUBE_FACE_COUNT; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mipLevels; + desc.ArraySize = gl::CUBE_FACE_COUNT; + desc.Format = mFormatInfo.texFormat; + desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags(); + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE | getMiscFlags(); - HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture); + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, outputTexture)); + outputTexture->setDebugName("TexStorageCube.Texture"); + } - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create cube texture storage, result: 0x%X.", result); - } + return gl::NoError(); +} + +gl::Error TextureStorage11_Cube::createRenderTargetSRV(const TextureHelper11 &texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + d3d11::SharedSRV *srv) const +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = resourceFormat; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex; + srvDesc.Texture2DArray.ArraySize = 1; - d3d11::SetDebugName(*outputTexture, "TexStorageCube.Texture"); + if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_10_0) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + } + else + { + // Will be used with Texture2D sampler, not TextureCube + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; } - return gl::Error(GL_NO_ERROR); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), srv)); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage11_Cube::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { - int faceIndex = index.layerIndex; - int level = index.mipIndex; + const int faceIndex = index.layerIndex; + const int level = index.mipIndex; ASSERT(level >= 0 && level < getLevelCount()); - ASSERT(faceIndex >= 0 && faceIndex < CUBE_FACE_COUNT); + ASSERT(faceIndex >= 0 && faceIndex < static_cast(gl::CUBE_FACE_COUNT)); if (!mRenderTarget[faceIndex][level]) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) + if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) { - return error; + ASSERT(index.mipIndex == 0); + ANGLE_TRY(useLevelZeroWorkaroundTexture(context, true)); } + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); + if (mUseLevelZeroTexture) { if (!mLevelZeroRenderTarget[faceIndex]) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; - rtvDesc.Texture2DArray.ArraySize = 1; + rtvDesc.Texture2DArray.ArraySize = 1; - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mLevelZeroTexture.get(), &rtv)); - if (result == E_OUTOFMEMORY) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } - ASSERT(SUCCEEDED(result)); - - mLevelZeroRenderTarget[faceIndex] = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); + mLevelZeroRenderTarget[faceIndex].reset(new TextureRenderTarget11( + std::move(rtv), mLevelZeroTexture, d3d11::SharedSRV(), d3d11::SharedSRV(), + mFormatInfo.internalFormat, getFormatSet(), getLevelWidth(level), + getLevelHeight(level), 1, 0)); } ASSERT(outRT); - *outRT = mLevelZeroRenderTarget[faceIndex]; - return gl::Error(GL_NO_ERROR); + *outRT = mLevelZeroRenderTarget[faceIndex].get(); + return gl::NoError(); } - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = faceIndex; - srvDesc.Texture2DArray.ArraySize = 1; - - if (mRenderer->getRenderer11DeviceCaps().featureLevel <= D3D_FEATURE_LEVEL_9_3) + d3d11::SharedSRV srv; + ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.srvFormat, &srv)); + d3d11::SharedSRV blitSRV; + if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat) { - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.blitSRVFormat, &blitSRV)); } else { - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube + blitSRV = srv.makeCopy(); } - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(texture, &srvDesc, &srv); + srv.setDebugName("TexStorageCube.RenderTargetSRV"); - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); - } + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; + rtvDesc.Texture2DArray.ArraySize = 1; - d3d11::SetDebugName(srv, "TexStorageCube.RenderTargetSRV"); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + rtv.setDebugName("TexStorageCube.RenderTargetRTV"); - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11( + std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0)); + } + else if (mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; - rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; - rtvDesc.Texture2DArray.ArraySize = 1; + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mFormatInfo.dsvFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Flags = 0; + dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; + dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; + dsvDesc.Texture2DArray.ArraySize = 1; - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); + d3d11::DepthStencilView dsv; + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv)); + dsv.setDebugName("TexStorageCube.RenderTargetDSV"); - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - 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 - SafeRelease(rtv); - SafeRelease(srv); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; - dsvDesc.Flags = 0; - dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; - dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; - dsvDesc.Texture2DArray.ArraySize = 1; - - ID3D11DepthStencilView *dsv; - result = device->CreateDepthStencilView(texture, &dsvDesc, &dsv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - 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 - SafeRelease(dsv); - SafeRelease(srv); + mRenderTarget[faceIndex][level].reset(new TextureRenderTarget11( + std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, 0)); } else { @@ -2239,215 +2120,237 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re } ASSERT(outRT); - *outRT = mRenderTarget[faceIndex][level]; - return gl::Error(GL_NO_ERROR); + *outRT = mRenderTarget[faceIndex][level].get(); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const +gl::Error TextureStorage11_Cube::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { ASSERT(outSRV); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = format; - // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); - if (dxgiFormatInfo.componentType == GL_INT || dxgiFormatInfo.componentType == GL_UNSIGNED_INT) + // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six + // 2D textures + const GLenum componentType = d3d11::GetComponentType(format); + if (componentType == GL_INT || componentType == GL_UNSIGNED_INT) { - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; srvDesc.Texture2DArray.MipLevels = mipLevels; srvDesc.Texture2DArray.FirstArraySlice = 0; - srvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; + srvDesc.Texture2DArray.ArraySize = gl::CUBE_FACE_COUNT; } else { - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - srvDesc.TextureCube.MipLevels = mipLevels; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = mipLevels; srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; } - ID3D11Resource *srvTexture = texture; + const TextureHelper11 *srvTexture = &texture; if (mRenderer->getWorkarounds().zeroMaxLodWorkaround) { ASSERT(mTopLevel == 0); ASSERT(baseLevel == 0); - // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture. + // This code also assumes that the incoming texture equals either mLevelZeroTexture or + // mTexture. if (mipLevels == 1 && mMipLevels > 1) { // We must use a SRV on the level-zero-only texture. - ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture); - srvTexture = mLevelZeroTexture; + ANGLE_TRY(ensureTextureExists(1)); + srvTexture = &mLevelZeroTexture; } else { ASSERT(mipLevels == static_cast(mMipLevels)); - ASSERT(mTexture != NULL && texture == mTexture); - srvTexture = mTexture; + ASSERT(mTexture.valid() && texture == mTexture); + srvTexture = &mTexture; } } - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, srvTexture->get(), outSRV)); + outSRV->setDebugName("TexStorageCube.SRV"); - 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, "TexStorageCube.SRV"); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_Cube::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_Cube::getSwizzleTexture(const TextureHelper11 **outTexture) { ASSERT(outTexture); - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = CUBE_FACE_COUNT; - desc.Format = mSwizzleTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = gl::CUBE_FACE_COUNT; + desc.Format = format.texFormat; + 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 = D3D11_RESOURCE_MISC_TEXTURECUBE; - - 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); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; - d3d11::SetDebugName(*outTexture, "TexStorageCube.SwizzleTexture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorageCube.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } -gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; rtvDesc.Texture2DArray.FirstArraySlice = 0; - rtvDesc.Texture2DArray.ArraySize = CUBE_FACE_COUNT; + rtvDesc.Texture2DArray.ArraySize = gl::CUBE_FACE_COUNT; - 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); - } + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &mSwizzleRenderTargets[mipLevel])); } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRTV = &mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); } -TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, - GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), - GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels)) +gl::Error TextureStorage11::initDropStencilTexture(const gl::Context *context, + const gl::ImageIndexIterator &it) { - mTexture = NULL; - mSwizzleTexture = NULL; + const TextureHelper11 *sourceTexture = nullptr; + ANGLE_TRY(getResource(context, &sourceTexture)); - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + gl::ImageIndexIterator itCopy = it; + + while (itCopy.hasNext()) + { + gl::ImageIndex index = itCopy.next(); + gl::Box wholeArea(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), + 1); + gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1); + UINT subresource = getSubresourceIndex(index); + ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil( + *sourceTexture, subresource, wholeArea, wholeSize, mDropStencilTexture, subresource, + wholeArea, wholeSize, nullptr)); + } + + return gl::NoError(); +} + +gl::ErrorOrResult TextureStorage11_Cube::ensureDropStencilTexture( + const gl::Context *context) +{ + if (mDropStencilTexture.valid()) { - mAssociatedImages[i] = NULL; - mLevelRenderTargets[i] = NULL; - mSwizzleRenderTargets[i] = NULL; + return DropStencil::ALREADY_EXISTS; } - mInternalFormat = internalformat; + D3D11_TEXTURE2D_DESC dropDesc = {}; + dropDesc.ArraySize = 6; + dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; + dropDesc.CPUAccessFlags = 0; + dropDesc.Format = DXGI_FORMAT_R32_TYPELESS; + dropDesc.Height = mTextureHeight; + dropDesc.MipLevels = mMipLevels; + dropDesc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + dropDesc.SampleDesc.Count = 1; + dropDesc.SampleDesc.Quality = 0; + dropDesc.Usage = D3D11_USAGE_DEFAULT; + dropDesc.Width = mTextureWidth; - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; + const auto &format = + d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps()); + ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture)); + mDropStencilTexture.setDebugName("TexStorageCube.DropStencil"); + + ANGLE_TRY(initDropStencilTexture(context, gl::ImageIndexIterator::MakeCube(0, mMipLevels))); + + return DropStencil::CREATED; +} + +TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, + GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, + renderer->getRenderer11DeviceCaps(), + renderTarget, + levels), + internalformat) +{ + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mAssociatedImages[i] = nullptr; + mLevelRenderTargets[i] = nullptr; + } // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); - mMipLevels = mTopLevel + levels; - mTextureWidth = width; + mMipLevels = mTopLevel + levels; + mTextureWidth = width; mTextureHeight = height; - mTextureDepth = depth; + mTextureDepth = depth; } -TextureStorage11_3D::~TextureStorage11_3D() +gl::Error TextureStorage11_3D::onDestroy(const gl::Context *context) { for (unsigned i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { - if (mAssociatedImages[i] != NULL) + if (mAssociatedImages[i] != nullptr) { - bool imageAssociationCorrect = mAssociatedImages[i]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); + mAssociatedImages[i]->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - mAssociatedImages[i]->recoverFromAssociatedStorage(); - } + // We must let the Images recover their data before we delete it from the + // TextureStorage. + ANGLE_TRY(mAssociatedImages[i]->recoverFromAssociatedStorage(context)); } } - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); + InvalidateRenderTargetContainer(context, &mLevelRenderTargets); + InvalidateRenderTargetContainer(context, &mLevelLayerRenderTargets); - for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++) - { - SafeDelete(i->second); - } - mLevelLayerRenderTargets.clear(); + return gl::NoError(); +} - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - SafeDelete(mLevelRenderTargets[i]); - SafeRelease(mSwizzleRenderTargets[i]); - } +TextureStorage11_3D::~TextureStorage11_3D() +{ } -void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &index) +void TextureStorage11_3D::associateImage(Image11 *image, const gl::ImageIndex &index) { - GLint level = index.mipIndex; + const GLint level = index.mipIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); @@ -2457,676 +2360,796 @@ void TextureStorage11_3D::associateImage(Image11* image, const gl::ImageIndex &i } } -bool TextureStorage11_3D::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_3D::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) { - GLint level = index.mipIndex; + const GLint level = index.mipIndex; - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - // This validation check should never return false. It means the Image/TextureStorage association is broken. - bool retValue = (mAssociatedImages[level] == expectedImage); - ASSERT(retValue); - return retValue; - } - - return false; + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + ASSERT(mAssociatedImages[level] == expectedImage); } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_3D::disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) { - GLint level = index.mipIndex; + const GLint level = index.mipIndex; ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - - if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - { - ASSERT(mAssociatedImages[level] == expectedImage); - - if (mAssociatedImages[level] == expectedImage) - { - mAssociatedImages[level] = NULL; - } - } + ASSERT(mAssociatedImages[level] == expectedImage); + mAssociatedImages[level] = nullptr; } -// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image +// recover its data before ending the association. +gl::Error TextureStorage11_3D::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) { - GLint level = index.mipIndex; + const GLint level = index.mipIndex; ASSERT((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)); if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) { // No need to let the old Image recover its data, if it is also the incoming Image. - if (mAssociatedImages[level] != NULL && mAssociatedImages[level] != incomingImage) + if (mAssociatedImages[level] != nullptr && mAssociatedImages[level] != incomingImage) { - // Ensure that the Image is still associated with this TextureStorage. This should be true. - bool imageAssociationCorrect = mAssociatedImages[level]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); + // Ensure that the Image is still associated with this TextureStorage. + mAssociatedImages[level]->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[level]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to nullptr too. + ANGLE_TRY(mAssociatedImages[level]->recoverFromAssociatedStorage(context)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_3D::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_3D::getResource(const gl::Context *context, + const TextureHelper11 **outResource) { - // If the width, height or depth are not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + // If the width, height or depth are not positive this should be treated as an incomplete + // texture. We handle that here by skipping the d3d texture creation. + if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) { ASSERT(mMipLevels > 0); - ID3D11Device *device = mRenderer->getDevice(); - D3D11_TEXTURE3D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.Depth = mTextureDepth; - desc.MipLevels = mMipLevels; - desc.Format = mTextureFormat; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = mFormatInfo.texFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); desc.CPUAccessFlags = 0; - desc.MiscFlags = getMiscFlags(); - - HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 3D texture storage, result: 0x%X.", result); - } + desc.MiscFlags = getMiscFlags(); - d3d11::SetDebugName(mTexture, "TexStorage3D.Texture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture)); + mTexture.setDebugName("TexStorage3D.Texture"); } - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + *outResource = &mTexture; + return gl::NoError(); } -gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const +gl::Error TextureStorage11_3D::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { ASSERT(outSRV); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; srvDesc.Texture3D.MostDetailedMip = baseLevel; - srvDesc.Texture3D.MipLevels = mipLevels; + srvDesc.Texture3D.MipLevels = mipLevels; - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorage3D.SRV"); - 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, "TexStorage3D.SRV"); - - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage11_3D::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { - int mipLevel = index.mipIndex; + const int mipLevel = index.mipIndex; ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN); + ASSERT(mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN); if (!index.hasLayer()) { if (!mLevelRenderTargets[mipLevel]) { - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); - ID3D11ShaderResourceView *srv = NULL; - error = getSRVLevel(mipLevel, &srv); - if (error.isError()) - { - return error; - } + const d3d11::SharedSRV *srv = nullptr; + ANGLE_TRY(getSRVLevel(context, mipLevel, false, &srv)); - ID3D11Device *device = mRenderer->getDevice(); + const d3d11::SharedSRV *blitSRV = nullptr; + ANGLE_TRY(getSRVLevel(context, mipLevel, true, &blitSRV)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; rtvDesc.Texture3D.FirstWSlice = 0; - rtvDesc.Texture3D.WSize = static_cast(-1); - - ID3D11RenderTargetView *rtv; - HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - 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"); + rtvDesc.Texture3D.WSize = static_cast(-1); - mLevelRenderTargets[mipLevel] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(mipLevel), 0); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + rtv.setDebugName("TexStorage3D.RTV"); - // RenderTarget will take ownership of these resources - SafeRelease(rtv); + mLevelRenderTargets[mipLevel].reset(new TextureRenderTarget11( + std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, + getFormatSet(), getLevelWidth(mipLevel), getLevelHeight(mipLevel), + getLevelDepth(mipLevel), 0)); } ASSERT(outRT); - *outRT = mLevelRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRT = mLevelRenderTargets[mipLevel].get(); + return gl::NoError(); } - else - { - int layer = index.layerIndex; - LevelLayerKey key(mipLevel, layer); - if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) - { - return error; - } - - // TODO, what kind of SRV is expected here? - ID3D11ShaderResourceView *srv = NULL; + const int layer = index.layerIndex; - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; - rtvDesc.Texture3D.FirstWSlice = layer; - rtvDesc.Texture3D.WSize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } - ASSERT(SUCCEEDED(result)); + LevelLayerKey key(mipLevel, layer); + if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) + { + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); - d3d11::SetDebugName(rtv, "TexStorage3D.LayerRTV"); + // TODO, what kind of SRV is expected here? + const d3d11::SharedSRV srv; + const d3d11::SharedSRV blitSRV; - mLevelLayerRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = layer; + rtvDesc.Texture3D.WSize = 1; - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - } + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + rtv.setDebugName("TexStorage3D.LayerRTV"); - ASSERT(outRT); - *outRT = mLevelLayerRenderTargets[key]; - return gl::Error(GL_NO_ERROR); + mLevelLayerRenderTargets[key].reset(new TextureRenderTarget11( + std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0)); } + + ASSERT(outRT); + *outRT = mLevelLayerRenderTargets[key].get(); + return gl::NoError(); } -gl::Error TextureStorage11_3D::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_3D::getSwizzleTexture(const TextureHelper11 **outTexture) { ASSERT(outTexture); - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE3D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.Depth = mTextureDepth; - desc.MipLevels = mMipLevels; - desc.Format = mSwizzleTextureFormat; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = format.texFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture3D(&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); - } + desc.MiscFlags = 0; - d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleTexture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorage3D.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } -gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; rtvDesc.Texture3D.FirstWSlice = 0; - rtvDesc.Texture3D.WSize = static_cast(-1); + rtvDesc.Texture3D.WSize = static_cast(-1); - 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); - } - - d3d11::SetDebugName(mSwizzleTexture, "TexStorage3D.SwizzleRTV"); + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &mSwizzleRenderTargets[mipLevel])); + mSwizzleRenderTargets[mipLevel].setDebugName("TexStorage3D.SwizzleRTV"); } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + *outRTV = &mSwizzleRenderTargets[mipLevel]; + return gl::NoError(); } -TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels) - : TextureStorage11(renderer, - GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), - GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget, levels)) +TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, + GLenum internalformat, + bool renderTarget, + GLsizei width, + GLsizei height, + GLsizei depth, + int levels) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), renderTarget), + GetTextureMiscFlags(internalformat, + renderer->getRenderer11DeviceCaps(), + renderTarget, + levels), + internalformat) { - mTexture = NULL; - mSwizzleTexture = NULL; - - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - mSwizzleRenderTargets[level] = NULL; - } - - mInternalFormat = internalformat; - - const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getRenderer11DeviceCaps()); - mTextureFormat = formatInfo.texFormat; - mShaderResourceFormat = formatInfo.srvFormat; - mDepthStencilFormat = formatInfo.dsvFormat; - mRenderTargetFormat = formatInfo.rtvFormat; - mSwizzleTextureFormat = formatInfo.swizzleTexFormat; - mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat; - mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat; - // adjust size if needed for compressed textures - d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); - mMipLevels = mTopLevel + levels; - mTextureWidth = width; + mMipLevels = mTopLevel + levels; + mTextureWidth = width; mTextureHeight = height; - mTextureDepth = depth; + mTextureDepth = depth; } -TextureStorage11_2DArray::~TextureStorage11_2DArray() +gl::Error TextureStorage11_2DArray::onDestroy(const gl::Context *context) { - for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++) + for (auto iter : mAssociatedImages) { - if (i->second) + if (iter.second) { - bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); + iter.second->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // We must let the Images recover their data before we delete it from the TextureStorage. - i->second->recoverFromAssociatedStorage(); - } + // We must let the Images recover their data before we delete it from the + // TextureStorage. + ANGLE_TRY(iter.second->recoverFromAssociatedStorage(context)); } } mAssociatedImages.clear(); - SafeRelease(mTexture); - SafeRelease(mSwizzleTexture); + InvalidateRenderTargetContainer(context, &mRenderTargets); - for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - SafeRelease(mSwizzleRenderTargets[level]); - } + return gl::NoError(); +} - for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++) - { - SafeDelete(i->second); - } - mRenderTargets.clear(); +TextureStorage11_2DArray::~TextureStorage11_2DArray() +{ } -void TextureStorage11_2DArray::associateImage(Image11* image, const gl::ImageIndex &index) +void TextureStorage11_2DArray::associateImage(Image11 *image, const gl::ImageIndex &index) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + const GLint numLayers = index.numLayers; ASSERT(0 <= level && level < getLevelCount()); if (0 <= level && level < getLevelCount()) { - LevelLayerKey key(level, layerTarget); + LevelLayerRangeKey key(level, layerTarget, numLayers); mAssociatedImages[key] = image; } } -bool TextureStorage11_2DArray::isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_2DArray::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + const GLint numLayers = index.numLayers; - LevelLayerKey key(level, layerTarget); + LevelLayerRangeKey key(level, layerTarget, numLayers); - // This validation check should never return false. It means the Image/TextureStorage association is broken. - bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); + // This validation check should never return false. It means the Image/TextureStorage + // association is broken. + bool retValue = (mAssociatedImages.find(key) != mAssociatedImages.end() && + (mAssociatedImages[key] == expectedImage)); ASSERT(retValue); - return retValue; } // disassociateImage allows an Image to end its association with a Storage. -void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) +void TextureStorage11_2DArray::disassociateImage(const gl::ImageIndex &index, + Image11 *expectedImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + const GLint numLayers = index.numLayers; - LevelLayerKey key(level, layerTarget); + LevelLayerRangeKey key(level, layerTarget, numLayers); - bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && (mAssociatedImages[key] == expectedImage)); + bool imageAssociationCorrect = (mAssociatedImages.find(key) != mAssociatedImages.end() && + (mAssociatedImages[key] == expectedImage)); ASSERT(imageAssociationCorrect); - - if (imageAssociationCorrect) - { - mAssociatedImages[key] = NULL; - } + mAssociatedImages[key] = nullptr; } -// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image recover its data before ending the association. -gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) +// releaseAssociatedImage prepares the Storage for a new Image association. It lets the old Image +// recover its data before ending the association. +gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) { - GLint level = index.mipIndex; - GLint layerTarget = index.layerIndex; + const GLint level = index.mipIndex; + const GLint layerTarget = index.layerIndex; + const GLint numLayers = index.numLayers; - LevelLayerKey key(level, layerTarget); + LevelLayerRangeKey key(level, layerTarget, numLayers); if (mAssociatedImages.find(key) != mAssociatedImages.end()) { - if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage) + if (mAssociatedImages[key] != nullptr && mAssociatedImages[key] != incomingImage) { - // Ensure that the Image is still associated with this TextureStorage. This should be true. - bool imageAssociationCorrect = mAssociatedImages[key]->isAssociatedStorageValid(this); - ASSERT(imageAssociationCorrect); + // Ensure that the Image is still associated with this TextureStorage. + mAssociatedImages[key]->verifyAssociatedStorageValid(this); - if (imageAssociationCorrect) - { - // Force the image to recover from storage before its data is overwritten. - // This will reset mAssociatedImages[level] to NULL too. - gl::Error error = mAssociatedImages[key]->recoverFromAssociatedStorage(); - if (error.isError()) - { - return error; - } - } + // Force the image to recover from storage before its data is overwritten. + // This will reset mAssociatedImages[level] to nullptr too. + ANGLE_TRY(mAssociatedImages[key]->recoverFromAssociatedStorage(context)); } } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::getResource(ID3D11Resource **outResource) +gl::Error TextureStorage11_2DArray::getResource(const gl::Context *context, + const TextureHelper11 **outResource) { // if the width, height or depth is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation - if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) + if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0 && mTextureDepth > 0) { ASSERT(mMipLevels > 0); - ID3D11Device *device = mRenderer->getDevice(); - D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = mTextureDepth; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + desc.Format = mFormatInfo.texFormat; + desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = getMiscFlags(); - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create 2D array texture storage, result: 0x%X.", result); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = getMiscFlags(); - d3d11::SetDebugName(mTexture, "TexStorage2DArray.Texture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture)); + mTexture.setDebugName("TexStorage2DArray.Texture"); } - *outResource = mTexture; - return gl::Error(GL_NO_ERROR); + *outResource = &mTexture; + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const +gl::Error TextureStorage11_2DArray::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = format; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; - srvDesc.Texture2DArray.MipLevels = mipLevels; + srvDesc.Texture2DArray.MipLevels = mipLevels; srvDesc.Texture2DArray.FirstArraySlice = 0; - srvDesc.Texture2DArray.ArraySize = mTextureDepth; + srvDesc.Texture2DArray.ArraySize = mTextureDepth; - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorage2DArray.SRV"); - 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); - } + return gl::NoError(); +} + +gl::Error TextureStorage11_2DArray::createRenderTargetSRV(const TextureHelper11 &texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + d3d11::SharedSRV *srv) const +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = resourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + index.mipIndex; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = index.layerIndex; + srvDesc.Texture2DArray.ArraySize = index.numLayers; - d3d11::SetDebugName(*outSRV, "TexStorage2DArray.SRV"); + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), srv)); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) +gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) { ASSERT(index.hasLayer()); - int mipLevel = index.mipIndex; - int layer = index.layerIndex; + const int mipLevel = index.mipIndex; + const int layer = index.layerIndex; + const int numLayers = index.numLayers; ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); - LevelLayerKey key(mipLevel, layer); + LevelLayerRangeKey key(mipLevel, layer, numLayers); if (mRenderTargets.find(key) == mRenderTargets.end()) { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - ID3D11Resource *texture = NULL; - gl::Error error = getResource(&texture); - if (error.isError()) + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); + d3d11::SharedSRV srv; + ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.srvFormat, &srv)); + d3d11::SharedSRV blitSRV; + if (mFormatInfo.blitSRVFormat != mFormatInfo.srvFormat) { - return error; + ANGLE_TRY(createRenderTargetSRV(*texture, index, mFormatInfo.blitSRVFormat, &blitSRV)); } - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; - srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = layer; - srvDesc.Texture2DArray.ArraySize = 1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(texture, &srvDesc, &srv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) + else { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal shader resource view for texture storage, result: 0x%X.", result); + blitSRV = srv.makeCopy(); } - d3d11::SetDebugName(srv, "TexStorage2DArray.RenderTargetSRV"); + srv.setDebugName("TexStorage2DArray.RenderTargetSRV"); - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; rtvDesc.Texture2DArray.FirstArraySlice = layer; - rtvDesc.Texture2DArray.ArraySize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv); - - ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result)); - if (FAILED(result)) - { - SafeRelease(srv); - return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result); - } + rtvDesc.Texture2DArray.ArraySize = numLayers; - d3d11::SetDebugName(rtv, "TexStorage2DArray.RenderTargetRTV"); + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + rtv.setDebugName("TexStorage2DArray.RenderTargetRTV"); - mRenderTargets[key] = new TextureRenderTarget11(rtv, texture, srv, mInternalFormat, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0); - - // RenderTarget will take ownership of these resources - SafeRelease(rtv); - SafeRelease(srv); + mRenderTargets[key].reset(new TextureRenderTarget11( + std::move(rtv), *texture, srv, blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0)); } else { - UNREACHABLE(); + ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mFormatInfo.dsvFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + dsvDesc.Texture2DArray.FirstArraySlice = layer; + dsvDesc.Texture2DArray.ArraySize = numLayers; + dsvDesc.Flags = 0; + + d3d11::DepthStencilView dsv; + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv)); + dsv.setDebugName("TexStorage2DArray.RenderTargetDSV"); + + mRenderTargets[key].reset(new TextureRenderTarget11( + std::move(dsv), *texture, srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1, 0)); } } ASSERT(outRT); - *outRT = mRenderTargets[key]; - return gl::Error(GL_NO_ERROR); + *outRT = mRenderTargets[key].get(); + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::getSwizzleTexture(ID3D11Resource **outTexture) +gl::Error TextureStorage11_2DArray::getSwizzleTexture(const TextureHelper11 **outTexture) { - if (!mSwizzleTexture) + if (!mSwizzleTexture.valid()) { - ID3D11Device *device = mRenderer->getDevice(); + const auto &format = mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()); D3D11_TEXTURE2D_DESC desc; - desc.Width = mTextureWidth; - desc.Height = mTextureHeight; - desc.MipLevels = mMipLevels; - desc.ArraySize = mTextureDepth; - desc.Format = mSwizzleTextureFormat; - desc.SampleDesc.Count = 1; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + desc.Format = format.texFormat; + 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); - } + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; - d3d11::SetDebugName(*outTexture, "TexStorage2DArray.SwizzleTexture"); + ANGLE_TRY(mRenderer->allocateTexture(desc, format, &mSwizzleTexture)); + mSwizzleTexture.setDebugName("TexStorage2DArray.SwizzleTexture"); } - *outTexture = mSwizzleTexture; - return gl::Error(GL_NO_ERROR); + *outTexture = &mSwizzleTexture; + return gl::NoError(); } -gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) +gl::Error TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) { ASSERT(mipLevel >= 0 && mipLevel < getLevelCount()); ASSERT(outRTV); - if (!mSwizzleRenderTargets[mipLevel]) + if (!mSwizzleRenderTargets[mipLevel].valid()) { - ID3D11Resource *swizzleTexture = NULL; - gl::Error error = getSwizzleTexture(&swizzleTexture); - if (error.isError()) - { - return error; - } - - ID3D11Device *device = mRenderer->getDevice(); + const TextureHelper11 *swizzleTexture = nullptr; + ANGLE_TRY(getSwizzleTexture(&swizzleTexture)); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mSwizzleRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Format = + mFormatInfo.getSwizzleFormat(mRenderer->getRenderer11DeviceCaps()).rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; rtvDesc.Texture2DArray.FirstArraySlice = 0; - rtvDesc.Texture2DArray.ArraySize = mTextureDepth; + rtvDesc.Texture2DArray.ArraySize = mTextureDepth; - HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, mSwizzleTexture.get(), + &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::NoError(); +} + +gl::ErrorOrResult TextureStorage11_2DArray::ensureDropStencilTexture( + const gl::Context *context) +{ + if (mDropStencilTexture.valid()) + { + return DropStencil::ALREADY_EXISTS; } - *outRTV = mSwizzleRenderTargets[mipLevel]; - return gl::Error(GL_NO_ERROR); + D3D11_TEXTURE2D_DESC dropDesc = {}; + dropDesc.ArraySize = mTextureDepth; + dropDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_DEPTH_STENCIL; + dropDesc.CPUAccessFlags = 0; + dropDesc.Format = DXGI_FORMAT_R32_TYPELESS; + dropDesc.Height = mTextureHeight; + dropDesc.MipLevels = mMipLevels; + dropDesc.MiscFlags = 0; + dropDesc.SampleDesc.Count = 1; + dropDesc.SampleDesc.Quality = 0; + dropDesc.Usage = D3D11_USAGE_DEFAULT; + dropDesc.Width = mTextureWidth; + + const auto &format = + d3d11::Format::Get(GL_DEPTH_COMPONENT32F, mRenderer->getRenderer11DeviceCaps()); + ANGLE_TRY(mRenderer->allocateTexture(dropDesc, format, &mDropStencilTexture)); + mDropStencilTexture.setDebugName("TexStorage2DArray.DropStencil"); + + std::vector layerCounts(mMipLevels, mTextureDepth); + + ANGLE_TRY(initDropStencilTexture( + context, gl::ImageIndexIterator::Make2DArray(0, mMipLevels, layerCounts.data()))); + + return DropStencil::CREATED; } +TextureStorage11_2DMultisample::TextureStorage11_2DMultisample(Renderer11 *renderer, + GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations) + : TextureStorage11( + renderer, + GetTextureBindFlags(internalformat, renderer->getRenderer11DeviceCaps(), true), + GetTextureMiscFlags(internalformat, renderer->getRenderer11DeviceCaps(), true, levels), + internalformat), + mTexture(), + mRenderTarget(nullptr) +{ + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mFormatInfo.texFormat, &width, &height, &mTopLevel); + + mMipLevels = 1; + mTextureWidth = width; + mTextureHeight = height; + mTextureDepth = 1; + mSamples = samples; + mFixedSampleLocations = fixedSampleLocations; +} + +gl::Error TextureStorage11_2DMultisample::onDestroy(const gl::Context *context) +{ + InvalidateRenderTarget(context, mRenderTarget.get()); + mRenderTarget.reset(); + return gl::NoError(); } + +TextureStorage11_2DMultisample::~TextureStorage11_2DMultisample() +{ +} + +gl::Error TextureStorage11_2DMultisample::copyToStorage(const gl::Context *context, + TextureStorage *destStorage) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "copyToStorage is unimplemented"; +} + +void TextureStorage11_2DMultisample::associateImage(Image11 *image, const gl::ImageIndex &index) +{ +} + +void TextureStorage11_2DMultisample::verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) +{ +} + +void TextureStorage11_2DMultisample::disassociateImage(const gl::ImageIndex &index, + Image11 *expectedImage) +{ +} + +gl::Error TextureStorage11_2DMultisample::releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) +{ + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::getResource(const gl::Context *context, + const TextureHelper11 **outResource) +{ + ANGLE_TRY(ensureTextureExists(1)); + + *outResource = &mTexture; + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::ensureTextureExists(int mipLevels) +{ + // For Multisampled textures, mipLevels always equals 1. + ASSERT(mipLevels == 1); + + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (!mTexture.valid() && mTextureWidth > 0 && mTextureHeight > 0) + { + D3D11_TEXTURE2D_DESC desc; + ZeroMemory(&desc, sizeof(desc)); + desc.Width = mTextureWidth; // Compressed texture size constraints? + desc.Height = mTextureHeight; + desc.MipLevels = mipLevels; + desc.ArraySize = 1; + desc.Format = mFormatInfo.texFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = getMiscFlags(); + + const gl::TextureCaps &textureCaps = + mRenderer->getNativeTextureCaps().get(mFormatInfo.internalFormat); + GLuint supportedSamples = textureCaps.getNearestSamples(mSamples); + desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; + desc.SampleDesc.Quality = static_cast(D3D11_STANDARD_MULTISAMPLE_PATTERN); + + ANGLE_TRY(mRenderer->allocateTexture(desc, mFormatInfo, &mTexture)); + mTexture.setDebugName("TexStorage2DMS.Texture"); + } + + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) +{ + ASSERT(!index.hasLayer()); + + const int level = index.mipIndex; + ASSERT(level == 0); + + ASSERT(outRT); + if (mRenderTarget) + { + *outRT = mRenderTarget.get(); + return gl::NoError(); + } + + const TextureHelper11 *texture = nullptr; + ANGLE_TRY(getResource(context, &texture)); + + const d3d11::SharedSRV *srv = nullptr; + ANGLE_TRY(getSRVLevel(context, level, false, &srv)); + + const d3d11::SharedSRV *blitSRV = nullptr; + ANGLE_TRY(getSRVLevel(context, level, true, &blitSRV)); + + if (mFormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mFormatInfo.rtvFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + + d3d11::RenderTargetView rtv; + ANGLE_TRY(mRenderer->allocateResource(rtvDesc, texture->get(), &rtv)); + + mRenderTarget.reset(new TextureRenderTarget11( + std::move(rtv), *texture, *srv, *blitSRV, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, mSamples)); + + *outRT = mRenderTarget.get(); + return gl::NoError(); + } + + ASSERT(mFormatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mFormatInfo.dsvFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Flags = 0; + + d3d11::DepthStencilView dsv; + ANGLE_TRY(mRenderer->allocateResource(dsvDesc, texture->get(), &dsv)); + + mRenderTarget.reset(new TextureRenderTarget11( + std::move(dsv), *texture, *srv, mFormatInfo.internalFormat, getFormatSet(), + getLevelWidth(level), getLevelHeight(level), 1, mSamples)); + + *outRT = mRenderTarget.get(); + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) +{ + ASSERT(outSRV); + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; + + ANGLE_TRY(mRenderer->allocateResource(srvDesc, texture.get(), outSRV)); + outSRV->setDebugName("TexStorage2DMS.SRV"); + return gl::NoError(); +} + +gl::Error TextureStorage11_2DMultisample::getSwizzleTexture(const TextureHelper11 **outTexture) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "getSwizzleTexture is unimplemented."; +} + +gl::Error TextureStorage11_2DMultisample::getSwizzleRenderTarget( + int mipLevel, + const d3d11::RenderTargetView **outRTV) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "getSwizzleRenderTarget is unimplemented."; +} + +gl::ErrorOrResult +TextureStorage11_2DMultisample::ensureDropStencilTexture(const gl::Context *context) +{ + UNIMPLEMENTED(); + return gl::InternalError() << "Drop stencil texture not implemented."; +} + +} // namespace rx 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 a88db2f0af..336aa495a8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h @@ -10,10 +10,13 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ -#include "libANGLE/Texture.h" #include "libANGLE/Error.h" +#include "libANGLE/Texture.h" #include "libANGLE/renderer/d3d/TextureStorage.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include #include namespace gl @@ -31,69 +34,111 @@ class SwapChain11; class Image11; struct Renderer11DeviceCaps; +template +using TexLevelArray = std::array; + +template +using CubeFaceArray = std::array; + class TextureStorage11 : public TextureStorage { public: - virtual ~TextureStorage11(); + ~TextureStorage11() override; 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::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); - - virtual int getTopLevel() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; + const d3d11::Format &getFormatSet() const; + gl::Error getSRVLevels(const gl::Context *context, + GLint baseLevel, + GLint maxLevel, + const d3d11::SharedSRV **outSRV); + gl::Error generateSwizzles(const gl::Context *context, const gl::SwizzleState &swizzleTarget); + void markLevelDirty(int mipLevel); + void markDirty(); + + gl::Error updateSubresourceLevel(const gl::Context *context, + const TextureHelper11 &texture, + unsigned int sourceSubresource, + const gl::ImageIndex &index, + const gl::Box ©Area); + + gl::Error copySubresourceLevel(const gl::Context *context, + const TextureHelper11 &dstTexture, + unsigned int dstSubresource, + const gl::ImageIndex &index, + const gl::Box ®ion); + + // TextureStorage virtual functions + int getTopLevel() const override; + bool isRenderTarget() const override; + bool isManaged() const override; bool supportsNativeMipmapFunction() const override; - virtual int getLevelCount() const; + int getLevelCount() const override; + gl::Error generateMipmap(const gl::Context *context, + const gl::ImageIndex &sourceIndex, + const gl::ImageIndex &destIndex) override; + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; + gl::Error setData(const gl::Context *context, + const gl::ImageIndex &index, + ImageD3D *image, + const gl::Box *destBox, + GLenum type, + const gl::PixelUnpackState &unpack, + const uint8_t *pixelData) override; + + virtual gl::Error getSRV(const gl::Context *context, + const gl::TextureState &textureState, + const d3d11::SharedSRV **outSRV); virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; - - gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); - void invalidateSwizzleCacheLevel(int mipLevel); - void invalidateSwizzleCache(); - - gl::Error updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, - const gl::ImageIndex &index, const gl::Box ©Area); - - gl::Error copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, - const gl::ImageIndex &index, const gl::Box ®ion); - + virtual gl::Error getResource(const gl::Context *context, + const TextureHelper11 **outResource) = 0; virtual void associateImage(Image11* image, const gl::ImageIndex &index) = 0; virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage) = 0; - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage) = 0; - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0; - - virtual gl::Error copyToStorage(TextureStorage *destStorage); - 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); + virtual void verifyAssociatedImageValid(const gl::ImageIndex &index, + Image11 *expectedImage) = 0; + virtual gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) = 0; protected: - TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags); + TextureStorage11(Renderer11 *renderer, UINT bindFlags, UINT miscFlags, GLenum internalFormat); int getLevelWidth(int mipLevel) const; int getLevelHeight(int mipLevel) const; int getLevelDepth(int mipLevel) const; // Some classes (e.g. TextureStorage11_2D) will override getMippedResource. - virtual gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); } - - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0; - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0; - gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV); + virtual gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource); + + virtual gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) = 0; + virtual gl::Error getSwizzleRenderTarget(int mipLevel, + const d3d11::RenderTargetView **outRTV) = 0; + gl::Error getSRVLevel(const gl::Context *context, + int mipLevel, + bool blitSRV, + const d3d11::SharedSRV **outSRV); + + // Get a version of a depth texture with only depth information, not stencil. + enum DropStencil + { + CREATED, + ALREADY_EXISTS + }; + virtual gl::ErrorOrResult ensureDropStencilTexture(const gl::Context *context); + gl::Error initDropStencilTexture(const gl::Context *context, const gl::ImageIndexIterator &it); - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const = 0; + // The baseLevel parameter should *not* have mTopLevel applied. + virtual gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) = 0; - void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + void verifySwizzleExists(const gl::SwizzleState &swizzleState); // Clear all cached non-swizzle SRVs and invalidate the swizzle cache. void clearSRVCache(); @@ -102,32 +147,13 @@ class TextureStorage11 : public TextureStorage int mTopLevel; unsigned int mMipLevels; - GLenum mInternalFormat; - DXGI_FORMAT mTextureFormat; - DXGI_FORMAT mShaderResourceFormat; - DXGI_FORMAT mRenderTargetFormat; - DXGI_FORMAT mDepthStencilFormat; - DXGI_FORMAT mSwizzleTextureFormat; - DXGI_FORMAT mSwizzleShaderResourceFormat; - DXGI_FORMAT mSwizzleRenderTargetFormat; + const d3d11::Format &mFormatInfo; unsigned int mTextureWidth; unsigned int mTextureHeight; unsigned int mTextureDepth; - struct SwizzleCacheValue - { - GLenum swizzleRed; - GLenum swizzleGreen; - GLenum swizzleBlue; - GLenum swizzleAlpha; - - SwizzleCacheValue(); - SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha); - - bool operator ==(const SwizzleCacheValue &other) const; - bool operator !=(const SwizzleCacheValue &other) const; - }; - SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelArray mSwizzleCache; + TextureHelper11 mDropStencilTexture; private: const UINT mBindFlags; @@ -135,18 +161,24 @@ class TextureStorage11 : public TextureStorage struct SRVKey { - SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false); + SRVKey(int baseLevel, int mipLevels, bool swizzle, bool dropStencil); bool operator<(const SRVKey &rhs) const; - int baseLevel; - int mipLevels; - bool swizzle; + int baseLevel = 0; // Without mTopLevel applied. + int mipLevels = 0; + bool swizzle = false; + bool dropStencil = false; }; - typedef std::map SRVCache; + typedef std::map SRVCache; + + gl::Error getCachedOrCreateSRV(const gl::Context *context, + const SRVKey &key, + const d3d11::SharedSRV **outSRV); SRVCache mSrvCache; - ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelArray mLevelSRVs; + TexLevelArray mLevelBlitSRVs; }; class TextureStorage11_2D : public TextureStorage11 @@ -154,33 +186,48 @@ class TextureStorage11_2D : public TextureStorage11 public: TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain); TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false); - virtual ~TextureStorage11_2D(); + ~TextureStorage11_2D() override; - virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getMippedResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::Error onDestroy(const gl::Context *context) override; - virtual gl::Error copyToStorage(TextureStorage *destStorage); + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - virtual void associateImage(Image11* image, const gl::ImageIndex &index); - virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; - virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; + + gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) override; protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + gl::ErrorOrResult ensureDropStencilTexture(const gl::Context *context) override; gl::Error ensureTextureExists(int mipLevels); private: - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; - ID3D11Texture2D *mTexture; - RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mTexture; + TexLevelArray> mRenderTarget; + bool mHasKeyedMutex; // These are members related to the zero max-LOD workaround. // D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero). @@ -191,108 +238,179 @@ class TextureStorage11_2D : public TextureStorage11 // One example of this is an application that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture. // A more likely example is an app that creates an empty texture, renders to it, and then calls glGenerateMipmap // TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been created to save memory. - ID3D11Texture2D *mLevelZeroTexture; - RenderTarget11 *mLevelZeroRenderTarget; + TextureHelper11 mLevelZeroTexture; + std::unique_ptr mLevelZeroRenderTarget; bool mUseLevelZeroTexture; // Swizzle-related variables - ID3D11Texture2D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mSwizzleTexture; + TexLevelArray mSwizzleRenderTargets; + + TexLevelArray mAssociatedImages; +}; + +class TextureStorage11_External : public TextureStorage11 +{ + public: + TextureStorage11_External(Renderer11 *renderer, + egl::Stream *stream, + const egl::Stream::GLTextureDescription &glDesc); + ~TextureStorage11_External() override; + + gl::Error onDestroy(const gl::Context *context) override; + + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; + + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; + + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; + + protected: + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + private: + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; + + TextureHelper11 mTexture; + int mSubresourceIndex; + bool mHasKeyedMutex; - Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + Image11 *mAssociatedImage; }; class TextureStorage11_EGLImage final : public TextureStorage11 { public: - TextureStorage11_EGLImage(Renderer11 *renderer, EGLImageD3D *eglImage); + TextureStorage11_EGLImage(Renderer11 *renderer, + EGLImageD3D *eglImage, + RenderTarget11 *renderTarget11); ~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 getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getSRV(const gl::Context *context, + const gl::TextureState &textureState, + const d3d11::SharedSRV **outSRV) override; + gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - gl::Error copyToStorage(TextureStorage *destStorage) override; + gl::Error copyToStorage(const gl::Context *context, 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; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; - gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) override; + gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) override; protected: - gl::Error getSwizzleTexture(ID3D11Resource **outTexture) override; - gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) override; + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **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 checkForUpdatedRenderTarget(const gl::Context *context); - gl::Error createSRV(int baseLevel, + gl::Error createSRV(const gl::Context *context, + int baseLevel, int mipLevels, DXGI_FORMAT format, - ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const override; + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; - gl::Error getImageRenderTarget(RenderTarget11 **outRT) const; + gl::Error getImageRenderTarget(const gl::Context *context, RenderTarget11 **outRT) const; EGLImageD3D *mImage; uintptr_t mCurrentRenderTarget; // Swizzle-related variables - ID3D11Texture2D *mSwizzleTexture; - std::vector mSwizzleRenderTargets; + TextureHelper11 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(); + ~TextureStorage11_Cube() override; - virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const; + gl::Error onDestroy(const gl::Context *context) override; + + UINT getSubresourceIndex(const gl::ImageIndex &index) const override; - virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getMippedResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getMippedResource(const gl::Context *context, + const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - virtual gl::Error copyToStorage(TextureStorage *destStorage); + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; - virtual void associateImage(Image11* image, const gl::ImageIndex &index); - virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; - virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture); + gl::Error useLevelZeroWorkaroundTexture(const gl::Context *context, + bool useLevelZeroTexture) override; protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + gl::ErrorOrResult ensureDropStencilTexture(const gl::Context *context) override; gl::Error ensureTextureExists(int mipLevels); private: - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; - - static const size_t CUBE_FACE_COUNT = 6; + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; + gl::Error createRenderTargetSRV(const TextureHelper11 &texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + d3d11::SharedSRV *srv) const; - ID3D11Texture2D *mTexture; - RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mTexture; + CubeFaceArray>> mRenderTarget; // Level-zero workaround members. See TextureStorage11_2D's workaround members for a description. - ID3D11Texture2D *mLevelZeroTexture; - RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT]; + TextureHelper11 mLevelZeroTexture; + CubeFaceArray> mLevelZeroRenderTarget; bool mUseLevelZeroTexture; - ID3D11Texture2D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mSwizzleTexture; + TexLevelArray mSwizzleRenderTargets; - Image11 *mAssociatedImages[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + CubeFaceArray> mAssociatedImages; }; class TextureStorage11_3D : public TextureStorage11 @@ -300,37 +418,46 @@ class TextureStorage11_3D : public TextureStorage11 public: TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual ~TextureStorage11_3D(); + ~TextureStorage11_3D() override; + + gl::Error onDestroy(const gl::Context *context) override; - virtual gl::Error getResource(ID3D11Resource **outResource); + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; // Handles both layer and non-layer RTs - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - virtual void associateImage(Image11* image, const gl::ImageIndex &index); - virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; private: - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; typedef std::pair LevelLayerKey; - typedef std::map RenderTargetMap; - RenderTargetMap mLevelLayerRenderTargets; + std::map> mLevelLayerRenderTargets; - RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelArray> mLevelRenderTargets; - ID3D11Texture3D *mTexture; - ID3D11Texture3D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mTexture; + TextureHelper11 mSwizzleTexture; + TexLevelArray mSwizzleRenderTargets; - Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TexLevelArray mAssociatedImages; }; class TextureStorage11_2DArray : public TextureStorage11 @@ -338,37 +465,125 @@ class TextureStorage11_2DArray : public TextureStorage11 public: TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual ~TextureStorage11_2DArray(); + ~TextureStorage11_2DArray() override; + + gl::Error onDestroy(const gl::Context *context) override; - virtual gl::Error getResource(ID3D11Resource **outResource); - virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT); + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; - virtual void associateImage(Image11* image, const gl::ImageIndex &index); - virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage); - virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage); - virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage); + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; protected: - virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture); - virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV); + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + gl::ErrorOrResult ensureDropStencilTexture(const gl::Context *context) override; private: - virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture, - ID3D11ShaderResourceView **outSRV) const; + struct LevelLayerRangeKey + { + LevelLayerRangeKey(int mipLevelIn, int layerIn, int numLayersIn) + : mipLevel(mipLevelIn), layer(layerIn), numLayers(numLayersIn) + { + } + bool operator<(const LevelLayerRangeKey &other) const + { + if (mipLevel != other.mipLevel) + { + return mipLevel < other.mipLevel; + } + if (layer != other.layer) + { + return layer < other.layer; + } + return numLayers < other.numLayers; + } + int mipLevel; + int layer; + int numLayers; + }; - typedef std::pair LevelLayerKey; - typedef std::map RenderTargetMap; - RenderTargetMap mRenderTargets; + private: + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; + gl::Error createRenderTargetSRV(const TextureHelper11 &texture, + const gl::ImageIndex &index, + DXGI_FORMAT resourceFormat, + d3d11::SharedSRV *srv) const; + + std::map> mRenderTargets; - ID3D11Texture2D *mTexture; + TextureHelper11 mTexture; - ID3D11Texture2D *mSwizzleTexture; - ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + TextureHelper11 mSwizzleTexture; + TexLevelArray mSwizzleRenderTargets; - typedef std::map ImageMap; + typedef std::map ImageMap; ImageMap mAssociatedImages; }; +class TextureStorage11_2DMultisample : public TextureStorage11 +{ + public: + TextureStorage11_2DMultisample(Renderer11 *renderer, + GLenum internalformat, + GLsizei width, + GLsizei height, + int levels, + int samples, + bool fixedSampleLocations); + ~TextureStorage11_2DMultisample() override; + + gl::Error onDestroy(const gl::Context *context) override; + + gl::Error getResource(const gl::Context *context, const TextureHelper11 **outResource) override; + gl::Error getRenderTarget(const gl::Context *context, + const gl::ImageIndex &index, + RenderTargetD3D **outRT) override; + + gl::Error copyToStorage(const gl::Context *context, TextureStorage *destStorage) override; + + void associateImage(Image11 *image, const gl::ImageIndex &index) override; + void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override; + void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override; + gl::Error releaseAssociatedImage(const gl::Context *context, + const gl::ImageIndex &index, + Image11 *incomingImage) override; + + protected: + gl::Error getSwizzleTexture(const TextureHelper11 **outTexture) override; + gl::Error getSwizzleRenderTarget(int mipLevel, const d3d11::RenderTargetView **outRTV) override; + + gl::ErrorOrResult ensureDropStencilTexture(const gl::Context *context) override; + + gl::Error ensureTextureExists(int mipLevels); + + private: + gl::Error createSRV(const gl::Context *context, + int baseLevel, + int mipLevels, + DXGI_FORMAT format, + const TextureHelper11 &texture, + d3d11::SharedSRV *outSRV) override; + + TextureHelper11 mTexture; + std::unique_ptr mRenderTarget; + + unsigned int mSamples; + GLboolean mFixedSampleLocations; +}; } #endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp new file mode 100644 index 0000000000..4b08edf71f --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.cpp @@ -0,0 +1,124 @@ +// +// 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. +// + +// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers. + +#include "libANGLE/renderer/d3d/d3d11/TransformFeedback11.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +TransformFeedback11::TransformFeedback11(const gl::TransformFeedbackState &state, + Renderer11 *renderer) + : TransformFeedbackImpl(state), + mRenderer(renderer), + mIsDirty(true), + mBuffers(state.getIndexedBuffers().size(), nullptr), + mBufferOffsets(state.getIndexedBuffers().size(), 0), + mSerial(mRenderer->generateSerial()) +{ +} + +TransformFeedback11::~TransformFeedback11() +{ +} + +void TransformFeedback11::begin(GLenum primitiveMode) +{ + // Reset all the cached offsets to the binding offsets + mIsDirty = true; + for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++) + { + const auto &binding = mState.getIndexedBuffer(bindingIdx); + if (binding.get() != nullptr) + { + mBufferOffsets[bindingIdx] = static_cast(binding.getOffset()); + } + else + { + mBufferOffsets[bindingIdx] = 0; + } + } +} + +void TransformFeedback11::end() +{ + if (mRenderer->getWorkarounds().flushAfterEndingTransformFeedback) + { + mRenderer->getDeviceContext()->Flush(); + } +} + +void TransformFeedback11::pause() +{ +} + +void TransformFeedback11::resume() +{ +} + +void TransformFeedback11::bindGenericBuffer(const gl::BindingPointer &binding) +{ +} + +void TransformFeedback11::bindIndexedBuffer(size_t index, + const gl::OffsetBindingPointer &binding) +{ + mIsDirty = true; + mBufferOffsets[index] = static_cast(binding.getOffset()); +} + +void TransformFeedback11::onApply() +{ + mIsDirty = false; + + // Change all buffer offsets to -1 so that if any of them need to be re-applied, the are set to + // append + std::fill(mBufferOffsets.begin(), mBufferOffsets.end(), -1); +} + +bool TransformFeedback11::isDirty() const +{ + return mIsDirty; +} + +UINT TransformFeedback11::getNumSOBuffers() const +{ + return static_cast(mBuffers.size()); +} + +gl::ErrorOrResult *> TransformFeedback11::getSOBuffers( + const gl::Context *context) +{ + for (size_t bindingIdx = 0; bindingIdx < mBuffers.size(); bindingIdx++) + { + const auto &binding = mState.getIndexedBuffer(bindingIdx); + if (binding.get() != nullptr) + { + Buffer11 *storage = GetImplAs(binding.get()); + ANGLE_TRY_RESULT(storage->getBuffer(context, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK), + mBuffers[bindingIdx]); + } + } + + return &mBuffers; +} + +const std::vector &TransformFeedback11::getSOBufferOffsets() const +{ + return mBufferOffsets; +} + +Serial TransformFeedback11::getSerial() const +{ + return mSerial; +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h new file mode 100644 index 0000000000..cc9fcc335a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TransformFeedback11.h @@ -0,0 +1,60 @@ +// +// 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. +// + +// TransformFeedback11.h: Implements the abstract rx::TransformFeedbackImpl class. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_ + +#include "common/platform.h" + +#include "libANGLE/Error.h" +#include "libANGLE/angletypes.h" +#include "libANGLE/renderer/TransformFeedbackImpl.h" +#include "libANGLE/renderer/renderer_utils.h" + +namespace rx +{ + +class Renderer11; + +class TransformFeedback11 : public TransformFeedbackImpl +{ + public: + TransformFeedback11(const gl::TransformFeedbackState &state, Renderer11 *renderer); + ~TransformFeedback11() override; + + void begin(GLenum primitiveMode) override; + void end() override; + void pause() override; + void resume() override; + + void bindGenericBuffer(const gl::BindingPointer &binding) override; + void bindIndexedBuffer(size_t index, + const gl::OffsetBindingPointer &binding) override; + + void onApply(); + + bool isDirty() const; + + UINT getNumSOBuffers() const; + gl::ErrorOrResult *> getSOBuffers(const gl::Context *context); + const std::vector &getSOBufferOffsets() const; + + Serial getSerial() const; + + private: + Renderer11 *mRenderer; + + bool mIsDirty; + std::vector mBuffers; + std::vector mBufferOffsets; + + Serial mSerial; +}; +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TRANSFORMFEEDBACK11_H_ diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp index 213ce31817..29185a9d93 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp @@ -11,9 +11,15 @@ #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" #if defined (ANGLE_ENABLE_WINDOWS_STORE) -using namespace ABI::Windows::Foundation; +#include +#include +#include +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::ApplicationModel; using namespace ABI::Windows::ApplicationModel::Core; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::Foundation::Collections; #endif namespace rx @@ -41,7 +47,6 @@ void Trim11::trim() #if defined (ANGLE_ENABLE_WINDOWS_STORE) ID3D11Device* device = mRenderer->getDevice(); - // IDXGIDevice3 is only supported on Windows 8.1 and Windows Phone 8.1 and above. IDXGIDevice3 *dxgiDevice3 = d3d11::DynamicCastComObject(device); if (dxgiDevice3) { 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 4741e81601..69fa05a57b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h @@ -13,9 +13,7 @@ #include "libANGLE/angletypes.h" #include "libANGLE/Error.h" -#if !defined(ANGLE_ENABLE_WINDOWS_STORE) -typedef void* EventRegistrationToken; -#else +#if defined(ANGLE_ENABLE_WINDOWS_STORE) #include #endif diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp new file mode 100644 index 0000000000..97c29415ed --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp @@ -0,0 +1,413 @@ +// +// Copyright 2016 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. +// +// VertexArray11: +// Implementation of rx::VertexArray11. +// + +#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h" + +#include "common/bitset_utils.h" +#include "libANGLE/Context.h" +#include "libANGLE/renderer/d3d/d3d11/Buffer11.h" +#include "libANGLE/renderer/d3d/d3d11/Context11.h" + +using namespace angle; + +namespace rx +{ + +namespace +{ +OnBufferDataDirtyChannel *GetBufferBroadcastChannel(Buffer11 *buffer11, + IndexStorageType storageType) +{ + switch (storageType) + { + case IndexStorageType::Direct: + return buffer11->getDirectBroadcastChannel(); + case IndexStorageType::Static: + return buffer11->getStaticBroadcastChannel(); + case IndexStorageType::Dynamic: + return buffer11 ? buffer11->getStaticBroadcastChannel() : nullptr; + default: + UNREACHABLE(); + return nullptr; + } +} +} // anonymous namespace + +VertexArray11::VertexArray11(const gl::VertexArrayState &data) + : VertexArrayImpl(data), + mAttributeStorageTypes(data.getMaxAttribs(), VertexStorageType::CURRENT_VALUE), + mTranslatedAttribs(data.getMaxAttribs()), + mCurrentArrayBuffers(data.getMaxAttribs()), + mCurrentElementArrayBuffer(), + mOnArrayBufferDataDirty(), + mOnElementArrayBufferDataDirty(this, mCurrentArrayBuffers.size()), + mAppliedNumViewsToDivisor(1), + mLastElementType(GL_NONE), + mLastDrawElementsOffset(0), + mCurrentElementArrayStorage(IndexStorageType::Invalid), + mCachedIndexInfoValid(false) +{ + for (size_t attribIndex = 0; attribIndex < mCurrentArrayBuffers.size(); ++attribIndex) + { + mOnArrayBufferDataDirty.emplace_back(this, attribIndex); + } +} + +VertexArray11::~VertexArray11() +{ +} + +void VertexArray11::destroy(const gl::Context *context) +{ + for (auto &buffer : mCurrentArrayBuffers) + { + if (buffer.get()) + { + buffer.set(context, nullptr); + } + } + + mCurrentElementArrayBuffer.set(context, nullptr); +} + +void VertexArray11::syncState(const gl::Context *context, + const gl::VertexArray::DirtyBits &dirtyBits) +{ + ASSERT(dirtyBits.any()); + + // Generate a state serial. This serial is used in the program class to validate the cached + // input layout, and skip recomputation in the fast path. + Renderer11 *renderer = GetImplAs(context)->getRenderer(); + mCurrentStateSerial = renderer->generateSerial(); + + // TODO(jmadill): Individual attribute invalidation. + renderer->getStateManager()->invalidateVertexBuffer(); + + for (auto dirtyBit : dirtyBits) + { + if (dirtyBit == gl::VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER) + { + mCachedIndexInfoValid = false; + mLastElementType = GL_NONE; + } + else + { + size_t index = gl::VertexArray::GetVertexIndexFromDirtyBit(dirtyBit); + // TODO(jiawei.shao@intel.com): Vertex Attrib Bindings + ASSERT(index == mState.getBindingIndexFromAttribIndex(index)); + mAttribsToUpdate.set(index); + } + } +} + +bool VertexArray11::flushAttribUpdates(const gl::Context *context) +{ + if (mAttribsToUpdate.any()) + { + const auto &activeLocations = + context->getGLState().getProgram()->getActiveAttribLocationsMask(); + + // Skip attrib locations the program doesn't use. + gl::AttributesMask activeToUpdate = mAttribsToUpdate & activeLocations; + + for (auto toUpdateIndex : activeToUpdate) + { + mAttribsToUpdate.reset(toUpdateIndex); + updateVertexAttribStorage(context, toUpdateIndex); + } + + return true; + } + + return false; +} + +bool VertexArray11::updateElementArrayStorage(const gl::Context *context, + GLenum elementType, + GLenum destElementType, + const void *indices) +{ + unsigned int offset = static_cast(reinterpret_cast(indices)); + + if (mCachedIndexInfoValid && mLastElementType == elementType && + offset == mLastDrawElementsOffset) + { + // Dynamic index buffers must be re-streamed every draw. + return (mCurrentElementArrayStorage == IndexStorageType::Dynamic); + } + + gl::Buffer *newBuffer = mState.getElementArrayBuffer().get(); + gl::Buffer *oldBuffer = mCurrentElementArrayBuffer.get(); + bool needsTranslation = false; + IndexStorageType newStorageType = ClassifyIndexStorage( + context->getGLState(), newBuffer, elementType, destElementType, offset, &needsTranslation); + + if (newBuffer != oldBuffer) + { + mCurrentElementArrayBuffer.set(context, newBuffer); + } + + if (newStorageType != mCurrentElementArrayStorage || newBuffer != oldBuffer) + { + Buffer11 *newBuffer11 = SafeGetImplAs(newBuffer); + + auto *newChannel = GetBufferBroadcastChannel(newBuffer11, newStorageType); + + mCurrentElementArrayStorage = newStorageType; + mOnElementArrayBufferDataDirty.bind(newChannel); + needsTranslation = true; + } + + if (mLastDrawElementsOffset != offset) + { + needsTranslation = true; + mLastDrawElementsOffset = offset; + } + + if (mLastElementType != elementType) + { + needsTranslation = true; + mLastElementType = elementType; + } + + // TODO(jmadill): We should probably promote static usage immediately, because this can change + // the storage type for dynamic buffers. + return needsTranslation || !mCachedIndexInfoValid; +} + +void VertexArray11::updateVertexAttribStorage(const gl::Context *context, size_t attribIndex) +{ + const auto &attrib = mState.getVertexAttribute(attribIndex); + const auto &binding = mState.getBindingFromAttribIndex(attribIndex); + + // Note: having an unchanged storage type doesn't mean the attribute is clean. + auto oldStorageType = mAttributeStorageTypes[attribIndex]; + auto newStorageType = ClassifyAttributeStorage(attrib, binding); + + mAttributeStorageTypes[attribIndex] = newStorageType; + + StateManager11 *stateManager = GetImplAs(context)->getRenderer()->getStateManager(); + + if (newStorageType == VertexStorageType::DYNAMIC) + { + if (oldStorageType != VertexStorageType::DYNAMIC) + { + // Sync dynamic attribs in a different set. + mAttribsToTranslate.reset(attribIndex); + mDynamicAttribsMask.set(attribIndex); + } + } + else + { + mAttribsToTranslate.set(attribIndex); + stateManager->invalidateVertexAttributeTranslation(); + + if (oldStorageType == VertexStorageType::DYNAMIC) + { + ASSERT(mDynamicAttribsMask[attribIndex]); + mDynamicAttribsMask.reset(attribIndex); + } + } + + gl::Buffer *oldBufferGL = mCurrentArrayBuffers[attribIndex].get(); + gl::Buffer *newBufferGL = binding.getBuffer().get(); + Buffer11 *oldBuffer11 = oldBufferGL ? GetImplAs(oldBufferGL) : nullptr; + Buffer11 *newBuffer11 = newBufferGL ? GetImplAs(newBufferGL) : nullptr; + + if (oldBuffer11 != newBuffer11 || oldStorageType != newStorageType) + { + OnBufferDataDirtyChannel *newChannel = nullptr; + + if (newStorageType == VertexStorageType::CURRENT_VALUE) + { + stateManager->invalidateCurrentValueAttrib(attribIndex); + } + else if (newBuffer11 != nullptr) + { + // Note that for static callbacks, promotion to a static buffer from a dynamic buffer + // means we need to tag dynamic buffers with static callbacks. + switch (newStorageType) + { + case VertexStorageType::DIRECT: + newChannel = newBuffer11->getDirectBroadcastChannel(); + break; + case VertexStorageType::STATIC: + case VertexStorageType::DYNAMIC: + newChannel = newBuffer11->getStaticBroadcastChannel(); + break; + default: + UNREACHABLE(); + break; + } + } + + mOnArrayBufferDataDirty[attribIndex].bind(newChannel); + mCurrentArrayBuffers[attribIndex].set(context, binding.getBuffer().get()); + } +} + +bool VertexArray11::hasActiveDynamicAttrib(const gl::Context *context) +{ + flushAttribUpdates(context); + const auto &activeLocations = + context->getGLState().getProgram()->getActiveAttribLocationsMask(); + auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); + return activeDynamicAttribs.any(); +} + +gl::Error VertexArray11::updateDirtyAndDynamicAttribs(const gl::Context *context, + VertexDataManager *vertexDataManager, + const DrawCallVertexParams &vertexParams) +{ + flushAttribUpdates(context); + + const auto &glState = context->getGLState(); + const gl::Program *program = glState.getProgram(); + const auto &activeLocations = program->getActiveAttribLocationsMask(); + const auto &attribs = mState.getVertexAttributes(); + const auto &bindings = mState.getVertexBindings(); + mAppliedNumViewsToDivisor = + (program != nullptr && program->usesMultiview()) ? program->getNumViews() : 1; + + if (mAttribsToTranslate.any()) + { + // Skip attrib locations the program doesn't use, saving for the next frame. + gl::AttributesMask dirtyActiveAttribs = (mAttribsToTranslate & activeLocations); + + for (auto dirtyAttribIndex : dirtyActiveAttribs) + { + mAttribsToTranslate.reset(dirtyAttribIndex); + + auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex]; + const auto ¤tValue = glState.getVertexAttribCurrentValue(dirtyAttribIndex); + + // Record basic attrib info + translatedAttrib->attribute = &attribs[dirtyAttribIndex]; + translatedAttrib->binding = &bindings[translatedAttrib->attribute->bindingIndex]; + translatedAttrib->currentValueType = currentValue.Type; + translatedAttrib->divisor = + translatedAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor; + + switch (mAttributeStorageTypes[dirtyAttribIndex]) + { + case VertexStorageType::DIRECT: + VertexDataManager::StoreDirectAttrib(translatedAttrib); + break; + case VertexStorageType::STATIC: + { + ANGLE_TRY(VertexDataManager::StoreStaticAttrib(context, translatedAttrib)); + break; + } + case VertexStorageType::CURRENT_VALUE: + // Current value attribs are managed by the StateManager11. + break; + default: + UNREACHABLE(); + break; + } + } + } + + if (mDynamicAttribsMask.any()) + { + auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); + if (activeDynamicAttribs.none()) + { + return gl::NoError(); + } + + for (auto dynamicAttribIndex : activeDynamicAttribs) + { + auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex]; + const auto ¤tValue = glState.getVertexAttribCurrentValue(dynamicAttribIndex); + + // Record basic attrib info + dynamicAttrib->attribute = &attribs[dynamicAttribIndex]; + dynamicAttrib->binding = &bindings[dynamicAttrib->attribute->bindingIndex]; + dynamicAttrib->currentValueType = currentValue.Type; + dynamicAttrib->divisor = + dynamicAttrib->binding->getDivisor() * mAppliedNumViewsToDivisor; + } + + ANGLE_TRY(vertexDataManager->storeDynamicAttribs( + context, &mTranslatedAttribs, activeDynamicAttribs, vertexParams.firstVertex(), + vertexParams.vertexCount(), vertexParams.instances())); + } + + return gl::NoError(); +} + +const std::vector &VertexArray11::getTranslatedAttribs() const +{ + return mTranslatedAttribs; +} + +void VertexArray11::signal(size_t channelID, const gl::Context *context) +{ + if (channelID == mAttributeStorageTypes.size()) + { + mCachedIndexInfoValid = false; + mLastElementType = GL_NONE; + mLastDrawElementsOffset = 0; + } + else + { + ASSERT(mAttributeStorageTypes[channelID] != VertexStorageType::CURRENT_VALUE); + + // This can change a buffer's storage, we'll need to re-check. + mAttribsToUpdate.set(channelID); + + // Changing the vertex attribute state can affect the vertex shader. + Renderer11 *renderer = GetImplAs(context)->getRenderer(); + renderer->getStateManager()->invalidateShaders(); + } +} + +void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::Context *context, + const DrawCallVertexParams &vertexParams) +{ + const gl::State &state = context->getGLState(); + const gl::Program *program = state.getProgram(); + const auto &activeLocations = program->getActiveAttribLocationsMask(); + mAttribsToUpdate &= ~activeLocations; + + // Promote to static after we clear the dirty attributes, otherwise we can lose dirtyness. + auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); + if (activeDynamicAttribs.any()) + { + VertexDataManager::PromoteDynamicAttribs(context, mTranslatedAttribs, activeDynamicAttribs, + vertexParams.vertexCount()); + } +} + +void VertexArray11::markAllAttributeDivisorsForAdjustment(int numViews) +{ + if (mAppliedNumViewsToDivisor != numViews) + { + mAppliedNumViewsToDivisor = numViews; + mAttribsToUpdate.set(); + } +} + +TranslatedIndexData *VertexArray11::getCachedIndexInfo() +{ + return &mCachedIndexInfo; +} + +void VertexArray11::setCachedIndexInfoValid() +{ + mCachedIndexInfoValid = true; +} + +bool VertexArray11::isCachedIndexInfoValid() const +{ + return mCachedIndexInfoValid; +} + +} // namespace rx 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 b397140e71..4cdc92531d 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h @@ -9,23 +9,91 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ #define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ +#include "libANGLE/Framebuffer.h" #include "libANGLE/renderer/VertexArrayImpl.h" #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/signal_utils.h" namespace rx { class Renderer11; -class VertexArray11 : public VertexArrayImpl +class VertexArray11 : public VertexArrayImpl, public OnBufferDataDirtyReceiver { public: - VertexArray11(const gl::VertexArray::Data &data) - : VertexArrayImpl(data) - { - } - virtual ~VertexArray11() {} + VertexArray11(const gl::VertexArrayState &data); + ~VertexArray11() override; + void destroy(const gl::Context *context) override; + + void syncState(const gl::Context *context, + const gl::VertexArray::DirtyBits &dirtyBits) override; + // This will flush any pending attrib updates and then check the dynamic attribs mask. + bool hasActiveDynamicAttrib(const gl::Context *context); + gl::Error updateDirtyAndDynamicAttribs(const gl::Context *context, + VertexDataManager *vertexDataManager, + const DrawCallVertexParams &vertexParams); + void clearDirtyAndPromoteDynamicAttribs(const gl::Context *context, + const DrawCallVertexParams &vertexParams); + + const std::vector &getTranslatedAttribs() const; + + // SignalReceiver implementation + void signal(size_t channelID, const gl::Context *context) override; + + Serial getCurrentStateSerial() const { return mCurrentStateSerial; } + + // In case of a multi-view program change, we have to update all attributes so that the divisor + // is adjusted. + void markAllAttributeDivisorsForAdjustment(int numViews); + + bool flushAttribUpdates(const gl::Context *context); + + // Returns true if the element array buffer needs to be translated. + bool updateElementArrayStorage(const gl::Context *context, + GLenum elementType, + GLenum destElementType, + const void *indices); + + TranslatedIndexData *getCachedIndexInfo(); + void setCachedIndexInfoValid(); + bool isCachedIndexInfoValid() const; + + private: + void updateVertexAttribStorage(const gl::Context *context, size_t attribIndex); + + std::vector mAttributeStorageTypes; + std::vector mTranslatedAttribs; + + // The mask of attributes marked as dynamic. + gl::AttributesMask mDynamicAttribsMask; + + // A mask of attributes that need to be re-evaluated. + gl::AttributesMask mAttribsToUpdate; + + // A set of attributes we know are dirty, and need to be re-translated. + gl::AttributesMask mAttribsToTranslate; + + // We need to keep a safe pointer to the Buffer so we can attach the correct dirty callbacks. + std::vector> mCurrentArrayBuffers; + gl::BindingPointer mCurrentElementArrayBuffer; + + std::vector mOnArrayBufferDataDirty; + OnBufferDataDirtyBinding mOnElementArrayBufferDataDirty; + + Serial mCurrentStateSerial; + + // The numViews value used to adjust the divisor. + int mAppliedNumViewsToDivisor; + + // If the index buffer needs re-streaming. + GLenum mLastElementType; + unsigned int mLastDrawElementsOffset; + IndexStorageType mCurrentElementArrayStorage; + TranslatedIndexData mCachedIndexInfo; + bool mCachedIndexInfoValid; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_ 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 098cefcd53..611bd0f18b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -19,92 +19,88 @@ namespace rx { -VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) + : mRenderer(renderer), + mBuffer(), + mBufferSize(0), + mDynamicUsage(false), + mMappedResourceData(nullptr) { - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; - mMappedResourceData = NULL; } VertexBuffer11::~VertexBuffer11() { - ASSERT(mMappedResourceData == NULL); - SafeRelease(mBuffer); + ASSERT(mMappedResourceData == nullptr); } gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) { - SafeRelease(mBuffer); - + mBuffer.reset(); updateSerial(); if (size > 0) { - ID3D11Device* dxDevice = mRenderer->getDevice(); - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = size; - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; + bufferDesc.ByteWidth = size; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; bufferDesc.StructureByteStride = 0; - HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); - if (FAILED(result)) - { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); - } + ANGLE_TRY(mRenderer->allocateResource(bufferDesc, &mBuffer)); if (dynamicUsage) { - d3d11::SetDebugName(mBuffer, "VertexBuffer11 (dynamic)"); + mBuffer.setDebugName("VertexBuffer11 (dynamic)"); } else { - d3d11::SetDebugName(mBuffer, "VertexBuffer11 (static)"); + mBuffer.setDebugName("VertexBuffer11 (static)"); } } - mBufferSize = size; + mBufferSize = size; mDynamicUsage = dynamicUsage; - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } gl::Error VertexBuffer11::mapResource() { - if (mMappedResourceData == NULL) + if (mMappedResourceData == nullptr) { ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + HRESULT result = + dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result); + return gl::OutOfMemory() + << "Failed to map internal vertex buffer, " << gl::FmtHR(result); } - mMappedResourceData = reinterpret_cast(mappedResource.pData); + mMappedResourceData = reinterpret_cast(mappedResource.pData); } - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } void VertexBuffer11::hintUnmapResource() { - if (mMappedResourceData != NULL) + if (mMappedResourceData != nullptr) { ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - dxContext->Unmap(mBuffer, 0); + dxContext->Unmap(mBuffer.get(), 0); - mMappedResourceData = NULL; + mMappedResourceData = nullptr; } } gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, GLenum currentValueType, GLint start, GLsizei count, @@ -112,81 +108,33 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri unsigned int offset, const uint8_t *sourceData) { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + return gl::OutOfMemory() << "Internal vertex buffer is not initialized."; } - int inputStride = static_cast(ComputeVertexAttributeStride(attrib)); + int inputStride = static_cast(ComputeVertexAttributeStride(attrib, binding)); // This will map the resource if it isn't already mapped. - gl::Error error = mapResource(); - if (error.isError()) - { - return error; - } + ANGLE_TRY(mapResource()); uint8_t *output = mMappedResourceData + offset; const uint8_t *input = sourceData; - if (instances == 0 || attrib.divisor == 0) + if (instances == 0 || binding.getDivisor() == 0) { input += inputStride * start; } 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); + const D3D_FEATURE_LEVEL featureLevel = mRenderer->getRenderer11DeviceCaps().featureLevel; + const d3d11::VertexFormat &vertexFormatInfo = + d3d11::GetVertexFormatInfo(vertexFormatType, featureLevel); + ASSERT(vertexFormatInfo.copyFunction != nullptr); vertexFormatInfo.copyFunction(input, inputStride, count, output); - return gl::Error(GL_NO_ERROR); -} - -gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, - GLsizei instances, unsigned int *outSpaceRequired) const -{ - unsigned int elementCount = 0; - if (attrib.enabled) - { - if (instances == 0 || attrib.divisor == 0) - { - elementCount = count; - } - else - { - // Round up to divisor, if possible - elementCount = UnsignedCeilDivide(static_cast(instances), attrib.divisor); - } - - 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) - { - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * elementCount; - } - return gl::Error(GL_NO_ERROR); - } - else - { - return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); - } - } - else - { - const unsigned int elementSize = 4; - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * 4; - } - return gl::Error(GL_NO_ERROR); - } + return gl::NoError(); } unsigned int VertexBuffer11::getBufferSize() const @@ -202,34 +150,35 @@ gl::Error VertexBuffer11::setBufferSize(unsigned int size) } else { - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } } gl::Error VertexBuffer11::discard() { - if (!mBuffer) + if (!mBuffer.valid()) { - return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + return gl::OutOfMemory() << "Internal vertex buffer is not initialized."; } ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + HRESULT result = dxContext->Map(mBuffer.get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer for discarding, HRESULT: 0x%08x", result); + return gl::OutOfMemory() << "Failed to map internal buffer for discarding, " + << gl::FmtHR(result); } - dxContext->Unmap(mBuffer, 0); + dxContext->Unmap(mBuffer.get(), 0); - return gl::Error(GL_NO_ERROR); + return gl::NoError(); } -ID3D11Buffer *VertexBuffer11::getBuffer() const +const d3d11::Buffer &VertexBuffer11::getBuffer() const { return mBuffer; } -} +} // namespace rx 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 773c4474e1..ab619ae503 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h @@ -12,6 +12,7 @@ #include #include "libANGLE/renderer/d3d/VertexBuffer.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" namespace rx { @@ -21,11 +22,13 @@ class VertexBuffer11 : public VertexBuffer { public: explicit VertexBuffer11(Renderer11 *const renderer); - virtual ~VertexBuffer11(); - virtual gl::Error initialize(unsigned int size, bool dynamicUsage); + gl::Error initialize(unsigned int size, bool dynamicUsage) override; + // Warning: you should ensure binding really matches attrib.bindingIndex before using this + // function. gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, + const gl::VertexBinding &binding, GLenum currentValueType, GLint start, GLsizei count, @@ -33,29 +36,27 @@ class VertexBuffer11 : public VertexBuffer unsigned int offset, const uint8_t *sourceData) override; - virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const; + unsigned int getBufferSize() const override; + gl::Error setBufferSize(unsigned int size) override; + gl::Error discard() override; - virtual unsigned int getBufferSize() const; - virtual gl::Error setBufferSize(unsigned int size); - virtual gl::Error discard(); + void hintUnmapResource() override; - virtual void hintUnmapResource(); - - ID3D11Buffer *getBuffer() const; + const d3d11::Buffer &getBuffer() const; private: + ~VertexBuffer11() override; gl::Error mapResource(); Renderer11 *const mRenderer; - ID3D11Buffer *mBuffer; + d3d11::Buffer mBuffer; unsigned int mBufferSize; bool mDynamicUsage; uint8_t *mMappedResourceData; }; -} +} // namespace rx #endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_ 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 1ec21dee55..7c5c157c6f 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl @@ -15,33 +15,42 @@ inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t cou if (attribSize == stride && inputComponentCount == outputComponentCount) { memcpy(output, input, count * attribSize); + return; } - else - { - const T defaultAlphaValue = gl::bitCast(alphaDefaultValueBits); - const size_t lastNonAlphaOutputComponent = std::min(outputComponentCount, 3); + if (inputComponentCount == outputComponentCount) + { for (size_t i = 0; i < count; i++) { const T *offsetInput = reinterpret_cast(input + (i * stride)); T *offsetOutput = reinterpret_cast(output) + i * outputComponentCount; - for (size_t j = 0; j < inputComponentCount; j++) - { - offsetOutput[j] = offsetInput[j]; - } + memcpy(offsetOutput, offsetInput, attribSize); + } + return; + } - for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++) - { - // Set the remaining G/B channels to 0. - offsetOutput[j] = 0; - } + const T defaultAlphaValue = gl::bitCast(alphaDefaultValueBits); + const size_t lastNonAlphaOutputComponent = std::min(outputComponentCount, 3); - if (inputComponentCount < outputComponentCount && outputComponentCount == 4) - { - // Set the remaining alpha channel to the defaultAlphaValue. - offsetOutput[3] = defaultAlphaValue; - } + for (size_t i = 0; i < count; i++) + { + const T *offsetInput = reinterpret_cast(input + (i * stride)); + T *offsetOutput = reinterpret_cast(output) + i * outputComponentCount; + + memcpy(offsetOutput, offsetInput, attribSize); + + if (inputComponentCount < lastNonAlphaOutputComponent) + { + // Set the remaining G/B channels to 0. + size_t numComponents = (lastNonAlphaOutputComponent - inputComponentCount); + memset(&offsetOutput[inputComponentCount], 0, numComponents * sizeof(T)); + } + + if (inputComponentCount < outputComponentCount && outputComponentCount == 4) + { + // Set the remaining alpha channel to the defaultAlphaValue. + offsetOutput[3] = defaultAlphaValue; } } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json new file mode 100644 index 0000000000..891d30d252 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_data.json @@ -0,0 +1,118 @@ +{ + "UNKNOWN": "NONE", + "R32G32B32A32_TYPELESS": "", + "R32G32B32A32_FLOAT": "", + "R32G32B32A32_UINT": "", + "R32G32B32A32_SINT": "", + "R32G32B32_TYPELESS": "", + "R32G32B32_FLOAT": "", + "R32G32B32_UINT": "", + "R32G32B32_SINT": "", + "R16G16B16A16_TYPELESS": "", + "R16G16B16A16_FLOAT": "", + "R16G16B16A16_UNORM": "", + "R16G16B16A16_UINT": "", + "R16G16B16A16_SNORM": "", + "R16G16B16A16_SINT": "", + "R32G32_TYPELESS": "", + "R32G32_FLOAT": "", + "R32G32_UINT": "", + "R32G32_SINT": "", + "R32G8X24_TYPELESS": "", + "D32_FLOAT_S8X24_UINT": "", + "R32_FLOAT_X8X24_TYPELESS": "", + "X32_TYPELESS_G8X24_UINT": "", + "R10G10B10A2_TYPELESS": "", + "R10G10B10A2_UNORM": "", + "R10G10B10A2_UINT": "", + "R11G11B10_FLOAT": "", + "R8G8B8A8_TYPELESS": "", + "R8G8B8A8_UNORM": "", + "R8G8B8A8_UNORM_SRGB": "", + "R8G8B8A8_UINT": "", + "R8G8B8A8_SNORM": "", + "R8G8B8A8_SINT": "", + "R16G16_TYPELESS": "", + "R16G16_FLOAT": "", + "R16G16_UNORM": "", + "R16G16_UINT": "", + "R16G16_SNORM": "", + "R16G16_SINT": "", + "R32_TYPELESS": "", + "D32_FLOAT": "", + "R32_FLOAT": "", + "R32_UINT": "", + "R32_SINT": "", + "R24G8_TYPELESS": "", + "D24_UNORM_S8_UINT": "", + "R24_UNORM_X8_TYPELESS": "", + "X24_TYPELESS_G8_UINT": "", + "R8G8_TYPELESS": "", + "R8G8_UNORM": "", + "R8G8_UINT": "", + "R8G8_SNORM": "", + "R8G8_SINT": "", + "R16_TYPELESS": "", + "R16_FLOAT": "", + "D16_UNORM": "", + "R16_UNORM": "", + "R16_UINT": "", + "R16_SNORM": "", + "R16_SINT": "", + "R8_TYPELESS": "", + "R8_UNORM": "", + "R8_UINT": "", + "R8_SNORM": "", + "R8_SINT": "", + "A8_UNORM": "", + "R1_UNORM": "", + "R9G9B9E5_SHAREDEXP": "", + "R8G8_B8G8_UNORM": "", + "G8R8_G8B8_UNORM": "", + "BC1_TYPELESS": "", + "BC1_UNORM": "BC1_RGBA_UNORM_BLOCK", + "BC1_UNORM_SRGB": "BC1_RGBA_UNORM_SRGB_BLOCK", + "BC2_TYPELESS": "", + "BC2_UNORM": "BC2_RGBA_UNORM_BLOCK", + "BC2_UNORM_SRGB": "BC2_RGBA_UNORM_SRGB_BLOCK", + "BC3_TYPELESS": "", + "BC3_UNORM": "BC3_RGBA_UNORM_BLOCK", + "BC3_UNORM_SRGB": "BC3_RGBA_UNORM_SRGB_BLOCK", + "BC4_TYPELESS": "", + "BC4_UNORM": "", + "BC4_SNORM": "", + "BC5_TYPELESS": "", + "BC5_UNORM": "", + "BC5_SNORM": "", + "B5G6R5_UNORM": "", + "B5G5R5A1_UNORM": "", + "B8G8R8A8_UNORM": "", + "B8G8R8X8_UNORM": "", + "R10G10B10_XR_BIAS_A2_UNORM": "", + "B8G8R8A8_TYPELESS": "", + "B8G8R8A8_UNORM_SRGB": "", + "B8G8R8X8_TYPELESS": "", + "B8G8R8X8_UNORM_SRGB": "", + "BC6H_TYPELESS": "", + "BC6H_UF16": "", + "BC6H_SF16": "", + "BC7_TYPELESS": "", + "BC7_UNORM": "", + "BC7_UNORM_SRGB": "", + "AYUV": "", + "Y410": "", + "Y416": "", + "NV12": "", + "P010": "", + "P016": "", + "420_OPAQUE": "", + "YUY2": "", + "Y210": "", + "Y216": "", + "NV11": "", + "AI44": "", + "IA44": "", + "P8": "", + "A8P8": "", + "B4G4R4A4_UNORM": "" +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp new file mode 100644 index 0000000000..b0697bc5db --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp @@ -0,0 +1,516 @@ +// GENERATED FILE - DO NOT EDIT. +// Generated by gen_dxgi_format_table.py using data from dxgi_format_data.json. +// +// Copyright 2017 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 format info: +// Determining metadata about a DXGI format. + +#include "libANGLE/renderer/Format.h" + +using namespace angle; + +namespace rx +{ + +namespace d3d11 +{ + +GLenum GetComponentType(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + break; + case DXGI_FORMAT_A8P8: + break; + case DXGI_FORMAT_A8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_AI44: + break; + case DXGI_FORMAT_AYUV: + break; + case DXGI_FORMAT_B4G4R4A4_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B5G5R5A1_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B5G6R5_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + break; + case DXGI_FORMAT_B8G8R8A8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + break; + case DXGI_FORMAT_B8G8R8X8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC1_TYPELESS: + break; + case DXGI_FORMAT_BC1_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC1_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC2_TYPELESS: + break; + case DXGI_FORMAT_BC2_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC2_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC3_TYPELESS: + break; + case DXGI_FORMAT_BC3_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC3_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC4_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_BC4_TYPELESS: + break; + case DXGI_FORMAT_BC4_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC5_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_BC5_TYPELESS: + break; + case DXGI_FORMAT_BC5_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC6H_SF16: + break; + case DXGI_FORMAT_BC6H_TYPELESS: + break; + case DXGI_FORMAT_BC6H_UF16: + break; + case DXGI_FORMAT_BC7_TYPELESS: + break; + case DXGI_FORMAT_BC7_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_BC7_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_D16_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + break; + case DXGI_FORMAT_D32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + break; + case DXGI_FORMAT_G8R8_G8B8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_IA44: + break; + case DXGI_FORMAT_NV11: + break; + case DXGI_FORMAT_NV12: + break; + case DXGI_FORMAT_P010: + break; + case DXGI_FORMAT_P016: + break; + case DXGI_FORMAT_P8: + break; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + break; + case DXGI_FORMAT_R10G10B10A2_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R10G10B10A2_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R11G11B10_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R16G16B16A16_SINT: + return GL_INT; + case DXGI_FORMAT_R16G16B16A16_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + break; + case DXGI_FORMAT_R16G16B16A16_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R16G16B16A16_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R16G16_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R16G16_SINT: + return GL_INT; + case DXGI_FORMAT_R16G16_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R16G16_TYPELESS: + break; + case DXGI_FORMAT_R16G16_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R16G16_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R16_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R16_SINT: + return GL_INT; + case DXGI_FORMAT_R16_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R16_TYPELESS: + break; + case DXGI_FORMAT_R16_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R16_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R1_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R24G8_TYPELESS: + break; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R32G32B32A32_SINT: + return GL_INT; + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32A32_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R32G32B32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R32G32B32_SINT: + return GL_INT; + case DXGI_FORMAT_R32G32B32_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R32G32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R32G32_SINT: + return GL_INT; + case DXGI_FORMAT_R32G32_TYPELESS: + break; + case DXGI_FORMAT_R32G32_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R32G8X24_TYPELESS: + break; + case DXGI_FORMAT_R32_FLOAT: + return GL_FLOAT; + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + return GL_FLOAT; + case DXGI_FORMAT_R32_SINT: + return GL_INT; + case DXGI_FORMAT_R32_TYPELESS: + break; + case DXGI_FORMAT_R32_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R8G8B8A8_SINT: + return GL_INT; + case DXGI_FORMAT_R8G8B8A8_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + break; + case DXGI_FORMAT_R8G8B8A8_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R8G8B8A8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8_B8G8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8_SINT: + return GL_INT; + case DXGI_FORMAT_R8G8_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R8G8_TYPELESS: + break; + case DXGI_FORMAT_R8G8_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R8G8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R8_SINT: + return GL_INT; + case DXGI_FORMAT_R8_SNORM: + return GL_SIGNED_NORMALIZED; + case DXGI_FORMAT_R8_TYPELESS: + break; + case DXGI_FORMAT_R8_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_R8_UNORM: + return GL_UNSIGNED_NORMALIZED; + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + return GL_FLOAT; + case DXGI_FORMAT_UNKNOWN: + break; + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return GL_UNSIGNED_INT; + case DXGI_FORMAT_Y210: + break; + case DXGI_FORMAT_Y216: + break; + case DXGI_FORMAT_Y410: + break; + case DXGI_FORMAT_Y416: + break; + case DXGI_FORMAT_YUY2: + break; + default: + break; + } + + UNREACHABLE(); + return GL_NONE; +} + +} // namespace d3d11 + +namespace d3d11_angle +{ + +const Format &GetFormat(DXGI_FORMAT dxgiFormat) +{ + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + break; + case DXGI_FORMAT_A8P8: + break; + case DXGI_FORMAT_A8_UNORM: + return Format::Get(Format::ID::A8_UNORM); + case DXGI_FORMAT_AI44: + break; + case DXGI_FORMAT_AYUV: + break; + case DXGI_FORMAT_B4G4R4A4_UNORM: + return Format::Get(Format::ID::B4G4R4A4_UNORM); + case DXGI_FORMAT_B5G5R5A1_UNORM: + return Format::Get(Format::ID::B5G5R5A1_UNORM); + case DXGI_FORMAT_B5G6R5_UNORM: + return Format::Get(Format::ID::B5G6R5_UNORM); + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + break; + case DXGI_FORMAT_B8G8R8A8_UNORM: + return Format::Get(Format::ID::B8G8R8A8_UNORM); + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + return Format::Get(Format::ID::B8G8R8A8_UNORM_SRGB); + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + break; + case DXGI_FORMAT_B8G8R8X8_UNORM: + return Format::Get(Format::ID::B8G8R8X8_UNORM); + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + break; + case DXGI_FORMAT_BC1_TYPELESS: + break; + case DXGI_FORMAT_BC1_UNORM: + return Format::Get(Format::ID::BC1_RGBA_UNORM_BLOCK); + case DXGI_FORMAT_BC1_UNORM_SRGB: + return Format::Get(Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK); + case DXGI_FORMAT_BC2_TYPELESS: + break; + case DXGI_FORMAT_BC2_UNORM: + return Format::Get(Format::ID::BC2_RGBA_UNORM_BLOCK); + case DXGI_FORMAT_BC2_UNORM_SRGB: + return Format::Get(Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK); + case DXGI_FORMAT_BC3_TYPELESS: + break; + case DXGI_FORMAT_BC3_UNORM: + return Format::Get(Format::ID::BC3_RGBA_UNORM_BLOCK); + case DXGI_FORMAT_BC3_UNORM_SRGB: + return Format::Get(Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK); + case DXGI_FORMAT_BC4_SNORM: + break; + case DXGI_FORMAT_BC4_TYPELESS: + break; + case DXGI_FORMAT_BC4_UNORM: + break; + case DXGI_FORMAT_BC5_SNORM: + break; + case DXGI_FORMAT_BC5_TYPELESS: + break; + case DXGI_FORMAT_BC5_UNORM: + break; + case DXGI_FORMAT_BC6H_SF16: + break; + case DXGI_FORMAT_BC6H_TYPELESS: + break; + case DXGI_FORMAT_BC6H_UF16: + break; + case DXGI_FORMAT_BC7_TYPELESS: + break; + case DXGI_FORMAT_BC7_UNORM: + break; + case DXGI_FORMAT_BC7_UNORM_SRGB: + break; + case DXGI_FORMAT_D16_UNORM: + return Format::Get(Format::ID::D16_UNORM); + case DXGI_FORMAT_D24_UNORM_S8_UINT: + return Format::Get(Format::ID::D24_UNORM_S8_UINT); + case DXGI_FORMAT_D32_FLOAT: + return Format::Get(Format::ID::D32_FLOAT); + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + return Format::Get(Format::ID::D32_FLOAT_S8X24_UINT); + case DXGI_FORMAT_G8R8_G8B8_UNORM: + break; + case DXGI_FORMAT_IA44: + break; + case DXGI_FORMAT_NV11: + break; + case DXGI_FORMAT_NV12: + break; + case DXGI_FORMAT_P010: + break; + case DXGI_FORMAT_P016: + break; + case DXGI_FORMAT_P8: + break; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + break; + case DXGI_FORMAT_R10G10B10A2_UINT: + return Format::Get(Format::ID::R10G10B10A2_UINT); + case DXGI_FORMAT_R10G10B10A2_UNORM: + return Format::Get(Format::ID::R10G10B10A2_UNORM); + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + break; + case DXGI_FORMAT_R11G11B10_FLOAT: + return Format::Get(Format::ID::R11G11B10_FLOAT); + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return Format::Get(Format::ID::R16G16B16A16_FLOAT); + case DXGI_FORMAT_R16G16B16A16_SINT: + return Format::Get(Format::ID::R16G16B16A16_SINT); + case DXGI_FORMAT_R16G16B16A16_SNORM: + return Format::Get(Format::ID::R16G16B16A16_SNORM); + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + break; + case DXGI_FORMAT_R16G16B16A16_UINT: + return Format::Get(Format::ID::R16G16B16A16_UINT); + case DXGI_FORMAT_R16G16B16A16_UNORM: + return Format::Get(Format::ID::R16G16B16A16_UNORM); + case DXGI_FORMAT_R16G16_FLOAT: + return Format::Get(Format::ID::R16G16_FLOAT); + case DXGI_FORMAT_R16G16_SINT: + return Format::Get(Format::ID::R16G16_SINT); + case DXGI_FORMAT_R16G16_SNORM: + return Format::Get(Format::ID::R16G16_SNORM); + case DXGI_FORMAT_R16G16_TYPELESS: + break; + case DXGI_FORMAT_R16G16_UINT: + return Format::Get(Format::ID::R16G16_UINT); + case DXGI_FORMAT_R16G16_UNORM: + return Format::Get(Format::ID::R16G16_UNORM); + case DXGI_FORMAT_R16_FLOAT: + return Format::Get(Format::ID::R16_FLOAT); + case DXGI_FORMAT_R16_SINT: + return Format::Get(Format::ID::R16_SINT); + case DXGI_FORMAT_R16_SNORM: + return Format::Get(Format::ID::R16_SNORM); + case DXGI_FORMAT_R16_TYPELESS: + break; + case DXGI_FORMAT_R16_UINT: + return Format::Get(Format::ID::R16_UINT); + case DXGI_FORMAT_R16_UNORM: + return Format::Get(Format::ID::R16_UNORM); + case DXGI_FORMAT_R1_UNORM: + break; + case DXGI_FORMAT_R24G8_TYPELESS: + break; + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32A32_FLOAT: + return Format::Get(Format::ID::R32G32B32A32_FLOAT); + case DXGI_FORMAT_R32G32B32A32_SINT: + return Format::Get(Format::ID::R32G32B32A32_SINT); + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32A32_UINT: + return Format::Get(Format::ID::R32G32B32A32_UINT); + case DXGI_FORMAT_R32G32B32_FLOAT: + return Format::Get(Format::ID::R32G32B32_FLOAT); + case DXGI_FORMAT_R32G32B32_SINT: + return Format::Get(Format::ID::R32G32B32_SINT); + case DXGI_FORMAT_R32G32B32_TYPELESS: + break; + case DXGI_FORMAT_R32G32B32_UINT: + return Format::Get(Format::ID::R32G32B32_UINT); + case DXGI_FORMAT_R32G32_FLOAT: + return Format::Get(Format::ID::R32G32_FLOAT); + case DXGI_FORMAT_R32G32_SINT: + return Format::Get(Format::ID::R32G32_SINT); + case DXGI_FORMAT_R32G32_TYPELESS: + break; + case DXGI_FORMAT_R32G32_UINT: + return Format::Get(Format::ID::R32G32_UINT); + case DXGI_FORMAT_R32G8X24_TYPELESS: + break; + case DXGI_FORMAT_R32_FLOAT: + return Format::Get(Format::ID::R32_FLOAT); + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + break; + case DXGI_FORMAT_R32_SINT: + return Format::Get(Format::ID::R32_SINT); + case DXGI_FORMAT_R32_TYPELESS: + break; + case DXGI_FORMAT_R32_UINT: + return Format::Get(Format::ID::R32_UINT); + case DXGI_FORMAT_R8G8B8A8_SINT: + return Format::Get(Format::ID::R8G8B8A8_SINT); + case DXGI_FORMAT_R8G8B8A8_SNORM: + return Format::Get(Format::ID::R8G8B8A8_SNORM); + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + break; + case DXGI_FORMAT_R8G8B8A8_UINT: + return Format::Get(Format::ID::R8G8B8A8_UINT); + case DXGI_FORMAT_R8G8B8A8_UNORM: + return Format::Get(Format::ID::R8G8B8A8_UNORM); + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + return Format::Get(Format::ID::R8G8B8A8_UNORM_SRGB); + case DXGI_FORMAT_R8G8_B8G8_UNORM: + break; + case DXGI_FORMAT_R8G8_SINT: + return Format::Get(Format::ID::R8G8_SINT); + case DXGI_FORMAT_R8G8_SNORM: + return Format::Get(Format::ID::R8G8_SNORM); + case DXGI_FORMAT_R8G8_TYPELESS: + break; + case DXGI_FORMAT_R8G8_UINT: + return Format::Get(Format::ID::R8G8_UINT); + case DXGI_FORMAT_R8G8_UNORM: + return Format::Get(Format::ID::R8G8_UNORM); + case DXGI_FORMAT_R8_SINT: + return Format::Get(Format::ID::R8_SINT); + case DXGI_FORMAT_R8_SNORM: + return Format::Get(Format::ID::R8_SNORM); + case DXGI_FORMAT_R8_TYPELESS: + break; + case DXGI_FORMAT_R8_UINT: + return Format::Get(Format::ID::R8_UINT); + case DXGI_FORMAT_R8_UNORM: + return Format::Get(Format::ID::R8_UNORM); + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + return Format::Get(Format::ID::R9G9B9E5_SHAREDEXP); + case DXGI_FORMAT_UNKNOWN: + return Format::Get(Format::ID::NONE); + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + break; + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + break; + case DXGI_FORMAT_Y210: + break; + case DXGI_FORMAT_Y216: + break; + case DXGI_FORMAT_Y410: + break; + case DXGI_FORMAT_Y416: + break; + case DXGI_FORMAT_YUY2: + break; + default: + break; + } + + UNREACHABLE(); + return Format::Get(Format::ID::NONE); +} + +} // namespace d3d11_angle + +} // namespace rx 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 index e81b4deea5..942745674f 100644 --- 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 @@ -8,7 +8,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32A32_TYPELESS": { @@ -18,7 +19,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32A32_FLOAT": { @@ -28,27 +30,30 @@ "shaderSample": "10_0check10_1always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R32G32B32A32_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32A32_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32_TYPELESS": { @@ -58,7 +63,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32_FLOAT": { @@ -68,7 +74,8 @@ "shaderSample": "11_0check", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32_UINT": { @@ -78,7 +85,8 @@ "shaderSample": "never", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32B32_SINT": { @@ -88,7 +96,8 @@ "shaderSample": "never", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16B16A16_TYPELESS": { @@ -98,57 +107,63 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16B16A16_FLOAT": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "9_3check_10_0always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R16G16B16A16_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R16G16B16A16_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16B16A16_SNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R16G16B16A16_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32_TYPELESS": { @@ -158,7 +173,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32_FLOAT": { @@ -168,37 +184,41 @@ "shaderSample": "10_0check10_1always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R32G32_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G32_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32G8X24_TYPELESS": { - "texture2D": "always", + "texture2D": "10_0", "texture3D": "never", - "textureCube": "always", + "textureCube": "10_0", "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_D32_FLOAT_S8X24_UINT": { @@ -208,7 +228,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "check", - "depthStencil": "always" + "depthStencil": "10_0", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS": { @@ -218,7 +239,8 @@ "shaderSample": "10_0check10_1always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_X32_TYPELESS_G8X24_UINT": { @@ -228,47 +250,52 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R10G10B10A2_TYPELESS": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R10G10B10A2_UNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R10G10B10A2_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R11G11B10_FLOAT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8G8B8A8_TYPELESS": { @@ -278,57 +305,63 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8B8A8_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R8G8B8A8_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8B8A8_SNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8G8B8A8_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16_TYPELESS": { @@ -338,7 +371,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16_FLOAT": { @@ -348,57 +382,63 @@ "shaderSample": "10_0", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R16G16_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R16G16_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16G16_SNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R16G16_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32_TYPELESS": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_D32_FLOAT": { @@ -408,7 +448,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "check", - "depthStencil": "always" + "depthStencil": "10_0", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32_FLOAT": { @@ -418,27 +459,30 @@ "shaderSample": "10_0check10_1always", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_R32_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R32_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R24G8_TYPELESS": { @@ -448,7 +492,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_D24_UNORM_S8_UINT": { @@ -468,7 +513,8 @@ "shaderSample": "10_0check10_1always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_X24_TYPELESS_G8_UINT": { @@ -478,7 +524,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8_TYPELESS": { @@ -488,47 +535,52 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8_UNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", - "shaderSample": "10_0", - "renderTarget": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "9_3check_10_0always", + "renderTarget": "9_3check_10_0always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8G8_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8_SNORM": { "texture2D": "always", - "texture3D": "always", - "textureCube": "always", - "shaderSample": "10_0", - "renderTarget": "always", + "texture3D": "10_0", + "textureCube": "10_0", + "shaderSample": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8G8_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16_TYPELESS": { @@ -538,17 +590,19 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16_FLOAT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_D16_UNORM": { @@ -558,47 +612,52 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "check", - "depthStencil": "always" + "depthStencil": "always", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", - "renderTarget": "always", + "shaderSample": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R16_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R16_SNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R16_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8_TYPELESS": { @@ -608,47 +667,52 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", - "renderTarget": "always", + "shaderSample": "always", + "renderTarget": "9_3check_10_0always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8_UINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8_SNORM": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R8_SINT": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "never", - "renderTarget": "always", + "renderTarget": "10_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_A8_UNORM": { @@ -658,7 +722,8 @@ "shaderSample": "10_0", "renderTarget": "always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "10_0" }, "DXGI_FORMAT_R1_UNORM": { @@ -668,17 +733,19 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R9G9B9E5_SHAREDEXP": { - "texture2D": "always", - "texture3D": "always", - "textureCube": "always", + "texture2D": "10_0", + "texture3D": "10_0", + "textureCube": "10_0", "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R8G8_B8G8_UNORM": { @@ -688,7 +755,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_G8R8_G8B8_UNORM": { @@ -698,7 +766,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC1_TYPELESS": { @@ -708,27 +777,30 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC1_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC1_UNORM_SRGB": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC2_TYPELESS": { @@ -738,27 +810,30 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC2_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC2_UNORM_SRGB": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC3_TYPELESS": { @@ -768,27 +843,30 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC3_UNORM": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC3_UNORM_SRGB": { "texture2D": "always", "texture3D": "always", "textureCube": "always", - "shaderSample": "10_0", + "shaderSample": "always", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC4_TYPELESS": { @@ -798,7 +876,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC4_UNORM": { @@ -808,7 +887,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC4_SNORM": { @@ -818,7 +898,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC5_TYPELESS": { @@ -828,7 +909,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC5_UNORM": { @@ -838,7 +920,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC5_SNORM": { @@ -848,7 +931,8 @@ "shaderSample": "10_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B5G6R5_UNORM": { @@ -858,7 +942,8 @@ "shaderSample": "dxgi1_2", "renderTarget": "dxgi1_2", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "dxgi1_2" }, "DXGI_FORMAT_B5G5R5A1_UNORM": { @@ -868,17 +953,19 @@ "shaderSample": "dxgi1_2", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "dxgi1_2" }, "DXGI_FORMAT_B8G8R8A8_UNORM": { "texture2D": "check", "texture3D": "check", "textureCube": "check", - "shaderSample": "10_0check11_0always", - "renderTarget": "10_0check11_0always", + "shaderSample": "9_3always_10_0check11_0always", + "renderTarget": "9_3always_10_0check11_0always", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "always" }, "DXGI_FORMAT_B8G8R8X8_UNORM": { @@ -888,7 +975,8 @@ "shaderSample": "10_0check11_0always", "renderTarget": "11_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM": { @@ -898,7 +986,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B8G8R8A8_TYPELESS": { @@ -908,7 +997,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB": { @@ -918,7 +1008,8 @@ "shaderSample": "10_0check11_0always", "renderTarget": "11_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B8G8R8X8_TYPELESS": { @@ -928,7 +1019,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B8G8R8X8_UNORM_SRGB": { @@ -938,7 +1030,8 @@ "shaderSample": "10_0check11_0always", "renderTarget": "11_0", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC6H_TYPELESS": { @@ -948,7 +1041,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC6H_UF16": { @@ -958,7 +1052,8 @@ "shaderSample": "11_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC6H_SF16": { @@ -968,7 +1063,8 @@ "shaderSample": "11_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC7_TYPELESS": { @@ -978,7 +1074,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC7_UNORM": { @@ -988,7 +1085,8 @@ "shaderSample": "11_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_BC7_UNORM_SRGB": { @@ -998,7 +1096,8 @@ "shaderSample": "11_0", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_AYUV": { @@ -1008,7 +1107,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_Y410": { @@ -1018,7 +1118,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_Y416": { @@ -1028,7 +1129,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_NV12": { @@ -1038,7 +1140,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_P010": { @@ -1048,7 +1151,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_P016": { @@ -1058,7 +1162,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_420_OPAQUE": { @@ -1068,7 +1173,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_YUY2": { @@ -1078,7 +1184,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_Y210": { @@ -1088,7 +1195,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_Y216": { @@ -1098,7 +1206,8 @@ "shaderSample": "11_1", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_NV11": { @@ -1108,7 +1217,8 @@ "shaderSample": "11_1", "renderTarget": "11_1", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_AI44": { @@ -1118,7 +1228,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_IA44": { @@ -1128,7 +1239,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_P8": { @@ -1138,7 +1250,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_A8P8": { @@ -1148,7 +1261,8 @@ "shaderSample": "never", "renderTarget": "never", "multisampleRT": "never", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "never" }, "DXGI_FORMAT_B4G4R4A4_UNORM": { @@ -1158,7 +1272,8 @@ "shaderSample": "dxgi1_2", "renderTarget": "check", "multisampleRT": "check", - "depthStencil": "never" + "depthStencil": "never", + "mipAutoGen": "dxgi1_2" } } ] 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 index cbc36445e6..4d7e46bdf2 100644 --- 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 @@ -26,205 +26,205 @@ namespace d3d11 #define F_RT D3D11_FORMAT_SUPPORT_RENDER_TARGET #define F_MS D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET #define F_DS D3D11_FORMAT_SUPPORT_DEPTH_STENCIL +#define F_MIPGEN D3D11_FORMAT_SUPPORT_MIP_AUTOGEN 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 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 | D3D11_FORMAT_SUPPORT_MIP_AUTOGEN; static const DXGISupport defaultSupport(0, 0, AllSupportFlags); return defaultSupport; } -const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) +const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat) { + // clang-format off 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_MIPGEN | 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(0, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); + static const DXGISupport info(0, F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); 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); + static const DXGISupport info(0, F_DS | F_MIPGEN, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_BC6H_SF16: { - static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); return info; } case DXGI_FORMAT_D24_UNORM_S8_UINT: @@ -234,112 +234,112 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_D32_FLOAT: { - static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, 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); + static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS | F_SAMPLE); 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); return info; } case DXGI_FORMAT_R16G16_SNORM: @@ -349,157 +349,157 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_R16G16_TYPELESS: { - static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(0, 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | 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); + static const DXGISupport info(F_2D, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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_DS, F_MS | F_SAMPLE); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | F_RT, F_DS, F_MS); 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | F_SAMPLE, F_MS); return info; } case DXGI_FORMAT_R8G8B8A8_SNORM: @@ -509,122 +509,122 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_R8G8B8A8_TYPELESS: { - static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MS | F_RT | F_SAMPLE, 0); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS, F_MS | F_RT | F_SAMPLE); 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS, F_MS | F_RT); 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } @@ -632,190 +632,192 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) UNREACHABLE(); return GetDefaultSupport(); } + // clang-format on } -const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) +const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) { + // clang-format off 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_MIPGEN, 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); + static const DXGISupport info(0, F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_DS | F_MIPGEN, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } case DXGI_FORMAT_BC6H_SF16: { - static const DXGISupport info(0, F_DS | F_MS | F_RT, 0); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); return info; } case DXGI_FORMAT_D24_UNORM_S8_UINT: @@ -825,397 +827,397 @@ const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_D32_FLOAT: { - static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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_SAMPLE, F_DS, F_MS); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_SAMPLE, F_3D | F_DS | F_MS | F_RT, 0); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } @@ -1223,190 +1225,192 @@ const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) UNREACHABLE(); return GetDefaultSupport(); } + // clang-format on } -const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) +const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) { + // clang-format off 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_MIPGEN, 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(F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS); + static const DXGISupport info(0, F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); 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); + static const DXGISupport info(0, F_DS | F_MIPGEN, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | F_RT | F_SAMPLE, F_MS); return info; } case DXGI_FORMAT_D24_UNORM_S8_UINT: @@ -1416,397 +1420,1583 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) } case DXGI_FORMAT_D32_FLOAT: { - static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_RT | F_SAMPLE, F_MS); + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE | F_DS, F_3D | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, 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); + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(0, F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE | F_SAMPLE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_RT, F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y210: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } + // clang-format on +} + +const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) +{ + // clang-format off + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8P8: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_AI44: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_AYUV: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + static const DXGISupport info(F_MIPGEN | 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_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | 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_MIPGEN, 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_MIPGEN, 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_IA44: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_NV11: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_Y210: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y216: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y410: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_Y416: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_YUY2: + { + static const DXGISupport info(0, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); + return info; + } + + default: + UNREACHABLE(); + return GetDefaultSupport(); + } + // clang-format on +} + +const DXGISupport &GetDXGISupport_11_1(DXGI_FORMAT dxgiFormat) +{ + // clang-format off + switch (dxgiFormat) + { + case DXGI_FORMAT_420_OPAQUE: + { + static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_A8P8: + { + static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | 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_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_AI44: + { + static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_AYUV: + { + static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_B4G4R4A4_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_RT | F_SAMPLE, F_DS, F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, F_2D | F_3D | F_CUBE); + return info; + } + case DXGI_FORMAT_B8G8R8A8_UNORM: + { + static const DXGISupport info(F_MIPGEN | 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_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); + return info; + } + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + { + static const DXGISupport info(0, F_DS | F_MIPGEN | 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_MIPGEN, 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_MIPGEN, 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_IA44: + { + static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT | F_SAMPLE, 0); + return info; + } + case DXGI_FORMAT_NV11: + { + static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_NV12: + { + static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P010: + { + static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P016: + { + static const DXGISupport info(F_2D | F_RT | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN, F_MS); + return info; + } + case DXGI_FORMAT_P8: + { + static const DXGISupport info(F_2D, F_3D | F_CUBE | F_DS | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R10G10B10A2_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16B16A16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16G16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R16_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_MS | F_RT, 0); + return info; + } + case DXGI_FORMAT_R32G32B32A32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32B32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32B32_SINT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS | F_RT); + return info; + } + case DXGI_FORMAT_R32G32_FLOAT: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32G8X24_TYPELESS: + { + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R32_TYPELESS: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE, F_DS | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8B8A8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8G8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_SNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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_MIPGEN | 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_MIPGEN | F_SAMPLE, F_MS); + return info; + } + case DXGI_FORMAT_R8_UNORM: + { + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_3D | F_CUBE | F_SAMPLE, F_DS | F_MIPGEN | 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); + static const DXGISupport info(0, F_2D | F_3D | F_CUBE | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_CUBE, F_3D | F_DS | F_MIPGEN | 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); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 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); + static const DXGISupport info(F_2D | F_SAMPLE, F_3D | F_CUBE | F_DS | F_MIPGEN | F_MS | F_RT, 0); return info; } @@ -1814,6 +3004,7 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) UNREACHABLE(); return GetDefaultSupport(); } + // clang-format on } } @@ -1825,17 +3016,22 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) #undef F_RT #undef F_MS #undef F_DS +#undef F_MIPGEN const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { + case D3D_FEATURE_LEVEL_9_3: + return GetDXGISupport_9_3(dxgiFormat); 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); + case D3D_FEATURE_LEVEL_11_1: + return GetDXGISupport_11_1(dxgiFormat); default: return GetDefaultSupport(); } 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 index 1d8d68565e..a818f376ef 100644 --- 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 @@ -8,6 +8,9 @@ // version, D3D feature level, and is sometimes guaranteed or optional. // +#ifndef LIBANGLE_RENDERER_D3D_D3D11_DXGI_SUPPORT_TABLE_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_DXGI_SUPPORT_TABLE_H_ + #include "common/platform.h" namespace rx @@ -42,3 +45,5 @@ const DXGISupport &GetDXGISupport(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL feat } // namespace d3d11 } // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_DXGI_SUPPORT_TABLE_H_ 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 f073e9f46f..ce4edd26db 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp @@ -9,14 +9,15 @@ #include "libANGLE/renderer/d3d/d3d11/formatutils11.h" +#include "image_util/copyimage.h" +#include "image_util/generatemip.h" +#include "image_util/loadimage.h" + #include "libANGLE/formatutils.h" -#include "libANGLE/renderer/d3d/copyimage.h" #include "libANGLE/renderer/d3d/d3d11/copyvertex.h" +#include "libANGLE/renderer/d3d/d3d11/dxgi_support_table.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/Renderer.h" namespace rx { @@ -24,559 +25,388 @@ namespace rx namespace d3d11 { -typedef std::map DXGIToESFormatMap; - -inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value) +bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel) { - map->insert(std::make_pair(key, value)); + const auto &support = GetDXGISupport(dxgiFormat, featureLevel); + ASSERT((support.optionallySupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) == 0); + return ((support.alwaysSupportedFlags & D3D11_FORMAT_SUPPORT_MIP_AUTOGEN) != 0); } -static DXGIToESFormatMap BuildDXGIToESFormatMap() +DXGIFormatSize::DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight) + : pixelBytes(pixelBits / 8), blockWidth(blockWidth), blockHeight(blockHeight) { - DXGIToESFormatMap map; - - AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE); - - AddDXGIToESEntry(&map, DXGI_FORMAT_A8_UNORM, GL_ALPHA8_EXT); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UNORM, GL_R8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UNORM, GL_RG8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM, GL_RGBA8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, GL_SRGB8_ALPHA8); - AddDXGIToESEntry(&map, DXGI_FORMAT_B8G8R8A8_UNORM, GL_BGRA8_EXT); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SNORM, GL_R8_SNORM); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SNORM, GL_RG8_SNORM); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_UINT, GL_R8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UINT, GL_R16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_UINT, GL_R32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_UINT, GL_RG8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_UINT, GL_RG16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_UINT, GL_RG32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_UINT, GL_RGB32UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_UINT, GL_RGBA16UI); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_UINT, GL_RGBA32UI); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R8_SINT, GL_R8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_SINT, GL_R16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_SINT, GL_R32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8_SINT, GL_RG8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_SINT, GL_RG16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_SINT, GL_RG32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_SINT, GL_RGB32I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R8G8B8A8_SINT, GL_RGBA8I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_SINT, GL_RGBA16I); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_SINT, GL_RGBA32I); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2); - AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT, GL_R32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32_FLOAT, GL_RG32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32_FLOAT, GL_RGB32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, GL_RGB9_E5); - AddDXGIToESEntry(&map, DXGI_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_TYPELESS, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_R16_UNORM, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_D16_UNORM, GL_DEPTH_COMPONENT16); - AddDXGIToESEntry(&map, DXGI_FORMAT_R24G8_TYPELESS, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_OES); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32G8X24_TYPELESS, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8); - AddDXGIToESEntry(&map, DXGI_FORMAT_R32_TYPELESS, GL_DEPTH_COMPONENT32F); - AddDXGIToESEntry(&map, DXGI_FORMAT_D32_FLOAT, GL_DEPTH_COMPONENT32F); - - AddDXGIToESEntry(&map, DXGI_FORMAT_BC1_UNORM, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); - 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; } -struct D3D11FastCopyFormat +const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format) { - GLenum destFormat; - GLenum destType; - ColorCopyFunction copyFunction; - - D3D11FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) - : destFormat(destFormat), destType(destType), copyFunction(copyFunction) - { } - - bool operator<(const D3D11FastCopyFormat& other) const + static const DXGIFormatSize sizeUnknown(0, 0, 0); + static const DXGIFormatSize size128(128, 1, 1); + static const DXGIFormatSize size96(96, 1, 1); + static const DXGIFormatSize size64(64, 1, 1); + static const DXGIFormatSize size32(32, 1, 1); + static const DXGIFormatSize size16(16, 1, 1); + static const DXGIFormatSize size8(8, 1, 1); + static const DXGIFormatSize sizeBC1(64, 4, 4); + static const DXGIFormatSize sizeBC2(128, 4, 4); + static const DXGIFormatSize sizeBC3(128, 4, 4); + static const DXGIFormatSize sizeBC4(64, 4, 4); + static const DXGIFormatSize sizeBC5(128, 4, 4); + static const DXGIFormatSize sizeBC6H(128, 4, 4); + static const DXGIFormatSize sizeBC7(128, 4, 4); + switch (format) { - return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0; + case DXGI_FORMAT_UNKNOWN: + return sizeUnknown; + case DXGI_FORMAT_R32G32B32A32_TYPELESS: + case DXGI_FORMAT_R32G32B32A32_FLOAT: + case DXGI_FORMAT_R32G32B32A32_UINT: + case DXGI_FORMAT_R32G32B32A32_SINT: + return size128; + case DXGI_FORMAT_R32G32B32_TYPELESS: + case DXGI_FORMAT_R32G32B32_FLOAT: + case DXGI_FORMAT_R32G32B32_UINT: + case DXGI_FORMAT_R32G32B32_SINT: + return size96; + case DXGI_FORMAT_R16G16B16A16_TYPELESS: + case DXGI_FORMAT_R16G16B16A16_FLOAT: + case DXGI_FORMAT_R16G16B16A16_UNORM: + case DXGI_FORMAT_R16G16B16A16_UINT: + case DXGI_FORMAT_R16G16B16A16_SNORM: + case DXGI_FORMAT_R16G16B16A16_SINT: + case DXGI_FORMAT_R32G32_TYPELESS: + case DXGI_FORMAT_R32G32_FLOAT: + case DXGI_FORMAT_R32G32_UINT: + case DXGI_FORMAT_R32G32_SINT: + case DXGI_FORMAT_R32G8X24_TYPELESS: + case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: + case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: + case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: + return size64; + case DXGI_FORMAT_R10G10B10A2_TYPELESS: + case DXGI_FORMAT_R10G10B10A2_UNORM: + case DXGI_FORMAT_R10G10B10A2_UINT: + case DXGI_FORMAT_R11G11B10_FLOAT: + case DXGI_FORMAT_R8G8B8A8_TYPELESS: + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + case DXGI_FORMAT_R8G8B8A8_UINT: + case DXGI_FORMAT_R8G8B8A8_SNORM: + case DXGI_FORMAT_R8G8B8A8_SINT: + case DXGI_FORMAT_R16G16_TYPELESS: + case DXGI_FORMAT_R16G16_FLOAT: + case DXGI_FORMAT_R16G16_UNORM: + case DXGI_FORMAT_R16G16_UINT: + case DXGI_FORMAT_R16G16_SNORM: + case DXGI_FORMAT_R16G16_SINT: + case DXGI_FORMAT_R32_TYPELESS: + case DXGI_FORMAT_D32_FLOAT: + case DXGI_FORMAT_R32_FLOAT: + case DXGI_FORMAT_R32_UINT: + case DXGI_FORMAT_R32_SINT: + case DXGI_FORMAT_R24G8_TYPELESS: + case DXGI_FORMAT_D24_UNORM_S8_UINT: + case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: + case DXGI_FORMAT_X24_TYPELESS_G8_UINT: + return size32; + case DXGI_FORMAT_R8G8_TYPELESS: + case DXGI_FORMAT_R8G8_UNORM: + case DXGI_FORMAT_R8G8_UINT: + case DXGI_FORMAT_R8G8_SNORM: + case DXGI_FORMAT_R8G8_SINT: + case DXGI_FORMAT_R16_TYPELESS: + case DXGI_FORMAT_R16_FLOAT: + case DXGI_FORMAT_D16_UNORM: + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_UINT: + case DXGI_FORMAT_R16_SNORM: + case DXGI_FORMAT_R16_SINT: + return size16; + case DXGI_FORMAT_R8_TYPELESS: + case DXGI_FORMAT_R8_UNORM: + case DXGI_FORMAT_R8_UINT: + case DXGI_FORMAT_R8_SNORM: + case DXGI_FORMAT_R8_SINT: + case DXGI_FORMAT_A8_UNORM: + return size8; + case DXGI_FORMAT_R1_UNORM: + UNREACHABLE(); + return sizeUnknown; + case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: + case DXGI_FORMAT_R8G8_B8G8_UNORM: + case DXGI_FORMAT_G8R8_G8B8_UNORM: + return size32; + case DXGI_FORMAT_BC1_TYPELESS: + case DXGI_FORMAT_BC1_UNORM: + case DXGI_FORMAT_BC1_UNORM_SRGB: + return sizeBC1; + case DXGI_FORMAT_BC2_TYPELESS: + case DXGI_FORMAT_BC2_UNORM: + case DXGI_FORMAT_BC2_UNORM_SRGB: + return sizeBC2; + case DXGI_FORMAT_BC3_TYPELESS: + case DXGI_FORMAT_BC3_UNORM: + case DXGI_FORMAT_BC3_UNORM_SRGB: + return sizeBC3; + case DXGI_FORMAT_BC4_TYPELESS: + case DXGI_FORMAT_BC4_UNORM: + case DXGI_FORMAT_BC4_SNORM: + return sizeBC4; + case DXGI_FORMAT_BC5_TYPELESS: + case DXGI_FORMAT_BC5_UNORM: + case DXGI_FORMAT_BC5_SNORM: + return sizeBC5; + case DXGI_FORMAT_B5G6R5_UNORM: + case DXGI_FORMAT_B5G5R5A1_UNORM: + return size16; + case DXGI_FORMAT_B8G8R8A8_UNORM: + case DXGI_FORMAT_B8G8R8X8_UNORM: + case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: + case DXGI_FORMAT_B8G8R8A8_TYPELESS: + case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: + case DXGI_FORMAT_B8G8R8X8_TYPELESS: + case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: + return size32; + case DXGI_FORMAT_BC6H_TYPELESS: + case DXGI_FORMAT_BC6H_UF16: + case DXGI_FORMAT_BC6H_SF16: + return sizeBC6H; + case DXGI_FORMAT_BC7_TYPELESS: + case DXGI_FORMAT_BC7_UNORM: + case DXGI_FORMAT_BC7_UNORM_SRGB: + return sizeBC7; + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_Y416: + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_P010: + case DXGI_FORMAT_P016: + case DXGI_FORMAT_420_OPAQUE: + case DXGI_FORMAT_YUY2: + case DXGI_FORMAT_Y210: + case DXGI_FORMAT_Y216: + case DXGI_FORMAT_NV11: + case DXGI_FORMAT_AI44: + case DXGI_FORMAT_IA44: + case DXGI_FORMAT_P8: + case DXGI_FORMAT_A8P8: + UNREACHABLE(); + return sizeUnknown; + case DXGI_FORMAT_B4G4R4A4_UNORM: + return size16; + default: + UNREACHABLE(); + return sizeUnknown; } -}; - -typedef std::multimap D3D11FastCopyMap; - -static D3D11FastCopyMap BuildFastCopyMap() -{ - D3D11FastCopyMap map; - - map.insert(std::make_pair(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); - - return map; -} - -struct DXGIColorFormatInfo -{ - size_t redBits; - size_t greenBits; - size_t blueBits; - - size_t luminanceBits; - - size_t alphaBits; - size_t sharedBits; -}; - -typedef std::map ColorFormatInfoMap; -typedef std::pair ColorFormatInfoPair; - -static inline void InsertDXGIColorFormatInfo(ColorFormatInfoMap *map, DXGI_FORMAT format, size_t redBits, size_t greenBits, - size_t blueBits, size_t alphaBits, size_t sharedBits) -{ - DXGIColorFormatInfo info; - info.redBits = redBits; - info.greenBits = greenBits; - info.blueBits = blueBits; - info.alphaBits = alphaBits; - info.sharedBits = sharedBits; - - map->insert(std::make_pair(format, info)); -} - -static ColorFormatInfoMap BuildColorFormatInfoMap() -{ - ColorFormatInfoMap map; - - // | DXGI format | R | G | B | A | S | - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_A8_UNORM, 0, 0, 0, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UNORM, 8, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UNORM, 8, 8, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 8, 8, 8, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 8, 8, 8, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 8, 8, 8, 8, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SNORM, 8, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SNORM, 8, 8, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 8, 8, 8, 8, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UINT, 8, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_UINT, 16, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_UINT, 32, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UINT, 8, 8, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_UINT, 16, 16, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_UINT, 32, 32, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_UINT, 32, 32, 32, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UINT, 8, 8, 8, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_UINT, 16, 16, 16, 16, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_UINT, 32, 32, 32, 32, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SINT, 8, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_SINT, 16, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_SINT, 32, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SINT, 8, 8, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_SINT, 16, 16, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_SINT, 32, 32, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_SINT, 32, 32, 32, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SINT, 8, 8, 8, 8, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_SINT, 16, 16, 16, 16, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_SINT, 32, 32, 32, 32, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 10, 10, 10, 2, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UINT, 10, 10, 10, 2, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_FLOAT, 16, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_FLOAT, 16, 16, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 16, 16, 16, 16, 0); - - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_FLOAT, 32, 32, 0, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_FLOAT, 32, 32, 32, 0, 0); - InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 32, 32, 32, 32, 0); - - 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; -} - -struct DXGIDepthStencilInfo -{ - unsigned int depthBits; - unsigned int depthOffset; - unsigned int stencilBits; - unsigned int stencilOffset; -}; - -typedef std::map DepthStencilInfoMap; -typedef std::pair DepthStencilInfoPair; - -static inline void InsertDXGIDepthStencilInfo(DepthStencilInfoMap *map, DXGI_FORMAT format, unsigned int depthBits, - unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset) -{ - DXGIDepthStencilInfo info; - info.depthBits = depthBits; - info.depthOffset = depthOffset; - info.stencilBits = stencilBits; - info.stencilOffset = stencilOffset; - - map->insert(std::make_pair(format, info)); } -static DepthStencilInfoMap BuildDepthStencilInfoMap() +constexpr VertexFormat::VertexFormat() + : conversionType(VERTEX_CONVERT_NONE), nativeFormat(DXGI_FORMAT_UNKNOWN), copyFunction(nullptr) { - DepthStencilInfoMap map; - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_TYPELESS, 16, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R16_UNORM, 16, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D16_UNORM, 16, 0, 0, 0); - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24G8_TYPELESS, 24, 0, 8, 24); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 24, 0, 8, 24); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 24, 0, 8, 24); - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_TYPELESS, 32, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT, 32, 0, 0, 0); - - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 32, 0, 8, 32); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 32, 0, 8, 32); - InsertDXGIDepthStencilInfo(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 32, 0, 8, 32); - - return map; -} - -typedef std::map DXGIFormatInfoMap; - -DXGIFormat::DXGIFormat() - : pixelBytes(0), - blockWidth(0), - blockHeight(0), - redBits(0), - greenBits(0), - blueBits(0), - alphaBits(0), - sharedBits(0), - depthBits(0), - depthOffset(0), - stencilBits(0), - stencilOffset(0), - internalFormat(GL_NONE), - componentType(GL_NONE), - mipGenerationFunction(NULL), - colorReadFunction(NULL), - 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 +constexpr VertexFormat::VertexFormat(VertexConversionType conversionTypeIn, + DXGI_FORMAT nativeFormatIn, + VertexCopyFunction copyFunctionIn) + : conversionType(conversionTypeIn), nativeFormat(nativeFormatIn), copyFunction(copyFunctionIn) { - FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); - return (iter != fastCopyFunctions.end()) ? iter->second : NULL; } -void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, - GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc, NativeMipmapGenerationSupportFunction nativeMipmapSupport) +const VertexFormat *GetVertexFormatInfo_FL_9_3(gl::VertexFormatType vertexFormatType) { - DXGIFormat info; - info.pixelBytes = pixelBits / 8; - info.blockWidth = blockWidth; - info.blockHeight = blockHeight; - - static const ColorFormatInfoMap colorInfoMap = BuildColorFormatInfoMap(); - ColorFormatInfoMap::const_iterator colorInfoIter = colorInfoMap.find(dxgiFormat); - if (colorInfoIter != colorInfoMap.end()) - { - const DXGIColorFormatInfo &colorInfo = colorInfoIter->second; - 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(); - DepthStencilInfoMap::const_iterator dsInfoIter = dsInfoMap.find(dxgiFormat); - if (dsInfoIter != dsInfoMap.end()) - { - const DXGIDepthStencilInfo &dsInfo = dsInfoIter->second; - info.depthBits = dsInfo.depthBits; - info.depthOffset = dsInfo.depthOffset; - info.stencilBits = dsInfo.stencilBits; - info.stencilOffset = dsInfo.stencilOffset; - } - - static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap(); - DXGIToESFormatMap::const_iterator dxgiToESIter = dxgiToESMap.find(dxgiFormat); - info.internalFormat = (dxgiToESIter != dxgiToESMap.end()) ? dxgiToESIter->second : GL_NONE; - - info.componentType = componentType; - - info.mipGenerationFunction = mipFunc; - info.colorReadFunction = readFunc; + // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature + // Level 10_0+. + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx - static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap(); - std::pair fastCopyIter = fastCopyMap.equal_range(dxgiFormat); - for (D3D11FastCopyMap::const_iterator i = fastCopyIter.first; i != fastCopyIter.second; i++) + switch (vertexFormatType) { - 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)); -} - -// A map to determine the pixel size and mipmap generation function of a given DXGI format -static DXGIFormatInfoMap BuildDXGIFormatInfoMap() -{ - DXGIFormatInfoMap map; - - // | 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); + // GL_BYTE -- unnormalized + case gl::VERTEX_FORMAT_SBYTE1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, + &Copy8SintTo16SintVertexData<1, 2>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, + &Copy8SintTo16SintVertexData<2, 2>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, + &Copy8SintTo16SintVertexData<3, 4>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, + &Copy8SintTo16SintVertexData<4, 4>); + return &info; + } - 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); + // GL_BYTE -- normalized + case gl::VERTEX_FORMAT_SBYTE1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, + &Copy8SnormTo16SnormVertexData<1, 2>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, + &Copy8SnormTo16SnormVertexData<2, 2>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, + &Copy8SnormTo16SnormVertexData<3, 4>); + return &info; + } + case gl::VERTEX_FORMAT_SBYTE4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, + &Copy8SnormTo16SnormVertexData<4, 4>); + return &info; + } - 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); + // GL_UNSIGNED_BYTE -- un-normalized + // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format + // table. + case gl::VERTEX_FORMAT_UBYTE1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData); + return &info; + } + case gl::VERTEX_FORMAT_UBYTE2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData); + return &info; + } - 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); + // GL_UNSIGNED_BYTE -- normalized + // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table. - 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); + // GL_UNSIGNED_BYTE -- normalized + case gl::VERTEX_FORMAT_UBYTE1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, + &CopyNativeVertexData); + return &info; + } + case gl::VERTEX_FORMAT_UBYTE2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, + &CopyNativeVertexData); + return &info; + } - 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); + // GL_SHORT -- un-normalized + // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table. + case gl::VERTEX_FORMAT_SSHORT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, + &CopyNativeVertexData); + return &info; + } - 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); + // GL_SHORT -- normalized + // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table. + case gl::VERTEX_FORMAT_SSHORT1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, + &CopyNativeVertexData); + return &info; + } - 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); + // GL_UNSIGNED_SHORT -- un-normalized + case gl::VERTEX_FORMAT_USHORT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData); + return &info; + } + case gl::VERTEX_FORMAT_USHORT2: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData); + return &info; + } + case gl::VERTEX_FORMAT_USHORT3: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, + &CopyTo32FVertexData); + return &info; + } + case gl::VERTEX_FORMAT_USHORT4: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyTo32FVertexData); + return &info; + } - // 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); + // GL_UNSIGNED_SHORT -- normalized + case gl::VERTEX_FORMAT_USHORT1_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData); + return &info; + } + case gl::VERTEX_FORMAT_USHORT2_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyTo32FVertexData); + return &info; + } + case gl::VERTEX_FORMAT_USHORT3_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, + &CopyTo32FVertexData); + return &info; + } + case gl::VERTEX_FORMAT_USHORT4_NORM: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyTo32FVertexData); + return &info; + } - // Useful formats for vertex buffers - 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); + // GL_FIXED + // TODO: Add test to verify that this works correctly. + // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table. + case gl::VERTEX_FORMAT_FIXED1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &Copy32FixedTo32FVertexData<1, 2>); + return &info; + } - return map; -} + // GL_FLOAT + // TODO: Add test to verify that this works correctly. + // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table. + case gl::VERTEX_FORMAT_FLOAT1: + { + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, + &CopyNativeVertexData); + return &info; + } -const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format) -{ - static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap(); - DXGIFormatInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - return iter->second; - } - else - { - static DXGIFormat defaultInfo; - return defaultInfo; + default: + return nullptr; } } -typedef std::map D3D11VertexFormatInfoMap; -typedef std::pair D3D11VertexFormatPair; - -VertexFormat::VertexFormat() - : conversionType(VERTEX_CONVERT_NONE), - nativeFormat(DXGI_FORMAT_UNKNOWN), - copyFunction(NULL) -{ -} - -VertexFormat::VertexFormat(VertexConversionType conversionTypeIn, - DXGI_FORMAT nativeFormatIn, - VertexCopyFunction copyFunctionIn) - : conversionType(conversionTypeIn), - nativeFormat(nativeFormatIn), - copyFunction(copyFunctionIn) -{ -} - -static void AddVertexFormatInfo(D3D11VertexFormatInfoMap *map, - GLenum inputType, - GLboolean normalized, - GLuint componentCount, - VertexConversionType conversionType, - DXGI_FORMAT nativeFormat, - VertexCopyFunction copyFunction) -{ - gl::VertexFormatType formatType = gl::GetVertexFormatType(inputType, normalized, componentCount, false); - - VertexFormat info; - info.conversionType = conversionType; - info.nativeFormat = nativeFormat; - info.copyFunction = copyFunction; - - map->insert(D3D11VertexFormatPair(formatType, info)); -} - -static D3D11VertexFormatInfoMap BuildD3D11_FL9_3VertexFormatInfoOverrideMap() -{ - // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature Level 10_0+. - // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx - - D3D11VertexFormatInfoMap map; - - // GL_BYTE -- unnormalized - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<1, 2>); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<2, 2>); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<3, 4>); - AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<4, 4>); - - // GL_BYTE -- normalized - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<1, 2>); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<2, 2>); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<3, 4>); - AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<4, 4>); - - // GL_UNSIGNED_BYTE -- unnormalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData); - // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format table. - - // GL_UNSIGNED_BYTE -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData); - // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table. - - // GL_SHORT -- unnormalized - AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData); - // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table. - - // GL_SHORT -- normalized - AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData); - // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table. - - // GL_UNSIGNED_SHORT -- unnormalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); - - // GL_UNSIGNED_SHORT -- normalized - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData); - AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData); - - // GL_FIXED - // TODO: Add test to verify that this works correctly. - AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<1, 2>); - // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table. - - // GL_FLOAT - // TODO: Add test to verify that this works correctly. - AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData); - // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table. - - return map; -} - const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D3D_FEATURE_LEVEL featureLevel) { if (featureLevel == D3D_FEATURE_LEVEL_9_3) { - static const D3D11VertexFormatInfoMap vertexFormatMapFL9_3Override = - BuildD3D11_FL9_3VertexFormatInfoOverrideMap(); - - // First see if the format has a special mapping for FL9_3 - auto iter = vertexFormatMapFL9_3Override.find(vertexFormatType); - if (iter != vertexFormatMapFL9_3Override.end()) + const VertexFormat *result = GetVertexFormatInfo_FL_9_3(vertexFormatType); + if (result) { - return iter->second; + return *result; } } @@ -589,354 +419,418 @@ const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D // GL_BYTE -- un-normalized case gl::VERTEX_FORMAT_SBYTE1: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, + &CopyNativeVertexData); return info; } // GL_BYTE -- normalized case gl::VERTEX_FORMAT_SBYTE1_NORM: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, + &CopyNativeVertexData); return info; } // GL_UNSIGNED_BYTE -- un-normalized case gl::VERTEX_FORMAT_UBYTE1: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, + &CopyNativeVertexData); return info; } // GL_UNSIGNED_BYTE -- normalized case gl::VERTEX_FORMAT_UBYTE1_NORM: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, + &CopyNativeVertexData); return info; } // GL_SHORT -- un-normalized case gl::VERTEX_FORMAT_SSHORT1: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, + &CopyNativeVertexData); return info; } // GL_SHORT -- normalized case gl::VERTEX_FORMAT_SSHORT1_NORM: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, + &CopyNativeVertexData); return info; } // GL_UNSIGNED_SHORT -- un-normalized case gl::VERTEX_FORMAT_USHORT1: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, + &CopyNativeVertexData); return info; } // GL_UNSIGNED_SHORT -- normalized case gl::VERTEX_FORMAT_USHORT1_NORM: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, + &CopyNativeVertexData); return info; } // GL_INT -- un-normalized case gl::VERTEX_FORMAT_SINT1: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, + &CopyNativeVertexData); return info; } // GL_INT -- normalized case gl::VERTEX_FORMAT_SINT1_NORM: { - static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyTo32FVertexData); return info; } // GL_UNSIGNED_INT -- un-normalized case gl::VERTEX_FORMAT_UINT1: { - static const VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, + &CopyNativeVertexData); return info; } // GL_UNSIGNED_INT -- normalized case gl::VERTEX_FORMAT_UINT1_NORM: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, 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); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &CopyTo32FVertexData); return info; } // GL_FIXED case gl::VERTEX_FORMAT_FIXED1: { - static const VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1, 1>); + static constexpr 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>); + static constexpr 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>); + static constexpr 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>); + static constexpr VertexFormat info(VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, + &Copy32FixedTo32FVertexData<4, 4>); return info; } // GL_HALF_FLOAT case gl::VERTEX_FORMAT_HALF1: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, + &CopyNativeVertexData); return info; } // GL_FLOAT case gl::VERTEX_FORMAT_FLOAT1: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, + &CopyNativeVertexData); return info; } @@ -947,157 +841,183 @@ const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D // GL_BYTE case gl::VERTEX_FORMAT_SBYTE1_INT: { - static const VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr 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); + static constexpr VertexFormat info(VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, + &CopyNativeVertexData); return info; } default: { - static const VertexFormat info; + static constexpr VertexFormat info; return info; } } } -} +} // namespace d3d11 -} +} // namespace rx 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 7b97527140..883d338377 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h @@ -15,6 +15,7 @@ #include "common/platform.h" #include "libANGLE/angletypes.h" #include "libANGLE/formatutils.h" +#include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/d3d/formatutilsD3D.h" namespace rx @@ -24,58 +25,47 @@ struct Renderer11DeviceCaps; namespace d3d11 { -typedef std::map, ColorCopyFunction> FastCopyFunctionMap; -typedef bool (*NativeMipmapGenerationSupportFunction)(D3D_FEATURE_LEVEL); +// A texture might be stored as DXGI_FORMAT_R16_TYPELESS but store integer components, +// which are accessed through an DXGI_FORMAT_R16_SINT view. It's easy to write code which queries +// information about the wrong format. Therefore, use of this should be avoided where possible. -struct DXGIFormat +bool SupportsMipGen(DXGI_FORMAT dxgiFormat, D3D_FEATURE_LEVEL featureLevel); + +struct DXGIFormatSize { - DXGIFormat(); + DXGIFormatSize(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight); GLuint pixelBytes; GLuint blockWidth; GLuint blockHeight; - - GLuint redBits; - GLuint greenBits; - GLuint blueBits; - GLuint alphaBits; - GLuint sharedBits; - - GLuint depthBits; - GLuint depthOffset; - GLuint stencilBits; - GLuint stencilOffset; - - GLenum internalFormat; - GLenum componentType; - - MipGenerationFunction mipGenerationFunction; - ColorReadFunction colorReadFunction; - - FastCopyFunctionMap fastCopyFunctions; - - NativeMipmapGenerationSupportFunction nativeMipmapSupport; - - ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; }; -const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format); +const DXGIFormatSize &GetDXGIFormatSizeInfo(DXGI_FORMAT format); -struct VertexFormat +struct VertexFormat : private angle::NonCopyable { - VertexFormat(); - VertexFormat(VertexConversionType conversionType, - DXGI_FORMAT nativeFormat, - VertexCopyFunction copyFunction); + constexpr VertexFormat(); + constexpr VertexFormat(VertexConversionType conversionType, + DXGI_FORMAT nativeFormat, + VertexCopyFunction copyFunction); VertexConversionType conversionType; DXGI_FORMAT nativeFormat; VertexCopyFunction copyFunction; }; + const VertexFormat &GetVertexFormatInfo(gl::VertexFormatType vertexFormatType, D3D_FEATURE_LEVEL featureLevel); +// Auto-generated in dxgi_format_map_autogen.cpp. +GLenum GetComponentType(DXGI_FORMAT dxgiFormat); + } // namespace d3d11 +namespace d3d11_angle +{ +const angle::Format &GetFormat(DXGI_FORMAT dxgiFormat); +} + } // 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 deleted file mode 100644 index e69de29bb2..0000000000 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 deleted file mode 100644 index adb20a5e60..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// -// 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 deleted file mode 100644 index 2d538e1d82..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/internal_format_initializer_table.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// 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 deleted file mode 100644 index c85393e06b..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json +++ /dev/null @@ -1,1116 +0,0 @@ -{ - "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 deleted file mode 100644 index b17062f68d..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table.h +++ /dev/null @@ -1,31 +0,0 @@ -// -// 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 deleted file mode 100644 index acb48b9573..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp +++ /dev/null @@ -1,2098 +0,0 @@ -// 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 a1175db9af..d059b36120 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 @@ -12,369 +12,414 @@ #include #include "common/debug.h" -#include "libANGLE/formatutils.h" +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/Program.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/d3d/BufferD3D.h" +#include "libANGLE/renderer/d3d/FramebufferD3D.h" +#include "libANGLE/renderer/d3d/IndexBuffer.h" +#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h" +#include "libANGLE/renderer/d3d/d3d11/Renderer11.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/d3d/WorkaroundsD3D.h" - -#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY -# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2 -#endif -#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT -# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1 -#endif -#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT -# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4 -#endif -#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT -# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535 -#endif -#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT -# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575 -#endif -#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION -# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512 -#endif -#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION -# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096 -#endif -#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION -# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048 -#endif -#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION -# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256 -#endif -#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION -# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096 -#endif -#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION -# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384 -#endif -#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION -# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048 -#endif -#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION -# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048 -#endif -#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP -# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32 -#endif -#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP -# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32 -#endif -#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT -# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32 -#endif -#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT -# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32 -#endif -#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT -# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 -#endif -#ifndef D3D11_SO_BUFFER_SLOT_COUNT -# define D3D11_SO_BUFFER_SLOT_COUNT 4 -#endif -#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 -#endif -#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT -# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16 -#endif -#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8 -#endif -#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE -# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7 -#endif -#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT -# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 -#endif -#ifndef D3D11_PS_INPUT_REGISTER_COUNT -# define D3D11_PS_INPUT_REGISTER_COUNT 32 -#endif -#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT -# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32 -#endif -#if defined(ANGLE_MINGW32_COMPAT) -static const IID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 }; -#endif +#include "libANGLE/renderer/driver_utils.h" +#include "platform/Platform.h" +#include "platform/WorkaroundsD3D.h" namespace rx { -namespace gl_d3d11 +namespace d3d11_gl { - -D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) +namespace { - D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; +// Standard D3D sample positions from +// https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218.aspx +using SamplePositionsArray = std::array; +static constexpr std::array kSamplePositions = { + {{{0.5f, 0.5f}}, + {{0.75f, 0.75f, 0.25f, 0.25f}}, + {{0.375f, 0.125f, 0.875f, 0.375f, 0.125f, 0.625f, 0.625f, 0.875f}}, + {{0.5625f, 0.3125f, 0.4375f, 0.6875f, 0.8125f, 0.5625f, 0.3125f, 0.1875f, 0.1875f, 0.8125f, + 0.0625f, 0.4375f, 0.6875f, 0.9375f, 0.9375f, 0.0625f}}, + {{0.5625f, 0.5625f, 0.4375f, 0.3125f, 0.3125f, 0.625f, 0.75f, 0.4375f, + 0.1875f, 0.375f, 0.625f, 0.8125f, 0.8125f, 0.6875f, 0.6875f, 0.1875f, + 0.375f, 0.875f, 0.5f, 0.0625f, 0.25f, 0.125f, 0.125f, 0.75f, + 0.0f, 0.5f, 0.9375f, 0.25f, 0.875f, 0.9375f, 0.0625f, 0.0f}}}}; - switch (glBlend) +// 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) { - case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break; - case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break; - case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break; - case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break; - case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break; - case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break; - case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break; - case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break; - case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break; - case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; - case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; - case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break; - default: UNREACHABLE(); } - return d3dBlend; -} + bool query(DXGI_FORMAT dxgiFormat, UINT supportMask) + { + if (dxgiFormat == DXGI_FORMAT_UNKNOWN) + return false; -D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) -{ - D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; + auto dxgiSupport = d3d11::GetDXGISupport(dxgiFormat, mFeatureLevel); - switch (glBlendOp) - { - case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break; - case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break; - case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break; - case GL_MIN: d3dBlendOp = D3D11_BLEND_OP_MIN; break; - case GL_MAX: d3dBlendOp = D3D11_BLEND_OP_MAX; break; - default: UNREACHABLE(); + 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" << std::hex << dxgiFormat; + } + } + + return ((supportedBits & supportMask) == supportMask); } - return d3dBlendOp; -} + private: + ID3D11Device *mDevice; + D3D_FEATURE_LEVEL mFeatureLevel; +}; -UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) +gl::TextureCaps GenerateTextureFormatCaps(gl::Version maxClientVersion, + GLenum internalFormat, + ID3D11Device *device, + const Renderer11DeviceCaps &renderer11DeviceCaps) { - UINT8 mask = 0; - if (red) + gl::TextureCaps textureCaps; + + DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel); + const d3d11::Format &formatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); + + const gl::InternalFormat &internalFormatInfo = gl::GetSizedInternalFormatInfo(internalFormat); + + UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D; + if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0) { - mask |= D3D11_COLOR_WRITE_ENABLE_RED; + texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE; + if (maxClientVersion.major > 2) + { + texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D; + } } - if (green) + + 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)); + + DXGI_FORMAT renderFormat = DXGI_FORMAT_UNKNOWN; + if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) { - mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; + renderFormat = formatInfo.dsvFormat; } - if (blue) + else if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) { - mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; + renderFormat = formatInfo.rtvFormat; } - if (alpha) + if (renderFormat != DXGI_FORMAT_UNKNOWN && + support.query(renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) { - mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; - } - return mask; -} - -D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode) -{ - D3D11_CULL_MODE cull = D3D11_CULL_NONE; + // Assume 1x + textureCaps.sampleCounts.insert(1); - if (cullEnabled) - { - switch (cullMode) + for (unsigned int sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; + sampleCount *= 2) { - case GL_FRONT: cull = D3D11_CULL_FRONT; break; - case GL_BACK: cull = D3D11_CULL_BACK; break; - case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break; - default: UNREACHABLE(); + UINT qualityCount = 0; + if (SUCCEEDED(device->CheckMultisampleQualityLevels(renderFormat, sampleCount, + &qualityCount))) + { + // Assume we always support lower sample counts + if (qualityCount == 0) + { + break; + } + textureCaps.sampleCounts.insert(sampleCount); + } } } - else - { - cull = D3D11_CULL_NONE; - } - return cull; + return textureCaps; } -D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) +bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) { - D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; - switch (comparison) + switch (featureLevel) { - case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break; - case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break; - case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break; - case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break; - case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break; - case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break; - case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break; - case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break; - default: UNREACHABLE(); - } + 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 true; - return d3dComp; + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } } -D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) +float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) { - return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_MAX_MAXANISOTROPY; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_MAX_MAXANISOTROPY; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return 16; + + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + + default: + UNREACHABLE(); + return 0; + } } -UINT8 ConvertStencilMask(GLuint stencilmask) +bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) { - return static_cast(stencilmask); + 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 true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx + // ID3D11Device::CreateQuery + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return true; + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } } -D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) +bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) { - D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx + // ID3D11Device::CreateQuery - switch (stencilOp) + switch (featureLevel) { - case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break; - case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break; - case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break; - case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break; - case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break; - case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break; - case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break; - case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break; - default: UNREACHABLE(); - } + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return true; - return d3dStencilOp; + default: + UNREACHABLE(); + return false; + } } -D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode) +bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) { - bool comparison = comparisonMode != GL_NONE; + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx + // ID3D11Device::CreateInputLayout - if (maxAnisotropy > 1.0f) - { - return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast(comparison)); - } - else + switch (featureLevel) { - D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; - D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; - switch (minFilter) - { - case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break; - case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break; - default: UNREACHABLE(); - } + 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 true; + + // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be + // instanced. + // D3D9 has a similar restriction, where stream 0 must not be instanced. + // This restriction can be worked around by remapping any non-instanced slot to slot + // 0. + // This works because HLSL uses shader semantics to match the vertex inputs to the + // elements in the input layout, rather than the slots. + // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3 + // doesn't support OpenGL ES 3.0 + case D3D_FEATURE_LEVEL_9_3: + return true; - D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; - switch (magFilter) - { - case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break; - default: UNREACHABLE(); - } + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; - return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, static_cast(comparison)); + default: + UNREACHABLE(); + return false; } } -D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) +bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel) { - switch (wrap) + switch (featureLevel) { - case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP; - case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP; - case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR; - default: UNREACHABLE(); - } + 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 true; - return D3D11_TEXTURE_ADDRESS_WRAP; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; + } } -D3D11_QUERY ConvertQueryType(GLenum queryType) +bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel) { - switch (queryType) + switch (featureLevel) { - 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; + 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 true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; } } -} // namespace gl_d3d11 - -namespace d3d11_gl +bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) { + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that + // shader model + // ps_2_x is required for the ddx (and other derivative functions). -namespace -{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that + // feature level + // 9.3 supports shader model ps_2_x. -// 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) + 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: + case D3D_FEATURE_LEVEL_9_3: + return true; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return false; + + default: + UNREACHABLE(); + return false; } +} - bool query(DXGI_FORMAT dxgiFormat, UINT supportMask) +bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) { - if (dxgiFormat == DXGI_FORMAT_UNKNOWN) + 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 true; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; - auto dxgiSupport = d3d11::GetDXGISupport(dxgiFormat, mFeatureLevel); + default: + UNREACHABLE(); + return false; + } +} - UINT supportedBits = dxgiSupport.alwaysSupportedFlags; +size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx + // ID3D11Device::CreateInputLayout - 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); - } - } + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; - return ((supportedBits & supportMask) == supportMask); - } + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; - private: - ID3D11Device *mDevice; - D3D_FEATURE_LEVEL mFeatureLevel; -}; + case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; -} // anonymous namespace + default: + UNREACHABLE(); + return 0; + } +} -unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: - return 0; + return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: - return 3; // dx_ViewAdjust, dx_ViewCoords and dx_ViewScale + return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; default: UNREACHABLE(); @@ -382,20 +427,23 @@ unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) } } -unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { case D3D_FEATURE_LEVEL_11_1: case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURECUBE_DIMENSION; + case D3D_FEATURE_LEVEL_10_1: case D3D_FEATURE_LEVEL_10_0: - return 0; + return D3D10_REQ_TEXTURECUBE_DIMENSION; case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION; case D3D_FEATURE_LEVEL_9_2: case D3D_FEATURE_LEVEL_9_1: - return 3; + return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION; default: UNREACHABLE(); @@ -403,757 +451,829 @@ unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel) } } -GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximum2DTextureArraySize(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 3; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 2; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + + default: + UNREACHABLE(); + return 0; } } -static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum internalFormat, ID3D11Device *device, const Renderer11DeviceCaps &renderer11DeviceCaps) +size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) { - gl::TextureCaps textureCaps; + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - DXGISupportHelper support(device, renderer11DeviceCaps.featureLevel); - const d3d11::TextureFormat &formatInfo = - d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - UINT texSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D; - if (internalFormatInfo.depthBits == 0 && internalFormatInfo.stencilBits == 0) + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) { - texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURECUBE; - if (maxClientVersion > 2) - { - texSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D; - } + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_VIEWPORT_BOUNDS_MAX; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_VIEWPORT_BOUNDS_MAX; + + // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum + // texture sizes + case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: + UNREACHABLE(); + return 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)); +size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) +{ + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since + // that's what's + // returned from glGetInteger + static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, + "Unexpected D3D11 constant value."); + static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, + "Unexpected D3D11 constant value."); - if (support.query(formatInfo.renderFormat, D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) + switch (featureLevel) { - // Assume 1x - textureCaps.sampleCounts.insert(1); + 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 std::numeric_limits::max(); - for (unsigned int sampleCount = 2; sampleCount <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; - sampleCount *= 2) - { - UINT 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); - } - } - } + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; - return textureCaps; + default: + UNREACHABLE(); + return 0; + } } -static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) { + // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since + // that's what's + // returned from glGetInteger + static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); + 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 true; + 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 std::numeric_limits::max(); - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return 0; } } -static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_STANDARD_VERTEX_ELEMENT_COUNT; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_MAX_MAXANISOTROPY; + case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT; + case D3D_FEATURE_LEVEL_10_0: + return D3D10_STANDARD_VERTEX_ELEMENT_COUNT; - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: return 16; + // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + // "Max Input Slots" + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 16; - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + default: + UNREACHABLE(); + return 0; + } +} + +size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + + // 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 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel); - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumVertexUniformBlocks(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 true; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: return true; - case D3D_FEATURE_LEVEL_9_1: return false; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; + + // Uniform blocks not supported on D3D11 Feature Level 9 + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return 0; } } -static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) +size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) { - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + // According to The OpenGL ES Shading Language specifications + // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21) + // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord) + // which are statically used in the shader should be included in the variable packing + // algorithm. + // Therefore, we should not reserve output vectors for them. 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: - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return true; + // 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. + 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 2; + + // Just reserve dx_Position on Feature Level 9, since we don't ever need to output + // gl_Position. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 1; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return 0; } } -static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) { - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT, + "Unexpected D3D11 constant value."); 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 true; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); - // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be instanced. - // D3D9 has a similar restriction, where stream 0 must not be instanced. - // This restriction can be worked around by remapping any non-instanced slot to slot 0. - // This works because HLSL uses shader semantics to match the vertex inputs to the elements in the input layout, rather than the slots. - // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3 doesn't support OpenGL ES 3.0 - case D3D_FEATURE_LEVEL_9_3: return true; + case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_10_0: + return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; + // Use Shader Model 2.X limits + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 8 - GetReservedVertexOutputVectors(featureLevel); - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return 0; } } -static bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumVertexTextureUnits(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 true; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; + // Vertex textures not supported on D3D11 Feature Level 9 according to + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx + // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return 0; } } -static bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) { + // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass 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 true; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; - - default: UNREACHABLE(); return false; - } -} - -static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) -{ - // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model - // ps_2_x is required for the ddx (and other derivative functions). + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level - // 9.3 supports shader model ps_2_x. + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - 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: - case D3D_FEATURE_LEVEL_9_3: return true; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; + // 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 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel); - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return 0; } } -static bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumPixelUniformBlocks(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 true; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; + // Uniform blocks not supported on D3D11 Feature Level 9 + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return false; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) { - // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout - switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; + // Use Shader Model 2.X limits + case D3D_FEATURE_LEVEL_9_3: + return 8 - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 8 - GetReservedVertexOutputVectors(featureLevel); - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx + // ID3D11DeviceContext::PSSetShaderResources + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 16; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) +std::array GetMaxComputeWorkGroupCount(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_TEXTURECUBE_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURECUBE_DIMENSION; - - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION; - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return {{D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION, + D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION, + D3D11_CS_DISPATCH_MAX_THREAD_GROUPS_PER_DIMENSION}}; + break; + default: + return {{0, 0, 0}}; } } -static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) +std::array GetMaxComputeWorkGroupSize(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_ARRAY_AXIS_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return {{D3D11_CS_THREAD_GROUP_MAX_X, D3D11_CS_THREAD_GROUP_MAX_Y, + D3D11_CS_THREAD_GROUP_MAX_Z}}; + break; + default: + return {{0, 0, 0}}; } } -static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_CS_THREAD_GROUP_MAX_THREADS_PER_GROUP; + default: + return 0; } } -static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX; - - // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum texture sizes - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + default: + return 0; } } -static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumComputeUniformBlocks(D3D_FEATURE_LEVEL featureLevel) { - // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's - // returned from glGetInteger - static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); - static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); - 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 std::numeric_limits::max(); - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - + d3d11::RESERVED_CONSTANT_BUFFER_SLOT_COUNT; + default: + return 0; } } -static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumComputeTextureUnits(D3D_FEATURE_LEVEL featureLevel) { - // D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's - // returned from glGetInteger - static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); - static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value."); - 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 std::numeric_limits::max(); - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: return D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT; - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT; - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + default: + return 0; } } -static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumImageUnits(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - 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; - case D3D_FEATURE_LEVEL_10_0: return D3D10_STANDARD_VERTEX_ELEMENT_COUNT; - - // From http://http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx "Max Input Slots" - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 16; - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + // TODO(xinghua.cao@intel.com): Get a more accurate limit. For now using + // the minimum requirement for GLES 3.1. + return 4; + default: + return 0; } } -static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumComputeImageUniforms(D3D_FEATURE_LEVEL featureLevel) { - // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; - - // 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 - d3d11_gl::GetReservedVertexUniformVectors(featureLevel); - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + // TODO(xinghua.cao@intel.com): Get a more accurate limit. For now using + // the minimum requirement for GLES 3.1. + return 4; + default: + return 0; } } -static size_t GetReservedVertexUniformBuffers() -{ - // Reserve one buffer for the application uniforms, and one for driver uniforms - return 2; -} - -static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers(); + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; - // Uniform blocks not supported on D3D11 Feature Level 9 - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; + // Sampling functions with offsets are not available below shader model 4.0. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) { - // According to The OpenGL ES Shading Language specifications - // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21) - // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord) - // which are statically used in the shader should be included in the variable packing algorithm. - // Therefore, we should not reserve output vectors for them. - switch (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. - 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 2; + case D3D_FEATURE_LEVEL_11_1: + 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; - // Just reserve dx_Position on Feature Level 9, since we don't ever need to output gl_Position. - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 1; + // Sampling functions with offsets are not available below shader model 4.0. + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } - - return 1; } -static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) { - static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT, "Unexpected D3D11 constant value."); + // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum + // size of + // any buffer that could be allocated. + + const size_t bytesPerComponent = 4 * sizeof(float); switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); - case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; - // Use Shader Model 2.X limits - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel); + // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx + // remarks section + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 4096 * bytesPerComponent; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_SO_BUFFER_SLOT_COUNT; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; + case D3D_FEATURE_LEVEL_10_1: + return D3D10_1_SO_BUFFER_SLOT_COUNT; + case D3D_FEATURE_LEVEL_10_0: + return D3D10_SO_BUFFER_SLOT_COUNT; - // Vertex textures not supported on D3D11 Feature Level 9 according to - // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx - // ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel) { - // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + 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 1024; // D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return GetMaximumVertexOutputVectors(featureLevel) * 4; - // 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 - d3d11_gl::GetReservedFragmentUniformVectors(featureLevel); + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static size_t GetReservedPixelUniformBuffers() -{ - // Reserve one buffer for the application uniforms, and one for driver uniforms - return 2; -} - -static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return GetMaximumStreamOutputInterleavedComponents(featureLevel) / + GetMaximumStreamOutputBuffers(featureLevel); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers(); + // D3D 10 and 10.1 only allow one output per output slot if an output slot other + // than zero is used. + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 4; - // Uniform blocks not supported on D3D11 Feature Level 9 - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel) +size_t GetMaximumRenderToBufferWindowSize(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel); + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return D3D10_REQ_RENDER_TO_BUFFER_WINDOW_WIDTH; - // Use Shader Model 2.X limits - case D3D_FEATURE_LEVEL_9_3: return 8 - GetReservedVertexOutputVectors(featureLevel); - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel); + // REQ_RENDER_TO_BUFFER_WINDOW_WIDTH not supported on D3D11 Feature Level 9, + // use the maximum texture sizes + case D3D_FEATURE_LEVEL_9_3: + return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel) +IntelDriverVersion GetIntelDriverVersion(const Optional driverVersion) { - switch (featureLevel) - { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT; + if (!driverVersion.valid()) + return IntelDriverVersion(0); - // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx ID3D11DeviceContext::PSSetShaderResources - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 16; - - default: UNREACHABLE(); return 0; - } + // According to http://www.intel.com/content/www/us/en/support/graphics-drivers/000005654.html, + // only the fourth part is necessary since it stands for the driver specific unique version + // number. + WORD part = LOWORD(driverVersion.value().LowPart); + return IntelDriverVersion(part); } -static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +} // anonymous namespace + +unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE; + 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; - // Sampling functions with offsets are not available below shader model 4.0. - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: 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; + default: + UNREACHABLE(); + return 0; } } -static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel) +unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - 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; + 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; - // Sampling functions with offsets are not available below shader model 4.0. - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: 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; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel) +gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel) { - // Returns a size_t despite the limit being a GLuint64 because size_t is the maximum size of - // any buffer that could be allocated. - - const size_t bytesPerComponent = 4 * sizeof(float); - switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; - - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return gl::Version(3, 1); + case D3D_FEATURE_LEVEL_10_1: + return gl::Version(3, 0); - // Limits from http://msdn.microsoft.com/en-us/library/windows/desktop/ff476501.aspx remarks section - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 4096 * bytesPerComponent; + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return gl::Version(2, 0); - default: UNREACHABLE(); return 0; + default: + UNREACHABLE(); + return gl::Version(0, 0); } } -static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel) +unsigned int GetMaxViewportAndScissorRectanglesPerPipeline(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - 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; - case D3D_FEATURE_LEVEL_10_0: return D3D10_SO_BUFFER_SLOT_COUNT; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 1; + default: + UNREACHABLE(); + return 0; } } -static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL featureLevel) +bool IsMultiviewSupported(D3D_FEATURE_LEVEL featureLevel) { + // The ANGLE_multiview extension can always be supported in D3D11 through geometry shaders. 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 GetMaximumVertexOutputVectors(featureLevel) * 4; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return true; + default: + return false; } } -static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL featureLevel) +unsigned int GetMaxSampleMaskWords(D3D_FEATURE_LEVEL featureLevel) { switch (featureLevel) { - case D3D_FEATURE_LEVEL_11_1: - case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) / - GetMaximumStreamOutputBuffers(featureLevel); - - - // D3D 10 and 10.1 only allow one output per output slot if an output slot other than zero is used. - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return 4; - - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return 0; - - default: UNREACHABLE(); return 0; + // D3D10+ only allows 1 sample mask. + 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 1u; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0u; + default: + UNREACHABLE(); + return 0u; } } void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations) { - 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) + for (GLenum internalFormat : allFormats) { - gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device, renderer11DeviceCaps); - textureCapsMap->insert(*internalFormat, textureCaps); - - maxSamples = std::max(maxSamples, textureCaps.getMaxSamples()); + gl::TextureCaps textureCaps = GenerateTextureFormatCaps( + GetMaximumClientVersion(featureLevel), internalFormat, device, renderer11DeviceCaps); + textureCapsMap->insert(internalFormat, textureCaps); - if (gl::GetInternalFormatInfo(*internalFormat).compressed) + if (gl::GetSizedInternalFormatInfo(internalFormat).compressed) { - caps->compressedTextureFormats.push_back(*internalFormat); + caps->compressedTextureFormats.push_back(internalFormat); } } @@ -1226,6 +1346,14 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons caps->maxVertexTextureImageUnits = static_cast(GetMaximumVertexTextureUnits(featureLevel)); + // Vertex Attribute Bindings are emulated on D3D11. + caps->maxVertexAttribBindings = caps->maxVertexAttributes; + // Experimental testing confirmed there is no explicit limit on maximum buffer offset in D3D11. + caps->maxVertexAttribRelativeOffset = std::numeric_limits::max(); + // Experimental testing confirmed 2048 is the maximum stride that D3D11 can support on all + // platforms. + caps->maxVertexAttribStride = 2048; + // Fragment shader limits caps->maxFragmentUniformComponents = static_cast(GetMaximumPixelUniformVectors(featureLevel)) * 4; @@ -1239,108 +1367,504 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, cons caps->minProgramTexelOffset = GetMinimumTexelOffset(featureLevel); caps->maxProgramTexelOffset = GetMaximumTexelOffset(featureLevel); - // Aggregate shader limits - caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; - caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel); + // Compute shader limits + caps->maxComputeWorkGroupCount = GetMaxComputeWorkGroupCount(featureLevel); + caps->maxComputeWorkGroupSize = GetMaxComputeWorkGroupSize(featureLevel); + caps->maxComputeWorkGroupInvocations = + static_cast(GetMaxComputeWorkGroupInvocations(featureLevel)); + caps->maxComputeUniformComponents = + static_cast(GetMaximumComputeUniformVectors(featureLevel)) * 4; + caps->maxComputeUniformBlocks = + static_cast(GetMaximumComputeUniformBlocks(featureLevel)); + caps->maxComputeTextureImageUnits = + static_cast(GetMaximumComputeTextureUnits(featureLevel)); + caps->maxImageUnits = static_cast(GetMaximumImageUnits(featureLevel)); + caps->maxComputeImageUniforms = + static_cast(GetMaximumComputeImageUniforms(featureLevel)); + + // Aggregate shader limits + caps->maxUniformBufferBindings = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks; + caps->maxUniformBlockSize = GetMaximumConstantBufferSize(featureLevel); + + // TODO(oetuaho): Get a more accurate limit. For now using the minimum requirement for GLES 3.1. + caps->maxUniformLocations = 1024; + + // 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->maxCombinedComputeUniformComponents = + static_cast(caps->maxComputeUniformBlocks * (caps->maxUniformBlockSize / 4) + + caps->maxComputeUniformComponents); + caps->maxVaryingComponents = + static_cast(GetMaximumVertexOutputVectors(featureLevel)) * 4; + caps->maxVaryingVectors = static_cast(GetMaximumVertexOutputVectors(featureLevel)); + caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; + + // Transform feedback limits + caps->maxTransformFeedbackInterleavedComponents = + static_cast(GetMaximumStreamOutputInterleavedComponents(featureLevel)); + caps->maxTransformFeedbackSeparateAttributes = + static_cast(GetMaximumStreamOutputBuffers(featureLevel)); + caps->maxTransformFeedbackSeparateComponents = + static_cast(GetMaximumStreamOutputSeparateComponents(featureLevel)); + + // Defer the computation of multisample limits to Context::updateCaps() where max*Samples values + // are determined according to available sample counts for each individual format. + caps->maxSamples = std::numeric_limits::max(); + caps->maxColorTextureSamples = std::numeric_limits::max(); + caps->maxDepthTextureSamples = std::numeric_limits::max(); + caps->maxIntegerSamples = std::numeric_limits::max(); + + // Sample mask words limits + caps->maxSampleMaskWords = GetMaxSampleMaskWords(featureLevel); + + // Framebuffer limits + caps->maxFramebufferSamples = std::numeric_limits::max(); + caps->maxFramebufferWidth = + static_cast(GetMaximumRenderToBufferWindowSize(featureLevel)); + caps->maxFramebufferHeight = caps->maxFramebufferWidth; + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = true; + extensions->mapBuffer = true; + extensions->mapBufferRange = true; + extensions->textureNPOT = GetNPOTTextureSupport(featureLevel); + extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1; + extensions->textureStorage = true; + extensions->textureFilterAnisotropic = true; + extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel); + extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel); + extensions->fence = GetEventQuerySupport(featureLevel); + extensions->disjointTimerQuery = true; + extensions->queryCounterBitsTimeElapsed = 64; + extensions->queryCounterBitsTimestamp = + 0; // Timestamps cannot be supported due to D3D11 limitations + extensions->robustness = true; + // Direct3D guarantees to return zero for any resource that is accessed out of bounds. + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ff476332(v=vs.85).aspx + // and https://msdn.microsoft.com/en-us/library/windows/desktop/ff476900(v=vs.85).aspx + extensions->robustBufferAccessBehavior = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel); + extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel); + extensions->instancedArrays = GetInstancingSupport(featureLevel); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); + extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel); + extensions->fragDepth = true; + extensions->multiview = IsMultiviewSupported(featureLevel); + if (extensions->multiview) + { + extensions->maxViews = + std::min(static_cast(gl::IMPLEMENTATION_ANGLE_MULTIVIEW_MAX_VIEWS), + std::min(static_cast(GetMaximum2DTextureArraySize(featureLevel)), + GetMaxViewportAndScissorRectanglesPerPipeline(featureLevel))); + } + 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->eglImageExternal = true; + extensions->eglImageExternalEssl3 = true; + extensions->eglStreamConsumerExternal = true; + extensions->unpackSubimage = true; + extensions->packSubimage = true; + extensions->lossyETCDecode = true; + extensions->syncQuery = GetEventQuerySupport(featureLevel); + extensions->copyTexture = true; + extensions->copyCompressedTexture = 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 +} + +void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy) +{ + size_t indexKey = static_cast(ceil(log(sampleCount))); + ASSERT(indexKey < kSamplePositions.size() && + (2 * index + 1) < kSamplePositions[indexKey].size()); + + xy[0] = kSamplePositions[indexKey][2 * index]; + xy[1] = kSamplePositions[indexKey][2 * index + 1]; +} + +} // namespace d3d11_gl + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) +{ + D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; + + switch (glBlend) + { + case GL_ZERO: + d3dBlend = D3D11_BLEND_ZERO; + break; + case GL_ONE: + d3dBlend = D3D11_BLEND_ONE; + break; + case GL_SRC_COLOR: + d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); + break; + case GL_ONE_MINUS_SRC_COLOR: + d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); + break; + case GL_DST_COLOR: + d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); + break; + case GL_ONE_MINUS_DST_COLOR: + d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); + break; + case GL_SRC_ALPHA: + d3dBlend = D3D11_BLEND_SRC_ALPHA; + break; + case GL_ONE_MINUS_SRC_ALPHA: + d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; + break; + case GL_DST_ALPHA: + d3dBlend = D3D11_BLEND_DEST_ALPHA; + break; + case GL_ONE_MINUS_DST_ALPHA: + d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; + break; + case GL_CONSTANT_COLOR: + d3dBlend = D3D11_BLEND_BLEND_FACTOR; + break; + case GL_ONE_MINUS_CONSTANT_COLOR: + d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; + break; + case GL_CONSTANT_ALPHA: + d3dBlend = D3D11_BLEND_BLEND_FACTOR; + break; + case GL_ONE_MINUS_CONSTANT_ALPHA: + d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; + break; + case GL_SRC_ALPHA_SATURATE: + d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; + break; + default: + UNREACHABLE(); + } + + return d3dBlend; +} + +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) +{ + D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; + + switch (glBlendOp) + { + case GL_FUNC_ADD: + d3dBlendOp = D3D11_BLEND_OP_ADD; + break; + case GL_FUNC_SUBTRACT: + d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; + break; + case GL_FUNC_REVERSE_SUBTRACT: + d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; + break; + case GL_MIN: + d3dBlendOp = D3D11_BLEND_OP_MIN; + break; + case GL_MAX: + d3dBlendOp = D3D11_BLEND_OP_MAX; + break; + default: + UNREACHABLE(); + } + + return d3dBlendOp; +} + +UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + UINT8 mask = 0; + if (red) + { + mask |= D3D11_COLOR_WRITE_ENABLE_RED; + } + if (green) + { + mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; + } + if (blue) + { + mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; + } + if (alpha) + { + mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; + } + return mask; +} + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode) +{ + D3D11_CULL_MODE cull = D3D11_CULL_NONE; + + if (cullEnabled) + { + switch (cullMode) + { + case gl::CullFaceMode::Front: + cull = D3D11_CULL_FRONT; + break; + case gl::CullFaceMode::Back: + cull = D3D11_CULL_BACK; + break; + case gl::CullFaceMode::FrontAndBack: + cull = D3D11_CULL_NONE; + break; + default: + UNREACHABLE(); + } + } + else + { + cull = D3D11_CULL_NONE; + } + + return cull; +} + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) +{ + D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; + switch (comparison) + { + case GL_NEVER: + d3dComp = D3D11_COMPARISON_NEVER; + break; + case GL_ALWAYS: + d3dComp = D3D11_COMPARISON_ALWAYS; + break; + case GL_LESS: + d3dComp = D3D11_COMPARISON_LESS; + break; + case GL_LEQUAL: + d3dComp = D3D11_COMPARISON_LESS_EQUAL; + break; + case GL_EQUAL: + d3dComp = D3D11_COMPARISON_EQUAL; + break; + case GL_GREATER: + d3dComp = D3D11_COMPARISON_GREATER; + break; + case GL_GEQUAL: + d3dComp = D3D11_COMPARISON_GREATER_EQUAL; + break; + case GL_NOTEQUAL: + d3dComp = D3D11_COMPARISON_NOT_EQUAL; + break; + default: + UNREACHABLE(); + } + + return d3dComp; +} - // 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; +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) +{ + return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; +} - 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 = - static_cast(GetMaximumVertexOutputVectors(featureLevel)) * 4; - caps->maxVaryingVectors = static_cast(GetMaximumVertexOutputVectors(featureLevel)); - caps->maxCombinedTextureImageUnits = caps->maxVertexTextureImageUnits + caps->maxTextureImageUnits; +UINT8 ConvertStencilMask(GLuint stencilmask) +{ + return static_cast(stencilmask); +} - // Transform feedback limits - caps->maxTransformFeedbackInterleavedComponents = - static_cast(GetMaximumStreamOutputInterleavedComponents(featureLevel)); - caps->maxTransformFeedbackSeparateAttributes = - static_cast(GetMaximumStreamOutputBuffers(featureLevel)); - caps->maxTransformFeedbackSeparateComponents = - static_cast(GetMaximumStreamOutputSeparateComponents(featureLevel)); +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) +{ + D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; - // Multisample limits - caps->maxSamples = maxSamples; + switch (stencilOp) + { + case GL_ZERO: + d3dStencilOp = D3D11_STENCIL_OP_ZERO; + break; + case GL_KEEP: + d3dStencilOp = D3D11_STENCIL_OP_KEEP; + break; + case GL_REPLACE: + d3dStencilOp = D3D11_STENCIL_OP_REPLACE; + break; + case GL_INCR: + d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; + break; + case GL_DECR: + d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; + break; + case GL_INVERT: + d3dStencilOp = D3D11_STENCIL_OP_INVERT; + break; + case GL_INCR_WRAP: + d3dStencilOp = D3D11_STENCIL_OP_INCR; + break; + case GL_DECR_WRAP: + d3dStencilOp = D3D11_STENCIL_OP_DECR; + break; + default: + UNREACHABLE(); + } - // GL extension support - extensions->setTextureExtensionSupport(*textureCapsMap); - extensions->elementIndexUint = true; - extensions->getProgramBinary = true; - extensions->rgb8rgba8 = true; - extensions->readFormatBGRA = true; - extensions->pixelBufferObject = true; - extensions->mapBuffer = true; - extensions->mapBufferRange = true; - extensions->textureNPOT = GetNPOTTextureSupport(featureLevel); - extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1; - extensions->textureStorage = true; - extensions->textureFilterAnisotropic = true; - extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel); - 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->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; + return d3dStencilOp; +} - // 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_FILTER ConvertFilter(GLenum minFilter, + GLenum magFilter, + float maxAnisotropy, + GLenum comparisonMode) +{ + bool comparison = comparisonMode != GL_NONE; - // D3D11 Feature Level 9_3 doesn't support alpha-to-coverage - limitations->noSampleAlphaToCoverageSupport = (renderer11DeviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); + if (maxAnisotropy > 1.0f) + { + return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast(comparison)); + } + else + { + D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; + D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; + switch (minFilter) + { + case GL_NEAREST: + dxMin = D3D11_FILTER_TYPE_POINT; + dxMip = D3D11_FILTER_TYPE_POINT; + break; + case GL_LINEAR: + dxMin = D3D11_FILTER_TYPE_LINEAR; + dxMip = D3D11_FILTER_TYPE_POINT; + break; + case GL_NEAREST_MIPMAP_NEAREST: + dxMin = D3D11_FILTER_TYPE_POINT; + dxMip = D3D11_FILTER_TYPE_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + dxMin = D3D11_FILTER_TYPE_LINEAR; + dxMip = D3D11_FILTER_TYPE_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + dxMin = D3D11_FILTER_TYPE_POINT; + dxMip = D3D11_FILTER_TYPE_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + dxMin = D3D11_FILTER_TYPE_LINEAR; + dxMip = D3D11_FILTER_TYPE_LINEAR; + break; + default: + UNREACHABLE(); + } - // 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_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; + switch (magFilter) + { + case GL_NEAREST: + dxMag = D3D11_FILTER_TYPE_POINT; + break; + case GL_LINEAR: + dxMag = D3D11_FILTER_TYPE_LINEAR; + break; + default: + UNREACHABLE(); + } - // D3D11 has no concept of separate masks and refs for front and back faces in the depth stencil - // state. - limitations->noSeparateStencilRefsAndMasks = true; + return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, + static_cast(comparison)); + } +} - // D3D11 cannot support constant color and alpha blend funcs together - limitations->noSimultaneousConstantColorAndAlphaBlendFunc = true; +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) +{ + switch (wrap) + { + case GL_REPEAT: + return D3D11_TEXTURE_ADDRESS_WRAP; + case GL_CLAMP_TO_EDGE: + return D3D11_TEXTURE_ADDRESS_CLAMP; + case GL_MIRRORED_REPEAT: + return D3D11_TEXTURE_ADDRESS_MIRROR; + default: + UNREACHABLE(); + } -#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 + return D3D11_TEXTURE_ADDRESS_WRAP; } -} // namespace d3d11_gl +UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel) +{ + return static_cast(std::min(maxAnisotropy, d3d11_gl::GetMaximumAnisotropy(featureLevel))); +} + +D3D11_QUERY ConvertQueryType(GLenum queryType) +{ + switch (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; + case GL_COMMANDS_COMPLETED_CHROMIUM: + return D3D11_QUERY_EVENT; + default: + UNREACHABLE(); + return D3D11_QUERY_EVENT; + } +} + +// Get the D3D11 write mask covering all color channels of a given format +UINT8 GetColorMask(const gl::InternalFormat &format) +{ + return ConvertColorMask(format.redBits > 0, format.greenBits > 0, format.blueBits > 0, + format.alphaBits > 0); +} + +} // namespace gl_d3d11 namespace d3d11 { @@ -1352,9 +1876,7 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) IDXGIDevice *dxgiDevice = nullptr; IDXGIAdapter *dxgiAdapter = nullptr; -#if defined(ANGLE_ENABLE_D3D11_1) IDXGIAdapter2 *dxgiAdapter2 = nullptr; -#endif ANGLED3D11DeviceType retDeviceType = ANGLE_D3D11_DEVICE_TYPE_UNKNOWN; @@ -1365,7 +1887,6 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) if (SUCCEEDED(hr)) { std::wstring adapterString; -#if defined(ANGLE_ENABLE_D3D11_1) HRESULT adapter2hr = dxgiAdapter->QueryInterface(__uuidof(dxgiAdapter2), (void **)&dxgiAdapter2); if (SUCCEEDED(adapter2hr)) @@ -1378,7 +1899,6 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) adapterString = std::wstring(adapterDesc2.Description); } else -#endif { DXGI_ADAPTER_DESC adapterDesc; dxgiAdapter->GetDesc(&adapterDesc); @@ -1410,16 +1930,14 @@ ANGLED3D11DeviceType GetDeviceType(ID3D11Device *device) 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); + const DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(format); int upsampleCount = 0; // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. @@ -1433,7 +1951,10 @@ void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsi upsampleCount++; } } - *levelOffset = upsampleCount; + if (levelOffset) + { + *levelOffset = upsampleCount; + } } void GenerateInitialTextureData(GLint internalFormat, @@ -1445,10 +1966,11 @@ void GenerateInitialTextureData(GLint internalFormat, std::vector *outSubresourceData, std::vector> *outData) { - const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat, renderer11DeviceCaps); - ASSERT(d3dFormatInfo.dataInitializerFunction != NULL); + const d3d11::Format &d3dFormatInfo = d3d11::Format::Get(internalFormat, renderer11DeviceCaps); + ASSERT(d3dFormatInfo.dataInitializerFunction != nullptr); - const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat); + const d3d11::DXGIFormatSize &dxgiFormatInfo = + d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat); outSubresourceData->resize(mipLevels); outData->resize(mipLevels); @@ -1495,6 +2017,36 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo vertex->s = s; } +BlendStateKey::BlendStateKey() +{ + memset(this, 0, sizeof(BlendStateKey)); +} + +bool operator==(const BlendStateKey &a, const BlendStateKey &b) +{ + return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; +} + +bool operator!=(const BlendStateKey &a, const BlendStateKey &b) +{ + return !(a == b); +} + +RasterizerStateKey::RasterizerStateKey() +{ + memset(this, 0, sizeof(RasterizerStateKey)); +} + +bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b) +{ + return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; +} + +bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b) +{ + return !(a == b); +} + HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) { #if defined(_DEBUG) @@ -1533,34 +2085,66 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) #endif } +// Keep this in cpp file where it has visibility of Renderer11.h, otherwise calling +// allocateResource is only compatible with Clang and MSVS, which support calling a +// method on a forward declared class in a template. +template +gl::Error LazyResource::resolveImpl(Renderer11 *renderer, + const GetDescType &desc, + GetInitDataType *initData, + const char *name) +{ + if (!mResource.valid()) + { + ANGLE_TRY(renderer->allocateResource(desc, initData, &mResource)); + mResource.setDebugName(name); + } + return gl::NoError(); +} + +template gl::Error LazyResource::resolveImpl(Renderer11 *renderer, + const D3D11_BLEND_DESC &desc, + void *initData, + const char *name); +template gl::Error LazyResource::resolveImpl(Renderer11 *renderer, + const ShaderData &desc, + void *initData, + const char *name); +template gl::Error LazyResource::resolveImpl( + Renderer11 *renderer, + const ShaderData &desc, + const std::vector *initData, + const char *name); +template gl::Error LazyResource::resolveImpl( + Renderer11 *renderer, + const InputElementArray &desc, + const ShaderData *initData, + const char *name); +template gl::Error LazyResource::resolveImpl(Renderer11 *renderer, + const ShaderData &desc, + void *initData, + const char *name); +template gl::Error LazyResource::resolveImpl(Renderer11 *renderer, + const ShaderData &desc, + void *initData, + const char *name); + 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) + : mInputDesc(inputDesc, inputDescLen), mByteCode(byteCode, byteCodeLen), mDebugName(debugName) { - memcpy(&mInputDesc[0], inputDesc, sizeof(D3D11_INPUT_ELEMENT_DESC) * inputDescLen); } -ID3D11InputLayout *LazyInputLayout::resolve(ID3D11Device *device) +LazyInputLayout::~LazyInputLayout() { - 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; +gl::Error LazyInputLayout::resolve(Renderer11 *renderer) +{ + return resolveImpl(renderer, mInputDesc, &mByteCode, mDebugName); } LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName) @@ -1568,213 +2152,270 @@ LazyBlendState::LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugNa { } -ID3D11BlendState *LazyBlendState::resolve(ID3D11Device *device) +gl::Error LazyBlendState::resolve(Renderer11 *renderer) { - checkAssociatedDevice(device); + return resolveImpl(renderer, mDesc, nullptr, mDebugName); +} + +angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps, + const DXGI_ADAPTER_DESC &adapterDesc) +{ + bool is9_3 = (deviceCaps.featureLevel <= D3D_FEATURE_LEVEL_9_3); + + angle::WorkaroundsD3D workarounds; + workarounds.mrtPerfWorkaround = true; + workarounds.setDataFasterThanImageUpload = true; + workarounds.zeroMaxLodWorkaround = is9_3; + workarounds.useInstancedPointSpriteEmulation = is9_3; + + // TODO(jmadill): Narrow problematic driver range. + if (IsNvidia(adapterDesc.VendorId)) + { + if (deviceCaps.driverVersion.valid()) + { + WORD part1 = HIWORD(deviceCaps.driverVersion.value().LowPart); + WORD part2 = LOWORD(deviceCaps.driverVersion.value().LowPart); + + // Disable the workaround to fix a second driver bug on newer NVIDIA. + workarounds.depthStencilBlitExtraCopy = (part1 <= 13u && part2 < 6881); + } + else + { + workarounds.depthStencilBlitExtraCopy = true; + } + } + + // TODO(jmadill): Disable workaround when we have a fixed compiler DLL. + workarounds.expandIntegerPowExpressions = true; + + workarounds.flushAfterEndingTransformFeedback = IsNvidia(adapterDesc.VendorId); + workarounds.getDimensionsIgnoresBaseLevel = IsNvidia(adapterDesc.VendorId); - if (mResource == nullptr) + if (IsIntel(adapterDesc.VendorId)) { - HRESULT result = device->CreateBlendState(&mDesc, &mResource); - ASSERT(SUCCEEDED(result)); - UNUSED_ASSERTION_VARIABLE(result); - d3d11::SetDebugName(mResource, mDebugName); + IntelDriverVersion capsVersion = d3d11_gl::GetIntelDriverVersion(deviceCaps.driverVersion); + + workarounds.preAddTexelFetchOffsets = true; + workarounds.useSystemMemoryForConstantBuffers = true; + workarounds.disableB5G6R5Support = capsVersion < IntelDriverVersion(4539); + workarounds.addDummyTextureNoRenderTarget = capsVersion < IntelDriverVersion(4815); + if (IsSkylake(adapterDesc.DeviceId)) + { + workarounds.callClearTwice = capsVersion < IntelDriverVersion(4771); + workarounds.emulateIsnanFloat = capsVersion < IntelDriverVersion(4542); + } + else if (IsBroadwell(adapterDesc.DeviceId) || IsHaswell(adapterDesc.DeviceId)) + { + workarounds.rewriteUnaryMinusOperator = capsVersion < IntelDriverVersion(4624); + } + } + + // TODO(jmadill): Disable when we have a fixed driver version. + workarounds.emulateTinyStencilTextures = IsAMD(adapterDesc.VendorId); + + // The tiny stencil texture workaround involves using CopySubresource or UpdateSubresource on a + // depth stencil texture. This is not allowed until feature level 10.1 but since it is not + // possible to support ES3 on these devices, there is no need for the workaround to begin with + // (anglebug.com/1572). + if (deviceCaps.featureLevel < D3D_FEATURE_LEVEL_10_1) + { + workarounds.emulateTinyStencilTextures = false; } - return mResource; + // If the VPAndRTArrayIndexFromAnyShaderFeedingRasterizer feature is not available, we have to + // select the viewport / RT array index in the geometry shader. + workarounds.selectViewInGeometryShader = + (deviceCaps.supportsVpRtIndexWriteFromVertexShader == false); + + // Call platform hooks for testing overrides. + auto *platform = ANGLEPlatformCurrent(); + platform->overrideWorkaroundsD3D(platform, &workarounds); + + return workarounds; } -WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel) +void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth) { - WorkaroundsD3D workarounds; - workarounds.mrtPerfWorkaround = true; - workarounds.setDataFasterThanImageUpload = true; - workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3); - workarounds.useInstancedPointSpriteEmulation = (featureLevel <= D3D_FEATURE_LEVEL_9_3); - return workarounds; + constantBufferDescription->ByteWidth = static_cast(byteWidth); + constantBufferDescription->Usage = D3D11_USAGE_DYNAMIC; + constantBufferDescription->BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDescription->MiscFlags = 0; + constantBufferDescription->StructureByteStride = 0; } } // namespace d3d11 -TextureHelper11::TextureHelper11() - : mTextureType(GL_NONE), - mFormat(DXGI_FORMAT_UNKNOWN), - mSampleCount(0), - mTexture2D(nullptr), - mTexture3D(nullptr) +// TextureHelper11 implementation. +TextureHelper11::TextureHelper11() : mFormatSet(nullptr), mSampleCount(0) { } -TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) - : mTextureType(toCopy.mTextureType), - mExtents(toCopy.mExtents), - mFormat(toCopy.mFormat), - mSampleCount(toCopy.mSampleCount), - mTexture2D(toCopy.mTexture2D), - mTexture3D(toCopy.mTexture3D) +TextureHelper11::TextureHelper11(TextureHelper11 &&toCopy) : TextureHelper11() { - toCopy.reset(); + *this = std::move(toCopy); } -// static -TextureHelper11 TextureHelper11::MakeAndReference(ID3D11Resource *genericResource) +TextureHelper11::TextureHelper11(const TextureHelper11 &other) + : mFormatSet(other.mFormatSet), mExtents(other.mExtents), mSampleCount(other.mSampleCount) { - 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; + mData = other.mData; } -// static -TextureHelper11 TextureHelper11::MakeAndPossess2D(ID3D11Texture2D *texToOwn) +TextureHelper11::~TextureHelper11() { - TextureHelper11 newHelper; - newHelper.mTexture2D = texToOwn; - newHelper.mTextureType = GL_TEXTURE_2D; - newHelper.initDesc(); - return newHelper; } -// static -TextureHelper11 TextureHelper11::MakeAndPossess3D(ID3D11Texture3D *texToOwn) +void TextureHelper11::getDesc(D3D11_TEXTURE2D_DESC *desc) const { - TextureHelper11 newHelper; - newHelper.mTexture3D = texToOwn; - newHelper.mTextureType = GL_TEXTURE_3D; - newHelper.initDesc(); - return newHelper; + static_cast(mData->object)->GetDesc(desc); } -void TextureHelper11::initDesc() +void TextureHelper11::getDesc(D3D11_TEXTURE3D_DESC *desc) const { - if (mTextureType == GL_TEXTURE_2D) - { - ASSERT(!mTexture3D); - D3D11_TEXTURE2D_DESC desc2D; - mTexture2D->GetDesc(&desc2D); + static_cast(mData->object)->GetDesc(desc); +} - 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); +void TextureHelper11::initDesc(const D3D11_TEXTURE2D_DESC &desc2D) +{ + mData->resourceType = ResourceType::Texture2D; + mExtents.width = static_cast(desc2D.Width); + mExtents.height = static_cast(desc2D.Height); + mExtents.depth = 1; + mSampleCount = desc2D.SampleDesc.Count; +} - mExtents.width = static_cast(desc3D.Width); - mExtents.height = static_cast(desc3D.Height); - mExtents.depth = static_cast(desc3D.Depth); - mFormat = desc3D.Format; - mSampleCount = 1; - } +void TextureHelper11::initDesc(const D3D11_TEXTURE3D_DESC &desc3D) +{ + mData->resourceType = ResourceType::Texture3D; + mExtents.width = static_cast(desc3D.Width); + mExtents.height = static_cast(desc3D.Height); + mExtents.depth = static_cast(desc3D.Depth); + mSampleCount = 1; } -TextureHelper11::~TextureHelper11() +TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&other) { - SafeRelease(mTexture2D); - SafeRelease(mTexture3D); + std::swap(mData, other.mData); + std::swap(mExtents, other.mExtents); + std::swap(mFormatSet, other.mFormatSet); + std::swap(mSampleCount, other.mSampleCount); + return *this; } -ID3D11Resource *TextureHelper11::getResource() const +TextureHelper11 &TextureHelper11::operator=(const TextureHelper11 &other) { - return mTexture2D ? static_cast(mTexture2D) - : static_cast(mTexture3D); + mData = other.mData; + mExtents = other.mExtents; + mFormatSet = other.mFormatSet; + mSampleCount = other.mSampleCount; + return *this; } -TextureHelper11 &TextureHelper11::operator=(TextureHelper11 &&texture) +bool TextureHelper11::operator==(const TextureHelper11 &other) const { - SafeRelease(mTexture2D); - SafeRelease(mTexture3D); + return mData->object == other.mData->object; +} - mTextureType = texture.mTextureType; - mExtents = texture.mExtents; - mFormat = texture.mFormat; - mSampleCount = texture.mSampleCount; - mTexture2D = texture.mTexture2D; - mTexture3D = texture.mTexture3D; - texture.reset(); - return *this; +bool TextureHelper11::operator!=(const TextureHelper11 &other) const +{ + return mData->object != other.mData->object; +} + +bool UsePresentPathFast(const Renderer11 *renderer, + const gl::FramebufferAttachment *framebufferAttachment) +{ + if (framebufferAttachment == nullptr) + { + return false; + } + + return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT && + renderer->presentPathFastEnabled()); } -void TextureHelper11::reset() +bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled, GLenum type) { - mTextureType = GL_NONE; - mExtents = gl::Extents(); - mFormat = DXGI_FORMAT_UNKNOWN; - mSampleCount = 0; - mTexture2D = nullptr; - mTexture3D = nullptr; + // We should never have to deal with primitive restart workaround issue with GL_UNSIGNED_INT + // indices, since we restrict it via MAX_ELEMENT_INDEX. + return (!primitiveRestartFixedIndexEnabled && type == GL_UNSIGNED_SHORT); } -gl::ErrorOrResult CreateStagingTexture(GLenum textureType, - DXGI_FORMAT dxgiFormat, - const gl::Extents &size, - ID3D11Device *device) +bool IsStreamingIndexData(const gl::Context *context, GLenum srcType) { - if (textureType == GL_TEXTURE_2D) + const auto &glState = context->getGLState(); + gl::Buffer *glBuffer = glState.getVertexArray()->getElementArrayBuffer().get(); + + // Case 1: the indices are passed by pointer, which forces the streaming of index data + if (glBuffer == nullptr) { - 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; + return true; + } - 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); - } + bool primitiveRestartWorkaround = + UsePrimitiveRestartWorkaround(glState.isPrimitiveRestartEnabled(), srcType); + + BufferD3D *buffer = GetImplAs(glBuffer); + const GLenum dstType = (srcType == GL_UNSIGNED_INT || primitiveRestartWorkaround) + ? GL_UNSIGNED_INT + : GL_UNSIGNED_SHORT; - return TextureHelper11::MakeAndPossess2D(stagingTex); + // Case 2a: the buffer can be used directly + if (buffer->supportsDirectBinding() && dstType == srcType) + { + return false; } - 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; + // Case 2b: use a static translated copy or fall back to streaming + StaticIndexBufferInterface *staticBuffer = buffer->getStaticIndexBuffer(); + if (staticBuffer == nullptr) + { + return true; + } - ID3D11Texture3D *stagingTex = nullptr; - HRESULT result = device->CreateTexture3D(&stagingDesc, nullptr, &stagingTex); - if (FAILED(result)) + if ((staticBuffer->getBufferSize() == 0) || (staticBuffer->getIndexType() != dstType)) { - return gl::Error(GL_OUT_OF_MEMORY, "CreateStagingTextureFor failed, HRESULT: 0x%X.", - result); + return true; } - return TextureHelper11::MakeAndPossess3D(stagingTex); + return false; } -bool UsePresentPathFast(const Renderer11 *renderer, - const gl::FramebufferAttachment *framebufferAttachment) +IndexStorageType ClassifyIndexStorage(const gl::State &glState, + const gl::Buffer *elementArrayBuffer, + GLenum elementType, + GLenum destElementType, + unsigned int offset, + bool *needsTranslation) { - if (framebufferAttachment == nullptr) + // No buffer bound means we are streaming from a client pointer. + if (!elementArrayBuffer || !IsOffsetAligned(elementType, offset)) { - return false; + *needsTranslation = true; + return IndexStorageType::Dynamic; } - return (framebufferAttachment->type() == GL_FRAMEBUFFER_DEFAULT && - renderer->presentPathFastEnabled()); + // The buffer can be used directly if the storage supports it and no translation needed. + BufferD3D *bufferD3D = GetImplAs(elementArrayBuffer); + if (bufferD3D->supportsDirectBinding() && destElementType == elementType) + { + *needsTranslation = false; + return IndexStorageType::Direct; + } + + // Use a static copy when available. + StaticIndexBufferInterface *staticBuffer = bufferD3D->getStaticIndexBuffer(); + if (staticBuffer != nullptr) + { + // Need to re-translate the static data if has never been used, or changed type. + *needsTranslation = + (staticBuffer->getBufferSize() == 0 || staticBuffer->getIndexType() != destElementType); + return IndexStorageType::Static; + } + + // Static buffer not available, fall back to streaming. + *needsTranslation = true; + return IndexStorageType::Dynamic; } } // 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 4925a2d227..3af51bb0f6 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 @@ -11,12 +11,16 @@ #define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_ #include +#include #include -#include "libANGLE/angletypes.h" +#include "common/Color.h" + #include "libANGLE/Caps.h" #include "libANGLE/Error.h" #include "libANGLE/renderer/d3d/RendererD3D.h" +#include "libANGLE/renderer/d3d/d3d11/ResourceManager11.h" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" namespace gl { @@ -27,10 +31,10 @@ namespace rx { class Renderer11; class RenderTarget11; -struct WorkaroundsD3D; struct Renderer11DeviceCaps; -using RenderTargetArray = std::array; +using RenderTargetArray = std::array; +using RTVArray = std::array; namespace gl_d3d11 { @@ -39,7 +43,7 @@ D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha); D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp); UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha); -D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode); +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, gl::CullFaceMode cullMode); D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); @@ -48,9 +52,12 @@ D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp); D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode); D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); +UINT ConvertMaxAnisotropy(float maxAnisotropy, D3D_FEATURE_LEVEL featureLevel); D3D11_QUERY ConvertQueryType(GLenum queryType); +UINT8 GetColorMask(const gl::InternalFormat &formatInfo); + } // namespace gl_d3d11 namespace d3d11_gl @@ -60,10 +67,12 @@ unsigned int GetReservedVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel); unsigned int GetReservedFragmentUniformVectors(D3D_FEATURE_LEVEL featureLevel); -GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel); +gl::Version GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel); void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, const Renderer11DeviceCaps &renderer11DeviceCaps, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions, gl::Limitations *limitations); +void GetSamplePosition(GLsizei sampleCount, size_t index, GLfloat *xy); + } // namespace d3d11_gl namespace d3d11 @@ -108,32 +117,45 @@ struct PositionLayerTexCoord3DVertex void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, unsigned int layer, float u, float v, float s); -template -struct PositionDepthColorVertex +struct PositionVertex { - float x, y, z; - T r, g, b, a; + float x, y, z, w; }; -template -void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, - const gl::Color &color) +struct BlendStateKey final { - vertex->x = x; - vertex->y = y; - vertex->z = z; - vertex->r = color.red; - vertex->g = color.green; - vertex->b = color.blue; - vertex->a = color.alpha; -} + // This will zero-initialize the struct, including padding. + BlendStateKey(); + + gl::BlendState blendState; + + // An int so struct size rounds nicely. + uint32_t rtvMax; + + uint8_t rtvMasks[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT]; +}; + +bool operator==(const BlendStateKey &a, const BlendStateKey &b); +bool operator!=(const BlendStateKey &a, const BlendStateKey &b); + +struct RasterizerStateKey final +{ + // This will zero-initialize the struct, including padding. + RasterizerStateKey(); + + gl::RasterizerState rasterizerState; -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + // Use a 32-bit int to round the struct nicely. + uint32_t scissorEnabled; +}; + +bool operator==(const RasterizerStateKey &a, const RasterizerStateKey &b); +bool operator!=(const RasterizerStateKey &a, const RasterizerStateKey &b); template outType* DynamicCastComObject(IUnknown* object) { - outType *outObject = NULL; + outType *outObject = nullptr; HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast(&outObject)); if (SUCCEEDED(result)) { @@ -142,7 +164,7 @@ outType* DynamicCastComObject(IUnknown* object) else { SafeRelease(outObject); - return NULL; + return nullptr; } } @@ -161,143 +183,63 @@ inline bool isDeviceLostError(HRESULT errorCode) } } -inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name) -{ - ID3D11VertexShader *vs = nullptr; - HRESULT result = device->CreateVertexShader(byteCode, N, nullptr, &vs); - ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) - { - SetDebugName(vs, name); - return vs; - } - return nullptr; -} - -template -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 = nullptr; - HRESULT result = device->CreateGeometryShader(byteCode, N, nullptr, &gs); - ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) - { - SetDebugName(gs, name); - return gs; - } - return nullptr; -} - -template -ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +template +class LazyResource : angle::NonCopyable { - return CompileGS(device, byteCode, N, name); -} + public: + constexpr LazyResource() : mResource() {} + virtual ~LazyResource() {} -inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE *byteCode, size_t N, const char *name) -{ - ID3D11PixelShader *ps = nullptr; - HRESULT result = device->CreatePixelShader(byteCode, N, nullptr, &ps); - ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) + virtual gl::Error resolve(Renderer11 *renderer) = 0; + void reset() { mResource.reset(); } + GetD3D11Type *get() const { - SetDebugName(ps, name); - return ps; + ASSERT(mResource.valid()); + return mResource.get(); } - return nullptr; -} - -template -ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) -{ - return CompilePS(device, byteCode, N, name); -} - -template -class LazyResource : public angle::NonCopyable -{ - public: - LazyResource() : mResource(nullptr), mAssociatedDevice(nullptr) {} - virtual ~LazyResource() { release(); } - virtual ResourceType *resolve(ID3D11Device *device) = 0; - void release() { SafeRelease(mResource); } + const Resource11> &getObj() const { return mResource; } protected: - void checkAssociatedDevice(ID3D11Device *device); + LazyResource(LazyResource &&other) : mResource(std::move(other.mResource)) {} - ResourceType *mResource; - ID3D11Device *mAssociatedDevice; -}; + // Specialized in the cpp file to avoid MSVS/Clang specific code. + gl::Error resolveImpl(Renderer11 *renderer, + const GetDescType &desc, + GetInitDataType *initData, + const char *name); -template -void LazyResource::checkAssociatedDevice(ID3D11Device *device) -{ - ASSERT(mAssociatedDevice == nullptr || device == mAssociatedDevice); - mAssociatedDevice = device; -} + Resource11> mResource; +}; template -class LazyShader final : public LazyResource +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) + constexpr LazyShader(const BYTE *byteCode, size_t byteCodeSize, const char *name) + : mByteCode(byteCode, byteCodeSize), mName(name) { } - 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) + constexpr LazyShader(LazyShader &&shader) + : LazyResource()>(std::move(shader)), + mByteCode(std::move(shader.mByteCode)), + mName(shader.mName) { - mResource = CompileVS(device, mByteCode, mByteCodeSize, mName); } - return mResource; -} -template <> -inline ID3D11GeometryShader *LazyShader::resolve(ID3D11Device *device) -{ - checkAssociatedDevice(device); - if (mResource == nullptr) + gl::Error resolve(Renderer11 *renderer) override { - mResource = CompileGS(device, mByteCode, mByteCodeSize, mName); + return this->resolveImpl(renderer, mByteCode, nullptr, mName); } - return mResource; -} -template <> -inline ID3D11PixelShader *LazyShader::resolve(ID3D11Device *device) -{ - checkAssociatedDevice(device); - if (mResource == nullptr) - { - mResource = CompilePS(device, mByteCode, mByteCodeSize, mName); - } - return mResource; -} + private: + ShaderData mByteCode; + const char *mName; +}; -class LazyInputLayout final : public LazyResource +class LazyInputLayout final : public LazyResource { public: LazyInputLayout(const D3D11_INPUT_ELEMENT_DESC *inputDesc, @@ -305,22 +247,22 @@ class LazyInputLayout final : public LazyResource const BYTE *byteCode, size_t byteCodeLen, const char *debugName); + ~LazyInputLayout() override; - ID3D11InputLayout *resolve(ID3D11Device *device) override; + gl::Error resolve(Renderer11 *renderer) override; private: - std::vector mInputDesc; - size_t mByteCodeLen; - const BYTE *mByteCode; + InputElementArray mInputDesc; + ShaderData mByteCode; const char *mDebugName; }; -class LazyBlendState final : public LazyResource +class LazyBlendState final : public LazyResource { public: LazyBlendState(const D3D11_BLEND_DESC &desc, const char *debugName); - ID3D11BlendState *resolve(ID3D11Device *device) override; + gl::Error resolve(Renderer11 *renderer) override; private: D3D11_BLEND_DESC mDesc; @@ -342,48 +284,147 @@ void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, c } } -WorkaroundsD3D GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel); +angle::WorkaroundsD3D GenerateWorkarounds(const Renderer11DeviceCaps &deviceCaps, + const DXGI_ADAPTER_DESC &adapterDesc); + +enum ReservedConstantBufferSlot +{ + RESERVED_CONSTANT_BUFFER_SLOT_DEFAULT_UNIFORM_BLOCK = 0, + RESERVED_CONSTANT_BUFFER_SLOT_DRIVER = 1, + + RESERVED_CONSTANT_BUFFER_SLOT_COUNT = 2 +}; + +void InitConstantBufferDesc(D3D11_BUFFER_DESC *constantBufferDescription, size_t byteWidth); } // namespace d3d11 +struct GenericData +{ + GenericData() {} + ~GenericData() + { + if (object) + { + // We can have a nullptr factory when holding passed-in resources. + if (manager) + { + manager->onReleaseGeneric(resourceType, object); + manager = nullptr; + } + object->Release(); + object = nullptr; + } + } + + ResourceType resourceType = ResourceType::Last; + ID3D11Resource *object = nullptr; + ResourceManager11 *manager = nullptr; +}; + // A helper class which wraps a 2D or 3D texture. -class TextureHelper11 : angle::NonCopyable +class TextureHelper11 : public Resource11Base { 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; } + TextureHelper11(TextureHelper11 &&other); + TextureHelper11(const TextureHelper11 &other); + ~TextureHelper11() override; + TextureHelper11 &operator=(TextureHelper11 &&other); + TextureHelper11 &operator=(const TextureHelper11 &other); + + bool is2D() const { return mData->resourceType == ResourceType::Texture2D; } + bool is3D() const { return mData->resourceType == ResourceType::Texture3D; } + ResourceType getTextureType() const { return mData->resourceType; } gl::Extents getExtents() const { return mExtents; } - DXGI_FORMAT getFormat() const { return mFormat; } + DXGI_FORMAT getFormat() const { return mFormatSet->texFormat; } + const d3d11::Format &getFormatSet() const { return *mFormatSet; } int getSampleCount() const { return mSampleCount; } - ID3D11Texture2D *getTexture2D() const { return mTexture2D; } - ID3D11Texture3D *getTexture3D() const { return mTexture3D; } - ID3D11Resource *getResource() const; + + template + void init(Resource11 &&texture, const DescT &desc, const d3d11::Format &format) + { + std::swap(mData->manager, texture.mData->manager); + + // Can't use std::swap because texture is typed, and here we use ID3D11Resource. + ID3D11Resource *temp = mData->object; + mData->object = texture.mData->object; + texture.mData->object = static_cast(temp); + + mFormatSet = &format; + initDesc(desc); + } + + template + void set(ResourceT *object, const d3d11::Format &format) + { + ASSERT(!valid()); + mFormatSet = &format; + mData->object = object; + mData->manager = nullptr; + + GetDescFromD3D11 desc; + getDesc(&desc); + initDesc(desc); + } + + bool operator==(const TextureHelper11 &other) const; + bool operator!=(const TextureHelper11 &other) const; + + void getDesc(D3D11_TEXTURE2D_DESC *desc) const; + void getDesc(D3D11_TEXTURE3D_DESC *desc) const; private: - void reset(); - void initDesc(); + void initDesc(const D3D11_TEXTURE2D_DESC &desc2D); + void initDesc(const D3D11_TEXTURE3D_DESC &desc3D); - GLenum mTextureType; + const d3d11::Format *mFormatSet; 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); +enum class StagingAccess +{ + READ, + READ_WRITE, +}; bool UsePresentPathFast(const Renderer11 *renderer, const gl::FramebufferAttachment *colorbuffer); +bool UsePrimitiveRestartWorkaround(bool primitiveRestartFixedIndexEnabled, GLenum type); +bool IsStreamingIndexData(const gl::Context *context, GLenum srcType); + +enum class IndexStorageType +{ + // Dynamic indexes are re-streamed every frame. They come from a client data pointer or + // from buffers that are updated frequently. + Dynamic, + + // Static indexes are translated from the original storage once, and re-used multiple times. + Static, + + // Direct indexes are never transated and are used directly from the source buffer. They are + // the fastest available path. + Direct, + + // Not a real storage type. + Invalid, +}; + +IndexStorageType ClassifyIndexStorage(const gl::State &glState, + const gl::Buffer *elementArrayBuffer, + GLenum elementType, + GLenum destElementType, + unsigned int offset, + bool *needsTranslation); + +// Used for state change notifications between buffers and vertex arrays. +using OnBufferDataDirtyBinding = angle::ChannelBinding; +using OnBufferDataDirtyChannel = angle::BroadcastChannel; +using OnBufferDataDirtyReceiver = angle::SignalReceiver; + +// Used for state change notifications between RenderTarget11 and Framebuffer11. +using OnRenderTargetDirtyBinding = angle::ChannelBinding; +using OnRenderTargetDirtyChannel = angle::BroadcastChannel; +using OnRenderTargetDirtyReceiver = angle::SignalReceiver; } // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl index 2b3e1ebe4c..48f5b427ec 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl @@ -1,13 +1,152 @@ -// Assume we are in SM4+, which has 8 color outputs +// +// Copyright (c) 2017 The ANGLE Project. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// -void VS_ClearFloat( in float3 inPosition : POSITION, in float4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) +// Clear11.hlsl: Shaders for clearing RTVs and DSVs using draw calls and +// specifying float depth values and either float, uint or sint clear colors. +// Notes: +// - UINT & SINT clears can only be compiled with FL10+ +// - VS_Clear_FL9 requires a VB to be bound with vertices to create +// a primitive covering the entire surface (in clip co-ordinates) + +// Constants +static const float2 g_Corners[6] = +{ + float2(-1.0f, 1.0f), + float2( 1.0f, -1.0f), + float2(-1.0f, -1.0f), + float2(-1.0f, 1.0f), + float2( 1.0f, 1.0f), + float2( 1.0f, -1.0f), +}; + +// Vertex Shaders +void VS_Clear(in uint id : SV_VertexID, + out float4 outPosition : SV_POSITION) +{ + float2 corner = g_Corners[id]; + outPosition = float4(corner.x, corner.y, 0.0f, 1.0f); +} + +void VS_Multiview_Clear(in uint id : SV_VertexID, + in uint instanceID : SV_InstanceID, + out float4 outPosition : SV_POSITION, + out uint outLayerID : TEXCOORD0) +{ + float2 corner = g_Corners[id]; + outPosition = float4(corner.x, corner.y, 0.0f, 1.0f); + outLayerID = instanceID; +} + +void VS_Clear_FL9( in float4 inPosition : POSITION, + out float4 outPosition : SV_POSITION) +{ + outPosition = inPosition; +} + +// Geometry shader for clearing multiview layered textures +struct GS_INPUT +{ + float4 inPosition : SV_Position; + uint inLayerID : TEXCOORD0; +}; + +struct GS_OUTPUT { - outPosition = float4(inPosition, 1.0f); - outColor = inColor; + float4 outPosition : SV_Position; + uint outLayerID : SV_RenderTargetArrayIndex; +}; + +[maxvertexcount(3)] +void GS_Multiview_Clear(triangle GS_INPUT input[3], inout TriangleStream outStream) +{ + GS_OUTPUT output = (GS_OUTPUT)0; + for (int i = 0; i < 3; i++) + { + output.outPosition = input[i].inPosition; + output.outLayerID = input[i].inLayerID; + outStream.Append(output); + } + outStream.RestartStrip(); +} + +// Pixel Shader Constant Buffers +cbuffer ColorAndDepthDataFloat : register(b0) +{ + float4 color_Float : packoffset(c0); + float zValueF_Float : packoffset(c1); +} + +cbuffer ColorAndDepthDataSint : register(b0) +{ + int4 color_Sint : packoffset(c0); + float zValueF_Sint : packoffset(c1); +} + +cbuffer ColorAndDepthDataUint : register(b0) +{ + uint4 color_Uint : packoffset(c0); + float zValueF_Uint : packoffset(c1); } -struct PS_OutputFloat +cbuffer DepthOnlyData : register(b0) +{ + float zValue_Depth : packoffset(c1); +} + +// Pixel Shader Output Structs +struct PS_OutputFloat_FL9 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat1 +{ + float4 color0 : SV_TARGET0; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat2 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat3 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat4 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat5 +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float4 color4 : SV_TARGET4; + float depth : SV_DEPTH; +}; + +struct PS_OutputFloat6 { float4 color0 : SV_TARGET0; float4 color1 : SV_TARGET1; @@ -15,50 +154,98 @@ struct PS_OutputFloat float4 color3 : SV_TARGET3; float4 color4 : SV_TARGET4; float4 color5 : SV_TARGET5; - float4 color6 : SV_TARGET6; - float4 color7 : SV_TARGET7; + float depth : SV_DEPTH; }; -PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +struct PS_OutputFloat7 { - PS_OutputFloat outColor; - outColor.color0 = inColor; - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; - outColor.color4 = inColor; - outColor.color5 = inColor; - outColor.color6 = inColor; - outColor.color7 = inColor; - return outColor; -} + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; + float4 color4 : SV_TARGET4; + float4 color5 : SV_TARGET5; + float4 color6 : SV_TARGET6; + float depth : SV_DEPTH; +}; -struct PS_OutputFloat_FL9 +struct PS_OutputFloat8 { float4 color0 : SV_TARGET0; float4 color1 : SV_TARGET1; float4 color2 : SV_TARGET2; float4 color3 : SV_TARGET3; + float4 color4 : SV_TARGET4; + float4 color5 : SV_TARGET5; + float4 color6 : SV_TARGET6; + float4 color7 : SV_TARGET7; + float depth : SV_DEPTH; }; -PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +struct PS_OutputUint1 { - PS_OutputFloat_FL9 outColor; - outColor.color0 = inColor; - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; - return outColor; -} + uint4 color0 : SV_TARGET0; + float depth : SV_DEPTH; +}; -void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR) +struct PS_OutputUint2 { - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint3 +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint4 +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint5 +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + uint4 color4 : SV_TARGET4; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint6 +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + uint4 color4 : SV_TARGET4; + uint4 color5 : SV_TARGET5; + float depth : SV_DEPTH; +}; + +struct PS_OutputUint7 +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + uint4 color4 : SV_TARGET4; + uint4 color5 : SV_TARGET5; + uint4 color6 : SV_TARGET6; + float depth : SV_DEPTH; +}; -struct PS_OutputUint +struct PS_OutputUint8 { uint4 color0 : SV_TARGET0; uint4 color1 : SV_TARGET1; @@ -68,31 +255,73 @@ struct PS_OutputUint uint4 color5 : SV_TARGET5; uint4 color6 : SV_TARGET6; uint4 color7 : SV_TARGET7; + float depth : SV_DEPTH; }; -PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION, in uint4 inColor : COLOR) +struct PS_OutputSint1 { - PS_OutputUint outColor; - outColor.color0 = inColor; - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; - outColor.color4 = inColor; - outColor.color5 = inColor; - outColor.color6 = inColor; - outColor.color7 = inColor; - return outColor; -} + int4 color0 : SV_TARGET0; + float depth : SV_DEPTH; +}; +struct PS_OutputSint2 +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + float depth : SV_DEPTH; +}; -void VS_ClearSint( in float3 inPosition : POSITION, in int4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out int4 outColor : COLOR) +struct PS_OutputSint3 { - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + float depth : SV_DEPTH; +}; + +struct PS_OutputSint4 +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + float depth : SV_DEPTH; +}; + +struct PS_OutputSint5 +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + int4 color4 : SV_TARGET4; + float depth : SV_DEPTH; +}; + +struct PS_OutputSint6 +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + int4 color4 : SV_TARGET4; + int4 color5 : SV_TARGET5; + float depth : SV_DEPTH; +}; + +struct PS_OutputSint7 +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + int4 color4 : SV_TARGET4; + int4 color5 : SV_TARGET5; + int4 color6 : SV_TARGET6; + float depth : SV_DEPTH; +}; -struct PS_OutputSint +struct PS_OutputSint8 { int4 color0 : SV_TARGET0; int4 color1 : SV_TARGET1; @@ -102,18 +331,305 @@ struct PS_OutputSint int4 color5 : SV_TARGET5; int4 color6 : SV_TARGET6; int4 color7 : SV_TARGET7; + float depth : SV_DEPTH; +}; + +struct PS_OutputDepth +{ + float depth : SV_DEPTH; }; -PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION, in int4 inColor : COLOR) +// Pixel Shaders +PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat_FL9 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat1 PS_ClearFloat1(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat1 outData; + outData.color0 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat2 PS_ClearFloat2(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat2 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat3 PS_ClearFloat3(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat3 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat4 PS_ClearFloat4(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat4 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat5 PS_ClearFloat5(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat5 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.color4 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat6 PS_ClearFloat6(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat6 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.color4 = color_Float; + outData.color5 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat7 PS_ClearFloat7(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat7 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.color4 = color_Float; + outData.color5 = color_Float; + outData.color6 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputFloat8 PS_ClearFloat8(in float4 inPosition : SV_POSITION) +{ + PS_OutputFloat8 outData; + outData.color0 = color_Float; + outData.color1 = color_Float; + outData.color2 = color_Float; + outData.color3 = color_Float; + outData.color4 = color_Float; + outData.color5 = color_Float; + outData.color6 = color_Float; + outData.color7 = color_Float; + outData.depth = zValueF_Float; + return outData; +} + +PS_OutputUint1 PS_ClearUint1(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint1 outData; + outData.color0 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint2 PS_ClearUint2(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint2 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint3 PS_ClearUint3(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint3 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint4 PS_ClearUint4(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint4 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint5 PS_ClearUint5(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint5 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.color4 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint6 PS_ClearUint6(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint6 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.color4 = color_Uint; + outData.color5 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint7 PS_ClearUint7(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint7 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.color4 = color_Uint; + outData.color5 = color_Uint; + outData.color6 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputUint8 PS_ClearUint8(in float4 inPosition : SV_POSITION) +{ + PS_OutputUint8 outData; + outData.color0 = color_Uint; + outData.color1 = color_Uint; + outData.color2 = color_Uint; + outData.color3 = color_Uint; + outData.color4 = color_Uint; + outData.color5 = color_Uint; + outData.color6 = color_Uint; + outData.color7 = color_Uint; + outData.depth = zValueF_Uint; + return outData; +} + +PS_OutputSint1 PS_ClearSint1(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint1 outData; + outData.color0 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint2 PS_ClearSint2(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint2 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint3 PS_ClearSint3(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint3 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint4 PS_ClearSint4(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint4 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint5 PS_ClearSint5(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint5 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.color4 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint6 PS_ClearSint6(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint6 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.color4 = color_Sint; + outData.color5 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint7 PS_ClearSint7(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint7 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.color4 = color_Sint; + outData.color5 = color_Sint; + outData.color6 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputSint8 PS_ClearSint8(in float4 inPosition : SV_POSITION) +{ + PS_OutputSint8 outData; + outData.color0 = color_Sint; + outData.color1 = color_Sint; + outData.color2 = color_Sint; + outData.color3 = color_Sint; + outData.color4 = color_Sint; + outData.color5 = color_Sint; + outData.color6 = color_Sint; + outData.color7 = color_Sint; + outData.depth = zValueF_Sint; + return outData; +} + +PS_OutputDepth PS_ClearDepth(in float4 inPosition : SV_POSITION) { - PS_OutputSint outColor; - outColor.color0 = inColor; - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; - outColor.color4 = inColor; - outColor.color5 = inColor; - outColor.color6 = inColor; - outColor.color7 = inColor; - return outColor; + PS_OutputDepth outData; + outData.depth = zValue_Depth; + return outData; } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl new file mode 100644 index 0000000000..0d10b8eafa --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/MultiplyAlpha.hlsl @@ -0,0 +1,131 @@ +Texture2D TextureF : register(t0); +Texture2D TextureUI : register(t0); + +SamplerState Sampler : register(s0); + +// Notation: +// PM: premultiply, UM: unmulitply, PT: passthrough +// F: float, U: uint + +// Float to float LUMA +float4 PS_FtoF_PM_LUMA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb = color.r * color.a; + color.a = 1.0f; + return color; +} +float4 PS_FtoF_UM_LUMA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + if (color.a > 0.0f) + { + color.rgb = color.r / color.a; + } + color.a = 1.0f; + return color; +} + +// Float to float LUMAALPHA +float4 PS_FtoF_PM_LUMAALPHA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb = color.r * color.a; + return color; +} + +float4 PS_FtoF_UM_LUMAALPHA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + if (color.a > 0.0f) + { + color.rgb = color.r / color.a; + } + return color; +} + +// Float to float RGBA +float4 PS_FtoF_PM_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb *= color.a; + return color; +} + +float4 PS_FtoF_UM_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + if (color.a > 0.0f) + { + color.rgb /= color.a; + } + return color; +} + +// Float to float RGB +float4 PS_FtoF_PM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb *= color.a; + color.a = 1.0f; + return color; +} + +float4 PS_FtoF_UM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + if (color.a > 0.0f) + { + color.rgb /= color.a; + } + color.a = 1.0f; + return color; +} + +// Float to uint RGBA +uint4 PS_FtoU_PT_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + return uint4(color * 255); +} + +uint4 PS_FtoU_PM_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb *= color.a; + return uint4(color * 255); +} + +uint4 PS_FtoU_UM_RGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + if (color.a > 0.0f) + { + color.rgb /= color.a; + } + return uint4(color * 255); +} + +// Float to uint RGB +uint4 PS_FtoU_PT_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + return uint4(color.rgb * 255, 1); +} + +uint4 PS_FtoU_PM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + color.rgb *= color.a; + return uint4(color.rgb * 255, 1); +} + +uint4 PS_FtoU_UM_RGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + float4 color = TextureF.Sample(Sampler, inTexCoord).rgba; + if (color.a > 0.0f) + { + color.rgb /= color.a; + } + return uint4(color.rgb * 255, 1); +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl index 8671c39fb7..0b1a5ad169 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl @@ -1,4 +1,5 @@ Texture2D TextureF : register(t0); +Texture2DMS TextureF_MS: register(t0); Texture2D TextureUI : register(t0); Texture2D TextureI : register(t0); @@ -21,6 +22,16 @@ float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexC return TextureF.Sample(Sampler, inTexCoord).rgba; } +float4 PS_PassthroughA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(0.0f, 0.0f, 0.0f, TextureF.Sample(Sampler, inTexCoord).a); +} + +float4 PS_PassthroughRGBA2DMS(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCORD0, in uint inSampleIndex : SV_SAMPLEINDEX) : SV_TARGET0 +{ + return TextureF_MS.sample[inSampleIndex][inTexCoord].rgba; +} + uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 { uint2 size; diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl new file mode 100644 index 0000000000..7dc40d4b6a --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/ResolveDepthStencil.hlsl @@ -0,0 +1,56 @@ +static const float2 g_Corners[6] = +{ + float2(-1.0f, 1.0f), + float2( 1.0f, -1.0f), + float2(-1.0f, -1.0f), + float2(-1.0f, 1.0f), + float2( 1.0f, 1.0f), + float2( 1.0f, -1.0f), +}; + +void VS_ResolveDepthStencil(in uint id : SV_VertexID, + out float4 position : SV_Position, + out float2 texCoord : TEXCOORD0) +{ + float2 corner = g_Corners[id]; + position = float4(corner.x, corner.y, 0.0f, 1.0f); + texCoord = float2((corner.x + 1.0f) * 0.5f, (-corner.y + 1.0f) * 0.5f); +} + +Texture2DMS Depth : register(t0); +Texture2DMS Stencil : register(t1); + +void PS_ResolveDepth(in float4 position : SV_Position, + in float2 texCoord : TEXCOORD0, + out float depth : SV_Depth) +{ + // MS samplers must use Load + uint width, height, samples; + Depth.GetDimensions(width, height, samples); + uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height)); + depth = Depth.Load(coord, 0).r; +} + +void PS_ResolveDepthStencil(in float4 position : SV_Position, + in float2 texCoord : TEXCOORD0, + out float2 depthStencil : SV_Target0) +{ + // MS samplers must use Load + uint width, height, samples; + Depth.GetDimensions(width, height, samples); + uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height)); + depthStencil.r = Depth.Load(coord, 0).r; + depthStencil.g = float(Stencil.Load(coord, 0).g); +} + +void PS_ResolveStencil(in float4 position : SV_Position, + in float2 texCoord : TEXCOORD0, + out float2 stencil : SV_Target0) +{ + // MS samplers must use Load + uint width, height, samples; + Stencil.GetDimensions(width, height, samples); + uint2 coord = uint2(texCoord.x * float(width), texCoord.y * float(height)); + stencil.r = 0.0f; + stencil.g = float(Stencil.Load(coord, 0).g); +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h new file mode 100644 index 0000000000..a5cccdc98e --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dms11ps.h @@ -0,0 +1,155 @@ +#if 0 +// +// Generated by Microsoft (R) HLSL Shader Compiler 10.1 +// +// +// Resource Bindings: +// +// Name Type Format Dim HLSL Bind Count +// ------------------------------ ---------- ------- ----------- -------------- ------ +// TextureF_MS texture float4 2dMS t0 1 +// +// +// +// Input signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_POSITION 0 xyzw 0 POS float +// TEXCORD 0 xy 1 NONE float xy +// SV_SAMPLEINDEX 0 x 2 SAMPLE uint x +// +// +// Output signature: +// +// Name Index Mask Register SysValue Format Used +// -------------------- ----- ------ -------- -------- ------- ------ +// SV_TARGET 0 xyzw 0 TARGET float xyzw +// +// Pixel Shader runs at sample frequency +// +ps_4_1 +dcl_globalFlags refactoringAllowed +dcl_resource_texture2dms(0) (float,float,float,float) t0 +dcl_input_ps linear v1.xy +dcl_input_ps_sgv constant v2.x, sampleIndex +dcl_output o0.xyzw +dcl_temps 1 +ftou r0.xy, v1.xyxx +mov r0.zw, l(0,0,0,0) +ldms o0.xyzw, r0.xyzw, t0.xyzw, v2.x +ret +// Approximately 4 instruction slots used +#endif + +const BYTE g_PS_PassthroughRGBA2DMS[] = +{ + 68, 88, 66, 67, 206, 115, + 73, 27, 160, 237, 59, 223, + 179, 180, 28, 146, 74, 174, + 29, 197, 1, 0, 0, 0, + 136, 2, 0, 0, 5, 0, + 0, 0, 52, 0, 0, 0, + 172, 0, 0, 0, 40, 1, + 0, 0, 92, 1, 0, 0, + 12, 2, 0, 0, 82, 68, + 69, 70, 112, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 28, 0, 0, 0, 1, 4, + 255, 255, 0, 1, 0, 0, + 72, 0, 0, 0, 60, 0, + 0, 0, 2, 0, 0, 0, + 5, 0, 0, 0, 6, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 13, 0, 0, 0, + 84, 101, 120, 116, 117, 114, + 101, 70, 95, 77, 83, 0, + 77, 105, 99, 114, 111, 115, + 111, 102, 116, 32, 40, 82, + 41, 32, 72, 76, 83, 76, + 32, 83, 104, 97, 100, 101, + 114, 32, 67, 111, 109, 112, + 105, 108, 101, 114, 32, 49, + 48, 46, 49, 0, 73, 83, + 71, 78, 116, 0, 0, 0, + 3, 0, 0, 0, 8, 0, + 0, 0, 80, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 15, 0, + 0, 0, 92, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 3, 0, 0, 0, + 1, 0, 0, 0, 3, 3, + 0, 0, 100, 0, 0, 0, + 0, 0, 0, 0, 10, 0, + 0, 0, 1, 0, 0, 0, + 2, 0, 0, 0, 1, 1, + 0, 0, 83, 86, 95, 80, + 79, 83, 73, 84, 73, 79, + 78, 0, 84, 69, 88, 67, + 79, 82, 68, 0, 83, 86, + 95, 83, 65, 77, 80, 76, + 69, 73, 78, 68, 69, 88, + 0, 171, 79, 83, 71, 78, + 44, 0, 0, 0, 1, 0, + 0, 0, 8, 0, 0, 0, + 32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, + 0, 0, 15, 0, 0, 0, + 83, 86, 95, 84, 65, 82, + 71, 69, 84, 0, 171, 171, + 83, 72, 68, 82, 168, 0, + 0, 0, 65, 0, 0, 0, + 42, 0, 0, 0, 106, 8, + 0, 1, 88, 32, 0, 4, + 0, 112, 16, 0, 0, 0, + 0, 0, 85, 85, 0, 0, + 98, 16, 0, 3, 50, 16, + 16, 0, 1, 0, 0, 0, + 99, 8, 0, 4, 18, 16, + 16, 0, 2, 0, 0, 0, + 10, 0, 0, 0, 101, 0, + 0, 3, 242, 32, 16, 0, + 0, 0, 0, 0, 104, 0, + 0, 2, 1, 0, 0, 0, + 28, 0, 0, 5, 50, 0, + 16, 0, 0, 0, 0, 0, + 70, 16, 16, 0, 1, 0, + 0, 0, 54, 0, 0, 8, + 194, 0, 16, 0, 0, 0, + 0, 0, 2, 64, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 46, 0, + 0, 9, 242, 32, 16, 0, + 0, 0, 0, 0, 70, 14, + 16, 0, 0, 0, 0, 0, + 70, 126, 16, 0, 0, 0, + 0, 0, 10, 16, 16, 0, + 2, 0, 0, 0, 62, 0, + 0, 1, 83, 84, 65, 84, + 116, 0, 0, 0, 4, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 3, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0 +}; 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 deleted file mode 100644 index 3e9e6877d9..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_data.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "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 deleted file mode 100644 index df9a30ff50..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// 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 deleted file mode 100644 index 84d6fada97..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/swizzle_format_info_autogen.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// 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 index 87d303437f..61cd44a62b 100644 --- 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 @@ -1,692 +1,523 @@ { - "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": [ - { + "NONE": { + }, + "A8_UNORM": { + "texFormat": "DXGI_FORMAT_A8_UNORM", + "srvFormat": "DXGI_FORMAT_A8_UNORM", + "rtvFormat": "DXGI_FORMAT_A8_UNORM", + "channels": "a", + "componentType": "unorm", + "bits": { "alpha": 8 }, + "supportTest": "OnlyFL10Plus(deviceCaps)", + "fallbackFormat": "R8G8B8A8_UNORM" + }, + "R8G8B8A8_UNORM": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM", + "channels": "rgba", + "componentType": "unorm", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_RGBA8" + }, + "R16G16B16A16_UNORM": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM", + "channels": "rgba", + "componentType": "unorm", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16_EXT" + }, + "R16G16B16A16_FLOAT": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT", + "channels": "rgba", + "componentType": "float", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16F" + }, + "R32G32B32A32_FLOAT": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_FLOAT", + "channels": "rgba", + "componentType": "float", + "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 }, + "glInternalFormat": "GL_RGBA32F" + }, + "B8G8R8A8_UNORM": { + "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM", + "channels": "bgra", + "componentType": "unorm", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_BGRA8_EXT" + }, + "B8G8R8A8_UNORM_SRGB": { + "texFormat": "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB", + "rtvFormat": "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB", + "channels": "bgra", + "componentType": "unorm", + "bits": {"red": 8, "green": 8, "blue": 8,"alpha": 8}, + "siwzzleFormat": "GL_RGBA8" + }, + "BC1_RGBA_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM", + "srvFormat": "DXGI_FORMAT_BC1_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC1_RGB_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM", + "srvFormat": "DXGI_FORMAT_BC1_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC2_RGBA_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC2_UNORM", + "srvFormat": "DXGI_FORMAT_BC2_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC3_RGBA_UNORM_BLOCK": { + "texFormat": "DXGI_FORMAT_BC3_UNORM", + "srvFormat": "DXGI_FORMAT_BC3_UNORM", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC1_RGBA_UNORM_SRGB_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_BC1_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC1_RGB_UNORM_SRGB_BLOCK": { + "texFormat": "DXGI_FORMAT_BC1_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_BC1_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC2_RGBA_UNORM_SRGB_BLOCK": { + "texFormat": "DXGI_FORMAT_BC2_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_BC2_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "BC3_RGBA_UNORM_SRGB_BLOCK": { + "texFormat": "DXGI_FORMAT_BC3_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_BC3_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "swizzleFormat": "GL_RGBA8" + }, + "D24_UNORM_S8_UINT": { + "FL10Plus": { "texFormat": "DXGI_FORMAT_R24G8_TYPELESS", - "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS", - "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requirementsFcn": "OnlyFL10Plus" + "srvFormat": "DXGI_FORMAT_R24_UNORM_X8_TYPELESS" }, - { - "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" + "FL9_3": { + "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT" }, - { - "requirementsFcn": "OnlyFL9_3" - } - ], - "GL_DEPTH_COMPONENT16": [ - { + "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", + "channels": "ds", + "bits": { "depth": 24, "stencil": 8 }, + "glInternalFormat": "GL_DEPTH24_STENCIL8_OES" + }, + "D32_FLOAT_S8X24_UINT": { + "texFormat": "DXGI_FORMAT_R32G8X24_TYPELESS", + "srvFormat": "DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS", + "dsvFormat": "DXGI_FORMAT_D32_FLOAT_S8X24_UINT", + "channels": "ds", + "bits": { "depth": 32, "stencil": 8 }, + "glInternalFormat": "GL_DEPTH32F_STENCIL8" + }, + "D16_UNORM": { + "FL10Plus": { "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" + "srvFormat": "DXGI_FORMAT_R16_UNORM" }, - { - "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" + "FL9_3": { + "texFormat": "DXGI_FORMAT_D16_UNORM" }, - { - "texFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "dsvFormat": "DXGI_FORMAT_D24_UNORM_S8_UINT", - "requirementsFcn": "OnlyFL9_3" - } - ] + "dsvFormat": "DXGI_FORMAT_D16_UNORM", + "channels": "d", + "componentType": "unorm", + "bits": { "depth": 16 }, + "glInternalFormat": "GL_DEPTH_COMPONENT16" + }, + "D32_FLOAT": { + "texFormat": "DXGI_FORMAT_R32_TYPELESS", + "srvFormat": "DXGI_FORMAT_R32_FLOAT", + "dsvFormat": "DXGI_FORMAT_D32_FLOAT", + "channels": "d", + "componentType": "float", + "bits": { "depth": 32 }, + "glInternalFormat": "GL_DEPTH_COMPONENT32F" + }, + "R11G11B10_FLOAT": { + "texFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "srvFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "rtvFormat": "DXGI_FORMAT_R11G11B10_FLOAT", + "channels": "rgb", + "componentType": "float", + "bits": { "red": 11, "green": 11, "blue": 10 }, + "glInternalFormat": "GL_R11F_G11F_B10F" + }, + "R16_FLOAT": { + "texFormat": "DXGI_FORMAT_R16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16_FLOAT", + "channels": "r", + "componentType": "float", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16F" + }, + "R16_SINT": { + "texFormat": "DXGI_FORMAT_R16_SINT", + "srvFormat": "DXGI_FORMAT_R16_SINT", + "rtvFormat": "DXGI_FORMAT_R16_SINT", + "channels": "r", + "componentType": "int", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16I" + }, + "R16_UINT": { + "texFormat": "DXGI_FORMAT_R16_UINT", + "srvFormat": "DXGI_FORMAT_R16_UINT", + "rtvFormat": "DXGI_FORMAT_R16_UINT", + "channels": "r", + "componentType": "uint", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16UI" + }, + "R32_FLOAT": { + "texFormat": "DXGI_FORMAT_R32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32_FLOAT", + "channels": "r", + "componentType": "float", + "bits": { "red": 32 }, + "glInternalFormat": "GL_R32F" + }, + "R32_SINT": { + "texFormat": "DXGI_FORMAT_R32_SINT", + "srvFormat": "DXGI_FORMAT_R32_SINT", + "rtvFormat": "DXGI_FORMAT_R32_SINT", + "channels": "r", + "componentType": "int", + "bits": { "red": 32 }, + "glInternalFormat": "GL_R32I" + }, + "R32_UINT": { + "texFormat": "DXGI_FORMAT_R32_UINT", + "srvFormat": "DXGI_FORMAT_R32_UINT", + "rtvFormat": "DXGI_FORMAT_R32_UINT", + "channels": "r", + "componentType": "uint", + "bits": { "red": 32 }, + "glInternalFormat": "GL_R32UI" + }, + "R8_UNORM": { + "texFormat": "DXGI_FORMAT_R8_UNORM", + "srvFormat": "DXGI_FORMAT_R8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8_UNORM", + "channels": "r", + "componentType": "unorm", + "bits": { "red": 8 }, + "glInternalFormat": "GL_R8" + }, + "R8_SINT": { + "texFormat": "DXGI_FORMAT_R8_SINT", + "srvFormat": "DXGI_FORMAT_R8_SINT", + "rtvFormat": "DXGI_FORMAT_R8_SINT", + "channels": "r", + "componentType": "int", + "bits": { "red": 8 }, + "glInternalFormat": "GL_R8I" + }, + "R8_UINT": { + "texFormat": "DXGI_FORMAT_R8_UINT", + "srvFormat": "DXGI_FORMAT_R8_UINT", + "rtvFormat": "DXGI_FORMAT_R8_UINT", + "channels": "r", + "componentType": "uint", + "bits": { "red": 8 }, + "glInternalFormat": "GL_R8UI" + }, + "R8_SNORM": { + "texFormat": "DXGI_FORMAT_R8_SNORM", + "srvFormat": "DXGI_FORMAT_R8_SNORM", + "channels": "r", + "componentType": "snorm", + "bits": { "red": 8 }, + "glInternalFormat": "GL_R8_SNORM" + }, + "R16G16_FLOAT": { + "texFormat": "DXGI_FORMAT_R16G16_FLOAT", + "srvFormat": "DXGI_FORMAT_R16G16_FLOAT", + "rtvFormat": "DXGI_FORMAT_R16G16_FLOAT", + "channels": "rg", + "componentType": "float", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16F" + }, + "R16G16_SINT": { + "texFormat": "DXGI_FORMAT_R16G16_SINT", + "srvFormat": "DXGI_FORMAT_R16G16_SINT", + "rtvFormat": "DXGI_FORMAT_R16G16_SINT", + "channels": "rg", + "componentType": "int", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16I" + }, + "R16G16_UINT": { + "texFormat": "DXGI_FORMAT_R16G16_UINT", + "srvFormat": "DXGI_FORMAT_R16G16_UINT", + "rtvFormat": "DXGI_FORMAT_R16G16_UINT", + "channels": "rg", + "componentType": "uint", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16UI" + }, + "R32G32_FLOAT": { + "texFormat": "DXGI_FORMAT_R32G32_FLOAT", + "srvFormat": "DXGI_FORMAT_R32G32_FLOAT", + "rtvFormat": "DXGI_FORMAT_R32G32_FLOAT", + "channels": "rg", + "componentType": "float", + "bits": { "red": 32, "green": 32 }, + "glInternalFormat": "GL_RG32F" + }, + "R32G32_SINT": { + "texFormat": "DXGI_FORMAT_R32G32_SINT", + "srvFormat": "DXGI_FORMAT_R32G32_SINT", + "rtvFormat": "DXGI_FORMAT_R32G32_SINT", + "channels": "rg", + "componentType": "int", + "bits": { "red": 32, "green": 32 }, + "glInternalFormat": "GL_RG32I" + }, + "R32G32_UINT": { + "texFormat": "DXGI_FORMAT_R32G32_UINT", + "srvFormat": "DXGI_FORMAT_R32G32_UINT", + "rtvFormat": "DXGI_FORMAT_R32G32_UINT", + "channels": "rg", + "componentType": "uint", + "bits": { "red": 32, "green": 32 }, + "glInternalFormat": "GL_RG32UI" + }, + "R8G8_UNORM": { + "texFormat": "DXGI_FORMAT_R8G8_UNORM", + "srvFormat": "DXGI_FORMAT_R8G8_UNORM", + "rtvFormat": "DXGI_FORMAT_R8G8_UNORM", + "channels": "rg", + "componentType": "unorm", + "bits": { "red": 8, "green": 8 }, + "glInternalFormat": "GL_RG8" + }, + "R8G8_SINT": { + "texFormat": "DXGI_FORMAT_R8G8_SINT", + "srvFormat": "DXGI_FORMAT_R8G8_SINT", + "rtvFormat": "DXGI_FORMAT_R8G8_SINT", + "channels": "rg", + "componentType": "int", + "bits": { "red": 8, "green": 8 }, + "glInternalFormat": "GL_RG8I" + }, + "R8G8_UINT": { + "texFormat": "DXGI_FORMAT_R8G8_UINT", + "srvFormat": "DXGI_FORMAT_R8G8_UINT", + "rtvFormat": "DXGI_FORMAT_R8G8_UINT", + "channels": "rg", + "componentType": "uint", + "bits": { "red": 8, "green": 8 }, + "glInternalFormat": "GL_RG8UI" + }, + "R8G8_SNORM": { + "texFormat": "DXGI_FORMAT_R8G8_SNORM", + "srvFormat": "DXGI_FORMAT_R8G8_SNORM", + "channels": "rg", + "componentType": "snorm", + "bits": { "red": 8, "green": 8 }, + "glInternalFormat": "GL_RG8_SNORM" + }, + "R10G10B10A2_UNORM": { + "texFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", + "srvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", + "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UNORM", + "channels": "rgba", + "componentType": "unorm", + "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 }, + "glInternalFormat": "GL_RGB10_A2" + }, + "R10G10B10A2_UINT": { + "texFormat": "DXGI_FORMAT_R10G10B10A2_UINT", + "srvFormat": "DXGI_FORMAT_R10G10B10A2_UINT", + "rtvFormat": "DXGI_FORMAT_R10G10B10A2_UINT", + "channels": "rgba", + "componentType": "uint", + "bits": { "red": 10, "green": 10, "blue": 10, "alpha": 2 }, + "glInternalFormat": "GL_RGB10_A2UI" + }, + "R16G16B16A16_SINT": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_SINT", + "channels": "rgba", + "componentType": "int", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16I" + }, + "R16G16B16A16_UINT": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UINT", + "channels": "rgba", + "componentType": "uint", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16UI" + }, + "R32G32B32A32_SINT": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_SINT", + "channels": "rgba", + "componentType": "int", + "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 }, + "glInternalFormat": "GL_RGBA32I" + }, + "R32G32B32A32_UINT": { + "texFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "srvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "rtvFormat": "DXGI_FORMAT_R32G32B32A32_UINT", + "channels": "rgba", + "componentType": "uint", + "bits": { "red": 32, "green": 32, "blue": 32, "alpha": 32 }, + "glInternalFormat": "GL_RGBA32UI" + }, + "B5G6R5_UNORM": { + "texFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "srvFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "rtvFormat": "DXGI_FORMAT_B5G6R5_UNORM", + "channels": "bgr", + "componentType": "unorm", + "bits": { "red": 5, "green": 6, "blue": 5 }, + "supportTest": "SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)", + "fallbackFormat": "R8G8B8A8_UNORM" + }, + "B5G5R5A1_UNORM": { + "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "srvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "rtvFormat": "DXGI_FORMAT_B5G5R5A1_UNORM", + "channels": "bgra", + "componentType": "unorm", + "bits": { "red": 5, "green": 5, "blue": 5, "alpha": 1 }, + "supportTest": "SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps)", + "fallbackFormat": "R8G8B8A8_UNORM" + }, + "R8G8B8A8_SINT": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_SINT", + "channels": "rgba", + "componentType": "int", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_RGBA8I" + }, + "R8G8B8A8_UINT": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UINT", + "channels": "rgba", + "componentType": "uint", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_RGBA8UI" + }, + "R8G8B8A8_SNORM": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_SNORM", + "channels": "rgba", + "componentType": "snorm", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_RGBA8_SNORM" + }, + "R9G9B9E5_SHAREDEXP": { + "texFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", + "srvFormat": "DXGI_FORMAT_R9G9B9E5_SHAREDEXP", + "channels": "rgb", + "componentType": "float", + "bits": { "red": 9, "green": 9, "blue": 9, "shared": 5 } + }, + "B4G4R4A4_UNORM": { + "texFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "srvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "rtvFormat": "DXGI_FORMAT_B4G4R4A4_UNORM", + "channels": "bgra", + "componentType": "unorm", + "bits": { "red": 4, "green": 4, "blue": 4, "alpha": 4 }, + "supportTest": "SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps)", + "fallbackFormat": "R8G8B8A8_UNORM" + }, + "R8G8B8A8_UNORM_SRGB": { + "texFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "srvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "rtvFormat": "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB", + "channels": "rgba", + "componentType": "unorm", + "bits": { "red": 8, "green": 8, "blue": 8, "alpha": 8 }, + "glInternalFormat": "GL_SRGB8_ALPHA8" + }, + "R16_UNORM": { + "texFormat": "DXGI_FORMAT_R16_UNORM", + "srvFormat": "DXGI_FORMAT_R16_UNORM", + "rtvFormat": "DXGI_FORMAT_R16_UNORM", + "channels": "r", + "componentType": "unorm", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16_EXT" + }, + "R16G16_UNORM": { + "texFormat": "DXGI_FORMAT_R16G16_UNORM", + "srvFormat": "DXGI_FORMAT_R16G16_UNORM", + "rtvFormat": "DXGI_FORMAT_R16G16_UNORM", + "channels": "rg", + "componentType": "unorm", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16_EXT" + }, + "R16_SNORM": { + "texFormat": "DXGI_FORMAT_R16_SNORM", + "srvFormat": "DXGI_FORMAT_R16_SNORM", + "channels": "r", + "componentType": "snorm", + "bits": { "red": 16 }, + "glInternalFormat": "GL_R16_SNORM_EXT" + }, + "R16G16_SNORM": { + "texFormat": "DXGI_FORMAT_R16G16_SNORM", + "srvFormat": "DXGI_FORMAT_R16G16_SNORM", + "channels": "rg", + "componentType": "snorm", + "bits": { "red": 16, "green": 16 }, + "glInternalFormat": "GL_RG16_SNORM_EXT" + }, + "R16G16B16A16_SNORM": { + "texFormat": "DXGI_FORMAT_R16G16B16A16_SNORM", + "srvFormat": "DXGI_FORMAT_R16G16B16A16_SNORM", + "channels": "rgba", + "componentType": "snorm", + "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }, + "glInternalFormat": "GL_RGBA16_SNORM_EXT" + } } diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json new file mode 100644 index 0000000000..3ef2355645 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json @@ -0,0 +1,78 @@ +{ + "GL_ALPHA16F_EXT": "R16G16B16A16_FLOAT", + "GL_ALPHA32F_EXT": "R32G32B32A32_FLOAT", + "GL_BGR5_A1_ANGLEX": "B8G8R8A8_UNORM", + "GL_BGRA4_ANGLEX": "B8G8R8A8_UNORM", + "GL_BGRA8_SRGB_ANGLEX": "B8G8R8A8_UNORM_SRGB", + "GL_COMPRESSED_R11_EAC": "R8_UNORM", + "GL_COMPRESSED_RG11_EAC": "R8G8_UNORM", + "GL_COMPRESSED_RGB8_ETC2": "R8G8B8A8_UNORM", + "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM", + "GL_COMPRESSED_RGBA8_ETC2_EAC": "R8G8B8A8_UNORM", + "GL_COMPRESSED_RGBA_ASTC_4x4_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_5x4_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_5x5_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_6x5_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_6x6_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_8x5_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_8x6_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_8x8_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_10x5_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_10x6_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_10x8_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_10x10_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_12x10_KHR": "NONE", + "GL_COMPRESSED_RGBA_ASTC_12x12_KHR": "NONE", + "GL_COMPRESSED_SIGNED_R11_EAC": "R8_SNORM", + "GL_COMPRESSED_SIGNED_RG11_EAC": "R8G8_SNORM", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR": "NONE", + "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": "R8G8B8A8_UNORM_SRGB", + "GL_COMPRESSED_SRGB8_ETC2": "R8G8B8A8_UNORM_SRGB", + "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2": "R8G8B8A8_UNORM_SRGB", + "GL_DEPTH_COMPONENT24": "D24_UNORM_S8_UINT", + "GL_DEPTH_COMPONENT32_OES": "D24_UNORM_S8_UINT", + "GL_ETC1_RGB8_OES": "R8G8B8A8_UNORM", + "GL_ETC1_RGB8_LOSSY_DECODE_ANGLE": "BC1_RGB_UNORM_BLOCK", + "GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_BLOCK", + "GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGB_UNORM_SRGB_BLOCK", + "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_BLOCK", + "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE": "BC1_RGBA_UNORM_SRGB_BLOCK", + "GL_LUMINANCE16F_EXT": "R16G16B16A16_FLOAT", + "GL_LUMINANCE32F_EXT": "R32G32B32A32_FLOAT", + "GL_LUMINANCE8_ALPHA8_EXT": "R8G8B8A8_UNORM", + "GL_LUMINANCE8_EXT": "R8G8B8A8_UNORM", + "GL_LUMINANCE_ALPHA16F_EXT": "R16G16B16A16_FLOAT", + "GL_LUMINANCE_ALPHA32F_EXT": "R32G32B32A32_FLOAT", + "GL_RGB": "R8G8B8A8_UNORM", + "GL_RGB16F": "R16G16B16A16_FLOAT", + "GL_RGB16I": "R16G16B16A16_SINT", + "GL_RGB16UI": "R16G16B16A16_UINT", + "GL_RGB565": "B5G6R5_UNORM", + "GL_RGB5_A1": "B5G5R5A1_UNORM", + "GL_RGB8": "R8G8B8A8_UNORM", + "GL_RGB8I": "R8G8B8A8_SINT", + "GL_RGB8UI": "R8G8B8A8_UINT", + "GL_RGB8_SNORM": "R8G8B8A8_SNORM", + "GL_RGBA4": "B4G4R4A4_UNORM", + "GL_SRGB8": "R8G8B8A8_UNORM_SRGB", + "GL_STENCIL_INDEX8": "D24_UNORM_S8_UINT", + "GL_RGB16_EXT": "R16G16B16A16_UNORM", + "GL_RGBA16_EXT": "R16G16B16A16_UNORM", + "GL_RGB16_SNORM_EXT": "R16G16B16A16_SNORM", + "GL_RGB32F": "R32G32B32A32_FLOAT", + "GL_RGB32I": "R32G32B32A32_SINT", + "GL_RGB32UI": "R32G32B32A32_UINT" +} diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp new file mode 100644 index 0000000000..a9dfec56b8 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table.cpp @@ -0,0 +1,35 @@ +// +// Copyright 2016 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. +// +// Helper routines for the D3D11 texture format table. + +#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" + +#include "libANGLE/renderer/load_functions_table.h" + +namespace rx +{ + +namespace d3d11 +{ + +const Format &Format::getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const +{ + return (swizzleFormat == internalFormat ? *this : Format::Get(swizzleFormat, deviceCaps)); +} + +LoadFunctionMap Format::getLoadFunctions() const +{ + return GetLoadFunctionsMap(internalFormat, formatID); +} + +const angle::Format &Format::format() const +{ + return angle::Format::Get(formatID); +} + +} // namespace d3d11 + +} // namespace rx 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 index 1606a28a73..3efcb81adb 100644 --- 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 @@ -12,50 +12,91 @@ #include +#include "common/angleutils.h" #include "common/platform.h" +#include "libANGLE/renderer/Format.h" +#include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/d3d/formatutilsD3D.h" -#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" namespace rx { -namespace d3d11 -{ +struct Renderer11DeviceCaps; -struct LoadImageFunctionInfo +namespace d3d11 { - LoadImageFunctionInfo() : loadFunction(nullptr), requiresConversion(false) {} - LoadImageFunctionInfo(LoadImageFunction loadFunction, bool requiresConversion) - : loadFunction(loadFunction), requiresConversion(requiresConversion) - { - } - - LoadImageFunction loadFunction; - bool requiresConversion; -}; -struct TextureFormat +// For sized GL internal formats, there are several possible corresponding D3D11 formats depending +// on device capabilities. +// This structure allows querying for the DXGI texture formats to use for textures, SRVs, RTVs and +// DSVs given a GL internal format. +struct Format final : private angle::NonCopyable { - TextureFormat(); + constexpr Format(); + constexpr Format(GLenum internalFormat, + angle::Format::ID formatID, + DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, + DXGI_FORMAT rtvFormat, + DXGI_FORMAT dsvFormat, + DXGI_FORMAT blitSRVFormat, + GLenum swizzleFormat, + InitializeTextureDataFunction internalFormatInitializer); + + static const Format &Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps); + + const Format &getSwizzleFormat(const Renderer11DeviceCaps &deviceCaps) const; + LoadFunctionMap getLoadFunctions() const; + const angle::Format &format() const; + + GLenum internalFormat; + angle::Format::ID formatID; DXGI_FORMAT texFormat; DXGI_FORMAT srvFormat; DXGI_FORMAT rtvFormat; DXGI_FORMAT dsvFormat; - DXGI_FORMAT renderFormat; - DXGI_FORMAT swizzleTexFormat; - DXGI_FORMAT swizzleSRVFormat; - DXGI_FORMAT swizzleRTVFormat; + DXGI_FORMAT blitSRVFormat; - InitializeTextureDataFunction dataInitializerFunction; - typedef std::map LoadFunctionMap; + GLenum swizzleFormat; - LoadFunctionMap loadFunctions; + InitializeTextureDataFunction dataInitializerFunction; }; -const TextureFormat &GetTextureFormatInfo(GLenum internalformat, - const Renderer11DeviceCaps &renderer11DeviceCaps); +constexpr Format::Format() + : internalFormat(GL_NONE), + formatID(angle::Format::ID::NONE), + texFormat(DXGI_FORMAT_UNKNOWN), + srvFormat(DXGI_FORMAT_UNKNOWN), + rtvFormat(DXGI_FORMAT_UNKNOWN), + dsvFormat(DXGI_FORMAT_UNKNOWN), + blitSRVFormat(DXGI_FORMAT_UNKNOWN), + swizzleFormat(GL_NONE), + dataInitializerFunction(nullptr) +{ +} + +constexpr Format::Format(GLenum internalFormat, + angle::Format::ID formatID, + DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, + DXGI_FORMAT rtvFormat, + DXGI_FORMAT dsvFormat, + DXGI_FORMAT blitSRVFormat, + GLenum swizzleFormat, + InitializeTextureDataFunction internalFormatInitializer) + : internalFormat(internalFormat), + formatID(formatID), + texFormat(texFormat), + srvFormat(srvFormat), + rtvFormat(rtvFormat), + dsvFormat(dsvFormat), + blitSRVFormat(blitSRVFormat), + swizzleFormat(swizzleFormat), + dataInitializerFunction(internalFormatInitializer) +{ +} } // namespace d3d11 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 index 0b214c9756..3c1c2bcd50 100644 --- 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 @@ -1,7 +1,7 @@ // 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. +// Copyright 2017 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. // @@ -11,12 +11,15 @@ #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h" +#include "image_util/copyimage.h" +#include "image_util/generatemip.h" +#include "image_util/loadimage.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" +#include "libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h" + +using namespace angle; namespace rx { @@ -24,1756 +27,1899 @@ 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) +// static +const Format &Format::Get(GLenum internalFormat, const Renderer11DeviceCaps &deviceCaps) { // 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; - } + static constexpr Format info(GL_ALPHA16F_EXT, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_ALPHA32F_EXT, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + nullptr); + return info; } 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)) + if (OnlyFL10Plus(deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; + static constexpr Format info(GL_ALPHA8_EXT, + angle::Format::ID::A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_A8_UNORM, + GL_RGBA8, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_ALPHA8_EXT, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; } } - case GL_BGR5_A1_ANGLEX: + case GL_BGR565_ANGLEX: { - if (AnyDevice(renderer11DeviceCaps)) + if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; + static constexpr Format info(GL_BGR565_ANGLEX, + angle::Format::ID::B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B5G6R5_UNORM, + GL_RGBA8, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_BGR565_ANGLEX, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; } } - case GL_BGRA4_ANGLEX: + 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; - } + static constexpr Format info(GL_BGR5_A1_ANGLEX, + angle::Format::ID::B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM, + GL_BGRA8_EXT, + nullptr); + return info; } - case GL_BGRA8_EXT: + 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; - } + static constexpr Format info(GL_BGRA4_ANGLEX, + angle::Format::ID::B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM, + GL_BGRA8_EXT, + nullptr); + return info; } - case GL_BGRA_EXT: + 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; - } + static constexpr Format info(GL_BGRA8_EXT, + angle::Format::ID::B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM, + GL_BGRA8_EXT, + nullptr); + return info; + } + case GL_BGRA8_SRGB_ANGLEX: + { + static constexpr Format info(GL_BGRA8_SRGB_ANGLEX, + angle::Format::ID::B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, + GL_BGRA8_SRGB_ANGLEX, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_R11_EAC, + angle::Format::ID::R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_RG11_EAC, + angle::Format::ID::R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_RGB8_ETC2, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData); + return info; + } + case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE, + angle::Format::ID::BC1_RGB_UNORM_BLOCK, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData); + return info; + } + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, + angle::Format::ID::BC1_RGBA_UNORM_BLOCK, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_RGBA8_ETC2_EAC, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x10_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_10x8_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x10_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_12x12_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_4x4_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x4_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_5x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_6x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: + { + static constexpr Format info(GL_COMPRESSED_RGBA_ASTC_8x8_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + angle::Format::ID::BC1_RGBA_UNORM_BLOCK, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, + angle::Format::ID::BC2_RGBA_UNORM_BLOCK, + DXGI_FORMAT_BC2_UNORM, + DXGI_FORMAT_BC2_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC2_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, + angle::Format::ID::BC3_RGBA_UNORM_BLOCK, + DXGI_FORMAT_BC3_UNORM, + DXGI_FORMAT_BC3_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC3_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + angle::Format::ID::BC1_RGB_UNORM_BLOCK, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_SIGNED_R11_EAC, + angle::Format::ID::R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_SIGNED_RG11_EAC, + angle::Format::ID::R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_SRGB8_ETC2, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + Initialize4ComponentData); + return info; + } + case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE, + angle::Format::ID::BC1_RGB_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE: + { + static constexpr Format info(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE, + angle::Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: + { + static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, + angle::Format::ID::BC1_RGBA_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: + { + static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, + angle::Format::ID::BC2_RGBA_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC2_UNORM_SRGB, + DXGI_FORMAT_BC2_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC2_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: + { + static constexpr Format info(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, + angle::Format::ID::BC3_RGBA_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC3_UNORM_SRGB, + DXGI_FORMAT_BC3_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC3_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; + } + case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: + { + static constexpr Format info(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, + angle::Format::ID::BC1_RGB_UNORM_SRGB_BLOCK, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_BC1_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM_SRGB, + GL_RGBA8, + nullptr); + return info; } 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)) + if (OnlyFL10Plus(deviceCaps)) { - 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; + static constexpr Format info(GL_DEPTH24_STENCIL8, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + GL_RGBA32F, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_DEPTH24_STENCIL8, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + GL_RGBA32F, + nullptr); + return info; } } 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; - } + static constexpr Format info(GL_DEPTH32F_STENCIL8, + angle::Format::ID::D32_FLOAT_S8X24_UINT, + DXGI_FORMAT_R32G8X24_TYPELESS, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D32_FLOAT_S8X24_UINT, + DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, + GL_RGBA32F, + nullptr); + return info; } case GL_DEPTH_COMPONENT16: { - if (OnlyFL9_3(renderer11DeviceCaps)) + if (OnlyFL10Plus(deviceCaps)) { - 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; + static constexpr Format info(GL_DEPTH_COMPONENT16, + angle::Format::ID::D16_UNORM, + DXGI_FORMAT_R16_TYPELESS, + DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D16_UNORM, + DXGI_FORMAT_R16_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_DEPTH_COMPONENT16, + angle::Format::ID::D16_UNORM, + DXGI_FORMAT_D16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D16_UNORM, + DXGI_FORMAT_UNKNOWN, + GL_RGBA16_EXT, + nullptr); + return info; } } 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)) + if (OnlyFL10Plus(deviceCaps)) { - 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; + static constexpr Format info(GL_DEPTH_COMPONENT24, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + GL_RGBA32F, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_DEPTH_COMPONENT24, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + GL_RGBA32F, + nullptr); + return info; } } 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; - } + static constexpr Format info(GL_DEPTH_COMPONENT32F, + angle::Format::ID::D32_FLOAT, + DXGI_FORMAT_R32_TYPELESS, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + GL_RGBA32F, + nullptr); + return info; } case GL_DEPTH_COMPONENT32_OES: { - if (OnlyFL10Plus(renderer11DeviceCaps)) + if (OnlyFL10Plus(deviceCaps)) { - 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; + static constexpr Format info(GL_DEPTH_COMPONENT32_OES, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + GL_RGBA32F, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_DEPTH_COMPONENT32_OES, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + GL_RGBA32F, + nullptr); + return info; } } 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; - } + static constexpr Format info(GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, + angle::Format::ID::BC1_RGB_UNORM_BLOCK, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_BC1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_BC1_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_ETC1_RGB8_OES, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_LUMINANCE16F_EXT, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_LUMINANCE32F_EXT, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_LUMINANCE8_ALPHA8_EXT, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_LUMINANCE8_EXT, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_LUMINANCE_ALPHA16F_EXT, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_LUMINANCE_ALPHA32F_EXT, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_NONE, + angle::Format::ID::NONE, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + GL_NONE, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R11F_G11F_B10F, + angle::Format::ID::R11G11B10_FLOAT, + DXGI_FORMAT_R11G11B10_FLOAT, + DXGI_FORMAT_R11G11B10_FLOAT, + DXGI_FORMAT_R11G11B10_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R11G11B10_FLOAT, + GL_RGBA16F_EXT, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R16F, + angle::Format::ID::R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_FLOAT, + GL_RGBA16F_EXT, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R16I, + angle::Format::ID::R16_SINT, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_R16_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_SINT, + GL_RGBA16I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R16UI, + angle::Format::ID::R16_UINT, + DXGI_FORMAT_R16_UINT, + DXGI_FORMAT_R16_UINT, + DXGI_FORMAT_R16_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_UINT, + GL_RGBA16I, + nullptr); + return info; + } + case GL_R16_EXT: + { + static constexpr Format info(GL_R16_EXT, + angle::Format::ID::R16_UNORM, + DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; + } + case GL_R16_SNORM_EXT: + { + static constexpr Format info(GL_R16_SNORM_EXT, + angle::Format::ID::R16_SNORM, + DXGI_FORMAT_R16_SNORM, + DXGI_FORMAT_R16_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16_SNORM, + GL_RGBA16_SNORM_EXT, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R32F, + angle::Format::ID::R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32_FLOAT, + GL_RGBA32F, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R32I, + angle::Format::ID::R32_SINT, + DXGI_FORMAT_R32_SINT, + DXGI_FORMAT_R32_SINT, + DXGI_FORMAT_R32_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32_SINT, + GL_RGBA32I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R32UI, + angle::Format::ID::R32_UINT, + DXGI_FORMAT_R32_UINT, + DXGI_FORMAT_R32_UINT, + DXGI_FORMAT_R32_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32_UINT, + GL_RGBA32I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R8, + angle::Format::ID::R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_R8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R8I, + angle::Format::ID::R8_SINT, + DXGI_FORMAT_R8_SINT, + DXGI_FORMAT_R8_SINT, + DXGI_FORMAT_R8_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_SINT, + GL_RGBA8I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R8UI, + angle::Format::ID::R8_UINT, + DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_R8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_UINT, + GL_RGBA8I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_R8_SNORM, + angle::Format::ID::R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_R8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG16F, + angle::Format::ID::R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_R16G16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_FLOAT, + GL_RGBA16F_EXT, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG16I, + angle::Format::ID::R16G16_SINT, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_R16G16_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_SINT, + GL_RGBA16I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG16UI, + angle::Format::ID::R16G16_UINT, + DXGI_FORMAT_R16G16_UINT, + DXGI_FORMAT_R16G16_UINT, + DXGI_FORMAT_R16G16_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_UINT, + GL_RGBA16I, + nullptr); + return info; + } + case GL_RG16_EXT: + { + static constexpr Format info(GL_RG16_EXT, + angle::Format::ID::R16G16_UNORM, + DXGI_FORMAT_R16G16_UNORM, + DXGI_FORMAT_R16G16_UNORM, + DXGI_FORMAT_R16G16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; + } + case GL_RG16_SNORM_EXT: + { + static constexpr Format info(GL_RG16_SNORM_EXT, + angle::Format::ID::R16G16_SNORM, + DXGI_FORMAT_R16G16_SNORM, + DXGI_FORMAT_R16G16_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16_SNORM, + GL_RGBA16_SNORM_EXT, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG32F, + angle::Format::ID::R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_R32G32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32_FLOAT, + GL_RGBA32F, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG32I, + angle::Format::ID::R32G32_SINT, + DXGI_FORMAT_R32G32_SINT, + DXGI_FORMAT_R32G32_SINT, + DXGI_FORMAT_R32G32_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32_SINT, + GL_RGBA32I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG32UI, + angle::Format::ID::R32G32_UINT, + DXGI_FORMAT_R32G32_UINT, + DXGI_FORMAT_R32G32_UINT, + DXGI_FORMAT_R32G32_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32_UINT, + GL_RGBA32I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG8, + angle::Format::ID::R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_R8G8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG8I, + angle::Format::ID::R8G8_SINT, + DXGI_FORMAT_R8G8_SINT, + DXGI_FORMAT_R8G8_SINT, + DXGI_FORMAT_R8G8_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_SINT, + GL_RGBA8I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG8UI, + angle::Format::ID::R8G8_UINT, + DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_R8G8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_UINT, + GL_RGBA8I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RG8_SNORM, + angle::Format::ID::R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_R8G8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGB, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB10_A2, + angle::Format::ID::R10G10B10A2_UNORM, + DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_R10G10B10A2_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R10G10B10A2_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGB10_A2UI, + angle::Format::ID::R10G10B10A2_UINT, + DXGI_FORMAT_R10G10B10A2_UINT, + DXGI_FORMAT_R10G10B10A2_UINT, + DXGI_FORMAT_R10G10B10A2_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R10G10B10A2_UINT, + GL_RGBA16I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGB16F, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB16I, + angle::Format::ID::R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_SINT, + GL_RGBA16I, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB16UI, + angle::Format::ID::R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UINT, + GL_RGBA16UI, + Initialize4ComponentData); + return info; + } + case GL_RGB16_EXT: + { + static constexpr Format info(GL_RGB16_EXT, + angle::Format::ID::R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UNORM, + GL_RGBA16_EXT, + Initialize4ComponentData); + return info; + } + case GL_RGB16_SNORM_EXT: + { + static constexpr Format info(GL_RGB16_SNORM_EXT, + angle::Format::ID::R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_SNORM, + GL_RGBA16_SNORM_EXT, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB32F, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB32I, + angle::Format::ID::R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_SINT, + GL_RGBA32I, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB32UI, + angle::Format::ID::R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_UINT, + GL_RGBA32UI, + Initialize4ComponentData); + return info; } case GL_RGB565: { - if (SupportsFormat(renderer11DeviceCaps)) + if (SupportsFormat(DXGI_FORMAT_B5G6R5_UNORM, deviceCaps)) { - 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; + static constexpr Format info(GL_RGB565, + angle::Format::ID::B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_B5G6R5_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B5G6R5_UNORM, + GL_RGBA8, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_RGB565, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData); + return info; } } 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)) + if (SupportsFormat(DXGI_FORMAT_B5G5R5A1_UNORM, deviceCaps)) { - static const TextureFormat textureFormat = GetD3D11FormatInfo(internalFormat, - DXGI_FORMAT_B5G5R5A1_UNORM, - DXGI_FORMAT_B5G5R5A1_UNORM, - DXGI_FORMAT_B5G5R5A1_UNORM, - DXGI_FORMAT_UNKNOWN); - return textureFormat; + static constexpr Format info(GL_RGB5_A1, + angle::Format::ID::B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_B5G5R5A1_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B5G5R5A1_UNORM, + GL_RGBA8, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_RGB5_A1, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; } } 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; - } + static constexpr Format info(GL_RGB8, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB8I, + angle::Format::ID::R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_SINT, + GL_RGBA8I, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB8UI, + angle::Format::ID::R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UINT, + GL_RGBA8UI, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB8_SNORM, + angle::Format::ID::R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_SNORM, + GL_RGBA8_SNORM, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_RGB9_E5, + angle::Format::ID::R9G9B9E5_SHAREDEXP, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R9G9B9E5_SHAREDEXP, + GL_RGBA16F_EXT, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA16F, + angle::Format::ID::R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_R16G16B16A16_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_FLOAT, + GL_RGBA16F, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA16I, + angle::Format::ID::R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_R16G16B16A16_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_SINT, + GL_RGBA16I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA16UI, + angle::Format::ID::R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_R16G16B16A16_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UINT, + GL_RGBA16UI, + nullptr); + return info; + } + case GL_RGBA16_EXT: + { + static constexpr Format info(GL_RGBA16_EXT, + angle::Format::ID::R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_R16G16B16A16_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_UNORM, + GL_RGBA16_EXT, + nullptr); + return info; + } + case GL_RGBA16_SNORM_EXT: + { + static constexpr Format info(GL_RGBA16_SNORM_EXT, + angle::Format::ID::R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_R16G16B16A16_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R16G16B16A16_SNORM, + GL_RGBA16_SNORM_EXT, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA32F, + angle::Format::ID::R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_FLOAT, + GL_RGBA32F, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA32I, + angle::Format::ID::R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_R32G32B32A32_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_SINT, + GL_RGBA32I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA32UI, + angle::Format::ID::R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_R32G32B32A32_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R32G32B32A32_UINT, + GL_RGBA32UI, + nullptr); + return info; } case GL_RGBA4: { - if (SupportsFormat(renderer11DeviceCaps)) + if (SupportsFormat(DXGI_FORMAT_B4G4R4A4_UNORM, deviceCaps)) { - 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; + static constexpr Format info(GL_RGBA4, + angle::Format::ID::B4G4R4A4_UNORM, + DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_B4G4R4A4_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_B4G4R4A4_UNORM, + GL_RGBA4, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_RGBA4, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; } } 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; - } + static constexpr Format info(GL_RGBA8, + angle::Format::ID::R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM, + GL_RGBA8, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA8I, + angle::Format::ID::R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_R8G8B8A8_SINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_SINT, + GL_RGBA8I, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA8UI, + angle::Format::ID::R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_R8G8B8A8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UINT, + GL_RGBA8UI, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_RGBA8_SNORM, + angle::Format::ID::R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_R8G8B8A8_SNORM, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_SNORM, + GL_RGBA8_SNORM, + nullptr); + return info; } 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; - } + static constexpr Format info(GL_SRGB8, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + Initialize4ComponentData); + return info; } 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; - } + static constexpr Format info(GL_SRGB8_ALPHA8, + angle::Format::ID::R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + GL_SRGB8_ALPHA8, + nullptr); + return info; } case GL_STENCIL_INDEX8: { - if (OnlyFL9_3(renderer11DeviceCaps)) + if (OnlyFL10Plus(deviceCaps)) { - 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; + static constexpr Format info(GL_STENCIL_INDEX8, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_R24G8_TYPELESS, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_R24_UNORM_X8_TYPELESS, + GL_RGBA32F, + nullptr); + return info; } else { - break; + static constexpr Format info(GL_STENCIL_INDEX8, + angle::Format::ID::D24_UNORM_S8_UINT, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_UNKNOWN, + GL_RGBA32F, + nullptr); + return info; } } @@ -1782,9 +1928,10 @@ const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, } // clang-format on - static const TextureFormat defaultInfo; + UNREACHABLE(); + static constexpr Format defaultInfo; return defaultInfo; -} // GetTextureFormatInfo +} } // namespace d3d11 diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h new file mode 100644 index 0000000000..d5351ff882 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/texture_format_table_utils.h @@ -0,0 +1,85 @@ +// +// Copyright 2016 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. +// +// Helper routines for the D3D11 texture format table. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_ + +#include "libANGLE/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +namespace d3d11 +{ + +using FormatSupportFunction = bool (*)(const Renderer11DeviceCaps &); + +inline bool OnlyFL10Plus(const Renderer11DeviceCaps &deviceCaps) +{ + return (deviceCaps.featureLevel >= D3D_FEATURE_LEVEL_10_0); +} + +inline bool OnlyFL9_3(const Renderer11DeviceCaps &deviceCaps) +{ + return (deviceCaps.featureLevel == D3D_FEATURE_LEVEL_9_3); +} + +inline bool SupportsFormat(DXGI_FORMAT format, 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; + UINT minimumRequiredSamples = 0; + + if (d3d11_gl::GetMaximumClientVersion(deviceCaps.featureLevel).major > 2) + { + mustSupport |= D3D11_FORMAT_SUPPORT_TEXTURE3D; + + // RGBA4, RGB5A1 and RGB565 are all required multisampled renderbuffer formats in ES3 and + // need to support a minimum of 4 samples. + minimumRequiredSamples = 4; + } + + 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) && + deviceCaps.B5G6R5maxSamples >= minimumRequiredSamples; + } + else if (format == DXGI_FORMAT_B4G4R4A4_UNORM) + { + fullSupport = ((deviceCaps.B4G4R4A4support & mustSupport) == mustSupport) && + deviceCaps.B4G4R4A4maxSamples >= minimumRequiredSamples; + } + else if (format == DXGI_FORMAT_B5G5R5A1_UNORM) + { + fullSupport = ((deviceCaps.B5G5R5A1support & mustSupport) == mustSupport) && + deviceCaps.B5G5R5A1maxSamples >= minimumRequiredSamples; + } + else + { + UNREACHABLE(); + return false; + } + + // 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; +} + +} // namespace d3d11 + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURE_FORMAT_TABLE_UTILS_H_ 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 deleted file mode 100644 index da6460b136..0000000000 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp +++ /dev/null @@ -1,220 +0,0 @@ -// -// Copyright (c) 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. -// - -// 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, - 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; -} - -bool NativeWindow::getClientRect(LPRECT rect) -{ - return GetClientRect(mWindow, rect) == TRUE; -} - -bool NativeWindow::isIconic() -{ - return IsIconic(mWindow) == TRUE; -} - -bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window) -{ - return IsWindow(window) == TRUE; -} - -#if defined(ANGLE_ENABLE_D3D11) -HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory, - DXGI_FORMAT format, unsigned int width, unsigned int height, - DXGISwapChain** swapChain) -{ - if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) - { - return E_INVALIDARG; - } - -#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; - swapChainDesc.BufferDesc.Height = height; - swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - 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_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; - swapChainDesc.Flags = 0; - swapChainDesc.OutputWindow = mWindow; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - swapChainDesc.Windowed = TRUE; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - - const HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain); - if (SUCCEEDED(result)) - { - const HRESULT makeWindowAssociationResult = factory->MakeWindowAssociation(mWindow, DXGI_MWA_NO_ALT_ENTER); - 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/win32/NativeWindow11Win32.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp new file mode 100644 index 0000000000..5394e3d3e7 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp @@ -0,0 +1,217 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11Win32.cpp: Implementation of NativeWindow11 using win32 window APIs. + +#include "libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h" +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" + +#include "common/debug.h" + +#include +#include + +namespace rx +{ + +NativeWindow11Win32::NativeWindow11Win32(EGLNativeWindowType window, + bool hasAlpha, + bool directComposition) + : NativeWindow11(window), + mDirectComposition(directComposition), + mHasAlpha(hasAlpha), + mDevice(nullptr), + mCompositionTarget(nullptr), + mVisual(nullptr) +{ +} + +NativeWindow11Win32::~NativeWindow11Win32() +{ + SafeRelease(mCompositionTarget); + SafeRelease(mDevice); + SafeRelease(mVisual); +} + +bool NativeWindow11Win32::initialize() +{ + return true; +} + +bool NativeWindow11Win32::getClientRect(LPRECT rect) const +{ + return GetClientRect(getNativeWindow(), rect) == TRUE; +} + +bool NativeWindow11Win32::isIconic() const +{ + return IsIconic(getNativeWindow()) == TRUE; +} + +HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + UINT samples, + IDXGISwapChain **swapChain) +{ + if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 || + height == 0) + { + return E_INVALIDARG; + } + + 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(getNativeWindow(), 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 = + mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; + 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 = samples; + 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, getNativeWindow(), &swapChainDesc, + nullptr, nullptr, &swapChain1); + if (SUCCEEDED(result)) + { + factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); + *swapChain = static_cast(swapChain1); + } + SafeRelease(factory2); + return result; + } + + DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; + swapChainDesc.BufferCount = 1; + swapChainDesc.BufferDesc.Format = format; + swapChainDesc.BufferDesc.Width = width; + swapChainDesc.BufferDesc.Height = height; + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + 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_SHADER_INPUT | DXGI_USAGE_BACK_BUFFER; + swapChainDesc.Flags = 0; + swapChainDesc.OutputWindow = getNativeWindow(); + swapChainDesc.SampleDesc.Count = samples; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain); + if (SUCCEEDED(result)) + { + factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); + } + return result; +} + +void NativeWindow11Win32::commitChange() +{ + if (mDevice) + { + mDevice->Commit(); + } +} + +// static +bool NativeWindow11Win32::IsValidNativeWindow(EGLNativeWindowType window) +{ + return IsWindow(window) == TRUE; +} +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h new file mode 100644 index 0000000000..baeba6a347 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11Win32.h: Implementation of NativeWindow11 using win32 window APIs. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_ + +#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h" + +typedef interface IDCompositionDevice IDCompositionDevice; +typedef interface IDCompositionTarget IDCompositionTarget; +typedef interface IDCompositionVisual IDCompositionVisual; + +namespace rx +{ + +class NativeWindow11Win32 : public NativeWindow11 +{ + public: + NativeWindow11Win32(EGLNativeWindowType window, bool hasAlpha, bool directComposition); + ~NativeWindow11Win32() override; + + bool initialize() override; + bool getClientRect(LPRECT rect) const override; + bool isIconic() const override; + + HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + UINT samples, + IDXGISwapChain **swapChain) override; + + void commitChange() override; + + static bool IsValidNativeWindow(EGLNativeWindowType window); + + private: + bool mDirectComposition; + bool mHasAlpha; + IDCompositionDevice *mDevice; + IDCompositionTarget *mCompositionTarget; + IDCompositionVisual *mVisual; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WIN32_NATIVEWINDOW11WIN32_H_ 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 f401db614b..1ef90e7b09 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 @@ -8,6 +8,8 @@ #include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" +#include + using namespace ABI::Windows::Foundation::Collections; namespace rx @@ -19,7 +21,6 @@ CoreWindowNativeWindow::~CoreWindowNativeWindow() bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) { - mOrientationChangedEventToken.value = 0; ComPtr props = propertySet; ComPtr win = window; SIZE swapChainSize = {}; @@ -63,7 +64,8 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet // 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."); + ERR() << "It is invalid to specify both an EGLRenderSurfaceSizeProperty and a " + "EGLRenderResolutionScaleProperty."; return false; } } @@ -87,26 +89,16 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet } else { - SIZE coreWindowSize; + Size coreWindowSize; result = GetCoreWindowSizeInPixels(mCoreWindow, &coreWindowSize); if (SUCCEEDED(result)) { - mClientRect = { 0, 0, static_cast(coreWindowSize.cx * mSwapChainScale), static_cast(coreWindowSize.cy * mSwapChainScale) }; + mClientRect = clientRect(coreWindowSize); } } } - if (SUCCEEDED(result)) - { - ComPtr displayInformation; - result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), &displayInformation); - if (SUCCEEDED(result)) - { - result = displayInformation->GetForCurrentView(&mDisplayInformation); - } - } - if (SUCCEEDED(result)) { mNewClientRect = mClientRect; @@ -126,16 +118,6 @@ bool CoreWindowNativeWindow::registerForSizeChangeEvents() result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); } -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - ComPtr orientationChangedHandler; - result = sizeChangedHandler.As(&orientationChangedHandler); - if (SUCCEEDED(result)) - { - result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken); - orientationChangedHandler->Invoke(mDisplayInformation.Get(), nullptr); - } -#endif - if (SUCCEEDED(result)) { return true; @@ -150,34 +132,26 @@ 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, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) + IDXGISwapChain1 **swapChain) { - if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 || + height == 0) { return E_INVALIDARG; } DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; - swapChainDesc.Width = mRotationFlags ? height : width; - swapChainDesc.Height = mRotationFlags ? width : height; + swapChainDesc.Width = width; + swapChainDesc.Height = height; swapChainDesc.Format = format; swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc.Count = 1; @@ -195,17 +169,6 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, HRESULT result = factory->CreateSwapChainForCoreWindow(device, mCoreWindow.Get(), &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); if (SUCCEEDED(result)) { - -#if 0 //(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // Qt: allow Windows Phone to resize, but don't modify the backing texture in the swap chain. - // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On - // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed - // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations. - if (newSwapChain->ResizeBuffers(swapChainDesc.BufferCount, swapChainDesc.Width, swapChainDesc.Height, swapChainDesc.Format, DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) == DXGI_ERROR_UNSUPPORTED) - { - mSupportsSwapChainResize = false; - } -#endif // (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) - result = newSwapChain.CopyTo(swapChain); } @@ -222,14 +185,16 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, return result; } -inline HRESULT CoreWindowNativeWindow::scaleSwapChain(const Size &windowSize, const RECT &clientRect) +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) +HRESULT GetCoreWindowSizeInPixels(const ComPtr &coreWindow, + Size *windowSize) { ABI::Windows::Foundation::Rect bounds; HRESULT result = coreWindow->get_Bounds(&bounds); 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 fc1cd124a1..21855c2c3b 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 @@ -12,10 +12,10 @@ #include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" #include -#include + +#include typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler; -typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CDisplay__CDisplayInformation_IInspectable_t IDisplayOrientationEventHandler; namespace rx { @@ -26,12 +26,12 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override; HRESULT createSwapChain(ID3D11Device *device, - DXGIFactory *factory, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) override; + IDXGISwapChain1 **swapChain) override; protected: HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override; @@ -42,13 +42,11 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl private: ComPtr mCoreWindow; ComPtr> mPropertyMap; - ComPtr mDisplayInformation; - EventRegistrationToken mOrientationChangedEventToken; }; [uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)] class CoreWindowSizeChangedHandler : - public Microsoft::WRL::RuntimeClass, IWindowSizeChangedEventHandler, IDisplayOrientationEventHandler> + public Microsoft::WRL::RuntimeClass, IWindowSizeChangedEventHandler> { public: CoreWindowSizeChangedHandler() { } @@ -72,47 +70,21 @@ class CoreWindowSizeChangedHandler : ABI::Windows::Foundation::Size windowSize; if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize))) { - host->setNewClientSize(windowSize); + Size windowSizeInPixels = {ConvertDipsToPixels(windowSize.Width), + ConvertDipsToPixels(windowSize.Height)}; + host->setNewClientSize(windowSizeInPixels); } } 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))) - { - 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; - } - - private: std::weak_ptr mHost; }; -HRESULT GetCoreWindowSizeInPixels(const ComPtr& coreWindow, SIZE *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 aacfadd2f0..1bd796e58f 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,108 +11,6 @@ namespace rx { -NativeWindow::NativeWindow(EGLNativeWindowType window, - const egl::Config *config, - bool directComposition) -{ - mWindow = window; - mConfig = config; -} - -NativeWindow::~NativeWindow() -{ -} - -void NativeWindow::commitChange() -{ -} - -bool NativeWindow::initialize() -{ - // If the native window type is a IPropertySet, extract the - // EGLNativeWindowType (IInspectable) and initialize the - // proper host with this IPropertySet. - ComPtr propertySet; - ComPtr eglNativeWindow; - if (IsEGLConfiguredPropertySet(mWindow, &propertySet, &eglNativeWindow)) - { - // A property set was found and the EGLNativeWindowType was - // retrieved. The mWindow member of the host to must be updated - // to use the EGLNativeWindowType specified in the property set. - // mWindow is treated as a raw pointer not an AddRef'd interface, so - // the old mWindow does not need a Release() before this assignment. - mWindow = eglNativeWindow.Get(); - } - - ComPtr coreWindow; - ComPtr swapChainPanel; - if (IsCoreWindow(mWindow, &coreWindow)) - { - mImpl = std::make_shared(); - if (mImpl) - { - return mImpl->initialize(mWindow, propertySet.Get()); - } - } - else if (IsSwapChainPanel(mWindow, &swapChainPanel)) - { - mImpl = std::make_shared(); - if (mImpl) - { - return mImpl->initialize(mWindow, propertySet.Get()); - } - } - else - { - ERR("Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include ICoreWindow, ISwapChainPanel and IPropertySet"); - } - - return false; -} - -bool NativeWindow::getClientRect(RECT *rect) -{ - if (mImpl) - { - return mImpl->getClientRect(rect); - } - - return false; -} - -#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) -NativeWindow::RotationFlags NativeWindow::rotationFlags() const -{ - if (mImpl) - { - return mImpl->rotationFlags(); - } - - return NativeWindow::RotateNone; -} -#endif - -bool NativeWindow::isIconic() -{ - return false; -} - -bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window) -{ - return IsValidEGLNativeWindowType(window); -} - -HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) -{ - if (mImpl) - { - bool containsAlpha = (mConfig->alphaSize > 0); - return mImpl->createSwapChain(device, factory, format, width, height, containsAlpha, - swapChain); - } - - return E_UNEXPECTED; -} bool IsCoreWindow(EGLNativeWindowType window, ComPtr *coreWindow) { @@ -127,7 +25,7 @@ bool IsCoreWindow(EGLNativeWindowType window, ComPtr> &propertyMap, const wchar_t *propertyName, @@ -381,7 +268,13 @@ HRESULT GetOptionalSinglePropertyValue(const ComPtr(ConvertDipsToPixels(size.Width)), + static_cast(ConvertDipsToPixels(size.Height))}; +} + +float GetLogicalDpi() { ComPtr displayProperties; float dpi = 96.0f; @@ -396,7 +289,7 @@ static float GetLogicalDpi() return dpi; } -long ConvertDipsToPixels(float dips) +float ConvertDipsToPixels(float dips) { static const float dipsPerInch = 96.0f; return lround((dips * GetLogicalDpi() / dipsPerInch)); 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 2d58f1c00a..d81c3e5fb9 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 @@ -10,14 +10,18 @@ #ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ #define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_ -#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h" - +#include "common/debug.h" #include "common/platform.h" #include "angle_windowsstore.h" +#include + +#include #include #include +#include +#include using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; @@ -26,7 +30,8 @@ using namespace ABI::Windows::Foundation::Collections; namespace rx { -long ConvertDipsToPixels(float dips); +float ConvertDipsToPixels(float dips); +float GetLogicalDpi(); class InspectableNativeWindow { @@ -35,24 +40,25 @@ class InspectableNativeWindow mSupportsSwapChainResize(true), mSwapChainSizeSpecified(false), mSwapChainScaleSpecified(false), - mSwapChainScale(1.0f), mClientRectChanged(false), mClientRect({0,0,0,0}), - mNewClientRect({0,0,0,0}), - mRotationFlags(NativeWindow::RotateNone) + mNewClientRect({0,0,0,0}) { mSizeChangedEventToken.value = 0; + mSwapChainScale = 96.0f / GetLogicalDpi(); + if (mSwapChainScale != 1.0f) + mSwapChainScaleSpecified = true; } virtual ~InspectableNativeWindow(){} virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0; virtual HRESULT createSwapChain(ID3D11Device *device, - DXGIFactory *factory, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) = 0; + IDXGISwapChain1 **swapChain) = 0; bool getClientRect(RECT *rect) { @@ -77,8 +83,7 @@ class InspectableNativeWindow // 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) }; + mNewClientRect = clientRect(newWindowSize); 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 @@ -97,18 +102,9 @@ class InspectableNativeWindow } } - NativeWindow::RotationFlags rotationFlags() const - { - return mRotationFlags; - } - - void setRotationFlags(NativeWindow::RotationFlags flags) - { - mRotationFlags = flags; - } - protected: virtual HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) = 0; + RECT clientRect(const Size &size); bool mSupportsSwapChainResize; // Support for IDXGISwapChain::ResizeBuffers method bool mSwapChainSizeSpecified; // If an EGLRenderSurfaceSizeProperty was specified @@ -117,12 +113,10 @@ class InspectableNativeWindow RECT mClientRect; RECT mNewClientRect; bool mClientRectChanged; - NativeWindow::RotationFlags mRotationFlags; EventRegistrationToken mSizeChangedEventToken; }; -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); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp new file mode 100644 index 0000000000..655b23be83 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.cpp @@ -0,0 +1,126 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11WinRT.cpp: NativeWindow base class for managing IInspectable native window types. + +#include "libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h" + +#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" +#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h" + +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +namespace rx +{ +NativeWindow11WinRT::NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha) + : NativeWindow11(window), mHasAlpha(hasAlpha) +{ +} + +bool NativeWindow11WinRT::initialize() +{ + EGLNativeWindowType window = getNativeWindow(); + + // If the native window type is a IPropertySet, extract the + // EGLNativeWindowType (IInspectable) and initialize the + // proper host with this IPropertySet. + ComPtr propertySet; + ComPtr eglNativeWindow; + if (IsEGLConfiguredPropertySet(window, &propertySet, &eglNativeWindow)) + { + // A property set was found and the EGLNativeWindowType was + // retrieved. The mWindow member of the host to must be updated + // to use the EGLNativeWindowType specified in the property set. + // mWindow is treated as a raw pointer not an AddRef'd interface, so + // the old mWindow does not need a Release() before this assignment. + window = eglNativeWindow.Get(); + } + + ComPtr coreWindow; + ComPtr swapChainPanel; + if (IsCoreWindow(window, &coreWindow)) + { + mImpl = std::make_shared(); + if (mImpl) + { + return mImpl->initialize(window, propertySet.Get()); + } + } + else if (IsSwapChainPanel(window, &swapChainPanel)) + { + mImpl = std::make_shared(); + if (mImpl) + { + return mImpl->initialize(window, propertySet.Get()); + } + } + else + { + ERR() << "Invalid IInspectable EGLNativeWindowType detected. Valid IInspectables include " + "ICoreWindow, ISwapChainPanel and IPropertySet"; + } + + return false; +} + +bool NativeWindow11WinRT::getClientRect(LPRECT rect) const +{ + if (mImpl) + { + return mImpl->getClientRect(rect); + } + + return false; +} + +bool NativeWindow11WinRT::isIconic() const +{ + return false; +} + +HRESULT NativeWindow11WinRT::createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + UINT samples, + IDXGISwapChain **swapChain) +{ + if (mImpl) + { + IDXGIFactory2 *factory2 = d3d11::DynamicCastComObject(factory); + IDXGISwapChain1 *swapChain1 = nullptr; + HRESULT result = + mImpl->createSwapChain(device, factory2, format, width, height, mHasAlpha, &swapChain1); + SafeRelease(factory2); + *swapChain = static_cast(swapChain1); + return result; + } + + return E_UNEXPECTED; +} + +void NativeWindow11WinRT::commitChange() +{ +} + +// static +bool NativeWindow11WinRT::IsValidNativeWindow(EGLNativeWindowType window) +{ + // A Valid EGLNativeWindowType IInspectable can only be: + // + // ICoreWindow + // ISwapChainPanel + // IPropertySet + // + // Anything else will be rejected as an invalid IInspectable. + return IsCoreWindow(window) || IsSwapChainPanel(window) || IsEGLConfiguredPropertySet(window); +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h new file mode 100644 index 0000000000..c4ac997a55 --- /dev/null +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/NativeWindow11WinRT.h @@ -0,0 +1,51 @@ +// +// Copyright (c) 2016 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. +// + +// NativeWindow11WinRT.h: NativeWindow base class for managing IInspectable native window types. + +#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_ +#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_H_ + +#include "libANGLE/renderer/d3d/d3d11/NativeWindow11.h" + +#include +#include +#include +#include + +namespace rx +{ +class InspectableNativeWindow; + +class NativeWindow11WinRT : public NativeWindow11 +{ + public: + NativeWindow11WinRT(EGLNativeWindowType window, bool hasAlpha); + + bool initialize() override; + bool getClientRect(LPRECT rect) const override; + bool isIconic() const override; + + HRESULT createSwapChain(ID3D11Device *device, + IDXGIFactory *factory, + DXGI_FORMAT format, + UINT width, + UINT height, + UINT samples, + IDXGISwapChain **swapChain) override; + + void commitChange() override; + + static bool IsValidNativeWindow(EGLNativeWindowType window); + + private: + bool mHasAlpha; + std::shared_ptr mImpl; +}; + +} // namespace rx + +#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_NATIVEWINDOW11WINRT_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 548b4602fd..3425fad95d 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 @@ -49,7 +49,8 @@ HRESULT RunOnUIThread(CODE &&code, const ComPtr &dispatcher) } else { - Event waitEvent(CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS)); + Event waitEvent( + CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS)); if (!waitEvent.IsValid()) { return E_FAIL; @@ -78,7 +79,8 @@ HRESULT RunOnUIThread(CODE &&code, const ComPtr &dispatcher) // 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."); + ERR() + << "Timeout waiting for async action on UI thread. The UI thread might be blocked."; std::terminate(); return E_FAIL; } @@ -132,7 +134,8 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert // 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."); + ERR() << "It is invalid to specify both an EGLRenderSurfaceSizeProperty and a " + "EGLRenderResolutionScaleProperty."; return false; } } @@ -169,17 +172,14 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert } else { - SIZE swapChainPanelSize; + Size swapChainPanelSize; result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher, - &swapChainPanelSize, &mSwapChainScale); - if (mSwapChainScale != 1.0f) - mSwapChainScaleSpecified = true; + &swapChainPanelSize); 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)) }; + mClientRect = clientRect(swapChainPanelSize); } } } @@ -241,14 +241,15 @@ void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() } HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, - DXGIFactory *factory, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) + IDXGISwapChain1 **swapChain) { - if (device == NULL || factory == NULL || swapChain == NULL || width == 0 || height == 0) + if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 || + height == 0) { return E_INVALIDARG; } @@ -272,6 +273,7 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, ComPtr newSwapChain; ComPtr swapChainPanelNative; + Size currentPanelSize = {}; HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); @@ -306,14 +308,14 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, { if (mSwapChainSizeSpecified || mSwapChainScaleSpecified) { - ComPtr uiElement; - result = mSwapChainPanel.As(&uiElement); - ASSERT(SUCCEEDED(result)); - - Size currentSize; - result = uiElement->get_RenderSize(¤tSize); - ASSERT(SUCCEEDED(result)); - result = scaleSwapChain(currentSize, mClientRect); + result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher, + ¤tPanelSize); + + // Scale the swapchain to fit inside the contents of the panel. + if (SUCCEEDED(result)) + { + result = scaleSwapChain(currentPanelSize, mClientRect); + } } } @@ -342,31 +344,14 @@ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const Size &windowSize, const HRESULT GetSwapChainPanelSize( const ComPtr &swapChainPanel, const ComPtr &dispatcher, - SIZE *windowSize, float *scaleFactor) + Size *windowSize) { ComPtr uiElement; - Size renderSize = {0, 0}; HRESULT result = swapChainPanel.As(&uiElement); if (SUCCEEDED(result)) { result = RunOnUIThread( - [uiElement, &renderSize] - { - return uiElement->get_RenderSize(&renderSize); - }, - dispatcher); - } - - if (SUCCEEDED(result)) - { - long width = ConvertDipsToPixels(renderSize.Width); - long height = ConvertDipsToPixels(renderSize.Height); - *windowSize = { width, height }; - - if (scaleFactor) - { - *scaleFactor = renderSize.Width / width; - } + [uiElement, windowSize] { return uiElement->get_RenderSize(windowSize); }, dispatcher); } return result; 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 09d87ad523..f9a2fc0e4b 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 @@ -11,6 +11,8 @@ #include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h" +#include + namespace rx { class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this @@ -20,12 +22,12 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) override; HRESULT createSwapChain(ID3D11Device *device, - DXGIFactory *factory, + IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, - DXGISwapChain **swapChain) override; + IDXGISwapChain1 **swapChain) override; protected: HRESULT scaleSwapChain(const Size &windowSize, const RECT &clientRect) override; @@ -37,7 +39,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e ComPtr mSwapChainPanel; ComPtr mSwapChainPanelDispatcher; ComPtr> mPropertyMap; - ComPtr mSwapChain; + ComPtr mSwapChain; }; [uuid(8ACBD974-8187-4508-AD80-AEC77F93CF36)] @@ -86,6 +88,6 @@ class SwapChainPanelSizeChangedHandler : HRESULT GetSwapChainPanelSize( const ComPtr &swapChainPanel, const ComPtr &dispatcher, - SIZE *windowSize, float *scaleFactor); + Size *windowSize); } #endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ -- cgit v1.2.3