summaryrefslogtreecommitdiff
path: root/chromium/third_party/angle/src/libANGLE/renderer
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-05-16 09:59:13 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-05-20 10:28:53 +0000
commit6c11fb357ec39bf087b8b632e2b1e375aef1b38b (patch)
treec8315530db18a8ee566521c39ab8a6af4f72bc03 /chromium/third_party/angle/src/libANGLE/renderer
parent3ffaed019d0772e59d6cdb2d0d32fe4834c31f72 (diff)
downloadqtwebengine-chromium-6c11fb357ec39bf087b8b632e2b1e375aef1b38b.tar.gz
BASELINE: Update Chromium to 74.0.3729.159
Change-Id: I8d2497da544c275415aedd94dd25328d555de811 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/third_party/angle/src/libANGLE/renderer')
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/ContextImpl.h4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/EGLSyncImpl.h4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/FenceNVImpl.h4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/Format_table_autogen.cpp104
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/ImageImpl.h5
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/SyncImpl.h4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/angle_format_data.json156
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp89
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp282
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h21
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h7
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp39
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp58
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h9
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp3
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp34
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp11
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp86
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp43
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h11
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/d3d11_blit_shaders_autogen.gni2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_blit11helper.py2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp21
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp9
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp17
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp7
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gen_angle_format_table.py20
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.cpp4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp34
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h4
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h1
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp22
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h5
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp14
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp13
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp65
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/android_util.cpp158
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/android_util.h23
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp17
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp18
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp33
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.cpp5
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.cpp8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.h6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/renderer_utils.cpp2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp5
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.cpp212
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.h23
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp65
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.h8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp35
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.h6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp45
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp110
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.h29
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp18
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.h8
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp5
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp60
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.h17
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp109
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h9
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp437
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.h29
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp674
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h464
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp472
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h39
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.cpp233
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.h62
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp1069
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.h178
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/UtilsVk.cpp29
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp51
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h1
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp37
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.h12
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp208
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h55
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h1
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.cpp59
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.h39
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.cpp66
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h36
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp46
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.h35
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp212
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.h11
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_map.json60
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp204
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.cpp66
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.h10
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.cpp934
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.h213
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.cpp903
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.h625
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_wrapper.h1308
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h1
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.cpp38
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h2
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.cpp6
-rw-r--r--chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h1
131 files changed, 7972 insertions, 3316 deletions
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ContextImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/ContextImpl.h
index 4ee2756701e..0203276efaa 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/ContextImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/ContextImpl.h
@@ -137,8 +137,8 @@ class ContextImpl : public GLImplFactory
virtual void popGroupMarker() = 0;
// KHR_debug
- virtual void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) = 0;
- virtual void popDebugGroup() = 0;
+ virtual void pushDebugGroup(GLenum source, GLuint id, const std::string &message) = 0;
+ virtual void popDebugGroup() = 0;
// State sync with dirty bits.
virtual angle::Result syncState(const gl::Context *context,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/EGLSyncImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/EGLSyncImpl.h
index ebf8f795290..9d910c4538a 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/EGLSyncImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/EGLSyncImpl.h
@@ -25,8 +25,8 @@ namespace rx
class EGLSyncImpl : angle::NonCopyable
{
public:
- EGLSyncImpl(){};
- virtual ~EGLSyncImpl(){};
+ EGLSyncImpl() {}
+ virtual ~EGLSyncImpl() {}
virtual void onDestroy(const egl::Display *display) {}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/FenceNVImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/FenceNVImpl.h
index fa3fa52ffb6..eaa055749c6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/FenceNVImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/FenceNVImpl.h
@@ -25,8 +25,8 @@ namespace rx
class FenceNVImpl : angle::NonCopyable
{
public:
- FenceNVImpl(){};
- virtual ~FenceNVImpl(){};
+ FenceNVImpl() {}
+ virtual ~FenceNVImpl() {}
virtual angle::Result set(const gl::Context *context, GLenum condition) = 0;
virtual angle::Result test(const gl::Context *context, GLboolean *outFinished) = 0;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/Format_table_autogen.cpp b/chromium/third_party/angle/src/libANGLE/renderer/Format_table_autogen.cpp
index 6d7f5389b51..5a9f25c764e 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/Format_table_autogen.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/Format_table_autogen.cpp
@@ -29,34 +29,34 @@ const Format gFormatInfoTable[] = {
{ FormatID::A1R5G5B5_UNORM, GL_A1RGB5_ANGLEX, GL_A1RGB5_ANGLEX, GenerateMip<A1R5G5B5>, NoCopyFunctions, ReadColor<A1R5G5B5, GLfloat>, WriteColor<A1R5G5B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::A32_FLOAT, GL_ALPHA32F_EXT, GL_ALPHA32F_EXT, GenerateMip<A32F>, NoCopyFunctions, ReadColor<A32F, GLfloat>, WriteColor<A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 0, 0, 0, 4, 3, false, false },
{ FormatID::A8_UNORM, GL_ALPHA8_EXT, GL_ALPHA8_EXT, GenerateMip<A8>, NoCopyFunctions, ReadColor<A8, GLfloat>, WriteColor<A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 8, 0, 0, 0, 1, 0, false, false },
- { FormatID::ASTC_10x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_10x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_10x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_10x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_10x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_10x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_10x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_10x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_12x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_12x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_12x12_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_12x12_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_4x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_4x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_5x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_5x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_5x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_5x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_6x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_6x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_6x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_6x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_8x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_8x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_8x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_8x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_8x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ASTC_8x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_10x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_10x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_10x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_10x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_10x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_10x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_10x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_10x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_12x10_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_12x10_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_12x12_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_12x12_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_4x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_4x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_5x4_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_5x4_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_5x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_5x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_6x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_6x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_6x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_6x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_8x5_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_8x5_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_8x6_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_8x6_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_8x8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ASTC_8x8_UNORM_BLOCK, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
{ FormatID::B4G4R4A4_UNORM, GL_BGRA4_ANGLEX, GL_RGBA4, GenerateMip<A4R4G4B4>, NoCopyFunctions, ReadColor<A4R4G4B4, GLfloat>, WriteColor<A4R4G4B4, GLfloat>, GL_UNSIGNED_NORMALIZED, 4, 4, 4, 4, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::B5G5R5A1_UNORM, GL_BGR5_A1_ANGLEX, GL_RGB5_A1, GenerateMip<A1R5G5B5>, NoCopyFunctions, ReadColor<A1R5G5B5, GLfloat>, WriteColor<A1R5G5B5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 5, 5, 1, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::B5G6R5_UNORM, GL_BGR565_ANGLEX, GL_RGB565, GenerateMip<B5G6R5>, NoCopyFunctions, ReadColor<B5G6R5, GLfloat>, WriteColor<B5G6R5, GLfloat>, GL_UNSIGNED_NORMALIZED, 5, 6, 5, 0, 0, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false },
@@ -65,36 +65,36 @@ const Format gFormatInfoTable[] = {
{ FormatID::B8G8R8A8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, BGRACopyFunctions, ReadColor<B8G8R8A8, GLfloat>, WriteColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false },
{ FormatID::B8G8R8A8_UNORM_SRGB, GL_BGRA8_SRGB_ANGLEX, GL_BGRA8_SRGB_ANGLEX, GenerateMip<B8G8R8A8>, NoCopyFunctions, ReadColor<B8G8R8A8, GLfloat>, WriteColor<B8G8R8A8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, false, false },
{ FormatID::B8G8R8X8_UNORM, GL_BGRA8_EXT, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, NoCopyFunctions, ReadColor<B8G8R8X8, GLfloat>, WriteColor<B8G8R8X8, GLfloat>, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false },
- { FormatID::BC1_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BC1_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BC1_RGB_UNORM_BLOCK, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BC1_RGB_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BC2_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BC2_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BC3_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BC3_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BPTC_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BPTC_RGB_SIGNED_FLOAT_BLOCK, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_FLOAT, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BPTC_RGB_UNSIGNED_FLOAT_BLOCK, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_FLOAT, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::BPTC_SRGB_ALPHA_UNORM_BLOCK, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 0, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BC1_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BC1_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BC1_RGB_UNORM_BLOCK, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BC1_RGB_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BC2_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BC2_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BC3_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BC3_RGBA_UNORM_SRGB_BLOCK, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BPTC_RGBA_UNORM_BLOCK, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BPTC_RGB_SIGNED_FLOAT_BLOCK, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_FLOAT, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BPTC_RGB_UNSIGNED_FLOAT_BLOCK, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_FLOAT, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::BPTC_SRGB_ALPHA_UNORM_BLOCK, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 0, 0, 16, std::numeric_limits<GLuint>::max(), true, false },
{ FormatID::D16_UNORM, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT16, nullptr, NoCopyFunctions, ReadDepthStencil<D16>, WriteDepthStencil<D16>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 16, 0, 2, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, nullptr, NoCopyFunctions, ReadDepthStencil<D24S8>, WriteDepthStencil<D24S8>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 24, 8, 4, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::D24_UNORM_X8_UINT, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT24, nullptr, NoCopyFunctions, ReadDepthStencil<D24>, WriteDepthStencil<D24>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 24, 0, 4, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::D32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, nullptr, NoCopyFunctions, ReadDepthStencil<D32F>, WriteDepthStencil<D32F>, GL_FLOAT, 0, 0, 0, 0, 0, 32, 0, 4, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::D32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, nullptr, NoCopyFunctions, ReadDepthStencil<D32FS8>, WriteDepthStencil<D32FS8>, GL_FLOAT, 0, 0, 0, 0, 0, 32, 8, 8, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::D32_UNORM, GL_DEPTH_COMPONENT32_OES, GL_DEPTH_COMPONENT32_OES, nullptr, NoCopyFunctions, ReadDepthStencil<D32>, WriteDepthStencil<D32>, GL_UNSIGNED_NORMALIZED, 0, 0, 0, 0, 0, 32, 0, 4, std::numeric_limits<GLuint>::max(), false, false },
- { FormatID::EAC_R11G11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0, 0, 2, 0, true, false },
- { FormatID::EAC_R11G11_UNORM_BLOCK, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0, 0, 2, 0, true, false },
- { FormatID::EAC_R11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0, 0, 1, 0, true, false },
- { FormatID::EAC_R11_UNORM_BLOCK, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0, 0, 1, 0, true, false },
- { FormatID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, true, false },
- { FormatID::ETC1_R8G8B8_UNORM_BLOCK, GL_ETC1_RGB8_OES, GL_ETC1_RGB8_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, true, false },
- { FormatID::ETC2_R8G8B8A1_SRGB_BLOCK, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0, 0, 3, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ETC2_R8G8B8A1_UNORM_BLOCK, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0, 0, 3, std::numeric_limits<GLuint>::max(), true, false },
- { FormatID::ETC2_R8G8B8A8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, true, false },
- { FormatID::ETC2_R8G8B8A8_UNORM_BLOCK, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 4, 0, true, false },
- { FormatID::ETC2_R8G8B8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, true, false },
- { FormatID::ETC2_R8G8B8_UNORM_BLOCK, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 3, 0, true, false },
+ { FormatID::EAC_R11G11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0, 0, 16, 0, true, false },
+ { FormatID::EAC_R11G11_UNORM_BLOCK, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 11, 11, 0, 0, 0, 0, 0, 16, 0, true, false },
+ { FormatID::EAC_R11_SNORM_BLOCK, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_SIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0, 0, 8, 0, true, false },
+ { FormatID::EAC_R11_UNORM_BLOCK, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 11, 0, 0, 0, 0, 0, 0, 8, 0, true, false },
+ { FormatID::ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, GL_ETC1_RGB8_LOSSY_DECODE_ANGLE, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false },
+ { FormatID::ETC1_R8G8B8_UNORM_BLOCK, GL_ETC1_RGB8_OES, GL_ETC1_RGB8_OES, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false },
+ { FormatID::ETC2_R8G8B8A1_SRGB_BLOCK, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ETC2_R8G8B8A1_UNORM_BLOCK, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 1, 0, 0, 0, 8, std::numeric_limits<GLuint>::max(), true, false },
+ { FormatID::ETC2_R8G8B8A8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 16, 0, true, false },
+ { FormatID::ETC2_R8G8B8A8_UNORM_BLOCK, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 8, 0, 0, 0, 16, 0, true, false },
+ { FormatID::ETC2_R8G8B8_SRGB_BLOCK, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false },
+ { FormatID::ETC2_R8G8B8_UNORM_BLOCK, GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, nullptr, NoCopyFunctions, nullptr, nullptr, GL_UNSIGNED_NORMALIZED, 8, 8, 8, 0, 0, 0, 0, 8, 0, true, false },
{ FormatID::L16A16_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA16F_EXT, GenerateMip<L16A16F>, NoCopyFunctions, ReadColor<L16A16F, GLfloat>, WriteColor<L16A16F, GLfloat>, GL_FLOAT, 0, 0, 0, 16, 16, 0, 0, 4, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::L16_FLOAT, GL_LUMINANCE16F_EXT, GL_LUMINANCE16F_EXT, GenerateMip<L16F>, NoCopyFunctions, ReadColor<L16F, GLfloat>, WriteColor<L16F, GLfloat>, GL_FLOAT, 0, 0, 0, 0, 16, 0, 0, 2, std::numeric_limits<GLuint>::max(), false, false },
{ FormatID::L32A32_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA32F_EXT, GenerateMip<L32A32F>, NoCopyFunctions, ReadColor<L32A32F, GLfloat>, WriteColor<L32A32F, GLfloat>, GL_FLOAT, 0, 0, 0, 32, 32, 0, 0, 8, std::numeric_limits<GLuint>::max(), false, false },
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ImageImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/ImageImpl.h
index 5ee7aed9cc8..6d2e6e5337d 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/ImageImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/ImageImpl.h
@@ -33,6 +33,9 @@ class ExternalImageSiblingImpl : public FramebufferAttachmentObjectImpl
public:
~ExternalImageSiblingImpl() override {}
+ virtual egl::Error initialize(const egl::Display *display) = 0;
+ virtual void onDestroy(const egl::Display *display) {}
+
virtual gl::Format getFormat() const = 0;
virtual bool isRenderable(const gl::Context *context) const = 0;
virtual bool isTexturable(const gl::Context *context) const = 0;
@@ -45,6 +48,8 @@ class ImageImpl : angle::NonCopyable
public:
ImageImpl(const egl::ImageState &state) : mState(state) {}
virtual ~ImageImpl() {}
+ virtual void onDestroy(const egl::Display *display) {}
+
virtual egl::Error initialize(const egl::Display *display) = 0;
virtual angle::Result orphan(const gl::Context *context, egl::ImageSibling *sibling) = 0;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h
index 384ddaeacb2..2bc07040014 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/ProgramImpl.h
@@ -35,7 +35,7 @@ namespace rx
class LinkEvent : angle::NonCopyable
{
public:
- virtual ~LinkEvent(){};
+ virtual ~LinkEvent() {}
// Please be aware that these methods may be called under a gl::Context other
// than the one where the LinkEvent was created.
@@ -75,9 +75,9 @@ class ProgramImpl : angle::NonCopyable
virtual ~ProgramImpl() {}
virtual void destroy(const gl::Context *context) {}
- virtual angle::Result load(const gl::Context *context,
- gl::InfoLog &infoLog,
- gl::BinaryInputStream *stream) = 0;
+ virtual std::unique_ptr<LinkEvent> load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog) = 0;
virtual void save(const gl::Context *context, gl::BinaryOutputStream *stream) = 0;
virtual void setBinaryRetrievableHint(bool retrievable) = 0;
virtual void setSeparable(bool separable) = 0;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h
index 273c16d75a3..854226544f1 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/ShaderImpl.h
@@ -29,7 +29,7 @@ class ShaderImpl : angle::NonCopyable
std::string *sourcePath) = 0;
// Uses the GL driver to compile the shader source in a worker thread.
- virtual void compileAsync(const std::string &source) {}
+ virtual void compileAsync(const std::string &source, std::string &infoLog) {}
// Returns success for compiling on the driver. Returns success.
virtual bool postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog) = 0;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/SyncImpl.h b/chromium/third_party/angle/src/libANGLE/renderer/SyncImpl.h
index 0a4e2fa1f3d..58338bdbb25 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/SyncImpl.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/SyncImpl.h
@@ -25,8 +25,8 @@ namespace rx
class SyncImpl : angle::NonCopyable
{
public:
- SyncImpl(){};
- virtual ~SyncImpl(){};
+ SyncImpl() {}
+ virtual ~SyncImpl() {}
virtual void onDestroy(const gl::Context *context) {}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/angle_format_data.json b/chromium/third_party/angle/src/libANGLE/renderer/angle_format_data.json
index ba2f159a13d..5d3840ac2bf 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/angle_format_data.json
+++ b/chromium/third_party/angle/src/libANGLE/renderer/angle_format_data.json
@@ -32,5 +32,161 @@
},
"B8G8R8A8_TYPELESS_SRGB": {
"glInternalFormat": "GL_BGRA8_SRGB_ANGLEX"
+ },
+ "ASTC_4x4_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_4x4_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_5x4_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_5x4_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_5x5_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_5x5_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_6x5_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_6x5_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_6x6_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_6x6_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_8x5_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_8x5_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_8x6_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_8x6_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_8x8_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_8x8_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_10x5_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_10x5_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_10x6_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_10x6_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_10x8_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_10x8_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_10x10_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_10x10_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_12x10_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_12x10_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_12x12_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ASTC_12x12_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "BC1_RGB_UNORM_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "BC1_RGBA_UNORM_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "BC1_RGBA_UNORM_SRGB_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "BC1_RGB_UNORM_SRGB_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "BC2_RGBA_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "BC2_RGBA_UNORM_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "BC3_RGBA_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "BC3_RGBA_UNORM_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "BPTC_SRGB_ALPHA_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "BPTC_RGB_SIGNED_FLOAT_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "BPTC_RGB_UNSIGNED_FLOAT_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "BPTC_RGBA_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "EAC_R11_SNORM_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "EAC_R11_UNORM_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "EAC_R11G11_SNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "EAC_R11G11_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ETC1_R8G8B8_UNORM_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "ETC1_LOSSY_DECODE_R8G8B8_UNORM_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "ETC2_R8G8B8_SRGB_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "ETC2_R8G8B8_UNORM_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "ETC2_R8G8B8A1_SRGB_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "ETC2_R8G8B8A1_UNORM_BLOCK": {
+ "blockPixelBytes": "8"
+ },
+ "ETC2_R8G8B8A8_UNORM_BLOCK": {
+ "blockPixelBytes": "16"
+ },
+ "ETC2_R8G8B8A8_SRGB_BLOCK": {
+ "blockPixelBytes": "16"
}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
index 371471e6ba4..31b7fe80c9d 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
@@ -16,9 +16,9 @@
#include "libANGLE/renderer/d3d/ContextD3D.h"
#include "third_party/trace_event/trace_event.h"
-#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
namespace
{
+#if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
# ifdef CREATE_COMPILER_FLAG_INFO
# undef CREATE_COMPILER_FLAG_INFO
# endif
@@ -81,9 +81,19 @@ bool IsCompilerFlagSet(UINT mask, UINT flag)
return isFlagSet;
}
}
-} // anonymous namespace
#endif // ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED
+constexpr char kOldCompilerLibrary[] = "d3dcompiler_old.dll";
+
+enum D3DCompilerLoadLibraryResult
+{
+ D3DCompilerDefaultLibrarySuccess,
+ D3DCompilerOldLibrarySuccess,
+ D3DCompilerFailure,
+ D3DCompilerEnumBoundary,
+};
+} // anonymous namespace
+
namespace rx
{
@@ -132,15 +142,31 @@ angle::Result HLSLCompiler::ensureInitialized(d3d::Context *context)
// built with.
mD3DCompilerModule = LoadLibraryA(D3DCOMPILER_DLL_A);
- if (!mD3DCompilerModule)
+ if (mD3DCompilerModule)
{
- DWORD lastError = GetLastError();
- ERR() << "LoadLibrary(" << D3DCOMPILER_DLL_A << ") failed. GetLastError=" << lastError;
- ANGLE_TRY_HR(context, E_OUTOFMEMORY, "LoadLibrary failed to load D3D Compiler DLL.");
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3DCompilerLoadLibraryResult",
+ D3DCompilerDefaultLibrarySuccess, D3DCompilerEnumBoundary);
+ }
+ else
+ {
+ WARN() << "Failed to load HLSL compiler library. Using 'old' DLL.";
+ mD3DCompilerModule = LoadLibraryA(kOldCompilerLibrary);
+ if (mD3DCompilerModule)
+ {
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3DCompilerLoadLibraryResult",
+ D3DCompilerOldLibrarySuccess, D3DCompilerEnumBoundary);
+ }
}
}
- ASSERT(mD3DCompilerModule);
+ if (!mD3DCompilerModule)
+ {
+ DWORD lastError = GetLastError();
+ ERR() << "D3D Compiler LoadLibrary failed. GetLastError=" << lastError;
+ ANGLE_HISTOGRAM_ENUMERATION("GPU.ANGLE.D3DCompilerLoadLibraryResult", D3DCompilerFailure,
+ D3DCompilerEnumBoundary);
+ ANGLE_TRY_HR(context, E_OUTOFMEMORY, "LoadLibrary failed to load D3D Compiler DLL.");
+ }
mD3DCompileFunc =
reinterpret_cast<pD3DCompile>(GetProcAddress(mD3DCompilerModule, "D3DCompile"));
@@ -232,22 +258,43 @@ angle::Result HLSLCompiler::compileToBinary(d3d::Context *context,
WARN() << std::endl << message;
- if ((message.find("error X3531:") !=
- std::string::npos || // "can't unroll loops marked with loop attribute"
- message.find("error X4014:") !=
- std::string::npos) && // "cannot have gradient operations inside loops with
- // divergent flow control", even though it is
- // counter-intuitive to disable unrolling for this
- // error, some very long shaders have trouble deciding
- // which loops to unroll and turning off forced unrolls
- // allows them to compile properly.
- macros != nullptr)
+ if (macros != nullptr)
{
- macros = nullptr; // Disable [loop] and [flatten]
+ constexpr const char *kLoopRelatedErrors[] = {
+ // "can't unroll loops marked with loop attribute"
+ "error X3531:",
+
+ // "cannot have gradient operations inside loops with divergent flow control",
+ // even though it is counter-intuitive to disable unrolling for this error, some
+ // very long shaders have trouble deciding which loops to unroll and turning off
+ // forced unrolls allows them to compile properly.
+ "error X4014:",
+
+ // "array index out of bounds", loop unrolling can result in invalid array
+ // access if the indices become constant, causing loops that may never be
+ // executed to generate compilation errors
+ "error X3504:",
+ };
+
+ bool hasLoopRelatedError = false;
+ for (const char *errorType : kLoopRelatedErrors)
+ {
+ if (message.find(errorType) != std::string::npos)
+ {
+ hasLoopRelatedError = true;
+ break;
+ }
+ }
- // Retry without changing compiler flags
- i--;
- continue;
+ if (hasLoopRelatedError)
+ {
+ // Disable [loop] and [flatten]
+ macros = nullptr;
+
+ // Retry without changing compiler flags
+ i--;
+ continue;
+ }
}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.h
index 04dd38b26f3..70b1e12e769 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ImageD3D.h
@@ -38,7 +38,7 @@ class ImageD3D : angle::NonCopyable
{
public:
ImageD3D();
- virtual ~ImageD3D(){};
+ virtual ~ImageD3D() {}
GLsizei getWidth() const { return mWidth; }
GLsizei getHeight() const { return mHeight; }
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index d43e560f606..df2f0217b58 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -8,6 +8,7 @@
#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "common/MemoryBuffer.h"
#include "common/bitset_utils.h"
#include "common/string_utils.h"
#include "common/utilities.h"
@@ -263,7 +264,7 @@ bool InterfaceBlockInfo::getBlockSize(const std::string &name,
*sizeOut = sizeIter->second;
return true;
-};
+}
bool InterfaceBlockInfo::getBlockMemberInfo(const std::string &name,
const std::string &mappedName,
@@ -278,7 +279,7 @@ bool InterfaceBlockInfo::getBlockMemberInfo(const std::string &name,
*infoOut = infoIter->second;
return true;
-};
+}
// Helper class that gathers uniform info from the default uniform block.
class UniformEncodingVisitorD3D : public sh::BlockEncoderVisitor
@@ -562,6 +563,50 @@ const ShaderD3D *ProgramD3DMetadata::getFragmentShader() const
return mAttachedShaders[gl::ShaderType::Fragment];
}
+// ProgramD3D::GetExecutableTask class
+class ProgramD3D::GetExecutableTask : public Closure, public d3d::Context
+{
+ public:
+ GetExecutableTask(ProgramD3D *program) : mProgram(program) {}
+
+ virtual angle::Result run() = 0;
+
+ void operator()() override { mResult = run(); }
+
+ angle::Result getResult() const { return mResult; }
+ const gl::InfoLog &getInfoLog() const { return mInfoLog; }
+ ShaderExecutableD3D *getExecutable() { return mExecutable; }
+
+ void handleResult(HRESULT hr,
+ const char *message,
+ const char *file,
+ const char *function,
+ unsigned int line) override
+ {
+ mStoredHR = hr;
+ mStoredMessage = message;
+ mStoredFile = file;
+ mStoredFunction = function;
+ mStoredLine = line;
+ }
+
+ void popError(d3d::Context *context)
+ {
+ context->handleResult(mStoredHR, mStoredMessage, mStoredFile, mStoredFunction, mStoredLine);
+ }
+
+ protected:
+ ProgramD3D *mProgram = nullptr;
+ angle::Result mResult = angle::Result::Continue;
+ gl::InfoLog mInfoLog;
+ ShaderExecutableD3D *mExecutable = nullptr;
+ HRESULT mStoredHR = S_OK;
+ const char *mStoredMessage = nullptr;
+ const char *mStoredFile = nullptr;
+ const char *mStoredFunction = nullptr;
+ unsigned int mStoredLine = 0;
+};
+
// ProgramD3D Implementation
ProgramD3D::VertexExecutable::VertexExecutable(const gl::InputLayout &inputLayout,
@@ -668,6 +713,7 @@ ProgramD3D::ProgramD3D(const gl::ProgramState &state, RendererD3D *renderer)
mDirtySamplerMapping(true),
mUsedComputeImageRange(0, 0),
mUsedComputeReadonlyImageRange(0, 0),
+ mUsedComputeAtomicCounterRange(0, 0),
mSerial(issueSerial())
{
mDynamicHLSL = new DynamicHLSL(renderer);
@@ -848,10 +894,92 @@ gl::RangeUI ProgramD3D::getUsedImageRange(gl::ShaderType type, bool readonly) co
}
}
-angle::Result ProgramD3D::load(const gl::Context *context,
- gl::InfoLog &infoLog,
- gl::BinaryInputStream *stream)
+class ProgramD3D::LoadBinaryTask : public ProgramD3D::GetExecutableTask
+{
+ public:
+ LoadBinaryTask(const gl::Context *context,
+ ProgramD3D *program,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
+ : ProgramD3D::GetExecutableTask(program),
+ mContext(context),
+ mProgram(program),
+ mInfoLog(infoLog)
+ {
+ ASSERT(mContext);
+ ASSERT(mProgram);
+ ASSERT(stream);
+
+ // Copy the remaining data from the stream locally so that the client can't modify it when
+ // loading off thread.
+ size_t dataSize = stream->remainingSize();
+ mDataCopySucceeded = mStreamData.resize(dataSize);
+ if (mDataCopySucceeded)
+ {
+ memcpy(mStreamData.data(), stream->data() + stream->offset(), dataSize);
+ }
+ }
+
+ angle::Result run() override
+ {
+ if (!mDataCopySucceeded)
+ {
+ mInfoLog << "Failed to copy program binary data to local buffer.";
+ return angle::Result::Stop;
+ }
+
+ gl::BinaryInputStream stream(mStreamData.data(), mStreamData.size());
+ return mProgram->loadBinaryShaderExecutables(mContext, &stream, mInfoLog);
+ }
+
+ private:
+ const gl::Context *mContext;
+ ProgramD3D *mProgram;
+ gl::InfoLog &mInfoLog;
+
+ bool mDataCopySucceeded;
+ angle::MemoryBuffer mStreamData;
+};
+
+class ProgramD3D::LoadBinaryLinkEvent final : public LinkEvent
+{
+ public:
+ LoadBinaryLinkEvent(std::shared_ptr<WorkerThreadPool> workerPool,
+ const gl::Context *context,
+ ProgramD3D *program,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
+ : mTask(std::make_shared<ProgramD3D::LoadBinaryTask>(context, program, stream, infoLog)),
+ mWaitableEvent(workerPool->postWorkerTask(mTask))
+ {}
+
+ angle::Result wait(const gl::Context *context) override
+ {
+ mWaitableEvent->wait();
+
+ // Continue and Incomplete are not errors. For Stop, pass the error to the ContextD3D.
+ if (mTask->getResult() != angle::Result::Stop)
+ {
+ return angle::Result::Continue;
+ }
+
+ ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
+ mTask->popError(contextD3D);
+ return angle::Result::Stop;
+ }
+
+ bool isLinking() override { return !mWaitableEvent->isReady(); }
+
+ private:
+ std::shared_ptr<ProgramD3D::LoadBinaryTask> mTask;
+ std::shared_ptr<WaitableEvent> mWaitableEvent;
+};
+
+std::unique_ptr<rx::LinkEvent> ProgramD3D::load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
{
+
// TODO(jmadill): Use Renderer from contextImpl.
reset();
@@ -864,14 +992,14 @@ angle::Result ProgramD3D::load(const gl::Context *context,
if (memcmp(&identifier, &binaryDeviceIdentifier, sizeof(DeviceIdentifier)) != 0)
{
infoLog << "Invalid program binary, device configuration has changed.";
- return angle::Result::Incomplete;
+ return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
}
int compileFlags = stream->readInt<int>();
if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
{
infoLog << "Mismatched compilation flags.";
- return angle::Result::Incomplete;
+ return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
}
for (int &index : mAttribLocationToD3DSemantic)
@@ -925,11 +1053,16 @@ angle::Result ProgramD3D::load(const gl::Context *context,
mUsedComputeReadonlyImageRange =
gl::RangeUI(computeReadonlyImageRangeLow, computeReadonlyImageRangeHigh);
+ unsigned int atomicCounterRangeLow, atomicCounterRangeHigh;
+ stream->readInt(&atomicCounterRangeLow);
+ stream->readInt(&atomicCounterRangeHigh);
+ mUsedComputeAtomicCounterRange = gl::RangeUI(atomicCounterRangeLow, atomicCounterRangeHigh);
+
const unsigned int shaderStorageBlockCount = stream->readInt<unsigned int>();
if (stream->error())
{
infoLog << "Invalid program binary.";
- return angle::Result::Incomplete;
+ return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
}
ASSERT(mD3DShaderStorageBlocks.empty());
@@ -943,11 +1076,17 @@ angle::Result ProgramD3D::load(const gl::Context *context,
mD3DShaderStorageBlocks.push_back(shaderStorageBlock);
}
+ for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS; ++ii)
+ {
+ unsigned int index = stream->readInt<unsigned int>();
+ mComputeAtomicCounterBufferRegisterIndices[ii] = index;
+ }
+
const unsigned int uniformCount = stream->readInt<unsigned int>();
if (stream->error())
{
infoLog << "Invalid program binary.";
- return angle::Result::Incomplete;
+ return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
}
const auto &linkedUniforms = mState.getUniforms();
@@ -974,7 +1113,7 @@ angle::Result ProgramD3D::load(const gl::Context *context,
if (stream->error())
{
infoLog << "Invalid program binary.";
- return angle::Result::Incomplete;
+ return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
}
ASSERT(mD3DUniformBlocks.empty());
@@ -1026,6 +1165,14 @@ angle::Result ProgramD3D::load(const gl::Context *context,
stream->readString(&mGeometryShaderPreamble);
+ return std::make_unique<LoadBinaryLinkEvent>(context->getWorkerThreadPool(), context, this,
+ stream, infoLog);
+}
+
+angle::Result ProgramD3D::loadBinaryShaderExecutables(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
+{
const unsigned char *binary = reinterpret_cast<const unsigned char *>(stream->data());
bool separateAttribs = (mState.getTransformFeedbackBufferMode() == GL_SEPARATE_ATTRIBS);
@@ -1225,6 +1372,8 @@ void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream
stream->writeInt(mUsedComputeImageRange.high());
stream->writeInt(mUsedComputeReadonlyImageRange.low());
stream->writeInt(mUsedComputeReadonlyImageRange.high());
+ stream->writeInt(mUsedComputeAtomicCounterRange.low());
+ stream->writeInt(mUsedComputeAtomicCounterRange.high());
stream->writeInt(mD3DShaderStorageBlocks.size());
for (const D3DInterfaceBlock &shaderStorageBlock : mD3DShaderStorageBlocks)
@@ -1235,6 +1384,11 @@ void ProgramD3D::save(const gl::Context *context, gl::BinaryOutputStream *stream
}
}
+ for (unsigned int ii = 0; ii < gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS; ++ii)
+ {
+ stream->writeInt(mComputeAtomicCounterBufferRegisterIndices[ii]);
+ }
+
stream->writeInt(mD3DUniforms.size());
for (const D3DUniform *uniform : mD3DUniforms)
{
@@ -1524,49 +1678,6 @@ angle::Result ProgramD3D::getGeometryExecutableForPrimitiveType(d3d::Context *co
return result;
}
-class ProgramD3D::GetExecutableTask : public Closure, public d3d::Context
-{
- public:
- GetExecutableTask(ProgramD3D *program) : mProgram(program) {}
-
- virtual angle::Result run() = 0;
-
- void operator()() override { mResult = run(); }
-
- angle::Result getResult() const { return mResult; }
- const gl::InfoLog &getInfoLog() const { return mInfoLog; }
- ShaderExecutableD3D *getExecutable() { return mExecutable; }
-
- void handleResult(HRESULT hr,
- const char *message,
- const char *file,
- const char *function,
- unsigned int line) override
- {
- mStoredHR = hr;
- mStoredMessage = message;
- mStoredFile = file;
- mStoredFunction = function;
- mStoredLine = line;
- }
-
- void popError(d3d::Context *context)
- {
- context->handleResult(mStoredHR, mStoredMessage, mStoredFile, mStoredFunction, mStoredLine);
- }
-
- protected:
- ProgramD3D *mProgram = nullptr;
- angle::Result mResult = angle::Result::Continue;
- gl::InfoLog mInfoLog;
- ShaderExecutableD3D *mExecutable = nullptr;
- HRESULT mStoredHR = S_OK;
- const char *mStoredMessage = nullptr;
- const char *mStoredFile = nullptr;
- const char *mStoredFunction = nullptr;
- unsigned int mStoredLine = 0;
-};
-
class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
{
public:
@@ -2111,6 +2222,18 @@ void ProgramD3D::updateUniformBufferCache(
}
}
+unsigned int ProgramD3D::getAtomicCounterBufferRegisterIndex(GLuint binding,
+ gl::ShaderType shaderType) const
+{
+ if (shaderType != gl::ShaderType::Compute)
+ {
+ // Implement atomic counters for non-compute shaders
+ // http://anglebug.com/1729
+ UNIMPLEMENTED();
+ }
+ return mComputeAtomicCounterBufferRegisterIndices[binding];
+}
+
unsigned int ProgramD3D::getShaderStorageBufferRegisterIndex(GLuint blockIndex,
gl::ShaderType shaderType) const
{
@@ -2308,11 +2431,15 @@ void ProgramD3D::defineUniformsAndAssignRegisters()
}
assignAllSamplerRegisters();
+ assignAllAtomicCounterRegisters();
// Samplers and readonly images share shader input resource slot, adjust low value of
// readonly image range.
mUsedComputeReadonlyImageRange =
gl::RangeUI(mUsedShaderSamplerRanges[gl::ShaderType::Compute].high(),
mUsedShaderSamplerRanges[gl::ShaderType::Compute].high());
+ // Atomic counter buffers and non-readonly images share input resource slots
+ mUsedComputeImageRange =
+ gl::RangeUI(mUsedComputeAtomicCounterRange.high(), mUsedComputeAtomicCounterRange.high());
assignAllImageRegisters();
initializeUniformStorage(attachedShaders);
}
@@ -2359,6 +2486,14 @@ void ProgramD3D::defineUniformBase(const gl::Shader *shader,
sh::TraverseShaderVariable(uniform, false, &visitor);
return;
}
+ else if (gl::IsAtomicCounterType(uniform.type))
+ {
+ UniformEncodingVisitorD3D visitor(shader->getType(), HLSLRegisterType::UnorderedAccessView,
+ &dummyEncoder, uniformMap);
+ sh::TraverseShaderVariable(uniform, false, &visitor);
+ mAtomicBindingMap[uniform.name] = uniform.binding;
+ return;
+ }
const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shader);
unsigned int startRegister = shaderD3D->getUniformRegister(uniform.name);
@@ -2568,6 +2703,45 @@ void ProgramD3D::assignAllImageRegisters()
}
}
+void ProgramD3D::assignAllAtomicCounterRegisters()
+{
+ if (mAtomicBindingMap.empty())
+ {
+ return;
+ }
+ gl::ShaderType shaderType = gl::ShaderType::Compute;
+ const gl::Shader *computeShader = mState.getAttachedShader(shaderType);
+ if (computeShader)
+ {
+ const ShaderD3D *computeShaderD3D = GetImplAs<ShaderD3D>(computeShader);
+ auto &registerIndices = mComputeAtomicCounterBufferRegisterIndices;
+ unsigned int firstRegister = GL_INVALID_VALUE;
+ unsigned int lastRegister = 0;
+ for (auto &atomicBinding : mAtomicBindingMap)
+ {
+ ASSERT(computeShaderD3D->hasUniform(atomicBinding.first));
+ unsigned int currentRegister =
+ computeShaderD3D->getUniformRegister(atomicBinding.first);
+ ASSERT(currentRegister != GL_INVALID_INDEX);
+ const int kBinding = atomicBinding.second;
+
+ registerIndices[kBinding] = currentRegister;
+
+ firstRegister = std::min(firstRegister, currentRegister);
+ lastRegister = std::max(lastRegister, currentRegister);
+ }
+ ASSERT(firstRegister != GL_INVALID_VALUE);
+ ASSERT(lastRegister != GL_INVALID_VALUE);
+ mUsedComputeAtomicCounterRange = gl::RangeUI(firstRegister, lastRegister + 1);
+ }
+ else
+ {
+ // Implement atomic counters for non-compute shaders
+ // http://anglebug.com/1729
+ UNIMPLEMENTED();
+ }
+}
+
void ProgramD3D::assignImageRegisters(size_t uniformIndex)
{
D3DUniform *d3dUniform = mD3DUniforms[uniformIndex];
@@ -2700,6 +2874,7 @@ void ProgramD3D::reset()
SafeDeleteContainer(mD3DUniforms);
mD3DUniformBlocks.clear();
mD3DShaderStorageBlocks.clear();
+ mComputeAtomicCounterBufferRegisterIndices.fill({});
for (gl::ShaderType shaderType : gl::AllShaderTypes())
{
@@ -2711,6 +2886,7 @@ void ProgramD3D::reset()
mReadonlyImagesCS.clear();
mUsedShaderSamplerRanges.fill({0, 0});
+ mUsedComputeAtomicCounterRange = {0, 0};
mDirtySamplerMapping = true;
mUsedComputeImageRange = {0, 0};
mUsedComputeReadonlyImageRange = {0, 0};
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
index 4853ae8ea28..46b405c3ddb 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -183,9 +183,9 @@ class ProgramD3D : public ProgramImpl
bool usesGeometryShaderForPointSpriteEmulation() const;
bool usesInstancedPointSpriteEmulation() const;
- angle::Result load(const gl::Context *context,
- gl::InfoLog &infoLog,
- gl::BinaryInputStream *stream) override;
+ std::unique_ptr<LinkEvent> load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog) override;
void save(const gl::Context *context, gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
void setSeparable(bool separable) override;
@@ -217,6 +217,9 @@ class ProgramD3D : public ProgramImpl
void updateUniformBufferCache(const gl::Caps &caps,
const gl::ShaderMap<unsigned int> &reservedShaderRegisterIndexes);
+ unsigned int getAtomicCounterBufferRegisterIndex(GLuint binding,
+ gl::ShaderType shaderType) const;
+
unsigned int getShaderStorageBufferRegisterIndex(GLuint blockIndex,
gl::ShaderType shaderType) const;
const std::vector<GLint> &getShaderUniformBufferCache(gl::ShaderType shaderType) const;
@@ -329,6 +332,9 @@ class ProgramD3D : public ProgramImpl
class GetGeometryExecutableTask;
class GraphicsProgramLinkEvent;
+ class LoadBinaryTask;
+ class LoadBinaryLinkEvent;
+
class VertexExecutable
{
public:
@@ -435,6 +441,7 @@ class ProgramD3D : public ProgramImpl
gl::RangeUI *outUsedRange);
void assignAllImageRegisters();
+ void assignAllAtomicCounterRegisters();
void assignImageRegisters(size_t uniformIndex);
static void AssignImages(unsigned int startImageIndex,
int startLogicalImageUnit,
@@ -467,6 +474,10 @@ class ProgramD3D : public ProgramImpl
gl::InfoLog &infoLog);
angle::Result compileComputeExecutable(d3d::Context *context, gl::InfoLog &infoLog);
+ angle::Result loadBinaryShaderExecutables(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog);
+
void gatherTransformFeedbackVaryings(const gl::VaryingPacking &varyings,
const BuiltinInfo &builtins);
D3DUniform *getD3DUniformFromLocation(GLint location);
@@ -522,6 +533,7 @@ class ProgramD3D : public ProgramImpl
std::vector<Image> mReadonlyImagesCS;
gl::RangeUI mUsedComputeImageRange;
gl::RangeUI mUsedComputeReadonlyImageRange;
+ gl::RangeUI mUsedComputeAtomicCounterRange;
// Cache for pixel shader output layout to save reallocations.
std::vector<GLenum> mPixelShaderOutputLayoutCache;
@@ -539,8 +551,11 @@ class ProgramD3D : public ProgramImpl
std::vector<D3DVarying> mStreamOutVaryings;
std::vector<D3DUniform *> mD3DUniforms;
std::map<std::string, int> mImageBindingMap;
+ std::map<std::string, int> mAtomicBindingMap;
std::vector<D3DInterfaceBlock> mD3DUniformBlocks;
std::vector<D3DInterfaceBlock> mD3DShaderStorageBlocks;
+ std::array<unsigned int, gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFERS>
+ mComputeAtomicCounterBufferRegisterIndices;
std::vector<sh::Uniform> mImage2DUniforms;
gl::ImageUnitTextureTypeMap mComputeShaderImage2DBindLayoutCache;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h
index 888c5caaedd..18c7b8e6e5e 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -92,7 +92,7 @@ class Context : angle::NonCopyable
// ANGLE_TRY for HRESULT errors.
#define ANGLE_TRY_HR(CONTEXT, EXPR, MESSAGE) \
- \
+ do \
{ \
auto ANGLE_LOCAL_VAR = (EXPR); \
if (ANGLE_UNLIKELY(FAILED(ANGLE_LOCAL_VAR))) \
@@ -100,16 +100,17 @@ class Context : angle::NonCopyable
CONTEXT->handleResult(ANGLE_LOCAL_VAR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \
return angle::Result::Stop; \
} \
- }
+ } while (0)
#define ANGLE_CHECK_HR(CONTEXT, EXPR, MESSAGE, ERROR) \
+ do \
{ \
if (ANGLE_UNLIKELY(!(EXPR))) \
{ \
CONTEXT->handleResult(ERROR, MESSAGE, __FILE__, ANGLE_FUNCTION, __LINE__); \
return angle::Result::Stop; \
} \
- }
+ } while (0)
#define ANGLE_HR_UNREACHABLE(context) \
UNREACHABLE(); \
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.h
index 8d2dfaf00ce..4eb43b5b929 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/TextureD3D.h
@@ -160,7 +160,7 @@ class TextureD3D : public TextureImpl
angle::Result releaseTexStorage(const gl::Context *context);
- GLuint getBaseLevel() const { return mBaseLevel; };
+ GLuint getBaseLevel() const { return mBaseLevel; }
virtual void markAllImagesDirty() = 0;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
index 2376fbb5b8a..2b91b9f3d59 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
@@ -62,7 +62,7 @@ class VertexBuffer : angle::NonCopyable
unsigned int getSerial() const;
// This may be overridden (e.g. by VertexBuffer11) if necessary.
- virtual void hintUnmapResource(){};
+ virtual void hintUnmapResource() {}
// Reference counting.
void addRef();
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
index 527f1942859..227484a5426 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -37,7 +37,23 @@ enum
CONSTANT_VERTEX_BUFFER_SIZE = 4096
};
-// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
+// Warning: ensure the binding matches attrib.bindingIndex before using these functions.
+int64_t GetMaxAttributeByteOffsetForDraw(const gl::VertexAttribute &attrib,
+ const gl::VertexBinding &binding,
+ int64_t elementCount)
+{
+ CheckedNumeric<int64_t> stride = ComputeVertexAttributeStride(attrib, binding);
+ CheckedNumeric<int64_t> offset = ComputeVertexAttributeOffset(attrib, binding);
+ CheckedNumeric<int64_t> size = ComputeVertexAttributeTypeSize(attrib);
+
+ ASSERT(elementCount > 0);
+
+ CheckedNumeric<int64_t> result =
+ stride * (CheckedNumeric<int64_t>(elementCount) - 1) + size + offset;
+ return result.ValueOrDefault(std::numeric_limits<int64_t>::max());
+}
+
+// Warning: ensure the binding matches attrib.bindingIndex before using these functions.
int ElementsInBuffer(const gl::VertexAttribute &attrib,
const gl::VertexBinding &binding,
unsigned int size)
@@ -345,7 +361,11 @@ angle::Result VertexDataManager::StoreStaticAttrib(const gl::Context *context,
const int offset = static_cast<int>(ComputeVertexAttributeOffset(attrib, binding));
ANGLE_TRY(bufferD3D->getData(context, &sourceData));
- sourceData += offset;
+
+ if (sourceData)
+ {
+ sourceData += offset;
+ }
unsigned int streamOffset = 0;
@@ -363,8 +383,11 @@ angle::Result VertexDataManager::StoreStaticAttrib(const gl::Context *context,
ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize()));
int startIndex = offset / static_cast<int>(ComputeVertexAttributeStride(attrib, binding));
- ANGLE_TRY(staticBuffer->storeStaticAttribute(context, attrib, binding, -startIndex,
- totalCount, 0, sourceData));
+ if (totalCount > 0)
+ {
+ ANGLE_TRY(staticBuffer->storeStaticAttribute(context, attrib, binding, -startIndex,
+ totalCount, 0, sourceData));
+ }
}
unsigned int firstElementOffset =
@@ -482,10 +505,12 @@ angle::Result VertexDataManager::reserveSpaceForAttrib(const gl::Context *contex
GLint firstVertexIndex = binding.getDivisor() > 0 ? 0 : start;
int64_t maxVertexCount =
static_cast<int64_t>(firstVertexIndex) + static_cast<int64_t>(totalCount);
- int elementsInBuffer =
- ElementsInBuffer(attrib, binding, static_cast<unsigned int>(bufferD3D->getSize()));
- ANGLE_CHECK(GetImplAs<ContextD3D>(context), maxVertexCount <= elementsInBuffer,
+ int64_t maxByte = GetMaxAttributeByteOffsetForDraw(attrib, binding, maxVertexCount);
+
+ ASSERT(bufferD3D->getSize() <= static_cast<size_t>(std::numeric_limits<int64_t>::max()));
+ ANGLE_CHECK(GetImplAs<ContextD3D>(context),
+ maxByte <= static_cast<int64_t>(bufferD3D->getSize()),
"Vertex buffer is not big enough for the draw call.", GL_INVALID_OPERATION);
}
return mStreamingBuffer.reserveVertexSpace(context, attrib, binding, totalCount, instances);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc
index 5c9434c4740..566270049b1 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Blit11Helper_autogen.inc
@@ -1,7 +1,7 @@
// GENERATED FILE - DO NOT EDIT.
// Generated by gen_blit11helper.py.
//
-// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Copyright 2019 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.
//
@@ -914,7 +914,7 @@ Blit11::BlitShaderType Blit11::getBlitShaderType(BlitShaderOperation operation,
UNREACHABLE();
return BLITSHADER_INVALID;
}
-};
+}
angle::Result Blit11::mapBlitShader(const gl::Context *context,
BlitShaderType blitShaderType)
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
index 213cb8b084e..0ec1a2aa61d 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -177,7 +177,10 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage
angle::Result getSRVForFormat(const gl::Context *context,
DXGI_FORMAT srvFormat,
const d3d11::ShaderResourceView **srvOut);
- angle::Result getRawUAV(const gl::Context *context, d3d11::UnorderedAccessView **uavOut);
+ angle::Result getRawUAV(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
+ d3d11::UnorderedAccessView **uavOut);
private:
static void FillBufferDesc(D3D11_BUFFER_DESC *bufferDesc,
@@ -185,11 +188,12 @@ class Buffer11::NativeStorage : public Buffer11::BufferStorage
BufferUsage usage,
unsigned int bufferSize);
void clearSRVs();
+ void clearUAVs();
d3d11::Buffer mBuffer;
const angle::Subject *mOnStorageChanged;
std::map<DXGI_FORMAT, d3d11::ShaderResourceView> mBufferResourceViews;
- d3d11::UnorderedAccessView mBufferRawUAV;
+ std::map<std::pair<unsigned int, unsigned int>, d3d11::UnorderedAccessView> mBufferRawUAVs;
};
// A emulated indexed buffer storage represents an underlying D3D11 buffer for data
@@ -692,7 +696,10 @@ angle::Result Buffer11::getConstantBufferRange(const gl::Context *context,
return angle::Result::Continue;
}
-angle::Result Buffer11::getRawUAV(const gl::Context *context, d3d11::UnorderedAccessView **uavOut)
+angle::Result Buffer11::getRawUAVRange(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ d3d11::UnorderedAccessView **uavOut)
{
NativeStorage *nativeStorage = nullptr;
ANGLE_TRY(getBufferStorage(context, BUFFER_USAGE_RAW_UAV, &nativeStorage));
@@ -705,7 +712,8 @@ angle::Result Buffer11::getRawUAV(const gl::Context *context, d3d11::UnorderedAc
onStorageUpdate(nativeStorage);
}
- return nativeStorage->getRawUAV(context, uavOut);
+ return nativeStorage->getRawUAV(context, static_cast<unsigned int>(offset),
+ static_cast<unsigned int>(size), uavOut);
}
angle::Result Buffer11::getSRV(const gl::Context *context,
@@ -1006,6 +1014,7 @@ Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer,
Buffer11::NativeStorage::~NativeStorage()
{
clearSRVs();
+ clearUAVs();
}
bool Buffer11::NativeStorage::isCPUAccessible(GLbitfield access) const
@@ -1047,6 +1056,11 @@ angle::Result Buffer11::NativeStorage::copyFromStorage(const gl::Context *contex
clampedSize = std::min(clampedSize, mBufferSize - destOffset);
}
+ if (clampedSize == 0)
+ {
+ return angle::Result::Continue;
+ }
+
if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
{
@@ -1087,6 +1101,13 @@ angle::Result Buffer11::NativeStorage::resize(const gl::Context *context,
size_t size,
bool preserveData)
{
+ if (size == 0)
+ {
+ mBuffer.reset();
+ mBufferSize = 0;
+ return angle::Result::Continue;
+ }
+
D3D11_BUFFER_DESC bufferDesc;
FillBufferDesc(&bufferDesc, mRenderer, mUsage, static_cast<unsigned int>(size));
@@ -1121,6 +1142,9 @@ angle::Result Buffer11::NativeStorage::resize(const gl::Context *context,
// Free the SRVs.
clearSRVs();
+ // Free the UAVs.
+ clearUAVs();
+
// Notify that the storage has changed.
if (mOnStorageChanged)
{
@@ -1261,26 +1285,33 @@ angle::Result Buffer11::NativeStorage::getSRVForFormat(const gl::Context *contex
}
angle::Result Buffer11::NativeStorage::getRawUAV(const gl::Context *context,
+ unsigned int offset,
+ unsigned int size,
d3d11::UnorderedAccessView **uavOut)
{
- if (mBufferRawUAV.get())
+ ASSERT(offset + size <= mBufferSize);
+
+ auto bufferRawUAV = mBufferRawUAVs.find({offset, size});
+ if (bufferRawUAV != mBufferRawUAVs.end())
{
- *uavOut = &mBufferRawUAV;
+ *uavOut = &bufferRawUAV->second;
return angle::Result::Continue;
}
D3D11_UNORDERED_ACCESS_VIEW_DESC bufferUAVDesc;
- bufferUAVDesc.Buffer.FirstElement = 0;
- bufferUAVDesc.Buffer.NumElements = mBufferSize / 4;
+
+ // DXGI_FORMAT_R32_TYPELESS uses 4 bytes per element
+ constexpr int kBytesToElement = 4;
+ bufferUAVDesc.Buffer.FirstElement = offset / kBytesToElement;
+ bufferUAVDesc.Buffer.NumElements = size / kBytesToElement;
bufferUAVDesc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW;
bufferUAVDesc.Format = DXGI_FORMAT_R32_TYPELESS; // Format must be DXGI_FORMAT_R32_TYPELESS,
// when creating Raw Unordered Access View
bufferUAVDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
ANGLE_TRY(mRenderer->allocateResource(GetImplAs<Context11>(context), bufferUAVDesc,
- mBuffer.get(), &mBufferRawUAV));
-
- *uavOut = &mBufferRawUAV;
+ mBuffer.get(), &mBufferRawUAVs[{offset, size}]));
+ *uavOut = &mBufferRawUAVs[{offset, size}];
return angle::Result::Continue;
}
@@ -1289,6 +1320,11 @@ void Buffer11::NativeStorage::clearSRVs()
mBufferResourceViews.clear();
}
+void Buffer11::NativeStorage::clearUAVs()
+{
+ mBufferRawUAVs.clear();
+}
+
// Buffer11::EmulatedIndexStorage implementation
Buffer11::EmulatedIndexedStorage::EmulatedIndexedStorage(Renderer11 *renderer)
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
index ba3773eafde..35b6745eb13 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
@@ -70,7 +70,11 @@ class Buffer11 : public BufferD3D
angle::Result getSRV(const gl::Context *context,
DXGI_FORMAT srvFormat,
const d3d11::ShaderResourceView **srvOut);
- angle::Result getRawUAV(const gl::Context *context, d3d11::UnorderedAccessView **uavOut);
+ angle::Result getRawUAVRange(const gl::Context *context,
+ GLintptr offset,
+ GLsizeiptr size,
+ d3d11::UnorderedAccessView **uavOut);
+
bool isMapped() const { return mMappedStorage != nullptr; }
angle::Result packPixels(const gl::Context *context,
const gl::FramebufferAttachment &readAttachment,
@@ -132,6 +136,9 @@ class Buffer11 : public BufferD3D
size_t sourceOffset,
size_t storageSize);
+ angle::Result getNativeStorageForUAV(const gl::Context *context,
+ Buffer11::NativeStorage **storageOut);
+
template <typename StorageOutT>
angle::Result getBufferStorage(const gl::Context *context,
BufferUsage usage,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
index 70603683544..3e673cf0f00 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.cpp
@@ -421,10 +421,10 @@ void Context11::popGroupMarker()
}
}
-void Context11::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message)
+void Context11::pushDebugGroup(GLenum source, GLuint id, const std::string &message)
{
// Fall through to the EXT_debug_marker functions
- pushGroupMarker(length, message);
+ pushGroupMarker(message.size(), message.c_str());
}
void Context11::popDebugGroup()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h
index aef1b20642d..df1e2611742 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Context11.h
@@ -119,7 +119,7 @@ class Context11 : public ContextD3D, public MultisampleTextureInitializer
void popGroupMarker() override;
// KHR_debug
- void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
+ void pushDebugGroup(GLenum source, GLuint id, const std::string &message) override;
void popDebugGroup() override;
// State sync with dirty bits.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
index a3c20da33b2..40666cbef5d 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -360,7 +360,8 @@ angle::Result Image11::copyFromTexStorage(const gl::Context *context,
const TextureHelper11 *textureHelper = nullptr;
ANGLE_TRY(storage11->getResource(context, &textureHelper));
- UINT subresourceIndex = storage11->getSubresourceIndex(imageIndex);
+ UINT subresourceIndex = 0;
+ ANGLE_TRY(storage11->getSubresourceIndex(context, imageIndex, &subresourceIndex));
gl::Box sourceBox(0, 0, 0, mWidth, mHeight, mDepth);
return copyWithoutConversion(context, gl::Offset(), sourceBox, *textureHelper,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index 11bf4b738ac..9b67ac4ff59 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -521,7 +521,7 @@ Renderer11::Renderer11(egl::Display *display)
UNREACHABLE();
}
- mCreateDebugDevice = ShouldUseDebugLayers(attributes);
+ mCreateDebugDevice = false;
}
else if (mDisplay->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
{
@@ -689,7 +689,11 @@ egl::Error Renderer11::initialize()
if (SUCCEEDED(result))
{
D3D11_MESSAGE_ID hideMessages[] = {
- D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET};
+ D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET,
+
+ // Robust access behaviour makes out of bounds messages safe
+ D3D11_MESSAGE_ID_DEVICE_DRAW_VERTEX_BUFFER_TOO_SMALL,
+ };
D3D11_INFO_QUEUE_FILTER filter = {};
filter.DenyList.NumIDs = static_cast<unsigned int>(ArraySize(hideMessages));
@@ -2406,10 +2410,15 @@ angle::Result Renderer11::copyTexture(const gl::Context *context,
if (srcTarget == gl::TextureTarget::_2D || srcTarget == gl::TextureTarget::_3D)
{
gl::ImageIndex sourceIndex = gl::ImageIndex::MakeFromTarget(srcTarget, sourceLevel);
- UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
+
+ UINT sourceSubresource = 0;
+ ANGLE_TRY(
+ sourceStorage11->getSubresourceIndex(context, sourceIndex, &sourceSubresource));
gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(destTarget, destLevel);
- UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
+
+ UINT destSubresource = 0;
+ ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource));
D3D11_BOX d3dBox{static_cast<UINT>(sourceBox.x),
static_cast<UINT>(sourceBox.y),
@@ -2435,9 +2444,14 @@ angle::Result Renderer11::copyTexture(const gl::Context *context,
for (int i = 0; i < sourceBox.depth; i++)
{
gl::ImageIndex srcIndex = gl::ImageIndex::Make2DArray(sourceLevel, i + sourceBox.z);
- UINT sourceSubresource = sourceStorage11->getSubresourceIndex(srcIndex);
- gl::ImageIndex dIndex = gl::ImageIndex::Make2DArray(destLevel, i + destOffset.z);
- UINT destSubresource = destStorage11->getSubresourceIndex(dIndex);
+ UINT sourceSubresource = 0;
+ ANGLE_TRY(
+ sourceStorage11->getSubresourceIndex(context, srcIndex, &sourceSubresource));
+
+ gl::ImageIndex dIndex = gl::ImageIndex::Make2DArray(destLevel, i + destOffset.z);
+ UINT destSubresource = 0;
+ ANGLE_TRY(destStorage11->getSubresourceIndex(context, dIndex, &destSubresource));
+
mDeviceContext->CopySubresourceRegion(
destResource->get(), destSubresource, destOffset.x, destOffset.y, 0,
sourceResource->get(), sourceSubresource, &d3dBox);
@@ -2525,7 +2539,8 @@ angle::Result Renderer11::copyCompressedTexture(const gl::Context *context,
ANGLE_TRY(destStorage11->getResource(context, &destResource));
gl::ImageIndex destIndex = gl::ImageIndex::Make2D(destLevel);
- UINT destSubresource = destStorage11->getSubresourceIndex(destIndex);
+ UINT destSubresource = 0;
+ ANGLE_TRY(destStorage11->getSubresourceIndex(context, destIndex, &destSubresource));
TextureD3D *sourceD3D = GetImplAs<TextureD3D>(source);
ASSERT(sourceD3D);
@@ -2540,7 +2555,8 @@ angle::Result Renderer11::copyCompressedTexture(const gl::Context *context,
ANGLE_TRY(sourceStorage11->getResource(context, &sourceResource));
gl::ImageIndex sourceIndex = gl::ImageIndex::Make2D(sourceLevel);
- UINT sourceSubresource = sourceStorage11->getSubresourceIndex(sourceIndex);
+ UINT sourceSubresource = 0;
+ ANGLE_TRY(sourceStorage11->getSubresourceIndex(context, sourceIndex, &sourceSubresource));
mDeviceContext->CopySubresourceRegion(destResource->get(), destSubresource, 0, 0, 0,
sourceResource->get(), sourceSubresource, nullptr);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index dcdd4c42fc7..9861b9b85cc 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -317,9 +317,9 @@ class Renderer11 : public RendererD3D
// D3D11-renderer specific methods
ID3D11Device *getDevice() { return mDevice; }
void *getD3DDevice() override;
- ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
- ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; };
- IDXGIFactory *getDxgiFactory() { return mDxgiFactory; };
+ ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }
+ ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; }
+ IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }
angle::Result getBlendState(const gl::Context *context,
const d3d11::BlendStateKey &key,
@@ -388,7 +388,7 @@ class Renderer11 : public RendererD3D
bool stencilBlit);
bool isES3Capable() const;
- const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; };
+ const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; }
RendererClass getRendererClass() const override;
StateManager11 *getStateManager() { return &mStateManager; }
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp
index c702fd9c476..2506200afad 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/ResourceManager11.cpp
@@ -23,6 +23,11 @@ constexpr FLOAT kDebugColorInitClearValue[4] = {0.3f, 0.5f, 0.7f, 0.5f};
constexpr FLOAT kDebugDepthInitValue = 0.2f;
constexpr UINT8 kDebugStencilInitValue = 3;
+// A hard limit on buffer size. This works around a problem in the NVIDIA drivers where buffer sizes
+// close to MAX_UINT would give undefined results. The limit of MAX_UINT/2 should be generous enough
+// for almost any demanding application.
+constexpr UINT kMaximumBufferSizeHardLimit = std::numeric_limits<UINT>::max() >> 1;
+
uint64_t ComputeMippedMemoryUsage(unsigned int width,
unsigned int height,
unsigned int depth,
@@ -109,6 +114,12 @@ HRESULT CreateResource(ID3D11Device *device,
const D3D11_SUBRESOURCE_DATA *initData,
ID3D11Buffer **buffer)
{
+ // Force buffers to be limited to a fixed max size.
+ if (desc->ByteWidth > kMaximumBufferSizeHardLimit)
+ {
+ return E_OUTOFMEMORY;
+ }
+
return device->CreateBuffer(desc, initData, buffer);
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
index 05802a649f4..0fb14ae8b84 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.cpp
@@ -3585,6 +3585,7 @@ angle::Result StateManager11::syncShaderStorageBuffersForShader(const gl::Contex
{
const gl::State &glState = context->getState();
const gl::Program *program = glState.getProgram();
+ angle::FixedVector<Buffer11 *, gl::IMPLEMENTATION_MAX_DRAW_BUFFERS> previouslyBound;
for (size_t blockIndex = 0; blockIndex < program->getActiveShaderStorageBlockCount();
blockIndex++)
{
@@ -3595,10 +3596,31 @@ angle::Result StateManager11::syncShaderStorageBuffersForShader(const gl::Contex
continue;
}
- Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(shaderStorageBuffer.get());
+ if (std::find(previouslyBound.begin(), previouslyBound.end(), bufferStorage) !=
+ previouslyBound.end())
+ {
+ // D3D11 doesn't support binding a buffer multiple times
+ // http://anglebug.com/3032
+ ERR() << "Writing to multiple blocks on the same buffer is not allowed.";
+ return angle::Result::Stop;
+ }
+ previouslyBound.push_back(bufferStorage);
+
d3d11::UnorderedAccessView *uavPtr = nullptr;
- // TODO(jiajia.qin@intel.com): add buffer offset support. http://anglebug.com/1951
- ANGLE_TRY(bufferStorage->getRawUAV(context, &uavPtr));
+ GLsizeiptr viewSize = 0;
+ // Bindings only have a valid size if bound using glBindBufferRange
+ if (shaderStorageBuffer.getSize() > 0)
+ {
+ viewSize = shaderStorageBuffer.getSize();
+ }
+ // We use the buffer size for glBindBufferBase
+ else
+ {
+ viewSize = bufferStorage->getSize();
+ }
+ ANGLE_TRY(bufferStorage->getRawUAVRange(context, shaderStorageBuffer.getOffset(), viewSize,
+ &uavPtr));
// We need to make sure that resource being set to UnorderedAccessView slot |registerIndex|
// is not bound on SRV.
@@ -3664,7 +3686,63 @@ angle::Result StateManager11::syncUniformBuffers(const gl::Context *context)
angle::Result StateManager11::syncAtomicCounterBuffers(const gl::Context *context)
{
- // TODO(jie.a.chen@intel.com): http://anglebug.com/1729
+ if (mProgramD3D->hasShaderStage(gl::ShaderType::Compute))
+ {
+ ANGLE_TRY(syncAtomicCounterBuffersForShader(context, gl::ShaderType::Compute));
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result StateManager11::syncAtomicCounterBuffersForShader(const gl::Context *context,
+ gl::ShaderType shaderType)
+{
+ const gl::State &glState = context->getState();
+ const gl::Program *program = glState.getProgram();
+ for (const auto &atomicCounterBuffer : program->getState().getAtomicCounterBuffers())
+ {
+ GLuint binding = atomicCounterBuffer.binding;
+ const auto &buffer = glState.getIndexedAtomicCounterBuffer(binding);
+
+ if (buffer.get() == nullptr)
+ {
+ continue;
+ }
+
+ Buffer11 *bufferStorage = GetImplAs<Buffer11>(buffer.get());
+ // TODO(enrico.galli@intel.com): Check to make sure that we aren't binding the same buffer
+ // multiple times, as this is unsupported by D3D11. http://anglebug.com/3141
+
+ // Bindings only have a valid size if bound using glBindBufferRange. Therefore, we use the
+ // buffer size for glBindBufferBase
+ GLsizeiptr viewSize = (buffer.getSize() > 0) ? buffer.getSize() : bufferStorage->getSize();
+ d3d11::UnorderedAccessView *uavPtr = nullptr;
+ ANGLE_TRY(bufferStorage->getRawUAVRange(context, buffer.getOffset(), viewSize, &uavPtr));
+
+ // We need to make sure that resource being set to UnorderedAccessView slot |registerIndex|
+ // is not bound on SRV.
+ if (uavPtr && unsetConflictingView(uavPtr->get()))
+ {
+ mInternalDirtyBits.set(DIRTY_BIT_TEXTURE_AND_SAMPLER_STATE);
+ }
+
+ const unsigned int registerIndex =
+ mProgramD3D->getAtomicCounterBufferRegisterIndex(binding, shaderType);
+
+ if (shaderType == gl::ShaderType::Compute)
+ {
+ ID3D11UnorderedAccessView *uav = uavPtr->get();
+ ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ deviceContext->CSSetUnorderedAccessViews(registerIndex, 1, &uav, nullptr);
+ }
+ else
+ {
+ // Atomic Shaders on non-compute shaders are currently unimplemented
+ // http://anglebug.com/1729
+ UNIMPLEMENTED();
+ }
+ }
+
return angle::Result::Continue;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
index 301d6f60d55..6c37949f210 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/StateManager11.h
@@ -370,6 +370,8 @@ class StateManager11 final : angle::NonCopyable
angle::Result syncUniformBuffersForShader(const gl::Context *context,
gl::ShaderType shaderType);
angle::Result syncAtomicCounterBuffers(const gl::Context *context);
+ angle::Result syncAtomicCounterBuffersForShader(const gl::Context *context,
+ gl::ShaderType shaderType);
angle::Result syncShaderStorageBuffers(const gl::Context *context);
angle::Result syncTransformFeedbackBuffers(const gl::Context *context);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
index f082f206323..031df72e4ce 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -194,13 +194,16 @@ angle::Result TextureStorage11::getMippedResource(const gl::Context *context,
return getResource(context, outResource);
}
-UINT TextureStorage11::getSubresourceIndex(const gl::ImageIndex &index) const
+angle::Result TextureStorage11::getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const
{
UINT mipSlice = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.getLayerIndex() : 0);
UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
ASSERT(subresource != std::numeric_limits<UINT>::max());
- return subresource;
+ *outSubresourceIndex = subresource;
+ return angle::Result::Continue;
}
angle::Result TextureStorage11::getSRVForSampler(const gl::Context *context,
@@ -531,7 +534,8 @@ angle::Result TextureStorage11::updateSubresourceLevel(const gl::Context *contex
ANGLE_TRY(getResource(context, &dstTexture));
}
- unsigned int dstSubresource = getSubresourceIndex(index);
+ unsigned int dstSubresource = 0;
+ ANGLE_TRY(getSubresourceIndex(context, index, &dstSubresource));
ASSERT(dstTexture->valid());
@@ -586,7 +590,8 @@ angle::Result TextureStorage11::copySubresourceLevel(const gl::Context *context,
ASSERT(srcTexture->valid());
- unsigned int srcSubresource = getSubresourceIndex(index);
+ unsigned int srcSubresource = 0;
+ ANGLE_TRY(getSubresourceIndex(context, index, &srcSubresource));
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
@@ -713,7 +718,8 @@ angle::Result TextureStorage11::setData(const gl::Context *context,
ANGLE_TRY(getResource(context, &resource));
ASSERT(resource && resource->valid());
- UINT destSubresource = getSubresourceIndex(index);
+ UINT destSubresource = 0;
+ ANGLE_TRY(getSubresourceIndex(context, index, &destSubresource));
const gl::InternalFormat &internalFormatInfo =
gl::GetInternalFormatInfo(image->getInternalFormat(), type);
@@ -824,7 +830,10 @@ angle::Result TextureStorage11::initDropStencilTexture(const gl::Context *contex
gl::Box wholeArea(0, 0, 0, getLevelWidth(index.getLevelIndex()),
getLevelHeight(index.getLevelIndex()), 1);
gl::Extents wholeSize(wholeArea.width, wholeArea.height, 1);
- UINT subresource = getSubresourceIndex(index);
+
+ UINT subresource = 0;
+ ANGLE_TRY(getSubresourceIndex(context, index, &subresource));
+
ANGLE_TRY(mRenderer->getBlitter()->copyDepthStencil(
context, *sourceTexture, subresource, wholeArea, wholeSize, mDropStencilTexture,
subresource, wholeArea, wholeSize, nullptr));
@@ -1642,6 +1651,19 @@ TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
TextureStorage11_EGLImage::~TextureStorage11_EGLImage() {}
+angle::Result TextureStorage11_EGLImage::getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const
+{
+ ASSERT(index.getType() == gl::TextureType::_2D);
+ ASSERT(index.getLevelIndex() == 0);
+
+ RenderTarget11 *renderTarget11 = nullptr;
+ ANGLE_TRY(getImageRenderTarget(context, &renderTarget11));
+ *outSubresourceIndex = renderTarget11->getSubresourceIndex();
+ return angle::Result::Continue;
+}
+
angle::Result TextureStorage11_EGLImage::getResource(const gl::Context *context,
const TextureHelper11 **outResource)
{
@@ -1897,7 +1919,9 @@ angle::Result TextureStorage11_Cube::onDestroy(const gl::Context *context)
TextureStorage11_Cube::~TextureStorage11_Cube() {}
-UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const
+angle::Result TextureStorage11_Cube::getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const
{
UINT arraySlice = index.cubeMapFaceIndex();
if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture &&
@@ -1905,15 +1929,16 @@ UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) con
{
UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
ASSERT(subresource != std::numeric_limits<UINT>::max());
- return subresource;
+ *outSubresourceIndex = subresource;
}
else
{
UINT mipSlice = static_cast<UINT>(index.getLevelIndex() + mTopLevel);
UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
ASSERT(subresource != std::numeric_limits<UINT>::max());
- return subresource;
+ *outSubresourceIndex = subresource;
}
+ return angle::Result::Continue;
}
angle::Result TextureStorage11_Cube::copyToStorage(const gl::Context *context,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
index a77c7c95688..82131cd9b03 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
@@ -103,7 +103,9 @@ class TextureStorage11 : public TextureStorage
angle::Result getUAVForImage(const gl::Context *context,
const gl::ImageUnit &imageUnit,
const d3d11::SharedUAV **outUAV);
- virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
+ virtual angle::Result getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const;
virtual angle::Result getResource(const gl::Context *context,
const TextureHelper11 **outResource) = 0;
virtual void associateImage(Image11 *image, const gl::ImageIndex &index) = 0;
@@ -419,6 +421,9 @@ class TextureStorage11_EGLImage final : public TextureStorage11ImmutableBase
RenderTarget11 *renderTarget11);
~TextureStorage11_EGLImage() override;
+ angle::Result getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const override;
angle::Result getResource(const gl::Context *context,
const TextureHelper11 **outResource) override;
angle::Result getSRVForSampler(const gl::Context *context,
@@ -478,7 +483,9 @@ class TextureStorage11_Cube : public TextureStorage11
angle::Result onDestroy(const gl::Context *context) override;
- UINT getSubresourceIndex(const gl::ImageIndex &index) const override;
+ angle::Result getSubresourceIndex(const gl::Context *context,
+ const gl::ImageIndex &index,
+ UINT *outSubresourceIndex) const override;
angle::Result getResource(const gl::Context *context,
const TextureHelper11 **outResource) override;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
index 9fcd8a5c2f3..e88b9065906 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.cpp
@@ -97,9 +97,9 @@ angle::Result VertexArray11::syncState(const gl::Context *context,
break;
}
- ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
- ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
- ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC)
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC)
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC)
default:
UNREACHABLE();
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/d3d11_blit_shaders_autogen.gni b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/d3d11_blit_shaders_autogen.gni
index 185810e39b3..988ae52724c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/d3d11_blit_shaders_autogen.gni
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/d3d11_blit_shaders_autogen.gni
@@ -1,7 +1,7 @@
# GENERATED FILE - DO NOT EDIT.
# Generated by gen_blit11helper.py.
#
-# Copyright 2018 The ANGLE Project Authors. All rights reserved.
+# Copyright 2019 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.
#
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_blit11helper.py b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_blit11helper.py
index 3b0468908d0..d262b43b8b0 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_blit11helper.py
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/gen_blit11helper.py
@@ -45,7 +45,7 @@ Blit11::BlitShaderType Blit11::getBlitShaderType(BlitShaderOperation operation,
UNREACHABLE();
return BLITSHADER_INVALID;
}}
-}};
+}}
angle::Result Blit11::mapBlitShader(const gl::Context *context,
BlitShaderType blitShaderType)
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index 4fb304caf7d..0d855df3820 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -893,6 +893,21 @@ size_t GetMaxComputeWorkGroupInvocations(D3D_FEATURE_LEVEL featureLevel)
}
}
+unsigned int GetMaxComputeSharedMemorySize(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+ // In D3D11 the maximum total size of all variables with the groupshared storage class is
+ // 32kb.
+ // https://docs.microsoft.com/en-us/windows/desktop/direct3dhlsl/dx-graphics-hlsl-variable-syntax
+ case D3D_FEATURE_LEVEL_11_1:
+ case D3D_FEATURE_LEVEL_11_0:
+ return 32768u;
+ default:
+ return 0u;
+ }
+}
+
size_t GetMaximumComputeUniformVectors(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
@@ -1491,6 +1506,7 @@ void GenerateCaps(ID3D11Device *device,
caps->maxComputeWorkGroupSize = GetMaxComputeWorkGroupSize(featureLevel);
caps->maxComputeWorkGroupInvocations =
static_cast<GLuint>(GetMaxComputeWorkGroupInvocations(featureLevel));
+ caps->maxComputeSharedMemorySize = GetMaxComputeSharedMemorySize(featureLevel);
caps->maxShaderUniformComponents[gl::ShaderType::Compute] =
static_cast<GLuint>(GetMaximumComputeUniformVectors(featureLevel)) * 4;
caps->maxShaderUniformBlocks[gl::ShaderType::Compute] =
@@ -1593,9 +1609,12 @@ void GenerateCaps(ID3D11Device *device,
// and https://msdn.microsoft.com/en-us/library/windows/desktop/ff476900(v=vs.85).aspx
extensions->robustBufferAccessBehavior = true;
extensions->blendMinMax = true;
+ // https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware
+ extensions->floatBlend = true;
extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel);
extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel);
- extensions->instancedArrays = GetInstancingSupport(featureLevel);
+ extensions->instancedArraysANGLE = GetInstancingSupport(featureLevel);
+ extensions->instancedArraysEXT = GetInstancingSupport(featureLevel);
extensions->packReverseRowOrder = true;
extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel);
extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp
index 71171c64479..4a371e9d49b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow_unittest.cpp
@@ -443,7 +443,7 @@ static const scaleValidPair scales[] = {scaleValidPair(1.0f, true), scaleValidPa
scaleValidPair(0.0f, false), scaleValidPair(0.01f, true),
scaleValidPair(2.00f, true)};
-INSTANTIATE_TEST_CASE_P(NativeWindowTest, CoreWindowScaleTest, testing::ValuesIn(scales));
+INSTANTIATE_TEST_SUITE_P(NativeWindowTest, CoreWindowScaleTest, testing::ValuesIn(scales));
// Tests that the size property works as expected in a property set with a SwapChainPanel
class CoreWindowSizeTest : public testing::TestWithParam<std::tuple<float, float, bool>>
@@ -492,6 +492,6 @@ typedef std::tuple<float, float, bool> sizeValidPair;
static const sizeValidPair sizes[] = {sizeValidPair(800, 480, true), sizeValidPair(0, 480, false),
sizeValidPair(800, 0, false), sizeValidPair(0, 0, false)};
-INSTANTIATE_TEST_CASE_P(NativeWindowTest, CoreWindowSizeTest, testing::ValuesIn(sizes));
+INSTANTIATE_TEST_SUITE_P(NativeWindowTest, CoreWindowSizeTest, testing::ValuesIn(sizes));
} // namespace
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp
index 087c2500c12..54a403060b1 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow_unittest.cpp
@@ -566,7 +566,7 @@ static const scaleValidPair scales[] = {scaleValidPair(1.0f, true), scaleValidPa
scaleValidPair(0.0f, false), scaleValidPair(0.01f, true),
scaleValidPair(2.00f, true)};
-INSTANTIATE_TEST_CASE_P(NativeWindowTest, SwapChainPanelScaleTest, testing::ValuesIn(scales));
+INSTANTIATE_TEST_SUITE_P(NativeWindowTest, SwapChainPanelScaleTest, testing::ValuesIn(scales));
// Tests that the size property works as expected in a property set with a SwapChainPanel
class SwapChainPanelSizeTest : public testing::TestWithParam<std::tuple<float, float, bool>>
@@ -615,6 +615,6 @@ typedef std::tuple<float, float, bool> sizeValidPair;
static const sizeValidPair sizes[] = {sizeValidPair(800, 480, true), sizeValidPair(0, 480, false),
sizeValidPair(800, 0, false), sizeValidPair(0, 0, false)};
-INSTANTIATE_TEST_CASE_P(NativeWindowTest, SwapChainPanelSizeTest, testing::ValuesIn(sizes));
+INSTANTIATE_TEST_SUITE_P(NativeWindowTest, SwapChainPanelSizeTest, testing::ValuesIn(sizes));
} // namespace
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
index 77dcf54a0a1..dbf875134bd 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
@@ -59,7 +59,14 @@ angle::Result Buffer9::setData(const gl::Context *context,
angle::Result Buffer9::getData(const gl::Context *context, const uint8_t **outData)
{
- *outData = mMemory.data();
+ if (mMemory.empty())
+ {
+ *outData = nullptr;
+ }
+ else
+ {
+ *outData = mMemory.data();
+ }
return angle::Result::Continue;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
index a39dcf00a98..da4fabcb868 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.cpp
@@ -244,10 +244,10 @@ void Context9::popGroupMarker()
}
}
-void Context9::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message)
+void Context9::pushDebugGroup(GLenum source, GLuint id, const std::string &message)
{
// Fall through to the EXT_debug_marker functions
- pushGroupMarker(length, message);
+ pushGroupMarker(message.size(), message.c_str());
}
void Context9::popDebugGroup()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h
index 7f81a5399fb..944231ad992 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Context9.h
@@ -118,7 +118,7 @@ class Context9 : public ContextD3D
void popGroupMarker() override;
// KHR_debug
- void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
+ void pushDebugGroup(GLenum source, GLuint id, const std::string &message) override;
void popDebugGroup() override;
// State sync with dirty bits.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index 1dd84e77fec..49a1d9ee53c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -89,6 +89,11 @@ static void DrawPoints(IDirect3DDevice9 *device, GLsizei count, const void *indi
device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1);
}
}
+
+// A hard limit on buffer size. This works around a problem in the NVIDIA drivers where buffer sizes
+// close to MAX_UINT would give undefined results. The limit of MAX_UINT/2 should be generous enough
+// for almost any demanding application.
+constexpr UINT kMaximumBufferSizeHardLimit = std::numeric_limits<UINT>::max() >> 1;
} // anonymous namespace
Renderer9::Renderer9(egl::Display *display) : RendererD3D(display), mStateManager(this)
@@ -865,6 +870,12 @@ HRESULT Renderer9::createVertexBuffer(UINT Length,
DWORD Usage,
IDirect3DVertexBuffer9 **ppVertexBuffer)
{
+ // Force buffers to be limited to a fixed max size.
+ if (Length > kMaximumBufferSizeHardLimit)
+ {
+ return E_OUTOFMEMORY;
+ }
+
D3DPOOL Pool = getBufferPool(Usage);
return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, nullptr);
}
@@ -879,6 +890,12 @@ HRESULT Renderer9::createIndexBuffer(UINT Length,
D3DFORMAT Format,
IDirect3DIndexBuffer9 **ppIndexBuffer)
{
+ // Force buffers to be limited to a fixed max size.
+ if (Length > kMaximumBufferSizeHardLimit)
+ {
+ return E_OUTOFMEMORY;
+ }
+
D3DPOOL Pool = getBufferPool(Usage);
return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, nullptr);
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
index 4a8b23d828a..0926a52d779 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -709,9 +709,14 @@ void GenerateCaps(IDirect3D9 *d3d9,
// https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_robustness.txt
extensions->robustBufferAccessBehavior = false;
extensions->blendMinMax = true;
+ // https://docs.microsoft.com/en-us/windows/desktop/direct3ddxgi/format-support-for-direct3d-feature-level-9-1-hardware
+ extensions->floatBlend = false;
extensions->framebufferBlit = true;
extensions->framebufferMultisample = true;
- extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+ extensions->instancedArraysANGLE = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0);
+ // D3D9 requires at least one attribute that has a divisor of 0, which isn't required by the EXT
+ // extension
+ extensions->instancedArraysEXT = false;
extensions->packReverseRowOrder = true;
extensions->standardDerivatives =
(deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gen_angle_format_table.py b/chromium/third_party/angle/src/libANGLE/renderer/gen_angle_format_table.py
index b53210e2cec..2b0262fb9ff 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gen_angle_format_table.py
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gen_angle_format_table.py
@@ -259,13 +259,23 @@ def json_to_table_data(format_id, json, angle_to_gl):
if format_id == "B8G8R8A8_UNORM":
parsed["fastCopyFunctions"] = "BGRACopyFunctions"
- sum_of_bits = 0
- for channel in angle_format.kChannels:
- sum_of_bits += int(parsed[channel])
- parsed["pixelBytes"] = sum_of_bits / 8
+ is_block = format_id.endswith("_BLOCK")
+
+ pixel_bytes = 0
+ if is_block:
+ assert 'blockPixelBytes' in parsed, \
+ 'Compressed format %s requires its block size to be specified in angle_format_data.json' % \
+ format_id
+ pixel_bytes = parsed['blockPixelBytes']
+ else:
+ sum_of_bits = 0
+ for channel in angle_format.kChannels:
+ sum_of_bits += int(parsed[channel])
+ pixel_bytes = sum_of_bits / 8
+ parsed["pixelBytes"] = pixel_bytes
parsed["componentAlignmentMask"] = get_component_alignment_mask(
parsed["channels"], parsed["bits"])
- parsed["isBlock"] = "true" if format_id.endswith("_BLOCK") else "false"
+ parsed["isBlock"] = "true" if is_block else "false"
parsed["isFixed"] = "true" if "FIXED" in format_id else "false"
return format_entry_template.format(**parsed)
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.cpp
index 2cb10e22c72..14464ccdaa6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.cpp
@@ -508,9 +508,9 @@ void ContextGL::popGroupMarker()
mRenderer->popGroupMarker();
}
-void ContextGL::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message)
+void ContextGL::pushDebugGroup(GLenum source, GLuint id, const std::string &message)
{
- mRenderer->pushDebugGroup(source, id, length, message);
+ mRenderer->pushDebugGroup(source, id, message);
}
void ContextGL::popDebugGroup()
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.h
index 9e513cfe378..263e40f5fcb 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ContextGL.h
@@ -173,7 +173,7 @@ class ContextGL : public ContextImpl
void popGroupMarker() override;
// KHR_debug
- void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
+ void pushDebugGroup(GLenum source, GLuint id, const std::string &message) override;
void popDebugGroup() override;
// State sync with dirty bits.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
index b5422e1c9c6..2585d1fa1ee 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.cpp
@@ -57,9 +57,9 @@ ProgramGL::~ProgramGL()
mProgramID = 0;
}
-angle::Result ProgramGL::load(const gl::Context *context,
- gl::InfoLog &infoLog,
- gl::BinaryInputStream *stream)
+std::unique_ptr<LinkEvent> ProgramGL::load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
{
preLink();
@@ -75,13 +75,13 @@ angle::Result ProgramGL::load(const gl::Context *context,
// Verify that the program linked
if (!checkLinkStatus(infoLog))
{
- return angle::Result::Incomplete;
+ return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
}
postLink();
reapplyUBOBindingsIfNeeded(context);
- return angle::Result::Continue;
+ return std::make_unique<LinkEventDone>(angle::Result::Continue);
}
void ProgramGL::save(const gl::Context *context, gl::BinaryOutputStream *stream)
@@ -130,22 +130,24 @@ void ProgramGL::setSeparable(bool separable)
mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
}
-using LinkImplFunctor = std::function<bool()>;
+using LinkImplFunctor = std::function<bool(std::string &)>;
class ProgramGL::LinkTask final : public angle::Closure
{
public:
LinkTask(LinkImplFunctor &&functor) : mLinkImplFunctor(functor), mFallbackToMainContext(false)
{}
- void operator()() override { mFallbackToMainContext = mLinkImplFunctor(); }
+ void operator()() override { mFallbackToMainContext = mLinkImplFunctor(mInfoLog); }
bool fallbackToMainContext() { return mFallbackToMainContext; }
+ const std::string &getInfoLog() { return mInfoLog; }
private:
LinkImplFunctor mLinkImplFunctor;
bool mFallbackToMainContext;
+ std::string mInfoLog;
};
-using PostLinkImplFunctor = std::function<angle::Result(bool)>;
+using PostLinkImplFunctor = std::function<angle::Result(bool, const std::string &)>;
class ProgramGL::LinkEventGL final : public LinkEvent
{
public:
@@ -162,7 +164,7 @@ class ProgramGL::LinkEventGL final : public LinkEvent
angle::Result wait(const gl::Context *context) override
{
mWaitableEvent->wait();
- return mPostLinkImplFunctor(mLinkTask->fallbackToMainContext());
+ return mPostLinkImplFunctor(mLinkTask->fallbackToMainContext(), mLinkTask->getInfoLog());
}
bool isLinking() override { return !mWaitableEvent->isReady(); }
@@ -358,13 +360,13 @@ std::unique_ptr<LinkEvent> ProgramGL::link(const gl::Context *context,
}
}
auto workerPool = context->getWorkerThreadPool();
- auto linkTask = std::make_shared<LinkTask>([this]() {
- std::string infoLog;
- ScopedWorkerContextGL worker(mRenderer.get(), &infoLog);
+ auto linkTask = std::make_shared<LinkTask>([this](std::string &infoLog) {
+ std::string workerInfoLog;
+ ScopedWorkerContextGL worker(mRenderer.get(), &workerInfoLog);
if (!worker())
{
#if !defined(NDEBUG)
- WARN() << "bindWorkerContext failed." << std::endl << infoLog;
+ infoLog += "bindWorkerContext failed.\n" + workerInfoLog;
#endif
// Fallback to the main context.
return true;
@@ -379,7 +381,9 @@ std::unique_ptr<LinkEvent> ProgramGL::link(const gl::Context *context,
return false;
});
- auto postLinkImplTask = [this, &infoLog, &resources](bool fallbackToMainContext) {
+ auto postLinkImplTask = [this, &infoLog, &resources](bool fallbackToMainContext,
+ const std::string &workerInfoLog) {
+ infoLog << workerInfoLog;
if (fallbackToMainContext)
{
mFunctions->linkProgram(mProgramID);
@@ -433,7 +437,7 @@ std::unique_ptr<LinkEvent> ProgramGL::link(const gl::Context *context,
}
else
{
- return std::make_unique<LinkEventDone>(postLinkImplTask(true));
+ return std::make_unique<LinkEventDone>(postLinkImplTask(true, std::string()));
}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h
index 73f5afe8036..c92398f401f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ProgramGL.h
@@ -33,9 +33,9 @@ class ProgramGL : public ProgramImpl
const std::shared_ptr<RendererGL> &renderer);
~ProgramGL() override;
- angle::Result load(const gl::Context *context,
- gl::InfoLog &infoLog,
- gl::BinaryInputStream *stream) override;
+ std::unique_ptr<LinkEvent> load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog) override;
void save(const gl::Context *context, gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
void setSeparable(bool separable) override;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp
index 23f4ef6b2e1..459e555dd25 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/QueryGL.cpp
@@ -326,7 +326,7 @@ angle::Result SyncQueryGL::end(const gl::Context *context)
else if (nativegl::SupportsOcclusionQueries(mFunctions))
{
mSyncProvider.reset(new SyncProviderGLQuery(mFunctions));
- ANGLE_TRY(mSyncProvider->init(context, gl::QueryType::AnySamples))
+ ANGLE_TRY(mSyncProvider->init(context, gl::QueryType::AnySamples));
}
else
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp
index 2655aaaf1ee..042ead517d3 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.cpp
@@ -422,7 +422,7 @@ void RendererGL::pushGroupMarker(GLsizei length, const char *marker) {}
void RendererGL::popGroupMarker() {}
-void RendererGL::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) {}
+void RendererGL::pushDebugGroup(GLenum source, GLuint id, const std::string &message) {}
void RendererGL::popDebugGroup() {}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h
index f1eb3964dd2..f8f6c6b632b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/RendererGL.h
@@ -51,7 +51,7 @@ class StateManagerGL;
class WorkerContext : angle::NonCopyable
{
public:
- virtual ~WorkerContext(){};
+ virtual ~WorkerContext() {}
virtual bool makeCurrent() = 0;
virtual void unmakeCurrent() = 0;
@@ -146,7 +146,7 @@ class RendererGL : angle::NonCopyable
void popGroupMarker();
// KHR_debug
- void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message);
+ void pushDebugGroup(GLenum source, GLuint id, const std::string &message);
void popDebugGroup();
std::string getVendorString() const;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
index e4c6c2e4472..4067d6ad29a 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.cpp
@@ -177,10 +177,10 @@ void ShaderGL::compileAndCheckShader(const char *source)
}
}
-void ShaderGL::compileAsync(const std::string &source)
+void ShaderGL::compileAsync(const std::string &source, std::string &infoLog)
{
- std::string infoLog;
- ScopedWorkerContextGL worker(mRenderer.get(), &infoLog);
+ std::string workerInfoLog;
+ ScopedWorkerContextGL worker(mRenderer.get(), &workerInfoLog);
if (worker())
{
compileAndCheckShader(source.c_str());
@@ -189,7 +189,7 @@ void ShaderGL::compileAsync(const std::string &source)
else
{
#if !defined(NDEBUG)
- WARN() << "bindWorkerContext failed." << std::endl << infoLog;
+ infoLog += "bindWorkerContext failed.\n" + workerInfoLog;
#endif
}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h
index cb10679b126..43d2ba5e335 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/ShaderGL.h
@@ -32,7 +32,7 @@ class ShaderGL : public ShaderImpl
ShCompileOptions prepareSourceAndReturnOptions(const gl::Context *context,
std::stringstream *sourceStream,
std::string *sourcePath) override;
- void compileAsync(const std::string &source) override;
+ void compileAsync(const std::string &source, std::string &infoLog) override;
bool postTranslateCompile(gl::ShCompilerInstance *compiler, std::string *infoLog) override;
std::string getDebugInfo() const override;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
index a67f97489f0..3ddbcb379d5 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.cpp
@@ -2245,7 +2245,7 @@ void StateManagerGL::syncTransformFeedbackState(const gl::Context *context)
TransformFeedbackGL *transformFeedbackGL =
GetImplAs<TransformFeedbackGL>(transformFeedback);
bindTransformFeedback(GL_TRANSFORM_FEEDBACK, transformFeedbackGL->getTransformFeedbackID());
- transformFeedbackGL->syncActiveState(transformFeedback->isActive(),
+ transformFeedbackGL->syncActiveState(context, transformFeedback->isActive(),
transformFeedback->getPrimitiveMode());
transformFeedbackGL->syncPausedState(transformFeedback->isPaused());
mCurrentTransformFeedback = transformFeedbackGL;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h
index b40bea8c1f2..41c903e0895 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/StateManagerGL.h
@@ -173,6 +173,7 @@ class StateManagerGL final : angle::NonCopyable
}
}
+ GLuint getProgramID() const { return mProgram; }
GLuint getVertexArrayID() const { return mVAO; }
GLuint getFramebufferID(angle::FramebufferBinding binding) const
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
index fbddad97225..8255ffb3396 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.cpp
@@ -9,10 +9,14 @@
#include "libANGLE/renderer/gl/TransformFeedbackGL.h"
#include "common/debug.h"
+#include "libANGLE/Context.h"
#include "libANGLE/State.h"
#include "libANGLE/renderer/gl/BufferGL.h"
#include "libANGLE/renderer/gl/FunctionsGL.h"
+#include "libANGLE/renderer/gl/ProgramGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h"
+#include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/gl/renderergl_utils.h"
namespace rx
{
@@ -25,7 +29,8 @@ TransformFeedbackGL::TransformFeedbackGL(const gl::TransformFeedbackState &state
mStateManager(stateManager),
mTransformFeedbackID(0),
mIsActive(false),
- mIsPaused(false)
+ mIsPaused(false),
+ mActiveProgram(0)
{
mFunctions->genTransformFeedbacks(1, &mTransformFeedbackID);
}
@@ -48,7 +53,7 @@ angle::Result TransformFeedbackGL::end(const gl::Context *context)
mStateManager->onTransformFeedbackStateChange();
// Immediately end the transform feedback so that the results are visible.
- syncActiveState(false, gl::PrimitiveMode::InvalidEnum);
+ syncActiveState(context, false, gl::PrimitiveMode::InvalidEnum);
return angle::Result::Continue;
}
@@ -107,7 +112,9 @@ GLuint TransformFeedbackGL::getTransformFeedbackID() const
return mTransformFeedbackID;
}
-void TransformFeedbackGL::syncActiveState(bool active, gl::PrimitiveMode primitiveMode) const
+void TransformFeedbackGL::syncActiveState(const gl::Context *context,
+ bool active,
+ gl::PrimitiveMode primitiveMode) const
{
if (mIsActive != active)
{
@@ -118,11 +125,20 @@ void TransformFeedbackGL::syncActiveState(bool active, gl::PrimitiveMode primiti
if (mIsActive)
{
ASSERT(primitiveMode != gl::PrimitiveMode::InvalidEnum);
+ mActiveProgram = GetImplAs<ProgramGL>(mState.getBoundProgram())->getProgramID();
+ mStateManager->useProgram(mActiveProgram);
mFunctions->beginTransformFeedback(gl::ToGLenum(primitiveMode));
}
else
{
+ // Implementations disagree about what should happen if a different program is bound
+ // when calling EndTransformFeedback. We avoid the ambiguity by always re-binding the
+ // program associated with this transform feedback.
+ GLuint previousProgram = mStateManager->getProgramID();
+ mStateManager->useProgram(mActiveProgram);
mFunctions->endTransformFeedback();
+ // Restore the current program if we changed it.
+ mStateManager->useProgram(previousProgram);
}
}
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
index 41f3296958e..421fd3fac26 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/TransformFeedbackGL.h
@@ -38,7 +38,9 @@ class TransformFeedbackGL : public TransformFeedbackImpl
GLuint getTransformFeedbackID() const;
- void syncActiveState(bool active, gl::PrimitiveMode primitiveMode) const;
+ void syncActiveState(const gl::Context *context,
+ bool active,
+ gl::PrimitiveMode primitiveMode) const;
void syncPausedState(bool paused) const;
private:
@@ -49,6 +51,7 @@ class TransformFeedbackGL : public TransformFeedbackImpl
mutable bool mIsActive;
mutable bool mIsPaused;
+ mutable GLuint mActiveProgram;
};
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
index 1479b59b66c..dc8264fab94 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/VertexArrayGL.cpp
@@ -98,7 +98,7 @@ void VertexArrayGL::destroy(const gl::Context *context)
mAppliedElementArrayBuffer.set(context, nullptr);
for (auto &binding : mAppliedBindings)
{
- binding.setBuffer(context, nullptr, false);
+ binding.setBuffer(context, nullptr);
}
}
@@ -435,7 +435,7 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri
{
// Mark the applied binding isn't using a buffer by setting its buffer to nullptr so that if
// it starts to use a buffer later, there is no chance that the caching will skip it.
- mAppliedBindings[attribIndex].setBuffer(context, nullptr, false);
+ mAppliedBindings[attribIndex].setBuffer(context, nullptr);
return;
}
@@ -474,7 +474,7 @@ void VertexArrayGL::updateAttribPointer(const gl::Context *context, size_t attri
mAppliedBindings[attribIndex].setStride(binding.getStride());
mAppliedBindings[attribIndex].setOffset(binding.getOffset());
- mAppliedBindings[attribIndex].setBuffer(context, binding.getBuffer().get(), false);
+ mAppliedBindings[attribIndex].setBuffer(context, binding.getBuffer().get());
}
void VertexArrayGL::callVertexAttribPointer(GLuint attribIndex,
@@ -569,7 +569,7 @@ void VertexArrayGL::updateBindingBuffer(const gl::Context *context, size_t bindi
mAppliedBindings[bindingIndex].setStride(binding.getStride());
mAppliedBindings[bindingIndex].setOffset(binding.getOffset());
- mAppliedBindings[bindingIndex].setBuffer(context, binding.getBuffer().get(), false);
+ mAppliedBindings[bindingIndex].setBuffer(context, binding.getBuffer().get());
}
void VertexArrayGL::updateBindingDivisor(size_t bindingIndex)
@@ -690,9 +690,9 @@ angle::Result VertexArrayGL::syncState(const gl::Context *context,
case VertexArray::DIRTY_BIT_ELEMENT_ARRAY_BUFFER_DATA:
break;
- ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_ATTRIB_FUNC);
- ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_BINDING_FUNC);
- ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_BUFFER_DATA_FUNC);
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_ATTRIB_FUNC)
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_BINDING_FUNC)
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_DIRTY_BUFFER_DATA_FUNC)
default:
UNREACHABLE();
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp
index 7c88f65ad4a..ac03341c9b9 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp
@@ -145,11 +145,14 @@ FunctionsEGL::~FunctionsEGL()
egl::Error FunctionsEGL::initialize(EGLNativeDisplayType nativeDisplay)
{
-#define ANGLE_GET_PROC_OR_ERROR(MEMBER, NAME) \
- if (!SetPtr(MEMBER, getProcAddress(#NAME))) \
- { \
- return egl::EglNotInitialized() << "Could not load EGL entry point " #NAME; \
- }
+#define ANGLE_GET_PROC_OR_ERROR(MEMBER, NAME) \
+ do \
+ { \
+ if (!SetPtr(MEMBER, getProcAddress(#NAME))) \
+ { \
+ return egl::EglNotInitialized() << "Could not load EGL entry point " #NAME; \
+ } \
+ } while (0)
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->bindAPIPtr, eglBindAPI);
ANGLE_GET_PROC_OR_ERROR(&mFnPtrs->chooseConfigPtr, eglChooseConfig);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp
index 7abe559ae3d..a42b5eef33a 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp
@@ -8,63 +8,30 @@
#include "libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h"
-#include "libANGLE/renderer/gl/egl/android/android_util.h"
-
-// Taken from cutils/native_handle.h:
-// https://android.googlesource.com/platform/system/core/+/master/libcutils/include/cutils/native_handle.h
-typedef struct native_handle
-{
- int version; /* sizeof(native_handle_t) */
- int numFds; /* number of file-descriptors at &data[0] */
- int numInts; /* number of ints at &data[numFds] */
- int data[0]; /* numFds + numInts ints */
-} native_handle_t;
-
-// Taken from nativebase/nativebase.h
-// https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativebase/include/nativebase/nativebase.h
-typedef const native_handle_t *buffer_handle_t;
-
-typedef struct android_native_base_t
-{
- /* a magic value defined by the actual EGL native type */
- int magic;
- /* the sizeof() of the actual EGL native type */
- int version;
- void *reserved[4];
- /* reference-counting interface */
- void (*incRef)(struct android_native_base_t *base);
- void (*decRef)(struct android_native_base_t *base);
-} android_native_base_t;
-
-typedef struct ANativeWindowBuffer
-{
- struct android_native_base_t common;
- int width;
- int height;
- int stride;
- int format;
- int usage_deprecated;
- uintptr_t layerCount;
- void *reserved[1];
- const native_handle_t *handle;
- uint64_t usage;
- // we needed extra space for storing the 64-bits usage flags
- // the number of slots to use from reserved_proc depends on the
- // architecture.
- void *reserved_proc[8 - (sizeof(uint64_t) / sizeof(void *))];
-} ANativeWindowBuffer_t;
+#include "common/android_util.h"
namespace rx
{
NativeBufferImageSiblingAndroid::NativeBufferImageSiblingAndroid(EGLClientBuffer buffer)
- : mBuffer(static_cast<struct ANativeWindowBuffer *>(buffer))
+ : mBuffer(buffer), mFormat(GL_NONE)
{}
NativeBufferImageSiblingAndroid::~NativeBufferImageSiblingAndroid() {}
+egl::Error NativeBufferImageSiblingAndroid::initialize(const egl::Display *display)
+{
+ int pixelFormat = 0;
+ angle::android::GetANativeWindowBufferProperties(
+ angle::android::ClientBufferToANativeWindowBuffer(mBuffer), &mSize.width, &mSize.height,
+ &mSize.depth, &pixelFormat);
+ mFormat = gl::Format(angle::android::NativePixelFormatToGLInternalFormat(pixelFormat));
+
+ return egl::NoError();
+}
+
gl::Format NativeBufferImageSiblingAndroid::getFormat() const
{
- return gl::Format(android::NativePixelFormatToGLInternalFormat(mBuffer->format));
+ return mFormat;
}
bool NativeBufferImageSiblingAndroid::isRenderable(const gl::Context *context) const
@@ -79,7 +46,7 @@ bool NativeBufferImageSiblingAndroid::isTexturable(const gl::Context *context) c
gl::Extents NativeBufferImageSiblingAndroid::getSize() const
{
- return gl::Extents(mBuffer->width, mBuffer->height, 1);
+ return mSize;
}
size_t NativeBufferImageSiblingAndroid::getSamples() const
@@ -89,7 +56,7 @@ size_t NativeBufferImageSiblingAndroid::getSamples() const
EGLClientBuffer NativeBufferImageSiblingAndroid::getBuffer() const
{
- return static_cast<EGLClientBuffer>(mBuffer);
+ return mBuffer;
}
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h
index 20c8960b1d9..764a4886659 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h
@@ -12,8 +12,6 @@
#include "libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h"
-struct ANativeWindowBuffer;
-
namespace rx
{
@@ -23,6 +21,8 @@ class NativeBufferImageSiblingAndroid : public ExternalImageSiblingEGL
NativeBufferImageSiblingAndroid(EGLClientBuffer buffer);
virtual ~NativeBufferImageSiblingAndroid();
+ egl::Error initialize(const egl::Display *display) override;
+
// ExternalImageSiblingImpl interface
gl::Format getFormat() const override;
bool isRenderable(const gl::Context *context) const override;
@@ -34,7 +34,9 @@ class NativeBufferImageSiblingAndroid : public ExternalImageSiblingEGL
EGLClientBuffer getBuffer() const override;
private:
- struct ANativeWindowBuffer *mBuffer;
+ EGLClientBuffer mBuffer;
+ gl::Extents mSize;
+ gl::Format mFormat;
};
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/android_util.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/android_util.cpp
deleted file mode 100644
index 29b0af27ee4..00000000000
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/android_util.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-//
-// Copyright 2018 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.
-//
-
-// android_util.cpp: Utilities for the using the Android platform
-
-#include "libANGLE/renderer/gl/egl/android/android_util.h"
-
-namespace rx
-{
-
-namespace
-{
-
-// Taken from android/hardware_buffer.h
-// https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativewindow/include/android/hardware_buffer.h
-
-// AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM,
-// AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM formats were deprecated and re-added explicitly.
-
-// clang-format off
-/**
- * Buffer pixel formats.
- */
-enum {
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_R8G8B8A8_UNORM
- * OpenGL ES: GL_RGBA8
- */
- AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
- /**
- * 32 bits per pixel, 8 bits per channel format where alpha values are
- * ignored (always opaque).
- * Corresponding formats:
- * Vulkan: VK_FORMAT_R8G8B8A8_UNORM
- * OpenGL ES: GL_RGB8
- */
- AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_R8G8B8_UNORM
- * OpenGL ES: GL_RGB8
- */
- AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_R5G6B5_UNORM_PACK16
- * OpenGL ES: GL_RGB565
- */
- AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4,
- AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM = 5,
- AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM = 6,
- AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM = 7,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT
- * OpenGL ES: GL_RGBA16F
- */
- AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT = 0x16,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_A2B10G10R10_UNORM_PACK32
- * OpenGL ES: GL_RGB10_A2
- */
- AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b,
- /**
- * An opaque binary blob format that must have height 1, with width equal to
- * the buffer size in bytes.
- */
- AHARDWAREBUFFER_FORMAT_BLOB = 0x21,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_D16_UNORM
- * OpenGL ES: GL_DEPTH_COMPONENT16
- */
- AHARDWAREBUFFER_FORMAT_D16_UNORM = 0x30,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_X8_D24_UNORM_PACK32
- * OpenGL ES: GL_DEPTH_COMPONENT24
- */
- AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_D24_UNORM_S8_UINT
- * OpenGL ES: GL_DEPTH24_STENCIL8
- */
- AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT = 0x32,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_D32_SFLOAT
- * OpenGL ES: GL_DEPTH_COMPONENT32F
- */
- AHARDWAREBUFFER_FORMAT_D32_FLOAT = 0x33,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_D32_SFLOAT_S8_UINT
- * OpenGL ES: GL_DEPTH32F_STENCIL8
- */
- AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT = 0x34,
- /**
- * Corresponding formats:
- * Vulkan: VK_FORMAT_S8_UINT
- * OpenGL ES: GL_STENCIL_INDEX8
- */
- AHARDWAREBUFFER_FORMAT_S8_UINT = 0x35,
-};
-// clang-format on
-
-} // anonymous namespace
-
-namespace android
-{
-GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)
-{
- switch (pixelFormat)
- {
- case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
- return GL_RGBA8;
- case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
- return GL_RGB8;
- case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
- return GL_RGB8;
- case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
- return GL_RGB565;
- case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM:
- return GL_BGRA8_EXT;
- case AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM:
- return GL_RGBA4;
- case AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM:
- return GL_RGB5_A1;
- case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
- return GL_RGBA16F;
- case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
- return GL_RGB10_A2;
- case AHARDWAREBUFFER_FORMAT_BLOB:
- return GL_NONE;
- case AHARDWAREBUFFER_FORMAT_D16_UNORM:
- return GL_DEPTH_COMPONENT16;
- case AHARDWAREBUFFER_FORMAT_D24_UNORM:
- return GL_DEPTH_COMPONENT24;
- case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
- return GL_DEPTH24_STENCIL8;
- case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
- return GL_DEPTH_COMPONENT32F;
- case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
- return GL_DEPTH32F_STENCIL8;
- case AHARDWAREBUFFER_FORMAT_S8_UINT:
- return GL_STENCIL_INDEX8;
- default:
- return GL_NONE;
- }
-}
-} // namespace android
-} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/android_util.h b/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/android_util.h
deleted file mode 100644
index e1ac8782e44..00000000000
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/egl/android/android_util.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright 2018 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.
-//
-
-// android_util.h: Utilities for the using the Android platform
-
-#ifndef LIBANGLE_RENDERER_GL_EGL_ANDROID_ANDROID_UTIL_H_
-#define LIBANGLE_RENDERER_GL_EGL_ANDROID_ANDROID_UTIL_H_
-
-#include "angle_gl.h"
-
-namespace rx
-{
-
-namespace android
-{
-GLenum NativePixelFormatToGLInternalFormat(int pixelFormat);
-}
-} // namespace rx
-
-#endif // LIBANGLE_RENDERER_GL_EGL_ANDROID_ANDROID_UTIL_H_ \ No newline at end of file
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
index bb9fb6a6169..1304622e9f0 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/glx/FunctionsGLX.cpp
@@ -150,16 +150,19 @@ bool FunctionsGLX::initialize(Display *xDisplay, int screen, std::string *errorS
getProc = reinterpret_cast<PFNGETPROCPROC>(glXGetProcAddress);
#endif
-#define GET_PROC_OR_ERROR(MEMBER, NAME) \
- if (!GetProc(getProc, MEMBER, #NAME)) \
- { \
- *errorString = "Could not load GLX entry point " #NAME; \
- return false; \
- }
+#define GET_PROC_OR_ERROR(MEMBER, NAME) \
+ do \
+ { \
+ if (!GetProc(getProc, MEMBER, #NAME)) \
+ { \
+ *errorString = "Could not load GLX entry point " #NAME; \
+ return false; \
+ } \
+ } while (0)
#if !defined(ANGLE_LINK_GLX)
# define GET_FNPTR_OR_ERROR(MEMBER, NAME) GET_PROC_OR_ERROR(MEMBER, NAME)
#else
-# define GET_FNPTR_OR_ERROR(MEMBER, NAME) *MEMBER = NAME;
+# define GET_FNPTR_OR_ERROR(MEMBER, NAME) *MEMBER = NAME
#endif
// GLX 1.0
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
index 81af439886e..c0d3bfa0761 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -1123,12 +1123,13 @@ void GenerateCaps(const FunctionsGL *functions,
functions->hasGLESExtension("GL_OES_texture_border_clamp") ||
functions->hasGLESExtension("GL_EXT_texture_border_clamp") ||
functions->hasGLESExtension("GL_NV_texture_border_clamp");
- extensions->instancedArrays = functions->isAtLeastGL(gl::Version(3, 1)) ||
- (functions->hasGLExtension("GL_ARB_instanced_arrays") &&
- (functions->hasGLExtension("GL_ARB_draw_instanced") ||
- functions->hasGLExtension("GL_EXT_draw_instanced"))) ||
- functions->isAtLeastGLES(gl::Version(3, 0)) ||
- functions->hasGLESExtension("GL_EXT_instanced_arrays");
+ extensions->instancedArraysANGLE = functions->isAtLeastGL(gl::Version(3, 1)) ||
+ (functions->hasGLExtension("GL_ARB_instanced_arrays") &&
+ (functions->hasGLExtension("GL_ARB_draw_instanced") ||
+ functions->hasGLExtension("GL_EXT_draw_instanced"))) ||
+ functions->isAtLeastGLES(gl::Version(3, 0)) ||
+ functions->hasGLESExtension("GL_EXT_instanced_arrays");
+ extensions->instancedArraysEXT = extensions->instancedArraysANGLE;
extensions->unpackSubimage = functions->standard == STANDARD_GL_DESKTOP ||
functions->isAtLeastGLES(gl::Version(3, 0)) ||
functions->hasGLESExtension("GL_EXT_unpack_subimage");
@@ -1344,6 +1345,11 @@ void GenerateCaps(const FunctionsGL *functions,
extensions->maxDualSourceDrawBuffers = 1;
}
+ // EXT_float_blend
+ // Assume all desktop driver supports this by default.
+ extensions->floatBlend = functions->standard == STANDARD_GL_DESKTOP ||
+ functions->hasGLESExtension("GL_EXT_float_blend");
+
// GL_CHROMIUM_compressed_texture_etc
// Expose this extension only when we support the formats or we're running on top of a native
// ES driver.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
index 5baa08a6a03..2a413878a5f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/gl/wgl/DisplayWGL.cpp
@@ -282,7 +282,7 @@ egl::Error DisplayWGL::initializeImpl(egl::Display *display)
mHasRobustness = functionsGL->getGraphicsResetStatus != nullptr;
if (mHasWGLCreateContextRobustness != mHasRobustness)
{
- WARN() << "WGL_ARB_create_context_robustness exists but unable to OpenGL context with "
+ WARN() << "WGL_ARB_create_context_robustness exists but unable to create a context with "
"robustness.";
}
@@ -885,7 +885,7 @@ HGLRC DisplayWGL::createContextAttribs(const gl::Version &version,
egl::Error DisplayWGL::createRenderer(std::shared_ptr<RendererWGL> *outRenderer)
{
- HGLRC context = nullptr;
+ HGLRC context = nullptr;
HGLRC sharedContext = nullptr;
std::vector<int> workerContextAttribs;
@@ -1006,19 +1006,22 @@ WorkerContext *DisplayWGL::createWorkerContext(std::string *infoLog,
HDC workerDeviceContext = nullptr;
HGLRC workerContext = nullptr;
-#define CLEANUP_ON_ERROR() \
- if (workerContext) \
- { \
- mFunctionsWGL->deleteContext(workerContext); \
- } \
- if (workerDeviceContext) \
- { \
- mFunctionsWGL->releasePbufferDCARB(workerPbuffer, workerDeviceContext); \
- } \
- if (workerPbuffer) \
- { \
- mFunctionsWGL->destroyPbufferARB(workerPbuffer); \
- }
+#define CLEANUP_ON_ERROR() \
+ do \
+ { \
+ if (workerContext) \
+ { \
+ mFunctionsWGL->deleteContext(workerContext); \
+ } \
+ if (workerDeviceContext) \
+ { \
+ mFunctionsWGL->releasePbufferDCARB(workerPbuffer, workerDeviceContext); \
+ } \
+ if (workerPbuffer) \
+ { \
+ mFunctionsWGL->destroyPbufferARB(workerPbuffer); \
+ } \
+ } while (0)
const int attribs[] = {0, 0};
workerPbuffer = mFunctionsWGL->createPbufferARB(mDeviceContext, mPixelFormat, 1, 1, attribs);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.cpp
index 3460b89e521..86fd9c5391b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.cpp
@@ -68,7 +68,8 @@ ContextNULL::ContextNULL(const gl::State &state,
mExtensions = gl::Extensions();
mExtensions.fence = true;
- mExtensions.instancedArrays = true;
+ mExtensions.instancedArraysANGLE = true;
+ mExtensions.instancedArraysEXT = true;
mExtensions.pixelBufferObject = true;
mExtensions.mapBuffer = true;
mExtensions.mapBufferRange = true;
@@ -265,7 +266,7 @@ void ContextNULL::pushGroupMarker(GLsizei length, const char *marker) {}
void ContextNULL::popGroupMarker() {}
-void ContextNULL::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) {}
+void ContextNULL::pushDebugGroup(GLenum source, GLuint id, const std::string &message) {}
void ContextNULL::popDebugGroup() {}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.h b/chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.h
index a369e4c7b00..0d963ea5ab4 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/null/ContextNULL.h
@@ -140,7 +140,7 @@ class ContextNULL : public ContextImpl
void popGroupMarker() override;
// KHR_debug
- void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
+ void pushDebugGroup(GLenum source, GLuint id, const std::string &message) override;
void popDebugGroup() override;
// State sync with dirty bits.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.cpp b/chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.cpp
index f9884e83139..77b2e1e8427 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.cpp
@@ -18,11 +18,11 @@ ProgramNULL::ProgramNULL(const gl::ProgramState &state) : ProgramImpl(state) {}
ProgramNULL::~ProgramNULL() {}
-angle::Result ProgramNULL::load(const gl::Context *context,
- gl::InfoLog &infoLog,
- gl::BinaryInputStream *stream)
+std::unique_ptr<LinkEvent> ProgramNULL::load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
{
- return angle::Result::Continue;
+ return std::make_unique<LinkEventDone>(angle::Result::Continue);
}
void ProgramNULL::save(const gl::Context *context, gl::BinaryOutputStream *stream) {}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.h b/chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.h
index 6b3c974542a..8260577dfbc 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/null/ProgramNULL.h
@@ -21,9 +21,9 @@ class ProgramNULL : public ProgramImpl
ProgramNULL(const gl::ProgramState &state);
~ProgramNULL() override;
- angle::Result load(const gl::Context *context,
- gl::InfoLog &infoLog,
- gl::BinaryInputStream *stream) override;
+ std::unique_ptr<LinkEvent> load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog) override;
void save(const gl::Context *context, gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
void setSeparable(bool separable) override;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/renderer_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/renderer_utils.cpp
index ed4b629caea..4cbc899e4d6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/renderer_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/renderer_utils.cpp
@@ -577,7 +577,7 @@ angle::Result ComputeStartVertex(ContextImpl *contextImpl,
// unsigned integers(with wrapping on overflow conditions)." ANGLE does not fully handle
// these rules, an overflow error is returned if the start vertex cannot be stored in a
// 32-bit signed integer.
- ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 <= std::numeric_limits<GLint>::max())
+ ANGLE_CHECK_GL_MATH(contextImpl, startVertexInt64 <= std::numeric_limits<GLint>::max());
*firstVertexOut = static_cast<GLint>(startVertexInt64);
return angle::Result::Continue;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp
index 4ef782b9f8d..3d0389e519f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/BufferVk.cpp
@@ -14,6 +14,7 @@
#include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "third_party/trace_event/trace_event.h"
namespace rx
{
@@ -176,6 +177,7 @@ angle::Result BufferVk::getIndexRange(const gl::Context *context,
return angle::Result::Continue;
}
+ TRACE_EVENT0("gpu.angle", "BufferVk::getIndexRange");
// Needed before reading buffer or we could get stale data.
ANGLE_TRY(renderer->finish(contextVk));
@@ -246,8 +248,7 @@ angle::Result BufferVk::copyToBuffer(ContextVk *contextVk,
{
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(mBuffer.recordCommands(contextVk, &commandBuffer));
- commandBuffer->copyBuffer(mBuffer.getBuffer().getHandle(), destBuffer->getBuffer().getHandle(),
- copyCount, copies);
+ commandBuffer->copyBuffer(mBuffer.getBuffer(), destBuffer->getBuffer(), copyCount, copies);
destBuffer->onRead(&mBuffer, VK_ACCESS_TRANSFER_READ_BIT);
mBuffer.onWrite(VK_ACCESS_TRANSFER_WRITE_BIT);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.cpp
index adce3e330c5..5f6892b3d41 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.cpp
@@ -74,11 +74,56 @@ const char *GetResourceTypeName(CommandGraphResourceType resourceType,
UNREACHABLE();
return "Query";
}
+ case CommandGraphResourceType::FenceSync:
+ switch (function)
+ {
+ case CommandGraphNodeFunction::SetFenceSync:
+ return "SetFenceSync";
+ case CommandGraphNodeFunction::WaitFenceSync:
+ return "WaitFenceSync";
+ default:
+ UNREACHABLE();
+ return "FenceSync";
+ }
+ case CommandGraphResourceType::DebugMarker:
+ switch (function)
+ {
+ case CommandGraphNodeFunction::InsertDebugMarker:
+ return "InsertDebugMarker";
+ case CommandGraphNodeFunction::PushDebugMarker:
+ return "PushDebugMarker";
+ case CommandGraphNodeFunction::PopDebugMarker:
+ return "PopDebugMarker";
+ default:
+ UNREACHABLE();
+ return "DebugMarker";
+ }
default:
UNREACHABLE();
return "";
}
}
+
+void MakeDebugUtilsLabel(GLenum source, const char *marker, VkDebugUtilsLabelEXT *label)
+{
+ static constexpr angle::ColorF kLabelColors[6] = {
+ angle::ColorF(1.0f, 0.5f, 0.5f, 1.0f), // DEBUG_SOURCE_API
+ angle::ColorF(0.5f, 1.0f, 0.5f, 1.0f), // DEBUG_SOURCE_WINDOW_SYSTEM
+ angle::ColorF(0.5f, 0.5f, 1.0f, 1.0f), // DEBUG_SOURCE_SHADER_COMPILER
+ angle::ColorF(0.7f, 0.7f, 0.7f, 1.0f), // DEBUG_SOURCE_THIRD_PARTY
+ angle::ColorF(0.5f, 0.8f, 0.9f, 1.0f), // DEBUG_SOURCE_APPLICATION
+ angle::ColorF(0.9f, 0.8f, 0.5f, 1.0f), // DEBUG_SOURCE_OTHER
+ };
+
+ int colorIndex = source - GL_DEBUG_SOURCE_API;
+ ASSERT(colorIndex >= 0 && static_cast<size_t>(colorIndex) < ArraySize(kLabelColors));
+
+ label->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ label->pNext = nullptr;
+ label->pLabelName = marker;
+ kLabelColors[colorIndex].writeData(label->color);
+}
+
} // anonymous namespace
// CommandGraphResource implementation.
@@ -211,6 +256,7 @@ CommandGraphNode::CommandGraphNode(CommandGraphNodeFunction function)
mFunction(function),
mQueryPool(VK_NULL_HANDLE),
mQueryIndex(0),
+ mFenceSyncEvent(VK_NULL_HANDLE),
mHasChildren(false),
mVisitedState(VisitedState::Unvisited),
mGlobalMemoryBarrierSrcAccess(0),
@@ -337,6 +383,21 @@ void CommandGraphNode::setQueryPool(const QueryPool *queryPool, uint32_t queryIn
mQueryIndex = queryIndex;
}
+void CommandGraphNode::setFenceSync(const vk::Event &event)
+{
+ ASSERT(mFunction == CommandGraphNodeFunction::SetFenceSync ||
+ mFunction == CommandGraphNodeFunction::WaitFenceSync);
+ mFenceSyncEvent = event.getHandle();
+}
+
+void CommandGraphNode::setDebugMarker(GLenum source, std::string &&marker)
+{
+ ASSERT(mFunction == CommandGraphNodeFunction::InsertDebugMarker ||
+ mFunction == CommandGraphNodeFunction::PushDebugMarker);
+ mDebugMarkerSource = source;
+ mDebugMarker = std::move(marker);
+}
+
// Do not call this in anything but testing code, since it's slow.
bool CommandGraphNode::isChildOf(CommandGraphNode *parent)
{
@@ -381,7 +442,7 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
switch (mFunction)
{
case CommandGraphNodeFunction::Generic:
- ASSERT(mQueryPool == VK_NULL_HANDLE);
+ ASSERT(mQueryPool == VK_NULL_HANDLE && mFenceSyncEvent == VK_NULL_HANDLE);
// Record the deferred pipeline barrier if necessary.
ASSERT((mGlobalMemoryBarrierDstAccess == 0) == (mGlobalMemoryBarrierSrcAccess == 0));
@@ -461,6 +522,58 @@ angle::Result CommandGraphNode::visitAndExecute(vk::Context *context,
break;
+ case CommandGraphNodeFunction::SetFenceSync:
+ ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
+ ASSERT(mFenceSyncEvent != VK_NULL_HANDLE);
+
+ primaryCommandBuffer->setEvent(mFenceSyncEvent, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
+
+ break;
+
+ case CommandGraphNodeFunction::WaitFenceSync:
+ ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
+ ASSERT(mFenceSyncEvent != VK_NULL_HANDLE);
+
+ // Fence Syncs are purely execution barriers, so there are no memory barriers attached.
+ primaryCommandBuffer->waitEvents(
+ 1, &mFenceSyncEvent, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, nullptr, 0, nullptr, 0, nullptr);
+
+ break;
+
+ case CommandGraphNodeFunction::InsertDebugMarker:
+ ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
+
+ if (vkCmdInsertDebugUtilsLabelEXT)
+ {
+ VkDebugUtilsLabelEXT label;
+ MakeDebugUtilsLabel(mDebugMarkerSource, mDebugMarker.c_str(), &label);
+
+ vkCmdInsertDebugUtilsLabelEXT(primaryCommandBuffer->getHandle(), &label);
+ }
+ break;
+
+ case CommandGraphNodeFunction::PushDebugMarker:
+ ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
+
+ if (vkCmdBeginDebugUtilsLabelEXT)
+ {
+ VkDebugUtilsLabelEXT label;
+ MakeDebugUtilsLabel(mDebugMarkerSource, mDebugMarker.c_str(), &label);
+
+ vkCmdBeginDebugUtilsLabelEXT(primaryCommandBuffer->getHandle(), &label);
+ }
+ break;
+
+ case CommandGraphNodeFunction::PopDebugMarker:
+ ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
+
+ if (vkCmdEndDebugUtilsLabelEXT)
+ {
+ vkCmdEndDebugUtilsLabelEXT(primaryCommandBuffer->getHandle());
+ }
+ break;
+
default:
UNREACHABLE();
}
@@ -660,6 +773,40 @@ void CommandGraph::writeTimestamp(const QueryPool *queryPool, uint32_t queryInde
newNode->setQueryPool(queryPool, queryIndex);
}
+void CommandGraph::setFenceSync(const vk::Event &event)
+{
+ CommandGraphNode *newNode = allocateBarrierNode(CommandGraphResourceType::FenceSync,
+ CommandGraphNodeFunction::SetFenceSync);
+ newNode->setFenceSync(event);
+}
+
+void CommandGraph::waitFenceSync(const vk::Event &event)
+{
+ CommandGraphNode *newNode = allocateBarrierNode(CommandGraphResourceType::FenceSync,
+ CommandGraphNodeFunction::WaitFenceSync);
+ newNode->setFenceSync(event);
+}
+
+void CommandGraph::insertDebugMarker(GLenum source, std::string &&marker)
+{
+ CommandGraphNode *newNode = allocateBarrierNode(CommandGraphResourceType::DebugMarker,
+ CommandGraphNodeFunction::InsertDebugMarker);
+ newNode->setDebugMarker(source, std::move(marker));
+}
+
+void CommandGraph::pushDebugMarker(GLenum source, std::string &&marker)
+{
+ CommandGraphNode *newNode = allocateBarrierNode(CommandGraphResourceType::DebugMarker,
+ CommandGraphNodeFunction::PushDebugMarker);
+ newNode->setDebugMarker(source, std::move(marker));
+}
+
+void CommandGraph::popDebugMarker()
+{
+ allocateBarrierNode(CommandGraphResourceType::DebugMarker,
+ CommandGraphNodeFunction::PopDebugMarker);
+}
+
// Dumps the command graph into a dot file that works with graphviz.
void CommandGraph::dumpGraphDotFile(std::ostream &out) const
{
@@ -687,38 +834,53 @@ void CommandGraph::dumpGraphDotFile(std::ostream &out) const
std::stringstream strstr;
strstr << GetResourceTypeName(node->getResourceTypeForDiagnostics(), node->getFunction());
- strstr << " ";
- auto it = objectIDMap.find(node->getResourceIDForDiagnostics());
- if (it != objectIDMap.end())
+ if (node->getResourceTypeForDiagnostics() == CommandGraphResourceType::DebugMarker)
{
- strstr << it->second;
+ // For debug markers, use the string from the debug marker itself.
+ if (node->getFunction() != CommandGraphNodeFunction::PopDebugMarker)
+ {
+ strstr << " " << node->getDebugMarker();
+ }
}
else
{
- int id = 0;
+ strstr << " ";
- switch (node->getResourceTypeForDiagnostics())
+ // Otherwise assign each object an ID, so all the nodes of the same object have the same
+ // label.
+ ASSERT(node->getResourceIDForDiagnostics() != 0);
+ auto it = objectIDMap.find(node->getResourceIDForDiagnostics());
+ if (it != objectIDMap.end())
{
- case CommandGraphResourceType::Buffer:
- id = bufferIDCounter++;
- break;
- case CommandGraphResourceType::Framebuffer:
- id = framebufferIDCounter++;
- break;
- case CommandGraphResourceType::Image:
- id = imageIDCounter++;
- break;
- case CommandGraphResourceType::Query:
- id = queryIDCounter++;
- break;
- default:
- UNREACHABLE();
- break;
+ strstr << it->second;
+ }
+ else
+ {
+ int id = 0;
+
+ switch (node->getResourceTypeForDiagnostics())
+ {
+ case CommandGraphResourceType::Buffer:
+ id = bufferIDCounter++;
+ break;
+ case CommandGraphResourceType::Framebuffer:
+ id = framebufferIDCounter++;
+ break;
+ case CommandGraphResourceType::Image:
+ id = imageIDCounter++;
+ break;
+ case CommandGraphResourceType::Query:
+ id = queryIDCounter++;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ objectIDMap[node->getResourceIDForDiagnostics()] = id;
+ strstr << id;
}
-
- objectIDMap[node->getResourceIDForDiagnostics()] = id;
- strstr << id;
}
const std::string &label = strstr.str();
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.h
index 1314da57ac1..adf199335f2 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/CommandGraph.h
@@ -30,6 +30,8 @@ enum class CommandGraphResourceType
Framebuffer,
Image,
Query,
+ FenceSync,
+ DebugMarker,
};
// Certain functionality cannot be put in secondary command buffers, so they are special-cased in
@@ -40,6 +42,11 @@ enum class CommandGraphNodeFunction
BeginQuery,
EndQuery,
WriteTimestamp,
+ SetFenceSync,
+ WaitFenceSync,
+ InsertDebugMarker,
+ PushDebugMarker,
+ PopDebugMarker,
};
// Receives notifications when a command buffer is no longer able to record. Can be used with
@@ -127,6 +134,9 @@ class CommandGraphNode final : angle::NonCopyable
CommandGraphNodeFunction getFunction() const { return mFunction; }
void setQueryPool(const QueryPool *queryPool, uint32_t queryIndex);
+ void setFenceSync(const vk::Event &event);
+ void setDebugMarker(GLenum source, std::string &&marker);
+ const std::string &getDebugMarker() const { return mDebugMarker; }
ANGLE_INLINE void addGlobalMemoryBarrier(VkFlags srcAccess, VkFlags dstAccess)
{
@@ -168,8 +178,14 @@ class CommandGraphNode final : angle::NonCopyable
CommandBuffer mInsideRenderPassCommands;
// Special-function additional data:
+ // Queries:
VkQueryPool mQueryPool;
uint32_t mQueryIndex;
+ // GLsync and EGLSync:
+ VkEvent mFenceSyncEvent;
+ // Debug markers:
+ GLenum mDebugMarkerSource;
+ std::string mDebugMarker;
// Parents are commands that must be submitted before 'this' CommandNode can be submitted.
std::vector<CommandGraphNode *> mParents;
@@ -359,6 +375,13 @@ class CommandGraph final : angle::NonCopyable
void beginQuery(const QueryPool *queryPool, uint32_t queryIndex);
void endQuery(const QueryPool *queryPool, uint32_t queryIndex);
void writeTimestamp(const QueryPool *queryPool, uint32_t queryIndex);
+ // GLsync and EGLSync:
+ void setFenceSync(const vk::Event &event);
+ void waitFenceSync(const vk::Event &event);
+ // Debug markers:
+ void insertDebugMarker(GLenum source, std::string &&marker);
+ void pushDebugMarker(GLenum source, std::string &&marker);
+ void popDebugMarker();
private:
CommandGraphNode *allocateBarrierNode(CommandGraphResourceType resourceType,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp
index 9af3932d71b..c2ab5fb003c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.cpp
@@ -199,6 +199,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
gl::PrimitiveMode mode,
GLint firstVertex,
GLsizei vertexOrIndexCount,
+ GLsizei instanceCount,
gl::DrawElementsType indexTypeOrNone,
const void *indices,
DirtyBits dirtyBitMask,
@@ -216,7 +217,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
if (context->getStateCache().hasAnyActiveClientAttrib())
{
ANGLE_TRY(mVertexArray->updateClientAttribs(context, firstVertex, vertexOrIndexCount,
- indexTypeOrNone, indices));
+ instanceCount, indexTypeOrNone, indices));
mDirtyBits.set(DIRTY_BIT_VERTEX_BUFFERS);
}
@@ -226,11 +227,11 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
// TODO(jmadill): Use dirty bit. http://anglebug.com/3014
if (!mCommandBuffer)
{
+ mDirtyBits |= mNewCommandBufferDirtyBits;
if (!mDrawFramebuffer->appendToStartedRenderPass(mRenderer->getCurrentQueueSerial(),
&mCommandBuffer))
{
ANGLE_TRY(mDrawFramebuffer->startNewRenderPass(this, &mCommandBuffer));
- mDirtyBits |= mNewCommandBufferDirtyBits;
}
}
@@ -266,6 +267,7 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
gl::PrimitiveMode mode,
GLsizei indexCount,
+ GLsizei instanceCount,
gl::DrawElementsType indexType,
const void *indices,
vk::CommandBuffer **commandBufferOut)
@@ -297,8 +299,8 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
}
}
- return setupDraw(context, mode, 0, indexCount, indexType, indices, mIndexedDirtyBitsMask,
- commandBufferOut);
+ return setupDraw(context, mode, 0, indexCount, instanceCount, indexType, indices,
+ mIndexedDirtyBitsMask, commandBufferOut);
}
angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
@@ -315,7 +317,7 @@ angle::Result ContextVk::setupLineLoopDraw(const gl::Context *context,
mCurrentDrawElementsType = indexTypeOrInvalid != gl::DrawElementsType::InvalidEnum
? indexTypeOrInvalid
: gl::DrawElementsType::UnsignedInt;
- return setupDraw(context, mode, firstVertex, vertexOrIndexCount, indexTypeOrInvalid, indices,
+ return setupDraw(context, mode, firstVertex, vertexOrIndexCount, 1, indexTypeOrInvalid, indices,
mIndexedDirtyBitsMask, commandBufferOut);
}
@@ -326,7 +328,7 @@ angle::Result ContextVk::handleDirtyDefaultAttribs(const gl::Context *context,
for (size_t attribIndex : mDirtyDefaultAttribsMask)
{
- ANGLE_TRY(updateDefaultAttribute(attribIndex))
+ ANGLE_TRY(updateDefaultAttribute(attribIndex));
}
mDirtyDefaultAttribsMask.reset();
@@ -455,8 +457,8 @@ angle::Result ContextVk::drawArrays(const gl::Context *context,
}
else
{
- ANGLE_TRY(setupDraw(context, mode, first, count, gl::DrawElementsType::InvalidEnum, nullptr,
- mNonIndexedDirtyBitsMask, &commandBuffer));
+ ANGLE_TRY(setupDraw(context, mode, first, count, 1, gl::DrawElementsType::InvalidEnum,
+ nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->draw(clampedVertexCount, 1, first, 0);
}
@@ -467,10 +469,20 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
gl::PrimitiveMode mode,
GLint first,
GLsizei count,
- GLsizei instanceCount)
+ GLsizei instances)
{
- ANGLE_VK_UNREACHABLE(this);
- return angle::Result::Stop;
+ if (mode == gl::PrimitiveMode::LineLoop)
+ {
+ // TODO - http://anglebug.com/2672
+ ANGLE_VK_UNREACHABLE(this);
+ return angle::Result::Stop;
+ }
+
+ vk::CommandBuffer *commandBuffer = nullptr;
+ ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
+ nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
+ commandBuffer->draw(gl::GetClampedVertexCount<uint32_t>(count), instances, first, 0);
+ return angle::Result::Continue;
}
angle::Result ContextVk::drawElements(const gl::Context *context,
@@ -487,7 +499,7 @@ angle::Result ContextVk::drawElements(const gl::Context *context,
}
else
{
- ANGLE_TRY(setupIndexedDraw(context, mode, count, type, indices, &commandBuffer));
+ ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
commandBuffer->drawIndexed(count, 1, 0, 0, 0);
}
@@ -501,8 +513,17 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
const void *indices,
GLsizei instances)
{
- ANGLE_VK_UNREACHABLE(this);
- return angle::Result::Stop;
+ if (mode == gl::PrimitiveMode::LineLoop)
+ {
+ // TODO - http://anglebug.com/2672
+ ANGLE_VK_UNREACHABLE(this);
+ return angle::Result::Stop;
+ }
+
+ vk::CommandBuffer *commandBuffer = nullptr;
+ ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer));
+ commandBuffer->drawIndexed(count, instances, 0, 0, 0);
+ return angle::Result::Continue;
}
angle::Result ContextVk::drawRangeElements(const gl::Context *context,
@@ -565,27 +586,31 @@ std::string ContextVk::getRendererDescription() const
void ContextVk::insertEventMarker(GLsizei length, const char *marker)
{
- // TODO: Forward this to a Vulkan debug marker. http://anglebug.com/2853
+ std::string markerStr(marker, length <= 0 ? strlen(marker) : length);
+ mRenderer->insertDebugMarker(GL_DEBUG_SOURCE_APPLICATION, static_cast<GLuint>(-1),
+ std::move(markerStr));
}
void ContextVk::pushGroupMarker(GLsizei length, const char *marker)
{
- // TODO: Forward this to a Vulkan debug marker. http://anglebug.com/2853
+ std::string markerStr(marker, length <= 0 ? strlen(marker) : length);
+ mRenderer->pushDebugMarker(GL_DEBUG_SOURCE_APPLICATION, static_cast<GLuint>(-1),
+ std::move(markerStr));
}
void ContextVk::popGroupMarker()
{
- // TODO: Forward this to a Vulkan debug marker. http://anglebug.com/2853
+ mRenderer->popDebugMarker();
}
-void ContextVk::pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message)
+void ContextVk::pushDebugGroup(GLenum source, GLuint id, const std::string &message)
{
- // TODO: Forward this to a Vulkan debug marker. http://anglebug.com/2853
+ mRenderer->pushDebugMarker(source, id, std::string(message));
}
void ContextVk::popDebugGroup()
{
- // TODO: Forward this to a Vulkan debug marker. http://anglebug.com/2853
+ mRenderer->popDebugMarker();
}
bool ContextVk::isViewportFlipEnabledForDrawFBO() const
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.h
index b4eaa3033d2..09d651ffc4b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ContextVk.h
@@ -61,7 +61,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff
GLsizei count,
gl::DrawElementsType type,
const void *indices,
- GLsizei instances) override;
+ GLsizei instanceCount) override;
angle::Result drawRangeElements(const gl::Context *context,
gl::PrimitiveMode mode,
GLuint start,
@@ -90,7 +90,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff
void popGroupMarker() override;
// KHR_debug
- void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
+ void pushDebugGroup(GLenum source, GLuint id, const std::string &message) override;
void popDebugGroup() override;
bool isViewportFlipEnabledForDrawFBO() const;
@@ -232,6 +232,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff
gl::PrimitiveMode mode,
GLint firstVertex,
GLsizei vertexOrIndexCount,
+ GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices,
DirtyBits dirtyBitMask,
@@ -239,6 +240,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff
angle::Result setupIndexedDraw(const gl::Context *context,
gl::PrimitiveMode mode,
GLsizei indexCount,
+ GLsizei instanceCount,
gl::DrawElementsType indexType,
const void *indices,
vk::CommandBuffer **commandBufferOut);
@@ -342,7 +344,7 @@ class ContextVk : public ContextImpl, public vk::Context, public vk::CommandBuff
vk::DynamicBuffer mDriverUniformsBuffer;
VkDescriptorSet mDriverUniformsDescriptorSet;
vk::BindingPointer<vk::DescriptorSetLayout> mDriverUniformsSetLayout;
- vk::SharedDescriptorPoolBinding mDriverUniformsDescriptorPoolBinding;
+ vk::RefCountedDescriptorPoolBinding mDriverUniformsDescriptorPoolBinding;
// This cache should also probably include the texture index (shader location) and array
// index (also in the shader). This info is used in the descriptor update step.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp
index b134394404d..43bf3eedde4 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.cpp
@@ -13,8 +13,11 @@
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/ImageVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/SurfaceVk.h"
+#include "libANGLE/renderer/vulkan/SyncVk.h"
+#include "third_party/trace_event/trace_event.h"
namespace rx
{
@@ -31,7 +34,7 @@ DisplayVk::~DisplayVk()
egl::Error DisplayVk::initialize(egl::Display *display)
{
ASSERT(mRenderer != nullptr && display != nullptr);
- angle::Result result = mRenderer->initialize(this, display, getWSIName());
+ angle::Result result = mRenderer->initialize(this, display, getWSIExtension(), getWSILayer());
ANGLE_TRY(angle::ToEGL(result, this, EGL_NOT_INITIALIZED));
return egl::NoError();
}
@@ -80,10 +83,7 @@ DeviceImpl *DisplayVk::createDevice()
egl::Error DisplayVk::waitClient(const gl::Context *context)
{
- // TODO(jmadill): Call flush instead of finish once it is implemented in RendererVK.
- // http://anglebug.com/2504
- UNIMPLEMENTED();
-
+ TRACE_EVENT0("gpu.angle", "DisplayVk::waitClient");
return angle::ToEGL(mRenderer->finish(this), this, EGL_BAD_ACCESS);
}
@@ -136,8 +136,7 @@ ImageImpl *DisplayVk::createImage(const egl::ImageState &state,
EGLenum target,
const egl::AttributeMap &attribs)
{
- UNIMPLEMENTED();
- return static_cast<ImageImpl *>(0);
+ return new ImageVk(state, context);
}
rx::ContextImpl *DisplayVk::createContext(const gl::State &state,
@@ -157,6 +156,11 @@ StreamProducerImpl *DisplayVk::createStreamProducerD3DTexture(
return static_cast<StreamProducerImpl *>(0);
}
+EGLSyncImpl *DisplayVk::createSync(const egl::AttributeMap &attribs)
+{
+ return new EGLSyncVk(attribs);
+}
+
gl::Version DisplayVk::getMaxSupportedESVersion() const
{
return mRenderer->getMaxSupportedESVersion();
@@ -176,6 +180,18 @@ void DisplayVk::generateExtensions(egl::DisplayExtensions *outExtensions) const
// When the Vulkan driver supports VK_KHR_incremental_present, it will use it. Otherwise, it
// will ignore the hint and do a regular swap.
outExtensions->swapBuffersWithDamage = true;
+
+ outExtensions->fenceSync = true;
+ outExtensions->waitSync = true;
+
+ outExtensions->image = true;
+ outExtensions->imageBase = true;
+ outExtensions->imagePixmap = false; // ANGLE does not support pixmaps
+ outExtensions->glTexture2DImage = true;
+ outExtensions->glTextureCubemapImage = true;
+ outExtensions->glTexture3DImage = false;
+ outExtensions->glRenderbufferImage = true;
+ outExtensions->imageNativeBuffer = getRenderer()->getFeatures().supportsAndroidHardwareBuffer;
}
void DisplayVk::generateCaps(egl::Caps *outCaps) const
@@ -183,6 +199,11 @@ void DisplayVk::generateCaps(egl::Caps *outCaps) const
outCaps->textureNPOT = true;
}
+const char *DisplayVk::getWSILayer() const
+{
+ return nullptr;
+}
+
bool DisplayVk::getScratchBuffer(size_t requstedSizeBytes,
angle::MemoryBuffer **scratchBufferOut) const
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.h
index 618debdcdfb..fbdb7d78930 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/DisplayVk.h
@@ -67,9 +67,13 @@ class DisplayVk : public DisplayImpl, public vk::Context
StreamProducerImpl *createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,
const egl::AttributeMap &attribs) override;
+
+ EGLSyncImpl *createSync(const egl::AttributeMap &attribs) override;
+
gl::Version getMaxSupportedESVersion() const override;
- virtual const char *getWSIName() const = 0;
+ virtual const char *getWSIExtension() const = 0;
+ virtual const char *getWSILayer() const;
// Determine if a config with given formats and sample counts is supported. This callback may
// modify the config to add or remove platform specific attributes such as nativeVisualID before
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
index fc634645be6..b0af4745256 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
@@ -24,6 +24,7 @@
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/SurfaceVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
+#include "third_party/trace_event/trace_event.h"
namespace rx
{
@@ -296,10 +297,9 @@ angle::Result FramebufferVk::clear(const gl::Context *context, GLbitfield mask)
ASSERT(colorRenderTarget);
vk::ImageHelper *image = colorRenderTarget->getImageForWrite(&mFramebuffer);
- GLint mipLevelToClear = (attachment->type() == GL_TEXTURE) ? attachment->mipLevel() : 0;
// If we're clearing a cube map face ensure we only clear the selected layer.
- image->clearColorLayer(modifiedClearColorValue, mipLevelToClear, 1,
+ image->clearColorLayer(modifiedClearColorValue, colorRenderTarget->getLevelIndex(), 1,
colorRenderTarget->getLayerIndex(), 1, commandBuffer);
}
@@ -421,19 +421,30 @@ angle::Result FramebufferVk::blitWithCopy(ContextVk *contextVk,
bool blitDepthBuffer,
bool blitStencilBuffer)
{
- vk::ImageHelper *writeImage = drawRenderTarget->getImageForWrite(&mFramebuffer);
+ VkImageAspectFlags aspectMask =
+ vk::GetDepthStencilAspectFlagsForCopy(blitDepthBuffer, blitStencilBuffer);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(mFramebuffer.recordCommands(contextVk, &commandBuffer));
+ vk::ImageHelper *writeImage = drawRenderTarget->getImageForWrite(&mFramebuffer);
+ writeImage->changeLayout(writeImage->getAspectFlags(), vk::ImageLayout::TransferDst,
+ commandBuffer);
+
vk::ImageHelper *readImage = readRenderTarget->getImageForRead(
- &mFramebuffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, commandBuffer);
+ &mFramebuffer, vk::ImageLayout::TransferSrc, commandBuffer);
+
+ VkImageSubresourceLayers readSubresource = {};
+ readSubresource.aspectMask = aspectMask;
+ readSubresource.mipLevel = 0;
+ readSubresource.baseArrayLayer = 0;
+ readSubresource.layerCount = 1;
+
+ VkImageSubresourceLayers writeSubresource = readSubresource;
- VkImageAspectFlags aspectMask =
- vk::GetDepthStencilAspectFlagsForCopy(blitDepthBuffer, blitStencilBuffer);
vk::ImageHelper::Copy(readImage, writeImage, gl::Offset(), gl::Offset(),
- gl::Extents(copyArea.width, copyArea.height, 1), aspectMask,
- commandBuffer);
+ gl::Extents(copyArea.width, copyArea.height, 1), readSubresource,
+ writeSubresource, commandBuffer);
return angle::Result::Continue;
}
@@ -505,9 +516,8 @@ angle::Result FramebufferVk::blitWithReadback(ContextVk *contextVk,
// destination target.
vk::ImageHelper *imageForWrite = drawRenderTarget->getImageForWrite(&mFramebuffer);
- imageForWrite->changeLayoutWithStages(
- imageForWrite->getAspectFlags(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer);
+ imageForWrite->changeLayout(imageForWrite->getAspectFlags(), vk::ImageLayout::TransferDst,
+ commandBuffer);
commandBuffer->copyBufferToImage(destBufferHandle, imageForWrite->getImage(),
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copyRegion);
@@ -667,7 +677,7 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
colorBlit ? VK_IMAGE_ASPECT_COLOR_BIT
: vk::GetDepthStencilAspectFlags(readImageFormat.textureFormat());
vk::ImageHelper *srcImage = readRenderTarget->getImageForRead(
- &mFramebuffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, commandBuffer);
+ &mFramebuffer, vk::ImageLayout::TransferSrc, commandBuffer);
const gl::Extents sourceFrameBufferExtents = readRenderTarget->getImageExtents();
gl::Rectangle readRect = readRectIn;
@@ -702,9 +712,7 @@ angle::Result FramebufferVk::blitWithCommand(ContextVk *contextVk,
// Requirement of the copyImageToBuffer, the dst image must be in
// VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL layout.
- dstImage->changeLayoutWithStages(aspectMask, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer);
+ dstImage->changeLayout(aspectMask, vk::ImageLayout::TransferDst, commandBuffer);
commandBuffer->blitImage(srcImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
dstImage->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &blit,
@@ -1099,6 +1107,7 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
RenderTargetVk *renderTarget,
void *pixels)
{
+ TRACE_EVENT0("gpu.angle", "FramebufferVk::readPixelsImpl");
RendererVk *renderer = contextVk->getRenderer();
ANGLE_TRY(renderTarget->ensureImageInitialized(contextVk));
@@ -1108,8 +1117,8 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
// Note that although we're reading from the image, we need to update the layout below.
- vk::ImageHelper *srcImage = renderTarget->getImageForRead(
- &mFramebuffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, commandBuffer);
+ vk::ImageHelper *srcImage =
+ renderTarget->getImageForRead(&mFramebuffer, vk::ImageLayout::TransferSrc, commandBuffer);
const angle::Format *readFormat = &srcImage->getFormat().textureFormat();
@@ -1139,7 +1148,7 @@ angle::Result FramebufferVk::readPixelsImpl(ContextVk *contextVk,
region.imageSubresource.aspectMask = copyAspectFlags;
region.imageSubresource.baseArrayLayer = renderTarget->getLayerIndex();
region.imageSubresource.layerCount = 1;
- region.imageSubresource.mipLevel = 0;
+ region.imageSubresource.mipLevel = renderTarget->getLevelIndex();
commandBuffer->copyImageToBuffer(srcImage->getImage(), srcImage->getCurrentLayout(),
bufferHandle, 1, &region);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
index af679e2d76c..d0677d63b9f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/GlslangWrapper.cpp
@@ -8,14 +8,18 @@
#include "libANGLE/renderer/vulkan/GlslangWrapper.h"
+// glslang has issues with some specific warnings.
+ANGLE_DISABLE_EXTRA_SEMI_WARNING
+
// glslang's version of ShaderLang.h, not to be confused with ANGLE's.
-// Our function defs conflict with theirs, but we carefully manage our includes to prevent this.
-#include <ShaderLang.h>
+#include <glslang/Public/ShaderLang.h>
// Other glslang includes.
#include <SPIRV/GlslangToSpv.h>
#include <StandAlone/ResourceLimits.h>
+ANGLE_REENABLE_EXTRA_SEMI_WARNING
+
#include <array>
#include "common/FixedVector.h"
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp
index 5ad2903bb83..3e9db933849 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.cpp
@@ -11,25 +11,125 @@
#include "common/debug.h"
#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
+#include "libANGLE/renderer/vulkan/RenderbufferVk.h"
+#include "libANGLE/renderer/vulkan/TextureVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
namespace rx
{
-ImageVk::ImageVk(const egl::ImageState &state) : ImageImpl(state) {}
+ImageVk::ImageVk(const egl::ImageState &state, const gl::Context *context)
+ : ImageImpl(state), mImageLevel(0), mOwnsImage(false), mImage(nullptr), mContext(context)
+{}
ImageVk::~ImageVk() {}
+void ImageVk::onDestroy(const egl::Display *display)
+{
+ DisplayVk *displayVk = vk::GetImpl(display);
+ RendererVk *renderer = displayVk->getRenderer();
+
+ if (mImage != nullptr && mOwnsImage)
+ {
+ mImage->releaseImage(renderer);
+ mImage->releaseStagingBuffer(renderer);
+ delete mImage;
+ }
+ mImage = nullptr;
+}
+
egl::Error ImageVk::initialize(const egl::Display *display)
{
- UNIMPLEMENTED();
- return egl::EglBadAccess();
+ if (egl::IsTextureTarget(mState.target))
+ {
+ TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
+
+ // Make sure the texture has created its backing storage
+ ASSERT(mContext != nullptr);
+ ContextVk *contextVk = vk::GetImpl(mContext);
+ ANGLE_TRY(ResultToEGL(textureVk->ensureImageInitialized(contextVk)));
+
+ mImage = &textureVk->getImage();
+
+ // The staging buffer for a texture source should already be initialized
+
+ mOwnsImage = false;
+
+ mImageTextureType = mState.imageIndex.getType();
+ mImageLevel = mState.imageIndex.getLevelIndex();
+ mImageLayer = mState.imageIndex.hasLayer() ? mState.imageIndex.getLayerIndex() : 0;
+ }
+ else
+ {
+ RendererVk *renderer = nullptr;
+ if (egl::IsRenderbufferTarget(mState.target))
+ {
+ RenderbufferVk *renderbufferVk =
+ GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
+ mImage = renderbufferVk->getImage();
+
+ ASSERT(mContext != nullptr);
+ renderer = vk::GetImpl(mContext)->getRenderer();
+ ;
+ }
+ else if (egl::IsExternalImageTarget(mState.target))
+ {
+ const ExternalImageSiblingVk *externalImageSibling =
+ GetImplAs<ExternalImageSiblingVk>(GetAs<egl::ExternalImageSibling>(mState.source));
+ mImage = externalImageSibling->getImage();
+
+ ASSERT(mContext == nullptr);
+ renderer = vk::GetImpl(display)->getRenderer();
+ }
+ else
+ {
+ UNREACHABLE();
+ return egl::EglBadAccess();
+ }
+
+ // Make sure a staging buffer is ready to use to upload data
+ mImage->initStagingBuffer(renderer, mImage->getFormat());
+
+ mOwnsImage = false;
+
+ mImageTextureType = gl::TextureType::_2D;
+ mImageLevel = 0;
+ mImageLayer = 0;
+ }
+
+ return egl::NoError();
}
angle::Result ImageVk::orphan(const gl::Context *context, egl::ImageSibling *sibling)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ if (sibling == mState.source)
+ {
+ if (egl::IsTextureTarget(mState.target))
+ {
+ TextureVk *textureVk = GetImplAs<TextureVk>(GetAs<gl::Texture>(mState.source));
+ ASSERT(mImage == &textureVk->getImage());
+ textureVk->releaseOwnershipOfImage(context);
+ mOwnsImage = true;
+ }
+ else if (egl::IsRenderbufferTarget(mState.target))
+ {
+ RenderbufferVk *renderbufferVk =
+ GetImplAs<RenderbufferVk>(GetAs<gl::Renderbuffer>(mState.source));
+ ASSERT(mImage == renderbufferVk->getImage());
+ renderbufferVk->releaseOwnershipOfImage(context);
+ mOwnsImage = true;
+ }
+ else
+ {
+ ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
+ return angle::Result::Stop;
+ }
+ }
+
+ return angle::Result::Continue;
}
+
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.h
index c6611b74eae..b91d322a78a 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ImageVk.h
@@ -11,18 +11,45 @@
#define LIBANGLE_RENDERER_VULKAN_IMAGEVK_H_
#include "libANGLE/renderer/ImageImpl.h"
+#include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx
{
+class ExternalImageSiblingVk : public ExternalImageSiblingImpl
+{
+ public:
+ ExternalImageSiblingVk() {}
+ ~ExternalImageSiblingVk() override {}
+
+ virtual vk::ImageHelper *getImage() const = 0;
+};
+
class ImageVk : public ImageImpl
{
public:
- ImageVk(const egl::ImageState &state);
+ ImageVk(const egl::ImageState &state, const gl::Context *context);
~ImageVk() override;
+ void onDestroy(const egl::Display *display) override;
+
egl::Error initialize(const egl::Display *display) override;
angle::Result orphan(const gl::Context *context, egl::ImageSibling *sibling) override;
+
+ vk::ImageHelper *getImage() const { return mImage; }
+ gl::TextureType getImageTextureType() const { return mImageTextureType; }
+ uint32_t getImageLevel() const { return mImageLevel; }
+ uint32_t getImageLayer() const { return mImageLayer; }
+
+ private:
+ gl::TextureType mImageTextureType;
+ uint32_t mImageLevel;
+ uint32_t mImageLayer;
+
+ bool mOwnsImage;
+ vk::ImageHelper *mImage;
+
+ const gl::Context *mContext;
};
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp
index 0c47c5bd6a6..206bc20ce3b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.cpp
@@ -215,18 +215,18 @@ void ProgramVk::reset(RendererVk *renderer)
mDescriptorSets.clear();
mUsedDescriptorSetRange.invalidate();
- for (vk::SharedDescriptorPoolBinding &binding : mDescriptorPoolBindings)
+ for (vk::RefCountedDescriptorPoolBinding &binding : mDescriptorPoolBindings)
{
binding.reset();
}
}
-angle::Result ProgramVk::load(const gl::Context *context,
- gl::InfoLog &infoLog,
- gl::BinaryInputStream *stream)
+std::unique_ptr<rx::LinkEvent> ProgramVk::load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog)
{
UNIMPLEMENTED();
- return angle::Result::Stop;
+ return std::make_unique<LinkEventDone>(angle::Result::Stop);
}
void ProgramVk::save(const gl::Context *context, gl::BinaryOutputStream *stream)
@@ -860,15 +860,13 @@ angle::Result ProgramVk::updateTexturesDescriptorSet(ContextVk *contextVk,
vk::ImageHelper &image = textureVk->getImage();
// Ensure the image is in read-only layout
- if (image.getCurrentLayout() != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
+ if (image.isLayoutChangeNecessary(vk::ImageLayout::FragmentShaderReadOnly))
{
vk::CommandBuffer *srcLayoutChange;
ANGLE_TRY(image.recordCommands(contextVk, &srcLayoutChange));
- image.changeLayoutWithStages(
- VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
- srcLayoutChange);
+ image.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT,
+ vk::ImageLayout::FragmentShaderReadOnly, srcLayoutChange);
}
image.addReadDependency(framebuffer);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.h
index 70b6ad046b0..e59feefe10f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/ProgramVk.h
@@ -32,9 +32,9 @@ class ProgramVk : public ProgramImpl
~ProgramVk() override;
void destroy(const gl::Context *context) override;
- angle::Result load(const gl::Context *context,
- gl::InfoLog &infoLog,
- gl::BinaryInputStream *stream) override;
+ std::unique_ptr<LinkEvent> load(const gl::Context *context,
+ gl::BinaryInputStream *stream,
+ gl::InfoLog &infoLog) override;
void save(const gl::Context *context, gl::BinaryOutputStream *stream) override;
void setBinaryRetrievableHint(bool retrievable) override;
void setSeparable(bool separable) override;
@@ -224,7 +224,7 @@ class ProgramVk : public ProgramImpl
// Keep bindings to the descriptor pools. This ensures the pools stay valid while the Program
// is in use.
- vk::DescriptorSetLayoutArray<vk::SharedDescriptorPoolBinding> mDescriptorPoolBindings;
+ vk::DescriptorSetLayoutArray<vk::RefCountedDescriptorPoolBinding> mDescriptorPoolBindings;
class ShaderInfo final : angle::NonCopyable
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp
index c3214025bfa..42c42992c91 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/QueryVk.cpp
@@ -143,6 +143,8 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
}
ANGLE_VK_TRY(contextVk, result);
+ double timestampPeriod = renderer->getPhysicalDeviceProperties().limits.timestampPeriod;
+
// Fix up the results to what OpenGL expects.
switch (getType())
{
@@ -152,6 +154,7 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
mCachedResult = !!mCachedResult;
break;
case gl::QueryType::Timestamp:
+ mCachedResult = static_cast<uint64_t>(mCachedResult * timestampPeriod);
break;
case gl::QueryType::TimeElapsed:
{
@@ -166,6 +169,8 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
ANGLE_VK_TRY(contextVk, result);
mCachedResult = timeElapsedEnd - mCachedResult;
+ mCachedResult = static_cast<uint64_t>(mCachedResult * timestampPeriod);
+
break;
}
default:
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp
index a94943f3fde..8035c8ee23c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.cpp
@@ -16,11 +16,8 @@
namespace rx
{
-RenderTargetVk::RenderTargetVk(vk::ImageHelper *image,
- vk::ImageView *imageView,
- size_t layerIndex,
- TextureVk *owner)
- : mImage(image), mImageView(imageView), mLayerIndex(layerIndex), mOwner(owner)
+RenderTargetVk::RenderTargetVk()
+ : mImage(nullptr), mImageView(nullptr), mLevelIndex(0), mLayerIndex(0), mOwner(nullptr)
{}
RenderTargetVk::~RenderTargetVk() {}
@@ -28,10 +25,33 @@ RenderTargetVk::~RenderTargetVk() {}
RenderTargetVk::RenderTargetVk(RenderTargetVk &&other)
: mImage(other.mImage),
mImageView(other.mImageView),
+ mLevelIndex(other.mLevelIndex),
mLayerIndex(other.mLayerIndex),
mOwner(other.mOwner)
{}
+void RenderTargetVk::init(vk::ImageHelper *image,
+ vk::ImageView *imageView,
+ size_t levelIndex,
+ size_t layerIndex,
+ TextureVk *owner)
+{
+ mImage = image;
+ mImageView = imageView;
+ mLevelIndex = levelIndex;
+ mLayerIndex = layerIndex;
+ mOwner = owner;
+}
+
+void RenderTargetVk::reset()
+{
+ mImage = nullptr;
+ mImageView = nullptr;
+ mLevelIndex = 0;
+ mLayerIndex = 0;
+ mOwner = nullptr;
+}
+
void RenderTargetVk::onColorDraw(vk::FramebufferHelper *framebufferVk,
vk::CommandBuffer *commandBuffer,
vk::RenderPassDesc *renderPassDesc)
@@ -43,10 +63,8 @@ void RenderTargetVk::onColorDraw(vk::FramebufferHelper *framebufferVk,
renderPassDesc->packAttachment(mImage->getFormat());
// TODO(jmadill): Use automatic layout transition. http://anglebug.com/2361
- mImage->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, commandBuffer);
+ mImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment,
+ commandBuffer);
// Set up dependencies between the RT resource and the Framebuffer.
mImage->addWriteDependency(framebufferVk);
@@ -66,9 +84,7 @@ void RenderTargetVk::onDepthStencilDraw(vk::FramebufferHelper *framebufferVk,
const angle::Format &format = mImage->getFormat().textureFormat();
VkImageAspectFlags aspectFlags = vk::GetDepthStencilAspectFlags(format);
- mImage->changeLayoutWithStages(aspectFlags, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, commandBuffer);
+ mImage->changeLayout(aspectFlags, vk::ImageLayout::DepthStencilAttachment, commandBuffer);
// Set up dependencies between the RT resource and the Framebuffer.
mImage->addWriteDependency(framebufferVk);
@@ -118,17 +134,29 @@ void RenderTargetVk::updateSwapchainImage(vk::ImageHelper *image, vk::ImageView
}
vk::ImageHelper *RenderTargetVk::getImageForRead(vk::CommandGraphResource *readingResource,
- VkImageLayout layout,
+ vk::ImageLayout layout,
vk::CommandBuffer *commandBuffer)
{
ASSERT(mImage && mImage->valid());
// TODO(jmadill): Better simultaneous resource access. http://anglebug.com/2679
+ //
+ // A better alternative would be:
+ //
+ // if (mImage->isLayoutChangeNecessary(layout)
+ // {
+ // vk::CommandBuffer *srcLayoutChange;
+ // ANGLE_TRY(mImage->recordCommands(contextVk, &srcLayoutChange));
+ // mImage->changeLayout(mImage->getAspectFlags(), layout, srcLayoutChange);
+ // }
+ // mImage->addReadDependency(readingResource);
+ //
+ // I.e. the transition should happen on a node generated from mImage itself.
+ // However, this needs context to be available here, or all call sites changed
+ // to perform the layout transition and set the dependency.
mImage->addWriteDependency(readingResource);
- mImage->changeLayoutWithStages(mImage->getAspectFlags(), layout,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer);
+ mImage->changeLayout(mImage->getAspectFlags(), layout, commandBuffer);
return mImage;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.h
index e23187953ae..bc6ace30740 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderTargetVk.h
@@ -14,6 +14,7 @@
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx
{
@@ -37,15 +38,19 @@ class TextureVk;
class RenderTargetVk final : public FramebufferAttachmentRenderTarget
{
public:
- RenderTargetVk(vk::ImageHelper *image,
- vk::ImageView *imageView,
- size_t layerIndex,
- TextureVk *ownwer);
+ RenderTargetVk();
~RenderTargetVk() override;
// Used in std::vector initialization.
RenderTargetVk(RenderTargetVk &&other);
+ void init(vk::ImageHelper *image,
+ vk::ImageView *imageView,
+ size_t levelIndex,
+ size_t layerIndex,
+ TextureVk *owner);
+ void reset();
+
// Note: RenderTargets should be called in order, with the depth/stencil onRender last.
void onColorDraw(vk::FramebufferHelper *framebufferVk,
vk::CommandBuffer *commandBuffer,
@@ -59,7 +64,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
// getImageForRead will also transition the resource to the given layout.
vk::ImageHelper *getImageForRead(vk::CommandGraphResource *readingResource,
- VkImageLayout layout,
+ vk::ImageLayout layout,
vk::CommandBuffer *commandBuffer);
vk::ImageHelper *getImageForWrite(vk::CommandGraphResource *writingResource) const;
@@ -68,6 +73,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
const vk::Format &getImageFormat() const;
const gl::Extents &getImageExtents() const;
+ size_t getLevelIndex() const { return mLevelIndex; }
size_t getLayerIndex() const { return mLayerIndex; }
// Special mutator for Surface RenderTargets. Allows the Framebuffer to keep a single
@@ -81,6 +87,7 @@ class RenderTargetVk final : public FramebufferAttachmentRenderTarget
// Note that the draw and read image views are the same, given the requirements of a render
// target.
vk::ImageView *mImageView;
+ size_t mLevelIndex;
size_t mLayerIndex;
// If owned by the texture, this will be non-nullptr, and is used to ensure texture changes
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
index c5ac794ac38..1e485a90f7e 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.cpp
@@ -10,7 +10,9 @@
#include "libANGLE/renderer/vulkan/RenderbufferVk.h"
#include "libANGLE/Context.h"
+#include "libANGLE/Image.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/ImageVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
namespace rx
@@ -24,7 +26,7 @@ constexpr VkClearColorValue kBlackClearColorValue = {{0}};
} // anonymous namespace
RenderbufferVk::RenderbufferVk(const gl::RenderbufferState &state)
- : RenderbufferImpl(state), mRenderTarget(&mImage, &mImageView, 0, nullptr)
+ : RenderbufferImpl(state), mOwnsImage(false), mImage(nullptr)
{}
RenderbufferVk::~RenderbufferVk() {}
@@ -33,9 +35,7 @@ void RenderbufferVk::onDestroy(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
-
- mImage.release(renderer);
- renderer->releaseObject(renderer->getCurrentQueueSerial(), &mImageView);
+ releaseAndDeleteImage(context, renderer);
}
angle::Result RenderbufferVk::setStorage(const gl::Context *context,
@@ -47,20 +47,30 @@ angle::Result RenderbufferVk::setStorage(const gl::Context *context,
RendererVk *renderer = contextVk->getRenderer();
const vk::Format &vkFormat = renderer->getFormat(internalformat);
- if (mImage.valid())
+ if (!mOwnsImage)
+ {
+ releaseAndDeleteImage(context, renderer);
+ }
+
+ if (mImage != nullptr && mImage->valid())
{
// Check against the state if we need to recreate the storage.
if (internalformat != mState.getFormat().info->internalFormat ||
static_cast<GLsizei>(width) != mState.getWidth() ||
static_cast<GLsizei>(height) != mState.getHeight())
{
- mImage.release(renderer);
- renderer->releaseObject(renderer->getCurrentQueueSerial(), &mImageView);
+ releaseImage(context, renderer);
}
}
- if (!mImage.valid() && (width != 0 && height != 0))
+ if ((mImage == nullptr || !mImage->valid()) && (width != 0 && height != 0))
{
+ if (mImage == nullptr)
+ {
+ mImage = new vk::ImageHelper();
+ mOwnsImage = true;
+ }
+
const angle::Format &textureFormat = vkFormat.textureFormat();
bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0;
const VkImageUsageFlags usage =
@@ -70,30 +80,33 @@ angle::Result RenderbufferVk::setStorage(const gl::Context *context,
(isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
gl::Extents extents(static_cast<int>(width), static_cast<int>(height), 1);
- ANGLE_TRY(mImage.init(contextVk, gl::TextureType::_2D, extents, vkFormat, 1, usage, 1, 1));
+ ANGLE_TRY(mImage->init(contextVk, gl::TextureType::_2D, extents, vkFormat, 1, usage, 1, 1));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- ANGLE_TRY(mImage.initMemory(contextVk, renderer->getMemoryProperties(), flags));
+ ANGLE_TRY(mImage->initMemory(contextVk, renderer->getMemoryProperties(), flags));
VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat);
// Note that LUMA textures are not color-renderable, so a read-view with swizzle is not
// needed.
- ANGLE_TRY(mImage.initImageView(contextVk, gl::TextureType::_2D, aspect, gl::SwizzleState(),
- &mImageView, 1));
+ ANGLE_TRY(mImage->initImageView(contextVk, gl::TextureType::_2D, aspect, gl::SwizzleState(),
+ &mImageView, 0, 1));
// TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
vk::CommandBuffer *commandBuffer = nullptr;
- ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer));
+ ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
if (isDepthOrStencilFormat)
{
- mImage.clearDepthStencil(aspect, aspect, kDefaultClearDepthStencilValue, commandBuffer);
+ mImage->clearDepthStencil(aspect, aspect, kDefaultClearDepthStencilValue,
+ commandBuffer);
}
else
{
- mImage.clearColor(kBlackClearColorValue, 0, 1, commandBuffer);
+ mImage->clearColor(kBlackClearColorValue, 0, 1, commandBuffer);
}
+
+ mRenderTarget.init(mImage, &mImageView, 0, 0, nullptr);
}
return angle::Result::Continue;
@@ -112,8 +125,38 @@ angle::Result RenderbufferVk::setStorageMultisample(const gl::Context *context,
angle::Result RenderbufferVk::setStorageEGLImageTarget(const gl::Context *context,
egl::Image *image)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ ContextVk *contextVk = vk::GetImpl(context);
+ RendererVk *renderer = contextVk->getRenderer();
+
+ releaseAndDeleteImage(context, renderer);
+
+ ImageVk *imageVk = vk::GetImpl(image);
+ mImage = imageVk->getImage();
+ mOwnsImage = false;
+
+ const vk::Format &vkFormat = renderer->getFormat(image->getFormat().info->sizedInternalFormat);
+ const angle::Format &textureFormat = vkFormat.textureFormat();
+
+ VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat);
+
+ // Transfer the image to this queue if needed
+ uint32_t rendererQueueFamilyIndex = contextVk->getRenderer()->getQueueFamilyIndex();
+ if (mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex))
+ {
+ vk::CommandBuffer *commandBuffer = nullptr;
+ ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
+ mImage->changeLayoutAndQueue(aspect, vk::ImageLayout::ColorAttachment,
+ rendererQueueFamilyIndex, commandBuffer);
+ }
+
+ ANGLE_TRY(mImage->initLayerImageView(contextVk, imageVk->getImageTextureType(), aspect,
+ gl::SwizzleState(), &mImageView, imageVk->getImageLevel(),
+ 1, imageVk->getImageLayer(), 1));
+
+ mRenderTarget.init(mImage, &mImageView, imageVk->getImageLevel(), imageVk->getImageLayer(),
+ nullptr);
+
+ return angle::Result::Continue;
}
angle::Result RenderbufferVk::getAttachmentRenderTarget(const gl::Context *context,
@@ -121,7 +164,7 @@ angle::Result RenderbufferVk::getAttachmentRenderTarget(const gl::Context *conte
const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut)
{
- ASSERT(mImage.valid());
+ ASSERT(mImage && mImage->valid());
*rtOut = &mRenderTarget;
return angle::Result::Continue;
}
@@ -133,4 +176,34 @@ angle::Result RenderbufferVk::initializeContents(const gl::Context *context,
return angle::Result::Continue;
}
+void RenderbufferVk::releaseOwnershipOfImage(const gl::Context *context)
+{
+ ContextVk *contextVk = vk::GetImpl(context);
+ RendererVk *renderer = contextVk->getRenderer();
+
+ mOwnsImage = false;
+ releaseAndDeleteImage(context, renderer);
+}
+
+void RenderbufferVk::releaseAndDeleteImage(const gl::Context *context, RendererVk *renderer)
+{
+ releaseImage(context, renderer);
+ SafeDelete(mImage);
+}
+
+void RenderbufferVk::releaseImage(const gl::Context *context, RendererVk *renderer)
+{
+ if (mImage && mOwnsImage)
+ {
+ mImage->releaseImage(renderer);
+ mImage->releaseStagingBuffer(renderer);
+ }
+ else
+ {
+ mImage = nullptr;
+ }
+
+ renderer->releaseObject(renderer->getCurrentQueueSerial(), &mImageView);
+}
+
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h
index b94af3bef71..57c6ccc7bd7 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RenderbufferVk.h
@@ -44,8 +44,15 @@ class RenderbufferVk : public RenderbufferImpl
angle::Result initializeContents(const gl::Context *context,
const gl::ImageIndex &imageIndex) override;
+ vk::ImageHelper *getImage() const { return mImage; }
+ void releaseOwnershipOfImage(const gl::Context *context);
+
private:
- vk::ImageHelper mImage;
+ void releaseAndDeleteImage(const gl::Context *context, RendererVk *renderer);
+ void releaseImage(const gl::Context *context, RendererVk *renderer);
+
+ bool mOwnsImage;
+ vk::ImageHelper *mImage;
vk::ImageView mImageView;
RenderTargetVk mRenderTarget;
};
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp
index 912a0dd74ed..9e14e4b7c39 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.cpp
@@ -31,7 +31,6 @@
#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
#include "platform/Platform.h"
-
#include "third_party/trace_event/trace_event.h"
// Consts
@@ -53,9 +52,15 @@ namespace
// one for the vertex shader.
constexpr size_t kUniformBufferDescriptorsPerDescriptorSet = 2;
// Update the pipeline cache every this many swaps (if 60fps, this means every 10 minutes)
-static constexpr uint32_t kPipelineCacheVkUpdatePeriod = 10 * 60 * 60;
+constexpr uint32_t kPipelineCacheVkUpdatePeriod = 10 * 60 * 60;
// Wait a maximum of 10s. If that times out, we declare it a failure.
-static constexpr uint64_t kMaxFenceWaitTimeNs = 10'000'000'000llu;
+constexpr uint64_t kMaxFenceWaitTimeNs = 10'000'000'000llu;
+// Per the Vulkan specification, as long as Vulkan 1.1+ is returned by vkEnumerateInstanceVersion,
+// ANGLE must indicate the highest version of Vulkan functionality that it uses. The Vulkan
+// validation layers will issue messages for any core functionality that requires a higher version.
+// This value must be increased whenever ANGLE starts using functionality from a newer core
+// version of Vulkan.
+constexpr uint32_t kPreferredVulkanAPIVersion = VK_API_VERSION_1_1;
bool ShouldEnableMockICD(const egl::AttributeMap &attribs)
{
@@ -69,49 +74,51 @@ bool ShouldEnableMockICD(const egl::AttributeMap &attribs)
#endif // !defined(ANGLE_PLATFORM_ANDROID)
}
-VkResult VerifyExtensionsPresent(const std::vector<VkExtensionProperties> &extensionProps,
- const std::vector<const char *> &enabledExtensionNames)
+bool StrLess(const char *a, const char *b)
{
- // Compile the extensions names into a set.
- std::set<std::string> extensionNames;
- for (const auto &extensionProp : extensionProps)
- {
- extensionNames.insert(extensionProp.extensionName);
- }
-
- for (const char *extensionName : enabledExtensionNames)
- {
- if (extensionNames.count(extensionName) == 0)
- {
- return VK_ERROR_EXTENSION_NOT_PRESENT;
- }
- }
+ return strcmp(a, b) < 0;
+}
- return VK_SUCCESS;
+bool ExtensionFound(const char *needle, const RendererVk::ExtensionNameList &haystack)
+{
+ // NOTE: The list must be sorted.
+ return std::binary_search(haystack.begin(), haystack.end(), needle, StrLess);
}
-bool ExtensionFound(const char *extensionName,
- const std::vector<VkExtensionProperties> &extensionProps)
+VkResult VerifyExtensionsPresent(const RendererVk::ExtensionNameList &haystack,
+ const RendererVk::ExtensionNameList &needles)
{
- for (const auto &extensionProp : extensionProps)
+ // NOTE: The lists must be sorted.
+ if (std::includes(haystack.begin(), haystack.end(), needles.begin(), needles.end(), StrLess))
+ {
+ return VK_SUCCESS;
+ }
+ for (const char *needle : needles)
{
- if (strcmp(extensionProp.extensionName, extensionName) == 0)
+ if (!ExtensionFound(needle, haystack))
{
- return true;
+ ERR() << "Extension not supported: " << needle;
}
}
- return false;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// Array of Validation error/warning messages that will be ignored, should include bugID
-constexpr std::array<const char *, 1> kSkippedMessages = {
+constexpr const char *kSkippedMessages[] = {
+ // http://anglebug.com/2866
+ "UNASSIGNED-CoreValidation-Shader-OutputNotConsumed",
// http://anglebug.com/2796
- "UNASSIGNED-CoreValidation-Shader-PointSizeMissing"};
+ "UNASSIGNED-CoreValidation-Shader-PointSizeMissing",
+};
// Suppress validation errors that are known
// return "true" if given code/prefix/message is known, else return "false"
bool IsIgnoredDebugMessage(const char *message)
{
+ if (!message)
+ {
+ return false;
+ }
for (const char *msg : kSkippedMessages)
{
if (strstr(message, msg) != nullptr)
@@ -200,7 +207,7 @@ const char *GetVkObjectTypeName(VkObjectType type)
return "Debug Utils Messenger";
case VK_OBJECT_TYPE_VALIDATION_CACHE_EXT:
return "Validation Cache";
- case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NVX:
+ case VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV:
return "Acceleration Structure";
default:
return "<Unrecognized>";
@@ -213,16 +220,6 @@ DebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
const VkDebugUtilsMessengerCallbackDataEXT *callbackData,
void *userData)
{
- constexpr VkDebugUtilsMessageSeverityFlagsEXT kSeveritiesToLog =
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
-
- // Check if we even care about this message.
- if ((messageSeverity & kSeveritiesToLog) == 0)
- {
- return VK_FALSE;
- }
-
// See if it's an issue we are aware of and don't want to be spammed about.
if (IsIgnoredDebugMessage(callbackData->pMessageIdName))
{
@@ -230,7 +227,11 @@ DebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
}
std::ostringstream log;
- log << "[ " << callbackData->pMessageIdName << " ] " << callbackData->pMessage << std::endl;
+ if (callbackData->pMessageIdName)
+ {
+ log << "[ " << callbackData->pMessageIdName << " ] ";
+ }
+ log << callbackData->pMessage << std::endl;
// Aesthetic value based on length of the function name, line number, etc.
constexpr size_t kStartIndent = 28;
@@ -281,15 +282,16 @@ DebugUtilsMessenger(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
}
}
- bool isError = (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0;
+ bool isError = (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) != 0;
+ std::string msg = log.str();
if (isError)
{
- ERR() << log.str();
+ ERR() << msg;
}
else
{
- WARN() << log.str();
+ WARN() << msg;
}
return VK_FALSE;
@@ -344,7 +346,7 @@ class ScopedVkLoaderEnvironment : angle::NonCopyable
// Changing CWD and setting environment variables makes no sense on Android,
// since this code is a part of Java application there.
// Android Vulkan loader doesn't need this either.
-#if !defined(ANGLE_PLATFORM_ANDROID)
+#if !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_FUCHSIA)
if (enableMockICD)
{
// Override environment variable to use built Mock ICD
@@ -466,8 +468,9 @@ RendererVk::CommandBatch::CommandBatch() = default;
RendererVk::CommandBatch::~CommandBatch() = default;
RendererVk::CommandBatch::CommandBatch(CommandBatch &&other)
- : commandPool(std::move(other.commandPool)), fence(std::move(other.fence)), serial(other.serial)
-{}
+{
+ *this = std::move(other);
+}
RendererVk::CommandBatch &RendererVk::CommandBatch::operator=(CommandBatch &&other)
{
@@ -480,7 +483,7 @@ RendererVk::CommandBatch &RendererVk::CommandBatch::operator=(CommandBatch &&oth
void RendererVk::CommandBatch::destroy(VkDevice device)
{
commandPool.destroy(device);
- fence.destroy(device);
+ fence.reset(device);
}
// RendererVk implementation.
@@ -496,6 +499,7 @@ RendererVk::RendererVk()
mPhysicalDevice(VK_NULL_HANDLE),
mQueue(VK_NULL_HANDLE),
mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
+ mMaxVertexAttribDivisor(1),
mDevice(VK_NULL_HANDLE),
mLastCompletedQueueSerial(mQueueSerialFactory.generate()),
mCurrentQueueSerial(mQueueSerialFactory.generate()),
@@ -585,7 +589,8 @@ bool RendererVk::isDeviceLost() const
angle::Result RendererVk::initialize(DisplayVk *displayVk,
egl::Display *display,
- const char *wsiName)
+ const char *wsiExtension,
+ const char *wsiLayer)
{
mDisplay = display;
const egl::AttributeMap &attribs = mDisplay->getAttributeMap();
@@ -605,6 +610,22 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
instanceLayerProps.data()));
}
+ VulkanLayerVector enabledInstanceLayerNames;
+ if (mEnableValidationLayers)
+ {
+ bool layersRequested =
+ (attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE) == EGL_TRUE);
+ mEnableValidationLayers = GetAvailableValidationLayers(instanceLayerProps, layersRequested,
+ &enabledInstanceLayerNames);
+ }
+
+ if (wsiLayer)
+ {
+ enabledInstanceLayerNames.push_back(wsiLayer);
+ }
+
+ // Enumerate instance extensions that are provided by the vulkan
+ // implementation and implicit layers.
uint32_t instanceExtensionCount = 0;
ANGLE_VK_TRY(displayVk,
vkEnumerateInstanceExtensionProperties(nullptr, &instanceExtensionCount, nullptr));
@@ -617,26 +638,39 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
instanceExtensionProps.data()));
}
- const char *const *enabledLayerNames = nullptr;
- uint32_t enabledLayerCount = 0;
- if (mEnableValidationLayers)
+ // Enumerate instance extensions that are provided by explicit layers.
+ for (const char *layerName : enabledInstanceLayerNames)
{
- bool layersRequested =
- (attribs.get(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE, EGL_DONT_CARE) == EGL_TRUE);
- mEnableValidationLayers = GetAvailableValidationLayers(
- instanceLayerProps, layersRequested, &enabledLayerNames, &enabledLayerCount);
+ uint32_t previousExtensionCount = instanceExtensionProps.size();
+ uint32_t instanceLayerExtensionCount = 0;
+ ANGLE_VK_TRY(displayVk, vkEnumerateInstanceExtensionProperties(
+ layerName, &instanceLayerExtensionCount, nullptr));
+ instanceExtensionProps.resize(previousExtensionCount + instanceLayerExtensionCount);
+ ANGLE_VK_TRY(displayVk, vkEnumerateInstanceExtensionProperties(
+ layerName, &instanceLayerExtensionCount,
+ instanceExtensionProps.data() + previousExtensionCount));
+ }
+
+ ExtensionNameList instanceExtensionNames;
+ if (!instanceExtensionProps.empty())
+ {
+ for (const VkExtensionProperties &i : instanceExtensionProps)
+ {
+ instanceExtensionNames.push_back(i.extensionName);
+ }
+ std::sort(instanceExtensionNames.begin(), instanceExtensionNames.end(), StrLess);
}
- std::vector<const char *> enabledInstanceExtensions;
+ ExtensionNameList enabledInstanceExtensions;
enabledInstanceExtensions.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
- enabledInstanceExtensions.push_back(wsiName);
+ enabledInstanceExtensions.push_back(wsiExtension);
bool enableDebugUtils =
mEnableValidationLayers &&
- ExtensionFound(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instanceExtensionProps);
+ ExtensionFound(VK_EXT_DEBUG_UTILS_EXTENSION_NAME, instanceExtensionNames);
bool enableDebugReport =
mEnableValidationLayers && !enableDebugUtils &&
- ExtensionFound(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instanceExtensionProps);
+ ExtensionFound(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, instanceExtensionNames);
if (enableDebugUtils)
{
@@ -648,8 +682,16 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
}
// Verify the required extensions are in the extension names set. Fail if not.
+ std::sort(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(), StrLess);
ANGLE_VK_TRY(displayVk,
- VerifyExtensionsPresent(instanceExtensionProps, enabledInstanceExtensions));
+ VerifyExtensionsPresent(instanceExtensionNames, enabledInstanceExtensions));
+
+ // Enable VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME if available.
+ if (ExtensionFound(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
+ instanceExtensionNames))
+ {
+ enabledInstanceExtensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+ }
VkApplicationInfo applicationInfo = {};
applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -670,11 +712,12 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
ANGLE_VK_TRY(displayVk, enumerateInstanceVersion(&apiVersion));
if ((VK_VERSION_MAJOR(apiVersion) > 1) || (VK_VERSION_MINOR(apiVersion) >= 1))
{
- // Note: will need to revisit this with Vulkan 1.2+.
- applicationInfo.apiVersion = VK_API_VERSION_1_1;
+ // This is the highest version of core Vulkan functionality that ANGLE uses.
+ applicationInfo.apiVersion = kPreferredVulkanAPIVersion;
}
else
{
+ // Since only 1.0 instance-level functionality is available, this must set to 1.0.
applicationInfo.apiVersion = VK_API_VERSION_1_0;
}
}
@@ -688,8 +731,8 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
instanceInfo.enabledExtensionCount = static_cast<uint32_t>(enabledInstanceExtensions.size());
instanceInfo.ppEnabledExtensionNames =
enabledInstanceExtensions.empty() ? nullptr : enabledInstanceExtensions.data();
- instanceInfo.enabledLayerCount = enabledLayerCount;
- instanceInfo.ppEnabledLayerNames = enabledLayerNames;
+ instanceInfo.enabledLayerCount = enabledInstanceLayerNames.size();
+ instanceInfo.ppEnabledLayerNames = enabledInstanceLayerNames.data();
ANGLE_VK_TRY(displayVk, vkCreateInstance(&instanceInfo, nullptr, &mInstance));
@@ -701,12 +744,18 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
// Create the messenger callback.
VkDebugUtilsMessengerCreateInfoEXT messengerInfo = {};
+ constexpr VkDebugUtilsMessageSeverityFlagsEXT kSeveritiesToLog =
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
+
+ constexpr VkDebugUtilsMessageTypeFlagsEXT kMessagesToLog =
+ VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
+ VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+
messengerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
- messengerInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
- messengerInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
- VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
+ messengerInfo.messageSeverity = kSeveritiesToLog;
+ messengerInfo.messageType = kMessagesToLog;
messengerInfo.pfnUserCallback = &DebugUtilsMessenger;
messengerInfo.pUserData = this;
@@ -729,6 +778,14 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
&mDebugReportCallback));
}
+ if (std::find(enabledInstanceExtensions.begin(), enabledInstanceExtensions.end(),
+ VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME) !=
+ enabledInstanceExtensions.end())
+ {
+ InitGetPhysicalDeviceProperties2KHRFunctions(mInstance);
+ ASSERT(vkGetPhysicalDeviceProperties2KHR);
+ }
+
uint32_t physicalDeviceCount = 0;
ANGLE_VK_TRY(displayVk, vkEnumeratePhysicalDevices(mInstance, &physicalDeviceCount, nullptr));
ANGLE_VK_CHECK(displayVk, physicalDeviceCount > 0, VK_ERROR_INITIALIZATION_FAILED);
@@ -803,6 +860,21 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
deviceLayerProps.data()));
}
+ VulkanLayerVector enabledDeviceLayerNames;
+ if (mEnableValidationLayers)
+ {
+ mEnableValidationLayers =
+ GetAvailableValidationLayers(deviceLayerProps, false, &enabledDeviceLayerNames);
+ }
+
+ const char *wsiLayer = displayVk->getWSILayer();
+ if (wsiLayer)
+ {
+ enabledDeviceLayerNames.push_back(wsiLayer);
+ }
+
+ // Enumerate device extensions that are provided by the vulkan
+ // implementation and implicit layers.
uint32_t deviceExtensionCount = 0;
ANGLE_VK_TRY(displayVk, vkEnumerateDeviceExtensionProperties(mPhysicalDevice, nullptr,
&deviceExtensionCount, nullptr));
@@ -815,18 +887,35 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
deviceExtensionProps.data()));
}
- const char *const *enabledLayerNames = nullptr;
- uint32_t enabledLayerCount = 0;
- if (mEnableValidationLayers)
+ // Enumerate device extensions that are provided by explicit layers.
+ for (const char *layerName : enabledDeviceLayerNames)
+ {
+ uint32_t previousExtensionCount = deviceExtensionProps.size();
+ uint32_t deviceLayerExtensionCount = 0;
+ ANGLE_VK_TRY(displayVk,
+ vkEnumerateDeviceExtensionProperties(mPhysicalDevice, layerName,
+ &deviceLayerExtensionCount, nullptr));
+ deviceExtensionProps.resize(previousExtensionCount + deviceLayerExtensionCount);
+ ANGLE_VK_TRY(displayVk, vkEnumerateDeviceExtensionProperties(
+ mPhysicalDevice, layerName, &deviceLayerExtensionCount,
+ deviceExtensionProps.data() + previousExtensionCount));
+ }
+
+ ExtensionNameList deviceExtensionNames;
+ if (!deviceExtensionProps.empty())
{
- mEnableValidationLayers = GetAvailableValidationLayers(
- deviceLayerProps, false, &enabledLayerNames, &enabledLayerCount);
+ ASSERT(deviceExtensionNames.size() <= deviceExtensionProps.size());
+ for (const VkExtensionProperties &prop : deviceExtensionProps)
+ {
+ deviceExtensionNames.push_back(prop.extensionName);
+ }
+ std::sort(deviceExtensionNames.begin(), deviceExtensionNames.end(), StrLess);
}
- std::vector<const char *> enabledDeviceExtensions;
+ ExtensionNameList enabledDeviceExtensions;
enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
- initFeatures(deviceExtensionProps);
+ initFeatures(deviceExtensionNames);
mFeaturesInitialized = true;
// Selectively enable KHR_MAINTENANCE1 to support viewport flipping.
@@ -840,36 +929,77 @@ angle::Result RendererVk::initializeDevice(DisplayVk *displayVk, uint32_t queueF
enabledDeviceExtensions.push_back(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
}
- ANGLE_VK_TRY(displayVk, VerifyExtensionsPresent(deviceExtensionProps, enabledDeviceExtensions));
+#if defined(ANGLE_PLATFORM_ANDROID)
+ if (getFeatures().supportsAndroidHardwareBuffer)
+ {
+ enabledDeviceExtensions.push_back(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME);
+ enabledDeviceExtensions.push_back(
+ VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME);
+ InitExternalMemoryHardwareBufferANDROIDFunctions(mInstance);
+ }
+#else
+ ASSERT(!getFeatures().supportsAndroidHardwareBuffer);
+#endif
- // Select additional features to be enabled
- VkPhysicalDeviceFeatures enabledFeatures = {};
- enabledFeatures.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
- enabledFeatures.robustBufferAccess = mPhysicalDeviceFeatures.robustBufferAccess;
+ std::sort(enabledDeviceExtensions.begin(), enabledDeviceExtensions.end(), StrLess);
+ ANGLE_VK_TRY(displayVk, VerifyExtensionsPresent(deviceExtensionNames, enabledDeviceExtensions));
- VkDeviceQueueCreateInfo queueCreateInfo = {};
+ // Select additional features to be enabled
+ VkPhysicalDeviceFeatures2KHR enabledFeatures = {};
+ enabledFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ enabledFeatures.features.inheritedQueries = mPhysicalDeviceFeatures.inheritedQueries;
+ enabledFeatures.features.robustBufferAccess = mPhysicalDeviceFeatures.robustBufferAccess;
+ enabledFeatures.features.samplerAnisotropy = mPhysicalDeviceFeatures.samplerAnisotropy;
- float zeroPriority = 0.0f;
+ VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT divisorFeatures = {};
+ divisorFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT;
+ divisorFeatures.vertexAttributeInstanceRateDivisor = true;
- queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
- queueCreateInfo.flags = 0;
- queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
- queueCreateInfo.queueCount = 1;
- queueCreateInfo.pQueuePriorities = &zeroPriority;
+ float zeroPriority = 0.0f;
+ VkDeviceQueueCreateInfo queueCreateInfo = {};
+ queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueCreateInfo.flags = 0;
+ queueCreateInfo.queueFamilyIndex = queueFamilyIndex;
+ queueCreateInfo.queueCount = 1;
+ queueCreateInfo.pQueuePriorities = &zeroPriority;
// Initialize the device
VkDeviceCreateInfo createInfo = {};
- createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
- createInfo.flags = 0;
- createInfo.queueCreateInfoCount = 1;
- createInfo.pQueueCreateInfos = &queueCreateInfo;
- createInfo.enabledLayerCount = enabledLayerCount;
- createInfo.ppEnabledLayerNames = enabledLayerNames;
+ createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ createInfo.flags = 0;
+ createInfo.queueCreateInfoCount = 1;
+ createInfo.pQueueCreateInfos = &queueCreateInfo;
+ createInfo.enabledLayerCount = enabledDeviceLayerNames.size();
+ createInfo.ppEnabledLayerNames = enabledDeviceLayerNames.data();
+
+ if (vkGetPhysicalDeviceProperties2KHR &&
+ ExtensionFound(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME, deviceExtensionNames))
+ {
+ enabledDeviceExtensions.push_back(VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME);
+ enabledFeatures.pNext = &divisorFeatures;
+
+ VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT divisorProperties = {};
+ divisorProperties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
+
+ VkPhysicalDeviceProperties2 deviceProperties = {};
+ deviceProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ deviceProperties.pNext = &divisorProperties;
+
+ vkGetPhysicalDeviceProperties2KHR(mPhysicalDevice, &deviceProperties);
+ mMaxVertexAttribDivisor = divisorProperties.maxVertexAttribDivisor;
+
+ createInfo.pNext = &enabledFeatures;
+ }
+ else
+ {
+ createInfo.pEnabledFeatures = &enabledFeatures.features;
+ }
+
createInfo.enabledExtensionCount = static_cast<uint32_t>(enabledDeviceExtensions.size());
createInfo.ppEnabledExtensionNames =
enabledDeviceExtensions.empty() ? nullptr : enabledDeviceExtensions.data();
- createInfo.pEnabledFeatures = &enabledFeatures;
ANGLE_VK_TRY(displayVk, vkCreateDevice(mPhysicalDevice, &createInfo, nullptr, &mDevice));
@@ -1002,8 +1132,12 @@ std::string RendererVk::getRendererDescription() const
gl::Version RendererVk::getMaxSupportedESVersion() const
{
// Current highest supported version
- // TODO: Update this to support ES 3.0. http://crbug.com/angleproject/2950
- gl::Version maxVersion = gl::Version(2, 0);
+ gl::Version maxVersion = gl::Version(3, 0);
+
+#if ANGLE_VULKAN_CONFORMANT_CONFIGS_ONLY
+ // TODO: Disallow ES 3.0 until supported. http://crbug.com/angleproject/2950
+ maxVersion = gl::Version(2, 0);
+#endif
// Vulkan inherited queries are required to support any GL query type
if (!mPhysicalDeviceFeatures.inheritedQueries)
@@ -1014,7 +1148,7 @@ gl::Version RendererVk::getMaxSupportedESVersion() const
return maxVersion;
}
-void RendererVk::initFeatures(const std::vector<VkExtensionProperties> &deviceExtensionProps)
+void RendererVk::initFeatures(const ExtensionNameList &deviceExtensionNames)
{
// Use OpenGL line rasterization rules by default.
// TODO(jmadill): Fix Android support. http://anglebug.com/2830
@@ -1025,7 +1159,7 @@ void RendererVk::initFeatures(const std::vector<VkExtensionProperties> &deviceEx
#endif // defined(ANGLE_PLATFORM_ANDROID)
if ((mPhysicalDeviceProperties.apiVersion >= VK_MAKE_VERSION(1, 1, 0)) ||
- ExtensionFound(VK_KHR_MAINTENANCE1_EXTENSION_NAME, deviceExtensionProps))
+ ExtensionFound(VK_KHR_MAINTENANCE1_EXTENSION_NAME, deviceExtensionNames))
{
// TODO(lucferron): Currently disabled on Intel only since many tests are failing and need
// investigation. http://anglebug.com/2728
@@ -1050,6 +1184,13 @@ void RendererVk::initFeatures(const std::vector<VkExtensionProperties> &deviceEx
mFeatures.clampPointSize = true;
}
+ // We also need to clamp point size on several Android drivers.
+ // TODO(jmadill): Remove suppression once fixed. http://anglebug.com/2599
+ if (IsAndroid())
+ {
+ mFeatures.clampPointSize = true;
+ }
+
#if defined(ANGLE_PLATFORM_ANDROID)
// Work around ineffective compute-graphics barriers on Nexus 5X.
// TODO(syoussefi): Figure out which other vendors and driver versions are affected.
@@ -1058,10 +1199,22 @@ void RendererVk::initFeatures(const std::vector<VkExtensionProperties> &deviceEx
IsNexus5X(mPhysicalDeviceProperties.vendorID, mPhysicalDeviceProperties.deviceID);
#endif
- if (ExtensionFound(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, deviceExtensionProps))
+ if (ExtensionFound(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, deviceExtensionNames))
{
mFeatures.supportsIncrementalPresent = true;
}
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+ mFeatures.supportsAndroidHardwareBuffer =
+ ExtensionFound(VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME,
+ deviceExtensionNames) &&
+ ExtensionFound(VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME, deviceExtensionNames);
+#endif
+
+ if (IsLinux() && IsIntel(mPhysicalDeviceProperties.vendorID))
+ {
+ mFeatures.disableFifoPresentMode = true;
+ }
}
void RendererVk::initPipelineCacheVkKey()
@@ -1102,18 +1255,6 @@ angle::Result RendererVk::initPipelineCache(DisplayVk *display)
return angle::Result::Continue;
}
-void RendererVk::ensureCapsInitialized() const
-{
- if (!mCapsInitialized)
- {
- ASSERT(mCurrentQueueFamilyIndex < mQueueFamilyProperties.size());
- vk::GenerateCaps(mPhysicalDeviceProperties, mPhysicalDeviceFeatures,
- mQueueFamilyProperties[mCurrentQueueFamilyIndex], mNativeTextureCaps,
- &mNativeCaps, &mNativeExtensions, &mNativeLimitations);
- mCapsInitialized = true;
- }
-}
-
void RendererVk::getSubmitWaitSemaphores(
vk::Context *context,
angle::FixedVector<VkSemaphore, kMaxWaitSemaphores> *waitSemaphores,
@@ -1231,12 +1372,12 @@ void RendererVk::freeAllInFlightResources()
// On device loss we need to wait for fence to be signaled before destroying it
if (mDeviceLost)
{
- VkResult status = batch.fence.wait(mDevice, kMaxFenceWaitTimeNs);
+ VkResult status = batch.fence.get().wait(mDevice, kMaxFenceWaitTimeNs);
// If wait times out, it is probably not possible to recover from lost device
ASSERT(status == VK_SUCCESS || status == VK_ERROR_DEVICE_LOST);
}
- batch.fence.destroy(mDevice);
batch.commandPool.destroy(mDevice);
+ batch.fence.reset(mDevice);
}
mInFlightCommands.clear();
@@ -1255,7 +1396,7 @@ angle::Result RendererVk::checkCompletedCommands(vk::Context *context)
for (CommandBatch &batch : mInFlightCommands)
{
- VkResult result = batch.fence.getStatus(mDevice);
+ VkResult result = batch.fence.get().getStatus(mDevice);
if (result == VK_NOT_READY)
{
break;
@@ -1265,7 +1406,8 @@ angle::Result RendererVk::checkCompletedCommands(vk::Context *context)
ASSERT(batch.serial > mLastCompletedQueueSerial);
mLastCompletedQueueSerial = batch.serial;
- batch.fence.destroy(mDevice);
+ batch.fence.reset(mDevice);
+ TRACE_EVENT0("gpu.angle", "commandPool.destroy");
batch.commandPool.destroy(mDevice);
++finishedCount;
}
@@ -1293,15 +1435,12 @@ angle::Result RendererVk::submitFrame(vk::Context *context,
vk::CommandBuffer &&commandBuffer)
{
TRACE_EVENT0("gpu.angle", "RendererVk::submitFrame");
- VkFenceCreateInfo fenceInfo = {};
- fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceInfo.flags = 0;
vk::Scoped<CommandBatch> scopedBatch(mDevice);
CommandBatch &batch = scopedBatch.get();
- ANGLE_VK_TRY(context, batch.fence.init(mDevice, fenceInfo));
+ ANGLE_TRY(getSubmitFence(context, &batch.fence));
- ANGLE_VK_TRY(context, vkQueueSubmit(mQueue, 1, &submitInfo, batch.fence.getHandle()));
+ ANGLE_VK_TRY(context, vkQueueSubmit(mQueue, 1, &submitInfo, batch.fence.get().getHandle()));
// Store this command buffer in the in-flight list.
batch.commandPool = std::move(mCommandPool);
@@ -1309,10 +1448,12 @@ angle::Result RendererVk::submitFrame(vk::Context *context,
mInFlightCommands.emplace_back(scopedBatch.release());
+ // Make sure a new fence is created for the next submission.
+ mSubmitFence.reset(mDevice);
+
// CPU should be throttled to avoid mInFlightCommands from growing too fast. That is done on
// swap() though, and there could be multiple submissions in between (through glFlush() calls),
- // so the limit is larger than the expected number of images. The
- // InterleavedAttributeDataBenchmark perf test for example issues a large number of flushes.
+ // so the limit is larger than the expected number of images.
ASSERT(mInFlightCommands.size() <= kInFlightCommandsLimit);
nextSerial();
@@ -1383,7 +1524,10 @@ angle::Result RendererVk::finishToSerial(vk::Context *context, Serial serial)
const CommandBatch &batch = mInFlightCommands[batchIndex];
// Wait for it finish
- ANGLE_VK_TRY(context, batch.fence.wait(mDevice, kMaxFenceWaitTimeNs));
+ VkResult status = batch.fence.get().wait(mDevice, kMaxFenceWaitTimeNs);
+
+ // Don't tolerate timeout. If such a large wait time results in timeout, something's wrong.
+ ANGLE_VK_TRY(context, status);
// Clean up finished batches.
return checkCompletedCommands(context);
@@ -1546,6 +1690,26 @@ const vk::Semaphore *RendererVk::getSubmitLastSignaledSemaphore(vk::Context *con
return semaphore;
}
+angle::Result RendererVk::getSubmitFence(vk::Context *context,
+ vk::Shared<vk::Fence> *sharedFenceOut)
+{
+ if (!mSubmitFence.isReferenced())
+ {
+ vk::Fence fence;
+
+ VkFenceCreateInfo fenceCreateInfo = {};
+ fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceCreateInfo.flags = 0;
+
+ ANGLE_VK_TRY(context, fence.init(mDevice, fenceCreateInfo));
+
+ mSubmitFence.assign(mDevice, std::move(fence));
+ }
+
+ sharedFenceOut->copy(mDevice, mSubmitFence);
+ return angle::Result::Continue;
+}
+
angle::Result RendererVk::getTimestamp(vk::Context *context, uint64_t *timestampOut)
{
// The intent of this function is to query the timestamp without stalling the GPU. Currently,
@@ -1636,6 +1800,10 @@ angle::Result RendererVk::getTimestamp(vk::Context *context, uint64_t *timestamp
timestampQueryPool.get().freeQuery(context, &timestampQuery);
+ // Convert results to nanoseconds.
+ *timestampOut = static_cast<uint64_t>(
+ *timestampOut * static_cast<double>(mPhysicalDeviceProperties.limits.timestampPeriod));
+
return angle::Result::Continue;
}
@@ -1658,6 +1826,21 @@ bool RendererVk::hasBufferFormatFeatureBits(VkFormat format, const VkFormatFeatu
return hasFormatFeatureBits<&VkFormatProperties::bufferFeatures>(format, featureBits);
}
+void RendererVk::insertDebugMarker(GLenum source, GLuint id, std::string &&marker)
+{
+ mCommandGraph.insertDebugMarker(source, std::move(marker));
+}
+
+void RendererVk::pushDebugMarker(GLenum source, GLuint id, std::string &&marker)
+{
+ mCommandGraph.pushDebugMarker(source, std::move(marker));
+}
+
+void RendererVk::popDebugMarker()
+{
+ mCommandGraph.popDebugMarker();
+}
+
angle::Result RendererVk::synchronizeCpuGpuTime(vk::Context *context)
{
ASSERT(mGpuEventsEnabled);
@@ -1677,7 +1860,7 @@ angle::Result RendererVk::synchronizeCpuGpuTime(vk::Context *context)
//
// Post-submission work Begin execution
//
- // ???? Write timstamp Tgpu
+ // ???? Write timestamp Tgpu
//
// ???? End execution
//
@@ -1781,7 +1964,7 @@ angle::Result RendererVk::synchronizeCpuGpuTime(vk::Context *context)
ANGLE_VK_TRY(context, commandBuffer.begin(beginInfo));
- commandBuffer.setEvent(gpuReady.get(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
+ commandBuffer.setEvent(gpuReady.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
commandBuffer.waitEvents(1, cpuReady.get().ptr(), VK_PIPELINE_STAGE_HOST_BIT,
VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, nullptr, 0, nullptr, 0,
nullptr);
@@ -1792,7 +1975,7 @@ angle::Result RendererVk::synchronizeCpuGpuTime(vk::Context *context)
timestampQuery.getQueryPool()->getHandle(),
timestampQuery.getQuery());
- commandBuffer.setEvent(gpuDone.get(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
+ commandBuffer.setEvent(gpuDone.get().getHandle(), VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
ANGLE_VK_TRY(context, commandBuffer.end());
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.h
index 8bd247e7144..48a1fe5d444 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/RendererVk.h
@@ -45,7 +45,10 @@ class RendererVk : angle::NonCopyable
RendererVk();
~RendererVk();
- angle::Result initialize(DisplayVk *displayVk, egl::Display *display, const char *wsiName);
+ angle::Result initialize(DisplayVk *displayVk,
+ egl::Display *display,
+ const char *wsiExtension,
+ const char *wsiLayer);
void onDestroy(vk::Context *context);
void notifyDeviceLost();
@@ -107,6 +110,7 @@ class RendererVk : angle::NonCopyable
// mLastCompletedQueueSerial, for example for when the application busy waits on a query
// result).
angle::Result checkCompletedCommands(vk::Context *context);
+
// Wait for completion of batches until (at least) batch with given serial is finished.
angle::Result finishToSerial(vk::Context *context, Serial serial);
@@ -154,6 +158,9 @@ class RendererVk : angle::NonCopyable
// by next submission.
const vk::Semaphore *getSubmitLastSignaledSemaphore(vk::Context *context);
+ // Get (or allocate) the fence that will be signaled on next submission.
+ angle::Result getSubmitFence(vk::Context *context, vk::Shared<vk::Fence> *sharedFenceOut);
+
// This should only be called from ResourceVk.
// TODO(jmadill): Keep in ContextVk to enable threaded rendering.
vk::CommandGraph *getCommandGraph();
@@ -196,6 +203,13 @@ class RendererVk : angle::NonCopyable
bool hasTextureFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
bool hasBufferFormatFeatureBits(VkFormat format, const VkFormatFeatureFlags featureBits);
+ void insertDebugMarker(GLenum source, GLuint id, std::string &&marker);
+ void pushDebugMarker(GLenum source, GLuint id, std::string &&marker);
+ void popDebugMarker();
+
+ static constexpr size_t kMaxExtensionNames = 200;
+ using ExtensionNameList = angle::FixedVector<const char *, kMaxExtensionNames>;
+
private:
// Number of semaphores for external entities to renderer to issue a wait, such as surface's
// image acquire.
@@ -215,7 +229,7 @@ class RendererVk : angle::NonCopyable
vk::CommandBuffer &&commandBuffer);
void freeAllInFlightResources();
angle::Result flushCommandGraph(vk::Context *context, vk::CommandBuffer *commandBatch);
- void initFeatures(const std::vector<VkExtensionProperties> &deviceExtensionProps);
+ void initFeatures(const ExtensionNameList &extensions);
void initPipelineCacheVkKey();
angle::Result initPipelineCache(DisplayVk *display);
@@ -253,6 +267,7 @@ class RendererVk : angle::NonCopyable
std::vector<VkQueueFamilyProperties> mQueueFamilyProperties;
VkQueue mQueue;
uint32_t mCurrentQueueFamilyIndex;
+ uint32_t mMaxVertexAttribDivisor;
VkDevice mDevice;
vk::CommandPool mCommandPool;
SerialFactory mQueueSerialFactory;
@@ -273,7 +288,7 @@ class RendererVk : angle::NonCopyable
void destroy(VkDevice device);
vk::CommandPool commandPool;
- vk::Fence fence;
+ vk::Shared<vk::Fence> fence;
Serial serial;
};
@@ -311,6 +326,14 @@ class RendererVk : angle::NonCopyable
// A pool of semaphores used to support the aforementioned mid-frame submissions.
vk::DynamicSemaphorePool mSubmitSemaphorePool;
+ // mSubmitFence is the fence that's going to be signaled at the next submission. This is used
+ // to support SyncVk objects, which may outlive the context (as EGLSync objects).
+ //
+ // TODO(geofflang): this is in preparation for moving RendererVk functionality to ContextVk, and
+ // is otherwise unnecessary as the SyncVk objects don't actually outlive the renderer currently.
+ // http://anglebug.com/2701
+ vk::Shared<vk::Fence> mSubmitFence;
+
// See CommandGraph.h for a desription of the Command Graph.
vk::CommandGraph mCommandGraph;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp
new file mode 100644
index 00000000000..0e9725c2a05
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.cpp
@@ -0,0 +1,674 @@
+//
+// Copyright 2019 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.
+//
+// SecondaryCommandBuffer:
+// CPU-side storage of commands to delay GPU-side allocation until commands are submitted.
+//
+
+#include "libANGLE/renderer/vulkan/SecondaryCommandBuffer.h"
+#include "common/debug.h"
+
+namespace rx
+{
+namespace vk
+{
+
+// Allocate/initialize memory for the command and return pointer to Cmd Header
+template <class StructType>
+StructType *SecondaryCommandBuffer::initCommand(CommandID cmdID, size_t variableSize)
+{
+ size_t paramSize = sizeof(StructType);
+ size_t completeSize = sizeof(CommandHeader) + paramSize + variableSize;
+ CommandHeader *header = static_cast<CommandHeader *>(mAllocator->allocate(completeSize));
+ // Update cmd ID in header
+ header->id = cmdID;
+ header->next = nullptr;
+ // Update mHead ptr
+ mHead = (mHead == nullptr) ? header : mHead;
+ // Update prev cmd's "next" ptr and mLast ptr
+ if (mLast)
+ {
+ mLast->next = header;
+ }
+ // Update mLast ptr
+ mLast = header;
+
+ uint8_t *fixedParamPtr = reinterpret_cast<uint8_t *>(header) + sizeof(CommandHeader);
+ mPtrCmdData = fixedParamPtr + sizeof(StructType);
+ return reinterpret_cast<StructType *>(fixedParamPtr);
+}
+
+template <class PtrType>
+void SecondaryCommandBuffer::storePointerParameter(const PtrType *paramData,
+ const PtrType **writePtr,
+ size_t sizeInBytes)
+{
+ *writePtr = reinterpret_cast<const PtrType *>(mPtrCmdData);
+ memcpy(mPtrCmdData, paramData, sizeInBytes);
+ mPtrCmdData += sizeInBytes;
+}
+
+void SecondaryCommandBuffer::bindDescriptorSets(VkPipelineBindPoint bindPoint,
+ VkPipelineLayout layout,
+ uint32_t firstSet,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet *descriptorSets,
+ uint32_t dynamicOffsetCount,
+ const uint32_t *dynamicOffsets)
+{
+ size_t descSize = descriptorSetCount * sizeof(VkDescriptorSet);
+ size_t offsetSize = dynamicOffsetCount * sizeof(uint32_t);
+ size_t varSize = descSize + offsetSize;
+ BindDescriptorSetParams *paramStruct =
+ initCommand<BindDescriptorSetParams>(CommandID::BindDescriptorSets, varSize);
+ // Copy params into memory
+ paramStruct->bindPoint = bindPoint;
+ paramStruct->layout = layout;
+ paramStruct->firstSet = firstSet;
+ paramStruct->descriptorSetCount = descriptorSetCount;
+ paramStruct->dynamicOffsetCount = dynamicOffsetCount;
+ // Copy variable sized data
+ storePointerParameter(descriptorSets, &paramStruct->descriptorSets, descSize);
+ storePointerParameter(dynamicOffsets, &paramStruct->dynamicOffsets, offsetSize);
+}
+
+void SecondaryCommandBuffer::bindIndexBuffer(const VkBuffer &buffer,
+ VkDeviceSize offset,
+ VkIndexType indexType)
+{
+ BindIndexBufferParams *paramStruct =
+ initCommand<BindIndexBufferParams>(CommandID::BindIndexBuffer, 0);
+ paramStruct->buffer = buffer;
+ paramStruct->offset = offset;
+ paramStruct->indexType = indexType;
+}
+
+void SecondaryCommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint,
+ VkPipeline pipeline)
+{
+ BindPipelineParams *paramStruct = initCommand<BindPipelineParams>(CommandID::BindPipeline, 0);
+ paramStruct->pipelineBindPoint = pipelineBindPoint;
+ paramStruct->pipeline = pipeline;
+}
+
+void SecondaryCommandBuffer::bindVertexBuffers(uint32_t firstBinding,
+ uint32_t bindingCount,
+ const VkBuffer *buffers,
+ const VkDeviceSize *offsets)
+{
+ size_t buffSize = bindingCount * sizeof(VkBuffer);
+ size_t offsetSize = bindingCount * sizeof(VkDeviceSize);
+ BindVertexBuffersParams *paramStruct =
+ initCommand<BindVertexBuffersParams>(CommandID::BindVertexBuffers, buffSize + offsetSize);
+ // Copy params
+ paramStruct->firstBinding = firstBinding;
+ paramStruct->bindingCount = bindingCount;
+ // Copy variable sized data
+ storePointerParameter(buffers, &paramStruct->buffers, buffSize);
+ storePointerParameter(offsets, &paramStruct->offsets, offsetSize);
+}
+
+void SecondaryCommandBuffer::blitImage(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageBlit *pRegions,
+ VkFilter filter)
+{
+ size_t regionSize = regionCount * sizeof(VkImageBlit);
+ BlitImageParams *paramStruct = initCommand<BlitImageParams>(CommandID::BlitImage, regionSize);
+ paramStruct->srcImage = srcImage;
+ paramStruct->srcImageLayout = srcImageLayout;
+ paramStruct->dstImage = dstImage;
+ paramStruct->dstImageLayout = dstImageLayout;
+ paramStruct->regionCount = regionCount;
+ paramStruct->filter = filter;
+ // Copy variable sized data
+ storePointerParameter(pRegions, &paramStruct->pRegions, regionSize);
+}
+
+void SecondaryCommandBuffer::copyBuffer(const VkBuffer &srcBuffer,
+ const VkBuffer &destBuffer,
+ uint32_t regionCount,
+ const VkBufferCopy *regions)
+{
+ size_t regionSize = regionCount * sizeof(VkBufferCopy);
+ CopyBufferParams *paramStruct =
+ initCommand<CopyBufferParams>(CommandID::CopyBuffer, regionSize);
+ paramStruct->srcBuffer = srcBuffer;
+ paramStruct->destBuffer = destBuffer;
+ paramStruct->regionCount = regionCount;
+ // Copy variable sized data
+ storePointerParameter(regions, &paramStruct->regions, regionSize);
+}
+
+void SecondaryCommandBuffer::copyBufferToImage(VkBuffer srcBuffer,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy *regions)
+{
+ size_t regionSize = regionCount * sizeof(VkBufferImageCopy);
+ CopyBufferToImageParams *paramStruct =
+ initCommand<CopyBufferToImageParams>(CommandID::CopyBufferToImage, regionSize);
+ paramStruct->srcBuffer = srcBuffer;
+ paramStruct->dstImage = dstImage;
+ paramStruct->dstImageLayout = dstImageLayout;
+ paramStruct->regionCount = regionCount;
+ // Copy variable sized data
+ storePointerParameter(regions, &paramStruct->regions, regionSize);
+}
+
+void SecondaryCommandBuffer::copyImage(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageCopy *regions)
+{
+ size_t regionSize = regionCount * sizeof(VkImageCopy);
+ CopyImageParams *paramStruct = initCommand<CopyImageParams>(CommandID::CopyImage, regionSize);
+ paramStruct->srcImage = srcImage;
+ paramStruct->srcImageLayout = srcImageLayout;
+ paramStruct->dstImage = dstImage;
+ paramStruct->dstImageLayout = dstImageLayout;
+ paramStruct->regionCount = regionCount;
+ // Copy variable sized data
+ storePointerParameter(regions, &paramStruct->regions, regionSize);
+}
+
+void SecondaryCommandBuffer::copyImageToBuffer(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferImageCopy *regions)
+{
+ size_t regionSize = regionCount * sizeof(VkBufferImageCopy);
+ CopyImageToBufferParams *paramStruct =
+ initCommand<CopyImageToBufferParams>(CommandID::CopyImageToBuffer, regionSize);
+ paramStruct->srcImage = srcImage;
+ paramStruct->srcImageLayout = srcImageLayout;
+ paramStruct->dstBuffer = dstBuffer;
+ paramStruct->regionCount = regionCount;
+ // Copy variable sized data
+ storePointerParameter(regions, &paramStruct->regions, regionSize);
+}
+
+void SecondaryCommandBuffer::clearAttachments(uint32_t attachmentCount,
+ const VkClearAttachment *attachments,
+ uint32_t rectCount,
+ const VkClearRect *rects)
+{
+ size_t attachSize = attachmentCount * sizeof(VkClearAttachment);
+ size_t rectSize = rectCount * sizeof(VkClearRect);
+ ClearAttachmentsParams *paramStruct =
+ initCommand<ClearAttachmentsParams>(CommandID::ClearAttachments, attachSize + rectSize);
+ paramStruct->attachmentCount = attachmentCount;
+ paramStruct->rectCount = rectCount;
+ // Copy variable sized data
+ storePointerParameter(attachments, &paramStruct->attachments, attachSize);
+ storePointerParameter(rects, &paramStruct->rects, rectSize);
+}
+
+void SecondaryCommandBuffer::clearColorImage(VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearColorValue &color,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange *ranges)
+{
+ size_t rangeSize = rangeCount * sizeof(VkImageSubresourceRange);
+ ClearColorImageParams *paramStruct =
+ initCommand<ClearColorImageParams>(CommandID::ClearColorImage, rangeSize);
+ paramStruct->image = image;
+ paramStruct->imageLayout = imageLayout;
+ paramStruct->color = color;
+ paramStruct->rangeCount = rangeCount;
+ // Copy variable sized data
+ storePointerParameter(ranges, &paramStruct->ranges, rangeSize);
+}
+
+void SecondaryCommandBuffer::clearDepthStencilImage(VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearDepthStencilValue &depthStencil,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange *ranges)
+{
+ size_t rangeSize = rangeCount * sizeof(VkImageSubresourceRange);
+ ClearDepthStencilImageParams *paramStruct =
+ initCommand<ClearDepthStencilImageParams>(CommandID::ClearDepthStencilImage, rangeSize);
+ paramStruct->image = image;
+ paramStruct->imageLayout = imageLayout;
+ paramStruct->depthStencil = depthStencil;
+ paramStruct->rangeCount = rangeCount;
+ // Copy variable sized data
+ storePointerParameter(ranges, &paramStruct->ranges, rangeSize);
+}
+
+void SecondaryCommandBuffer::updateBuffer(VkBuffer buffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize dataSize,
+ const void *data)
+{
+ ASSERT(dataSize == static_cast<size_t>(dataSize));
+ UpdateBufferParams *paramStruct =
+ initCommand<UpdateBufferParams>(CommandID::UpdateBuffer, static_cast<size_t>(dataSize));
+ paramStruct->buffer = buffer;
+ paramStruct->dstOffset = dstOffset;
+ paramStruct->dataSize = dataSize;
+ // Copy variable sized data
+ storePointerParameter(data, &paramStruct->data, static_cast<size_t>(dataSize));
+}
+
+void SecondaryCommandBuffer::pushConstants(VkPipelineLayout layout,
+ VkShaderStageFlags flag,
+ uint32_t offset,
+ uint32_t size,
+ const void *data)
+{
+ ASSERT(size == static_cast<size_t>(size));
+ PushConstantsParams *paramStruct =
+ initCommand<PushConstantsParams>(CommandID::PushConstants, static_cast<size_t>(size));
+ paramStruct->layout = layout;
+ paramStruct->flag = flag;
+ paramStruct->offset = offset;
+ paramStruct->size = size;
+ // Copy variable sized data
+ storePointerParameter(data, &paramStruct->data, static_cast<size_t>(size));
+}
+
+void SecondaryCommandBuffer::setViewport(uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkViewport *viewports)
+{
+ size_t viewportSize = viewportCount * sizeof(VkViewport);
+ SetViewportParams *paramStruct =
+ initCommand<SetViewportParams>(CommandID::SetViewport, viewportSize);
+ paramStruct->firstViewport = firstViewport;
+ paramStruct->viewportCount = viewportCount;
+ // Copy variable sized data
+ storePointerParameter(viewports, &paramStruct->viewports, viewportSize);
+}
+
+void SecondaryCommandBuffer::setScissor(uint32_t firstScissor,
+ uint32_t scissorCount,
+ const VkRect2D *scissors)
+{
+ size_t scissorSize = scissorCount * sizeof(VkRect2D);
+ SetScissorParams *paramStruct =
+ initCommand<SetScissorParams>(CommandID::SetScissor, scissorSize);
+ paramStruct->firstScissor = firstScissor;
+ paramStruct->scissorCount = scissorCount;
+ // Copy variable sized data
+ storePointerParameter(scissors, &paramStruct->scissors, scissorSize);
+}
+
+void SecondaryCommandBuffer::draw(uint32_t vertexCount,
+ uint32_t instanceCount,
+ uint32_t firstVertex,
+ uint32_t firstInstance)
+{
+ DrawParams *paramStruct = initCommand<DrawParams>(CommandID::Draw, 0);
+ paramStruct->vertexCount = vertexCount;
+ paramStruct->instanceCount = instanceCount;
+ paramStruct->firstVertex = firstVertex;
+ paramStruct->firstInstance = firstInstance;
+}
+
+void SecondaryCommandBuffer::drawIndexed(uint32_t indexCount,
+ uint32_t instanceCount,
+ uint32_t firstIndex,
+ int32_t vertexOffset,
+ uint32_t firstInstance)
+{
+ DrawIndexedParams *paramStruct = initCommand<DrawIndexedParams>(CommandID::DrawIndexed, 0);
+ paramStruct->indexCount = indexCount;
+ paramStruct->instanceCount = instanceCount;
+ paramStruct->firstIndex = firstIndex;
+ paramStruct->vertexOffset = vertexOffset;
+ paramStruct->firstInstance = firstInstance;
+}
+
+void SecondaryCommandBuffer::dispatch(uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ)
+{
+ DispatchParams *paramStruct = initCommand<DispatchParams>(CommandID::Dispatch, 0);
+ paramStruct->groupCountX = groupCountX;
+ paramStruct->groupCountY = groupCountY;
+ paramStruct->groupCountZ = groupCountZ;
+}
+
+void SecondaryCommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ VkDependencyFlags dependencyFlags,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier *memoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *bufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *imageMemoryBarriers)
+{
+ size_t memBarrierSize = memoryBarrierCount * sizeof(VkMemoryBarrier);
+ size_t buffBarrierSize = bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier);
+ size_t imgBarrierSize = imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier);
+ PipelineBarrierParams *paramStruct = initCommand<PipelineBarrierParams>(
+ CommandID::PipelinBarrier, memBarrierSize + buffBarrierSize + imgBarrierSize);
+ paramStruct->srcStageMask = srcStageMask;
+ paramStruct->dstStageMask = dstStageMask;
+ paramStruct->memoryBarrierCount = memoryBarrierCount;
+ paramStruct->bufferMemoryBarrierCount = bufferMemoryBarrierCount;
+ paramStruct->imageMemoryBarrierCount = imageMemoryBarrierCount;
+ // Copy variable sized data
+ storePointerParameter(memoryBarriers, &paramStruct->memoryBarriers, memBarrierSize);
+ storePointerParameter(bufferMemoryBarriers, &paramStruct->bufferMemoryBarriers,
+ buffBarrierSize);
+ storePointerParameter(imageMemoryBarriers, &paramStruct->imageMemoryBarriers, imgBarrierSize);
+}
+
+void SecondaryCommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
+{
+ SetEventParams *paramStruct = initCommand<SetEventParams>(CommandID::SetEvent, 0);
+ paramStruct->event = event;
+ paramStruct->stageMask = stageMask;
+}
+
+void SecondaryCommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
+{
+ ResetEventParams *paramStruct = initCommand<ResetEventParams>(CommandID::ResetEvent, 0);
+ paramStruct->event = event;
+ paramStruct->stageMask = stageMask;
+}
+
+void SecondaryCommandBuffer::waitEvents(uint32_t eventCount,
+ const VkEvent *events,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier *memoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *bufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *imageMemoryBarriers)
+{
+ size_t eventSize = eventCount * sizeof(VkEvent);
+ size_t memBarrierSize = memoryBarrierCount * sizeof(VkMemoryBarrier);
+ size_t buffBarrierSize = bufferMemoryBarrierCount * sizeof(VkBufferMemoryBarrier);
+ size_t imgBarrierSize = imageMemoryBarrierCount * sizeof(VkImageMemoryBarrier);
+ WaitEventsParams *paramStruct = initCommand<WaitEventsParams>(
+ CommandID::WaitEvents, eventSize + memBarrierSize + buffBarrierSize + imgBarrierSize);
+ paramStruct->eventCount = eventCount;
+ paramStruct->srcStageMask = srcStageMask;
+ paramStruct->dstStageMask = dstStageMask;
+ paramStruct->memoryBarrierCount = memoryBarrierCount;
+ paramStruct->bufferMemoryBarrierCount = bufferMemoryBarrierCount;
+ paramStruct->imageMemoryBarrierCount = imageMemoryBarrierCount;
+ // Copy variable sized data
+ storePointerParameter(events, &paramStruct->events, eventSize);
+ storePointerParameter(memoryBarriers, &paramStruct->memoryBarriers, memBarrierSize);
+ storePointerParameter(bufferMemoryBarriers, &paramStruct->bufferMemoryBarriers,
+ buffBarrierSize);
+ storePointerParameter(imageMemoryBarriers, &paramStruct->imageMemoryBarriers, imgBarrierSize);
+}
+
+void SecondaryCommandBuffer::resetQueryPool(VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount)
+{
+ ResetQueryPoolParams *paramStruct =
+ initCommand<ResetQueryPoolParams>(CommandID::ResetQueryPool, 0);
+ paramStruct->queryPool = queryPool;
+ paramStruct->firstQuery = firstQuery;
+ paramStruct->queryCount = queryCount;
+}
+
+void SecondaryCommandBuffer::beginQuery(VkQueryPool queryPool,
+ uint32_t query,
+ VkQueryControlFlags flags)
+{
+ BeginQueryParams *paramStruct = initCommand<BeginQueryParams>(CommandID::BeginQuery, 0);
+ paramStruct->queryPool = queryPool;
+ paramStruct->query = query;
+ paramStruct->flags = flags;
+}
+
+void SecondaryCommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
+{
+ EndQueryParams *paramStruct = initCommand<EndQueryParams>(CommandID::EndQuery, 0);
+ paramStruct->queryPool = queryPool;
+ paramStruct->query = query;
+}
+
+void SecondaryCommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage,
+ VkQueryPool queryPool,
+ uint32_t query)
+{
+ WriteTimestampParams *paramStruct =
+ initCommand<WriteTimestampParams>(CommandID::WriteTimestamp, 0);
+ paramStruct->pipelineStage = pipelineStage;
+ paramStruct->queryPool = queryPool;
+ paramStruct->query = query;
+}
+
+// Parse the cmds in this cmd buffer into given primary cmd buffer
+void SecondaryCommandBuffer::executeCommands(VkCommandBuffer cmdBuffer)
+{
+ for (CommandHeader *currentCommand = mHead; currentCommand;
+ currentCommand = currentCommand->next)
+ {
+ switch (currentCommand->id)
+ {
+ case CommandID::BindDescriptorSets:
+ {
+ BindDescriptorSetParams *params =
+ getParamPtr<BindDescriptorSetParams>(currentCommand);
+ vkCmdBindDescriptorSets(cmdBuffer, params->bindPoint, params->layout,
+ params->firstSet, params->descriptorSetCount,
+ params->descriptorSets, params->dynamicOffsetCount,
+ params->dynamicOffsets);
+ break;
+ }
+ case CommandID::BindIndexBuffer:
+ {
+ BindIndexBufferParams *params = getParamPtr<BindIndexBufferParams>(currentCommand);
+ vkCmdBindIndexBuffer(cmdBuffer, params->buffer, params->offset, params->indexType);
+ break;
+ }
+ case CommandID::BindPipeline:
+ {
+ BindPipelineParams *params = getParamPtr<BindPipelineParams>(currentCommand);
+ vkCmdBindPipeline(cmdBuffer, params->pipelineBindPoint, params->pipeline);
+ break;
+ }
+ case CommandID::BindVertexBuffers:
+ {
+ BindVertexBuffersParams *params =
+ getParamPtr<BindVertexBuffersParams>(currentCommand);
+ vkCmdBindVertexBuffers(cmdBuffer, params->firstBinding, params->bindingCount,
+ params->buffers, params->offsets);
+ break;
+ }
+ case CommandID::BlitImage:
+ {
+ BlitImageParams *params = getParamPtr<BlitImageParams>(currentCommand);
+ vkCmdBlitImage(cmdBuffer, params->srcImage, params->srcImageLayout,
+ params->dstImage, params->dstImageLayout, params->regionCount,
+ params->pRegions, params->filter);
+ break;
+ }
+ case CommandID::CopyBuffer:
+ {
+ CopyBufferParams *params = getParamPtr<CopyBufferParams>(currentCommand);
+ vkCmdCopyBuffer(cmdBuffer, params->srcBuffer, params->destBuffer,
+ params->regionCount, params->regions);
+ break;
+ }
+ case CommandID::CopyBufferToImage:
+ {
+ CopyBufferToImageParams *params =
+ getParamPtr<CopyBufferToImageParams>(currentCommand);
+ vkCmdCopyBufferToImage(cmdBuffer, params->srcBuffer, params->dstImage,
+ params->dstImageLayout, params->regionCount,
+ params->regions);
+ break;
+ }
+ case CommandID::CopyImage:
+ {
+ CopyImageParams *params = getParamPtr<CopyImageParams>(currentCommand);
+ vkCmdCopyImage(cmdBuffer, params->srcImage, params->srcImageLayout,
+ params->dstImage, params->dstImageLayout, params->regionCount,
+ params->regions);
+ break;
+ }
+ case CommandID::CopyImageToBuffer:
+ {
+ CopyImageToBufferParams *params =
+ getParamPtr<CopyImageToBufferParams>(currentCommand);
+ vkCmdCopyImageToBuffer(cmdBuffer, params->srcImage, params->srcImageLayout,
+ params->dstBuffer, params->regionCount, params->regions);
+ break;
+ }
+ case CommandID::ClearAttachments:
+ {
+ ClearAttachmentsParams *params =
+ getParamPtr<ClearAttachmentsParams>(currentCommand);
+ vkCmdClearAttachments(cmdBuffer, params->attachmentCount, params->attachments,
+ params->rectCount, params->rects);
+ break;
+ }
+ case CommandID::ClearColorImage:
+ {
+ ClearColorImageParams *params = getParamPtr<ClearColorImageParams>(currentCommand);
+ vkCmdClearColorImage(cmdBuffer, params->image, params->imageLayout, &params->color,
+ params->rangeCount, params->ranges);
+ break;
+ }
+ case CommandID::ClearDepthStencilImage:
+ {
+ ClearDepthStencilImageParams *params =
+ getParamPtr<ClearDepthStencilImageParams>(currentCommand);
+ vkCmdClearDepthStencilImage(cmdBuffer, params->image, params->imageLayout,
+ &params->depthStencil, params->rangeCount,
+ params->ranges);
+ break;
+ }
+ case CommandID::UpdateBuffer:
+ {
+ UpdateBufferParams *params = getParamPtr<UpdateBufferParams>(currentCommand);
+ vkCmdUpdateBuffer(cmdBuffer, params->buffer, params->dstOffset, params->dataSize,
+ params->data);
+ break;
+ }
+ case CommandID::PushConstants:
+ {
+ PushConstantsParams *params = getParamPtr<PushConstantsParams>(currentCommand);
+ vkCmdPushConstants(cmdBuffer, params->layout, params->flag, params->offset,
+ params->size, params->data);
+ break;
+ }
+ case CommandID::SetViewport:
+ {
+ SetViewportParams *params = getParamPtr<SetViewportParams>(currentCommand);
+ vkCmdSetViewport(cmdBuffer, params->firstViewport, params->viewportCount,
+ params->viewports);
+ break;
+ }
+ case CommandID::SetScissor:
+ {
+ SetScissorParams *params = getParamPtr<SetScissorParams>(currentCommand);
+ vkCmdSetScissor(cmdBuffer, params->firstScissor, params->scissorCount,
+ params->scissors);
+ break;
+ }
+ case CommandID::Draw:
+ {
+ DrawParams *params = getParamPtr<DrawParams>(currentCommand);
+ vkCmdDraw(cmdBuffer, params->vertexCount, params->instanceCount,
+ params->firstVertex, params->firstInstance);
+ break;
+ }
+ case CommandID::DrawIndexed:
+ {
+ DrawIndexedParams *params = getParamPtr<DrawIndexedParams>(currentCommand);
+ vkCmdDrawIndexed(cmdBuffer, params->indexCount, params->instanceCount,
+ params->firstIndex, params->vertexOffset, params->firstInstance);
+ break;
+ }
+ case CommandID::Dispatch:
+ {
+ DispatchParams *params = getParamPtr<DispatchParams>(currentCommand);
+ vkCmdDispatch(cmdBuffer, params->groupCountX, params->groupCountY,
+ params->groupCountZ);
+ break;
+ }
+ case CommandID::PipelinBarrier:
+ {
+ PipelineBarrierParams *params = getParamPtr<PipelineBarrierParams>(currentCommand);
+ vkCmdPipelineBarrier(cmdBuffer, params->srcStageMask, params->dstStageMask,
+ params->dependencyFlags, params->memoryBarrierCount,
+ params->memoryBarriers, params->bufferMemoryBarrierCount,
+ params->bufferMemoryBarriers, params->imageMemoryBarrierCount,
+ params->imageMemoryBarriers);
+ break;
+ }
+ case CommandID::SetEvent:
+ {
+ SetEventParams *params = getParamPtr<SetEventParams>(currentCommand);
+ vkCmdSetEvent(cmdBuffer, params->event, params->stageMask);
+ break;
+ }
+ case CommandID::ResetEvent:
+ {
+ ResetEventParams *params = getParamPtr<ResetEventParams>(currentCommand);
+ vkCmdResetEvent(cmdBuffer, params->event, params->stageMask);
+ break;
+ }
+ case CommandID::WaitEvents:
+ {
+ WaitEventsParams *params = getParamPtr<WaitEventsParams>(currentCommand);
+ vkCmdWaitEvents(cmdBuffer, params->eventCount, params->events, params->srcStageMask,
+ params->dstStageMask, params->memoryBarrierCount,
+ params->memoryBarriers, params->bufferMemoryBarrierCount,
+ params->bufferMemoryBarriers, params->imageMemoryBarrierCount,
+ params->imageMemoryBarriers);
+ break;
+ }
+ case CommandID::ResetQueryPool:
+ {
+ ResetQueryPoolParams *params = getParamPtr<ResetQueryPoolParams>(currentCommand);
+ vkCmdResetQueryPool(cmdBuffer, params->queryPool, params->firstQuery,
+ params->queryCount);
+ break;
+ }
+ case CommandID::BeginQuery:
+ {
+ BeginQueryParams *params = getParamPtr<BeginQueryParams>(currentCommand);
+ vkCmdBeginQuery(cmdBuffer, params->queryPool, params->query, params->flags);
+ break;
+ }
+ case CommandID::EndQuery:
+ {
+ EndQueryParams *params = getParamPtr<EndQueryParams>(currentCommand);
+ vkCmdEndQuery(cmdBuffer, params->queryPool, params->query);
+ break;
+ }
+ case CommandID::WriteTimestamp:
+ {
+ WriteTimestampParams *params = getParamPtr<WriteTimestampParams>(currentCommand);
+ vkCmdWriteTimestamp(cmdBuffer, params->pipelineStage, params->queryPool,
+ params->query);
+ break;
+ }
+ default:
+ {
+ UNREACHABLE();
+ break;
+ }
+ }
+ }
+}
+
+} // namespace vk
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h
new file mode 100644
index 00000000000..31b3f59690d
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SecondaryCommandBuffer.h
@@ -0,0 +1,464 @@
+//
+// Copyright 2019 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.
+//
+// SecondaryCommandBuffer:
+// Lightweight, CPU-Side command buffers used to hold command state until
+// it has to be submitted to GPU.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_
+#define LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_
+
+#include <vulkan/vulkan.h>
+
+#include "common/PoolAlloc.h"
+
+namespace rx
+{
+
+namespace vk
+{
+
+enum class CommandID
+{
+ // State update cmds
+ BindDescriptorSets = 0,
+ BindIndexBuffer = 1,
+ BindPipeline = 2,
+ BindVertexBuffers = 3,
+ BlitImage = 4,
+ CopyBuffer = 5,
+ CopyBufferToImage = 6,
+ CopyImage = 7,
+ CopyImageToBuffer = 8,
+ ClearAttachments = 9,
+ ClearColorImage = 10,
+ ClearDepthStencilImage = 11,
+ UpdateBuffer = 12,
+ PushConstants = 13,
+ SetViewport = 14,
+ SetScissor = 15,
+ // Draw/dispatch cmds
+ Draw = 16,
+ DrawIndexed = 17,
+ Dispatch = 18,
+ // Sync & Query cmds
+ PipelinBarrier = 19,
+ ResetEvent = 20,
+ SetEvent = 21,
+ WaitEvents = 22,
+ ResetQueryPool = 23,
+ BeginQuery = 24,
+ EndQuery = 25,
+ WriteTimestamp = 26,
+};
+
+// Structs to encapsulate parameters for different commands
+// This makes it easy to know the size of params & to copy params
+// TODO: Could optimize the size of some of these structs through bit-packing
+// and customizing sizing based on limited parameter sets used by ANGLE
+struct BindDescriptorSetParams
+{
+ VkPipelineBindPoint bindPoint;
+ VkPipelineLayout layout;
+ uint32_t firstSet;
+ uint32_t descriptorSetCount;
+ const VkDescriptorSet *descriptorSets;
+ uint32_t dynamicOffsetCount;
+ const uint32_t *dynamicOffsets;
+};
+
+struct BindIndexBufferParams
+{
+ VkBuffer buffer;
+ VkDeviceSize offset;
+ VkIndexType indexType;
+};
+
+struct BindPipelineParams
+{
+ VkPipelineBindPoint pipelineBindPoint;
+ VkPipeline pipeline;
+};
+
+struct BindVertexBuffersParams
+{
+ uint32_t firstBinding;
+ uint32_t bindingCount;
+ const VkBuffer *buffers;
+ const VkDeviceSize *offsets;
+};
+
+struct BlitImageParams
+{
+ VkImage srcImage;
+ VkImageLayout srcImageLayout;
+ VkImage dstImage;
+ VkImageLayout dstImageLayout;
+ uint32_t regionCount;
+ const VkImageBlit *pRegions;
+ VkFilter filter;
+};
+
+struct CopyBufferParams
+{
+ VkBuffer srcBuffer;
+ VkBuffer destBuffer;
+ uint32_t regionCount;
+ const VkBufferCopy *regions;
+};
+
+struct CopyBufferToImageParams
+{
+ VkBuffer srcBuffer;
+ VkImage dstImage;
+ VkImageLayout dstImageLayout;
+ uint32_t regionCount;
+ const VkBufferImageCopy *regions;
+};
+
+struct CopyImageParams
+{
+ VkImage srcImage;
+ VkImageLayout srcImageLayout;
+ VkImage dstImage;
+ VkImageLayout dstImageLayout;
+ uint32_t regionCount;
+ const VkImageCopy *regions;
+};
+
+struct CopyImageToBufferParams
+{
+ VkImage srcImage;
+ VkImageLayout srcImageLayout;
+ VkBuffer dstBuffer;
+ uint32_t regionCount;
+ const VkBufferImageCopy *regions;
+};
+
+struct ClearAttachmentsParams
+{
+ uint32_t attachmentCount;
+ const VkClearAttachment *attachments;
+ uint32_t rectCount;
+ const VkClearRect *rects;
+};
+
+struct ClearColorImageParams
+{
+ VkImage image;
+ VkImageLayout imageLayout;
+ VkClearColorValue color;
+ uint32_t rangeCount;
+ const VkImageSubresourceRange *ranges;
+};
+
+struct ClearDepthStencilImageParams
+{
+ VkImage image;
+ VkImageLayout imageLayout;
+ VkClearDepthStencilValue depthStencil;
+ uint32_t rangeCount;
+ const VkImageSubresourceRange *ranges;
+};
+
+struct UpdateBufferParams
+{
+ VkBuffer buffer;
+ VkDeviceSize dstOffset;
+ VkDeviceSize dataSize;
+ const void *data;
+};
+
+struct PushConstantsParams
+{
+ VkPipelineLayout layout;
+ VkShaderStageFlags flag;
+ uint32_t offset;
+ uint32_t size;
+ const void *data;
+};
+
+struct SetViewportParams
+{
+ uint32_t firstViewport;
+ uint32_t viewportCount;
+ const VkViewport *viewports;
+};
+
+struct SetScissorParams
+{
+ uint32_t firstScissor;
+ uint32_t scissorCount;
+ const VkRect2D *scissors;
+};
+
+struct DrawParams
+{
+ uint32_t vertexCount;
+ uint32_t instanceCount;
+ uint32_t firstVertex;
+ uint32_t firstInstance;
+};
+
+struct DrawIndexedParams
+{
+ uint32_t indexCount;
+ uint32_t instanceCount;
+ uint32_t firstIndex;
+ int32_t vertexOffset;
+ uint32_t firstInstance;
+};
+
+struct DispatchParams
+{
+ uint32_t groupCountX;
+ uint32_t groupCountY;
+ uint32_t groupCountZ;
+};
+
+struct PipelineBarrierParams
+{
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ VkDependencyFlags dependencyFlags;
+ uint32_t memoryBarrierCount;
+ const VkMemoryBarrier *memoryBarriers;
+ uint32_t bufferMemoryBarrierCount;
+ const VkBufferMemoryBarrier *bufferMemoryBarriers;
+ uint32_t imageMemoryBarrierCount;
+ const VkImageMemoryBarrier *imageMemoryBarriers;
+};
+
+struct SetEventParams
+{
+ VkEvent event;
+ VkPipelineStageFlags stageMask;
+};
+
+struct ResetEventParams
+{
+ VkEvent event;
+ VkPipelineStageFlags stageMask;
+};
+
+struct WaitEventsParams
+{
+ uint32_t eventCount;
+ const VkEvent *events;
+ VkPipelineStageFlags srcStageMask;
+ VkPipelineStageFlags dstStageMask;
+ uint32_t memoryBarrierCount;
+ const VkMemoryBarrier *memoryBarriers;
+ uint32_t bufferMemoryBarrierCount;
+ const VkBufferMemoryBarrier *bufferMemoryBarriers;
+ uint32_t imageMemoryBarrierCount;
+ const VkImageMemoryBarrier *imageMemoryBarriers;
+};
+
+struct ResetQueryPoolParams
+{
+ VkQueryPool queryPool;
+ uint32_t firstQuery;
+ uint32_t queryCount;
+};
+
+struct BeginQueryParams
+{
+ VkQueryPool queryPool;
+ uint32_t query;
+ VkQueryControlFlags flags;
+};
+
+struct EndQueryParams
+{
+ VkQueryPool queryPool;
+ uint32_t query;
+};
+
+struct WriteTimestampParams
+{
+ VkPipelineStageFlagBits pipelineStage;
+ VkQueryPool queryPool;
+ uint32_t query;
+};
+
+// Header for every cmd in custom cmd buffer
+struct CommandHeader
+{
+ CommandID id;
+ CommandHeader *next;
+};
+
+class SecondaryCommandBuffer final : angle::NonCopyable
+{
+ public:
+ SecondaryCommandBuffer(angle::PoolAllocator *allocator)
+ : mHead(nullptr), mLast(nullptr), mAllocator(allocator)
+ {}
+ ~SecondaryCommandBuffer() {}
+
+ // Add commands
+ void bindDescriptorSets(VkPipelineBindPoint bindPoint,
+ VkPipelineLayout layout,
+ uint32_t firstSet,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet *descriptorSets,
+ uint32_t dynamicOffsetCount,
+ const uint32_t *dynamicOffsets);
+
+ void bindIndexBuffer(const VkBuffer &buffer, VkDeviceSize offset, VkIndexType indexType);
+
+ void bindPipeline(VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline);
+
+ void bindVertexBuffers(uint32_t firstBinding,
+ uint32_t bindingCount,
+ const VkBuffer *buffers,
+ const VkDeviceSize *offsets);
+
+ void blitImage(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageBlit *pRegions,
+ VkFilter filter);
+
+ void copyBuffer(const VkBuffer &srcBuffer,
+ const VkBuffer &destBuffer,
+ uint32_t regionCount,
+ const VkBufferCopy *regions);
+
+ void copyBufferToImage(VkBuffer srcBuffer,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy *regions);
+
+ void copyImage(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkImage dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageCopy *regions);
+
+ void copyImageToBuffer(VkImage srcImage,
+ VkImageLayout srcImageLayout,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferImageCopy *regions);
+
+ void clearAttachments(uint32_t attachmentCount,
+ const VkClearAttachment *attachments,
+ uint32_t rectCount,
+ const VkClearRect *rects);
+
+ void clearColorImage(VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearColorValue &color,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange *ranges);
+
+ void clearDepthStencilImage(VkImage image,
+ VkImageLayout imageLayout,
+ const VkClearDepthStencilValue &depthStencil,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange *ranges);
+
+ void updateBuffer(VkBuffer buffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize dataSize,
+ const void *data);
+
+ void pushConstants(VkPipelineLayout layout,
+ VkShaderStageFlags flag,
+ uint32_t offset,
+ uint32_t size,
+ const void *data);
+
+ void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports);
+ void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors);
+
+ void draw(uint32_t vertexCount,
+ uint32_t instanceCount,
+ uint32_t firstVertex,
+ uint32_t firstInstance);
+
+ void drawIndexed(uint32_t indexCount,
+ uint32_t instanceCount,
+ uint32_t firstIndex,
+ int32_t vertexOffset,
+ uint32_t firstInstance);
+
+ void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+
+ void pipelineBarrier(VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ VkDependencyFlags dependencyFlags,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier *memoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *bufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *imageMemoryBarriers);
+
+ void setEvent(VkEvent event, VkPipelineStageFlags stageMask);
+ void resetEvent(VkEvent event, VkPipelineStageFlags stageMask);
+ void waitEvents(uint32_t eventCount,
+ const VkEvent *events,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier *memoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *bufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *imageMemoryBarriers);
+
+ void resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
+ void beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
+ void endQuery(VkQueryPool queryPool, uint32_t query);
+ void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
+ VkQueryPool queryPool,
+ uint32_t query);
+
+ // Parse the cmds in this cmd buffer into given primary cmd buffer for execution
+ void executeCommands(VkCommandBuffer cmdBuffer);
+
+ private:
+ // Allocate and initialize memory for given commandID & variable param size
+ // returning a pointer to the start of the commands parameter data and updating
+ // mPtrCmdData to just past the fixed parameter data.
+ template <class StructType>
+ StructType *initCommand(CommandID cmdID, size_t variableSize);
+ // Return a ptr to the parameter type
+ template <class StructType>
+ StructType *getParamPtr(CommandHeader *header)
+ {
+ return reinterpret_cast<StructType *>(reinterpret_cast<char *>(header) +
+ sizeof(CommandHeader));
+ }
+ // Copy sizeInBytes data from paramData to mPtrCmdData and assign *writePtr
+ // to mPtrCmdData. Then increment mPtrCmdData by sizeInBytes.
+ // Precondition: initCommand() must have already been called on the given cmd
+ template <class PtrType>
+ void storePointerParameter(const PtrType *paramData,
+ const PtrType **writePtr,
+ size_t sizeInBytes);
+
+ // Pointer to start of cmd buffer
+ CommandHeader *mHead;
+ // Last command inserted in cmd buffer
+ CommandHeader *mLast;
+ angle::PoolAllocator *mAllocator;
+ // Ptr to write variable ptr data section of cmd into.
+ // This is set to just past fixed parameter data when initCommand() is called
+ uint8_t *mPtrCmdData;
+};
+
+} // namespace vk
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_SECONDARYCOMMANDBUFFERVK_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
index d0076ce4600..682208b8915 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.cpp
@@ -27,20 +27,24 @@ namespace
{
VkPresentModeKHR GetDesiredPresentMode(const std::vector<VkPresentModeKHR> &presentModes,
- EGLint minSwapInterval,
- EGLint maxSwapInterval)
+ EGLint interval)
{
ASSERT(!presentModes.empty());
- // Use FIFO mode for v-sync, since it throttles you to the display rate.
- //
- // However, for performance testing (for now), we want to issue draws as fast as possible so we
- // use either of the following, if available, in order specified here:
+ // If v-sync is enabled, use FIFO, which throttles you to the display rate and is guaranteed to
+ // always be supported.
+ if (interval > 0)
+ {
+ return VK_PRESENT_MODE_FIFO_KHR;
+ }
+
+ // Otherwise, choose either of the following, if available, in order specified here:
//
// - Mailbox is similar to triple-buffering.
// - Immediate is similar to single-buffering.
//
- // TODO(jmadill): Properly select present mode and re-create display if changed.
+ // If neither is supported, we fallback to FIFO.
+
bool mailboxAvailable = false;
bool immediateAvailable = false;
@@ -59,7 +63,7 @@ VkPresentModeKHR GetDesiredPresentMode(const std::vector<VkPresentModeKHR> &pres
}
}
- // Note that VK_PRESENT_MODE_FIFO_KHR is guaranteed to be available.
+ // Note again that VK_PRESENT_MODE_FIFO_KHR is guaranteed to be available.
return mailboxAvailable
? VK_PRESENT_MODE_MAILBOX_KHR
: immediateAvailable ? VK_PRESENT_MODE_IMMEDIATE_KHR : VK_PRESENT_MODE_FIFO_KHR;
@@ -75,8 +79,9 @@ constexpr VkImageUsageFlags kSurfaceVKDepthStencilImageUsageFlags =
} // namespace
OffscreenSurfaceVk::AttachmentImage::AttachmentImage()
- : renderTarget(&image, &imageView, 0, nullptr)
-{}
+{
+ renderTarget.init(&image, &imageView, 0, 0, nullptr);
+}
OffscreenSurfaceVk::AttachmentImage::~AttachmentImage() = default;
@@ -92,7 +97,8 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display
const VkImageUsageFlags usage = isDepthOrStencilFormat ? kSurfaceVKDepthStencilImageUsageFlags
: kSurfaceVKColorImageUsageFlags;
- gl::Extents extents(static_cast<int>(width), static_cast<int>(height), 1);
+ gl::Extents extents(std::max(static_cast<int>(width), 1), std::max(static_cast<int>(height), 1),
+ 1);
ANGLE_TRY(image.init(displayVk, gl::TextureType::_2D, extents, vkFormat, 1, usage, 1, 1));
VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
@@ -101,7 +107,7 @@ angle::Result OffscreenSurfaceVk::AttachmentImage::initialize(DisplayVk *display
VkImageAspectFlags aspect = vk::GetFormatAspectFlags(textureFormat);
ANGLE_TRY(image.initImageView(displayVk, gl::TextureType::_2D, aspect, gl::SwizzleState(),
- &imageView, 1));
+ &imageView, 0, 1));
return angle::Result::Continue;
}
@@ -111,7 +117,8 @@ void OffscreenSurfaceVk::AttachmentImage::destroy(const egl::Display *display)
const DisplayVk *displayVk = vk::GetImpl(display);
RendererVk *renderer = displayVk->getRenderer();
- image.release(renderer);
+ image.releaseImage(renderer);
+ image.releaseStagingBuffer(renderer);
renderer->releaseObject(renderer->getCurrentQueueSerial(), &imageView);
}
@@ -253,6 +260,11 @@ angle::Result OffscreenSurfaceVk::initializeContents(const gl::Context *context,
return angle::Result::Continue;
}
+vk::ImageHelper *OffscreenSurfaceVk::getColorAttachmentImage()
+{
+ return &mColorAttachment.image;
+}
+
WindowSurfaceVk::SwapchainImage::SwapchainImage() = default;
WindowSurfaceVk::SwapchainImage::~SwapchainImage() = default;
@@ -272,11 +284,15 @@ WindowSurfaceVk::WindowSurfaceVk(const egl::SurfaceState &surfaceState,
mInstance(VK_NULL_HANDLE),
mSwapchain(VK_NULL_HANDLE),
mSwapchainPresentMode(VK_PRESENT_MODE_FIFO_KHR),
- mColorRenderTarget(nullptr, nullptr, 0, nullptr),
- mDepthStencilRenderTarget(&mDepthStencilImage, &mDepthStencilImageView, 0, nullptr),
+ mDesiredSwapchainPresentMode(VK_PRESENT_MODE_FIFO_KHR),
+ mMinImageCount(0),
+ mPreTransform(VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR),
+ mCompositeAlpha(VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR),
mCurrentSwapchainImageIndex(0),
- mCurrentSwapSerialIndex(0)
-{}
+ mCurrentSwapHistoryIndex(0)
+{
+ mDepthStencilRenderTarget.init(&mDepthStencilImage, &mDepthStencilImageView, 0, 0, nullptr);
+}
WindowSurfaceVk::~WindowSurfaceVk()
{
@@ -290,20 +306,23 @@ void WindowSurfaceVk::destroy(const egl::Display *display)
RendererVk *renderer = displayVk->getRenderer();
VkDevice device = renderer->getDevice();
VkInstance instance = renderer->getInstance();
+ bool swapchainOutOfDate;
+ // Queueing the image for presentation ensures the image is no longer in use when
+ // we delete the window surface.
+ (void)present(displayVk, nullptr, 0, swapchainOutOfDate);
// We might not need to flush the pipe here.
(void)renderer->finish(displayVk);
- mDepthStencilImage.release(renderer);
- mDepthStencilImageView.destroy(device);
+ releaseSwapchainImages(renderer);
- for (SwapchainImage &swapchainImage : mSwapchainImages)
+ for (SwapHistory &swap : mSwapHistory)
{
- // Although we don't own the swapchain image handles, we need to keep our shutdown clean.
- swapchainImage.image.resetImageWeakReference();
- swapchainImage.image.destroy(device);
- swapchainImage.imageView.destroy(device);
- swapchainImage.framebuffer.destroy(device);
+ if (swap.swapchain != VK_NULL_HANDLE)
+ {
+ vkDestroySwapchainKHR(device, swap.swapchain, nullptr);
+ swap.swapchain = VK_NULL_HANDLE;
+ }
}
if (mSwapchain)
@@ -339,34 +358,28 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
const VkPhysicalDevice &physicalDevice = renderer->getPhysicalDevice();
- VkSurfaceCapabilitiesKHR surfaceCaps;
- ANGLE_VK_TRY(displayVk,
- vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface, &surfaceCaps));
+ ANGLE_VK_TRY(displayVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface,
+ &mSurfaceCaps));
// Adjust width and height to the swapchain if necessary.
- uint32_t width = surfaceCaps.currentExtent.width;
- uint32_t height = surfaceCaps.currentExtent.height;
+ uint32_t width = mSurfaceCaps.currentExtent.width;
+ uint32_t height = mSurfaceCaps.currentExtent.height;
// TODO(jmadill): Support devices which don't support copy. We use this for ReadPixels.
ANGLE_VK_CHECK(displayVk,
- (surfaceCaps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) != 0,
+ (mSurfaceCaps.supportedUsageFlags & kSurfaceVKColorImageUsageFlags) ==
+ kSurfaceVKColorImageUsageFlags,
VK_ERROR_INITIALIZATION_FAILED);
EGLAttrib attribWidth = mState.attributes.get(EGL_WIDTH, 0);
EGLAttrib attribHeight = mState.attributes.get(EGL_HEIGHT, 0);
- if (surfaceCaps.currentExtent.width == 0xFFFFFFFFu)
+ if (mSurfaceCaps.currentExtent.width == 0xFFFFFFFFu)
{
- ASSERT(surfaceCaps.currentExtent.height == 0xFFFFFFFFu);
+ ASSERT(mSurfaceCaps.currentExtent.height == 0xFFFFFFFFu);
- if (attribWidth == 0)
- {
- width = windowSize.width;
- }
- if (attribHeight == 0)
- {
- height = windowSize.height;
- }
+ width = (attribWidth != 0) ? static_cast<uint32_t>(attribWidth) : windowSize.width;
+ height = (attribHeight != 0) ? static_cast<uint32_t>(attribHeight) : windowSize.height;
}
gl::Extents extents(static_cast<int>(width), static_cast<int>(height), 1);
@@ -376,31 +389,19 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
&presentModeCount, nullptr));
ASSERT(presentModeCount > 0);
- std::vector<VkPresentModeKHR> presentModes(presentModeCount);
+ mPresentModes.resize(presentModeCount);
ANGLE_VK_TRY(displayVk, vkGetPhysicalDeviceSurfacePresentModesKHR(
- physicalDevice, mSurface, &presentModeCount, presentModes.data()));
-
- // Select appropriate present mode based on vsync parameter.
- // TODO(jmadill): More complete implementation, which allows for changing and more values.
- const EGLint minSwapInterval = mState.config->minSwapInterval;
- const EGLint maxSwapInterval = mState.config->maxSwapInterval;
- ASSERT(minSwapInterval == 0 || minSwapInterval == 1);
- ASSERT(maxSwapInterval == 0 || maxSwapInterval == 1);
-
- mSwapchainPresentMode = GetDesiredPresentMode(presentModes, minSwapInterval, maxSwapInterval);
+ physicalDevice, mSurface, &presentModeCount, mPresentModes.data()));
- // Determine number of swapchain images. Aim for one more than the minimum.
- uint32_t minImageCount = surfaceCaps.minImageCount + 1;
- if (surfaceCaps.maxImageCount > 0 && minImageCount > surfaceCaps.maxImageCount)
- {
- minImageCount = surfaceCaps.maxImageCount;
- }
+ // Select appropriate present mode based on vsync parameter. Default to 1 (FIFO), though it
+ // will get clamped to the min/max values specified at display creation time.
+ setSwapInterval(renderer->getFeatures().disableFifoPresentMode ? 0 : 1);
// Default to identity transform.
- VkSurfaceTransformFlagBitsKHR preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
- if ((surfaceCaps.supportedTransforms & preTransform) == 0)
+ mPreTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
+ if ((mSurfaceCaps.supportedTransforms & mPreTransform) == 0)
{
- preTransform = surfaceCaps.currentTransform;
+ mPreTransform = mSurfaceCaps.currentTransform;
}
uint32_t surfaceFormatCount = 0;
@@ -434,39 +435,91 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
ANGLE_VK_CHECK(displayVk, foundFormat, VK_ERROR_INITIALIZATION_FAILED);
}
- VkCompositeAlphaFlagBitsKHR compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
- if ((surfaceCaps.supportedCompositeAlpha & compositeAlpha) == 0)
+ mCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+ if ((mSurfaceCaps.supportedCompositeAlpha & mCompositeAlpha) == 0)
{
- compositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
+ mCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
}
- ANGLE_VK_CHECK(displayVk, (surfaceCaps.supportedCompositeAlpha & compositeAlpha) != 0,
+ ANGLE_VK_CHECK(displayVk, (mSurfaceCaps.supportedCompositeAlpha & mCompositeAlpha) != 0,
VK_ERROR_INITIALIZATION_FAILED);
+ ANGLE_TRY(recreateSwapchain(displayVk, extents, mCurrentSwapHistoryIndex));
+
+ // Get the first available swapchain iamge.
+ return nextSwapchainImage(displayVk);
+}
+
+angle::Result WindowSurfaceVk::recreateSwapchain(DisplayVk *displayVk,
+ const gl::Extents &extents,
+ uint32_t swapHistoryIndex)
+{
+ RendererVk *renderer = displayVk->getRenderer();
+ VkDevice device = renderer->getDevice();
+
+ VkSwapchainKHR oldSwapchain = mSwapchain;
+ mSwapchain = VK_NULL_HANDLE;
+
+ if (oldSwapchain)
+ {
+ // Note: the old swapchain must be destroyed regardless of whether creating the new
+ // swapchain succeeds. We can only destroy the swapchain once rendering to all its images
+ // have finished. We therefore store the handle to the swapchain being destroyed in the
+ // swap history (alongside the serial of the last submission) so it can be destroyed once we
+ // wait on that serial as part of the CPU throttling.
+ //
+ // TODO(syoussefi): the spec specifically allows multiple retired swapchains to exist:
+ //
+ // > Multiple retired swapchains can be associated with the same VkSurfaceKHR through
+ // > multiple uses of oldSwapchain that outnumber calls to vkDestroySwapchainKHR.
+ //
+ // However, a bug in the validation layers currently forces us to limit this to one retired
+ // swapchain. Once the issue is resolved, the following for loop can be removed.
+ // http://anglebug.com/3095
+ for (SwapHistory &swap : mSwapHistory)
+ {
+ if (swap.swapchain != VK_NULL_HANDLE)
+ {
+ ANGLE_TRY(renderer->finishToSerial(displayVk, swap.serial));
+ vkDestroySwapchainKHR(renderer->getDevice(), swap.swapchain, nullptr);
+ swap.swapchain = VK_NULL_HANDLE;
+ }
+ }
+ mSwapHistory[swapHistoryIndex].swapchain = oldSwapchain;
+ }
+
+ releaseSwapchainImages(renderer);
+
+ const vk::Format &format = renderer->getFormat(mState.config->renderTargetFormat);
+ VkFormat nativeFormat = format.vkTextureFormat;
+
// We need transfer src for reading back from the backbuffer.
- VkImageUsageFlags imageUsageFlags = kSurfaceVKColorImageUsageFlags;
+ constexpr VkImageUsageFlags kImageUsageFlags = kSurfaceVKColorImageUsageFlags;
VkSwapchainCreateInfoKHR swapchainInfo = {};
swapchainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainInfo.flags = 0;
swapchainInfo.surface = mSurface;
- swapchainInfo.minImageCount = minImageCount;
+ swapchainInfo.minImageCount = mMinImageCount;
swapchainInfo.imageFormat = nativeFormat;
swapchainInfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
- swapchainInfo.imageExtent.width = width;
- swapchainInfo.imageExtent.height = height;
+ // Note: Vulkan doesn't allow 0-width/height swapchains.
+ swapchainInfo.imageExtent.width = std::max(extents.width, 1);
+ swapchainInfo.imageExtent.height = std::max(extents.height, 1);
swapchainInfo.imageArrayLayers = 1;
- swapchainInfo.imageUsage = imageUsageFlags;
+ swapchainInfo.imageUsage = kImageUsageFlags;
swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
swapchainInfo.queueFamilyIndexCount = 0;
swapchainInfo.pQueueFamilyIndices = nullptr;
- swapchainInfo.preTransform = preTransform;
- swapchainInfo.compositeAlpha = compositeAlpha;
- swapchainInfo.presentMode = mSwapchainPresentMode;
+ swapchainInfo.preTransform = mPreTransform;
+ swapchainInfo.compositeAlpha = mCompositeAlpha;
+ swapchainInfo.presentMode = mDesiredSwapchainPresentMode;
swapchainInfo.clipped = VK_TRUE;
- swapchainInfo.oldSwapchain = VK_NULL_HANDLE;
+ swapchainInfo.oldSwapchain = oldSwapchain;
- VkDevice device = renderer->getDevice();
+ // TODO(syoussefi): Once EGL_SWAP_BEHAVIOR_PRESERVED_BIT is supported, the contents of the old
+ // swapchain need to carry over to the new one. http://anglebug.com/2942
ANGLE_VK_TRY(displayVk, vkCreateSwapchainKHR(device, &swapchainInfo, nullptr, &mSwapchain));
+ mSwapchainPresentMode = mDesiredSwapchainPresentMode;
// Intialize the swapchain image views.
uint32_t imageCount = 0;
@@ -483,7 +536,7 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
transparentBlack.float32[3] = 0.0f;
mSwapchainImages.resize(imageCount);
- mSwapSerials.resize(imageCount);
+ ANGLE_TRY(resizeSwapHistory(displayVk, imageCount));
for (uint32_t imageIndex = 0; imageIndex < imageCount; ++imageIndex)
{
@@ -492,7 +545,7 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
ANGLE_TRY(member.image.initImageView(displayVk, gl::TextureType::_2D,
VK_IMAGE_ASPECT_COLOR_BIT, gl::SwizzleState(),
- &member.imageView, 1));
+ &member.imageView, 0, 1));
// Allocate a command buffer for clearing our images to black.
vk::CommandBuffer *commandBuffer = nullptr;
@@ -502,9 +555,6 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
member.image.clearColor(transparentBlack, 0, 1, commandBuffer);
}
- // Get the first available swapchain iamge.
- ANGLE_TRY(nextSwapchainImage(displayVk));
-
// Initialize depth/stencil if requested.
if (mState.config->depthStencilFormat != GL_NONE)
{
@@ -526,7 +576,8 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
mDepthStencilImage.clearDepthStencil(aspect, aspect, depthStencilClearValue, commandBuffer);
ANGLE_TRY(mDepthStencilImage.initImageView(displayVk, gl::TextureType::_2D, aspect,
- gl::SwizzleState(), &mDepthStencilImageView, 1));
+ gl::SwizzleState(), &mDepthStencilImageView, 0,
+ 1));
// We will need to pass depth/stencil image views to the RenderTargetVk in the future.
}
@@ -534,6 +585,83 @@ angle::Result WindowSurfaceVk::initializeImpl(DisplayVk *displayVk)
return angle::Result::Continue;
}
+angle::Result WindowSurfaceVk::checkForOutOfDateSwapchain(DisplayVk *displayVk,
+ uint32_t swapHistoryIndex,
+ bool presentOutOfDate)
+{
+ bool swapIntervalChanged = mSwapchainPresentMode != mDesiredSwapchainPresentMode;
+
+ // Check for window resize and recreate swapchain if necessary.
+ gl::Extents currentExtents;
+ ANGLE_TRY(getCurrentWindowSize(displayVk, &currentExtents));
+
+ gl::Extents swapchainExtents(getWidth(), getHeight(), 0);
+
+ // If window size has changed, check with surface capabilities. It has been observed on
+ // Android that `getCurrentWindowSize()` returns 1920x1080 for example, while surface
+ // capabilities returns the size the surface was created with.
+ if (currentExtents != swapchainExtents)
+ {
+ const VkPhysicalDevice &physicalDevice = displayVk->getRenderer()->getPhysicalDevice();
+ ANGLE_VK_TRY(displayVk, vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, mSurface,
+ &mSurfaceCaps));
+
+ uint32_t width = mSurfaceCaps.currentExtent.width;
+ uint32_t height = mSurfaceCaps.currentExtent.height;
+
+ if (width != 0xFFFFFFFFu)
+ {
+ ASSERT(height != 0xFFFFFFFFu);
+ currentExtents.width = width;
+ currentExtents.height = height;
+ }
+ }
+
+ // If anything has changed, recreate the swapchain.
+ if (presentOutOfDate || swapIntervalChanged || currentExtents != swapchainExtents)
+ {
+ ANGLE_TRY(recreateSwapchain(displayVk, currentExtents, swapHistoryIndex));
+ }
+
+ return angle::Result::Continue;
+}
+
+void WindowSurfaceVk::releaseSwapchainImages(RendererVk *renderer)
+{
+ if (mDepthStencilImage.valid())
+ {
+ Serial depthStencilSerial = mDepthStencilImage.getStoredQueueSerial();
+ mDepthStencilImage.releaseImage(renderer);
+ mDepthStencilImage.releaseStagingBuffer(renderer);
+
+ if (mDepthStencilImageView.valid())
+ {
+ renderer->releaseObject(depthStencilSerial, &mDepthStencilImageView);
+ }
+ }
+
+ for (SwapchainImage &swapchainImage : mSwapchainImages)
+ {
+ Serial imageSerial = swapchainImage.image.getStoredQueueSerial();
+
+ // We don't own the swapchain image handles, so we just remove our reference to it.
+ swapchainImage.image.resetImageWeakReference();
+ swapchainImage.image.destroy(renderer->getDevice());
+
+ if (swapchainImage.imageView.valid())
+ {
+ renderer->releaseObject(imageSerial, &swapchainImage.imageView);
+ }
+
+ if (swapchainImage.framebuffer.valid())
+ {
+ renderer->releaseObject(imageSerial, &swapchainImage.framebuffer);
+ }
+ }
+
+ mSwapchainImages.clear();
+}
+
FramebufferImpl *WindowSurfaceVk::createDefaultFramebuffer(const gl::Context *context,
const gl::FramebufferState &state)
{
@@ -557,34 +685,39 @@ egl::Error WindowSurfaceVk::swap(const gl::Context *context)
return angle::ToEGL(result, displayVk, EGL_BAD_SURFACE);
}
-angle::Result WindowSurfaceVk::swapImpl(DisplayVk *displayVk, EGLint *rects, EGLint n_rects)
+angle::Result WindowSurfaceVk::present(DisplayVk *displayVk,
+ EGLint *rects,
+ EGLint n_rects,
+ bool &swapchainOutOfDate)
{
RendererVk *renderer = displayVk->getRenderer();
- // If the swapchain is not in mailbox mode, throttle the submissions. NOTE(syoussefi): this can
- // be done in mailbox mode too, just currently unnecessary.
- if (mSwapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR)
+ // Throttle the submissions to avoid getting too far ahead of the GPU.
{
- TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::swapImpl: Throttle CPU");
- ANGLE_TRY(renderer->finishToSerial(displayVk, mSwapSerials[mCurrentSwapSerialIndex]));
+ TRACE_EVENT0("gpu.angle", "WindowSurfaceVk::present: Throttle CPU");
+ SwapHistory &swap = mSwapHistory[mCurrentSwapHistoryIndex];
+ ANGLE_TRY(renderer->finishToSerial(displayVk, swap.serial));
+ if (swap.swapchain != VK_NULL_HANDLE)
+ {
+ vkDestroySwapchainKHR(renderer->getDevice(), swap.swapchain, nullptr);
+ swap.swapchain = VK_NULL_HANDLE;
+ }
}
- vk::CommandBuffer *swapCommands = nullptr;
- ANGLE_TRY(mSwapchainImages[mCurrentSwapchainImageIndex].image.recordCommands(displayVk,
- &swapCommands));
-
SwapchainImage &image = mSwapchainImages[mCurrentSwapchainImageIndex];
- image.image.changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, swapCommands);
+ vk::CommandBuffer *swapCommands = nullptr;
+ ANGLE_TRY(image.image.recordCommands(displayVk, &swapCommands));
+
+ image.image.changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::Present, swapCommands);
ANGLE_TRY(renderer->flush(displayVk));
// Remember the serial of the last submission.
- mSwapSerials[mCurrentSwapSerialIndex++] = renderer->getLastSubmittedQueueSerial();
- mCurrentSwapSerialIndex =
- mCurrentSwapSerialIndex == mSwapSerials.size() ? 0 : mCurrentSwapSerialIndex;
+ mSwapHistory[mCurrentSwapHistoryIndex].serial = renderer->getLastSubmittedQueueSerial();
+ ++mCurrentSwapHistoryIndex;
+ mCurrentSwapHistoryIndex =
+ mCurrentSwapHistoryIndex == mSwapHistory.size() ? 0 : mCurrentSwapHistoryIndex;
// Ask the renderer what semaphore it signaled in the last flush.
const vk::Semaphore *commandsCompleteSemaphore =
@@ -600,13 +733,14 @@ angle::Result WindowSurfaceVk::swapImpl(DisplayVk *displayVk, EGLint *rects, EGL
presentInfo.pImageIndices = &mCurrentSwapchainImageIndex;
presentInfo.pResults = nullptr;
+ VkPresentRegionKHR presentRegion = {};
VkPresentRegionsKHR presentRegions = {};
+ std::vector<VkRectLayerKHR> vk_rects;
if (renderer->getFeatures().supportsIncrementalPresent && (n_rects > 0))
{
- VkPresentRegionKHR presentRegion = {};
- std::vector<VkRectLayerKHR> vk_rects(n_rects);
EGLint *egl_rects = rects;
presentRegion.rectangleCount = n_rects;
+ vk_rects.resize(n_rects);
for (EGLint rect = 0; rect < n_rects; rect++)
{
vk_rects[rect].offset.x = *egl_rects++;
@@ -625,7 +759,28 @@ angle::Result WindowSurfaceVk::swapImpl(DisplayVk *displayVk, EGLint *rects, EGL
presentInfo.pNext = &presentRegions;
}
- ANGLE_VK_TRY(displayVk, vkQueuePresentKHR(renderer->getQueue(), &presentInfo));
+ VkResult result = vkQueuePresentKHR(renderer->getQueue(), &presentInfo);
+
+ // If SUBOPTIMAL/OUT_OF_DATE is returned, it's ok, we just need to recreate the swapchain before
+ // continuing.
+ swapchainOutOfDate = result == VK_SUBOPTIMAL_KHR || result == VK_ERROR_OUT_OF_DATE_KHR;
+ if (!swapchainOutOfDate)
+ {
+ ANGLE_VK_TRY(displayVk, result);
+ }
+
+ return angle::Result::Continue;
+}
+
+angle::Result WindowSurfaceVk::swapImpl(DisplayVk *displayVk, EGLint *rects, EGLint n_rects)
+{
+ bool swapchainOutOfDate;
+ // Save this now, since present() will increment the value.
+ size_t currentSwapHistoryIndex = mCurrentSwapHistoryIndex;
+
+ ANGLE_TRY(present(displayVk, rects, n_rects, swapchainOutOfDate));
+
+ ANGLE_TRY(checkForOutOfDateSwapchain(displayVk, currentSwapHistoryIndex, swapchainOutOfDate));
{
// Note: TRACE_EVENT0 is put here instead of inside the function to workaround this issue:
@@ -635,6 +790,7 @@ angle::Result WindowSurfaceVk::swapImpl(DisplayVk *displayVk, EGLint *rects, EGL
ANGLE_TRY(nextSwapchainImage(displayVk));
}
+ RendererVk *renderer = displayVk->getRenderer();
ANGLE_TRY(renderer->syncPipelineCacheVk(displayVk));
return angle::Result::Continue;
@@ -660,6 +816,82 @@ angle::Result WindowSurfaceVk::nextSwapchainImage(DisplayVk *displayVk)
return angle::Result::Continue;
}
+angle::Result WindowSurfaceVk::resizeSwapHistory(DisplayVk *displayVk, size_t imageCount)
+{
+ // The number of swapchain images can change if the present mode is changed. If that number is
+ // increased, we need to rearrange the history (which is a circular buffer) so it remains
+ // continuous. If it shrinks, we have to additionally make sure we clean up any old swapchains
+ // that can no longer fit in the history.
+ //
+ // Assume the following history buffer identified with serials:
+ //
+ // mCurrentSwapHistoryIndex
+ // V
+ // +----+----+----+
+ // | 11 | 9 | 10 |
+ // +----+----+----+
+ //
+ // When shrinking to size 2, we want to clean up 9, and rearrange to the following:
+ //
+ // mCurrentSwapHistoryIndex
+ // V
+ // +----+----+
+ // | 10 | 11 |
+ // +----+----+
+ //
+ // When expanding back to 3, we want to rearrange to the following:
+ //
+ // mCurrentSwapHistoryIndex
+ // V
+ // +----+----+----+
+ // | 0 | 10 | 11 |
+ // +----+----+----+
+
+ if (mSwapHistory.size() == imageCount)
+ {
+ return angle::Result::Continue;
+ }
+
+ RendererVk *renderer = displayVk->getRenderer();
+
+ // First, clean up anything that won't fit in the resized history.
+ if (imageCount < mSwapHistory.size())
+ {
+ size_t toClean = mSwapHistory.size() - imageCount;
+ for (size_t i = 0; i < toClean; ++i)
+ {
+ size_t historyIndex = (mCurrentSwapHistoryIndex + i) % mSwapHistory.size();
+ SwapHistory &swap = mSwapHistory[historyIndex];
+
+ ANGLE_TRY(renderer->finishToSerial(displayVk, swap.serial));
+ if (swap.swapchain != VK_NULL_HANDLE)
+ {
+ vkDestroySwapchainKHR(renderer->getDevice(), swap.swapchain, nullptr);
+ swap.swapchain = VK_NULL_HANDLE;
+ }
+ }
+ }
+
+ // Now, move the history, from most recent to oldest (as much as fits), into a new vector.
+ std::vector<SwapHistory> resizedHistory(imageCount);
+
+ size_t toCopy = std::min(imageCount, mSwapHistory.size());
+ for (size_t i = 0; i < toCopy; ++i)
+ {
+ size_t historyIndex =
+ (mCurrentSwapHistoryIndex + mSwapHistory.size() - i - 1) % mSwapHistory.size();
+ size_t resizedHistoryIndex = imageCount - i - 1;
+ resizedHistory[resizedHistoryIndex] = mSwapHistory[historyIndex];
+ }
+
+ // Set this as the new history. Note that after rearranging in either case, the oldest history
+ // is at index 0.
+ mSwapHistory = std::move(resizedHistory);
+ mCurrentSwapHistoryIndex = 0;
+
+ return angle::Result::Continue;
+}
+
egl::Error WindowSurfaceVk::postSubBuffer(const gl::Context *context,
EGLint x,
EGLint y,
@@ -696,7 +928,45 @@ egl::Error WindowSurfaceVk::getSyncValues(EGLuint64KHR * /*ust*/,
return egl::EglBadAccess();
}
-void WindowSurfaceVk::setSwapInterval(EGLint interval) {}
+void WindowSurfaceVk::setSwapInterval(EGLint interval)
+{
+ const EGLint minSwapInterval = mState.config->minSwapInterval;
+ const EGLint maxSwapInterval = mState.config->maxSwapInterval;
+ ASSERT(minSwapInterval == 0 || minSwapInterval == 1);
+ ASSERT(maxSwapInterval == 0 || maxSwapInterval == 1);
+
+ interval = gl::clamp(interval, minSwapInterval, maxSwapInterval);
+
+ mDesiredSwapchainPresentMode = GetDesiredPresentMode(mPresentModes, interval);
+
+ // Determine the number of swapchain images:
+ //
+ // - On mailbox, we use minImageCount. The drivers may increase the number so that non-blocking
+ // mailbox actually makes sense.
+ // - On immediate, we use max(2, minImageCount). The vkQueuePresentKHR call immediately frees
+ // up the other image, so there is no point in having any more images.
+ // - On fifo, we use max(3, minImageCount). Triple-buffering allows us to present an image,
+ // have one in the queue and record in another. Note: on certain configurations (windows +
+ // nvidia + windowed mode), we could get away with a smaller number.
+ mMinImageCount = mSurfaceCaps.minImageCount;
+ if (mDesiredSwapchainPresentMode == VK_PRESENT_MODE_IMMEDIATE_KHR)
+ {
+ mMinImageCount = std::max(2u, mMinImageCount);
+ }
+ else if (mDesiredSwapchainPresentMode == VK_PRESENT_MODE_FIFO_KHR)
+ {
+ mMinImageCount = std::max(3u, mMinImageCount);
+ }
+
+ // Make sure we don't exceed maxImageCount.
+ if (mSurfaceCaps.maxImageCount > 0 && mMinImageCount > mSurfaceCaps.maxImageCount)
+ {
+ mMinImageCount = mSurfaceCaps.maxImageCount;
+ }
+
+ // On the next swap, if the desired present mode is different from the current one, the
+ // swapchain will be recreated.
+}
EGLint WindowSurfaceVk::getWidth() const
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h
index aa67aacca6c..6038b69a3f5 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SurfaceVk.h
@@ -60,6 +60,8 @@ class OffscreenSurfaceVk : public SurfaceImpl
angle::Result initializeContents(const gl::Context *context,
const gl::ImageIndex &imageIndex) override;
+ vk::ImageHelper *getColorAttachmentImage();
+
private:
struct AttachmentImage final : angle::NonCopyable
{
@@ -141,12 +143,34 @@ class WindowSurfaceVk : public SurfaceImpl
private:
virtual angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) = 0;
+ virtual angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) = 0;
+
angle::Result initializeImpl(DisplayVk *displayVk);
+ angle::Result recreateSwapchain(DisplayVk *displayVk,
+ const gl::Extents &extents,
+ uint32_t swapHistoryIndex);
+ angle::Result checkForOutOfDateSwapchain(DisplayVk *displayVk,
+ uint32_t swapHistoryIndex,
+ bool presentOutOfDate);
+ void releaseSwapchainImages(RendererVk *renderer);
angle::Result nextSwapchainImage(DisplayVk *displayVk);
+ angle::Result present(DisplayVk *displayVk,
+ EGLint *rects,
+ EGLint n_rects,
+ bool &swapchainOutOfDate);
angle::Result swapImpl(DisplayVk *displayVk, EGLint *rects, EGLint n_rects);
+ angle::Result resizeSwapHistory(DisplayVk *displayVk, size_t imageCount);
+
+ VkSurfaceCapabilitiesKHR mSurfaceCaps;
+ std::vector<VkPresentModeKHR> mPresentModes;
VkSwapchainKHR mSwapchain;
- VkPresentModeKHR mSwapchainPresentMode;
+ // Cached information used to recreate swapchains.
+ VkPresentModeKHR mSwapchainPresentMode; // Current swapchain mode
+ VkPresentModeKHR mDesiredSwapchainPresentMode; // Desired mode set through setSwapInterval()
+ uint32_t mMinImageCount;
+ VkSurfaceTransformFlagBitsKHR mPreTransform;
+ VkCompositeAlphaFlagBitsKHR mCompositeAlpha;
RenderTargetVk mColorRenderTarget;
RenderTargetVk mDepthStencilRenderTarget;
@@ -167,10 +191,15 @@ class WindowSurfaceVk : public SurfaceImpl
std::vector<SwapchainImage> mSwapchainImages;
// A circular buffer, with the same size as mSwapchainImages (N), that stores the serial of the
- // renderer on every swap. In FIFO present modes, the CPU is throttled by waiting for the
- // Nth previous serial to finish.
- std::vector<Serial> mSwapSerials;
- size_t mCurrentSwapSerialIndex;
+ // renderer on every swap. The CPU is throttled by waiting for the Nth previous serial to
+ // finish. Old swapchains are scheduled to be destroyed at the same time.
+ struct SwapHistory
+ {
+ Serial serial;
+ VkSwapchainKHR swapchain = VK_NULL_HANDLE;
+ };
+ std::vector<SwapHistory> mSwapHistory;
+ size_t mCurrentSwapHistoryIndex;
vk::ImageHelper mDepthStencilImage;
vk::ImageView mDepthStencilImageView;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.cpp
index 0091f255ba2..b248ffbcb6e 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.cpp
@@ -11,20 +11,122 @@
#include "common/debug.h"
#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
-#include "libANGLE/renderer/vulkan/vk_utils.h"
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
namespace rx
{
+FenceSyncVk::FenceSyncVk() {}
+
+FenceSyncVk::~FenceSyncVk() {}
+
+void FenceSyncVk::onDestroy(RendererVk *renderer)
+{
+ if (mEvent.valid())
+ {
+ renderer->releaseObject(renderer->getCurrentQueueSerial(), &mEvent);
+ }
+
+ mFence.reset(renderer->getDevice());
+}
+
+angle::Result FenceSyncVk::initialize(vk::Context *context)
+{
+ ASSERT(!mEvent.valid());
+
+ RendererVk *renderer = context->getRenderer();
+ VkDevice device = renderer->getDevice();
+
+ VkEventCreateInfo eventCreateInfo = {};
+ eventCreateInfo.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
+ eventCreateInfo.flags = 0;
+
+ vk::Scoped<vk::Event> event(device);
+ ANGLE_VK_TRY(context, event.get().init(device, eventCreateInfo));
+
+ ANGLE_TRY(renderer->getSubmitFence(context, &mFence));
+
+ mEvent = event.release();
+
+ renderer->getCommandGraph()->setFenceSync(mEvent);
+ return angle::Result::Continue;
+}
+
+angle::Result FenceSyncVk::clientWait(vk::Context *context,
+ bool flushCommands,
+ uint64_t timeout,
+ VkResult *outResult)
+{
+ RendererVk *renderer = context->getRenderer();
+
+ // If the event is already set, don't wait
+ bool alreadySignaled = false;
+ ANGLE_TRY(getStatus(context, &alreadySignaled));
+ if (alreadySignaled)
+ {
+ *outResult = VK_EVENT_SET;
+ return angle::Result::Continue;
+ }
+
+ // If timeout is zero, there's no need to wait, so return timeout already.
+ if (timeout == 0)
+ {
+ *outResult = VK_TIMEOUT;
+ return angle::Result::Continue;
+ }
+
+ if (flushCommands)
+ {
+ ANGLE_TRY(renderer->flush(context));
+ }
+
+ // Wait on the fence that's expected to be signaled on the first vkQueueSubmit after
+ // `initialize` was called.
+ VkResult status = mFence.get().wait(renderer->getDevice(), timeout);
+
+ // Check for errors, but don't consider timeout as such.
+ if (status != VK_TIMEOUT)
+ {
+ ANGLE_VK_TRY(context, status);
+ }
+
+ *outResult = status;
+ return angle::Result::Continue;
+}
+
+angle::Result FenceSyncVk::serverWait(vk::Context *context)
+{
+ context->getRenderer()->getCommandGraph()->waitFenceSync(mEvent);
+ return angle::Result::Continue;
+}
+
+angle::Result FenceSyncVk::getStatus(vk::Context *context, bool *signaled)
+{
+ VkResult result = mEvent.getStatus(context->getRenderer()->getDevice());
+ if (result != VK_EVENT_SET && result != VK_EVENT_RESET)
+ {
+ ANGLE_VK_TRY(context, result);
+ }
+ *signaled = result == VK_EVENT_SET;
+ return angle::Result::Continue;
+}
SyncVk::SyncVk() : SyncImpl() {}
SyncVk::~SyncVk() {}
+void SyncVk::onDestroy(const gl::Context *context)
+{
+ mFenceSync.onDestroy(vk::GetImpl(context)->getRenderer());
+}
+
angle::Result SyncVk::set(const gl::Context *context, GLenum condition, GLbitfield flags)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ ASSERT(condition == GL_SYNC_GPU_COMMANDS_COMPLETE);
+ ASSERT(flags == 0);
+
+ return mFenceSync.initialize(vk::GetImpl(context));
}
angle::Result SyncVk::clientWait(const gl::Context *context,
@@ -32,20 +134,133 @@ angle::Result SyncVk::clientWait(const gl::Context *context,
GLuint64 timeout,
GLenum *outResult)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ ContextVk *contextVk = vk::GetImpl(context);
+
+ ASSERT((flags & ~GL_SYNC_FLUSH_COMMANDS_BIT) == 0);
+
+ bool flush = (flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0;
+ VkResult result;
+
+ ANGLE_TRY(mFenceSync.clientWait(contextVk, flush, static_cast<uint64_t>(timeout), &result));
+
+ switch (result)
+ {
+ case VK_EVENT_SET:
+ *outResult = GL_ALREADY_SIGNALED;
+ return angle::Result::Continue;
+
+ case VK_SUCCESS:
+ *outResult = GL_CONDITION_SATISFIED;
+ return angle::Result::Continue;
+
+ case VK_TIMEOUT:
+ *outResult = GL_TIMEOUT_EXPIRED;
+ return angle::Result::Incomplete;
+
+ default:
+ UNREACHABLE();
+ *outResult = GL_WAIT_FAILED;
+ return angle::Result::Stop;
+ }
}
angle::Result SyncVk::serverWait(const gl::Context *context, GLbitfield flags, GLuint64 timeout)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ ASSERT(flags == 0);
+ ASSERT(timeout == GL_TIMEOUT_IGNORED);
+
+ return mFenceSync.serverWait(vk::GetImpl(context));
}
angle::Result SyncVk::getStatus(const gl::Context *context, GLint *outResult)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ bool signaled = false;
+ ANGLE_TRY(mFenceSync.getStatus(vk::GetImpl(context), &signaled));
+
+ *outResult = signaled ? GL_SIGNALED : GL_UNSIGNALED;
+ return angle::Result::Continue;
+}
+
+EGLSyncVk::EGLSyncVk(const egl::AttributeMap &attribs) : EGLSyncImpl()
+{
+ ASSERT(attribs.isEmpty());
+}
+
+EGLSyncVk::~EGLSyncVk() {}
+
+void EGLSyncVk::onDestroy(const egl::Display *display)
+{
+ mFenceSync.onDestroy(vk::GetImpl(display)->getRenderer());
+}
+
+egl::Error EGLSyncVk::initialize(const egl::Display *display, EGLenum type)
+{
+ ASSERT(type == EGL_SYNC_FENCE_KHR);
+
+ if (mFenceSync.initialize(vk::GetImpl(display)) == angle::Result::Stop)
+ {
+ return egl::Error(EGL_BAD_ALLOC, "eglCreateSyncKHR failed to create sync object");
+ }
+
+ return egl::NoError();
+}
+
+egl::Error EGLSyncVk::clientWait(const egl::Display *display,
+ EGLint flags,
+ EGLTime timeout,
+ EGLint *outResult)
+{
+ ASSERT((flags & ~EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) == 0);
+
+ bool flush = (flags & EGL_SYNC_FLUSH_COMMANDS_BIT_KHR) != 0;
+ VkResult result;
+
+ if (mFenceSync.clientWait(vk::GetImpl(display), flush, static_cast<uint64_t>(timeout),
+ &result) == angle::Result::Stop)
+ {
+ return egl::Error(EGL_BAD_ALLOC);
+ }
+
+ switch (result)
+ {
+ case VK_EVENT_SET:
+ // fall through. EGL doesn't differentiate between event being already set, or set
+ // before timeout.
+ case VK_SUCCESS:
+ *outResult = EGL_CONDITION_SATISFIED_KHR;
+ return egl::NoError();
+
+ case VK_TIMEOUT:
+ *outResult = EGL_TIMEOUT_EXPIRED_KHR;
+ return egl::NoError();
+
+ default:
+ UNREACHABLE();
+ *outResult = EGL_FALSE;
+ return egl::Error(EGL_BAD_ALLOC);
+ }
+}
+
+egl::Error EGLSyncVk::serverWait(const egl::Display *display, EGLint flags)
+{
+ ASSERT(flags == 0);
+ if (mFenceSync.serverWait(vk::GetImpl(display)) == angle::Result::Stop)
+ {
+ return egl::Error(EGL_BAD_ALLOC);
+ }
+ return egl::NoError();
+}
+
+egl::Error EGLSyncVk::getStatus(const egl::Display *display, EGLint *outStatus)
+{
+ bool signaled = false;
+ if (mFenceSync.getStatus(vk::GetImpl(display), &signaled) == angle::Result::Stop)
+ {
+ return egl::Error(EGL_BAD_ALLOC);
+ }
+
+ *outStatus = signaled ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
+ return egl::NoError();
}
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.h
index 01a9eca542b..79ff9bd1b63 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/SyncVk.h
@@ -10,16 +10,53 @@
#ifndef LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_
#define LIBANGLE_RENDERER_VULKAN_FENCESYNCVK_H_
+#include "libANGLE/renderer/EGLSyncImpl.h"
#include "libANGLE/renderer/SyncImpl.h"
+#include "libANGLE/renderer/vulkan/vk_utils.h"
+
+namespace egl
+{
+class AttributeMap;
+}
+
namespace rx
{
-class SyncVk : public SyncImpl
+// The behaviors of SyncImpl and EGLSyncImpl as fence syncs (only supported type) are currently
+// identical for the Vulkan backend, and this class implements both interfaces.
+class FenceSyncVk
+{
+ public:
+ FenceSyncVk();
+ ~FenceSyncVk();
+
+ void onDestroy(RendererVk *renderer);
+
+ angle::Result initialize(vk::Context *context);
+ angle::Result clientWait(vk::Context *context,
+ bool flushCommands,
+ uint64_t timeout,
+ VkResult *outResult);
+ angle::Result serverWait(vk::Context *context);
+ angle::Result getStatus(vk::Context *context, bool *signaled);
+
+ private:
+ // The vkEvent that's signaled on `init` and can be waited on in `serverWait`, or queried with
+ // `getStatus`.
+ vk::Event mEvent;
+ // The vkFence that's signaled once the command buffer including the `init` signal is executed.
+ // `clientWait` waits on this fence.
+ vk::Shared<vk::Fence> mFence;
+};
+
+class SyncVk final : public SyncImpl
{
public:
SyncVk();
~SyncVk() override;
+ void onDestroy(const gl::Context *context) override;
+
angle::Result set(const gl::Context *context, GLenum condition, GLbitfield flags) override;
angle::Result clientWait(const gl::Context *context,
GLbitfield flags,
@@ -29,6 +66,29 @@ class SyncVk : public SyncImpl
GLbitfield flags,
GLuint64 timeout) override;
angle::Result getStatus(const gl::Context *context, GLint *outResult) override;
+
+ private:
+ FenceSyncVk mFenceSync;
+};
+
+class EGLSyncVk final : public EGLSyncImpl
+{
+ public:
+ EGLSyncVk(const egl::AttributeMap &attribs);
+ ~EGLSyncVk() override;
+
+ void onDestroy(const egl::Display *display) override;
+
+ egl::Error initialize(const egl::Display *display, EGLenum type) override;
+ egl::Error clientWait(const egl::Display *display,
+ EGLint flags,
+ EGLTime timeout,
+ EGLint *outResult) override;
+ egl::Error serverWait(const egl::Display *display, EGLint flags) override;
+ egl::Error getStatus(const egl::Display *display, EGLint *outStatus) override;
+
+ private:
+ FenceSyncVk mFenceSync;
};
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
index 20476461212..329ce9df8fd 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.cpp
@@ -11,26 +11,44 @@
#include "common/debug.h"
#include "image_util/generatemip.inl"
+#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
+#include "libANGLE/Image.h"
+#include "libANGLE/Surface.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
+#include "libANGLE/renderer/vulkan/ImageVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/SurfaceVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
+#include "third_party/trace_event/trace_event.h"
namespace rx
{
namespace
{
-constexpr VkBufferUsageFlags kStagingBufferFlags =
- VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
-constexpr size_t kStagingBufferSize = 1024 * 16;
-
-constexpr VkImageUsageFlags kStagingImageFlags =
+constexpr VkImageUsageFlags kDrawStagingImageFlags =
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+constexpr VkImageUsageFlags kTransferStagingImageFlags =
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+
constexpr VkFormatFeatureFlags kBlitFeatureFlags =
VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT;
+bool CanCopyWithTransfer(RendererVk *renderer,
+ const vk::Format &srcFormat,
+ const vk::Format &destFormat)
+{
+ // NOTE(syoussefi): technically, you can transfer between formats as long as they have the same
+ // size and are compatible, but for now, let's just support same-format copies with transfer.
+ return srcFormat.internalFormat == destFormat.internalFormat &&
+ renderer->hasTextureFormatFeatureBits(srcFormat.vkTextureFormat,
+ VK_FORMAT_FEATURE_TRANSFER_SRC_BIT) &&
+ renderer->hasTextureFormatFeatureBits(destFormat.vkTextureFormat,
+ VK_FORMAT_FEATURE_TRANSFER_DST_BIT);
+}
+
bool CanCopyWithDraw(RendererVk *renderer,
const vk::Format &srcFormat,
const vk::Format &destFormat)
@@ -73,359 +91,6 @@ gl::TextureType Get2DTextureType(uint32_t layerCount, GLint samples)
}
} // anonymous namespace
-// StagingStorage implementation.
-PixelBuffer::PixelBuffer(RendererVk *renderer)
- : mStagingBuffer(kStagingBufferFlags, kStagingBufferSize, true)
-{
- // vkCmdCopyBufferToImage must have an offset that is a multiple of 4.
- // https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkBufferImageCopy.html
- mStagingBuffer.init(4, renderer);
-}
-
-PixelBuffer::~PixelBuffer() {}
-
-void PixelBuffer::release(RendererVk *renderer)
-{
- // Remove updates that never made it to the texture.
- for (SubresourceUpdate &update : mSubresourceUpdates)
- {
- update.release(renderer);
- }
- mStagingBuffer.release(renderer);
- mSubresourceUpdates.clear();
-}
-
-void PixelBuffer::removeStagedUpdates(RendererVk *renderer, const gl::ImageIndex &index)
-{
- // Find any staged updates for this index and removes them from the pending list.
- uint32_t levelIndex = index.getLevelIndex();
- uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
-
- for (size_t index = 0; index < mSubresourceUpdates.size();)
- {
- auto update = mSubresourceUpdates.begin() + index;
- if (update->isUpdateToLayerLevel(layerIndex, levelIndex))
- {
- update->release(renderer);
- mSubresourceUpdates.erase(update);
- }
- else
- {
- index++;
- }
- }
-}
-
-angle::Result PixelBuffer::stageSubresourceUpdate(ContextVk *contextVk,
- const gl::ImageIndex &index,
- const gl::Extents &extents,
- const gl::Offset &offset,
- const gl::InternalFormat &formatInfo,
- const gl::PixelUnpackState &unpack,
- GLenum type,
- const uint8_t *pixels)
-{
- GLuint inputRowPitch = 0;
- ANGLE_VK_CHECK_MATH(contextVk, formatInfo.computeRowPitch(type, extents.width, unpack.alignment,
- unpack.rowLength, &inputRowPitch));
-
- GLuint inputDepthPitch = 0;
- ANGLE_VK_CHECK_MATH(contextVk, formatInfo.computeDepthPitch(extents.height, unpack.imageHeight,
- inputRowPitch, &inputDepthPitch));
-
- // TODO(jmadill): skip images for 3D Textures.
- bool applySkipImages = false;
-
- GLuint inputSkipBytes = 0;
- ANGLE_VK_CHECK_MATH(contextVk,
- formatInfo.computeSkipBytes(type, inputRowPitch, inputDepthPitch, unpack,
- applySkipImages, &inputSkipBytes));
-
- RendererVk *renderer = contextVk->getRenderer();
-
- const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);
- const angle::Format &storageFormat = vkFormat.textureFormat();
-
- size_t outputRowPitch = storageFormat.pixelBytes * extents.width;
- size_t outputDepthPitch = outputRowPitch * extents.height;
-
- VkBuffer bufferHandle = VK_NULL_HANDLE;
-
- uint8_t *stagingPointer = nullptr;
- VkDeviceSize stagingOffset = 0;
- size_t allocationSize = outputDepthPitch * extents.depth;
- ANGLE_TRY(mStagingBuffer.allocate(contextVk, allocationSize, &stagingPointer, &bufferHandle,
- &stagingOffset, nullptr));
-
- const uint8_t *source = pixels + inputSkipBytes;
-
- LoadImageFunctionInfo loadFunction = vkFormat.textureLoadFunctions(type);
-
- loadFunction.loadFunction(extents.width, extents.height, extents.depth, source, inputRowPitch,
- inputDepthPitch, stagingPointer, outputRowPitch, outputDepthPitch);
-
- VkBufferImageCopy copy = {};
-
- copy.bufferOffset = stagingOffset;
- copy.bufferRowLength = extents.width;
- copy.bufferImageHeight = extents.height;
- copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copy.imageSubresource.mipLevel = index.getLevelIndex();
- copy.imageSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
- copy.imageSubresource.layerCount = index.getLayerCount();
-
- gl_vk::GetOffset(offset, &copy.imageOffset);
- gl_vk::GetExtent(extents, &copy.imageExtent);
-
- mSubresourceUpdates.emplace_back(bufferHandle, copy);
-
- return angle::Result::Continue;
-}
-
-angle::Result PixelBuffer::stageSubresourceUpdateFromFramebuffer(
- const gl::Context *context,
- const gl::ImageIndex &index,
- const gl::Rectangle &sourceArea,
- const gl::Offset &dstOffset,
- const gl::Extents &dstExtent,
- const gl::InternalFormat &formatInfo,
- FramebufferVk *framebufferVk)
-{
- ContextVk *contextVk = vk::GetImpl(context);
-
- // If the extents and offset is outside the source image, we need to clip.
- gl::Rectangle clippedRectangle;
- const gl::Extents readExtents = framebufferVk->getReadImageExtents();
- if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, readExtents.width, readExtents.height),
- &clippedRectangle))
- {
- // Empty source area, nothing to do.
- return angle::Result::Continue;
- }
-
- bool isViewportFlipEnabled = contextVk->isViewportFlipEnabledForDrawFBO();
- if (isViewportFlipEnabled)
- {
- clippedRectangle.y = readExtents.height - clippedRectangle.y - clippedRectangle.height;
- }
-
- // 1- obtain a buffer handle to copy to
- RendererVk *renderer = contextVk->getRenderer();
-
- const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);
- const angle::Format &storageFormat = vkFormat.textureFormat();
- LoadImageFunctionInfo loadFunction = vkFormat.textureLoadFunctions(formatInfo.type);
-
- size_t outputRowPitch = storageFormat.pixelBytes * clippedRectangle.width;
- size_t outputDepthPitch = outputRowPitch * clippedRectangle.height;
-
- VkBuffer bufferHandle = VK_NULL_HANDLE;
-
- uint8_t *stagingPointer = nullptr;
- VkDeviceSize stagingOffset = 0;
-
- // The destination is only one layer deep.
- size_t allocationSize = outputDepthPitch;
- ANGLE_TRY(mStagingBuffer.allocate(contextVk, allocationSize, &stagingPointer, &bufferHandle,
- &stagingOffset, nullptr));
-
- const angle::Format &copyFormat =
- GetFormatFromFormatType(formatInfo.internalFormat, formatInfo.type);
- PackPixelsParams params(clippedRectangle, copyFormat, static_cast<GLuint>(outputRowPitch),
- isViewportFlipEnabled, nullptr, 0);
-
- // 2- copy the source image region to the pixel buffer using a cpu readback
- if (loadFunction.requiresConversion)
- {
- // When a conversion is required, we need to use the loadFunction to read from a temporary
- // buffer instead so its an even slower path.
- size_t bufferSize =
- storageFormat.pixelBytes * clippedRectangle.width * clippedRectangle.height;
- angle::MemoryBuffer *memoryBuffer = nullptr;
- ANGLE_VK_CHECK_ALLOC(contextVk, context->getScratchBuffer(bufferSize, &memoryBuffer));
-
- // Read into the scratch buffer
- ANGLE_TRY(framebufferVk->readPixelsImpl(
- contextVk, clippedRectangle, params, VK_IMAGE_ASPECT_COLOR_BIT,
- framebufferVk->getColorReadRenderTarget(), memoryBuffer->data()));
-
- // Load from scratch buffer to our pixel buffer
- loadFunction.loadFunction(clippedRectangle.width, clippedRectangle.height, 1,
- memoryBuffer->data(), outputRowPitch, 0, stagingPointer,
- outputRowPitch, 0);
- }
- else
- {
- // We read directly from the framebuffer into our pixel buffer.
- ANGLE_TRY(framebufferVk->readPixelsImpl(
- contextVk, clippedRectangle, params, VK_IMAGE_ASPECT_COLOR_BIT,
- framebufferVk->getColorReadRenderTarget(), stagingPointer));
- }
-
- // 3- enqueue the destination image subresource update
- VkBufferImageCopy copyToImage = {};
- copyToImage.bufferOffset = static_cast<VkDeviceSize>(stagingOffset);
- copyToImage.bufferRowLength = 0; // Tightly packed data can be specified as 0.
- copyToImage.bufferImageHeight = clippedRectangle.height;
- copyToImage.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copyToImage.imageSubresource.mipLevel = index.getLevelIndex();
- copyToImage.imageSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
- copyToImage.imageSubresource.layerCount = index.getLayerCount();
- gl_vk::GetOffset(dstOffset, &copyToImage.imageOffset);
- gl_vk::GetExtent(dstExtent, &copyToImage.imageExtent);
-
- // 3- enqueue the destination image subresource update
- mSubresourceUpdates.emplace_back(bufferHandle, copyToImage);
- return angle::Result::Continue;
-}
-
-void PixelBuffer::stageSubresourceUpdateFromImage(vk::ImageHelper *image,
- const gl::ImageIndex &index,
- const gl::Offset &destOffset,
- const gl::Extents &extents)
-{
- VkImageCopy copyToImage = {};
- copyToImage.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copyToImage.srcSubresource.layerCount = index.getLayerCount();
- copyToImage.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copyToImage.dstSubresource.mipLevel = index.getLevelIndex();
- copyToImage.dstSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
- copyToImage.dstSubresource.layerCount = index.getLayerCount();
- gl_vk::GetOffset(destOffset, &copyToImage.dstOffset);
- gl_vk::GetExtent(extents, &copyToImage.extent);
-
- mSubresourceUpdates.emplace_back(image, copyToImage);
-}
-
-angle::Result PixelBuffer::allocate(ContextVk *contextVk,
- size_t sizeInBytes,
- uint8_t **ptrOut,
- VkBuffer *handleOut,
- VkDeviceSize *offsetOut,
- bool *newBufferAllocatedOut)
-{
- return mStagingBuffer.allocate(contextVk, sizeInBytes, ptrOut, handleOut, offsetOut,
- newBufferAllocatedOut);
-}
-
-angle::Result PixelBuffer::flushUpdatesToImage(ContextVk *contextVk,
- uint32_t levelCount,
- vk::ImageHelper *image,
- vk::CommandBuffer *commandBuffer)
-{
- if (mSubresourceUpdates.empty())
- {
- return angle::Result::Continue;
- }
-
- RendererVk *renderer = contextVk->getRenderer();
-
- ANGLE_TRY(mStagingBuffer.flush(contextVk));
-
- std::vector<SubresourceUpdate> updatesToKeep;
-
- for (SubresourceUpdate &update : mSubresourceUpdates)
- {
- ASSERT((update.updateSource == SubresourceUpdate::UpdateSource::Buffer &&
- update.buffer.bufferHandle != VK_NULL_HANDLE) ||
- (update.updateSource == SubresourceUpdate::UpdateSource::Image &&
- update.image.image != nullptr && update.image.image->valid()));
-
- const uint32_t updateMipLevel = update.dstSubresource().mipLevel;
-
- // It's possible we've accumulated updates that are no longer applicable if the image has
- // never been flushed but the image description has changed. Check if this level exist for
- // this image.
- if (updateMipLevel >= levelCount)
- {
- updatesToKeep.emplace_back(update);
- continue;
- }
-
- // Conservatively flush all writes to the image. We could use a more restricted barrier.
- // Do not move this above the for loop, otherwise multiple updates can have race conditions
- // and not be applied correctly as seen in:
- // dEQP-gles2.functional_texture_specification_texsubimage2d_align_2d* tests on Windows AMD
- image->changeLayoutWithStages(
- VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
-
- if (update.updateSource == SubresourceUpdate::UpdateSource::Buffer)
- {
- commandBuffer->copyBufferToImage(update.buffer.bufferHandle, image->getImage(),
- image->getCurrentLayout(), 1,
- &update.buffer.copyRegion);
- }
- else
- {
- // Note: currently, the staging images are only made through color attachment writes. If
- // they were written to otherwise in the future, the src stage of this transition should
- // be adjusted appropriately.
- update.image.image->changeLayoutWithStages(
- VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
- commandBuffer);
-
- update.image.image->addReadDependency(image);
-
- commandBuffer->copyImage(update.image.image->getImage(),
- update.image.image->getCurrentLayout(), image->getImage(),
- image->getCurrentLayout(), 1, &update.image.copyRegion);
- }
-
- update.release(renderer);
- }
-
- // Only remove the updates that were actually applied to the image.
- mSubresourceUpdates = std::move(updatesToKeep);
-
- if (mSubresourceUpdates.empty())
- {
- mStagingBuffer.releaseRetainedBuffers(contextVk->getRenderer());
- }
- else
- {
- WARN() << "Internal Vulkan buffer could not be released. This is likely due to having "
- "extra images defined in the Texture.";
- }
-
- return angle::Result::Continue;
-}
-
-bool PixelBuffer::empty() const
-{
- return mSubresourceUpdates.empty();
-}
-
-angle::Result PixelBuffer::stageSubresourceUpdateAndGetData(ContextVk *contextVk,
- size_t allocationSize,
- const gl::ImageIndex &imageIndex,
- const gl::Extents &extents,
- const gl::Offset &offset,
- uint8_t **destData)
-{
- VkBuffer bufferHandle;
- VkDeviceSize stagingOffset = 0;
- ANGLE_TRY(mStagingBuffer.allocate(contextVk, allocationSize, destData, &bufferHandle,
- &stagingOffset, nullptr));
-
- VkBufferImageCopy copy = {};
- copy.bufferOffset = stagingOffset;
- copy.bufferRowLength = extents.width;
- copy.bufferImageHeight = extents.height;
- copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
- copy.imageSubresource.mipLevel = imageIndex.getLevelIndex();
- copy.imageSubresource.baseArrayLayer = imageIndex.hasLayer() ? imageIndex.getLayerIndex() : 0;
- copy.imageSubresource.layerCount = imageIndex.getLayerCount();
-
- gl_vk::GetOffset(offset, &copy.imageOffset);
- gl_vk::GetExtent(extents, &copy.imageExtent);
-
- mSubresourceUpdates.emplace_back(bufferHandle, copy);
-
- return angle::Result::Continue;
-}
-
angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
const angle::Format &sourceFormat,
GLuint layer,
@@ -454,7 +119,7 @@ angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
size_t mipAllocationSize = destRowPitch * mipHeight;
gl::Extents mipLevelExtents(static_cast<int>(mipWidth), static_cast<int>(mipHeight), 1);
- ANGLE_TRY(mPixelBuffer.stageSubresourceUpdateAndGetData(
+ ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
contextVk, mipAllocationSize,
gl::ImageIndex::MakeFromType(mState.getType(), currentMipLevel, layer), mipLevelExtents,
gl::Offset(), &destData));
@@ -474,54 +139,9 @@ angle::Result TextureVk::generateMipmapLevelsWithCPU(ContextVk *contextVk,
return angle::Result::Continue;
}
-PixelBuffer::SubresourceUpdate::SubresourceUpdate()
- : updateSource(UpdateSource::Buffer), buffer{VK_NULL_HANDLE}
-{}
-
-PixelBuffer::SubresourceUpdate::SubresourceUpdate(VkBuffer bufferHandleIn,
- const VkBufferImageCopy &copyRegionIn)
- : updateSource(UpdateSource::Buffer), buffer{bufferHandleIn, copyRegionIn}
-{}
-
-PixelBuffer::SubresourceUpdate::SubresourceUpdate(vk::ImageHelper *imageIn,
- const VkImageCopy &copyRegionIn)
- : updateSource(UpdateSource::Image), image{imageIn, copyRegionIn}
-{}
-
-PixelBuffer::SubresourceUpdate::SubresourceUpdate(const SubresourceUpdate &other)
- : updateSource(other.updateSource)
-{
- if (updateSource == UpdateSource::Buffer)
- {
- buffer = other.buffer;
- }
- else
- {
- image = other.image;
- }
-}
-
-void PixelBuffer::SubresourceUpdate::release(RendererVk *renderer)
-{
- if (updateSource == UpdateSource::Image)
- {
- image.image->release(renderer);
- SafeDelete(image.image);
- }
-}
-
-bool PixelBuffer::SubresourceUpdate::isUpdateToLayerLevel(uint32_t layerIndex,
- uint32_t levelIndex) const
-{
- const VkImageSubresourceLayers &dst = dstSubresource();
- return dst.baseArrayLayer == layerIndex && dst.mipLevel == levelIndex;
-}
-
// TextureVk implementation.
TextureVk::TextureVk(const gl::TextureState &state, RendererVk *renderer)
- : TextureImpl(state),
- mRenderTarget(&mImage, &mDrawBaseLevelImageView, 0, this),
- mPixelBuffer(renderer)
+ : TextureImpl(state), mOwnsImage(false), mImage(nullptr)
{}
TextureVk::~TextureVk() = default;
@@ -531,10 +151,8 @@ void TextureVk::onDestroy(const gl::Context *context)
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
- releaseImage(context, renderer);
+ releaseAndDeleteImage(context, renderer);
renderer->releaseObject(renderer->getCurrentQueueSerial(), &mSampler);
-
- mPixelBuffer.release(renderer);
}
angle::Result TextureVk::setImage(const gl::Context *context,
@@ -546,31 +164,9 @@ angle::Result TextureVk::setImage(const gl::Context *context,
const gl::PixelUnpackState &unpack,
const uint8_t *pixels)
{
- ContextVk *contextVk = vk::GetImpl(context);
- RendererVk *renderer = contextVk->getRenderer();
-
- // Convert internalFormat to sized internal format.
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat, type);
- ANGLE_TRY(redefineImage(context, index, formatInfo, size));
-
- // Early-out on empty textures, don't create a zero-sized storage.
- if (size.empty())
- {
- return angle::Result::Continue;
- }
-
- // Create a new graph node to store image initialization commands.
- mImage.finishCurrentCommands(renderer);
-
- // Handle initial data.
- if (pixels)
- {
- ANGLE_TRY(mPixelBuffer.stageSubresourceUpdate(contextVk, index, size, gl::Offset(),
- formatInfo, unpack, type, pixels));
- }
-
- return angle::Result::Continue;
+ return setImageImpl(context, index, formatInfo, size, type, unpack, pixels);
}
angle::Result TextureVk::setSubImage(const gl::Context *context,
@@ -582,16 +178,9 @@ angle::Result TextureVk::setSubImage(const gl::Context *context,
gl::Buffer *unpackBuffer,
const uint8_t *pixels)
{
- ContextVk *contextVk = vk::GetImpl(context);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, type);
- ANGLE_TRY(mPixelBuffer.stageSubresourceUpdate(
- contextVk, index, gl::Extents(area.width, area.height, area.depth),
- gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels));
-
- // Create a new graph node to store image initialization commands.
- mImage.finishCurrentCommands(contextVk->getRenderer());
- return angle::Result::Continue;
+ return setSubImageImpl(context, index, area, formatInfo, type, unpack, pixels);
}
angle::Result TextureVk::setCompressedImage(const gl::Context *context,
@@ -602,8 +191,9 @@ angle::Result TextureVk::setCompressedImage(const gl::Context *context,
size_t imageSize,
const uint8_t *pixels)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalFormat);
+
+ return setImageImpl(context, index, formatInfo, size, GL_UNSIGNED_BYTE, unpack, pixels);
}
angle::Result TextureVk::setCompressedSubImage(const gl::Context *context,
@@ -614,8 +204,58 @@ angle::Result TextureVk::setCompressedSubImage(const gl::Context *context,
size_t imageSize,
const uint8_t *pixels)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format, GL_UNSIGNED_BYTE);
+
+ return setSubImageImpl(context, index, area, formatInfo, GL_UNSIGNED_BYTE, unpack, pixels);
+}
+
+angle::Result TextureVk::setImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::InternalFormat &formatInfo,
+ const gl::Extents &size,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ ContextVk *contextVk = vk::GetImpl(context);
+ RendererVk *renderer = contextVk->getRenderer();
+
+ const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);
+
+ ANGLE_TRY(redefineImage(context, index, vkFormat, size));
+
+ // Early-out on empty textures, don't create a zero-sized storage.
+ if (size.empty())
+ {
+ return angle::Result::Continue;
+ }
+
+ return setSubImageImpl(context, index, gl::Box(0, 0, 0, size.width, size.height, size.depth),
+ formatInfo, type, unpack, pixels);
+}
+
+angle::Result TextureVk::setSubImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ const gl::InternalFormat &formatInfo,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels)
+{
+ ContextVk *contextVk = vk::GetImpl(context);
+
+ if (pixels)
+ {
+ ANGLE_TRY(mImage->stageSubresourceUpdate(
+ contextVk, getNativeImageIndex(index), gl::Extents(area.width, area.height, area.depth),
+ gl::Offset(area.x, area.y, area.z), formatInfo, unpack, type, pixels));
+
+ // Create a new graph node to store image initialization commands.
+ mImage->finishCurrentCommands(contextVk->getRenderer());
+ }
+
+ return angle::Result::Continue;
}
angle::Result TextureVk::copyImage(const gl::Context *context,
@@ -624,10 +264,14 @@ angle::Result TextureVk::copyImage(const gl::Context *context,
GLenum internalFormat,
gl::Framebuffer *source)
{
+ RendererVk *renderer = vk::GetImpl(context)->getRenderer();
+
gl::Extents newImageSize(sourceArea.width, sourceArea.height, 1);
const gl::InternalFormat &internalFormatInfo =
gl::GetInternalFormatInfo(internalFormat, GL_UNSIGNED_BYTE);
- ANGLE_TRY(redefineImage(context, index, internalFormatInfo, newImageSize));
+ const vk::Format &vkFormat = renderer->getFormat(internalFormatInfo.sizedInternalFormat);
+
+ ANGLE_TRY(redefineImage(context, index, vkFormat, newImageSize));
return copySubImageImpl(context, index, gl::Offset(0, 0, 0), sourceArea, internalFormatInfo,
source);
}
@@ -652,14 +296,17 @@ angle::Result TextureVk::copyTexture(const gl::Context *context,
bool unpackUnmultiplyAlpha,
const gl::Texture *source)
{
+ RendererVk *renderer = vk::GetImpl(context)->getRenderer();
+
TextureVk *sourceVk = vk::GetImpl(source);
const gl::ImageDesc &sourceImageDesc =
sourceVk->mState.getImageDesc(NonCubeTextureTypeToTarget(source->getType()), sourceLevel);
gl::Rectangle sourceArea(0, 0, sourceImageDesc.size.width, sourceImageDesc.size.height);
const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(internalFormat, type);
+ const vk::Format &destVkFormat = renderer->getFormat(destFormatInfo.sizedInternalFormat);
- ANGLE_TRY(redefineImage(context, index, destFormatInfo, sourceImageDesc.size));
+ ANGLE_TRY(redefineImage(context, index, destVkFormat, sourceImageDesc.size));
return copySubTextureImpl(vk::GetImpl(context), index, gl::kOffsetZero, destFormatInfo,
sourceLevel, sourceArea, unpackFlipY, unpackPremultiplyAlpha,
@@ -684,6 +331,32 @@ angle::Result TextureVk::copySubTexture(const gl::Context *context,
unpackUnmultiplyAlpha, vk::GetImpl(source));
}
+angle::Result TextureVk::copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source)
+{
+ ContextVk *contextVk = vk::GetImpl(context);
+ TextureVk *sourceVk = vk::GetImpl(source);
+
+ gl::TextureTarget sourceTarget = NonCubeTextureTypeToTarget(source->getType());
+ constexpr GLint sourceLevel = 0;
+ constexpr GLint destLevel = 0;
+
+ const gl::InternalFormat &internalFormat = *source->getFormat(sourceTarget, sourceLevel).info;
+ const vk::Format &vkFormat =
+ contextVk->getRenderer()->getFormat(internalFormat.sizedInternalFormat);
+ const gl::Extents size(static_cast<int>(source->getWidth(sourceTarget, sourceLevel)),
+ static_cast<int>(source->getHeight(sourceTarget, sourceLevel)), 1);
+ const gl::ImageIndex destIndex = gl::ImageIndex::MakeFromTarget(sourceTarget, destLevel);
+
+ ANGLE_TRY(redefineImage(context, destIndex, vkFormat, size));
+
+ ANGLE_TRY(sourceVk->ensureImageInitialized(contextVk));
+
+ return copySubImageImplWithTransfer(contextVk, destIndex, gl::Offset(0, 0, 0), vkFormat,
+ sourceLevel, gl::Rectangle(0, 0, size.width, size.height),
+ &sourceVk->getImage());
+}
+
angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
const gl::ImageIndex &index,
const gl::Offset &destOffset,
@@ -706,37 +379,47 @@ angle::Result TextureVk::copySubImageImpl(const gl::Context *context,
RendererVk *renderer = contextVk->getRenderer();
FramebufferVk *framebufferVk = vk::GetImpl(source);
+ const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);
const gl::Offset modifiedDestOffset(destOffset.x, destOffset.y, 0);
const vk::Format &srcFormat = framebufferVk->getColorReadRenderTarget()->getImageFormat();
const vk::Format &destFormat = renderer->getFormat(internalFormat.sizedInternalFormat);
- bool forceCpuPath = ForceCpuPathForCopy(renderer, &mImage);
+ bool isViewportFlipY = contextVk->isViewportFlipEnabledForDrawFBO();
+
+ // If it's possible to perform the copy with a transfer, that's the best option.
+ if (!isViewportFlipY && CanCopyWithTransfer(renderer, srcFormat, destFormat))
+ {
+ RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
+
+ return copySubImageImplWithTransfer(contextVk, offsetImageIndex, modifiedDestOffset,
+ destFormat, 0, clippedSourceArea,
+ &colorReadRT->getImage());
+ }
+
+ bool forceCpuPath = ForceCpuPathForCopy(renderer, mImage);
// If it's possible to perform the copy with a draw call, do that.
if (CanCopyWithDraw(renderer, srcFormat, destFormat) && !forceCpuPath)
{
RenderTargetVk *colorReadRT = framebufferVk->getColorReadRenderTarget();
- bool isViewportFlipY = contextVk->isViewportFlipEnabledForDrawFBO();
// Layer count can only be 1 as the source is a framebuffer.
- ASSERT(index.getLayerCount() == 1);
+ ASSERT(offsetImageIndex.getLayerCount() == 1);
- ANGLE_TRY(copySubImageImplWithDraw(
- contextVk, index, modifiedDestOffset, destFormat, 0, clippedSourceArea, isViewportFlipY,
- false, false, false, &colorReadRT->getImage(), colorReadRT->getReadImageView()));
-
- return angle::Result::Continue;
+ return copySubImageImplWithDraw(contextVk, offsetImageIndex, modifiedDestOffset, destFormat,
+ 0, clippedSourceArea, isViewportFlipY, false, false, false,
+ &colorReadRT->getImage(), colorReadRT->getReadImageView());
}
// Do a CPU readback that does the conversion, and then stage the change to the pixel buffer.
- ANGLE_TRY(mPixelBuffer.stageSubresourceUpdateFromFramebuffer(
- context, index, clippedSourceArea, modifiedDestOffset,
+ ANGLE_TRY(mImage->stageSubresourceUpdateFromFramebuffer(
+ context, offsetImageIndex, clippedSourceArea, modifiedDestOffset,
gl::Extents(clippedSourceArea.width, clippedSourceArea.height, 1), internalFormat,
framebufferVk));
- mImage.finishCurrentCommands(renderer);
- framebufferVk->getFramebuffer()->addReadDependency(&mImage);
+ mImage->finishCurrentCommands(renderer);
+ framebufferVk->getFramebuffer()->addReadDependency(mImage);
return angle::Result::Continue;
}
@@ -758,17 +441,25 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
const vk::Format &sourceVkFormat = source->getImage().getFormat();
const vk::Format &destVkFormat = renderer->getFormat(destFormat.sizedInternalFormat);
- bool forceCpuPath = ForceCpuPathForCopy(renderer, &mImage);
+ const gl::ImageIndex offsetImageIndex = getNativeImageIndex(index);
+
+ // If it's possible to perform the copy with a transfer, that's the best option.
+ if (!unpackFlipY && !unpackPremultiplyAlpha && !unpackUnmultiplyAlpha &&
+ CanCopyWithTransfer(renderer, sourceVkFormat, destVkFormat))
+ {
+ return copySubImageImplWithTransfer(contextVk, offsetImageIndex, destOffset, destVkFormat,
+ sourceLevel, sourceArea, &source->getImage());
+ }
+
+ bool forceCpuPath = ForceCpuPathForCopy(renderer, mImage);
// If it's possible to perform the copy with a draw call, do that.
if (CanCopyWithDraw(renderer, sourceVkFormat, destVkFormat) && !forceCpuPath)
{
- ANGLE_TRY(copySubImageImplWithDraw(contextVk, index, destOffset, destVkFormat, sourceLevel,
- sourceArea, false, unpackFlipY, unpackPremultiplyAlpha,
- unpackUnmultiplyAlpha, &source->getImage(),
- &source->getReadImageView()));
-
- return angle::Result::Continue;
+ return copySubImageImplWithDraw(contextVk, offsetImageIndex, destOffset, destVkFormat,
+ sourceLevel, sourceArea, false, unpackFlipY,
+ unpackPremultiplyAlpha, unpackUnmultiplyAlpha,
+ &source->getImage(), &source->getReadImageView());
}
if (sourceLevel != 0)
@@ -788,8 +479,8 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
// Allocate memory in the destination texture for the copy/conversion
uint8_t *destData = nullptr;
- ANGLE_TRY(mPixelBuffer.stageSubresourceUpdateAndGetData(
- contextVk, destinationAllocationSize, index,
+ ANGLE_TRY(mImage->stageSubresourceUpdateAndGetData(
+ contextVk, destinationAllocationSize, offsetImageIndex,
gl::Extents(sourceArea.width, sourceArea.height, 1), destOffset, &destData));
// Source and dest data is tightly packed
@@ -818,7 +509,95 @@ angle::Result TextureVk::copySubTextureImpl(ContextVk *contextVk,
unpackUnmultiplyAlpha);
// Create a new graph node to store image initialization commands.
- mImage.finishCurrentCommands(contextVk->getRenderer());
+ mImage->finishCurrentCommands(contextVk->getRenderer());
+
+ return angle::Result::Continue;
+}
+
+angle::Result TextureVk::copySubImageImplWithTransfer(ContextVk *contextVk,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const vk::Format &destFormat,
+ size_t sourceLevel,
+ const gl::Rectangle &sourceArea,
+ vk::ImageHelper *srcImage)
+{
+ RendererVk *renderer = contextVk->getRenderer();
+
+ uint32_t level = index.getLevelIndex();
+ uint32_t baseLayer = index.hasLayer() ? index.getLayerIndex() : 0;
+ uint32_t layerCount = index.getLayerCount();
+ gl::Offset srcOffset = {sourceArea.x, sourceArea.y, 0};
+ gl::Extents extents = {sourceArea.width, sourceArea.height, 1};
+
+ // Change source layout if necessary
+ if (srcImage->isLayoutChangeNecessary(vk::ImageLayout::TransferSrc))
+ {
+ vk::CommandBuffer *srcLayoutChange;
+ ANGLE_TRY(srcImage->recordCommands(contextVk, &srcLayoutChange));
+ srcImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc,
+ srcLayoutChange);
+ }
+
+ VkImageSubresourceLayers srcSubresource = {};
+ srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ srcSubresource.mipLevel = sourceLevel;
+ srcSubresource.baseArrayLayer = 0;
+ srcSubresource.layerCount = layerCount;
+
+ // If destination is valid, copy the source directly into it.
+ if (mImage->valid())
+ {
+ // Make sure any updates to the image are already flushed.
+ ANGLE_TRY(ensureImageInitialized(contextVk));
+
+ vk::CommandBuffer *commandBuffer;
+ ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
+
+ // Change the image layout before the transfer
+ mImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst,
+ commandBuffer);
+
+ // Source's layout change should happen before the copy
+ srcImage->addReadDependency(mImage);
+
+ VkImageSubresourceLayers destSubresource = srcSubresource;
+ destSubresource.mipLevel = level;
+ destSubresource.baseArrayLayer = baseLayer;
+
+ vk::ImageHelper::Copy(srcImage, mImage, srcOffset, destOffset, extents, srcSubresource,
+ destSubresource, commandBuffer);
+ }
+ else
+ {
+ std::unique_ptr<vk::ImageHelper> stagingImage;
+
+ // Create a temporary image to stage the copy
+ stagingImage = std::make_unique<vk::ImageHelper>();
+
+ ANGLE_TRY(stagingImage->init2DStaging(contextVk, renderer->getMemoryProperties(),
+ gl::Extents(sourceArea.width, sourceArea.height, 1),
+ destFormat, kTransferStagingImageFlags, layerCount));
+
+ vk::CommandBuffer *commandBuffer;
+ ANGLE_TRY(stagingImage->recordCommands(contextVk, &commandBuffer));
+
+ // Change the image layout before the transfer
+ stagingImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst,
+ commandBuffer);
+
+ // Source's layout change should happen before the copy
+ srcImage->addReadDependency(stagingImage.get());
+
+ VkImageSubresourceLayers destSubresource = srcSubresource;
+ destSubresource.mipLevel = 0;
+
+ vk::ImageHelper::Copy(srcImage, stagingImage.get(), srcOffset, gl::Offset(), extents,
+ srcSubresource, destSubresource, commandBuffer);
+
+ // Stage the copy for when the image storage is actually created.
+ mImage->stageSubresourceUpdateFromImage(stagingImage.release(), index, destOffset, extents);
+ }
return angle::Result::Continue;
}
@@ -859,7 +638,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
uint32_t layerCount = index.getLayerCount();
// If destination is valid, copy the source directly into it.
- if (mImage.valid())
+ if (mImage->valid())
{
// Make sure any updates to the image are already flushed.
ANGLE_TRY(ensureImageInitialized(contextVk));
@@ -872,7 +651,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
ANGLE_TRY(
getLayerLevelDrawImageView(contextVk, baseLayer + layerIndex, level, &destView));
- ANGLE_TRY(utilsVk.copyImage(contextVk, &mImage, destView, srcImage, srcView, params));
+ ANGLE_TRY(utilsVk.copyImage(contextVk, mImage, destView, srcImage, srcView, params));
}
}
else
@@ -887,7 +666,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
ANGLE_TRY(stagingImage->init2DStaging(contextVk, renderer->getMemoryProperties(),
gl::Extents(sourceArea.width, sourceArea.height, 1),
- destFormat, kStagingImageFlags, layerCount));
+ destFormat, kDrawStagingImageFlags, layerCount));
params.destOffset[0] = 0;
params.destOffset[1] = 0;
@@ -911,7 +690,7 @@ angle::Result TextureVk::copySubImageImplWithDraw(ContextVk *contextVk,
}
// Stage the copy for when the image storage is actually created.
- mPixelBuffer.stageSubresourceUpdateFromImage(
+ mImage->stageSubresourceUpdateFromImage(
stagingImage.release(), index, destOffset,
gl::Extents(sourceArea.width, sourceArea.height, 1));
}
@@ -925,15 +704,23 @@ angle::Result TextureVk::setStorage(const gl::Context *context,
GLenum internalFormat,
const gl::Extents &size)
{
- ContextVk *contextVk = GetAs<ContextVk>(context->getImplementation());
- RendererVk *renderer = contextVk->getRenderer();
- const vk::Format &format = renderer->getFormat(internalFormat);
+ ContextVk *contextVk = GetAs<ContextVk>(context->getImplementation());
+ RendererVk *renderer = contextVk->getRenderer();
+
+ if (!mOwnsImage)
+ {
+ releaseAndDeleteImage(context, renderer);
+ }
+
+ const vk::Format &format = renderer->getFormat(internalFormat);
+ ANGLE_TRY(ensureImageAllocated(renderer, format));
+
vk::CommandBuffer *commandBuffer = nullptr;
- ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer));
+ ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
- if (mImage.valid())
+ if (mImage->valid())
{
- releaseImage(context, renderer);
+ releaseImage(renderer);
}
ANGLE_TRY(initImage(contextVk, format, size, static_cast<uint32_t>(levels), commandBuffer));
@@ -944,8 +731,31 @@ angle::Result TextureVk::setEGLImageTarget(const gl::Context *context,
gl::TextureType type,
egl::Image *image)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ ContextVk *contextVk = vk::GetImpl(context);
+ RendererVk *renderer = contextVk->getRenderer();
+
+ releaseAndDeleteImage(context, renderer);
+
+ const vk::Format &format = renderer->getFormat(image->getFormat().info->sizedInternalFormat);
+
+ ImageVk *imageVk = vk::GetImpl(image);
+ setImageHelper(renderer, imageVk->getImage(), imageVk->getImageTextureType(), format,
+ imageVk->getImageLevel(), imageVk->getImageLayer(), false);
+
+ ANGLE_TRY(initImageViews(contextVk, format, 1));
+
+ // Transfer the image to this queue if needed
+ uint32_t rendererQueueFamilyIndex = renderer->getQueueFamilyIndex();
+ if (mImage->isQueueChangeNeccesary(rendererQueueFamilyIndex))
+ {
+ vk::CommandBuffer *commandBuffer = nullptr;
+ ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
+ mImage->changeLayoutAndQueue(VK_IMAGE_ASPECT_COLOR_BIT,
+ vk::ImageLayout::FragmentShaderReadOnly,
+ rendererQueueFamilyIndex, commandBuffer);
+ }
+
+ return angle::Result::Continue;
}
angle::Result TextureVk::setImageExternal(const gl::Context *context,
@@ -957,31 +767,126 @@ angle::Result TextureVk::setImageExternal(const gl::Context *context,
return angle::Result::Stop;
}
+gl::ImageIndex TextureVk::getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const
+{
+ // The input index can be a specific layer (for cube maps, 2d arrays, etc) or mImageLayerOffset
+ // can be non-zero but both of these cannot be true at the same time. EGL images can source
+ // from a cube map or 3D texture but can only be a 2D destination.
+ ASSERT(!(inputImageIndex.hasLayer() && mImageLayerOffset > 0));
+
+ // handle the special-case where image index can represent a whole level of a texture
+ GLint resultImageLayer = inputImageIndex.getLayerIndex();
+ if (inputImageIndex.getType() != mImageNativeType)
+ {
+ ASSERT(!inputImageIndex.hasLayer());
+ resultImageLayer = mImageLayerOffset;
+ }
+
+ return gl::ImageIndex::MakeFromType(mImageNativeType,
+ getNativeImageLevel(inputImageIndex.getLevelIndex()),
+ resultImageLayer, inputImageIndex.getLayerCount());
+}
+
+uint32_t TextureVk::getNativeImageLevel(uint32_t frontendLevel) const
+{
+ return mImageLevelOffset + frontendLevel;
+}
+
+uint32_t TextureVk::getNativeImageLayer(uint32_t frontendLayer) const
+{
+ return mImageLayerOffset + frontendLayer;
+}
+
+void TextureVk::releaseAndDeleteImage(const gl::Context *context, RendererVk *renderer)
+{
+ if (mImage)
+ {
+ releaseImage(renderer);
+ releaseStagingBuffer(renderer);
+ SafeDelete(mImage);
+ }
+}
+
+angle::Result TextureVk::ensureImageAllocated(RendererVk *renderer, const vk::Format &format)
+{
+ if (mImage == nullptr)
+ {
+ setImageHelper(renderer, new vk::ImageHelper(), mState.getType(), format, 0, 0, true);
+ }
+ else
+ {
+ updateImageHelper(renderer, format);
+ }
+
+ return angle::Result::Continue;
+}
+
+void TextureVk::setImageHelper(RendererVk *renderer,
+ vk::ImageHelper *imageHelper,
+ gl::TextureType imageType,
+ const vk::Format &format,
+ uint32_t imageLevelOffset,
+ uint32_t imageLayerOffset,
+ bool selfOwned)
+{
+ ASSERT(mImage == nullptr);
+
+ mOwnsImage = selfOwned;
+ mImageNativeType = imageType;
+ mImageLevelOffset = imageLevelOffset;
+ mImageLayerOffset = imageLayerOffset;
+ mImage = imageHelper;
+ mImage->initStagingBuffer(renderer, format);
+
+ mRenderTarget.init(mImage, &mDrawBaseLevelImageView, getNativeImageLevel(0),
+ getNativeImageLayer(0), this);
+
+ // Force re-creation of cube map render targets next time they are needed
+ mCubeMapRenderTargets.clear();
+}
+
+void TextureVk::updateImageHelper(RendererVk *renderer, const vk::Format &format)
+{
+ ASSERT(mImage != nullptr);
+ mImage->initStagingBuffer(renderer, format);
+}
+
angle::Result TextureVk::redefineImage(const gl::Context *context,
const gl::ImageIndex &index,
- const gl::InternalFormat &internalFormat,
+ const vk::Format &format,
const gl::Extents &size)
{
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
- // If there is any staged changes for this index, we can remove them since we're going to
- // override them with this call.
- mPixelBuffer.removeStagedUpdates(renderer, index);
+ if (!mOwnsImage)
+ {
+ releaseAndDeleteImage(context, renderer);
+ }
- if (mImage.valid())
+ if (mImage != nullptr)
{
- const vk::Format &vkFormat = renderer->getFormat(internalFormat.sizedInternalFormat);
+ // If there is any staged changes for this index, we can remove them since we're going to
+ // override them with this call.
+ mImage->removeStagedUpdates(renderer, index);
- // Calculate the expected size for the index we are defining. If the size is different from
- // the given size, or the format is different, we are redefining the image so we must
- // release it.
- if (mImage.getFormat() != vkFormat || size != mImage.getSize(index))
+ if (mImage->valid())
{
- releaseImage(context, renderer);
+ // Calculate the expected size for the index we are defining. If the size is different
+ // from the given size, or the format is different, we are redefining the image so we
+ // must release it.
+ if (mImage->getFormat() != format || size != mImage->getSize(index))
+ {
+ releaseImage(renderer);
+ }
}
}
+ if (!size.empty())
+ {
+ ANGLE_TRY(ensureImageAllocated(renderer, format));
+ }
+
return angle::Result::Continue;
}
@@ -991,6 +896,7 @@ angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk,
const gl::Rectangle &sourceArea,
uint8_t **outDataPtr)
{
+ TRACE_EVENT0("gpu.angle", "TextureVk::copyImageDataToBuffer");
// Make sure the source is initialized and it's images are flushed.
ANGLE_TRY(ensureImageInitialized(contextVk));
@@ -999,19 +905,17 @@ angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk,
sourceArea.width * sourceArea.height * imageFormat.pixelBytes * layerCount;
vk::CommandBuffer *commandBuffer = nullptr;
- ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer));
+ ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
// Requirement of the copyImageToBuffer, the source image must be in SRC_OPTIMAL layout.
- mImage.changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, commandBuffer);
+ mImage->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferSrc, commandBuffer);
// Allocate enough memory to copy the sourceArea region of the source texture into its pixel
// buffer.
VkBuffer copyBufferHandle = VK_NULL_HANDLE;
VkDeviceSize sourceCopyOffset = 0;
- ANGLE_TRY(mPixelBuffer.allocate(contextVk, sourceCopyAllocationSize, outDataPtr,
- &copyBufferHandle, &sourceCopyOffset, nullptr));
+ ANGLE_TRY(mImage->allocateStagingMemory(contextVk, sourceCopyAllocationSize, outDataPtr,
+ &copyBufferHandle, &sourceCopyOffset, nullptr));
VkBufferImageCopy region = {};
region.bufferOffset = sourceCopyOffset;
@@ -1028,8 +932,8 @@ angle::Result TextureVk::copyImageDataToBuffer(ContextVk *contextVk,
region.imageSubresource.layerCount = layerCount;
region.imageSubresource.mipLevel = static_cast<uint32_t>(sourceLevel);
- commandBuffer->copyImageToBuffer(mImage.getImage(), mImage.getCurrentLayout(), copyBufferHandle,
- 1, &region);
+ commandBuffer->copyImageToBuffer(mImage->getImage(), mImage->getCurrentLayout(),
+ copyBufferHandle, 1, &region);
// Explicitly finish. If new use cases arise where we don't want to block we can change this.
ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
@@ -1041,15 +945,15 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
{
ContextVk *contextVk = vk::GetImpl(context);
- const gl::Extents baseLevelExtents = mImage.getExtents();
- uint32_t imageLayerCount = mImage.getLayerCount();
+ const gl::Extents baseLevelExtents = mImage->getExtents();
+ uint32_t imageLayerCount = mImage->getLayerCount();
uint8_t *imageData = nullptr;
gl::Rectangle imageArea(0, 0, baseLevelExtents.width, baseLevelExtents.height);
ANGLE_TRY(copyImageDataToBuffer(contextVk, mState.getEffectiveBaseLevel(), imageLayerCount,
imageArea, &imageData));
- const angle::Format &angleFormat = mImage.getFormat().textureFormat();
+ const angle::Format &angleFormat = mImage->getFormat().textureFormat();
GLuint sourceRowPitch = baseLevelExtents.width * angleFormat.pixelBytes;
size_t baseLevelAllocationSize = sourceRowPitch * baseLevelExtents.height;
@@ -1067,8 +971,9 @@ angle::Result TextureVk::generateMipmapsWithCPU(const gl::Context *context)
}
vk::CommandBuffer *commandBuffer;
- ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer));
- return mPixelBuffer.flushUpdatesToImage(contextVk, getLevelCount(), &mImage, commandBuffer);
+ ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
+ return mImage->flushStagedUpdates(contextVk, getNativeImageLevel(0), getLevelCount(),
+ commandBuffer);
}
angle::Result TextureVk::generateMipmap(const gl::Context *context)
@@ -1076,13 +981,13 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
ContextVk *contextVk = vk::GetImpl(context);
// Some data is pending, or the image has not been defined at all yet
- if (!mImage.valid())
+ if (!mImage->valid())
{
// lets initialize the image so we can generate the next levels.
- if (!mPixelBuffer.empty())
+ if (mImage->hasStagedUpdates())
{
ANGLE_TRY(ensureImageInitialized(contextVk));
- ASSERT(mImage.valid());
+ ASSERT(mImage->valid());
}
else
{
@@ -1095,11 +1000,11 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
// Check if the image supports blit. If it does, we can do the mipmap generation on the gpu
// only.
- if (renderer->hasTextureFormatFeatureBits(mImage.getFormat().vkTextureFormat,
+ if (renderer->hasTextureFormatFeatureBits(mImage->getFormat().vkTextureFormat,
kBlitFeatureFlags))
{
ANGLE_TRY(ensureImageInitialized(contextVk));
- ANGLE_TRY(mImage.generateMipmapsWithBlit(contextVk, mState.getMipmapMaxLevel()));
+ ANGLE_TRY(mImage->generateMipmapsWithBlit(contextVk, mState.getMipmapMaxLevel()));
}
else
{
@@ -1107,7 +1012,7 @@ angle::Result TextureVk::generateMipmap(const gl::Context *context)
}
// We're changing this textureVk content, make sure we let the graph know.
- mImage.finishCurrentCommands(renderer);
+ mImage->finishCurrentCommands(renderer);
return angle::Result::Continue;
}
@@ -1120,14 +1025,29 @@ angle::Result TextureVk::setBaseLevel(const gl::Context *context, GLuint baseLev
angle::Result TextureVk::bindTexImage(const gl::Context *context, egl::Surface *surface)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ ContextVk *contextVk = vk::GetImpl(context);
+ RendererVk *renderer = contextVk->getRenderer();
+
+ releaseAndDeleteImage(context, renderer);
+
+ const vk::Format &format = renderer->getFormat(surface->getConfig()->renderTargetFormat);
+
+ // eglBindTexImage can only be called with pbuffer (offscreen) surfaces
+ OffscreenSurfaceVk *offscreenSurface = GetImplAs<OffscreenSurfaceVk>(surface);
+ setImageHelper(renderer, offscreenSurface->getColorAttachmentImage(), mState.getType(), format,
+ surface->getMipmapLevel(), 0, false);
+
+ return initImageViews(contextVk, format, 1);
}
angle::Result TextureVk::releaseTexImage(const gl::Context *context)
{
- ANGLE_VK_UNREACHABLE(vk::GetImpl(context));
- return angle::Result::Stop;
+ ContextVk *contextVk = vk::GetImpl(context);
+ RendererVk *renderer = contextVk->getRenderer();
+
+ releaseImage(renderer);
+
+ return angle::Result::Continue;
}
angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
@@ -1174,19 +1094,19 @@ angle::Result TextureVk::ensureImageInitializedImpl(ContextVk *contextVk,
uint32_t levelCount,
const vk::Format &format)
{
- if (mImage.valid() && mPixelBuffer.empty())
+ if (mImage->valid() && !mImage->hasStagedUpdates())
{
return angle::Result::Continue;
}
vk::CommandBuffer *commandBuffer = nullptr;
- ANGLE_TRY(mImage.recordCommands(contextVk, &commandBuffer));
+ ANGLE_TRY(mImage->recordCommands(contextVk, &commandBuffer));
- if (!mImage.valid())
+ if (!mImage->valid())
{
ANGLE_TRY(initImage(contextVk, format, baseLevelExtents, levelCount, commandBuffer));
}
- return mPixelBuffer.flushUpdatesToImage(contextVk, levelCount, &mImage, commandBuffer);
+ return mImage->flushStagedUpdates(contextVk, getNativeImageLevel(0), levelCount, commandBuffer);
}
angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk)
@@ -1195,11 +1115,13 @@ angle::Result TextureVk::initCubeMapRenderTargets(ContextVk *contextVk)
if (!mCubeMapRenderTargets.empty())
return angle::Result::Continue;
+ mCubeMapRenderTargets.resize(gl::kCubeFaceCount);
for (size_t cubeMapFaceIndex = 0; cubeMapFaceIndex < gl::kCubeFaceCount; ++cubeMapFaceIndex)
{
vk::ImageView *imageView;
ANGLE_TRY(getLayerLevelDrawImageView(contextVk, cubeMapFaceIndex, 0, &imageView));
- mCubeMapRenderTargets.emplace_back(&mImage, imageView, cubeMapFaceIndex, this);
+ mCubeMapRenderTargets[cubeMapFaceIndex].init(mImage, imageView, getNativeImageLevel(0),
+ getNativeImageLayer(cubeMapFaceIndex), this);
}
return angle::Result::Continue;
}
@@ -1267,9 +1189,18 @@ angle::Result TextureVk::initializeContents(const gl::Context *context,
return angle::Result::Continue;
}
+void TextureVk::releaseOwnershipOfImage(const gl::Context *context)
+{
+ ContextVk *contextVk = vk::GetImpl(context);
+ RendererVk *renderer = contextVk->getRenderer();
+
+ mOwnsImage = false;
+ releaseAndDeleteImage(context, renderer);
+}
+
const vk::ImageView &TextureVk::getReadImageView() const
{
- ASSERT(mImage.valid());
+ ASSERT(mImage->valid());
const GLenum minFilter = mState.getSamplerState().getMinFilter();
if (minFilter == GL_LINEAR || minFilter == GL_NEAREST)
@@ -1285,18 +1216,19 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context,
size_t level,
vk::ImageView **imageViewOut)
{
- ASSERT(mImage.valid());
+ ASSERT(mImage->valid());
+ ASSERT(!mImage->getFormat().textureFormat().isBlock);
// Lazily allocate the storage for image views
if (mLayerLevelDrawImageViews.empty())
{
- mLayerLevelDrawImageViews.resize(mImage.getLayerCount());
+ mLayerLevelDrawImageViews.resize(mImage->getLayerCount());
}
ASSERT(mLayerLevelDrawImageViews.size() > layer);
if (mLayerLevelDrawImageViews[layer].empty())
{
- mLayerLevelDrawImageViews[layer].resize(mImage.getLevelCount());
+ mLayerLevelDrawImageViews[layer].resize(mImage->getLevelCount());
}
ASSERT(mLayerLevelDrawImageViews[layer].size() > level);
@@ -1309,8 +1241,9 @@ angle::Result TextureVk::getLayerLevelDrawImageView(vk::Context *context,
// Lazily allocate the image view itself.
// Note that these views are specifically made to be used as color attachments, and therefore
// don't have swizzle.
- return mImage.initLayerImageView(context, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
- gl::SwizzleState(), *imageViewOut, level, 1, layer, 1);
+ return mImage->initLayerImageView(context, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
+ gl::SwizzleState(), *imageViewOut, getNativeImageLevel(level),
+ 1, getNativeImageLayer(layer), 1);
}
const vk::Sampler &TextureVk::getSampler() const
@@ -1325,38 +1258,82 @@ angle::Result TextureVk::initImage(ContextVk *contextVk,
const uint32_t levelCount,
vk::CommandBuffer *commandBuffer)
{
- const RendererVk *renderer = contextVk->getRenderer();
+ const RendererVk *renderer = contextVk->getRenderer();
+ const angle::Format &angleFormat = format.textureFormat();
- const VkImageUsageFlags usage =
- (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
- VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
+ VkImageUsageFlags imageUsageFlags = VK_IMAGE_USAGE_TRANSFER_DST_BIT |
+ VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT;
- ANGLE_TRY(mImage.init(contextVk, mState.getType(), extents, format, 1, usage, levelCount,
- mState.getType() == gl::TextureType::CubeMap ? gl::kCubeFaceCount : 1));
+ if (!angleFormat.isBlock)
+ {
+ imageUsageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ }
+
+ ANGLE_TRY(mImage->init(contextVk, mState.getType(), extents, format, 1, imageUsageFlags,
+ levelCount,
+ mState.getType() == gl::TextureType::CubeMap ? gl::kCubeFaceCount : 1));
const VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
- ANGLE_TRY(mImage.initMemory(contextVk, renderer->getMemoryProperties(), flags));
+ ANGLE_TRY(mImage->initMemory(contextVk, renderer->getMemoryProperties(), flags));
+
+ ANGLE_TRY(initImageViews(contextVk, format, levelCount));
+
+ if (!angleFormat.isBlock)
+ {
+ // TODO(jmadill): Fold this into the RenderPass load/store ops if possible, or defer to
+ // first use. This is only necessary if robustness is required. http://anglebug.com/2361
+ VkClearColorValue black = {{0, 0, 0, 1.0f}};
+ mImage->clearColor(black, 0, levelCount, commandBuffer);
+ }
+ return angle::Result::Continue;
+}
+
+angle::Result TextureVk::initImageViews(ContextVk *contextVk,
+ const vk::Format &format,
+ uint32_t levelCount)
+{
+ ASSERT(mImage != nullptr);
gl::SwizzleState mappedSwizzle;
MapSwizzleState(format, mState.getSwizzleState(), &mappedSwizzle);
- ANGLE_TRY(mImage.initImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
- mappedSwizzle, &mReadMipmapImageView, levelCount));
- ANGLE_TRY(mImage.initImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
- mappedSwizzle, &mReadBaseLevelImageView, 1));
- ANGLE_TRY(mImage.initImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
- gl::SwizzleState(), &mDrawBaseLevelImageView, 1));
+ // TODO: Support non-zero base level for ES 3.0 by passing it to getNativeImageLevel.
+ // http://anglebug.com/3148
+ uint32_t baseLevel = getNativeImageLevel(0);
+ uint32_t baseLayer = getNativeImageLayer(0);
+ uint32_t layerCount = mState.getType() == gl::TextureType::CubeMap ? gl::kCubeFaceCount : 1;
+
+ ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
+ mappedSwizzle, &mReadMipmapImageView, baseLevel,
+ levelCount, baseLayer, layerCount));
+ ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
+ mappedSwizzle, &mReadBaseLevelImageView, baseLevel, 1,
+ baseLayer, layerCount));
+ if (!format.textureFormat().isBlock)
+ {
+ ANGLE_TRY(mImage->initLayerImageView(contextVk, mState.getType(), VK_IMAGE_ASPECT_COLOR_BIT,
+ gl::SwizzleState(), &mDrawBaseLevelImageView,
+ baseLevel, 1, baseLayer, layerCount));
+ }
- // TODO(jmadill): Fold this into the RenderPass load/store ops. http://anglebug.com/2361
- VkClearColorValue black = {{0, 0, 0, 1.0f}};
- mImage.clearColor(black, 0, levelCount, commandBuffer);
return angle::Result::Continue;
}
-void TextureVk::releaseImage(const gl::Context *context, RendererVk *renderer)
+void TextureVk::releaseImage(RendererVk *renderer)
{
- mImage.release(renderer);
+ if (mImage)
+ {
+ if (mOwnsImage)
+ {
+ mImage->releaseImage(renderer);
+ }
+ else
+ {
+ mImage = nullptr;
+ }
+ }
Serial currentSerial = renderer->getCurrentQueueSerial();
@@ -1378,6 +1355,14 @@ void TextureVk::releaseImage(const gl::Context *context, RendererVk *renderer)
mCubeMapRenderTargets.clear();
}
+void TextureVk::releaseStagingBuffer(RendererVk *renderer)
+{
+ if (mImage)
+ {
+ mImage->releaseStagingBuffer(renderer);
+ }
+}
+
uint32_t TextureVk::getLevelCount() const
{
ASSERT(mState.getEffectiveBaseLevel() == 0);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.h
index 65584a9252b..33a1057e67a 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/TextureVk.h
@@ -18,106 +18,6 @@
namespace rx
{
-class PixelBuffer final : angle::NonCopyable
-{
- public:
- PixelBuffer(RendererVk *renderer);
- ~PixelBuffer();
-
- void release(RendererVk *renderer);
-
- void removeStagedUpdates(RendererVk *renderer, const gl::ImageIndex &index);
-
- angle::Result stageSubresourceUpdate(ContextVk *contextVk,
- const gl::ImageIndex &index,
- const gl::Extents &extents,
- const gl::Offset &offset,
- const gl::InternalFormat &formatInfo,
- const gl::PixelUnpackState &unpack,
- GLenum type,
- const uint8_t *pixels);
-
- angle::Result stageSubresourceUpdateAndGetData(ContextVk *contextVk,
- size_t allocationSize,
- const gl::ImageIndex &imageIndex,
- const gl::Extents &extents,
- const gl::Offset &offset,
- uint8_t **destData);
-
- angle::Result stageSubresourceUpdateFromFramebuffer(const gl::Context *context,
- const gl::ImageIndex &index,
- const gl::Rectangle &sourceArea,
- const gl::Offset &dstOffset,
- const gl::Extents &dstExtent,
- const gl::InternalFormat &formatInfo,
- FramebufferVk *framebufferVk);
-
- void stageSubresourceUpdateFromImage(vk::ImageHelper *image,
- const gl::ImageIndex &index,
- const gl::Offset &destOffset,
- const gl::Extents &extents);
-
- // This will use the underlying dynamic buffer to allocate some memory to be used as a src or
- // dst.
- angle::Result allocate(ContextVk *contextVk,
- size_t sizeInBytes,
- uint8_t **ptrOut,
- VkBuffer *handleOut,
- VkDeviceSize *offsetOut,
- bool *newBufferAllocatedOut);
-
- angle::Result flushUpdatesToImage(ContextVk *contextVk,
- uint32_t levelCount,
- vk::ImageHelper *image,
- vk::CommandBuffer *commandBuffer);
-
- bool empty() const;
-
- private:
- struct SubresourceUpdate
- {
- SubresourceUpdate();
- SubresourceUpdate(VkBuffer bufferHandle, const VkBufferImageCopy &copyRegion);
- SubresourceUpdate(vk::ImageHelper *image, const VkImageCopy &copyRegion);
- SubresourceUpdate(const SubresourceUpdate &other);
-
- void release(RendererVk *renderer);
-
- const VkImageSubresourceLayers &dstSubresource() const
- {
- return updateSource == UpdateSource::Buffer ? buffer.copyRegion.imageSubresource
- : image.copyRegion.dstSubresource;
- }
- bool isUpdateToLayerLevel(uint32_t layerIndex, uint32_t levelIndex) const;
-
- enum class UpdateSource
- {
- Buffer,
- Image,
- };
- struct BufferUpdate
- {
- VkBuffer bufferHandle;
- VkBufferImageCopy copyRegion;
- };
- struct ImageUpdate
- {
- vk::ImageHelper *image;
- VkImageCopy copyRegion;
- };
-
- UpdateSource updateSource;
- union
- {
- BufferUpdate buffer;
- ImageUpdate image;
- };
- };
-
- vk::DynamicBuffer mStagingBuffer;
- std::vector<SubresourceUpdate> mSubresourceUpdates;
-};
-
class TextureVk : public TextureImpl
{
public:
@@ -187,6 +87,9 @@ class TextureVk : public TextureImpl
bool unpackUnmultiplyAlpha,
const gl::Texture *source) override;
+ angle::Result copyCompressedTexture(const gl::Context *context,
+ const gl::Texture *source) override;
+
angle::Result setStorage(const gl::Context *context,
gl::TextureType type,
size_t levels,
@@ -229,16 +132,18 @@ class TextureVk : public TextureImpl
const vk::ImageHelper &getImage() const
{
- ASSERT(mImage.valid());
- return mImage;
+ ASSERT(mImage && mImage->valid());
+ return *mImage;
}
vk::ImageHelper &getImage()
{
- ASSERT(mImage.valid());
- return mImage;
+ ASSERT(mImage && mImage->valid());
+ return *mImage;
}
+ void releaseOwnershipOfImage(const gl::Context *context);
+
const vk::ImageView &getReadImageView() const;
angle::Result getLayerLevelDrawImageView(vk::Context *context,
size_t layer,
@@ -249,11 +154,43 @@ class TextureVk : public TextureImpl
angle::Result ensureImageInitialized(ContextVk *contextVk);
private:
+ // Transform an image index from the frontend into one that can be used on the backing
+ // ImageHelper, taking into account mipmap or cube face offsets
+ gl::ImageIndex getNativeImageIndex(const gl::ImageIndex &inputImageIndex) const;
+ uint32_t getNativeImageLevel(uint32_t frontendLevel) const;
+ uint32_t getNativeImageLayer(uint32_t frontendLayer) const;
+
+ void releaseAndDeleteImage(const gl::Context *context, RendererVk *renderer);
+ angle::Result ensureImageAllocated(RendererVk *renderer, const vk::Format &format);
+ void setImageHelper(RendererVk *renderer,
+ vk::ImageHelper *imageHelper,
+ gl::TextureType imageType,
+ const vk::Format &format,
+ uint32_t imageLevelOffset,
+ uint32_t imageLayerOffset,
+ bool selfOwned);
+ void updateImageHelper(RendererVk *renderer, const vk::Format &internalFormat);
+
angle::Result redefineImage(const gl::Context *context,
const gl::ImageIndex &index,
- const gl::InternalFormat &internalFormat,
+ const vk::Format &format,
const gl::Extents &size);
+ angle::Result setImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::InternalFormat &formatInfo,
+ const gl::Extents &size,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels);
+ angle::Result setSubImageImpl(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Box &area,
+ const gl::InternalFormat &formatInfo,
+ GLenum type,
+ const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels);
+
angle::Result copyImageDataToBuffer(ContextVk *contextVk,
size_t sourceLevel,
uint32_t layerCount,
@@ -290,6 +227,14 @@ class TextureVk : public TextureImpl
bool unpackUnmultiplyAlpha,
TextureVk *source);
+ angle::Result copySubImageImplWithTransfer(ContextVk *contextVk,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const vk::Format &destFormat,
+ size_t sourceLevel,
+ const gl::Rectangle &sourceArea,
+ vk::ImageHelper *srcImage);
+
angle::Result copySubImageImplWithDraw(ContextVk *contextVk,
const gl::ImageIndex &index,
const gl::Offset &destOffset,
@@ -308,8 +253,12 @@ class TextureVk : public TextureImpl
const gl::Extents &extents,
const uint32_t levelCount,
vk::CommandBuffer *commandBuffer);
- void releaseImage(const gl::Context *context, RendererVk *renderer);
+ void releaseImage(RendererVk *renderer);
+ void releaseStagingBuffer(RendererVk *renderer);
uint32_t getLevelCount() const;
+ angle::Result initImageViews(ContextVk *contextVk,
+ const vk::Format &format,
+ uint32_t levelCount);
angle::Result initCubeMapRenderTargets(ContextVk *contextVk);
angle::Result ensureImageInitializedImpl(ContextVk *contextVk,
@@ -317,7 +266,20 @@ class TextureVk : public TextureImpl
uint32_t levelCount,
const vk::Format &format);
- vk::ImageHelper mImage;
+ bool mOwnsImage;
+
+ gl::TextureType mImageNativeType;
+
+ // The layer offset to apply when converting from a frontend texture layer to a texture layer in
+ // mImage. Used when this texture sources a cube map face or 3D texture layer from an EGL image.
+ uint32_t mImageLayerOffset;
+
+ // The level offset to apply when converting from a frontend texture level to texture level in
+ // mImage.
+ uint32_t mImageLevelOffset;
+
+ vk::ImageHelper *mImage;
+
vk::ImageView mDrawBaseLevelImageView;
vk::ImageView mReadBaseLevelImageView;
vk::ImageView mReadMipmapImageView;
@@ -326,8 +288,6 @@ class TextureVk : public TextureImpl
RenderTargetVk mRenderTarget;
std::vector<RenderTargetVk> mCubeMapRenderTargets;
-
- PixelBuffer mPixelBuffer;
};
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/UtilsVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/UtilsVk.cpp
index 0d403a52a45..a290eb1c895 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/UtilsVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/UtilsVk.cpp
@@ -389,7 +389,7 @@ angle::Result UtilsVk::clearBuffer(vk::Context *context,
shaderParams.clearValue = params.clearValue;
VkDescriptorSet descriptorSet;
- vk::SharedDescriptorPoolBinding descriptorPoolBinding;
+ vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
ANGLE_TRY(mDescriptorPools[Function::BufferClear].allocateSets(
context, mDescriptorSetLayouts[Function::BufferClear][kSetIndex].get().ptr(), 1,
&descriptorPoolBinding, &descriptorSet));
@@ -451,7 +451,7 @@ angle::Result UtilsVk::copyBuffer(vk::Context *context,
shaderParams.srcOffset = params.srcOffset;
VkDescriptorSet descriptorSet;
- vk::SharedDescriptorPoolBinding descriptorPoolBinding;
+ vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
ANGLE_TRY(mDescriptorPools[Function::BufferCopy].allocateSets(
context, mDescriptorSetLayouts[Function::BufferCopy][kSetIndex].get().ptr(), 1,
&descriptorPoolBinding, &descriptorSet));
@@ -534,7 +534,7 @@ angle::Result UtilsVk::convertVertexBuffer(vk::Context *context,
flags |= isAligned ? ConvertVertex_comp::kIsAligned : 0;
VkDescriptorSet descriptorSet;
- vk::SharedDescriptorPoolBinding descriptorPoolBinding;
+ vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
ANGLE_TRY(mDescriptorPools[Function::ConvertVertexBuffer].allocateSets(
context, mDescriptorSetLayouts[Function::ConvertVertexBuffer][kSetIndex].get().ptr(), 1,
&descriptorPoolBinding, &descriptorSet));
@@ -620,7 +620,7 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk,
vk::CommandBuffer *commandBuffer;
if (!framebuffer->appendToStartedRenderPass(renderer->getCurrentQueueSerial(), &commandBuffer))
{
- ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, &commandBuffer))
+ ANGLE_TRY(framebuffer->startNewRenderPass(contextVk, &commandBuffer));
}
ImageClearShaderParams shaderParams;
@@ -641,6 +641,11 @@ angle::Result UtilsVk::clearImage(ContextVk *contextVk,
VkRect2D scissor;
const gl::State &glState = contextVk->getState();
gl_vk::GetScissor(glState, invertViewport, renderArea, &scissor);
+ // TODO(courtneygo): workaround for scissor issue on some devices. http://anglebug.com/3114
+ if ((scissor.extent.width == 0) || (scissor.extent.height == 0))
+ {
+ return angle::Result::Continue;
+ }
pipelineDesc.setScissor(scissor);
vk::ShaderLibrary &shaderLibrary = renderer->getShaderLibrary();
@@ -705,7 +710,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
flags |= src->getLayerCount() > 1 ? ImageCopy_frag::kSrcIsArray : 0;
VkDescriptorSet descriptorSet;
- vk::SharedDescriptorPoolBinding descriptorPoolBinding;
+ vk::RefCountedDescriptorPoolBinding descriptorPoolBinding;
ANGLE_TRY(mDescriptorPools[Function::ImageCopy].allocateSets(
contextVk, mDescriptorSetLayouts[Function::ImageCopy][kSetIndex].get().ptr(), 1,
&descriptorPoolBinding, &descriptorSet));
@@ -733,24 +738,20 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
pipelineDesc.setScissor(scissor);
// Change source layout outside render pass
- if (src->getCurrentLayout() != VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
+ if (src->isLayoutChangeNecessary(vk::ImageLayout::FragmentShaderReadOnly))
{
vk::CommandBuffer *srcLayoutChange;
ANGLE_TRY(src->recordCommands(contextVk, &srcLayoutChange));
- src->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, srcLayoutChange);
+ src->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::FragmentShaderReadOnly,
+ srcLayoutChange);
}
// Change destination layout outside render pass as well
vk::CommandBuffer *destLayoutChange;
ANGLE_TRY(dest->recordCommands(contextVk, &destLayoutChange));
- dest->changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, destLayoutChange);
+ dest->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::ColorAttachment,
+ destLayoutChange);
vk::CommandBuffer *commandBuffer;
ANGLE_TRY(
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
index 1cdcbaa2624..03f96b38260 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
@@ -18,6 +18,7 @@
#include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_format_utils.h"
+#include "third_party/trace_event/trace_event.h"
namespace rx
{
@@ -261,6 +262,7 @@ angle::Result VertexArrayVk::convertVertexBufferCpu(ContextVk *contextVk,
size_t attribIndex,
const vk::Format &vertexFormat)
{
+ TRACE_EVENT0("gpu.angle", "VertexArrayVk::convertVertexBufferCpu");
// Needed before reading buffer or we could get stale data.
ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
@@ -357,7 +359,7 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
(*attribBits)[INDEX].reset(); \
break;
- ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC);
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_ATTRIB_FUNC)
#define ANGLE_VERTEX_DIRTY_BINDING_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BINDING_0 + INDEX: \
@@ -367,7 +369,7 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
(*bindingBits)[INDEX].reset(); \
break;
- ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC);
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BINDING_FUNC)
#define ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC(INDEX) \
case gl::VertexArray::DIRTY_BIT_BUFFER_DATA_0 + INDEX: \
@@ -375,7 +377,7 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
bindings[attribs[INDEX].bindingIndex], INDEX)); \
break;
- ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC);
+ ANGLE_VERTEX_INDEX_CASES(ANGLE_VERTEX_DIRTY_BUFFER_DATA_FUNC)
default:
UNREACHABLE();
@@ -490,6 +492,7 @@ angle::Result VertexArrayVk::syncDirtyAttrib(ContextVk *contextVk,
angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
GLint firstVertex,
GLsizei vertexOrIndexCount,
+ GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices)
{
@@ -520,22 +523,35 @@ angle::Result VertexArrayVk::updateClientAttribs(const gl::Context *context,
const vk::Format &vertexFormat = renderer->getFormat(GetVertexFormatID(attrib));
GLuint stride = vertexFormat.bufferFormat().pixelBytes;
- const size_t bytesToAllocate = (startVertex + vertexCount) * stride;
- const uint8_t *src =
- static_cast<const uint8_t *>(attrib.pointer) + startVertex * binding.getStride();
-
- size_t destOffset = startVertex * stride;
ASSERT(GetVertexInputAlignment(vertexFormat) <= kMaxVertexFormatAlignment);
- // Only vertexCount() vertices will be used by the upcoming draw. so that is all we copy.
- // We allocate space for startVertex + vertexCount so indexing will work. If we
- // don't start at zero all the indices will be off.
- // TODO(fjhenigman): See if we can account for indices being off by adjusting the
- // offset, thus avoiding wasted memory.
- ANGLE_TRY(StreamVertexData(
- contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
- binding.getStride(), vertexFormat.vertexLoadFunction,
- &mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
+ const uint8_t *src = static_cast<const uint8_t *>(attrib.pointer);
+ if (binding.getDivisor() > 0)
+ {
+ // instanced attrib
+ size_t count = UnsignedCeilDivide(instanceCount, binding.getDivisor());
+ size_t bytesToAllocate = count * stride;
+
+ ANGLE_TRY(StreamVertexData(contextVk, &mDynamicVertexData, src, bytesToAllocate, 0,
+ count, binding.getStride(), vertexFormat.vertexLoadFunction,
+ &mCurrentArrayBuffers[attribIndex],
+ &mCurrentArrayBufferOffsets[attribIndex]));
+ }
+ else
+ {
+ // Allocate space for startVertex + vertexCount so indexing will work. If we don't
+ // start at zero all the indices will be off.
+ // Only vertexCount vertices will be used by the upcoming draw so that is all we copy.
+ size_t bytesToAllocate = (startVertex + vertexCount) * stride;
+ src += startVertex * binding.getStride();
+ size_t destOffset = startVertex * stride;
+
+ ANGLE_TRY(StreamVertexData(
+ contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
+ binding.getStride(), vertexFormat.vertexLoadFunction,
+ &mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
+ }
+
mCurrentArrayBufferHandles[attribIndex] =
mCurrentArrayBuffers[attribIndex]->getBuffer().getHandle();
}
@@ -660,6 +676,7 @@ angle::Result VertexArrayVk::updateIndexTranslation(ContextVk *contextVk,
// as well support the ubyte to ushort case with correct handling of primitive restart.
// http://anglebug.com/3003
+ TRACE_EVENT0("gpu.angle", "VertexArrayVk::updateIndexTranslation");
// Needed before reading buffer or we could get stale data.
ANGLE_TRY(renderer->finish(contextVk));
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h
index 4056e1605dc..5f395d2cbfb 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/VertexArrayVk.h
@@ -39,6 +39,7 @@ class VertexArrayVk : public VertexArrayImpl
angle::Result updateClientAttribs(const gl::Context *context,
GLint firstVertex,
GLsizei vertexOrIndexCount,
+ GLsizei instanceCount,
gl::DrawElementsType indexTypeOrInvalid,
const void *indices);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp
index 777b18d3db1..66fdadbb663 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.cpp
@@ -14,6 +14,7 @@
#include <vulkan/vulkan.h>
#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h"
#include "libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h"
#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
@@ -45,7 +46,7 @@ SurfaceImpl *DisplayVkAndroid::createWindowSurfaceVk(const egl::SurfaceState &st
egl::ConfigSet DisplayVkAndroid::generateConfigs()
{
- constexpr GLenum kColorFormats[] = {GL_RGBA8, GL_RGB8, GL_RGB565};
+ constexpr GLenum kColorFormats[] = {GL_RGBA8, GL_RGB8, GL_RGB565, GL_RGB10_A2, GL_RGBA16F};
constexpr EGLint kSampleCounts[] = {0};
return egl_vk::GenerateConfigs(kColorFormats, egl_vk::kConfigDepthStencilFormats, kSampleCounts,
this);
@@ -58,7 +59,39 @@ bool DisplayVkAndroid::checkConfigSupport(egl::Config *config)
return true;
}
-const char *DisplayVkAndroid::getWSIName() const
+egl::Error DisplayVkAndroid::validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ switch (target)
+ {
+ case EGL_NATIVE_BUFFER_ANDROID:
+ return HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(mRenderer,
+ clientBuffer);
+
+ default:
+ return DisplayVk::validateImageClientBuffer(context, target, clientBuffer, attribs);
+ }
+}
+
+ExternalImageSiblingImpl *DisplayVkAndroid::createExternalImageSibling(
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs)
+{
+ switch (target)
+ {
+ case EGL_NATIVE_BUFFER_ANDROID:
+ return new HardwareBufferImageSiblingVkAndroid(buffer);
+
+ default:
+ return DisplayVk::createExternalImageSibling(context, target, buffer, attribs);
+ }
+}
+
+const char *DisplayVkAndroid::getWSIExtension() const
{
return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.h
index eb1870f113a..ef9f5ea8013 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/DisplayVkAndroid.h
@@ -31,7 +31,17 @@ class DisplayVkAndroid : public DisplayVk
egl::ConfigSet generateConfigs() override;
bool checkConfigSupport(egl::Config *config) override;
- const char *getWSIName() const override;
+ egl::Error validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const override;
+
+ ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs) override;
+
+ const char *getWSIExtension() const override;
};
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp
new file mode 100644
index 00000000000..a60f12cf6d0
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.cpp
@@ -0,0 +1,208 @@
+//
+// Copyright 2019 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.
+//
+
+// HardwareBufferImageSiblingVkAndroid.cpp: Implements HardwareBufferImageSiblingVkAndroid.
+
+#include "libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h"
+
+#include "common/android_util.h"
+
+#include "libANGLE/Display.h"
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+
+namespace rx
+{
+
+HardwareBufferImageSiblingVkAndroid::HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer)
+ : mBuffer(buffer),
+ mFormat(GL_NONE),
+ mRenderable(false),
+ mTextureable(false),
+ mSamples(0),
+ mImage(nullptr)
+{}
+
+HardwareBufferImageSiblingVkAndroid::~HardwareBufferImageSiblingVkAndroid() {}
+
+// Static
+egl::Error HardwareBufferImageSiblingVkAndroid::ValidateHardwareBuffer(RendererVk *renderer,
+ EGLClientBuffer buffer)
+{
+ struct ANativeWindowBuffer *windowBuffer =
+ angle::android::ClientBufferToANativeWindowBuffer(buffer);
+ struct AHardwareBuffer *hardwareBuffer =
+ angle::android::ANativeWindowBufferToAHardwareBuffer(windowBuffer);
+
+ VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties = {};
+ bufferFormatProperties.sType =
+ VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
+ bufferFormatProperties.pNext = nullptr;
+
+ VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {};
+ bufferProperties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
+ bufferProperties.pNext = &bufferFormatProperties;
+
+ VkDevice device = renderer->getDevice();
+ VkResult result =
+ vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer, &bufferProperties);
+ if (result != VK_SUCCESS)
+ {
+ return egl::EglBadParameter() << "Failed to query AHardwareBuffer properties";
+ }
+
+ if (!HasFullTextureFormatSupport(renderer, bufferFormatProperties.format))
+ {
+ return egl::EglBadParameter()
+ << "AHardwareBuffer format does not support enough features to use as a texture.";
+ }
+
+ return egl::NoError();
+}
+
+egl::Error HardwareBufferImageSiblingVkAndroid::initialize(const egl::Display *display)
+{
+ DisplayVk *displayVk = vk::GetImpl(display);
+ return angle::ToEGL(initImpl(displayVk), displayVk, EGL_BAD_PARAMETER);
+}
+
+angle::Result HardwareBufferImageSiblingVkAndroid::initImpl(DisplayVk *displayVk)
+{
+ RendererVk *renderer = displayVk->getRenderer();
+
+ struct ANativeWindowBuffer *windowBuffer =
+ angle::android::ClientBufferToANativeWindowBuffer(mBuffer);
+
+ int pixelFormat = 0;
+ angle::android::GetANativeWindowBufferProperties(windowBuffer, &mSize.width, &mSize.height,
+ &mSize.depth, &pixelFormat);
+ GLenum internalFormat = angle::android::NativePixelFormatToGLInternalFormat(pixelFormat);
+ mFormat = gl::Format(internalFormat);
+
+ struct AHardwareBuffer *hardwareBuffer =
+ angle::android::ANativeWindowBufferToAHardwareBuffer(windowBuffer);
+
+ VkAndroidHardwareBufferFormatPropertiesANDROID bufferFormatProperties;
+ bufferFormatProperties.sType =
+ VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID;
+ bufferFormatProperties.pNext = nullptr;
+
+ VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {};
+ bufferProperties.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID;
+ bufferProperties.pNext = &bufferFormatProperties;
+
+ VkDevice device = renderer->getDevice();
+ ANGLE_VK_TRY(displayVk, vkGetAndroidHardwareBufferPropertiesANDROID(device, hardwareBuffer,
+ &bufferProperties));
+
+ const vk::Format &vkFormat = renderer->getFormat(internalFormat);
+ const angle::Format &textureFormat = vkFormat.textureFormat();
+ bool isDepthOrStencilFormat = textureFormat.depthBits > 0 || textureFormat.stencilBits > 0;
+ const VkImageUsageFlags usage =
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT |
+ (textureFormat.redBits > 0 ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT : 0) |
+ (isDepthOrStencilFormat ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : 0);
+
+ VkExternalFormatANDROID externalFormat = {};
+ externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
+ externalFormat.externalFormat = 0;
+
+ if (bufferFormatProperties.format == VK_FORMAT_UNDEFINED)
+ {
+ externalFormat.externalFormat = bufferFormatProperties.externalFormat;
+ }
+
+ VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {};
+ externalMemoryImageCreateInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
+ externalMemoryImageCreateInfo.pNext = &externalFormat;
+ externalMemoryImageCreateInfo.handleTypes =
+ VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;
+
+ mImage = new vk::ImageHelper();
+ ANGLE_TRY(mImage->initExternal(displayVk, gl::TextureType::_2D, mSize, vkFormat, 1, usage,
+ vk::ImageLayout::ExternalPreInitialized,
+ &externalMemoryImageCreateInfo, 1, 1));
+
+ VkImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {};
+ importHardwareBufferInfo.sType = VK_STRUCTURE_TYPE_IMPORT_ANDROID_HARDWARE_BUFFER_INFO_ANDROID;
+ importHardwareBufferInfo.buffer = hardwareBuffer;
+
+ VkMemoryDedicatedAllocateInfo dedicatedAllocInfo = {};
+ dedicatedAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
+ dedicatedAllocInfo.pNext = &importHardwareBufferInfo;
+ dedicatedAllocInfo.image = mImage->getImage().getHandle();
+ dedicatedAllocInfo.buffer = VK_NULL_HANDLE;
+
+ VkMemoryRequirements externalMemoryRequirements = {};
+ externalMemoryRequirements.size = bufferProperties.allocationSize;
+ externalMemoryRequirements.alignment = 0;
+ externalMemoryRequirements.memoryTypeBits = bufferProperties.memoryTypeBits;
+
+ VkMemoryPropertyFlags flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
+ ANGLE_TRY(mImage->initExternalMemory(displayVk, renderer->getMemoryProperties(),
+ externalMemoryRequirements, &dedicatedAllocInfo,
+ VK_QUEUE_FAMILY_FOREIGN_EXT, flags));
+
+ constexpr uint32_t kColorRenderableRequiredBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ constexpr uint32_t kDepthStencilRenderableRequiredBits = VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ mRenderable = renderer->hasTextureFormatFeatureBits(vkFormat.vkTextureFormat,
+ kColorRenderableRequiredBits) ||
+ renderer->hasTextureFormatFeatureBits(vkFormat.vkTextureFormat,
+ kDepthStencilRenderableRequiredBits);
+
+ constexpr uint32_t kTextureableRequiredBits =
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
+ mTextureable =
+ renderer->hasTextureFormatFeatureBits(vkFormat.vkTextureFormat, kTextureableRequiredBits);
+
+ return angle::Result::Continue;
+}
+
+void HardwareBufferImageSiblingVkAndroid::onDestroy(const egl::Display *display)
+{
+ DisplayVk *displayVk = vk::GetImpl(display);
+ RendererVk *renderer = displayVk->getRenderer();
+
+ if (mImage != nullptr)
+ {
+ mImage->releaseImage(renderer);
+ mImage->releaseStagingBuffer(renderer);
+ SafeDelete(mImage);
+ }
+}
+
+gl::Format HardwareBufferImageSiblingVkAndroid::getFormat() const
+{
+ return mFormat;
+}
+
+bool HardwareBufferImageSiblingVkAndroid::isRenderable(const gl::Context *context) const
+{
+ return mRenderable;
+}
+
+bool HardwareBufferImageSiblingVkAndroid::isTexturable(const gl::Context *context) const
+{
+ return mTextureable;
+}
+
+gl::Extents HardwareBufferImageSiblingVkAndroid::getSize() const
+{
+ return mSize;
+}
+
+size_t HardwareBufferImageSiblingVkAndroid::getSamples() const
+{
+ return mSamples;
+}
+
+// ExternalImageSiblingVk interface
+vk::ImageHelper *HardwareBufferImageSiblingVkAndroid::getImage() const
+{
+ return mImage;
+}
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h
new file mode 100644
index 00000000000..e2648c60f15
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/HardwareBufferImageSiblingVkAndroid.h
@@ -0,0 +1,55 @@
+//
+// Copyright 2019 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.
+//
+
+// HardwareBufferImageSiblingVkAndroid.h: Defines the HardwareBufferImageSiblingVkAndroid to wrap
+// EGL images created from AHardwareBuffer objects
+
+#ifndef LIBANGLE_RENDERER_VULKAN_ANDROID_HARDWAREBUFFERIMAGESIBLINGVKANDROID_H_
+#define LIBANGLE_RENDERER_VULKAN_ANDROID_HARDWAREBUFFERIMAGESIBLINGVKANDROID_H_
+
+#include "libANGLE/renderer/vulkan/ImageVk.h"
+
+namespace rx
+{
+
+class HardwareBufferImageSiblingVkAndroid : public ExternalImageSiblingVk
+{
+ public:
+ HardwareBufferImageSiblingVkAndroid(EGLClientBuffer buffer);
+ ~HardwareBufferImageSiblingVkAndroid() override;
+
+ static egl::Error ValidateHardwareBuffer(RendererVk *renderer, EGLClientBuffer buffer);
+
+ egl::Error initialize(const egl::Display *display) override;
+ void onDestroy(const egl::Display *display) override;
+
+ // ExternalImageSiblingImpl interface
+ gl::Format getFormat() const override;
+ bool isRenderable(const gl::Context *context) const override;
+ bool isTexturable(const gl::Context *context) const override;
+ gl::Extents getSize() const override;
+ size_t getSamples() const override;
+
+ // ExternalImageSiblingVk interface
+ vk::ImageHelper *getImage() const override;
+
+ private:
+ angle::Result initImpl(DisplayVk *displayVk);
+
+ EGLClientBuffer mBuffer;
+ gl::Extents mSize;
+ gl::Format mFormat;
+
+ bool mRenderable;
+ bool mTextureable;
+ size_t mSamples;
+
+ vk::ImageHelper *mImage;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_ANDROID_HARDWAREBUFFERIMAGESIBLINGVKANDROID_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp
index 8fe230d30fc..13e6799379b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.cpp
@@ -33,6 +33,12 @@ angle::Result WindowSurfaceVkAndroid::createSurfaceVk(vk::Context *context, gl::
ANGLE_VK_TRY(context, vkCreateAndroidSurfaceKHR(context->getRenderer()->getInstance(),
&createInfo, nullptr, &mSurface));
+ return getCurrentWindowSize(context, extentsOut);
+}
+
+angle::Result WindowSurfaceVkAndroid::getCurrentWindowSize(vk::Context *context,
+ gl::Extents *extentsOut)
+{
int32_t width = ANativeWindow_getWidth(mNativeWindowType);
int32_t height = ANativeWindow_getHeight(mNativeWindowType);
ANGLE_VK_CHECK(context, width > 0 && height > 0, VK_ERROR_INITIALIZATION_FAILED);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h
index d9d633eaec7..13bb16fd1b6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/android/WindowSurfaceVkAndroid.h
@@ -25,6 +25,7 @@ class WindowSurfaceVkAndroid : public WindowSurfaceVk
private:
angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override;
+ angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override;
};
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.cpp
new file mode 100644
index 00000000000..19d08e8e7d0
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.cpp
@@ -0,0 +1,59 @@
+//
+// Copyright 2019 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.
+//
+// DisplayVkFuchsia.h:
+// Implements methods from DisplayVkFuchsia
+//
+
+#include "libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.h"
+
+#include "libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h"
+#include "libANGLE/renderer/vulkan/vk_caps_utils.h"
+
+namespace rx
+{
+
+DisplayVkFuchsia::DisplayVkFuchsia(const egl::DisplayState &state) : DisplayVk(state) {}
+
+bool DisplayVkFuchsia::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return WindowSurfaceVkFuchsia::isValidNativeWindow(window);
+}
+
+SurfaceImpl *DisplayVkFuchsia::createWindowSurfaceVk(const egl::SurfaceState &state,
+ EGLNativeWindowType window,
+ EGLint width,
+ EGLint height)
+{
+ ASSERT(isValidNativeWindow(window));
+ return new WindowSurfaceVkFuchsia(state, window, width, height);
+}
+
+egl::ConfigSet DisplayVkFuchsia::generateConfigs()
+{
+ constexpr GLenum kColorFormats[] = {GL_BGRA8_EXT, GL_BGRX8_ANGLEX};
+ constexpr EGLint kSampleCounts[] = {0};
+ return egl_vk::GenerateConfigs(kColorFormats, egl_vk::kConfigDepthStencilFormats, kSampleCounts,
+ this);
+}
+
+bool DisplayVkFuchsia::checkConfigSupport(egl::Config *config)
+{
+ // TODO(geofflang): Test for native support and modify the config accordingly.
+ // anglebug.com/2692
+ return true;
+}
+
+const char *DisplayVkFuchsia::getWSIExtension() const
+{
+ return VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME;
+}
+
+const char *DisplayVkFuchsia::getWSILayer() const
+{
+ return "VK_LAYER_FUCHSIA_imagepipe_swapchain";
+}
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.h
new file mode 100644
index 00000000000..c6f3c6c73e7
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/DisplayVkFuchsia.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2019 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.
+//
+// DisplayVkFuchsia.h:
+// Subclasses DisplayVk for the Fuchsia platform.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FUCHSIA_DISPLAYVKFUCHSIA_H_
+#define LIBANGLE_RENDERER_VULKAN_FUCHSIA_DISPLAYVKFUCHSIA_H_
+
+#include "libANGLE/renderer/vulkan/DisplayVk.h"
+
+namespace rx
+{
+
+class DisplayVkFuchsia : public DisplayVk
+{
+ public:
+ DisplayVkFuchsia(const egl::DisplayState &state);
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ SurfaceImpl *createWindowSurfaceVk(const egl::SurfaceState &state,
+ EGLNativeWindowType window,
+ EGLint width,
+ EGLint height) override;
+
+ egl::ConfigSet generateConfigs() override;
+ bool checkConfigSupport(egl::Config *config) override;
+
+ const char *getWSIExtension() const override;
+ const char *getWSILayer() const override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_FUCHSIA_DISPLAYVKFUCHSIA_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.cpp
new file mode 100644
index 00000000000..fa8f4e2ff1d
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.cpp
@@ -0,0 +1,66 @@
+//
+// Copyright 2019 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.
+//
+// WindowSurfaceVkFuchsia.cpp:
+// Implements methods from WindowSurfaceVkFuchsia.
+//
+
+#include "libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h"
+
+#include <fuchsia_egl.h>
+#include <fuchsia_egl_backend.h>
+#include <zircon/syscalls.h>
+#include <zircon/syscalls/object.h>
+
+#include "libANGLE/renderer/vulkan/RendererVk.h"
+#include "libANGLE/renderer/vulkan/vk_utils.h"
+
+namespace rx
+{
+
+WindowSurfaceVkFuchsia::WindowSurfaceVkFuchsia(const egl::SurfaceState &surfaceState,
+ EGLNativeWindowType window,
+ EGLint width,
+ EGLint height)
+ : WindowSurfaceVk(surfaceState, window, width, height)
+{}
+
+WindowSurfaceVkFuchsia::~WindowSurfaceVkFuchsia() {}
+
+// static
+bool WindowSurfaceVkFuchsia::isValidNativeWindow(EGLNativeWindowType window)
+{
+ fuchsia_egl_window *egl_window = reinterpret_cast<fuchsia_egl_window *>(window);
+ return fuchsia_egl_window_get_width(egl_window) >= 0;
+}
+
+angle::Result WindowSurfaceVkFuchsia::createSurfaceVk(vk::Context *context, gl::Extents *extentsOut)
+{
+ InitImagePipeSurfaceFUCHSIAFunctions(context->getRenderer()->getInstance());
+ fuchsia_egl_window *egl_window = reinterpret_cast<fuchsia_egl_window *>(mNativeWindowType);
+
+ VkImagePipeSurfaceCreateInfoFUCHSIA createInfo = {};
+ createInfo.sType = VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA;
+ createInfo.imagePipeHandle = fuchsia_egl_window_release_image_pipe(egl_window);
+ ANGLE_VK_TRY(context, vkCreateImagePipeSurfaceFUCHSIA(context->getRenderer()->getInstance(),
+ &createInfo, nullptr, &mSurface));
+
+ return getCurrentWindowSize(context, extentsOut);
+}
+
+angle::Result WindowSurfaceVkFuchsia::getCurrentWindowSize(vk::Context *context,
+ gl::Extents *extentsOut)
+{
+ fuchsia_egl_window *egl_window = reinterpret_cast<fuchsia_egl_window *>(mNativeWindowType);
+
+ int32_t width = fuchsia_egl_window_get_width(egl_window);
+ int32_t height = fuchsia_egl_window_get_height(egl_window);
+
+ *extentsOut = gl::Extents(width, height, 0);
+
+ return angle::Result::Continue;
+}
+
+} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h
new file mode 100644
index 00000000000..e9ce81803ec
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/fuchsia/WindowSurfaceVkFuchsia.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2019 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.
+//
+// WindowSurfaceVkFuchsia.h:
+// Subclasses WindowSurfaceVk for the Fuchsia platform.
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_FUCHSIA_WINDOWSURFACEVKFUCHSIA_H_
+#define LIBANGLE_RENDERER_VULKAN_FUCHSIA_WINDOWSURFACEVKFUCHSIA_H_
+
+#include "libANGLE/renderer/vulkan/SurfaceVk.h"
+
+namespace rx
+{
+
+class WindowSurfaceVkFuchsia : public WindowSurfaceVk
+{
+ public:
+ WindowSurfaceVkFuchsia(const egl::SurfaceState &surfaceState,
+ EGLNativeWindowType window,
+ EGLint width,
+ EGLint height);
+ ~WindowSurfaceVkFuchsia() override;
+
+ static bool isValidNativeWindow(EGLNativeWindowType window);
+
+ private:
+ angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override;
+ angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_FUCHSIA_WINDOWSURFACEVKFUCHSIA_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
index 0777ac379d0..cc3055a640c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.cpp
@@ -280,7 +280,7 @@ DestT Int4Array_Get(const uint8_t *arrayBytes, uint32_t arrayIndex)
// Helper macro that casts to a bitfield type then verifies no bits were dropped.
#define SetBitField(lhs, rhs) \
lhs = static_cast<typename std::decay<decltype(lhs)>::type>(rhs); \
- ASSERT(static_cast<decltype(rhs)>(lhs) == (rhs));
+ ASSERT(static_cast<decltype(rhs)>(lhs) == (rhs))
// When converting a byte number to a transition bit index we can shift instead of divide.
constexpr size_t kTransitionByteShift = Log2(kGraphicsPipelineDirtyBitBytes);
@@ -536,6 +536,11 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
sizeof(attributeDescs);
ANGLE_UNUSED_VARIABLE(unpackedSize);
+ gl::AttribArray<VkVertexInputBindingDivisorDescriptionEXT> divisorDesc;
+ VkPipelineVertexInputDivisorStateCreateInfoEXT divisorState = {};
+ divisorState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
+ divisorState.pVertexBindingDivisors = divisorDesc.data();
+
for (size_t attribIndexSizeT : activeAttribLocationsMask)
{
const uint32_t attribIndex = static_cast<uint32_t>(attribIndexSizeT);
@@ -545,8 +550,18 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
const PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex];
bindingDesc.binding = attribIndex;
- bindingDesc.inputRate = static_cast<VkVertexInputRate>(packedAttrib.inputRate);
bindingDesc.stride = static_cast<uint32_t>(packedAttrib.stride);
+ if (packedAttrib.divisor != 0)
+ {
+ bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_INSTANCE);
+ divisorDesc[divisorState.vertexBindingDivisorCount].binding = bindingDesc.binding;
+ divisorDesc[divisorState.vertexBindingDivisorCount].divisor = packedAttrib.divisor;
+ ++divisorState.vertexBindingDivisorCount;
+ }
+ else
+ {
+ bindingDesc.inputRate = static_cast<VkVertexInputRate>(VK_VERTEX_INPUT_RATE_VERTEX);
+ }
// The binding index could become more dynamic in ES 3.1.
attribDesc.binding = attribIndex;
@@ -564,6 +579,8 @@ angle::Result GraphicsPipelineDesc::initializePipeline(
vertexInputState.pVertexBindingDescriptions = bindingDescs.data();
vertexInputState.vertexAttributeDescriptionCount = vertexAttribCount;
vertexInputState.pVertexAttributeDescriptions = attributeDescs.data();
+ if (divisorState.vertexBindingDivisorCount)
+ vertexInputState.pNext = &divisorState;
// Primitive topology is filled in at draw time.
inputAssemblyState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
@@ -696,12 +713,12 @@ void GraphicsPipelineDesc::updateVertexInput(GraphicsPipelineTransitionBits *tra
{
vk::PackedAttribDesc &packedAttrib = mVertexInputAttribs.attribs[attribIndex];
- // TODO(http://anglebug.com/2672): This will need to be updated to support instancing.
- ASSERT(divisor == 0);
+ // TODO: Handle the case where the divisor overflows the field that holds it.
+ // http://anglebug.com/2672
+ ASSERT(divisor <= std::numeric_limits<decltype(packedAttrib.divisor)>::max());
SetBitField(packedAttrib.stride, stride);
- SetBitField(packedAttrib.inputRate,
- divisor > 0 ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX);
+ SetBitField(packedAttrib.divisor, divisor);
if (format == VK_FORMAT_UNDEFINED)
{
@@ -1374,7 +1391,7 @@ void DescriptorSetLayoutCache::destroy(VkDevice device)
{
for (auto &item : mPayload)
{
- vk::SharedDescriptorSetLayout &layout = item.second;
+ vk::RefCountedDescriptorSetLayout &layout = item.second;
ASSERT(!layout.isReferenced());
layout.get().destroy(device);
}
@@ -1390,7 +1407,7 @@ angle::Result DescriptorSetLayoutCache::getDescriptorSetLayout(
auto iter = mPayload.find(desc);
if (iter != mPayload.end())
{
- vk::SharedDescriptorSetLayout &layout = iter->second;
+ vk::RefCountedDescriptorSetLayout &layout = iter->second;
descriptorSetLayoutOut->set(&layout);
return angle::Result::Continue;
}
@@ -1408,8 +1425,9 @@ angle::Result DescriptorSetLayoutCache::getDescriptorSetLayout(
vk::DescriptorSetLayout newLayout;
ANGLE_VK_TRY(context, newLayout.init(context->getDevice(), createInfo));
- auto insertedItem = mPayload.emplace(desc, vk::SharedDescriptorSetLayout(std::move(newLayout)));
- vk::SharedDescriptorSetLayout &insertedLayout = insertedItem.first->second;
+ auto insertedItem =
+ mPayload.emplace(desc, vk::RefCountedDescriptorSetLayout(std::move(newLayout)));
+ vk::RefCountedDescriptorSetLayout &insertedLayout = insertedItem.first->second;
descriptorSetLayoutOut->set(&insertedLayout);
return angle::Result::Continue;
@@ -1427,7 +1445,7 @@ void PipelineLayoutCache::destroy(VkDevice device)
{
for (auto &item : mPayload)
{
- vk::SharedPipelineLayout &layout = item.second;
+ vk::RefCountedPipelineLayout &layout = item.second;
layout.get().destroy(device);
}
@@ -1443,7 +1461,7 @@ angle::Result PipelineLayoutCache::getPipelineLayout(
auto iter = mPayload.find(desc);
if (iter != mPayload.end())
{
- vk::SharedPipelineLayout &layout = iter->second;
+ vk::RefCountedPipelineLayout &layout = iter->second;
pipelineLayoutOut->set(&layout);
return angle::Result::Continue;
}
@@ -1501,8 +1519,8 @@ angle::Result PipelineLayoutCache::getPipelineLayout(
vk::PipelineLayout newLayout;
ANGLE_VK_TRY(context, newLayout.init(context->getDevice(), createInfo));
- auto insertedItem = mPayload.emplace(desc, vk::SharedPipelineLayout(std::move(newLayout)));
- vk::SharedPipelineLayout &insertedLayout = insertedItem.first->second;
+ auto insertedItem = mPayload.emplace(desc, vk::RefCountedPipelineLayout(std::move(newLayout)));
+ vk::RefCountedPipelineLayout &insertedLayout = insertedItem.first->second;
pipelineLayoutOut->set(&insertedLayout);
return angle::Result::Continue;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.h
index c767405a225..f1f9a1ada88 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_cache_utils.h
@@ -25,12 +25,12 @@ class ImageHelper;
using RenderPassAndSerial = ObjectAndSerial<RenderPass>;
using PipelineAndSerial = ObjectAndSerial<Pipeline>;
-using SharedDescriptorSetLayout = RefCounted<DescriptorSetLayout>;
-using SharedPipelineLayout = RefCounted<PipelineLayout>;
+using RefCountedDescriptorSetLayout = RefCounted<DescriptorSetLayout>;
+using RefCountedPipelineLayout = RefCounted<PipelineLayout>;
// Packed Vk resource descriptions.
// Most Vk types use many more bits than required to represent the underlying data.
-// Since ANGLE wants cache things like RenderPasses and Pipeline State Objects using
+// Since ANGLE wants to cache things like RenderPasses and Pipeline State Objects using
// hashing (and also needs to check equality) we can optimize these operations by
// using fewer bits. Hence the packed types.
//
@@ -86,19 +86,21 @@ bool operator==(const RenderPassDesc &lhs, const RenderPassDesc &rhs);
constexpr size_t kRenderPassDescSize = sizeof(RenderPassDesc);
static_assert(kRenderPassDescSize == 12, "Size check failed");
-struct alignas(8) PackedAttachmentOpsDesc final
+struct PackedAttachmentOpsDesc final
{
- uint8_t loadOp;
- uint8_t storeOp;
- uint8_t stencilLoadOp;
- uint8_t stencilStoreOp;
+ // VkAttachmentLoadOp is in range [0, 2], and VkAttachmentStoreOp is in range [0, 1].
+ uint16_t loadOp : 2;
+ uint16_t storeOp : 1;
+ uint16_t stencilLoadOp : 2;
+ uint16_t stencilStoreOp : 1;
- // 16-bits to force pad the structure to exactly 8 bytes.
- uint16_t initialLayout;
- uint16_t finalLayout;
+ // 5-bits to force pad the structure to exactly 2 bytes. Note that we currently don't support
+ // any of the extension layouts, whose values start at 1'000'000'000.
+ uint16_t initialLayout : 5;
+ uint16_t finalLayout : 5;
};
-static_assert(sizeof(PackedAttachmentOpsDesc) == 8, "Size check failed");
+static_assert(sizeof(PackedAttachmentOpsDesc) == 2, "Size check failed");
class AttachmentOpsArray final
{
@@ -122,15 +124,14 @@ class AttachmentOpsArray final
bool operator==(const AttachmentOpsArray &lhs, const AttachmentOpsArray &rhs);
-static_assert(sizeof(AttachmentOpsArray) == 80, "Size check failed");
+static_assert(sizeof(AttachmentOpsArray) == 20, "Size check failed");
struct PackedAttribDesc final
{
uint8_t format;
- // inputRate can also be used to store instancing divisors up to 255.
// TODO(http://anglebug.com/2672): Emulate divisors greater than UBYTE_MAX.
- uint8_t inputRate;
+ uint8_t divisor;
// Can only take 11 bits on NV.
uint16_t offset;
@@ -773,7 +774,7 @@ class DescriptorSetLayoutCache final : angle::NonCopyable
vk::BindingPointer<vk::DescriptorSetLayout> *descriptorSetLayoutOut);
private:
- std::unordered_map<vk::DescriptorSetLayoutDesc, vk::SharedDescriptorSetLayout> mPayload;
+ std::unordered_map<vk::DescriptorSetLayoutDesc, vk::RefCountedDescriptorSetLayout> mPayload;
};
class PipelineLayoutCache final : angle::NonCopyable
@@ -790,7 +791,7 @@ class PipelineLayoutCache final : angle::NonCopyable
vk::BindingPointer<vk::PipelineLayout> *pipelineLayoutOut);
private:
- std::unordered_map<vk::PipelineLayoutDesc, vk::SharedPipelineLayout> mPayload;
+ std::unordered_map<vk::PipelineLayoutDesc, vk::RefCountedPipelineLayout> mPayload;
};
// Some descriptor set and pipeline layout constants.
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
index eab9fb5eafc..4374bb5d4bd 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
@@ -25,118 +25,135 @@ constexpr unsigned int kComponentsPerVector = 4;
namespace rx
{
-namespace vk
-{
-void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
- const VkPhysicalDeviceFeatures &physicalDeviceFeatures,
- const VkQueueFamilyProperties &queueFamilyProperties,
- const gl::TextureCapsMap &textureCaps,
- gl::Caps *outCaps,
- gl::Extensions *outExtensions,
- gl::Limitations * /* outLimitations */)
+void RendererVk::ensureCapsInitialized() const
{
- outExtensions->setTextureExtensionSupport(textureCaps);
+ if (mCapsInitialized)
+ return;
+ mCapsInitialized = true;
+
+ ASSERT(mCurrentQueueFamilyIndex < mQueueFamilyProperties.size());
+ const VkQueueFamilyProperties &queueFamilyProperties =
+ mQueueFamilyProperties[mCurrentQueueFamilyIndex];
+
+ mNativeExtensions.setTextureExtensionSupport(mNativeTextureCaps);
// Enable this for simple buffer readback testing, but some functionality is missing.
// TODO(jmadill): Support full mapBufferRange extension.
- outExtensions->mapBuffer = true;
- outExtensions->mapBufferRange = true;
- outExtensions->textureStorage = true;
- outExtensions->framebufferBlit = true;
- outExtensions->copyTexture = true;
- outExtensions->debugMarker = true;
- outExtensions->robustness = true;
- outExtensions->textureBorderClamp = false; // not implemented yet
- outExtensions->translatedShaderSource = true;
+ mNativeExtensions.mapBuffer = true;
+ mNativeExtensions.mapBufferRange = true;
+ mNativeExtensions.textureStorage = true;
+ mNativeExtensions.framebufferBlit = true;
+ mNativeExtensions.copyTexture = true;
+ mNativeExtensions.copyCompressedTexture = true;
+ mNativeExtensions.debugMarker = true;
+ mNativeExtensions.robustness = true;
+ mNativeExtensions.textureBorderClamp = false; // not implemented yet
+ mNativeExtensions.translatedShaderSource = true;
+
+ mNativeExtensions.eglImage = true;
+ mNativeExtensions.eglImageExternal = true;
+ // TODO(geofflang): Support GL_OES_EGL_image_external_essl3. http://anglebug.com/2668
+ mNativeExtensions.eglImageExternalEssl3 = false;
+
+ // TODO: Enable this always and emulate instanced draws if any divisor exceeds the maximum
+ // supported. http://anglebug.com/2672
+ mNativeExtensions.instancedArraysANGLE = mMaxVertexAttribDivisor > 1;
// Only expose robust buffer access if the physical device supports it.
- outExtensions->robustBufferAccessBehavior = physicalDeviceFeatures.robustBufferAccess;
+ mNativeExtensions.robustBufferAccessBehavior = mPhysicalDeviceFeatures.robustBufferAccess;
+
+ mNativeExtensions.eglSync = true;
// We use secondary command buffers almost everywhere and they require a feature to be
// able to execute in the presence of queries. As a result, we won't support queries
// unless that feature is available.
- outExtensions->occlusionQueryBoolean = physicalDeviceFeatures.inheritedQueries;
+ mNativeExtensions.occlusionQueryBoolean = mPhysicalDeviceFeatures.inheritedQueries;
// From the Vulkan specs:
// > The number of valid bits in a timestamp value is determined by the
// > VkQueueFamilyProperties::timestampValidBits property of the queue on which the timestamp is
// > written. Timestamps are supported on any queue which reports a non-zero value for
// > timestampValidBits via vkGetPhysicalDeviceQueueFamilyProperties.
- outExtensions->disjointTimerQuery = queueFamilyProperties.timestampValidBits > 0;
- outExtensions->queryCounterBitsTimeElapsed = queueFamilyProperties.timestampValidBits;
- outExtensions->queryCounterBitsTimestamp = queueFamilyProperties.timestampValidBits;
-
- outExtensions->textureFilterAnisotropic =
- physicalDeviceFeatures.samplerAnisotropy &&
- physicalDeviceProperties.limits.maxSamplerAnisotropy > 1.0f;
- outExtensions->maxTextureAnisotropy = outExtensions->textureFilterAnisotropic
- ? physicalDeviceProperties.limits.maxSamplerAnisotropy
- : 0.0f;
+ mNativeExtensions.disjointTimerQuery = queueFamilyProperties.timestampValidBits > 0;
+ mNativeExtensions.queryCounterBitsTimeElapsed = queueFamilyProperties.timestampValidBits;
+ mNativeExtensions.queryCounterBitsTimestamp = queueFamilyProperties.timestampValidBits;
+
+ mNativeExtensions.textureFilterAnisotropic =
+ mPhysicalDeviceFeatures.samplerAnisotropy &&
+ mPhysicalDeviceProperties.limits.maxSamplerAnisotropy > 1.0f;
+ mNativeExtensions.maxTextureAnisotropy =
+ mNativeExtensions.textureFilterAnisotropic
+ ? mPhysicalDeviceProperties.limits.maxSamplerAnisotropy
+ : 0.0f;
// TODO(lucferron): Eventually remove everything above this line in this function as the caps
// get implemented.
// https://vulkan.lunarg.com/doc/view/1.0.30.0/linux/vkspec.chunked/ch31s02.html
- outCaps->maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
- outCaps->max3DTextureSize = physicalDeviceProperties.limits.maxImageDimension3D;
- outCaps->max2DTextureSize = physicalDeviceProperties.limits.maxImageDimension2D;
- outCaps->maxArrayTextureLayers = physicalDeviceProperties.limits.maxImageArrayLayers;
- outCaps->maxLODBias = physicalDeviceProperties.limits.maxSamplerLodBias;
- outCaps->maxCubeMapTextureSize = physicalDeviceProperties.limits.maxImageDimensionCube;
- outCaps->maxRenderbufferSize = outCaps->max2DTextureSize;
- outCaps->minAliasedPointSize =
- std::max(1.0f, physicalDeviceProperties.limits.pointSizeRange[0]);
- outCaps->maxAliasedPointSize = physicalDeviceProperties.limits.pointSizeRange[1];
-
- outCaps->minAliasedLineWidth = 1.0f;
- outCaps->maxAliasedLineWidth = 1.0f;
-
- outCaps->maxDrawBuffers =
- std::min<uint32_t>(physicalDeviceProperties.limits.maxColorAttachments,
- physicalDeviceProperties.limits.maxFragmentOutputAttachments);
- outCaps->maxFramebufferWidth = physicalDeviceProperties.limits.maxFramebufferWidth;
- outCaps->maxFramebufferHeight = physicalDeviceProperties.limits.maxFramebufferHeight;
- outCaps->maxColorAttachments = physicalDeviceProperties.limits.maxColorAttachments;
- outCaps->maxViewportWidth = physicalDeviceProperties.limits.maxViewportDimensions[0];
- outCaps->maxViewportHeight = physicalDeviceProperties.limits.maxViewportDimensions[1];
- outCaps->maxSampleMaskWords = physicalDeviceProperties.limits.maxSampleMaskWords;
- outCaps->maxColorTextureSamples = physicalDeviceProperties.limits.sampledImageColorSampleCounts;
- outCaps->maxDepthTextureSamples = physicalDeviceProperties.limits.sampledImageDepthSampleCounts;
- outCaps->maxIntegerSamples = physicalDeviceProperties.limits.sampledImageIntegerSampleCounts;
-
- outCaps->maxVertexAttributes = physicalDeviceProperties.limits.maxVertexInputAttributes;
- outCaps->maxVertexAttribBindings = physicalDeviceProperties.limits.maxVertexInputBindings;
- outCaps->maxVertexAttribRelativeOffset =
- physicalDeviceProperties.limits.maxVertexInputAttributeOffset;
- outCaps->maxVertexAttribStride = physicalDeviceProperties.limits.maxVertexInputBindingStride;
-
- outCaps->maxElementsIndices = std::numeric_limits<GLuint>::max();
- outCaps->maxElementsVertices = std::numeric_limits<GLuint>::max();
+ mNativeCaps.maxElementIndex = std::numeric_limits<GLuint>::max() - 1;
+ mNativeCaps.max3DTextureSize = mPhysicalDeviceProperties.limits.maxImageDimension3D;
+ mNativeCaps.max2DTextureSize = mPhysicalDeviceProperties.limits.maxImageDimension2D;
+ mNativeCaps.maxArrayTextureLayers = mPhysicalDeviceProperties.limits.maxImageArrayLayers;
+ mNativeCaps.maxLODBias = mPhysicalDeviceProperties.limits.maxSamplerLodBias;
+ mNativeCaps.maxCubeMapTextureSize = mPhysicalDeviceProperties.limits.maxImageDimensionCube;
+ mNativeCaps.maxRenderbufferSize = mNativeCaps.max2DTextureSize;
+ mNativeCaps.minAliasedPointSize =
+ std::max(1.0f, mPhysicalDeviceProperties.limits.pointSizeRange[0]);
+ mNativeCaps.maxAliasedPointSize = mPhysicalDeviceProperties.limits.pointSizeRange[1];
+
+ mNativeCaps.minAliasedLineWidth = 1.0f;
+ mNativeCaps.maxAliasedLineWidth = 1.0f;
+
+ mNativeCaps.maxDrawBuffers =
+ std::min<uint32_t>(mPhysicalDeviceProperties.limits.maxColorAttachments,
+ mPhysicalDeviceProperties.limits.maxFragmentOutputAttachments);
+ mNativeCaps.maxFramebufferWidth = mPhysicalDeviceProperties.limits.maxFramebufferWidth;
+ mNativeCaps.maxFramebufferHeight = mPhysicalDeviceProperties.limits.maxFramebufferHeight;
+ mNativeCaps.maxColorAttachments = mPhysicalDeviceProperties.limits.maxColorAttachments;
+ mNativeCaps.maxViewportWidth = mPhysicalDeviceProperties.limits.maxViewportDimensions[0];
+ mNativeCaps.maxViewportHeight = mPhysicalDeviceProperties.limits.maxViewportDimensions[1];
+ mNativeCaps.maxSampleMaskWords = mPhysicalDeviceProperties.limits.maxSampleMaskWords;
+ mNativeCaps.maxColorTextureSamples =
+ mPhysicalDeviceProperties.limits.sampledImageColorSampleCounts;
+ mNativeCaps.maxDepthTextureSamples =
+ mPhysicalDeviceProperties.limits.sampledImageDepthSampleCounts;
+ mNativeCaps.maxIntegerSamples =
+ mPhysicalDeviceProperties.limits.sampledImageIntegerSampleCounts;
+
+ mNativeCaps.maxVertexAttributes = mPhysicalDeviceProperties.limits.maxVertexInputAttributes;
+ mNativeCaps.maxVertexAttribBindings = mPhysicalDeviceProperties.limits.maxVertexInputBindings;
+ mNativeCaps.maxVertexAttribRelativeOffset =
+ mPhysicalDeviceProperties.limits.maxVertexInputAttributeOffset;
+ mNativeCaps.maxVertexAttribStride =
+ mPhysicalDeviceProperties.limits.maxVertexInputBindingStride;
+
+ mNativeCaps.maxElementsIndices = std::numeric_limits<GLuint>::max();
+ mNativeCaps.maxElementsVertices = std::numeric_limits<GLuint>::max();
// Looks like all floats are IEEE according to the docs here:
// https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/html/vkspec.html#spirvenv-precision-operation
- outCaps->vertexHighpFloat.setIEEEFloat();
- outCaps->vertexMediumpFloat.setIEEEFloat();
- outCaps->vertexLowpFloat.setIEEEFloat();
- outCaps->fragmentHighpFloat.setIEEEFloat();
- outCaps->fragmentMediumpFloat.setIEEEFloat();
- outCaps->fragmentLowpFloat.setIEEEFloat();
+ mNativeCaps.vertexHighpFloat.setIEEEFloat();
+ mNativeCaps.vertexMediumpFloat.setIEEEFloat();
+ mNativeCaps.vertexLowpFloat.setIEEEFloat();
+ mNativeCaps.fragmentHighpFloat.setIEEEFloat();
+ mNativeCaps.fragmentMediumpFloat.setIEEEFloat();
+ mNativeCaps.fragmentLowpFloat.setIEEEFloat();
// Can't find documentation on the int precision in Vulkan.
- outCaps->vertexHighpInt.setTwosComplementInt(32);
- outCaps->vertexMediumpInt.setTwosComplementInt(32);
- outCaps->vertexLowpInt.setTwosComplementInt(32);
- outCaps->fragmentHighpInt.setTwosComplementInt(32);
- outCaps->fragmentMediumpInt.setTwosComplementInt(32);
- outCaps->fragmentLowpInt.setTwosComplementInt(32);
+ mNativeCaps.vertexHighpInt.setTwosComplementInt(32);
+ mNativeCaps.vertexMediumpInt.setTwosComplementInt(32);
+ mNativeCaps.vertexLowpInt.setTwosComplementInt(32);
+ mNativeCaps.fragmentHighpInt.setTwosComplementInt(32);
+ mNativeCaps.fragmentMediumpInt.setTwosComplementInt(32);
+ mNativeCaps.fragmentLowpInt.setTwosComplementInt(32);
// TODO(lucferron): This is something we'll need to implement custom in the back-end.
// Vulkan doesn't do any waiting for you, our back-end code is going to manage sync objects,
// and we'll have to check that we've exceeded the max wait timeout. Also, this is ES 3.0 so
// we'll defer the implementation until we tackle the next version.
- // outCaps->maxServerWaitTimeout
+ // mNativeCaps.maxServerWaitTimeout
- GLuint maxUniformVectors = physicalDeviceProperties.limits.maxUniformBufferRange /
+ GLuint maxUniformVectors = mPhysicalDeviceProperties.limits.maxUniformBufferRange /
(sizeof(GLfloat) * kComponentsPerVector);
// Clamp the maxUniformVectors to 1024u, on AMD the maxUniformBufferRange is way too high.
@@ -146,24 +163,24 @@ void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
// Uniforms are implemented using a uniform buffer, so the max number of uniforms we can
// support is the max buffer range divided by the size of a single uniform (4X float).
- outCaps->maxVertexUniformVectors = maxUniformVectors;
- outCaps->maxShaderUniformComponents[gl::ShaderType::Vertex] = maxUniformComponents;
- outCaps->maxFragmentUniformVectors = maxUniformVectors;
- outCaps->maxShaderUniformComponents[gl::ShaderType::Fragment] = maxUniformComponents;
+ mNativeCaps.maxVertexUniformVectors = maxUniformVectors;
+ mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Vertex] = maxUniformComponents;
+ mNativeCaps.maxFragmentUniformVectors = maxUniformVectors;
+ mNativeCaps.maxShaderUniformComponents[gl::ShaderType::Fragment] = maxUniformComponents;
// TODO(jmadill): this is an ES 3.0 property and we can skip implementing it for now.
// This is maxDescriptorSetUniformBuffers minus the number of uniform buffers we
// reserve for internal variables. We reserve one per shader stage for default uniforms
// and likely one per shader stage for ANGLE internal variables.
- // outCaps->maxShaderUniformBlocks[gl::ShaderType::Vertex] = ...
+ // mNativeCaps.maxShaderUniformBlocks[gl::ShaderType::Vertex] = ...
// we use the same bindings on each stage, so the limitation is the same combined or not.
- outCaps->maxCombinedTextureImageUnits =
- physicalDeviceProperties.limits.maxPerStageDescriptorSamplers;
- outCaps->maxShaderTextureImageUnits[gl::ShaderType::Fragment] =
- physicalDeviceProperties.limits.maxPerStageDescriptorSamplers;
- outCaps->maxShaderTextureImageUnits[gl::ShaderType::Vertex] =
- physicalDeviceProperties.limits.maxPerStageDescriptorSamplers;
+ mNativeCaps.maxCombinedTextureImageUnits =
+ mPhysicalDeviceProperties.limits.maxPerStageDescriptorSamplers;
+ mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Fragment] =
+ mPhysicalDeviceProperties.limits.maxPerStageDescriptorSamplers;
+ mNativeCaps.maxShaderTextureImageUnits[gl::ShaderType::Vertex] =
+ mPhysicalDeviceProperties.limits.maxPerStageDescriptorSamplers;
// The max vertex output components should not include gl_Position.
// The gles2.0 section 2.10 states that "gl_Position is not a varying variable and does
@@ -173,11 +190,10 @@ void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
// and can often crash. Reserving an additional varying just for them bringing the total to 2.
// http://anglebug.com/2483
constexpr GLint kReservedVaryingCount = 2;
- outCaps->maxVaryingVectors =
- (physicalDeviceProperties.limits.maxVertexOutputComponents / 4) - kReservedVaryingCount;
- outCaps->maxVertexOutputComponents = outCaps->maxVaryingVectors * 4;
+ mNativeCaps.maxVaryingVectors =
+ (mPhysicalDeviceProperties.limits.maxVertexOutputComponents / 4) - kReservedVaryingCount;
+ mNativeCaps.maxVertexOutputComponents = mNativeCaps.maxVaryingVectors * 4;
}
-} // namespace vk
namespace egl_vk
{
@@ -233,8 +249,8 @@ egl::Config GenerateDefaultConfig(const RendererVk *renderer,
config.blueSize = colorFormat.blueBits;
config.alphaSize = colorFormat.alphaBits;
config.alphaMaskSize = 0;
- config.bindToTextureRGB = EGL_FALSE;
- config.bindToTextureRGBA = EGL_FALSE;
+ config.bindToTextureRGB = colorFormat.format == GL_RGB;
+ config.bindToTextureRGBA = colorFormat.format == GL_RGBA || colorFormat.format == GL_BGRA_EXT;
config.colorBufferType = EGL_RGB_BUFFER;
config.configCaveat = EGL_NONE;
config.conformant = 0;
@@ -246,7 +262,7 @@ egl::Config GenerateDefaultConfig(const RendererVk *renderer,
config.maxPBufferHeight = physicalDeviceProperties.limits.maxImageDimension2D;
config.maxPBufferPixels = ComputeMaximumPBufferPixels(physicalDeviceProperties);
config.maxSwapInterval = 1;
- config.minSwapInterval = 1;
+ config.minSwapInterval = 0;
config.nativeRenderable = EGL_TRUE;
config.nativeVisualID = 0;
config.nativeVisualType = EGL_NONE;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.h
index 151a1a5c226..e90ca7d0e9b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_caps_utils.h
@@ -30,17 +30,6 @@ struct FeaturesVk;
class DisplayVk;
-namespace vk
-{
-void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
- const VkPhysicalDeviceFeatures &physicalDeviceFeatures,
- const VkQueueFamilyProperties &queueFamilyProperties,
- const gl::TextureCapsMap &textureCaps,
- gl::Caps *outCaps,
- gl::Extensions *outExtensions,
- gl::Limitations * /* outLimitations */);
-} // namespace vk
-
namespace egl_vk
{
constexpr GLenum kConfigDepthStencilFormats[] = {GL_NONE, GL_DEPTH24_STENCIL8, GL_DEPTH_COMPONENT24,
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_map.json b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_map.json
index 15965b6bfd7..30ca499b4a6 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_map.json
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_map.json
@@ -39,52 +39,43 @@
"R8_SINT": "VK_FORMAT_R8_SINT",
"R8_USCALED": "VK_FORMAT_R8_USCALED",
"R8_SSCALED": "VK_FORMAT_R8_SSCALED",
- "R8_SRGB": "VK_FORMAT_R8_SRGB",
"R8G8_UNORM": "VK_FORMAT_R8G8_UNORM",
"R8G8_SNORM": "VK_FORMAT_R8G8_SNORM",
"R8G8_UINT": "VK_FORMAT_R8G8_UINT",
"R8G8_SINT": "VK_FORMAT_R8G8_SINT",
"R8G8_USCALED": "VK_FORMAT_R8G8_USCALED",
"R8G8_SSCALED": "VK_FORMAT_R8G8_SSCALED",
- "R8G8_SRGB": "VK_FORMAT_R8G8_SRGB",
"R8G8B8_UNORM": "VK_FORMAT_R8G8B8_UNORM",
"R8G8B8_SNORM": "VK_FORMAT_R8G8B8_SNORM",
"R8G8B8_UINT": "VK_FORMAT_R8G8B8_UINT",
"R8G8B8_SINT": "VK_FORMAT_R8G8B8_SINT",
"R8G8B8_USCALED": "VK_FORMAT_R8G8B8_USCALED",
"R8G8B8_SSCALED": "VK_FORMAT_R8G8B8_SSCALED",
- "R8G8B8_SRGB": "VK_FORMAT_R8G8B8_SRGB",
+ "R8G8B8_UNORM_SRGB": "VK_FORMAT_R8G8B8_SRGB",
"B8G8R8_UNORM": "VK_FORMAT_B8G8R8_UNORM",
"B8G8R8_SNORM": "VK_FORMAT_B8G8R8_SNORM",
"B8G8R8_UINT": "VK_FORMAT_B8G8R8_UINT",
"B8G8R8_SINT": "VK_FORMAT_B8G8R8_SINT",
- "B8G8R8_SRGB": "VK_FORMAT_B8G8R8_SRGB",
"R8G8B8A8_UNORM": "VK_FORMAT_R8G8B8A8_UNORM",
"R8G8B8A8_SNORM": "VK_FORMAT_R8G8B8A8_SNORM",
"R8G8B8A8_UINT": "VK_FORMAT_R8G8B8A8_UINT",
"R8G8B8A8_SINT": "VK_FORMAT_R8G8B8A8_SINT",
"R8G8B8A8_USCALED": "VK_FORMAT_R8G8B8A8_USCALED",
"R8G8B8A8_SSCALED": "VK_FORMAT_R8G8B8A8_SSCALED",
- "R8G8B8A8_SRGB": "VK_FORMAT_R8G8B8A8_SRGB",
+ "R8G8B8A8_UNORM_SRGB": "VK_FORMAT_R8G8B8A8_SRGB",
"B8G8R8A8_UNORM": "VK_FORMAT_B8G8R8A8_UNORM",
"B8G8R8A8_SNORM": "VK_FORMAT_B8G8R8A8_SNORM",
"B8G8R8A8_USCALED": "VK_FORMAT_B8G8R8A8_USCALED",
"B8G8R8A8_SSCALED": "VK_FORMAT_B8G8R8A8_SSCALED",
"B8G8R8A8_UINT": "VK_FORMAT_B8G8R8A8_UINT",
"B8G8R8A8_SINT": "VK_FORMAT_B8G8R8A8_SINT",
- "B8G8R8A8_SRGB": "VK_FORMAT_B8G8R8A8_SRGB",
- "A2R10G10B10_UNORM_PACK32": "VK_FORMAT_A2R10G10B10_UNORM_PACK32",
- "A2R10G10B10_SNORM_PACK32": "VK_FORMAT_A2R10G10B10_SNORM_PACK32",
- "A2R10G10B10_USCALED_PACK32": "VK_FORMAT_A2R10G10B10_USCALED_PACK32",
- "A2R10G10B10_SSCALED_PACK32": "VK_FORMAT_A2R10G10B10_SSCALED_PACK32",
- "A2R10G10B10_UINT_PACK32": "VK_FORMAT_A2R10G10B10_UINT_PACK32",
- "A2R10G10B10_SINT_PACK32": "VK_FORMAT_A2R10G10B10_SINT_PACK32",
- "A2B10G10R10_UNORM_PACK32": "VK_FORMAT_A2B10G10R10_UNORM_PACK32",
- "A2B10G10R10_SNORM_PACK32": "VK_FORMAT_A2B10G10R10_SNORM_PACK32",
- "A2B10G10R10_USCALED_PACK32": "VK_FORMAT_A2B10G10R10_USCALED_PACK32",
- "A2B10G10R10_SSCALED_PACK32": "VK_FORMAT_A2B10G10R10_SSCALED_PACK32",
- "A2B10G10R10_UINT_PACK32": "VK_FORMAT_A2B10G10R10_UINT_PACK32",
- "A2B10G10R10_SINT_PACK32": "VK_FORMAT_A2B10G10R10_SINT_PACK32",
+ "B8G8R8A8_UNORM_SRGB": "VK_FORMAT_B8G8R8A8_SRGB",
+ "R10G10B10A2_UNORM": "VK_FORMAT_A2B10G10R10_UNORM_PACK32",
+ "R10G10B10A2_SNORM": "VK_FORMAT_A2B10G10R10_SNORM_PACK32",
+ "R10G10B10A2_USCALED": "VK_FORMAT_A2B10G10R10_USCALED_PACK32",
+ "R10G10B10A2_SSCALED": "VK_FORMAT_A2B10G10R10_SSCALED_PACK32",
+ "R10G10B10A2_UINT": "VK_FORMAT_A2B10G10R10_UINT_PACK32",
+ "R10G10B10A2_SINT": "VK_FORMAT_A2B10G10R10_SINT_PACK32",
"R16_UNORM": "VK_FORMAT_R16_UNORM",
"R16_SNORM": "VK_FORMAT_R16_SNORM",
"R16_USCALED": "VK_FORMAT_R16_USCALED",
@@ -147,21 +138,17 @@
"D24_UNORM_S8_UINT": "VK_FORMAT_D24_UNORM_S8_UINT",
"D32_FLOAT_S8X24_UINT": "VK_FORMAT_D32_SFLOAT_S8_UINT",
"BC1_RGB_UNORM_BLOCK": "VK_FORMAT_BC1_RGB_UNORM_BLOCK",
- "BC1_RGB_SRGB_BLOCK": "VK_FORMAT_BC1_RGB_SRGB_BLOCK",
+ "BC1_RGB_UNORM_SRGB_BLOCK": "VK_FORMAT_BC1_RGB_SRGB_BLOCK",
"BC1_RGBA_UNORM_BLOCK": "VK_FORMAT_BC1_RGBA_UNORM_BLOCK",
- "BC1_RGBA_SRGB_BLOCK": "VK_FORMAT_BC1_RGBA_SRGB_BLOCK",
- "BC2_UNORM_BLOCK": "VK_FORMAT_BC2_UNORM_BLOCK",
- "BC2_SRGB_BLOCK": "VK_FORMAT_BC2_SRGB_BLOCK",
- "BC3_UNORM_BLOCK": "VK_FORMAT_BC3_UNORM_BLOCK",
- "BC3_SRGB_BLOCK": "VK_FORMAT_BC3_SRGB_BLOCK",
- "BC4_UNORM_BLOCK": "VK_FORMAT_BC4_UNORM_BLOCK",
- "BC4_SNORM_BLOCK": "VK_FORMAT_BC4_SNORM_BLOCK",
- "BC5_UNORM_BLOCK": "VK_FORMAT_BC5_UNORM_BLOCK",
- "BC5_SNORM_BLOCK": "VK_FORMAT_BC5_SNORM_BLOCK",
- "BC6H_UFLOAT_BLOCK": "VK_FORMAT_BC6H_UFLOAT_BLOCK",
- "BC6H_SFLOAT_BLOCK": "VK_FORMAT_BC6H_SFLOAT_BLOCK",
- "BC7_UNORM_BLOCK": "VK_FORMAT_BC7_UNORM_BLOCK",
- "BC7_SRGB_BLOCK": "VK_FORMAT_BC7_SRGB_BLOCK",
+ "BC1_RGBA_UNORM_SRGB_BLOCK": "VK_FORMAT_BC1_RGBA_SRGB_BLOCK",
+ "BC2_RGBA_UNORM_BLOCK": "VK_FORMAT_BC2_UNORM_BLOCK",
+ "BC2_RGBA_UNORM_SRGB_BLOCK": "VK_FORMAT_BC2_SRGB_BLOCK",
+ "BC3_RGBA_UNORM_BLOCK": "VK_FORMAT_BC3_UNORM_BLOCK",
+ "BC3_RGBA_UNORM_SRGB_BLOCK": "VK_FORMAT_BC3_SRGB_BLOCK",
+ "BPTC_RGB_UNSIGNED_FLOAT_BLOCK": "VK_FORMAT_BC6H_UFLOAT_BLOCK",
+ "BPTC_RGB_SIGNED_FLOAT_BLOCK": "VK_FORMAT_BC6H_SFLOAT_BLOCK",
+ "BPTC_RGBA_UNORM_BLOCK": "VK_FORMAT_BC7_UNORM_BLOCK",
+ "BPTC_SRGB_ALPHA_UNORM_BLOCK": "VK_FORMAT_BC7_SRGB_BLOCK",
"ETC2_R8G8B8_UNORM_BLOCK": "VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK",
"ETC2_R8G8B8_SRGB_BLOCK": "VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK",
"ETC2_R8G8B8A1_UNORM_BLOCK": "VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK",
@@ -202,6 +189,12 @@
"ASTC_12x12_SRGB_BLOCK": "VK_FORMAT_ASTC_12x12_SRGB_BLOCK"
},
"overrides": {
+ "A16_FLOAT": {
+ "texture": "R16_FLOAT"
+ },
+ "A32_FLOAT": {
+ "texture": "R32_FLOAT"
+ },
"A8_UNORM": {
"texture": "R8_UNORM"
},
@@ -220,6 +213,9 @@
"R8G8B8_UNORM": {
"texture": "R8G8B8A8_UNORM"
},
+ "R8G8B8_UNORM_SRGB": {
+ "texture": "R8G8B8A8_UNORM_SRGB"
+ },
"B8G8R8X8_UNORM": {
"buffer": "NONE",
"texture": "B8G8R8A8_UNORM"
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
index 9392b3c419d..0d793c0461c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_table_autogen.cpp
@@ -1,7 +1,7 @@
// GENERATED FILE - DO NOT EDIT.
// Generated by gen_vk_format_table.py using data from vk_format_map.json
//
-// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Copyright 2019 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.
//
@@ -27,7 +27,11 @@ void Format::initialize(RendererVk *renderer, const angle::Format &angleFormat)
switch (angleFormat.id)
{
case angle::FormatID::A16_FLOAT:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_ALPHA16F_EXT;
+ textureFormatID = angle::FormatID::R16_FLOAT;
+ vkTextureFormat = VK_FORMAT_R16_SFLOAT;
+ textureInitializerFunction = nullptr;
+
break;
case angle::FormatID::A1R5G5B5_UNORM:
@@ -43,7 +47,11 @@ void Format::initialize(RendererVk *renderer, const angle::Format &angleFormat)
break;
case angle::FormatID::A32_FLOAT:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_ALPHA32F_EXT;
+ textureFormatID = angle::FormatID::R32_FLOAT;
+ vkTextureFormat = VK_FORMAT_R32_SFLOAT;
+ textureInitializerFunction = nullptr;
+
break;
case angle::FormatID::A8_UNORM:
@@ -447,7 +455,15 @@ void Format::initialize(RendererVk *renderer, const angle::Format &angleFormat)
break;
case angle::FormatID::B8G8R8A8_UNORM_SRGB:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_BGRA8_SRGB_ANGLEX;
+ textureFormatID = angle::FormatID::B8G8R8A8_UNORM_SRGB;
+ vkTextureFormat = VK_FORMAT_B8G8R8A8_SRGB;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::B8G8R8A8_UNORM_SRGB;
+ vkBufferFormat = VK_FORMAT_B8G8R8A8_SRGB;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = CopyNativeVertexData<GLubyte, 4, 4, 0>;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::B8G8R8X8_UNORM:
@@ -475,7 +491,15 @@ void Format::initialize(RendererVk *renderer, const angle::Format &angleFormat)
break;
case angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT;
+ textureFormatID = angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BC1_RGBA_UNORM_SRGB_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC1_RGBA_SRGB_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::BC1_RGB_UNORM_BLOCK:
@@ -491,39 +515,111 @@ void Format::initialize(RendererVk *renderer, const angle::Format &angleFormat)
break;
case angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+ textureFormatID = angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC1_RGB_SRGB_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BC1_RGB_UNORM_SRGB_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC1_RGB_SRGB_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::BC2_RGBA_UNORM_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
+ textureFormatID = angle::FormatID::BC2_RGBA_UNORM_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC2_UNORM_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BC2_RGBA_UNORM_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC2_UNORM_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ textureFormatID = angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC2_SRGB_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BC2_RGBA_UNORM_SRGB_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC2_SRGB_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::BC3_RGBA_UNORM_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
+ textureFormatID = angle::FormatID::BC3_RGBA_UNORM_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC3_UNORM_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BC3_RGBA_UNORM_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC3_UNORM_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ textureFormatID = angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC3_SRGB_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BC3_RGBA_UNORM_SRGB_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC3_SRGB_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::BPTC_RGBA_UNORM_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_EXT;
+ textureFormatID = angle::FormatID::BPTC_RGBA_UNORM_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC7_UNORM_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BPTC_RGBA_UNORM_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC7_UNORM_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::BPTC_RGB_SIGNED_FLOAT_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;
+ textureFormatID = angle::FormatID::BPTC_RGB_SIGNED_FLOAT_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC6H_SFLOAT_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BPTC_RGB_SIGNED_FLOAT_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC6H_SFLOAT_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::BPTC_RGB_UNSIGNED_FLOAT_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;
+ textureFormatID = angle::FormatID::BPTC_RGB_UNSIGNED_FLOAT_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC6H_UFLOAT_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BPTC_RGB_UNSIGNED_FLOAT_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC6H_UFLOAT_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::BPTC_SRGB_ALPHA_UNORM_BLOCK:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT;
+ textureFormatID = angle::FormatID::BPTC_SRGB_ALPHA_UNORM_BLOCK;
+ vkTextureFormat = VK_FORMAT_BC7_SRGB_BLOCK;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::BPTC_SRGB_ALPHA_UNORM_BLOCK;
+ vkBufferFormat = VK_FORMAT_BC7_SRGB_BLOCK;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::D16_UNORM:
@@ -767,27 +863,75 @@ void Format::initialize(RendererVk *renderer, const angle::Format &angleFormat)
break;
case angle::FormatID::R10G10B10A2_SINT:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_RGB10_A2_SINT_ANGLEX;
+ textureFormatID = angle::FormatID::R10G10B10A2_SINT;
+ vkTextureFormat = VK_FORMAT_A2B10G10R10_SINT_PACK32;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::R10G10B10A2_SINT;
+ vkBufferFormat = VK_FORMAT_A2B10G10R10_SINT_PACK32;
+ vkBufferFormatIsPacked = true;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::R10G10B10A2_SNORM:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_RGB10_A2_SNORM_ANGLEX;
+ textureFormatID = angle::FormatID::R10G10B10A2_SNORM;
+ vkTextureFormat = VK_FORMAT_A2B10G10R10_SNORM_PACK32;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::R10G10B10A2_SNORM;
+ vkBufferFormat = VK_FORMAT_A2B10G10R10_SNORM_PACK32;
+ vkBufferFormatIsPacked = true;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::R10G10B10A2_SSCALED:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_RGB10_A2_SSCALED_ANGLEX;
+ textureFormatID = angle::FormatID::R10G10B10A2_SSCALED;
+ vkTextureFormat = VK_FORMAT_A2B10G10R10_SSCALED_PACK32;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::R10G10B10A2_SSCALED;
+ vkBufferFormat = VK_FORMAT_A2B10G10R10_SSCALED_PACK32;
+ vkBufferFormatIsPacked = true;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::R10G10B10A2_UINT:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_RGB10_A2UI;
+ textureFormatID = angle::FormatID::R10G10B10A2_UINT;
+ vkTextureFormat = VK_FORMAT_A2B10G10R10_UINT_PACK32;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::R10G10B10A2_UINT;
+ vkBufferFormat = VK_FORMAT_A2B10G10R10_UINT_PACK32;
+ vkBufferFormatIsPacked = true;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::R10G10B10A2_UNORM:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_RGB10_A2;
+ textureFormatID = angle::FormatID::R10G10B10A2_UNORM;
+ vkTextureFormat = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::R10G10B10A2_UNORM;
+ vkBufferFormat = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
+ vkBufferFormatIsPacked = true;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::R10G10B10A2_USCALED:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_RGB10_A2_USCALED_ANGLEX;
+ textureFormatID = angle::FormatID::R10G10B10A2_USCALED;
+ vkTextureFormat = VK_FORMAT_A2B10G10R10_USCALED_PACK32;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::R10G10B10A2_USCALED;
+ vkBufferFormat = VK_FORMAT_A2B10G10R10_USCALED_PACK32;
+ vkBufferFormatIsPacked = true;
+ vertexLoadFunction = nullptr;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::R11G11B10_FLOAT:
@@ -1540,7 +1684,15 @@ void Format::initialize(RendererVk *renderer, const angle::Format &angleFormat)
break;
case angle::FormatID::R8G8B8A8_UNORM_SRGB:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_SRGB8_ALPHA8;
+ textureFormatID = angle::FormatID::R8G8B8A8_UNORM_SRGB;
+ vkTextureFormat = VK_FORMAT_R8G8B8A8_SRGB;
+ textureInitializerFunction = nullptr;
+ bufferFormatID = angle::FormatID::R8G8B8A8_UNORM_SRGB;
+ vkBufferFormat = VK_FORMAT_R8G8B8A8_SRGB;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = CopyNativeVertexData<GLubyte, 4, 4, 0>;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::R8G8B8A8_USCALED:
@@ -1628,7 +1780,15 @@ void Format::initialize(RendererVk *renderer, const angle::Format &angleFormat)
break;
case angle::FormatID::R8G8B8_UNORM_SRGB:
- // This format is not implemented in Vulkan.
+ internalFormat = GL_SRGB8;
+ textureFormatID = angle::FormatID::R8G8B8A8_UNORM_SRGB;
+ vkTextureFormat = VK_FORMAT_R8G8B8A8_SRGB;
+ textureInitializerFunction = Initialize4ComponentData<GLubyte, 0x00, 0x00, 0x00, 0xFF>;
+ bufferFormatID = angle::FormatID::R8G8B8_UNORM_SRGB;
+ vkBufferFormat = VK_FORMAT_R8G8B8_SRGB;
+ vkBufferFormatIsPacked = false;
+ vertexLoadFunction = CopyNativeVertexData<GLubyte, 3, 3, 0>;
+ vertexLoadRequiresConversion = false;
break;
case angle::FormatID::R8G8B8_USCALED:
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.cpp
index a818a24a5d2..8e18f031fd7 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.cpp
@@ -65,17 +65,6 @@ void FillTextureFormatCaps(RendererVk *renderer, VkFormat format, gl::TextureCap
}
}
-bool HasFullTextureFormatSupport(RendererVk *renderer, VkFormat vkFormat)
-{
- constexpr uint32_t kBitsColor = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
- VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
- VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
- constexpr uint32_t kBitsDepth = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
-
- return renderer->hasTextureFormatFeatureBits(vkFormat, kBitsColor) ||
- renderer->hasTextureFormatFeatureBits(vkFormat, kBitsDepth);
-}
-
bool HasFullBufferFormatSupport(RendererVk *renderer, VkFormat vkFormat)
{
return renderer->hasBufferFormatFeatureBits(vkFormat, VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT);
@@ -153,6 +142,42 @@ void Format::initBufferFallback(RendererVk *renderer, const BufferFormatInitInfo
vertexLoadRequiresConversion = info[i].vertexLoadRequiresConversion;
}
+size_t Format::getImageCopyBufferAlignment() const
+{
+ // vkCmdCopyBufferToImage must have an offset that is a multiple of 4 as well as a multiple
+ // of the pixel block size.
+ // https://www.khronos.org/registry/vulkan/specs/1.0/man/html/VkBufferImageCopy.html
+ //
+ // We need lcm(4, blockSize) (lcm = least common multiplier). Since 4 is constant, this
+ // can be calculated as:
+ //
+ // | blockSize blockSize % 4 == 0
+ // | 4 * blockSize blockSize % 4 == 1
+ // lcm(4, blockSize) = <
+ // | 2 * blockSize blockSize % 4 == 2
+ // | 4 * blockSize blockSize % 4 == 3
+ //
+ // This means:
+ //
+ // - blockSize % 2 != 0 gives a 4x multiplier
+ // - else blockSize % 4 != 0 gives a 2x multiplier
+ // - else there's no multiplier.
+ //
+ const angle::Format &format = textureFormat();
+
+ if (!format.isBlock)
+ {
+ // Currently, 4 is sufficient for any known non-block format.
+ return 4;
+ }
+
+ const size_t blockSize = format.pixelBytes;
+ const size_t multiplier = blockSize % 2 != 0 ? 4 : blockSize % 4 != 0 ? 2 : 1;
+ const size_t alignment = multiplier * blockSize;
+
+ return alignment;
+}
+
bool operator==(const Format &lhs, const Format &rhs)
{
return &lhs == &rhs;
@@ -203,6 +228,17 @@ void FormatTable::initialize(RendererVk *renderer,
}
} // namespace vk
+bool HasFullTextureFormatSupport(RendererVk *renderer, VkFormat vkFormat)
+{
+ constexpr uint32_t kBitsColor = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
+ VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT |
+ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
+ constexpr uint32_t kBitsDepth = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
+
+ return renderer->hasTextureFormatFeatureBits(vkFormat, kBitsColor) ||
+ renderer->hasTextureFormatFeatureBits(vkFormat, kBitsDepth);
+}
+
size_t GetVertexInputAlignment(const vk::Format &format)
{
const angle::Format &bufferFormat = format.bufferFormat();
@@ -216,6 +252,14 @@ void MapSwizzleState(const vk::Format &format,
{
const angle::Format &angleFormat = format.angleFormat();
+ if (angleFormat.isBlock)
+ {
+ // No need to override swizzles for compressed images, as they are not emulated.
+ // Either way, angleFormat.xBits (with x in {red, green, blue, alpha}) is zero for blocked
+ // formats so the following code would incorrectly turn its swizzle to (0, 0, 0, 1).
+ return;
+ }
+
switch (format.internalFormat)
{
case GL_LUMINANCE8_OES:
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.h
index e7d1b20c7de..cd02c457aff 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_format_utils.h
@@ -66,6 +66,13 @@ struct Format final : private angle::NonCopyable
const angle::Format &textureFormat() const { return angle::Format::Get(textureFormatID); }
const angle::Format &bufferFormat() const { return angle::Format::Get(bufferFormatID); }
+ // Get buffer alignment for image-copy operations (to or from a buffer).
+ const gl::InternalFormat &getInternalFormatInfo(GLenum type) const
+ {
+ return gl::GetInternalFormatInfo(internalFormat, type);
+ }
+ size_t getImageCopyBufferAlignment() const;
+
angle::FormatID angleFormatID;
GLenum internalFormat;
angle::FormatID textureFormatID;
@@ -121,6 +128,9 @@ const VkFormatProperties &GetMandatoryFormatSupport(VkFormat vkFormat);
} // namespace vk
+// Checks if a vkFormat supports all the features needed to use it as a GL texture format
+bool HasFullTextureFormatSupport(RendererVk *renderer, VkFormat vkFormat);
+
// Returns the alignment for a buffer to be used with the vertex input stage in Vulkan. This
// calculation is listed in the Vulkan spec at the end of the section 'Vertex Input Description'.
size_t GetVertexInputAlignment(const vk::Format &format);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.cpp
index e62600504fb..8ba4f80d299 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.cpp
@@ -9,10 +9,13 @@
#include "libANGLE/renderer/vulkan/vk_helpers.h"
#include "common/utilities.h"
+#include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/BufferVk.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
+#include "libANGLE/renderer/vulkan/FramebufferVk.h"
#include "libANGLE/renderer/vulkan/RendererVk.h"
#include "libANGLE/renderer/vulkan/vk_utils.h"
+#include "third_party/trace_event/trace_event.h"
namespace rx
{
@@ -26,76 +29,168 @@ constexpr VkBufferUsageFlags kLineLoopDynamicBufferUsage =
constexpr int kLineLoopDynamicBufferMinSize = 1024 * 1024;
// This is an arbitrary max. We can change this later if necessary.
-constexpr uint32_t kDefaultDescriptorPoolMaxSets = 2048;
-
-// Gets access flags based on layout.
-VkAccessFlags GetSrcLayoutAccessFlags(VkImageLayout layout)
-{
- switch (layout)
- {
- case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
- return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
- return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
- case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
- return VK_ACCESS_TRANSFER_WRITE_BIT;
- case VK_IMAGE_LAYOUT_PREINITIALIZED:
- return VK_ACCESS_HOST_WRITE_BIT;
- case VK_IMAGE_LAYOUT_GENERAL:
- return VK_ACCESS_MEMORY_WRITE_BIT;
- case VK_IMAGE_LAYOUT_UNDEFINED:
- // Note: source access mask never needs a READ bit, as WAR hazards
- // don't need memory barriers (just execution barriers).
- case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
- case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
- case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
- return 0;
- default:
- // TODO(jmadill): Investigate other flags.
- UNREACHABLE();
- return 0;
- }
-}
-
-VkAccessFlags GetDstLayoutAccessFlags(VkImageLayout layout)
-{
- switch (layout)
+constexpr uint32_t kDefaultDescriptorPoolMaxSets = 128;
+
+struct ImageMemoryBarrierData
+{
+ // The Vk layout corresponding to the ImageLayout key.
+ VkImageLayout layout;
+ // The stage in which the image is used (or Bottom/Top if not using any specific stage). Unless
+ // Bottom/Top (Bottom used for transition to and Top used for transition from), the two values
+ // should match.
+ VkPipelineStageFlags dstStageMask;
+ VkPipelineStageFlags srcStageMask;
+ // Access mask when transitioning into this layout.
+ VkAccessFlags dstAccessMask;
+ // Access mask when transitioning out from this layout. Note that source access mask never
+ // needs a READ bit, as WAR hazards don't need memory barriers (just execution barriers).
+ VkAccessFlags srcAccessMask;
+
+ // If access is read-only, the execution barrier can be skipped altogether if retransitioning to
+ // the same layout. This is because read-after-read does not need an execution or memory
+ // barrier.
+ bool isReadOnlyAccess;
+};
+
+// clang-format off
+constexpr angle::PackedEnumMap<ImageLayout, ImageMemoryBarrierData> kImageMemoryBarrierData = {
+ {
+ ImageLayout::Undefined,
+ {
+ VK_IMAGE_LAYOUT_UNDEFINED,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ // Transition to: we don't expect to transition into Undefined.
+ 0,
+ // Transition from: there's no data in the image to care about.
+ 0,
+ true,
+ },
+ },
+ {
+ ImageLayout::ExternalPreInitialized,
+ {
+ VK_IMAGE_LAYOUT_PREINITIALIZED,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
+ // Transition to: we don't expect to transition into PreInitialized.
+ 0,
+ // Transition from: all writes must finish before barrier.
+ VK_ACCESS_MEMORY_WRITE_BIT,
+ false,
+ },
+ },
+ {
+ ImageLayout::TransferSrc,
+ {
+ VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ // Transition to: all reads must happen after barrier.
+ VK_ACCESS_TRANSFER_READ_BIT,
+ // Transition from: RAR and WAR don't need memory barrier.
+ 0,
+ true,
+ },
+ },
+ {
+ ImageLayout::TransferDst,
+ {
+ VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ // Transition to: all writes must happen after barrier.
+ VK_ACCESS_TRANSFER_WRITE_BIT,
+ // Transition from: all writes must finish before barrier.
+ VK_ACCESS_TRANSFER_WRITE_BIT,
+ false,
+ },
+ },
+ {
+ ImageLayout::ComputeShaderReadOnly,
+ {
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
+ VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
+ // Transition to: all reads must happen after barrier.
+ VK_ACCESS_SHADER_READ_BIT,
+ // Transition from: RAR and WAR don't need memory barrier.
+ 0,
+ true,
+ },
+ },
+ {
+ ImageLayout::ComputeShaderWrite,
+ {
+ VK_IMAGE_LAYOUT_GENERAL,
+ VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
+ VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
+ // Transition to: all reads and writes must happen after barrier.
+ VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT,
+ // Transition from: all writes must finish before barrier.
+ VK_ACCESS_SHADER_WRITE_BIT,
+ false,
+ },
+ },
+ {
+ ImageLayout::FragmentShaderReadOnly,
+ {
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ // Transition to: all reads must happen after barrier.
+ VK_ACCESS_SHADER_READ_BIT,
+ // Transition from: RAR and WAR don't need memory barrier.
+ 0,
+ true,
+ },
+ },
+ {
+ ImageLayout::ColorAttachment,
+ {
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ // Transition to: all reads and writes must happen after barrier.
+ VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+ // Transition from: all writes must finish before barrier.
+ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
+ false,
+ },
+ },
+ {
+ ImageLayout::DepthStencilAttachment,
+ {
+ VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+ VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
+ // Transition to: all reads and writes must happen after barrier.
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ // Transition from: all writes must finish before barrier.
+ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
+ false,
+ },
+ },
{
- case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
- return VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
- case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
- return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
- VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
- case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL:
- return VK_ACCESS_TRANSFER_READ_BIT;
- case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL:
- return VK_ACCESS_TRANSFER_WRITE_BIT;
- case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
- // vkQueuePresentKHR automatically performs the appropriate memory barriers:
+ ImageLayout::Present,
+ {
+ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ // transition to: vkQueuePresentKHR automatically performs the appropriate memory barriers:
//
// > Any writes to memory backing the images referenced by the pImageIndices and
// > pSwapchains members of pPresentInfo, that are available before vkQueuePresentKHR
// > is executed, are automatically made visible to the read access performed by the
// > presentation engine.
- return 0;
- case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
- return VK_ACCESS_SHADER_READ_BIT;
- case VK_IMAGE_LAYOUT_GENERAL:
- // NOTE(syoussefi): compute writes to images require them to be in GENERAL layout,
- // and in those cases VK_ACCESS_SHADER_READ/WRITE_BIT are sufficient. However, the
- // GENERAL layout covers so many cases that we can't narrow the access flags here.
- // The possible solutions are either adding VK_IMAGE_LAYOUT_SHADER_WRITE_OPTIMAL to
- // Vulkan, or tracking the necessary access mask alongside the old layout.
- return VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
- case VK_IMAGE_LAYOUT_PREINITIALIZED:
- case VK_IMAGE_LAYOUT_UNDEFINED:
- return 0;
- default:
- // TODO(jmadill): Investigate other flags.
- UNREACHABLE();
- return 0;
- }
-}
+ 0,
+ // Transition from: RAR and WAR don't need memory barrier.
+ 0,
+ true,
+ },
+ },
+};
+// clang-format on
VkImageCreateFlags GetImageCreateFlags(gl::TextureType textureType)
{
@@ -122,6 +217,20 @@ DynamicBuffer::DynamicBuffer(VkBufferUsageFlags usage, size_t minSize, bool host
mAlignment(0)
{}
+DynamicBuffer::DynamicBuffer(DynamicBuffer &&other)
+ : mUsage(other.mUsage),
+ mHostVisible(other.mHostVisible),
+ mMinSize(other.mMinSize),
+ mBuffer(other.mBuffer),
+ mNextAllocationOffset(other.mNextAllocationOffset),
+ mLastFlushOrInvalidateOffset(other.mLastFlushOrInvalidateOffset),
+ mSize(other.mSize),
+ mAlignment(other.mAlignment),
+ mRetainedBuffers(std::move(other.mRetainedBuffers))
+{
+ other.mBuffer = nullptr;
+}
+
void DynamicBuffer::init(size_t alignment, RendererVk *renderer)
{
// Workaround for the mock ICD not supporting allocations greater than 0x1000.
@@ -131,13 +240,13 @@ void DynamicBuffer::init(size_t alignment, RendererVk *renderer)
mMinSize = std::min<size_t>(mMinSize, 0x1000);
}
- ASSERT(alignment > 0);
- mAlignment = std::max(
- alignment,
- static_cast<size_t>(renderer->getPhysicalDeviceProperties().limits.nonCoherentAtomSize));
+ updateAlignment(renderer, alignment);
}
-DynamicBuffer::~DynamicBuffer() {}
+DynamicBuffer::~DynamicBuffer()
+{
+ ASSERT(mBuffer == nullptr);
+}
angle::Result DynamicBuffer::allocate(Context *context,
size_t sizeInBytes,
@@ -292,6 +401,27 @@ void DynamicBuffer::destroy(VkDevice device)
}
}
+void DynamicBuffer::updateAlignment(RendererVk *renderer, size_t alignment)
+{
+ ASSERT(alignment > 0);
+
+ size_t atomSize =
+ static_cast<size_t>(renderer->getPhysicalDeviceProperties().limits.nonCoherentAtomSize);
+
+ // We need lcm(alignment, atomSize), we are assuming one divides the other so std::max() could
+ // be used instead.
+ ASSERT(alignment % atomSize == 0 || atomSize % alignment == 0);
+ alignment = std::max(alignment, atomSize);
+
+ // If alignment has changed, make sure the next allocation is done at an aligned offset.
+ if (alignment != mAlignment)
+ {
+ mNextAllocationOffset = roundUp(mNextAllocationOffset, static_cast<uint32_t>(alignment));
+ }
+
+ mAlignment = alignment;
+}
+
void DynamicBuffer::setMinimumSizeForTesting(size_t minSize)
{
// This will really only have an effect next time we call allocate.
@@ -386,13 +516,13 @@ angle::Result DynamicDescriptorPool::init(Context *context,
mPoolSizes[i].descriptorCount *= mMaxSetsPerPool;
}
- mDescriptorPools.push_back(new SharedDescriptorPoolHelper());
+ mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper());
return mDescriptorPools[0]->get().init(context, mPoolSizes, mMaxSetsPerPool);
}
void DynamicDescriptorPool::destroy(VkDevice device)
{
- for (SharedDescriptorPoolHelper *pool : mDescriptorPools)
+ for (RefCountedDescriptorPoolHelper *pool : mDescriptorPools)
{
ASSERT(!pool->isReferenced());
pool->get().destroy(device);
@@ -405,7 +535,7 @@ void DynamicDescriptorPool::destroy(VkDevice device)
angle::Result DynamicDescriptorPool::allocateSets(Context *context,
const VkDescriptorSetLayout *descriptorSetLayout,
uint32_t descriptorSetCount,
- SharedDescriptorPoolBinding *bindingOut,
+ RefCountedDescriptorPoolBinding *bindingOut,
VkDescriptorSet *descriptorSetsOut)
{
if (!bindingOut->valid() || !bindingOut->get().hasCapacity(descriptorSetCount))
@@ -450,7 +580,7 @@ angle::Result DynamicDescriptorPool::allocateNewPool(Context *context)
if (!found)
{
- mDescriptorPools.push_back(new SharedDescriptorPoolHelper());
+ mDescriptorPools.push_back(new RefCountedDescriptorPoolHelper());
mCurrentPoolIndex = mDescriptorPools.size() - 1;
static constexpr size_t kMaxPools = 99999;
@@ -838,6 +968,7 @@ angle::Result LineLoopHelper::getIndexBufferForElementArrayBuffer(ContextVk *con
{
if (glIndexType == gl::DrawElementsType::UnsignedByte)
{
+ TRACE_EVENT0("gpu.angle", "LineLoopHelper::getIndexBufferForElementArrayBuffer");
// Needed before reading buffer or we could get stale data.
ANGLE_TRY(contextVk->getRenderer()->finish(contextVk));
@@ -955,8 +1086,8 @@ angle::Result BufferHelper::init(Context *context,
{
mSize = createInfo.size;
ANGLE_VK_TRY(context, mBuffer.init(context->getDevice(), createInfo));
- return vk::AllocateBufferMemory(context, memoryPropertyFlags, &mMemoryPropertyFlags, &mBuffer,
- &mDeviceMemory);
+ return vk::AllocateBufferMemory(context, memoryPropertyFlags, &mMemoryPropertyFlags, nullptr,
+ &mBuffer, &mDeviceMemory);
}
void BufferHelper::destroy(VkDevice device)
@@ -1092,14 +1223,24 @@ angle::Result BufferHelper::invalidate(Context *context, size_t offset, size_t s
return angle::Result::Continue;
}
+namespace
+{
+constexpr VkBufferUsageFlags kStagingBufferFlags =
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
+constexpr size_t kStagingBufferSize = 1024 * 16;
+
+} // anonymous namespace
+
// ImageHelper implementation.
ImageHelper::ImageHelper()
: CommandGraphResource(CommandGraphResourceType::Image),
mFormat(nullptr),
mSamples(0),
- mCurrentLayout(VK_IMAGE_LAYOUT_UNDEFINED),
+ mCurrentLayout(ImageLayout::Undefined),
+ mCurrentQueueFamilyIndex(std::numeric_limits<uint32_t>::max()),
mLayerCount(0),
- mLevelCount(0)
+ mLevelCount(0),
+ mStagingBuffer(kStagingBufferFlags, kStagingBufferSize, true)
{}
ImageHelper::ImageHelper(ImageHelper &&other)
@@ -1110,10 +1251,13 @@ ImageHelper::ImageHelper(ImageHelper &&other)
mFormat(other.mFormat),
mSamples(other.mSamples),
mCurrentLayout(other.mCurrentLayout),
+ mCurrentQueueFamilyIndex(other.mCurrentQueueFamilyIndex),
mLayerCount(other.mLayerCount),
- mLevelCount(other.mLevelCount)
+ mLevelCount(other.mLevelCount),
+ mStagingBuffer(std::move(other.mStagingBuffer)),
+ mSubresourceUpdates(std::move(other.mSubresourceUpdates))
{
- other.mCurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ other.mCurrentLayout = ImageLayout::Undefined;
other.mLayerCount = 0;
other.mLevelCount = 0;
}
@@ -1123,6 +1267,11 @@ ImageHelper::~ImageHelper()
ASSERT(!valid());
}
+void ImageHelper::initStagingBuffer(RendererVk *renderer, const vk::Format &format)
+{
+ mStagingBuffer.updateAlignment(renderer, format.getImageCopyBufferAlignment());
+}
+
angle::Result ImageHelper::init(Context *context,
gl::TextureType textureType,
const gl::Extents &extents,
@@ -1132,6 +1281,21 @@ angle::Result ImageHelper::init(Context *context,
uint32_t mipLevels,
uint32_t layerCount)
{
+ return initExternal(context, textureType, extents, format, samples, usage,
+ ImageLayout::Undefined, nullptr, mipLevels, layerCount);
+}
+
+angle::Result ImageHelper::initExternal(Context *context,
+ gl::TextureType textureType,
+ const gl::Extents &extents,
+ const Format &format,
+ GLint samples,
+ VkImageUsageFlags usage,
+ ImageLayout initialLayout,
+ const void *externalImageCreateInfo,
+ uint32_t mipLevels,
+ uint32_t layerCount)
+{
ASSERT(!valid());
// Validate that the input layerCount is compatible with the texture type
@@ -1148,6 +1312,7 @@ angle::Result ImageHelper::init(Context *context,
VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imageInfo.pNext = externalImageCreateInfo;
imageInfo.flags = GetImageCreateFlags(textureType);
imageInfo.imageType = gl_vk::GetImageType(textureType);
imageInfo.format = format.vkTextureFormat;
@@ -1162,20 +1327,32 @@ angle::Result ImageHelper::init(Context *context,
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.queueFamilyIndexCount = 0;
imageInfo.pQueueFamilyIndices = nullptr;
- imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ imageInfo.initialLayout = kImageMemoryBarrierData[initialLayout].layout;
- mCurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ mCurrentLayout = initialLayout;
ANGLE_VK_TRY(context, mImage.init(context->getDevice(), imageInfo));
+
return angle::Result::Continue;
}
-void ImageHelper::release(RendererVk *renderer)
+void ImageHelper::releaseImage(RendererVk *renderer)
{
renderer->releaseObject(getStoredQueueSerial(), &mImage);
renderer->releaseObject(getStoredQueueSerial(), &mDeviceMemory);
}
+void ImageHelper::releaseStagingBuffer(RendererVk *renderer)
+{
+ // Remove updates that never made it to the texture.
+ for (SubresourceUpdate &update : mSubresourceUpdates)
+ {
+ update.release(renderer);
+ }
+ mStagingBuffer.release(renderer);
+ mSubresourceUpdates.clear();
+}
+
void ImageHelper::resetImageWeakReference()
{
mImage.reset();
@@ -1186,7 +1363,23 @@ angle::Result ImageHelper::initMemory(Context *context,
VkMemoryPropertyFlags flags)
{
// TODO(jmadill): Memory sub-allocation. http://anglebug.com/2162
- ANGLE_TRY(AllocateImageMemory(context, flags, &mImage, &mDeviceMemory));
+ ANGLE_TRY(AllocateImageMemory(context, flags, nullptr, &mImage, &mDeviceMemory));
+ mCurrentQueueFamilyIndex = context->getRenderer()->getQueueFamilyIndex();
+ return angle::Result::Continue;
+}
+
+angle::Result ImageHelper::initExternalMemory(Context *context,
+ const MemoryProperties &memoryProperties,
+ const VkMemoryRequirements &memoryRequirements,
+ const void *extraAllocationInfo,
+ uint32_t currentQueueFamilyIndex,
+
+ VkMemoryPropertyFlags flags)
+{
+ // TODO(jmadill): Memory sub-allocation. http://anglebug.com/2162
+ ANGLE_TRY(AllocateImageMemoryWithRequirements(context, flags, memoryRequirements,
+ extraAllocationInfo, &mImage, &mDeviceMemory));
+ mCurrentQueueFamilyIndex = currentQueueFamilyIndex;
return angle::Result::Continue;
}
@@ -1195,10 +1388,11 @@ angle::Result ImageHelper::initImageView(Context *context,
VkImageAspectFlags aspectMask,
const gl::SwizzleState &swizzleMap,
ImageView *imageViewOut,
+ uint32_t baseMipLevel,
uint32_t levelCount)
{
- return initLayerImageView(context, textureType, aspectMask, swizzleMap, imageViewOut, 0,
- levelCount, 0, mLayerCount);
+ return initLayerImageView(context, textureType, aspectMask, swizzleMap, imageViewOut,
+ baseMipLevel, levelCount, 0, mLayerCount);
}
angle::Result ImageHelper::initLayerImageView(Context *context,
@@ -1245,7 +1439,7 @@ void ImageHelper::destroy(VkDevice device)
{
mImage.destroy(device);
mDeviceMemory.destroy(device);
- mCurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ mCurrentLayout = ImageLayout::Undefined;
mLayerCount = 0;
mLevelCount = 0;
}
@@ -1257,11 +1451,12 @@ void ImageHelper::init2DWeakReference(VkImage handle,
{
ASSERT(!valid());
- mExtents = extents;
- mFormat = &format;
- mSamples = samples;
- mLayerCount = 1;
- mLevelCount = 1;
+ mExtents = extents;
+ mFormat = &format;
+ mSamples = samples;
+ mCurrentLayout = ImageLayout::Undefined;
+ mLayerCount = 1;
+ mLevelCount = 1;
mImage.setHandle(handle);
}
@@ -1281,7 +1476,7 @@ angle::Result ImageHelper::init2DStaging(Context *context,
mLayerCount = layerCount;
mLevelCount = 1;
- mCurrentLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ mCurrentLayout = ImageLayout::Undefined;
VkImageCreateInfo imageInfo = {};
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
@@ -1299,7 +1494,7 @@ angle::Result ImageHelper::init2DStaging(Context *context,
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
imageInfo.queueFamilyIndexCount = 0;
imageInfo.pQueueFamilyIndices = nullptr;
- imageInfo.initialLayout = mCurrentLayout;
+ imageInfo.initialLayout = getCurrentLayout();
ANGLE_VK_TRY(context, mImage.init(context->getDevice(), imageInfo));
@@ -1346,20 +1541,59 @@ GLint ImageHelper::getSamples() const
return mSamples;
}
-void ImageHelper::changeLayoutWithStages(VkImageAspectFlags aspectMask,
- VkImageLayout newLayout,
- VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask,
- CommandBuffer *commandBuffer)
+VkImageLayout ImageHelper::getCurrentLayout() const
+{
+ return kImageMemoryBarrierData[mCurrentLayout].layout;
+}
+
+bool ImageHelper::isLayoutChangeNecessary(ImageLayout newLayout) const
+{
+ const ImageMemoryBarrierData &layoutData = kImageMemoryBarrierData[mCurrentLayout];
+
+ // If transitioning to the same read-only layout (RAR), don't generate a barrier.
+ bool sameLayoutReadAfterRead = mCurrentLayout == newLayout && layoutData.isReadOnlyAccess;
+
+ return !sameLayoutReadAfterRead;
+}
+
+void ImageHelper::changeLayout(VkImageAspectFlags aspectMask,
+ ImageLayout newLayout,
+ CommandBuffer *commandBuffer)
+{
+ if (!isLayoutChangeNecessary(newLayout))
+ {
+ return;
+ }
+
+ forceChangeLayoutAndQueue(aspectMask, newLayout, mCurrentQueueFamilyIndex, commandBuffer);
+}
+
+void ImageHelper::changeLayoutAndQueue(VkImageAspectFlags aspectMask,
+ ImageLayout newLayout,
+ uint32_t newQueueFamilyIndex,
+ CommandBuffer *commandBuffer)
{
+ ASSERT(isQueueChangeNeccesary(newQueueFamilyIndex));
+ forceChangeLayoutAndQueue(aspectMask, newLayout, newQueueFamilyIndex, commandBuffer);
+}
+
+void ImageHelper::forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
+ ImageLayout newLayout,
+ uint32_t newQueueFamilyIndex,
+ CommandBuffer *commandBuffer)
+{
+
+ const ImageMemoryBarrierData &transitionFrom = kImageMemoryBarrierData[mCurrentLayout];
+ const ImageMemoryBarrierData &transitionTo = kImageMemoryBarrierData[newLayout];
+
VkImageMemoryBarrier imageMemoryBarrier = {};
imageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- imageMemoryBarrier.srcAccessMask = 0;
- imageMemoryBarrier.dstAccessMask = 0;
- imageMemoryBarrier.oldLayout = mCurrentLayout;
- imageMemoryBarrier.newLayout = newLayout;
- imageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- imageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ imageMemoryBarrier.srcAccessMask = transitionFrom.srcAccessMask;
+ imageMemoryBarrier.dstAccessMask = transitionTo.dstAccessMask;
+ imageMemoryBarrier.oldLayout = transitionFrom.layout;
+ imageMemoryBarrier.newLayout = transitionTo.layout;
+ imageMemoryBarrier.srcQueueFamilyIndex = mCurrentQueueFamilyIndex;
+ imageMemoryBarrier.dstQueueFamilyIndex = newQueueFamilyIndex;
imageMemoryBarrier.image = mImage.getHandle();
// TODO(jmadill): Is this needed for mipped/layer images?
@@ -1369,15 +1603,11 @@ void ImageHelper::changeLayoutWithStages(VkImageAspectFlags aspectMask,
imageMemoryBarrier.subresourceRange.baseArrayLayer = 0;
imageMemoryBarrier.subresourceRange.layerCount = mLayerCount;
- // TODO(jmadill): Test all the permutations of the access flags.
- imageMemoryBarrier.srcAccessMask = GetSrcLayoutAccessFlags(mCurrentLayout);
-
- imageMemoryBarrier.dstAccessMask = GetDstLayoutAccessFlags(newLayout);
-
- commandBuffer->pipelineBarrier(srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1,
- &imageMemoryBarrier);
+ commandBuffer->pipelineBarrier(transitionFrom.srcStageMask, transitionTo.dstStageMask, 0, 0,
+ nullptr, 0, nullptr, 1, &imageMemoryBarrier);
mCurrentLayout = newLayout;
+ mCurrentQueueFamilyIndex = newQueueFamilyIndex;
}
void ImageHelper::clearColor(const VkClearColorValue &color,
@@ -1398,9 +1628,7 @@ void ImageHelper::clearColorLayer(const VkClearColorValue &color,
{
ASSERT(valid());
- changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
- commandBuffer);
+ changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, ImageLayout::TransferDst, commandBuffer);
VkImageSubresourceRange range = {};
range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
@@ -1409,7 +1637,7 @@ void ImageHelper::clearColorLayer(const VkClearColorValue &color,
range.baseArrayLayer = baseArrayLayer;
range.layerCount = layerCount;
- commandBuffer->clearColorImage(mImage, mCurrentLayout, color, 1, &range);
+ commandBuffer->clearColorImage(mImage, getCurrentLayout(), color, 1, &range);
}
void ImageHelper::clearDepthStencil(VkImageAspectFlags imageAspectFlags,
@@ -1419,9 +1647,7 @@ void ImageHelper::clearDepthStencil(VkImageAspectFlags imageAspectFlags,
{
ASSERT(valid());
- changeLayoutWithStages(imageAspectFlags, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
- commandBuffer);
+ changeLayout(imageAspectFlags, ImageLayout::TransferDst, commandBuffer);
VkImageSubresourceRange clearRange = {
/*aspectMask*/ clearAspectFlags,
@@ -1431,7 +1657,7 @@ void ImageHelper::clearDepthStencil(VkImageAspectFlags imageAspectFlags,
/*layerCount*/ 1,
};
- commandBuffer->clearDepthStencilImage(mImage, mCurrentLayout, depthStencil, 1, &clearRange);
+ commandBuffer->clearDepthStencilImage(mImage, getCurrentLayout(), depthStencil, 1, &clearRange);
}
gl::Extents ImageHelper::getSize(const gl::ImageIndex &index) const
@@ -1450,45 +1676,27 @@ void ImageHelper::Copy(ImageHelper *srcImage,
const gl::Offset &srcOffset,
const gl::Offset &dstOffset,
const gl::Extents &copySize,
- VkImageAspectFlags aspectMask,
+ const VkImageSubresourceLayers &srcSubresource,
+ const VkImageSubresourceLayers &dstSubresource,
CommandBuffer *commandBuffer)
{
ASSERT(commandBuffer->valid() && srcImage->valid() && dstImage->valid());
- if (srcImage->getCurrentLayout() != VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL &&
- srcImage->getCurrentLayout() != VK_IMAGE_LAYOUT_GENERAL)
- {
- srcImage->changeLayoutWithStages(
- srcImage->getAspectFlags(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
- }
-
- if (dstImage->getCurrentLayout() != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL &&
- dstImage->getCurrentLayout() != VK_IMAGE_LAYOUT_GENERAL)
- {
- dstImage->changeLayoutWithStages(
- dstImage->getAspectFlags(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, commandBuffer);
- }
-
- VkImageCopy region = {};
- region.srcSubresource.aspectMask = aspectMask;
- region.srcSubresource.mipLevel = 0;
- region.srcSubresource.baseArrayLayer = 0;
- region.srcSubresource.layerCount = 1;
- region.srcOffset.x = srcOffset.x;
- region.srcOffset.y = srcOffset.y;
- region.srcOffset.z = srcOffset.z;
- region.dstSubresource.aspectMask = aspectMask;
- region.dstSubresource.mipLevel = 0;
- region.dstSubresource.baseArrayLayer = 0;
- region.dstSubresource.layerCount = 1;
- region.dstOffset.x = dstOffset.x;
- region.dstOffset.y = dstOffset.y;
- region.dstOffset.z = dstOffset.z;
- region.extent.width = copySize.width;
- region.extent.height = copySize.height;
- region.extent.depth = copySize.depth;
+ ASSERT(srcImage->getCurrentLayout() == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
+ ASSERT(dstImage->getCurrentLayout() == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
+
+ VkImageCopy region = {};
+ region.srcSubresource = srcSubresource;
+ region.srcOffset.x = srcOffset.x;
+ region.srcOffset.y = srcOffset.y;
+ region.srcOffset.z = srcOffset.z;
+ region.dstSubresource = dstSubresource;
+ region.dstOffset.x = dstOffset.x;
+ region.dstOffset.y = dstOffset.y;
+ region.dstOffset.z = dstOffset.z;
+ region.extent.width = copySize.width;
+ region.extent.height = copySize.height;
+ region.extent.depth = copySize.depth;
commandBuffer->copyImage(srcImage->getImage(), srcImage->getCurrentLayout(),
dstImage->getImage(), dstImage->getCurrentLayout(), 1, &region);
@@ -1499,9 +1707,7 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(recordCommands(contextVk, &commandBuffer));
- changeLayoutWithStages(VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
- commandBuffer);
+ changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, ImageLayout::TransferDst, commandBuffer);
// We are able to use blitImage since the image format we are using supports it. This
// is a faster way we can generate the mips.
@@ -1526,7 +1732,7 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint
int32_t nextMipHeight = std::max<int32_t>(1, mipHeight >> 1);
barrier.subresourceRange.baseMipLevel = mipLevel - 1;
- barrier.oldLayout = mCurrentLayout;
+ barrier.oldLayout = getCurrentLayout();
barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
@@ -1568,12 +1774,420 @@ angle::Result ImageHelper::generateMipmapsWithBlit(ContextVk *contextVk, GLuint
0, 0, nullptr, 0, nullptr, 1, &barrier);
// This is just changing the internal state of the image helper so that the next call
- // to changeLayoutWithStages will use this layout as the "oldLayout" argument.
- mCurrentLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ // to changeLayout will use this layout as the "oldLayout" argument.
+ mCurrentLayout = ImageLayout::TransferSrc;
return angle::Result::Continue;
}
+void ImageHelper::removeStagedUpdates(RendererVk *renderer, const gl::ImageIndex &index)
+{
+ // Find any staged updates for this index and removes them from the pending list.
+ uint32_t levelIndex = index.getLevelIndex();
+ uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
+
+ for (size_t index = 0; index < mSubresourceUpdates.size();)
+ {
+ auto update = mSubresourceUpdates.begin() + index;
+ if (update->isUpdateToLayerLevel(layerIndex, levelIndex))
+ {
+ update->release(renderer);
+ mSubresourceUpdates.erase(update);
+ }
+ else
+ {
+ index++;
+ }
+ }
+}
+
+angle::Result ImageHelper::stageSubresourceUpdate(ContextVk *contextVk,
+ const gl::ImageIndex &index,
+ const gl::Extents &extents,
+ const gl::Offset &offset,
+ const gl::InternalFormat &formatInfo,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const uint8_t *pixels)
+{
+ GLuint inputRowPitch = 0;
+ ANGLE_VK_CHECK_MATH(contextVk, formatInfo.computeRowPitch(type, extents.width, unpack.alignment,
+ unpack.rowLength, &inputRowPitch));
+
+ GLuint inputDepthPitch = 0;
+ ANGLE_VK_CHECK_MATH(contextVk, formatInfo.computeDepthPitch(extents.height, unpack.imageHeight,
+ inputRowPitch, &inputDepthPitch));
+
+ // Note: skip images for 3D Textures.
+ ASSERT(!index.usesTex3D());
+ bool applySkipImages = false;
+
+ GLuint inputSkipBytes = 0;
+ ANGLE_VK_CHECK_MATH(contextVk,
+ formatInfo.computeSkipBytes(type, inputRowPitch, inputDepthPitch, unpack,
+ applySkipImages, &inputSkipBytes));
+
+ RendererVk *renderer = contextVk->getRenderer();
+
+ const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);
+ const angle::Format &storageFormat = vkFormat.textureFormat();
+
+ size_t outputRowPitch;
+ size_t outputDepthPitch;
+ uint32_t bufferRowLength;
+ uint32_t bufferImageHeight;
+
+ if (storageFormat.isBlock)
+ {
+ const gl::InternalFormat &storageFormatInfo = vkFormat.getInternalFormatInfo(type);
+ GLuint rowPitch;
+ GLuint depthPitch;
+
+ ANGLE_VK_CHECK_MATH(contextVk, storageFormatInfo.computeCompressedImageSize(
+ gl::Extents(extents.width, 1, 1), &rowPitch));
+ ANGLE_VK_CHECK_MATH(contextVk,
+ storageFormatInfo.computeCompressedImageSize(
+ gl::Extents(extents.width, extents.height, 1), &depthPitch));
+
+ outputRowPitch = rowPitch;
+ outputDepthPitch = depthPitch;
+
+ angle::CheckedNumeric<uint32_t> checkedRowLength =
+ rx::CheckedRoundUp<uint32_t>(extents.width, storageFormatInfo.compressedBlockWidth);
+ angle::CheckedNumeric<uint32_t> checkedImageHeight =
+ rx::CheckedRoundUp<uint32_t>(extents.height, storageFormatInfo.compressedBlockHeight);
+
+ ANGLE_VK_CHECK_MATH(contextVk, checkedRowLength.IsValid());
+ ANGLE_VK_CHECK_MATH(contextVk, checkedImageHeight.IsValid());
+
+ bufferRowLength = checkedRowLength.ValueOrDie();
+ bufferImageHeight = checkedImageHeight.ValueOrDie();
+ }
+ else
+ {
+ outputRowPitch = storageFormat.pixelBytes * extents.width;
+ outputDepthPitch = outputRowPitch * extents.height;
+
+ bufferRowLength = extents.width;
+ bufferImageHeight = extents.height;
+
+ ASSERT(storageFormat.pixelBytes != 0);
+ }
+
+ VkBuffer bufferHandle = VK_NULL_HANDLE;
+
+ uint8_t *stagingPointer = nullptr;
+ VkDeviceSize stagingOffset = 0;
+ size_t allocationSize = outputDepthPitch * extents.depth;
+ ANGLE_TRY(mStagingBuffer.allocate(contextVk, allocationSize, &stagingPointer, &bufferHandle,
+ &stagingOffset, nullptr));
+
+ const uint8_t *source = pixels + inputSkipBytes;
+
+ LoadImageFunctionInfo loadFunction = vkFormat.textureLoadFunctions(type);
+
+ loadFunction.loadFunction(extents.width, extents.height, extents.depth, source, inputRowPitch,
+ inputDepthPitch, stagingPointer, outputRowPitch, outputDepthPitch);
+
+ VkBufferImageCopy copy = {};
+
+ copy.bufferOffset = stagingOffset;
+ copy.bufferRowLength = bufferRowLength;
+ copy.bufferImageHeight = bufferImageHeight;
+ copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copy.imageSubresource.mipLevel = index.getLevelIndex();
+ copy.imageSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
+ copy.imageSubresource.layerCount = index.getLayerCount();
+
+ gl_vk::GetOffset(offset, &copy.imageOffset);
+ gl_vk::GetExtent(extents, &copy.imageExtent);
+
+ mSubresourceUpdates.emplace_back(bufferHandle, copy);
+
+ return angle::Result::Continue;
+}
+
+angle::Result ImageHelper::stageSubresourceUpdateAndGetData(ContextVk *contextVk,
+ size_t allocationSize,
+ const gl::ImageIndex &imageIndex,
+ const gl::Extents &extents,
+ const gl::Offset &offset,
+ uint8_t **destData)
+{
+ VkBuffer bufferHandle;
+ VkDeviceSize stagingOffset = 0;
+ ANGLE_TRY(mStagingBuffer.allocate(contextVk, allocationSize, destData, &bufferHandle,
+ &stagingOffset, nullptr));
+
+ VkBufferImageCopy copy = {};
+ copy.bufferOffset = stagingOffset;
+ copy.bufferRowLength = extents.width;
+ copy.bufferImageHeight = extents.height;
+ copy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copy.imageSubresource.mipLevel = imageIndex.getLevelIndex();
+ copy.imageSubresource.baseArrayLayer = imageIndex.hasLayer() ? imageIndex.getLayerIndex() : 0;
+ copy.imageSubresource.layerCount = imageIndex.getLayerCount();
+
+ gl_vk::GetOffset(offset, &copy.imageOffset);
+ gl_vk::GetExtent(extents, &copy.imageExtent);
+
+ mSubresourceUpdates.emplace_back(bufferHandle, copy);
+
+ return angle::Result::Continue;
+}
+
+angle::Result ImageHelper::stageSubresourceUpdateFromFramebuffer(
+ const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ const gl::Offset &dstOffset,
+ const gl::Extents &dstExtent,
+ const gl::InternalFormat &formatInfo,
+ FramebufferVk *framebufferVk)
+{
+ ContextVk *contextVk = vk::GetImpl(context);
+
+ // If the extents and offset is outside the source image, we need to clip.
+ gl::Rectangle clippedRectangle;
+ const gl::Extents readExtents = framebufferVk->getReadImageExtents();
+ if (!ClipRectangle(sourceArea, gl::Rectangle(0, 0, readExtents.width, readExtents.height),
+ &clippedRectangle))
+ {
+ // Empty source area, nothing to do.
+ return angle::Result::Continue;
+ }
+
+ bool isViewportFlipEnabled = contextVk->isViewportFlipEnabledForDrawFBO();
+ if (isViewportFlipEnabled)
+ {
+ clippedRectangle.y = readExtents.height - clippedRectangle.y - clippedRectangle.height;
+ }
+
+ // 1- obtain a buffer handle to copy to
+ RendererVk *renderer = contextVk->getRenderer();
+
+ const vk::Format &vkFormat = renderer->getFormat(formatInfo.sizedInternalFormat);
+ const angle::Format &storageFormat = vkFormat.textureFormat();
+ LoadImageFunctionInfo loadFunction = vkFormat.textureLoadFunctions(formatInfo.type);
+
+ size_t outputRowPitch = storageFormat.pixelBytes * clippedRectangle.width;
+ size_t outputDepthPitch = outputRowPitch * clippedRectangle.height;
+
+ VkBuffer bufferHandle = VK_NULL_HANDLE;
+
+ uint8_t *stagingPointer = nullptr;
+ VkDeviceSize stagingOffset = 0;
+
+ // The destination is only one layer deep.
+ size_t allocationSize = outputDepthPitch;
+ ANGLE_TRY(mStagingBuffer.allocate(contextVk, allocationSize, &stagingPointer, &bufferHandle,
+ &stagingOffset, nullptr));
+
+ const angle::Format &copyFormat =
+ GetFormatFromFormatType(formatInfo.internalFormat, formatInfo.type);
+ PackPixelsParams params(clippedRectangle, copyFormat, static_cast<GLuint>(outputRowPitch),
+ isViewportFlipEnabled, nullptr, 0);
+
+ // 2- copy the source image region to the pixel buffer using a cpu readback
+ if (loadFunction.requiresConversion)
+ {
+ // When a conversion is required, we need to use the loadFunction to read from a temporary
+ // buffer instead so its an even slower path.
+ size_t bufferSize =
+ storageFormat.pixelBytes * clippedRectangle.width * clippedRectangle.height;
+ angle::MemoryBuffer *memoryBuffer = nullptr;
+ ANGLE_VK_CHECK_ALLOC(contextVk, context->getScratchBuffer(bufferSize, &memoryBuffer));
+
+ // Read into the scratch buffer
+ ANGLE_TRY(framebufferVk->readPixelsImpl(
+ contextVk, clippedRectangle, params, VK_IMAGE_ASPECT_COLOR_BIT,
+ framebufferVk->getColorReadRenderTarget(), memoryBuffer->data()));
+
+ // Load from scratch buffer to our pixel buffer
+ loadFunction.loadFunction(clippedRectangle.width, clippedRectangle.height, 1,
+ memoryBuffer->data(), outputRowPitch, 0, stagingPointer,
+ outputRowPitch, 0);
+ }
+ else
+ {
+ // We read directly from the framebuffer into our pixel buffer.
+ ANGLE_TRY(framebufferVk->readPixelsImpl(
+ contextVk, clippedRectangle, params, VK_IMAGE_ASPECT_COLOR_BIT,
+ framebufferVk->getColorReadRenderTarget(), stagingPointer));
+ }
+
+ // 3- enqueue the destination image subresource update
+ VkBufferImageCopy copyToImage = {};
+ copyToImage.bufferOffset = static_cast<VkDeviceSize>(stagingOffset);
+ copyToImage.bufferRowLength = 0; // Tightly packed data can be specified as 0.
+ copyToImage.bufferImageHeight = clippedRectangle.height;
+ copyToImage.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyToImage.imageSubresource.mipLevel = index.getLevelIndex();
+ copyToImage.imageSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
+ copyToImage.imageSubresource.layerCount = index.getLayerCount();
+ gl_vk::GetOffset(dstOffset, &copyToImage.imageOffset);
+ gl_vk::GetExtent(dstExtent, &copyToImage.imageExtent);
+
+ // 3- enqueue the destination image subresource update
+ mSubresourceUpdates.emplace_back(bufferHandle, copyToImage);
+ return angle::Result::Continue;
+}
+
+void ImageHelper::stageSubresourceUpdateFromImage(vk::ImageHelper *image,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Extents &extents)
+{
+ VkImageCopy copyToImage = {};
+ copyToImage.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyToImage.srcSubresource.layerCount = index.getLayerCount();
+ copyToImage.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyToImage.dstSubresource.mipLevel = index.getLevelIndex();
+ copyToImage.dstSubresource.baseArrayLayer = index.hasLayer() ? index.getLayerIndex() : 0;
+ copyToImage.dstSubresource.layerCount = index.getLayerCount();
+ gl_vk::GetOffset(destOffset, &copyToImage.dstOffset);
+ gl_vk::GetExtent(extents, &copyToImage.extent);
+
+ mSubresourceUpdates.emplace_back(image, copyToImage);
+}
+
+angle::Result ImageHelper::allocateStagingMemory(ContextVk *contextVk,
+ size_t sizeInBytes,
+ uint8_t **ptrOut,
+ VkBuffer *handleOut,
+ VkDeviceSize *offsetOut,
+ bool *newBufferAllocatedOut)
+{
+ return mStagingBuffer.allocate(contextVk, sizeInBytes, ptrOut, handleOut, offsetOut,
+ newBufferAllocatedOut);
+}
+
+angle::Result ImageHelper::flushStagedUpdates(Context *context,
+ uint32_t baseLevel,
+ uint32_t levelCount,
+ vk::CommandBuffer *commandBuffer)
+{
+ if (mSubresourceUpdates.empty())
+ {
+ return angle::Result::Continue;
+ }
+
+ RendererVk *renderer = context->getRenderer();
+
+ ANGLE_TRY(mStagingBuffer.flush(context));
+
+ std::vector<SubresourceUpdate> updatesToKeep;
+
+ for (SubresourceUpdate &update : mSubresourceUpdates)
+ {
+ ASSERT((update.updateSource == SubresourceUpdate::UpdateSource::Buffer &&
+ update.buffer.bufferHandle != VK_NULL_HANDLE) ||
+ (update.updateSource == SubresourceUpdate::UpdateSource::Image &&
+ update.image.image != nullptr && update.image.image->valid()));
+
+ const uint32_t updateMipLevel = update.dstSubresource().mipLevel;
+
+ // It's possible we've accumulated updates that are no longer applicable if the image has
+ // never been flushed but the image description has changed. Check if this level exist for
+ // this image.
+ if (updateMipLevel < baseLevel || updateMipLevel >= baseLevel + levelCount)
+ {
+ updatesToKeep.emplace_back(update);
+ continue;
+ }
+
+ // Conservatively flush all writes to the image. We could use a more restricted barrier.
+ // Do not move this above the for loop, otherwise multiple updates can have race conditions
+ // and not be applied correctly as seen in:
+ // dEQP-gles2.functional_texture_specification_texsubimage2d_align_2d* tests on Windows AMD
+ changeLayout(VK_IMAGE_ASPECT_COLOR_BIT, vk::ImageLayout::TransferDst, commandBuffer);
+
+ if (update.updateSource == SubresourceUpdate::UpdateSource::Buffer)
+ {
+ commandBuffer->copyBufferToImage(update.buffer.bufferHandle, mImage, getCurrentLayout(),
+ 1, &update.buffer.copyRegion);
+ }
+ else
+ {
+ update.image.image->changeLayout(VK_IMAGE_ASPECT_COLOR_BIT,
+ vk::ImageLayout::TransferSrc, commandBuffer);
+
+ update.image.image->addReadDependency(this);
+
+ commandBuffer->copyImage(update.image.image->getImage(),
+ update.image.image->getCurrentLayout(), mImage,
+ getCurrentLayout(), 1, &update.image.copyRegion);
+ }
+
+ update.release(renderer);
+ }
+
+ // Only remove the updates that were actually applied to the image.
+ mSubresourceUpdates = std::move(updatesToKeep);
+
+ if (mSubresourceUpdates.empty())
+ {
+ mStagingBuffer.releaseRetainedBuffers(context->getRenderer());
+ }
+ else
+ {
+ WARN() << "Internal Vulkan buffer could not be released. This is likely due to having "
+ "extra images defined in the Texture.";
+ }
+
+ return angle::Result::Continue;
+}
+
+bool ImageHelper::hasStagedUpdates() const
+{
+ return !mSubresourceUpdates.empty();
+}
+
+// ImageHelper::SubresourceUpdate implementation
+ImageHelper::SubresourceUpdate::SubresourceUpdate()
+ : updateSource(UpdateSource::Buffer), buffer{VK_NULL_HANDLE}
+{}
+
+ImageHelper::SubresourceUpdate::SubresourceUpdate(VkBuffer bufferHandleIn,
+ const VkBufferImageCopy &copyRegionIn)
+ : updateSource(UpdateSource::Buffer), buffer{bufferHandleIn, copyRegionIn}
+{}
+
+ImageHelper::SubresourceUpdate::SubresourceUpdate(vk::ImageHelper *imageIn,
+ const VkImageCopy &copyRegionIn)
+ : updateSource(UpdateSource::Image), image{imageIn, copyRegionIn}
+{}
+
+ImageHelper::SubresourceUpdate::SubresourceUpdate(const SubresourceUpdate &other)
+ : updateSource(other.updateSource)
+{
+ if (updateSource == UpdateSource::Buffer)
+ {
+ buffer = other.buffer;
+ }
+ else
+ {
+ image = other.image;
+ }
+}
+
+void ImageHelper::SubresourceUpdate::release(RendererVk *renderer)
+{
+ if (updateSource == UpdateSource::Image)
+ {
+ image.image->releaseImage(renderer);
+ image.image->releaseStagingBuffer(renderer);
+ SafeDelete(image.image);
+ }
+}
+
+bool ImageHelper::SubresourceUpdate::isUpdateToLayerLevel(uint32_t layerIndex,
+ uint32_t levelIndex) const
+{
+ const VkImageSubresourceLayers &dst = dstSubresource();
+ return dst.baseArrayLayer == layerIndex && dst.mipLevel == levelIndex;
+}
+
// FramebufferHelper implementation.
FramebufferHelper::FramebufferHelper() : CommandGraphResource(CommandGraphResourceType::Framebuffer)
{}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.h
index 2ab9a2a5757..b0853a81cfb 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_helpers.h
@@ -33,6 +33,7 @@ class DynamicBuffer : angle::NonCopyable
{
public:
DynamicBuffer(VkBufferUsageFlags usage, size_t minSize, bool hostVisible);
+ DynamicBuffer(DynamicBuffer &&other);
~DynamicBuffer();
// Init is called after the buffer creation so that the alignment can be specified later.
@@ -64,7 +65,10 @@ class DynamicBuffer : angle::NonCopyable
// This frees resources immediately.
void destroy(VkDevice device);
- BufferHelper *getCurrentBuffer() { return mBuffer; };
+ BufferHelper *getCurrentBuffer() { return mBuffer; }
+
+ size_t getAlignment() { return mAlignment; }
+ void updateAlignment(RendererVk *renderer, size_t alignment);
// For testing only!
void setMinimumSizeForTesting(size_t minSize);
@@ -122,8 +126,8 @@ class DescriptorPoolHelper
Serial mMostRecentSerial;
};
-using SharedDescriptorPoolHelper = RefCounted<DescriptorPoolHelper>;
-using SharedDescriptorPoolBinding = BindingPointer<DescriptorPoolHelper>;
+using RefCountedDescriptorPoolHelper = RefCounted<DescriptorPoolHelper>;
+using RefCountedDescriptorPoolBinding = BindingPointer<DescriptorPoolHelper>;
class DynamicDescriptorPool final : angle::NonCopyable
{
@@ -144,7 +148,7 @@ class DynamicDescriptorPool final : angle::NonCopyable
angle::Result allocateSets(Context *context,
const VkDescriptorSetLayout *descriptorSetLayout,
uint32_t descriptorSetCount,
- SharedDescriptorPoolBinding *bindingOut,
+ RefCountedDescriptorPoolBinding *bindingOut,
VkDescriptorSet *descriptorSetsOut);
// For testing only!
@@ -155,7 +159,7 @@ class DynamicDescriptorPool final : angle::NonCopyable
uint32_t mMaxSetsPerPool;
size_t mCurrentPoolIndex;
- std::vector<SharedDescriptorPoolHelper *> mDescriptorPools;
+ std::vector<RefCountedDescriptorPoolHelper *> mDescriptorPools;
std::vector<VkDescriptorPoolSize> mPoolSizes;
};
@@ -470,6 +474,53 @@ class BufferHelper final : public CommandGraphResource
VkFlags mCurrentReadAccess;
};
+// Imagine an image going through a few layout transitions:
+//
+// srcStage 1 dstStage 2 srcStage 2 dstStage 3
+// Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3
+// srcAccess 1 dstAccess 2 srcAccess 2 dstAccess 3
+// \_________________ ___________________/
+// \/
+// A transition
+//
+// Every transition requires 6 pieces of information: from/to layouts, src/dst stage masks and
+// src/dst access masks. At the moment we decide to transition the image to Layout 2 (i.e.
+// Transition 1), we need to have Layout 1, srcStage 1 and srcAccess 1 stored as history of the
+// image. To perform the transition, we need to know Layout 2, dstStage 2 and dstAccess 2.
+// Additionally, we need to know srcStage 2 and srcAccess 2 to retain them for the next transition.
+//
+// That is, with the history kept, on every new transition we need 5 pieces of new information:
+// layout/dstStage/dstAccess to transition into the layout, and srcStage/srcAccess for the future
+// transition out from it. Given the small number of possible combinations of these values, an
+// enum is used were each value encapsulates these 5 pieces of information:
+//
+// +--------------------------------+
+// srcStage 1 | dstStage 2 srcStage 2 | dstStage 3
+// Layout 1 ------Transition 1-----> Layout 2 ------Transition 2------> Layout 3
+// srcAccess 1 |dstAccess 2 srcAccess 2| dstAccess 3
+// +--------------- ---------------+
+// \/
+// One enum value
+//
+// Note that, while generally dstStage for the to-transition and srcStage for the from-transition
+// are the same, they may occasionally be BOTTOM_OF_PIPE and TOP_OF_PIPE respectively.
+enum class ImageLayout
+{
+ Undefined = 0,
+ ExternalPreInitialized = 1,
+ TransferSrc = 2,
+ TransferDst = 3,
+ ComputeShaderReadOnly = 4,
+ ComputeShaderWrite = 5,
+ FragmentShaderReadOnly = 6,
+ ColorAttachment = 7,
+ DepthStencilAttachment = 8,
+ Present = 9,
+
+ InvalidEnum = 10,
+ EnumCount = 10,
+};
+
class ImageHelper final : public CommandGraphResource
{
public:
@@ -477,6 +528,8 @@ class ImageHelper final : public CommandGraphResource
ImageHelper(ImageHelper &&other);
~ImageHelper() override;
+ void initStagingBuffer(RendererVk *renderer, const vk::Format &format);
+
angle::Result init(Context *context,
gl::TextureType textureType,
const gl::Extents &extents,
@@ -485,9 +538,25 @@ class ImageHelper final : public CommandGraphResource
VkImageUsageFlags usage,
uint32_t mipLevels,
uint32_t layerCount);
+ angle::Result initExternal(Context *context,
+ gl::TextureType textureType,
+ const gl::Extents &extents,
+ const Format &format,
+ GLint samples,
+ VkImageUsageFlags usage,
+ ImageLayout initialLayout,
+ const void *externalImageCreateInfo,
+ uint32_t mipLevels,
+ uint32_t layerCount);
angle::Result initMemory(Context *context,
const MemoryProperties &memoryProperties,
VkMemoryPropertyFlags flags);
+ angle::Result initExternalMemory(Context *context,
+ const MemoryProperties &memoryProperties,
+ const VkMemoryRequirements &memoryRequirements,
+ const void *extraAllocationInfo,
+ uint32_t currentQueueFamilyIndex,
+ VkMemoryPropertyFlags flags);
angle::Result initLayerImageView(Context *context,
gl::TextureType textureType,
VkImageAspectFlags aspectMask,
@@ -502,6 +571,7 @@ class ImageHelper final : public CommandGraphResource
VkImageAspectFlags aspectMask,
const gl::SwizzleState &swizzleMap,
ImageView *imageViewOut,
+ uint32_t baseMipLevel,
uint32_t levelCount);
// Create a 2D[Array] for staging purposes. Used by:
//
@@ -514,7 +584,8 @@ class ImageHelper final : public CommandGraphResource
VkImageUsageFlags usage,
uint32_t layerCount);
- void release(RendererVk *renderer);
+ void releaseImage(RendererVk *renderer);
+ void releaseStagingBuffer(RendererVk *renderer);
bool valid() const { return mImage.valid(); }
@@ -537,13 +608,7 @@ class ImageHelper final : public CommandGraphResource
const Format &getFormat() const;
GLint getSamples() const;
- VkImageLayout getCurrentLayout() const { return mCurrentLayout; }
-
- void changeLayoutWithStages(VkImageAspectFlags aspectMask,
- VkImageLayout newLayout,
- VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask,
- CommandBuffer *commandBuffer);
+ VkImageLayout getCurrentLayout() const;
void clearColor(const VkClearColorValue &color,
uint32_t baseMipLevel,
@@ -568,12 +633,125 @@ class ImageHelper final : public CommandGraphResource
const gl::Offset &srcOffset,
const gl::Offset &dstOffset,
const gl::Extents &copySize,
- VkImageAspectFlags aspectMask,
+ const VkImageSubresourceLayers &srcSubresources,
+ const VkImageSubresourceLayers &dstSubresources,
CommandBuffer *commandBuffer);
angle::Result generateMipmapsWithBlit(ContextVk *contextVk, GLuint maxLevel);
+ // Data staging
+ void removeStagedUpdates(RendererVk *renderer, const gl::ImageIndex &index);
+
+ angle::Result stageSubresourceUpdate(ContextVk *contextVk,
+ const gl::ImageIndex &index,
+ const gl::Extents &extents,
+ const gl::Offset &offset,
+ const gl::InternalFormat &formatInfo,
+ const gl::PixelUnpackState &unpack,
+ GLenum type,
+ const uint8_t *pixels);
+
+ angle::Result stageSubresourceUpdateAndGetData(ContextVk *contextVk,
+ size_t allocationSize,
+ const gl::ImageIndex &imageIndex,
+ const gl::Extents &extents,
+ const gl::Offset &offset,
+ uint8_t **destData);
+
+ angle::Result stageSubresourceUpdateFromFramebuffer(const gl::Context *context,
+ const gl::ImageIndex &index,
+ const gl::Rectangle &sourceArea,
+ const gl::Offset &dstOffset,
+ const gl::Extents &dstExtent,
+ const gl::InternalFormat &formatInfo,
+ FramebufferVk *framebufferVk);
+
+ void stageSubresourceUpdateFromImage(vk::ImageHelper *image,
+ const gl::ImageIndex &index,
+ const gl::Offset &destOffset,
+ const gl::Extents &extents);
+
+ // This will use the underlying dynamic buffer to allocate some memory to be used as a src or
+ // dst.
+ angle::Result allocateStagingMemory(ContextVk *contextVk,
+ size_t sizeInBytes,
+ uint8_t **ptrOut,
+ VkBuffer *handleOut,
+ VkDeviceSize *offsetOut,
+ bool *newBufferAllocatedOut);
+
+ angle::Result flushStagedUpdates(Context *context,
+ uint32_t baseLevel,
+ uint32_t levelCount,
+ vk::CommandBuffer *commandBuffer);
+
+ bool hasStagedUpdates() const;
+
+ // changeLayout automatically skips the layout change if it's unnecessary. This function can be
+ // used to prevent creating a command graph node and subsequently a command buffer for the sole
+ // purpose of performing a transition (which may then not be issued).
+ bool isLayoutChangeNecessary(ImageLayout newLayout) const;
+
+ void changeLayout(VkImageAspectFlags aspectMask,
+ ImageLayout newLayout,
+ CommandBuffer *commandBuffer);
+
+ bool isQueueChangeNeccesary(uint32_t newQueueFamilyIndex) const
+ {
+ return mCurrentQueueFamilyIndex != newQueueFamilyIndex;
+ }
+
+ void changeLayoutAndQueue(VkImageAspectFlags aspectMask,
+ ImageLayout newLayout,
+ uint32_t newQueueFamilyIndex,
+ CommandBuffer *commandBuffer);
+
private:
+ void forceChangeLayoutAndQueue(VkImageAspectFlags aspectMask,
+ ImageLayout newLayout,
+ uint32_t newQueueFamilyIndex,
+ CommandBuffer *commandBuffer);
+
+ struct SubresourceUpdate
+ {
+ SubresourceUpdate();
+ SubresourceUpdate(VkBuffer bufferHandle, const VkBufferImageCopy &copyRegion);
+ SubresourceUpdate(vk::ImageHelper *image, const VkImageCopy &copyRegion);
+ SubresourceUpdate(const SubresourceUpdate &other);
+
+ void release(RendererVk *renderer);
+
+ const VkImageSubresourceLayers &dstSubresource() const
+ {
+ return updateSource == UpdateSource::Buffer ? buffer.copyRegion.imageSubresource
+ : image.copyRegion.dstSubresource;
+ }
+ bool isUpdateToLayerLevel(uint32_t layerIndex, uint32_t levelIndex) const;
+
+ enum class UpdateSource
+ {
+ Buffer,
+ Image,
+ };
+ struct BufferUpdate
+ {
+ VkBuffer bufferHandle;
+ VkBufferImageCopy copyRegion;
+ };
+ struct ImageUpdate
+ {
+ vk::ImageHelper *image;
+ VkImageCopy copyRegion;
+ };
+
+ UpdateSource updateSource;
+ union
+ {
+ BufferUpdate buffer;
+ ImageUpdate image;
+ };
+ };
+
// Vulkan objects.
Image mImage;
DeviceMemory mDeviceMemory;
@@ -584,11 +762,16 @@ class ImageHelper final : public CommandGraphResource
GLint mSamples;
// Current state.
- VkImageLayout mCurrentLayout;
+ ImageLayout mCurrentLayout;
+ uint32_t mCurrentQueueFamilyIndex;
// Cached properties.
uint32_t mLayerCount;
uint32_t mLevelCount;
+
+ // Staging buffer
+ vk::DynamicBuffer mStagingBuffer;
+ std::vector<SubresourceUpdate> mSubresourceUpdates;
};
class FramebufferHelper : public CommandGraphResource
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.cpp
index be204552b43..4b304894996 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.cpp
@@ -63,8 +63,6 @@ const char *g_VkValidationLayerNames[] = {
"VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
"VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation",
"VK_LAYER_GOOGLE_unique_objects"};
-const uint32_t g_VkNumValidationLayerNames =
- sizeof(g_VkValidationLayerNames) / sizeof(g_VkValidationLayerNames[0]);
bool HasValidationLayer(const std::vector<VkLayerProperties> &layerProps, const char *layerName)
{
@@ -102,6 +100,7 @@ angle::Result FindAndAllocateCompatibleMemory(vk::Context *context,
VkMemoryPropertyFlags requestedMemoryPropertyFlags,
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
const VkMemoryRequirements &memoryRequirements,
+ const void *extraAllocationInfo,
vk::DeviceMemory *deviceMemoryOut)
{
uint32_t memoryTypeIndex = 0;
@@ -111,6 +110,7 @@ angle::Result FindAndAllocateCompatibleMemory(vk::Context *context,
VkMemoryAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ allocInfo.pNext = extraAllocationInfo;
allocInfo.memoryTypeIndex = memoryTypeIndex;
allocInfo.allocationSize = memoryRequirements.size;
@@ -119,22 +119,39 @@ angle::Result FindAndAllocateCompatibleMemory(vk::Context *context,
}
template <typename T>
+angle::Result AllocateAndBindBufferOrImageMemory(vk::Context *context,
+ VkMemoryPropertyFlags requestedMemoryPropertyFlags,
+ VkMemoryPropertyFlags *memoryPropertyFlagsOut,
+ const VkMemoryRequirements &memoryRequirements,
+ const void *extraAllocationInfo,
+ T *bufferOrImage,
+ vk::DeviceMemory *deviceMemoryOut)
+{
+ const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties();
+
+ ANGLE_TRY(FindAndAllocateCompatibleMemory(
+ context, memoryProperties, requestedMemoryPropertyFlags, memoryPropertyFlagsOut,
+ memoryRequirements, extraAllocationInfo, deviceMemoryOut));
+ ANGLE_VK_TRY(context, bufferOrImage->bindMemory(context->getDevice(), *deviceMemoryOut));
+ return angle::Result::Continue;
+}
+
+template <typename T>
angle::Result AllocateBufferOrImageMemory(vk::Context *context,
VkMemoryPropertyFlags requestedMemoryPropertyFlags,
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
+ const void *extraAllocationInfo,
T *bufferOrImage,
vk::DeviceMemory *deviceMemoryOut)
{
- const vk::MemoryProperties &memoryProperties = context->getRenderer()->getMemoryProperties();
-
// Call driver to determine memory requirements.
VkMemoryRequirements memoryRequirements;
bufferOrImage->getMemoryRequirements(context->getDevice(), &memoryRequirements);
- ANGLE_TRY(FindAndAllocateCompatibleMemory(context, memoryProperties,
- requestedMemoryPropertyFlags, memoryPropertyFlagsOut,
- memoryRequirements, deviceMemoryOut));
- ANGLE_VK_TRY(context, bufferOrImage->bindMemory(context->getDevice(), *deviceMemoryOut));
+ ANGLE_TRY(AllocateAndBindBufferOrImageMemory(
+ context, requestedMemoryPropertyFlags, memoryPropertyFlagsOut, memoryRequirements,
+ extraAllocationInfo, bufferOrImage, deviceMemoryOut));
+
return angle::Result::Continue;
}
@@ -204,18 +221,18 @@ const char *VulkanResultString(VkResult result)
bool GetAvailableValidationLayers(const std::vector<VkLayerProperties> &layerProps,
bool mustHaveLayers,
- const char *const **enabledLayerNames,
- uint32_t *enabledLayerCount)
+ VulkanLayerVector *enabledLayerNames)
{
if (HasStandardValidationLayer(layerProps))
{
- *enabledLayerNames = &g_VkStdValidationLayerName;
- *enabledLayerCount = 1;
+ enabledLayerNames->push_back(g_VkStdValidationLayerName);
}
else if (HasValidationLayers(layerProps))
{
- *enabledLayerNames = g_VkValidationLayerNames;
- *enabledLayerCount = g_VkNumValidationLayerNames;
+ for (const char *layerName : g_VkValidationLayerNames)
+ {
+ enabledLayerNames->push_back(layerName);
+ }
}
else
{
@@ -229,8 +246,6 @@ bool GetAvailableValidationLayers(const std::vector<VkLayerProperties> &layerPro
WARN() << "Vulkan validation layers are missing.";
}
- *enabledLayerNames = nullptr;
- *enabledLayerCount = 0;
return false;
}
@@ -267,769 +282,6 @@ VkDevice Context::getDevice() const
return mRenderer->getDevice();
}
-// CommandPool implementation.
-CommandPool::CommandPool() {}
-
-void CommandPool::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyCommandPool(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult CommandPool::init(VkDevice device, const VkCommandPoolCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateCommandPool(device, &createInfo, nullptr, &mHandle);
-}
-
-// CommandBuffer implementation.
-CommandBuffer::CommandBuffer() {}
-
-VkCommandBuffer CommandBuffer::releaseHandle()
-{
- VkCommandBuffer handle = mHandle;
- mHandle = nullptr;
- return handle;
-}
-
-VkResult CommandBuffer::init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkAllocateCommandBuffers(device, &createInfo, &mHandle);
-}
-
-void CommandBuffer::blitImage(const Image &srcImage,
- VkImageLayout srcImageLayout,
- const Image &dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- VkImageBlit *pRegions,
- VkFilter filter)
-{
- ASSERT(valid());
- vkCmdBlitImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
- dstImageLayout, regionCount, pRegions, filter);
-}
-
-VkResult CommandBuffer::begin(const VkCommandBufferBeginInfo &info)
-{
- ASSERT(valid());
- return vkBeginCommandBuffer(mHandle, &info);
-}
-
-VkResult CommandBuffer::end()
-{
- ASSERT(valid());
- return vkEndCommandBuffer(mHandle);
-}
-
-VkResult CommandBuffer::reset()
-{
- ASSERT(valid());
- return vkResetCommandBuffer(mHandle, 0);
-}
-
-void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask,
- VkDependencyFlags dependencyFlags,
- uint32_t memoryBarrierCount,
- const VkMemoryBarrier *memoryBarriers,
- uint32_t bufferMemoryBarrierCount,
- const VkBufferMemoryBarrier *bufferMemoryBarriers,
- uint32_t imageMemoryBarrierCount,
- const VkImageMemoryBarrier *imageMemoryBarriers)
-{
- ASSERT(valid());
- vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount,
- memoryBarriers, bufferMemoryBarrierCount, bufferMemoryBarriers,
- imageMemoryBarrierCount, imageMemoryBarriers);
-}
-
-void CommandBuffer::destroy(VkDevice device)
-{
- releaseHandle();
-}
-
-void CommandBuffer::destroy(VkDevice device, const vk::CommandPool &commandPool)
-{
- if (valid())
- {
- ASSERT(commandPool.valid());
- vkFreeCommandBuffers(device, commandPool.getHandle(), 1, &mHandle);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-void CommandBuffer::copyBuffer(const vk::Buffer &srcBuffer,
- const vk::Buffer &destBuffer,
- uint32_t regionCount,
- const VkBufferCopy *regions)
-{
- ASSERT(valid());
- ASSERT(srcBuffer.valid() && destBuffer.valid());
- vkCmdCopyBuffer(mHandle, srcBuffer.getHandle(), destBuffer.getHandle(), regionCount, regions);
-}
-
-void CommandBuffer::copyBuffer(const VkBuffer &srcBuffer,
- const VkBuffer &destBuffer,
- uint32_t regionCount,
- const VkBufferCopy *regions)
-{
- ASSERT(valid());
- vkCmdCopyBuffer(mHandle, srcBuffer, destBuffer, regionCount, regions);
-}
-
-void CommandBuffer::copyBufferToImage(VkBuffer srcBuffer,
- const Image &dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- const VkBufferImageCopy *regions)
-{
- ASSERT(valid());
- ASSERT(srcBuffer != VK_NULL_HANDLE);
- ASSERT(dstImage.valid());
- vkCmdCopyBufferToImage(mHandle, srcBuffer, dstImage.getHandle(), dstImageLayout, regionCount,
- regions);
-}
-
-void CommandBuffer::copyImageToBuffer(const Image &srcImage,
- VkImageLayout srcImageLayout,
- VkBuffer dstBuffer,
- uint32_t regionCount,
- const VkBufferImageCopy *regions)
-{
- ASSERT(valid());
- ASSERT(dstBuffer != VK_NULL_HANDLE);
- ASSERT(srcImage.valid());
- vkCmdCopyImageToBuffer(mHandle, srcImage.getHandle(), srcImageLayout, dstBuffer, regionCount,
- regions);
-}
-
-void CommandBuffer::clearColorImage(const vk::Image &image,
- VkImageLayout imageLayout,
- const VkClearColorValue &color,
- uint32_t rangeCount,
- const VkImageSubresourceRange *ranges)
-{
- ASSERT(valid());
- vkCmdClearColorImage(mHandle, image.getHandle(), imageLayout, &color, rangeCount, ranges);
-}
-
-void CommandBuffer::clearDepthStencilImage(const vk::Image &image,
- VkImageLayout imageLayout,
- const VkClearDepthStencilValue &depthStencil,
- uint32_t rangeCount,
- const VkImageSubresourceRange *ranges)
-{
- ASSERT(valid());
- vkCmdClearDepthStencilImage(mHandle, image.getHandle(), imageLayout, &depthStencil, rangeCount,
- ranges);
-}
-
-void CommandBuffer::clearAttachments(uint32_t attachmentCount,
- const VkClearAttachment *attachments,
- uint32_t rectCount,
- const VkClearRect *rects)
-{
- ASSERT(valid());
-
- vkCmdClearAttachments(mHandle, attachmentCount, attachments, rectCount, rects);
-}
-
-void CommandBuffer::copyImage(const vk::Image &srcImage,
- VkImageLayout srcImageLayout,
- const vk::Image &dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- const VkImageCopy *regions)
-{
- ASSERT(valid() && srcImage.valid() && dstImage.valid());
- vkCmdCopyImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
- dstImageLayout, 1, regions);
-}
-
-void CommandBuffer::beginRenderPass(const VkRenderPassBeginInfo &beginInfo,
- VkSubpassContents subpassContents)
-{
- ASSERT(valid());
- vkCmdBeginRenderPass(mHandle, &beginInfo, subpassContents);
-}
-
-void CommandBuffer::endRenderPass()
-{
- ASSERT(mHandle != VK_NULL_HANDLE);
- vkCmdEndRenderPass(mHandle);
-}
-
-void CommandBuffer::bindIndexBuffer(const VkBuffer &buffer,
- VkDeviceSize offset,
- VkIndexType indexType)
-{
- ASSERT(valid());
- vkCmdBindIndexBuffer(mHandle, buffer, offset, indexType);
-}
-
-void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint bindPoint,
- const vk::PipelineLayout &layout,
- uint32_t firstSet,
- uint32_t descriptorSetCount,
- const VkDescriptorSet *descriptorSets,
- uint32_t dynamicOffsetCount,
- const uint32_t *dynamicOffsets)
-{
- ASSERT(valid());
- vkCmdBindDescriptorSets(mHandle, bindPoint, layout.getHandle(), firstSet, descriptorSetCount,
- descriptorSets, dynamicOffsetCount, dynamicOffsets);
-}
-
-void CommandBuffer::executeCommands(uint32_t commandBufferCount,
- const vk::CommandBuffer *commandBuffers)
-{
- ASSERT(valid());
- vkCmdExecuteCommands(mHandle, commandBufferCount, commandBuffers[0].ptr());
-}
-
-void CommandBuffer::updateBuffer(const vk::Buffer &buffer,
- VkDeviceSize dstOffset,
- VkDeviceSize dataSize,
- const void *data)
-{
- ASSERT(valid() && buffer.valid());
- vkCmdUpdateBuffer(mHandle, buffer.getHandle(), dstOffset, dataSize, data);
-}
-
-void CommandBuffer::pushConstants(const PipelineLayout &layout,
- VkShaderStageFlags flag,
- uint32_t offset,
- uint32_t size,
- const void *data)
-{
- ASSERT(valid() && layout.valid());
- vkCmdPushConstants(mHandle, layout.getHandle(), flag, offset, size, data);
-}
-
-void CommandBuffer::setEvent(const vk::Event &event, VkPipelineStageFlags stageMask)
-{
- ASSERT(valid() && event.valid());
- vkCmdSetEvent(mHandle, event.getHandle(), stageMask);
-}
-
-void CommandBuffer::resetEvent(const vk::Event &event, VkPipelineStageFlags stageMask)
-{
- ASSERT(valid() && event.valid());
- vkCmdResetEvent(mHandle, event.getHandle(), stageMask);
-}
-
-void CommandBuffer::waitEvents(uint32_t eventCount,
- const VkEvent *events,
- VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask,
- uint32_t memoryBarrierCount,
- const VkMemoryBarrier *memoryBarriers,
- uint32_t bufferMemoryBarrierCount,
- const VkBufferMemoryBarrier *bufferMemoryBarriers,
- uint32_t imageMemoryBarrierCount,
- const VkImageMemoryBarrier *imageMemoryBarriers)
-{
- ASSERT(valid());
- vkCmdWaitEvents(mHandle, eventCount, events, srcStageMask, dstStageMask, memoryBarrierCount,
- memoryBarriers, bufferMemoryBarrierCount, bufferMemoryBarriers,
- imageMemoryBarrierCount, imageMemoryBarriers);
-}
-
-void CommandBuffer::resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount)
-{
- ASSERT(valid());
- vkCmdResetQueryPool(mHandle, queryPool, firstQuery, queryCount);
-}
-
-void CommandBuffer::beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags)
-{
- ASSERT(valid());
- vkCmdBeginQuery(mHandle, queryPool, query, flags);
-}
-
-void CommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
-{
- ASSERT(valid());
- vkCmdEndQuery(mHandle, queryPool, query);
-}
-
-void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage,
- VkQueryPool queryPool,
- uint32_t query)
-{
- ASSERT(valid());
- vkCmdWriteTimestamp(mHandle, pipelineStage, queryPool, query);
-}
-
-void CommandBuffer::setViewport(uint32_t firstViewport,
- uint32_t viewportCount,
- const VkViewport *viewports)
-{
- ASSERT(valid());
- vkCmdSetViewport(mHandle, firstViewport, viewportCount, viewports);
-}
-
-void CommandBuffer::setScissor(uint32_t firstScissor,
- uint32_t scissorCount,
- const VkRect2D *scissors)
-{
- ASSERT(valid());
- vkCmdSetScissor(mHandle, firstScissor, scissorCount, scissors);
-}
-
-// Image implementation.
-Image::Image() {}
-
-void Image::setHandle(VkImage handle)
-{
- mHandle = handle;
-}
-
-void Image::reset()
-{
- mHandle = VK_NULL_HANDLE;
-}
-
-void Image::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyImage(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult Image::init(VkDevice device, const VkImageCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateImage(device, &createInfo, nullptr, &mHandle);
-}
-
-void Image::getMemoryRequirements(VkDevice device, VkMemoryRequirements *requirementsOut) const
-{
- ASSERT(valid());
- vkGetImageMemoryRequirements(device, mHandle, requirementsOut);
-}
-
-VkResult Image::bindMemory(VkDevice device, const vk::DeviceMemory &deviceMemory)
-{
- ASSERT(valid() && deviceMemory.valid());
- return vkBindImageMemory(device, mHandle, deviceMemory.getHandle(), 0);
-}
-
-void Image::getSubresourceLayout(VkDevice device,
- VkImageAspectFlagBits aspectMask,
- uint32_t mipLevel,
- uint32_t arrayLayer,
- VkSubresourceLayout *outSubresourceLayout) const
-{
- VkImageSubresource subresource = {};
- subresource.aspectMask = aspectMask;
- subresource.mipLevel = mipLevel;
- subresource.arrayLayer = arrayLayer;
-
- vkGetImageSubresourceLayout(device, getHandle(), &subresource, outSubresourceLayout);
-}
-
-// ImageView implementation.
-ImageView::ImageView() {}
-
-void ImageView::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyImageView(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult ImageView::init(VkDevice device, const VkImageViewCreateInfo &createInfo)
-{
- return vkCreateImageView(device, &createInfo, nullptr, &mHandle);
-}
-
-// Semaphore implementation.
-Semaphore::Semaphore() {}
-
-void Semaphore::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroySemaphore(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult Semaphore::init(VkDevice device)
-{
- ASSERT(!valid());
-
- VkSemaphoreCreateInfo semaphoreInfo = {};
- semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
- semaphoreInfo.flags = 0;
-
- return vkCreateSemaphore(device, &semaphoreInfo, nullptr, &mHandle);
-}
-
-// Framebuffer implementation.
-Framebuffer::Framebuffer() {}
-
-void Framebuffer::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyFramebuffer(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult Framebuffer::init(VkDevice device, const VkFramebufferCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateFramebuffer(device, &createInfo, nullptr, &mHandle);
-}
-
-void Framebuffer::setHandle(VkFramebuffer handle)
-{
- mHandle = handle;
-}
-
-// DeviceMemory implementation.
-DeviceMemory::DeviceMemory() {}
-
-void DeviceMemory::destroy(VkDevice device)
-{
- if (valid())
- {
- vkFreeMemory(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult DeviceMemory::allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo)
-{
- ASSERT(!valid());
- return vkAllocateMemory(device, &allocInfo, nullptr, &mHandle);
-}
-
-VkResult DeviceMemory::map(VkDevice device,
- VkDeviceSize offset,
- VkDeviceSize size,
- VkMemoryMapFlags flags,
- uint8_t **mapPointer) const
-{
- ASSERT(valid());
- return vkMapMemory(device, mHandle, offset, size, flags, reinterpret_cast<void **>(mapPointer));
-}
-
-void DeviceMemory::unmap(VkDevice device) const
-{
- ASSERT(valid());
- vkUnmapMemory(device, mHandle);
-}
-
-// RenderPass implementation.
-RenderPass::RenderPass() {}
-
-void RenderPass::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyRenderPass(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult RenderPass::init(VkDevice device, const VkRenderPassCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateRenderPass(device, &createInfo, nullptr, &mHandle);
-}
-
-// Buffer implementation.
-Buffer::Buffer() {}
-
-void Buffer::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyBuffer(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateBuffer(device, &createInfo, nullptr, &mHandle);
-}
-
-VkResult Buffer::bindMemory(VkDevice device, const DeviceMemory &deviceMemory)
-{
- ASSERT(valid() && deviceMemory.valid());
- return vkBindBufferMemory(device, mHandle, deviceMemory.getHandle(), 0);
-}
-
-void Buffer::getMemoryRequirements(VkDevice device, VkMemoryRequirements *memoryRequirementsOut)
-{
- ASSERT(valid());
- vkGetBufferMemoryRequirements(device, mHandle, memoryRequirementsOut);
-}
-
-// BufferView implementation.
-BufferView::BufferView() {}
-
-void BufferView::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyBufferView(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult BufferView::init(VkDevice device, const VkBufferViewCreateInfo &createInfo)
-{
- return vkCreateBufferView(device, &createInfo, nullptr, &mHandle);
-}
-
-// ShaderModule implementation.
-ShaderModule::ShaderModule() {}
-
-void ShaderModule::destroy(VkDevice device)
-{
- if (mHandle != VK_NULL_HANDLE)
- {
- vkDestroyShaderModule(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult ShaderModule::init(VkDevice device, const VkShaderModuleCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateShaderModule(device, &createInfo, nullptr, &mHandle);
-}
-
-// PipelineLayout implementation.
-PipelineLayout::PipelineLayout() {}
-
-void PipelineLayout::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyPipelineLayout(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult PipelineLayout::init(VkDevice device, const VkPipelineLayoutCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreatePipelineLayout(device, &createInfo, nullptr, &mHandle);
-}
-
-// PipelineCache implementation.
-PipelineCache::PipelineCache() {}
-
-void PipelineCache::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyPipelineCache(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult PipelineCache::init(VkDevice device, const VkPipelineCacheCreateInfo &createInfo)
-{
- ASSERT(!valid());
- // Note: if we are concerned with memory usage of this cache, we should give it custom
- // allocators. Also, failure of this function is of little importance.
- return vkCreatePipelineCache(device, &createInfo, nullptr, &mHandle);
-}
-
-VkResult PipelineCache::getCacheData(VkDevice device, size_t *cacheSize, void *cacheData)
-{
- ASSERT(valid());
-
- // Note: vkGetPipelineCacheData can return VK_INCOMPLETE if cacheSize is smaller than actual
- // size. There are two usages of this function. One is with *cacheSize == 0 to query the size
- // of the cache, and one is with an appropriate buffer to retrieve the cache contents.
- // VK_INCOMPLETE in the first case is an expected output. In the second case, VK_INCOMPLETE is
- // also acceptable and the resulting buffer will contain valid value by spec. Angle currently
- // ensures *cacheSize to be either 0 or of enough size, therefore VK_INCOMPLETE is not expected.
- return vkGetPipelineCacheData(device, mHandle, cacheSize, cacheData);
-}
-
-// Pipeline implementation.
-Pipeline::Pipeline() {}
-
-void Pipeline::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyPipeline(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult Pipeline::initGraphics(VkDevice device,
- const VkGraphicsPipelineCreateInfo &createInfo,
- const PipelineCache &pipelineCacheVk)
-{
- ASSERT(!valid());
- return vkCreateGraphicsPipelines(device, pipelineCacheVk.getHandle(), 1, &createInfo, nullptr,
- &mHandle);
-}
-
-VkResult Pipeline::initCompute(VkDevice device,
- const VkComputePipelineCreateInfo &createInfo,
- const PipelineCache &pipelineCacheVk)
-{
- ASSERT(!valid());
- return vkCreateComputePipelines(device, pipelineCacheVk.getHandle(), 1, &createInfo, nullptr,
- &mHandle);
-}
-
-// DescriptorSetLayout implementation.
-DescriptorSetLayout::DescriptorSetLayout() {}
-
-void DescriptorSetLayout::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyDescriptorSetLayout(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult DescriptorSetLayout::init(VkDevice device,
- const VkDescriptorSetLayoutCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateDescriptorSetLayout(device, &createInfo, nullptr, &mHandle);
-}
-
-// DescriptorPool implementation.
-DescriptorPool::DescriptorPool() {}
-
-void DescriptorPool::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyDescriptorPool(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult DescriptorPool::init(VkDevice device, const VkDescriptorPoolCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateDescriptorPool(device, &createInfo, nullptr, &mHandle);
-}
-
-VkResult DescriptorPool::allocateDescriptorSets(VkDevice device,
- const VkDescriptorSetAllocateInfo &allocInfo,
- VkDescriptorSet *descriptorSetsOut)
-{
- ASSERT(valid());
- return vkAllocateDescriptorSets(device, &allocInfo, descriptorSetsOut);
-}
-
-VkResult DescriptorPool::freeDescriptorSets(VkDevice device,
- uint32_t descriptorSetCount,
- const VkDescriptorSet *descriptorSets)
-{
- ASSERT(valid());
- ASSERT(descriptorSetCount > 0);
- return vkFreeDescriptorSets(device, mHandle, descriptorSetCount, descriptorSets);
-}
-
-// Sampler implementation.
-Sampler::Sampler() {}
-
-void Sampler::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroySampler(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult Sampler::init(VkDevice device, const VkSamplerCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateSampler(device, &createInfo, nullptr, &mHandle);
-}
-
-// Event implementation.
-Event::Event() {}
-
-void Event::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyEvent(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult Event::init(VkDevice device, const VkEventCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateEvent(device, &createInfo, nullptr, &mHandle);
-}
-
-VkResult Event::getStatus(VkDevice device) const
-{
- return vkGetEventStatus(device, mHandle);
-}
-
-VkResult Event::set(VkDevice device) const
-{
- return vkSetEvent(device, mHandle);
-}
-
-VkResult Event::reset(VkDevice device) const
-{
- return vkResetEvent(device, mHandle);
-}
-
-// Fence implementation.
-Fence::Fence() {}
-
-void Fence::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyFence(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult Fence::init(VkDevice device, const VkFenceCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateFence(device, &createInfo, nullptr, &mHandle);
-}
-
-VkResult Fence::getStatus(VkDevice device) const
-{
- return vkGetFenceStatus(device, mHandle);
-}
-
-VkResult Fence::wait(VkDevice device, uint64_t timeout) const
-{
- return vkWaitForFences(device, 1, &mHandle, true, timeout);
-}
-
// MemoryProperties implementation.
MemoryProperties::MemoryProperties() : mMemoryProperties{0} {}
@@ -1102,7 +354,7 @@ angle::Result StagingBuffer::init(Context *context, VkDeviceSize size, StagingUs
ANGLE_VK_TRY(context, mBuffer.init(context->getDevice(), createInfo));
VkMemoryPropertyFlags flagsOut = 0;
- ANGLE_TRY(AllocateBufferMemory(context, flags, &flagsOut, &mBuffer, &mDeviceMemory));
+ ANGLE_TRY(AllocateBufferMemory(context, flags, &flagsOut, nullptr, &mBuffer, &mDeviceMemory));
mSize = static_cast<size_t>(size);
return angle::Result::Continue;
}
@@ -1113,54 +365,40 @@ void StagingBuffer::dumpResources(Serial serial, std::vector<vk::GarbageObject>
mDeviceMemory.dumpResources(serial, garbageQueue);
}
-// QueryPool implementation.
-QueryPool::QueryPool() {}
-
-void QueryPool::destroy(VkDevice device)
-{
- if (valid())
- {
- vkDestroyQueryPool(device, mHandle, nullptr);
- mHandle = VK_NULL_HANDLE;
- }
-}
-
-VkResult QueryPool::init(VkDevice device, const VkQueryPoolCreateInfo &createInfo)
-{
- ASSERT(!valid());
- return vkCreateQueryPool(device, &createInfo, nullptr, &mHandle);
-}
-
-VkResult QueryPool::getResults(VkDevice device,
- uint32_t firstQuery,
- uint32_t queryCount,
- size_t dataSize,
- void *data,
- VkDeviceSize stride,
- VkQueryResultFlags flags) const
-{
- return vkGetQueryPoolResults(device, mHandle, firstQuery, queryCount, dataSize, data, stride,
- flags);
-}
-
angle::Result AllocateBufferMemory(vk::Context *context,
VkMemoryPropertyFlags requestedMemoryPropertyFlags,
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
+ const void *extraAllocationInfo,
Buffer *buffer,
DeviceMemory *deviceMemoryOut)
{
return AllocateBufferOrImageMemory(context, requestedMemoryPropertyFlags,
- memoryPropertyFlagsOut, buffer, deviceMemoryOut);
+ memoryPropertyFlagsOut, extraAllocationInfo, buffer,
+ deviceMemoryOut);
}
angle::Result AllocateImageMemory(vk::Context *context,
VkMemoryPropertyFlags memoryPropertyFlags,
+ const void *extraAllocationInfo,
Image *image,
DeviceMemory *deviceMemoryOut)
{
VkMemoryPropertyFlags memoryPropertyFlagsOut = 0;
- return AllocateBufferOrImageMemory(context, memoryPropertyFlags, &memoryPropertyFlagsOut, image,
- deviceMemoryOut);
+ return AllocateBufferOrImageMemory(context, memoryPropertyFlags, &memoryPropertyFlagsOut,
+ extraAllocationInfo, image, deviceMemoryOut);
+}
+
+angle::Result AllocateImageMemoryWithRequirements(vk::Context *context,
+ VkMemoryPropertyFlags memoryPropertyFlags,
+ const VkMemoryRequirements &memoryRequirements,
+ const void *extraAllocationInfo,
+ Image *image,
+ DeviceMemory *deviceMemoryOut)
+{
+ VkMemoryPropertyFlags memoryPropertyFlagsOut = 0;
+ return AllocateAndBindBufferOrImageMemory(context, memoryPropertyFlags, &memoryPropertyFlagsOut,
+ memoryRequirements, extraAllocationInfo, image,
+ deviceMemoryOut);
}
angle::Result InitShaderAndSerial(Context *context,
@@ -1272,11 +510,22 @@ void GarbageObject::destroy(VkDevice device)
// VK_EXT_debug_utils
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = nullptr;
PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr;
+PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT = nullptr;
+PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT = nullptr;
+PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT = nullptr;
// VK_EXT_debug_report
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = nullptr;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr;
+// VK_KHR_get_physical_device_properties2
+PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR = nullptr;
+
+#if defined(ANGLE_PLATFORM_FUCHSIA)
+// VK_FUCHSIA_imagepipe_surface
+PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA = nullptr;
+#endif
+
#define GET_FUNC(vkName) \
do \
{ \
@@ -1288,6 +537,9 @@ void InitDebugUtilsEXTFunctions(VkInstance instance)
{
GET_FUNC(vkCreateDebugUtilsMessengerEXT);
GET_FUNC(vkDestroyDebugUtilsMessengerEXT);
+ GET_FUNC(vkCmdBeginDebugUtilsLabelEXT);
+ GET_FUNC(vkCmdEndDebugUtilsLabelEXT);
+ GET_FUNC(vkCmdInsertDebugUtilsLabelEXT);
}
void InitDebugReportEXTFunctions(VkInstance instance)
@@ -1296,6 +548,29 @@ void InitDebugReportEXTFunctions(VkInstance instance)
GET_FUNC(vkDestroyDebugReportCallbackEXT);
}
+void InitGetPhysicalDeviceProperties2KHRFunctions(VkInstance instance)
+{
+ GET_FUNC(vkGetPhysicalDeviceProperties2KHR);
+}
+
+#if defined(ANGLE_PLATFORM_FUCHSIA)
+void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance)
+{
+ GET_FUNC(vkCreateImagePipeSurfaceFUCHSIA);
+}
+#endif
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID =
+ nullptr;
+PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID = nullptr;
+void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance)
+{
+ GET_FUNC(vkGetAndroidHardwareBufferPropertiesANDROID);
+ GET_FUNC(vkGetMemoryAndroidHardwareBufferANDROID);
+}
+#endif
+
#undef GET_FUNC
namespace gl_vk
@@ -1489,6 +764,7 @@ VkImageType GetImageType(gl::TextureType textureType)
case gl::TextureType::_2DMultisample:
case gl::TextureType::_2DMultisampleArray:
case gl::TextureType::CubeMap:
+ case gl::TextureType::External:
return VK_IMAGE_TYPE_2D;
case gl::TextureType::_3D:
return VK_IMAGE_TYPE_3D;
@@ -1505,6 +781,7 @@ VkImageViewType GetImageViewType(gl::TextureType textureType)
{
case gl::TextureType::_2D:
case gl::TextureType::_2DMultisample:
+ case gl::TextureType::External:
return VK_IMAGE_VIEW_TYPE_2D;
case gl::TextureType::_2DArray:
case gl::TextureType::_2DMultisampleArray:
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.h
index 027e3ebb9fd..b270878ab85 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_utils.h
@@ -12,14 +12,13 @@
#include <limits>
-#include <vulkan/vulkan.h>
-
+#include "common/FixedVector.h"
#include "common/Optional.h"
#include "common/PackedEnums.h"
#include "common/debug.h"
#include "libANGLE/Error.h"
#include "libANGLE/Observer.h"
-#include "libANGLE/renderer/renderer_utils.h"
+#include "libANGLE/renderer/vulkan/vk_wrapper.h"
#define ANGLE_GL_OBJECTS_X(PROC) \
PROC(Buffer) \
@@ -34,6 +33,7 @@
namespace egl
{
class Display;
+class Image;
}
namespace gl
@@ -47,7 +47,7 @@ struct SwizzleState;
struct VertexAttribute;
class VertexBinding;
-ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_OBJECT);
+ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_OBJECT)
} // namespace gl
#define ANGLE_PRE_DECLARE_VK_OBJECT(OBJ) class OBJ##Vk;
@@ -56,6 +56,7 @@ namespace rx
{
class CommandGraphResource;
class DisplayVk;
+class ImageVk;
class RenderTargetVk;
class RendererVk;
class RenderPassCache;
@@ -68,14 +69,17 @@ egl::Error ToEGL(Result result, rx::DisplayVk *displayVk, EGLint errorCode);
namespace rx
{
-ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_VK_OBJECT);
+ANGLE_GL_OBJECTS_X(ANGLE_PRE_DECLARE_VK_OBJECT)
const char *VulkanResultString(VkResult result);
+
+constexpr size_t kMaxVulkanLayers = 20;
+using VulkanLayerVector = angle::FixedVector<const char *, kMaxVulkanLayers>;
+
// Verify that validation layers are available.
bool GetAvailableValidationLayers(const std::vector<VkLayerProperties> &layerProps,
bool mustHaveLayers,
- const char *const **enabledLayerNames,
- uint32_t *enabledLayerCount);
+ VulkanLayerVector *enabledLayerNames);
extern const char *g_VkLoaderLayersPathEnv;
extern const char *g_VkICDPathEnv;
@@ -134,6 +138,12 @@ struct ImplTypeHelper<egl::Display>
using ImplType = DisplayVk;
};
+template <>
+struct ImplTypeHelper<egl::Image>
+{
+ using ImplType = ImageVk;
+};
+
template <typename T>
using GetImplType = typename ImplTypeHelper<T>::ImplType;
@@ -143,65 +153,6 @@ GetImplType<T> *GetImpl(const T *glObject)
return GetImplAs<GetImplType<T>>(glObject);
}
-// Unimplemented handle types:
-// Instance
-// PhysicalDevice
-// Device
-// Queue
-// DescriptorSet
-
-#define ANGLE_HANDLE_TYPES_X(FUNC) \
- FUNC(Buffer) \
- FUNC(BufferView) \
- FUNC(CommandBuffer) \
- FUNC(CommandPool) \
- FUNC(DescriptorPool) \
- FUNC(DescriptorSetLayout) \
- FUNC(DeviceMemory) \
- FUNC(Event) \
- FUNC(Fence) \
- FUNC(Framebuffer) \
- FUNC(Image) \
- FUNC(ImageView) \
- FUNC(Pipeline) \
- FUNC(PipelineCache) \
- FUNC(PipelineLayout) \
- FUNC(QueryPool) \
- FUNC(RenderPass) \
- FUNC(Sampler) \
- FUNC(Semaphore) \
- FUNC(ShaderModule)
-
-#define ANGLE_COMMA_SEP_FUNC(TYPE) TYPE,
-
-enum class HandleType
-{
- Invalid,
- ANGLE_HANDLE_TYPES_X(ANGLE_COMMA_SEP_FUNC)
-};
-
-#undef ANGLE_COMMA_SEP_FUNC
-
-#define ANGLE_PRE_DECLARE_CLASS_FUNC(TYPE) class TYPE;
-ANGLE_HANDLE_TYPES_X(ANGLE_PRE_DECLARE_CLASS_FUNC)
-#undef ANGLE_PRE_DECLARE_CLASS_FUNC
-
-// Returns the HandleType of a Vk Handle.
-template <typename T>
-struct HandleTypeHelper;
-
-// clang-format off
-#define ANGLE_HANDLE_TYPE_HELPER_FUNC(TYPE) \
-template<> struct HandleTypeHelper<TYPE> \
-{ \
- constexpr static HandleType kHandleType = HandleType::TYPE; \
-};
-// clang-format on
-
-ANGLE_HANDLE_TYPES_X(ANGLE_HANDLE_TYPE_HELPER_FUNC)
-
-#undef ANGLE_HANDLE_TYPE_HELPER_FUNC
-
class GarbageObject final
{
public:
@@ -228,46 +179,6 @@ class GarbageObject final
VkDevice mHandle;
};
-template <typename DerivedT, typename HandleT>
-class WrappedObject : angle::NonCopyable
-{
- public:
- HandleT getHandle() const { return mHandle; }
- bool valid() const { return (mHandle != VK_NULL_HANDLE); }
-
- const HandleT *ptr() const { return &mHandle; }
-
- void dumpResources(Serial serial, std::vector<GarbageObject> *garbageQueue)
- {
- if (valid())
- {
- garbageQueue->emplace_back(serial, *static_cast<DerivedT *>(this));
- mHandle = VK_NULL_HANDLE;
- }
- }
-
- protected:
- WrappedObject() : mHandle(VK_NULL_HANDLE) {}
- ~WrappedObject() { ASSERT(!valid()); }
-
- WrappedObject(WrappedObject &&other) : mHandle(other.mHandle)
- {
- other.mHandle = VK_NULL_HANDLE;
- }
-
- // Only works to initialize empty objects, since we don't have the device handle.
- WrappedObject &operator=(WrappedObject &&other)
- {
- ASSERT(!valid());
- std::swap(mHandle, other.mHandle);
- return *this;
- }
-
- HandleT mHandle;
-};
-
-// TODO(jmadill): Inline all the methods in the wrapper classes. http://anglebug.com/3014
-
class MemoryProperties final : angle::NonCopyable
{
public:
@@ -285,393 +196,6 @@ class MemoryProperties final : angle::NonCopyable
VkPhysicalDeviceMemoryProperties mMemoryProperties;
};
-class CommandPool final : public WrappedObject<CommandPool, VkCommandPool>
-{
- public:
- CommandPool();
-
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkCommandPoolCreateInfo &createInfo);
-};
-
-class Pipeline final : public WrappedObject<Pipeline, VkPipeline>
-{
- public:
- Pipeline();
- void destroy(VkDevice device);
-
- VkResult initGraphics(VkDevice device,
- const VkGraphicsPipelineCreateInfo &createInfo,
- const PipelineCache &pipelineCacheVk);
- VkResult initCompute(VkDevice device,
- const VkComputePipelineCreateInfo &createInfo,
- const PipelineCache &pipelineCacheVk);
-};
-
-// Helper class that wraps a Vulkan command buffer.
-class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
-{
- public:
- CommandBuffer();
-
- VkCommandBuffer releaseHandle();
-
- // This is used for normal pool allocated command buffers. It reset the handle.
- void destroy(VkDevice device);
-
- // This is used in conjunction with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT.
- void destroy(VkDevice device, const CommandPool &commandPool);
-
- VkResult init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo);
- void blitImage(const Image &srcImage,
- VkImageLayout srcImageLayout,
- const Image &dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- VkImageBlit *pRegions,
- VkFilter filter);
- using WrappedObject::operator=;
-
- VkResult begin(const VkCommandBufferBeginInfo &info);
-
- VkResult end();
- VkResult reset();
-
- void pipelineBarrier(VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask,
- VkDependencyFlags dependencyFlags,
- uint32_t memoryBarrierCount,
- const VkMemoryBarrier *memoryBarriers,
- uint32_t bufferMemoryBarrierCount,
- const VkBufferMemoryBarrier *bufferMemoryBarriers,
- uint32_t imageMemoryBarrierCount,
- const VkImageMemoryBarrier *imageMemoryBarriers);
-
- void clearColorImage(const Image &image,
- VkImageLayout imageLayout,
- const VkClearColorValue &color,
- uint32_t rangeCount,
- const VkImageSubresourceRange *ranges);
- void clearDepthStencilImage(const Image &image,
- VkImageLayout imageLayout,
- const VkClearDepthStencilValue &depthStencil,
- uint32_t rangeCount,
- const VkImageSubresourceRange *ranges);
-
- void clearAttachments(uint32_t attachmentCount,
- const VkClearAttachment *attachments,
- uint32_t rectCount,
- const VkClearRect *rects);
-
- void copyBuffer(const Buffer &srcBuffer,
- const Buffer &destBuffer,
- uint32_t regionCount,
- const VkBufferCopy *regions);
-
- void copyBuffer(const VkBuffer &srcBuffer,
- const VkBuffer &destBuffer,
- uint32_t regionCount,
- const VkBufferCopy *regions);
-
- void copyBufferToImage(VkBuffer srcBuffer,
- const Image &dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- const VkBufferImageCopy *regions);
- void copyImageToBuffer(const Image &srcImage,
- VkImageLayout srcImageLayout,
- VkBuffer dstBuffer,
- uint32_t regionCount,
- const VkBufferImageCopy *regions);
- void copyImage(const Image &srcImage,
- VkImageLayout srcImageLayout,
- const Image &dstImage,
- VkImageLayout dstImageLayout,
- uint32_t regionCount,
- const VkImageCopy *regions);
-
- void beginRenderPass(const VkRenderPassBeginInfo &beginInfo, VkSubpassContents subpassContents);
- void endRenderPass();
-
- void draw(uint32_t vertexCount,
- uint32_t instanceCount,
- uint32_t firstVertex,
- uint32_t firstInstance)
- {
- ASSERT(valid());
- vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
- }
-
- void drawIndexed(uint32_t indexCount,
- uint32_t instanceCount,
- uint32_t firstIndex,
- int32_t vertexOffset,
- uint32_t firstInstance)
- {
- ASSERT(valid());
- vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset,
- firstInstance);
- }
-
- void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ)
- {
- ASSERT(valid());
- vkCmdDispatch(mHandle, groupCountX, groupCountY, groupCountZ);
- }
-
- void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline)
- {
- ASSERT(valid() && pipeline.valid());
- vkCmdBindPipeline(mHandle, pipelineBindPoint, pipeline.getHandle());
- }
-
- void bindVertexBuffers(uint32_t firstBinding,
- uint32_t bindingCount,
- const VkBuffer *buffers,
- const VkDeviceSize *offsets)
- {
- ASSERT(valid());
- vkCmdBindVertexBuffers(mHandle, firstBinding, bindingCount, buffers, offsets);
- }
-
- void bindIndexBuffer(const VkBuffer &buffer, VkDeviceSize offset, VkIndexType indexType);
- void bindDescriptorSets(VkPipelineBindPoint bindPoint,
- const PipelineLayout &layout,
- uint32_t firstSet,
- uint32_t descriptorSetCount,
- const VkDescriptorSet *descriptorSets,
- uint32_t dynamicOffsetCount,
- const uint32_t *dynamicOffsets);
-
- void executeCommands(uint32_t commandBufferCount, const CommandBuffer *commandBuffers);
- void updateBuffer(const vk::Buffer &buffer,
- VkDeviceSize dstOffset,
- VkDeviceSize dataSize,
- const void *data);
- void pushConstants(const PipelineLayout &layout,
- VkShaderStageFlags flag,
- uint32_t offset,
- uint32_t size,
- const void *data);
-
- void setEvent(const vk::Event &event, VkPipelineStageFlags stageMask);
- void resetEvent(const vk::Event &event, VkPipelineStageFlags stageMask);
- void waitEvents(uint32_t eventCount,
- const VkEvent *events,
- VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask,
- uint32_t memoryBarrierCount,
- const VkMemoryBarrier *memoryBarriers,
- uint32_t bufferMemoryBarrierCount,
- const VkBufferMemoryBarrier *bufferMemoryBarriers,
- uint32_t imageMemoryBarrierCount,
- const VkImageMemoryBarrier *imageMemoryBarriers);
-
- void resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
- void beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
- void endQuery(VkQueryPool queryPool, uint32_t query);
- void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
- VkQueryPool queryPool,
- uint32_t query);
-
- void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports);
- void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors);
-};
-
-class Image final : public WrappedObject<Image, VkImage>
-{
- public:
- Image();
-
- // Use this method if the lifetime of the image is not controlled by ANGLE. (SwapChain)
- void setHandle(VkImage handle);
-
- // Called on shutdown when the helper class *doesn't* own the handle to the image resource.
- void reset();
-
- // Called on shutdown when the helper class *does* own the handle to the image resource.
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkImageCreateInfo &createInfo);
-
- void getMemoryRequirements(VkDevice device, VkMemoryRequirements *requirementsOut) const;
- VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
-
- void getSubresourceLayout(VkDevice device,
- VkImageAspectFlagBits aspectMask,
- uint32_t mipLevel,
- uint32_t arrayLayer,
- VkSubresourceLayout *outSubresourceLayout) const;
-};
-
-class ImageView final : public WrappedObject<ImageView, VkImageView>
-{
- public:
- ImageView();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkImageViewCreateInfo &createInfo);
-};
-
-class Semaphore final : public WrappedObject<Semaphore, VkSemaphore>
-{
- public:
- Semaphore();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device);
-};
-
-class Framebuffer final : public WrappedObject<Framebuffer, VkFramebuffer>
-{
- public:
- Framebuffer();
- void destroy(VkDevice device);
-
- // Use this method only in necessary cases. (RenderPass)
- void setHandle(VkFramebuffer handle);
-
- VkResult init(VkDevice device, const VkFramebufferCreateInfo &createInfo);
-};
-
-class DeviceMemory final : public WrappedObject<DeviceMemory, VkDeviceMemory>
-{
- public:
- DeviceMemory();
- void destroy(VkDevice device);
-
- VkResult allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo);
- VkResult map(VkDevice device,
- VkDeviceSize offset,
- VkDeviceSize size,
- VkMemoryMapFlags flags,
- uint8_t **mapPointer) const;
- void unmap(VkDevice device) const;
-};
-
-class RenderPass final : public WrappedObject<RenderPass, VkRenderPass>
-{
- public:
- RenderPass();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkRenderPassCreateInfo &createInfo);
-};
-
-enum class StagingUsage
-{
- Read,
- Write,
- Both,
-};
-
-class Buffer final : public WrappedObject<Buffer, VkBuffer>
-{
- public:
- Buffer();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkBufferCreateInfo &createInfo);
- VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
- void getMemoryRequirements(VkDevice device, VkMemoryRequirements *memoryRequirementsOut);
-};
-
-class BufferView final : public WrappedObject<BufferView, VkBufferView>
-{
- public:
- BufferView();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkBufferViewCreateInfo &createInfo);
-};
-
-class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule>
-{
- public:
- ShaderModule();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkShaderModuleCreateInfo &createInfo);
-};
-
-class PipelineLayout final : public WrappedObject<PipelineLayout, VkPipelineLayout>
-{
- public:
- PipelineLayout();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkPipelineLayoutCreateInfo &createInfo);
-};
-
-class PipelineCache final : public WrappedObject<PipelineCache, VkPipelineCache>
-{
- public:
- PipelineCache();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkPipelineCacheCreateInfo &createInfo);
- VkResult getCacheData(VkDevice device, size_t *cacheSize, void *cacheData);
-};
-
-class DescriptorSetLayout final : public WrappedObject<DescriptorSetLayout, VkDescriptorSetLayout>
-{
- public:
- DescriptorSetLayout();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkDescriptorSetLayoutCreateInfo &createInfo);
-};
-
-class DescriptorPool final : public WrappedObject<DescriptorPool, VkDescriptorPool>
-{
- public:
- DescriptorPool();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkDescriptorPoolCreateInfo &createInfo);
-
- VkResult allocateDescriptorSets(VkDevice device,
- const VkDescriptorSetAllocateInfo &allocInfo,
- VkDescriptorSet *descriptorSetsOut);
- VkResult freeDescriptorSets(VkDevice device,
- uint32_t descriptorSetCount,
- const VkDescriptorSet *descriptorSets);
-};
-
-class Sampler final : public WrappedObject<Sampler, VkSampler>
-{
- public:
- Sampler();
- void destroy(VkDevice device);
- VkResult init(VkDevice device, const VkSamplerCreateInfo &createInfo);
-};
-
-class Event final : public WrappedObject<Event, VkEvent>
-{
- public:
- Event();
- void destroy(VkDevice device);
- using WrappedObject::operator=;
-
- VkResult init(VkDevice device, const VkEventCreateInfo &createInfo);
- VkResult getStatus(VkDevice device) const;
- VkResult set(VkDevice device) const;
- VkResult reset(VkDevice device) const;
-};
-
-class Fence final : public WrappedObject<Fence, VkFence>
-{
- public:
- Fence();
- void destroy(VkDevice device);
- using WrappedObject::operator=;
-
- VkResult init(VkDevice device, const VkFenceCreateInfo &createInfo);
- VkResult getStatus(VkDevice device) const;
- VkResult wait(VkDevice device, uint64_t timeout) const;
-};
-
// Similar to StagingImage, for Buffers.
class StagingBuffer final : angle::NonCopyable
{
@@ -695,22 +219,6 @@ class StagingBuffer final : angle::NonCopyable
size_t mSize;
};
-class QueryPool final : public WrappedObject<QueryPool, VkQueryPool>
-{
- public:
- QueryPool();
- void destroy(VkDevice device);
-
- VkResult init(VkDevice device, const VkQueryPoolCreateInfo &createInfo);
- VkResult getResults(VkDevice device,
- uint32_t firstQuery,
- uint32_t queryCount,
- size_t dataSize,
- void *data,
- VkDeviceSize stride,
- VkQueryResultFlags flags) const;
-};
-
template <typename ObjT>
class ObjectAndSerial final : angle::NonCopyable
{
@@ -751,13 +259,21 @@ class ObjectAndSerial final : angle::NonCopyable
angle::Result AllocateBufferMemory(vk::Context *context,
VkMemoryPropertyFlags requestedMemoryPropertyFlags,
VkMemoryPropertyFlags *memoryPropertyFlagsOut,
+ const void *extraAllocationInfo,
Buffer *buffer,
DeviceMemory *deviceMemoryOut);
angle::Result AllocateImageMemory(vk::Context *context,
VkMemoryPropertyFlags memoryPropertyFlags,
+ const void *extraAllocationInfo,
Image *image,
DeviceMemory *deviceMemoryOut);
+angle::Result AllocateImageMemoryWithRequirements(vk::Context *context,
+ VkMemoryPropertyFlags memoryPropertyFlags,
+ const VkMemoryRequirements &memoryRequirements,
+ const void *extraAllocationInfo,
+ Image *image,
+ DeviceMemory *deviceMemoryOut);
using ShaderAndSerial = ObjectAndSerial<ShaderModule>;
@@ -803,6 +319,7 @@ class RefCounted : angle::NonCopyable
RefCounted(RefCounted &&copy) : mRefCount(copy.mRefCount), mObject(std::move(copy.mObject))
{
+ ASSERT(this != &copy);
copy.mRefCount = 0;
}
@@ -868,20 +385,110 @@ class BindingPointer final : angle::NonCopyable
private:
RefCounted<T> *mRefCounted;
};
+
+// Helper class to share ref-counted Vulkan objects. Requires that T have a destroy method
+// that takes a VkDevice and returns void.
+template <typename T>
+class Shared final : angle::NonCopyable
+{
+ public:
+ Shared() : mRefCounted(nullptr) {}
+ ~Shared() { ASSERT(mRefCounted == nullptr); }
+
+ Shared(Shared &&other) { *this = std::move(other); }
+ Shared &operator=(Shared &&other)
+ {
+ ASSERT(this != &other);
+ mRefCounted = other.mRefCounted;
+ other.mRefCounted = nullptr;
+ return *this;
+ }
+
+ void set(VkDevice device, RefCounted<T> *refCounted)
+ {
+ if (mRefCounted)
+ {
+ mRefCounted->releaseRef();
+ if (!mRefCounted->isReferenced())
+ {
+ mRefCounted->get().destroy(device);
+ SafeDelete(mRefCounted);
+ }
+ }
+
+ mRefCounted = refCounted;
+
+ if (mRefCounted)
+ {
+ mRefCounted->addRef();
+ }
+ }
+
+ void assign(VkDevice device, T &&newObject)
+ {
+ set(device, new RefCounted<T>(std::move(newObject)));
+ }
+
+ void copy(VkDevice device, const Shared<T> &other) { set(device, other.mRefCounted); }
+
+ void reset(VkDevice device) { set(device, nullptr); }
+
+ bool isReferenced() const
+ {
+ // If reference is zero, the object should have been deleted. I.e. if the object is not
+ // nullptr, it should have a reference.
+ ASSERT(!mRefCounted || mRefCounted->isReferenced());
+ return mRefCounted != nullptr;
+ }
+
+ T &get()
+ {
+ ASSERT(mRefCounted && mRefCounted->isReferenced());
+ return mRefCounted->get();
+ }
+ const T &get() const
+ {
+ ASSERT(mRefCounted && mRefCounted->isReferenced());
+ return mRefCounted->get();
+ }
+
+ private:
+ RefCounted<T> *mRefCounted;
+};
} // namespace vk
// List of function pointers for used extensions.
// VK_EXT_debug_utils
extern PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
+extern PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;
+extern PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;
+extern PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT;
// VK_EXT_debug_report
extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
+// VK_KHR_get_physical_device_properties2
+extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
+
// Lazily load entry points for each extension as necessary.
void InitDebugUtilsEXTFunctions(VkInstance instance);
void InitDebugReportEXTFunctions(VkInstance instance);
+void InitGetPhysicalDeviceProperties2KHRFunctions(VkInstance instance);
+
+#if defined(ANGLE_PLATFORM_FUCHSIA)
+// VK_FUCHSIA_imagepipe_surface
+extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA;
+void InitImagePipeSurfaceFUCHSIAFunctions(VkInstance instance);
+#endif
+
+#if defined(ANGLE_PLATFORM_ANDROID)
+// VK_ANDROID_external_memory_android_hardware_buffer
+extern PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID;
+extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID;
+void InitExternalMemoryHardwareBufferANDROIDFunctions(VkInstance instance);
+#endif
namespace gl_vk
{
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_wrapper.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_wrapper.h
new file mode 100644
index 00000000000..de7b84ec76f
--- /dev/null
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/vk_wrapper.h
@@ -0,0 +1,1308 @@
+//
+// Copyright 2019 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.
+//
+// vk_wrapper:
+// Wrapper classes around Vulkan objects. In an ideal world we could generate this
+// from vk.xml. Or reuse the generator in the vkhpp tool. For now this is manually
+// generated and we must add missing functions and objects as we need them.
+
+#ifndef LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
+#define LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
+
+#include <vulkan/vulkan.h>
+
+#include "libANGLE/renderer/renderer_utils.h"
+
+namespace rx
+{
+namespace vk
+{
+// Base class for all wrapped vulkan objects. Implements several common helper routines.
+template <typename DerivedT, typename HandleT>
+class WrappedObject : angle::NonCopyable
+{
+ public:
+ HandleT getHandle() const { return mHandle; }
+ bool valid() const { return (mHandle != VK_NULL_HANDLE); }
+
+ const HandleT *ptr() const { return &mHandle; }
+
+ template <typename ResourceOutType>
+ void dumpResources(Serial serial, std::vector<ResourceOutType> *outQueue)
+ {
+ if (valid())
+ {
+ outQueue->emplace_back(serial, *static_cast<DerivedT *>(this));
+ mHandle = VK_NULL_HANDLE;
+ }
+ }
+
+ protected:
+ WrappedObject() : mHandle(VK_NULL_HANDLE) {}
+ ~WrappedObject() { ASSERT(!valid()); }
+
+ WrappedObject(WrappedObject &&other) : mHandle(other.mHandle)
+ {
+ other.mHandle = VK_NULL_HANDLE;
+ }
+
+ // Only works to initialize empty objects, since we don't have the device handle.
+ WrappedObject &operator=(WrappedObject &&other)
+ {
+ ASSERT(!valid());
+ std::swap(mHandle, other.mHandle);
+ return *this;
+ }
+
+ HandleT mHandle;
+};
+
+// Helper macros that apply to all the wrapped object types.
+// Unimplemented handle types:
+// Instance
+// PhysicalDevice
+// Device
+// Queue
+// DescriptorSet
+
+#define ANGLE_HANDLE_TYPES_X(FUNC) \
+ FUNC(Buffer) \
+ FUNC(BufferView) \
+ FUNC(CommandBuffer) \
+ FUNC(CommandPool) \
+ FUNC(DescriptorPool) \
+ FUNC(DescriptorSetLayout) \
+ FUNC(DeviceMemory) \
+ FUNC(Event) \
+ FUNC(Fence) \
+ FUNC(Framebuffer) \
+ FUNC(Image) \
+ FUNC(ImageView) \
+ FUNC(Pipeline) \
+ FUNC(PipelineCache) \
+ FUNC(PipelineLayout) \
+ FUNC(QueryPool) \
+ FUNC(RenderPass) \
+ FUNC(Sampler) \
+ FUNC(Semaphore) \
+ FUNC(ShaderModule)
+
+#define ANGLE_COMMA_SEP_FUNC(TYPE) TYPE,
+
+enum class HandleType
+{
+ Invalid,
+ ANGLE_HANDLE_TYPES_X(ANGLE_COMMA_SEP_FUNC)
+};
+
+#undef ANGLE_COMMA_SEP_FUNC
+
+#define ANGLE_PRE_DECLARE_CLASS_FUNC(TYPE) class TYPE;
+ANGLE_HANDLE_TYPES_X(ANGLE_PRE_DECLARE_CLASS_FUNC)
+#undef ANGLE_PRE_DECLARE_CLASS_FUNC
+
+// Returns the HandleType of a Vk Handle.
+template <typename T>
+struct HandleTypeHelper;
+
+#define ANGLE_HANDLE_TYPE_HELPER_FUNC(TYPE) \
+ template <> \
+ struct HandleTypeHelper<TYPE> \
+ { \
+ constexpr static HandleType kHandleType = HandleType::TYPE; \
+ };
+
+ANGLE_HANDLE_TYPES_X(ANGLE_HANDLE_TYPE_HELPER_FUNC)
+
+#undef ANGLE_HANDLE_TYPE_HELPER_FUNC
+
+class CommandPool final : public WrappedObject<CommandPool, VkCommandPool>
+{
+ public:
+ CommandPool() = default;
+
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkCommandPoolCreateInfo &createInfo);
+};
+
+class Pipeline final : public WrappedObject<Pipeline, VkPipeline>
+{
+ public:
+ Pipeline() = default;
+ void destroy(VkDevice device);
+
+ VkResult initGraphics(VkDevice device,
+ const VkGraphicsPipelineCreateInfo &createInfo,
+ const PipelineCache &pipelineCacheVk);
+ VkResult initCompute(VkDevice device,
+ const VkComputePipelineCreateInfo &createInfo,
+ const PipelineCache &pipelineCacheVk);
+};
+
+// Helper class that wraps a Vulkan command buffer.
+class CommandBuffer : public WrappedObject<CommandBuffer, VkCommandBuffer>
+{
+ public:
+ CommandBuffer() = default;
+
+ VkCommandBuffer releaseHandle();
+
+ // This is used for normal pool allocated command buffers. It reset the handle.
+ void destroy(VkDevice device);
+
+ // This is used in conjunction with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT.
+ void destroy(VkDevice device, const CommandPool &commandPool);
+
+ VkResult init(VkDevice device, const VkCommandBufferAllocateInfo &createInfo);
+ void blitImage(const Image &srcImage,
+ VkImageLayout srcImageLayout,
+ const Image &dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ VkImageBlit *pRegions,
+ VkFilter filter);
+ using WrappedObject::operator=;
+
+ VkResult begin(const VkCommandBufferBeginInfo &info);
+
+ VkResult end();
+ VkResult reset();
+
+ void pipelineBarrier(VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ VkDependencyFlags dependencyFlags,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier *memoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *bufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *imageMemoryBarriers);
+
+ void clearColorImage(const Image &image,
+ VkImageLayout imageLayout,
+ const VkClearColorValue &color,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange *ranges);
+ void clearDepthStencilImage(const Image &image,
+ VkImageLayout imageLayout,
+ const VkClearDepthStencilValue &depthStencil,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange *ranges);
+
+ void clearAttachments(uint32_t attachmentCount,
+ const VkClearAttachment *attachments,
+ uint32_t rectCount,
+ const VkClearRect *rects);
+
+ void copyBuffer(const Buffer &srcBuffer,
+ const Buffer &destBuffer,
+ uint32_t regionCount,
+ const VkBufferCopy *regions);
+
+ void copyBufferToImage(VkBuffer srcBuffer,
+ const Image &dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy *regions);
+ void copyImageToBuffer(const Image &srcImage,
+ VkImageLayout srcImageLayout,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferImageCopy *regions);
+ void copyImage(const Image &srcImage,
+ VkImageLayout srcImageLayout,
+ const Image &dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageCopy *regions);
+
+ void beginRenderPass(const VkRenderPassBeginInfo &beginInfo, VkSubpassContents subpassContents);
+ void endRenderPass();
+
+ void draw(uint32_t vertexCount,
+ uint32_t instanceCount,
+ uint32_t firstVertex,
+ uint32_t firstInstance);
+
+ void drawIndexed(uint32_t indexCount,
+ uint32_t instanceCount,
+ uint32_t firstIndex,
+ int32_t vertexOffset,
+ uint32_t firstInstance);
+
+ void dispatch(uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ);
+
+ void bindPipeline(VkPipelineBindPoint pipelineBindPoint, const Pipeline &pipeline);
+
+ void bindVertexBuffers(uint32_t firstBinding,
+ uint32_t bindingCount,
+ const VkBuffer *buffers,
+ const VkDeviceSize *offsets);
+
+ void bindIndexBuffer(const VkBuffer &buffer, VkDeviceSize offset, VkIndexType indexType);
+ void bindDescriptorSets(VkPipelineBindPoint bindPoint,
+ const PipelineLayout &layout,
+ uint32_t firstSet,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet *descriptorSets,
+ uint32_t dynamicOffsetCount,
+ const uint32_t *dynamicOffsets);
+
+ void executeCommands(uint32_t commandBufferCount, const CommandBuffer *commandBuffers);
+ void updateBuffer(const vk::Buffer &buffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize dataSize,
+ const void *data);
+ void pushConstants(const PipelineLayout &layout,
+ VkShaderStageFlags flag,
+ uint32_t offset,
+ uint32_t size,
+ const void *data);
+
+ void setEvent(VkEvent event, VkPipelineStageFlags stageMask);
+ void resetEvent(VkEvent event, VkPipelineStageFlags stageMask);
+ void waitEvents(uint32_t eventCount,
+ const VkEvent *events,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier *memoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *bufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *imageMemoryBarriers);
+
+ void resetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
+ void beginQuery(VkQueryPool queryPool, uint32_t query, VkQueryControlFlags flags);
+ void endQuery(VkQueryPool queryPool, uint32_t query);
+ void writeTimestamp(VkPipelineStageFlagBits pipelineStage,
+ VkQueryPool queryPool,
+ uint32_t query);
+
+ void setViewport(uint32_t firstViewport, uint32_t viewportCount, const VkViewport *viewports);
+ void setScissor(uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *scissors);
+};
+
+class Image final : public WrappedObject<Image, VkImage>
+{
+ public:
+ Image() = default;
+
+ // Use this method if the lifetime of the image is not controlled by ANGLE. (SwapChain)
+ void setHandle(VkImage handle);
+
+ // Called on shutdown when the helper class *doesn't* own the handle to the image resource.
+ void reset();
+
+ // Called on shutdown when the helper class *does* own the handle to the image resource.
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkImageCreateInfo &createInfo);
+
+ void getMemoryRequirements(VkDevice device, VkMemoryRequirements *requirementsOut) const;
+ VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
+
+ void getSubresourceLayout(VkDevice device,
+ VkImageAspectFlagBits aspectMask,
+ uint32_t mipLevel,
+ uint32_t arrayLayer,
+ VkSubresourceLayout *outSubresourceLayout) const;
+};
+
+class ImageView final : public WrappedObject<ImageView, VkImageView>
+{
+ public:
+ ImageView() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkImageViewCreateInfo &createInfo);
+};
+
+class Semaphore final : public WrappedObject<Semaphore, VkSemaphore>
+{
+ public:
+ Semaphore() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device);
+};
+
+class Framebuffer final : public WrappedObject<Framebuffer, VkFramebuffer>
+{
+ public:
+ Framebuffer() = default;
+ void destroy(VkDevice device);
+
+ // Use this method only in necessary cases. (RenderPass)
+ void setHandle(VkFramebuffer handle);
+
+ VkResult init(VkDevice device, const VkFramebufferCreateInfo &createInfo);
+};
+
+class DeviceMemory final : public WrappedObject<DeviceMemory, VkDeviceMemory>
+{
+ public:
+ DeviceMemory() = default;
+ void destroy(VkDevice device);
+
+ VkResult allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo);
+ VkResult map(VkDevice device,
+ VkDeviceSize offset,
+ VkDeviceSize size,
+ VkMemoryMapFlags flags,
+ uint8_t **mapPointer) const;
+ void unmap(VkDevice device) const;
+};
+
+class RenderPass final : public WrappedObject<RenderPass, VkRenderPass>
+{
+ public:
+ RenderPass() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkRenderPassCreateInfo &createInfo);
+};
+
+enum class StagingUsage
+{
+ Read,
+ Write,
+ Both,
+};
+
+class Buffer final : public WrappedObject<Buffer, VkBuffer>
+{
+ public:
+ Buffer() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkBufferCreateInfo &createInfo);
+ VkResult bindMemory(VkDevice device, const DeviceMemory &deviceMemory);
+ void getMemoryRequirements(VkDevice device, VkMemoryRequirements *memoryRequirementsOut);
+};
+
+class BufferView final : public WrappedObject<BufferView, VkBufferView>
+{
+ public:
+ BufferView() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkBufferViewCreateInfo &createInfo);
+};
+
+class ShaderModule final : public WrappedObject<ShaderModule, VkShaderModule>
+{
+ public:
+ ShaderModule() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkShaderModuleCreateInfo &createInfo);
+};
+
+class PipelineLayout final : public WrappedObject<PipelineLayout, VkPipelineLayout>
+{
+ public:
+ PipelineLayout() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkPipelineLayoutCreateInfo &createInfo);
+};
+
+class PipelineCache final : public WrappedObject<PipelineCache, VkPipelineCache>
+{
+ public:
+ PipelineCache() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkPipelineCacheCreateInfo &createInfo);
+ VkResult getCacheData(VkDevice device, size_t *cacheSize, void *cacheData);
+};
+
+class DescriptorSetLayout final : public WrappedObject<DescriptorSetLayout, VkDescriptorSetLayout>
+{
+ public:
+ DescriptorSetLayout() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkDescriptorSetLayoutCreateInfo &createInfo);
+};
+
+class DescriptorPool final : public WrappedObject<DescriptorPool, VkDescriptorPool>
+{
+ public:
+ DescriptorPool() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkDescriptorPoolCreateInfo &createInfo);
+
+ VkResult allocateDescriptorSets(VkDevice device,
+ const VkDescriptorSetAllocateInfo &allocInfo,
+ VkDescriptorSet *descriptorSetsOut);
+ VkResult freeDescriptorSets(VkDevice device,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet *descriptorSets);
+};
+
+class Sampler final : public WrappedObject<Sampler, VkSampler>
+{
+ public:
+ Sampler() = default;
+ void destroy(VkDevice device);
+ VkResult init(VkDevice device, const VkSamplerCreateInfo &createInfo);
+};
+
+class Event final : public WrappedObject<Event, VkEvent>
+{
+ public:
+ Event() = default;
+ void destroy(VkDevice device);
+ using WrappedObject::operator=;
+
+ VkResult init(VkDevice device, const VkEventCreateInfo &createInfo);
+ VkResult getStatus(VkDevice device) const;
+ VkResult set(VkDevice device) const;
+ VkResult reset(VkDevice device) const;
+};
+
+class Fence final : public WrappedObject<Fence, VkFence>
+{
+ public:
+ Fence() = default;
+ void destroy(VkDevice device);
+ using WrappedObject::operator=;
+
+ VkResult init(VkDevice device, const VkFenceCreateInfo &createInfo);
+ VkResult getStatus(VkDevice device) const;
+ VkResult wait(VkDevice device, uint64_t timeout) const;
+};
+
+class QueryPool final : public WrappedObject<QueryPool, VkQueryPool>
+{
+ public:
+ QueryPool() = default;
+ void destroy(VkDevice device);
+
+ VkResult init(VkDevice device, const VkQueryPoolCreateInfo &createInfo);
+ VkResult getResults(VkDevice device,
+ uint32_t firstQuery,
+ uint32_t queryCount,
+ size_t dataSize,
+ void *data,
+ VkDeviceSize stride,
+ VkQueryResultFlags flags) const;
+};
+
+// CommandPool implementation.
+ANGLE_INLINE void CommandPool::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyCommandPool(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult CommandPool::init(VkDevice device, const VkCommandPoolCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateCommandPool(device, &createInfo, nullptr, &mHandle);
+}
+
+// CommandBuffer implementation.
+ANGLE_INLINE VkCommandBuffer CommandBuffer::releaseHandle()
+{
+ VkCommandBuffer handle = mHandle;
+ mHandle = nullptr;
+ return handle;
+}
+
+ANGLE_INLINE VkResult CommandBuffer::init(VkDevice device,
+ const VkCommandBufferAllocateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkAllocateCommandBuffers(device, &createInfo, &mHandle);
+}
+
+ANGLE_INLINE void CommandBuffer::blitImage(const Image &srcImage,
+ VkImageLayout srcImageLayout,
+ const Image &dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ VkImageBlit *pRegions,
+ VkFilter filter)
+{
+ ASSERT(valid());
+ vkCmdBlitImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
+ dstImageLayout, regionCount, pRegions, filter);
+}
+
+ANGLE_INLINE VkResult CommandBuffer::begin(const VkCommandBufferBeginInfo &info)
+{
+ ASSERT(valid());
+ return vkBeginCommandBuffer(mHandle, &info);
+}
+
+ANGLE_INLINE VkResult CommandBuffer::end()
+{
+ ASSERT(valid());
+ return vkEndCommandBuffer(mHandle);
+}
+
+ANGLE_INLINE VkResult CommandBuffer::reset()
+{
+ ASSERT(valid());
+ return vkResetCommandBuffer(mHandle, 0);
+}
+
+ANGLE_INLINE void CommandBuffer::pipelineBarrier(VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ VkDependencyFlags dependencyFlags,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier *memoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *bufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *imageMemoryBarriers)
+{
+ ASSERT(valid());
+ vkCmdPipelineBarrier(mHandle, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount,
+ memoryBarriers, bufferMemoryBarrierCount, bufferMemoryBarriers,
+ imageMemoryBarrierCount, imageMemoryBarriers);
+}
+
+ANGLE_INLINE void CommandBuffer::destroy(VkDevice device)
+{
+ releaseHandle();
+}
+
+ANGLE_INLINE void CommandBuffer::destroy(VkDevice device, const vk::CommandPool &commandPool)
+{
+ if (valid())
+ {
+ ASSERT(commandPool.valid());
+ vkFreeCommandBuffers(device, commandPool.getHandle(), 1, &mHandle);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE void CommandBuffer::copyBuffer(const vk::Buffer &srcBuffer,
+ const vk::Buffer &destBuffer,
+ uint32_t regionCount,
+ const VkBufferCopy *regions)
+{
+ ASSERT(valid());
+ ASSERT(srcBuffer.valid() && destBuffer.valid());
+ vkCmdCopyBuffer(mHandle, srcBuffer.getHandle(), destBuffer.getHandle(), regionCount, regions);
+}
+
+ANGLE_INLINE void CommandBuffer::copyBufferToImage(VkBuffer srcBuffer,
+ const Image &dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkBufferImageCopy *regions)
+{
+ ASSERT(valid());
+ ASSERT(srcBuffer != VK_NULL_HANDLE);
+ ASSERT(dstImage.valid());
+ vkCmdCopyBufferToImage(mHandle, srcBuffer, dstImage.getHandle(), dstImageLayout, regionCount,
+ regions);
+}
+
+ANGLE_INLINE void CommandBuffer::copyImageToBuffer(const Image &srcImage,
+ VkImageLayout srcImageLayout,
+ VkBuffer dstBuffer,
+ uint32_t regionCount,
+ const VkBufferImageCopy *regions)
+{
+ ASSERT(valid());
+ ASSERT(dstBuffer != VK_NULL_HANDLE);
+ ASSERT(srcImage.valid());
+ vkCmdCopyImageToBuffer(mHandle, srcImage.getHandle(), srcImageLayout, dstBuffer, regionCount,
+ regions);
+}
+
+ANGLE_INLINE void CommandBuffer::clearColorImage(const vk::Image &image,
+ VkImageLayout imageLayout,
+ const VkClearColorValue &color,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange *ranges)
+{
+ ASSERT(valid());
+ vkCmdClearColorImage(mHandle, image.getHandle(), imageLayout, &color, rangeCount, ranges);
+}
+
+ANGLE_INLINE void CommandBuffer::clearDepthStencilImage(
+ const vk::Image &image,
+ VkImageLayout imageLayout,
+ const VkClearDepthStencilValue &depthStencil,
+ uint32_t rangeCount,
+ const VkImageSubresourceRange *ranges)
+{
+ ASSERT(valid());
+ vkCmdClearDepthStencilImage(mHandle, image.getHandle(), imageLayout, &depthStencil, rangeCount,
+ ranges);
+}
+
+ANGLE_INLINE void CommandBuffer::clearAttachments(uint32_t attachmentCount,
+ const VkClearAttachment *attachments,
+ uint32_t rectCount,
+ const VkClearRect *rects)
+{
+ ASSERT(valid());
+ vkCmdClearAttachments(mHandle, attachmentCount, attachments, rectCount, rects);
+}
+
+ANGLE_INLINE void CommandBuffer::copyImage(const vk::Image &srcImage,
+ VkImageLayout srcImageLayout,
+ const vk::Image &dstImage,
+ VkImageLayout dstImageLayout,
+ uint32_t regionCount,
+ const VkImageCopy *regions)
+{
+ ASSERT(valid() && srcImage.valid() && dstImage.valid());
+ vkCmdCopyImage(mHandle, srcImage.getHandle(), srcImageLayout, dstImage.getHandle(),
+ dstImageLayout, 1, regions);
+}
+
+ANGLE_INLINE void CommandBuffer::beginRenderPass(const VkRenderPassBeginInfo &beginInfo,
+ VkSubpassContents subpassContents)
+{
+ ASSERT(valid());
+ vkCmdBeginRenderPass(mHandle, &beginInfo, subpassContents);
+}
+
+ANGLE_INLINE void CommandBuffer::endRenderPass()
+{
+ ASSERT(mHandle != VK_NULL_HANDLE);
+ vkCmdEndRenderPass(mHandle);
+}
+
+ANGLE_INLINE void CommandBuffer::bindIndexBuffer(const VkBuffer &buffer,
+ VkDeviceSize offset,
+ VkIndexType indexType)
+{
+ ASSERT(valid());
+ vkCmdBindIndexBuffer(mHandle, buffer, offset, indexType);
+}
+
+ANGLE_INLINE void CommandBuffer::bindDescriptorSets(VkPipelineBindPoint bindPoint,
+ const vk::PipelineLayout &layout,
+ uint32_t firstSet,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet *descriptorSets,
+ uint32_t dynamicOffsetCount,
+ const uint32_t *dynamicOffsets)
+{
+ ASSERT(valid());
+ vkCmdBindDescriptorSets(mHandle, bindPoint, layout.getHandle(), firstSet, descriptorSetCount,
+ descriptorSets, dynamicOffsetCount, dynamicOffsets);
+}
+
+ANGLE_INLINE void CommandBuffer::executeCommands(uint32_t commandBufferCount,
+ const vk::CommandBuffer *commandBuffers)
+{
+ ASSERT(valid());
+ vkCmdExecuteCommands(mHandle, commandBufferCount, commandBuffers[0].ptr());
+}
+
+ANGLE_INLINE void CommandBuffer::updateBuffer(const vk::Buffer &buffer,
+ VkDeviceSize dstOffset,
+ VkDeviceSize dataSize,
+ const void *data)
+{
+ ASSERT(valid() && buffer.valid());
+ vkCmdUpdateBuffer(mHandle, buffer.getHandle(), dstOffset, dataSize, data);
+}
+
+ANGLE_INLINE void CommandBuffer::pushConstants(const PipelineLayout &layout,
+ VkShaderStageFlags flag,
+ uint32_t offset,
+ uint32_t size,
+ const void *data)
+{
+ ASSERT(valid() && layout.valid());
+ vkCmdPushConstants(mHandle, layout.getHandle(), flag, offset, size, data);
+}
+
+ANGLE_INLINE void CommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
+{
+ ASSERT(valid() && event != VK_NULL_HANDLE);
+ vkCmdSetEvent(mHandle, event, stageMask);
+}
+
+ANGLE_INLINE void CommandBuffer::resetEvent(VkEvent event, VkPipelineStageFlags stageMask)
+{
+ ASSERT(valid() && event != VK_NULL_HANDLE);
+ vkCmdResetEvent(mHandle, event, stageMask);
+}
+
+ANGLE_INLINE void CommandBuffer::waitEvents(uint32_t eventCount,
+ const VkEvent *events,
+ VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask,
+ uint32_t memoryBarrierCount,
+ const VkMemoryBarrier *memoryBarriers,
+ uint32_t bufferMemoryBarrierCount,
+ const VkBufferMemoryBarrier *bufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount,
+ const VkImageMemoryBarrier *imageMemoryBarriers)
+{
+ ASSERT(valid());
+ vkCmdWaitEvents(mHandle, eventCount, events, srcStageMask, dstStageMask, memoryBarrierCount,
+ memoryBarriers, bufferMemoryBarrierCount, bufferMemoryBarriers,
+ imageMemoryBarrierCount, imageMemoryBarriers);
+}
+
+ANGLE_INLINE void CommandBuffer::resetQueryPool(VkQueryPool queryPool,
+ uint32_t firstQuery,
+ uint32_t queryCount)
+{
+ ASSERT(valid());
+ vkCmdResetQueryPool(mHandle, queryPool, firstQuery, queryCount);
+}
+
+ANGLE_INLINE void CommandBuffer::beginQuery(VkQueryPool queryPool,
+ uint32_t query,
+ VkQueryControlFlags flags)
+{
+ ASSERT(valid());
+ vkCmdBeginQuery(mHandle, queryPool, query, flags);
+}
+
+ANGLE_INLINE void CommandBuffer::endQuery(VkQueryPool queryPool, uint32_t query)
+{
+ ASSERT(valid());
+ vkCmdEndQuery(mHandle, queryPool, query);
+}
+
+ANGLE_INLINE void CommandBuffer::writeTimestamp(VkPipelineStageFlagBits pipelineStage,
+ VkQueryPool queryPool,
+ uint32_t query)
+{
+ ASSERT(valid());
+ vkCmdWriteTimestamp(mHandle, pipelineStage, queryPool, query);
+}
+
+ANGLE_INLINE void CommandBuffer::setViewport(uint32_t firstViewport,
+ uint32_t viewportCount,
+ const VkViewport *viewports)
+{
+ ASSERT(valid());
+ vkCmdSetViewport(mHandle, firstViewport, viewportCount, viewports);
+}
+
+ANGLE_INLINE void CommandBuffer::setScissor(uint32_t firstScissor,
+ uint32_t scissorCount,
+ const VkRect2D *scissors)
+{
+ ASSERT(valid());
+ vkCmdSetScissor(mHandle, firstScissor, scissorCount, scissors);
+}
+
+ANGLE_INLINE void CommandBuffer::draw(uint32_t vertexCount,
+ uint32_t instanceCount,
+ uint32_t firstVertex,
+ uint32_t firstInstance)
+{
+ ASSERT(valid());
+ vkCmdDraw(mHandle, vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+ANGLE_INLINE void CommandBuffer::drawIndexed(uint32_t indexCount,
+ uint32_t instanceCount,
+ uint32_t firstIndex,
+ int32_t vertexOffset,
+ uint32_t firstInstance)
+{
+ ASSERT(valid());
+ vkCmdDrawIndexed(mHandle, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
+}
+
+ANGLE_INLINE void CommandBuffer::dispatch(uint32_t groupCountX,
+ uint32_t groupCountY,
+ uint32_t groupCountZ)
+{
+ ASSERT(valid());
+ vkCmdDispatch(mHandle, groupCountX, groupCountY, groupCountZ);
+}
+
+ANGLE_INLINE void CommandBuffer::bindPipeline(VkPipelineBindPoint pipelineBindPoint,
+ const Pipeline &pipeline)
+{
+ ASSERT(valid() && pipeline.valid());
+ vkCmdBindPipeline(mHandle, pipelineBindPoint, pipeline.getHandle());
+}
+
+ANGLE_INLINE void CommandBuffer::bindVertexBuffers(uint32_t firstBinding,
+ uint32_t bindingCount,
+ const VkBuffer *buffers,
+ const VkDeviceSize *offsets)
+{
+ ASSERT(valid());
+ vkCmdBindVertexBuffers(mHandle, firstBinding, bindingCount, buffers, offsets);
+}
+
+// Image implementation.
+ANGLE_INLINE void Image::setHandle(VkImage handle)
+{
+ mHandle = handle;
+}
+
+ANGLE_INLINE void Image::reset()
+{
+ mHandle = VK_NULL_HANDLE;
+}
+
+ANGLE_INLINE void Image::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyImage(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult Image::init(VkDevice device, const VkImageCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateImage(device, &createInfo, nullptr, &mHandle);
+}
+
+ANGLE_INLINE void Image::getMemoryRequirements(VkDevice device,
+ VkMemoryRequirements *requirementsOut) const
+{
+ ASSERT(valid());
+ vkGetImageMemoryRequirements(device, mHandle, requirementsOut);
+}
+
+ANGLE_INLINE VkResult Image::bindMemory(VkDevice device, const vk::DeviceMemory &deviceMemory)
+{
+ ASSERT(valid() && deviceMemory.valid());
+ return vkBindImageMemory(device, mHandle, deviceMemory.getHandle(), 0);
+}
+
+ANGLE_INLINE void Image::getSubresourceLayout(VkDevice device,
+ VkImageAspectFlagBits aspectMask,
+ uint32_t mipLevel,
+ uint32_t arrayLayer,
+ VkSubresourceLayout *outSubresourceLayout) const
+{
+ VkImageSubresource subresource = {};
+ subresource.aspectMask = aspectMask;
+ subresource.mipLevel = mipLevel;
+ subresource.arrayLayer = arrayLayer;
+
+ vkGetImageSubresourceLayout(device, getHandle(), &subresource, outSubresourceLayout);
+}
+
+// ImageView implementation.
+ANGLE_INLINE void ImageView::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyImageView(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult ImageView::init(VkDevice device, const VkImageViewCreateInfo &createInfo)
+{
+ return vkCreateImageView(device, &createInfo, nullptr, &mHandle);
+}
+
+// Semaphore implementation.
+ANGLE_INLINE void Semaphore::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroySemaphore(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult Semaphore::init(VkDevice device)
+{
+ ASSERT(!valid());
+
+ VkSemaphoreCreateInfo semaphoreInfo = {};
+ semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+ semaphoreInfo.flags = 0;
+
+ return vkCreateSemaphore(device, &semaphoreInfo, nullptr, &mHandle);
+}
+
+// Framebuffer implementation.
+ANGLE_INLINE void Framebuffer::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyFramebuffer(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult Framebuffer::init(VkDevice device, const VkFramebufferCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateFramebuffer(device, &createInfo, nullptr, &mHandle);
+}
+
+ANGLE_INLINE void Framebuffer::setHandle(VkFramebuffer handle)
+{
+ mHandle = handle;
+}
+
+// DeviceMemory implementation.
+ANGLE_INLINE void DeviceMemory::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkFreeMemory(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult DeviceMemory::allocate(VkDevice device, const VkMemoryAllocateInfo &allocInfo)
+{
+ ASSERT(!valid());
+ return vkAllocateMemory(device, &allocInfo, nullptr, &mHandle);
+}
+
+ANGLE_INLINE VkResult DeviceMemory::map(VkDevice device,
+ VkDeviceSize offset,
+ VkDeviceSize size,
+ VkMemoryMapFlags flags,
+ uint8_t **mapPointer) const
+{
+ ASSERT(valid());
+ return vkMapMemory(device, mHandle, offset, size, flags, reinterpret_cast<void **>(mapPointer));
+}
+
+ANGLE_INLINE void DeviceMemory::unmap(VkDevice device) const
+{
+ ASSERT(valid());
+ vkUnmapMemory(device, mHandle);
+}
+
+// RenderPass implementation.
+ANGLE_INLINE void RenderPass::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyRenderPass(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult RenderPass::init(VkDevice device, const VkRenderPassCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateRenderPass(device, &createInfo, nullptr, &mHandle);
+}
+
+// Buffer implementation.
+ANGLE_INLINE void Buffer::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyBuffer(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult Buffer::init(VkDevice device, const VkBufferCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateBuffer(device, &createInfo, nullptr, &mHandle);
+}
+
+ANGLE_INLINE VkResult Buffer::bindMemory(VkDevice device, const DeviceMemory &deviceMemory)
+{
+ ASSERT(valid() && deviceMemory.valid());
+ return vkBindBufferMemory(device, mHandle, deviceMemory.getHandle(), 0);
+}
+
+ANGLE_INLINE void Buffer::getMemoryRequirements(VkDevice device,
+ VkMemoryRequirements *memoryRequirementsOut)
+{
+ ASSERT(valid());
+ vkGetBufferMemoryRequirements(device, mHandle, memoryRequirementsOut);
+}
+
+// BufferView implementation.
+ANGLE_INLINE void BufferView::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyBufferView(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult BufferView::init(VkDevice device, const VkBufferViewCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateBufferView(device, &createInfo, nullptr, &mHandle);
+}
+
+// ShaderModule implementation.
+ANGLE_INLINE void ShaderModule::destroy(VkDevice device)
+{
+ if (mHandle != VK_NULL_HANDLE)
+ {
+ vkDestroyShaderModule(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult ShaderModule::init(VkDevice device,
+ const VkShaderModuleCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateShaderModule(device, &createInfo, nullptr, &mHandle);
+}
+
+// PipelineLayout implementation.
+ANGLE_INLINE void PipelineLayout::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyPipelineLayout(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult PipelineLayout::init(VkDevice device,
+ const VkPipelineLayoutCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreatePipelineLayout(device, &createInfo, nullptr, &mHandle);
+}
+
+// PipelineCache implementation.
+ANGLE_INLINE void PipelineCache::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyPipelineCache(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult PipelineCache::init(VkDevice device,
+ const VkPipelineCacheCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ // Note: if we are concerned with memory usage of this cache, we should give it custom
+ // allocators. Also, failure of this function is of little importance.
+ return vkCreatePipelineCache(device, &createInfo, nullptr, &mHandle);
+}
+
+ANGLE_INLINE VkResult PipelineCache::getCacheData(VkDevice device,
+ size_t *cacheSize,
+ void *cacheData)
+{
+ ASSERT(valid());
+
+ // Note: vkGetPipelineCacheData can return VK_INCOMPLETE if cacheSize is smaller than actual
+ // size. There are two usages of this function. One is with *cacheSize == 0 to query the size
+ // of the cache, and one is with an appropriate buffer to retrieve the cache contents.
+ // VK_INCOMPLETE in the first case is an expected output. In the second case, VK_INCOMPLETE is
+ // also acceptable and the resulting buffer will contain valid value by spec. Angle currently
+ // ensures *cacheSize to be either 0 or of enough size, therefore VK_INCOMPLETE is not expected.
+ return vkGetPipelineCacheData(device, mHandle, cacheSize, cacheData);
+}
+
+// Pipeline implementation.
+ANGLE_INLINE void Pipeline::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyPipeline(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult Pipeline::initGraphics(VkDevice device,
+ const VkGraphicsPipelineCreateInfo &createInfo,
+ const PipelineCache &pipelineCacheVk)
+{
+ ASSERT(!valid());
+ return vkCreateGraphicsPipelines(device, pipelineCacheVk.getHandle(), 1, &createInfo, nullptr,
+ &mHandle);
+}
+
+ANGLE_INLINE VkResult Pipeline::initCompute(VkDevice device,
+ const VkComputePipelineCreateInfo &createInfo,
+ const PipelineCache &pipelineCacheVk)
+{
+ ASSERT(!valid());
+ return vkCreateComputePipelines(device, pipelineCacheVk.getHandle(), 1, &createInfo, nullptr,
+ &mHandle);
+}
+
+// DescriptorSetLayout implementation.
+ANGLE_INLINE void DescriptorSetLayout::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyDescriptorSetLayout(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult DescriptorSetLayout::init(VkDevice device,
+ const VkDescriptorSetLayoutCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateDescriptorSetLayout(device, &createInfo, nullptr, &mHandle);
+}
+
+// DescriptorPool implementation.
+ANGLE_INLINE void DescriptorPool::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyDescriptorPool(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult DescriptorPool::init(VkDevice device,
+ const VkDescriptorPoolCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateDescriptorPool(device, &createInfo, nullptr, &mHandle);
+}
+
+ANGLE_INLINE VkResult
+DescriptorPool::allocateDescriptorSets(VkDevice device,
+ const VkDescriptorSetAllocateInfo &allocInfo,
+ VkDescriptorSet *descriptorSetsOut)
+{
+ ASSERT(valid());
+ return vkAllocateDescriptorSets(device, &allocInfo, descriptorSetsOut);
+}
+
+ANGLE_INLINE VkResult DescriptorPool::freeDescriptorSets(VkDevice device,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet *descriptorSets)
+{
+ ASSERT(valid());
+ ASSERT(descriptorSetCount > 0);
+ return vkFreeDescriptorSets(device, mHandle, descriptorSetCount, descriptorSets);
+}
+
+// Sampler implementation.
+ANGLE_INLINE void Sampler::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroySampler(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult Sampler::init(VkDevice device, const VkSamplerCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateSampler(device, &createInfo, nullptr, &mHandle);
+}
+
+// Event implementation.
+ANGLE_INLINE void Event::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyEvent(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult Event::init(VkDevice device, const VkEventCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateEvent(device, &createInfo, nullptr, &mHandle);
+}
+
+ANGLE_INLINE VkResult Event::getStatus(VkDevice device) const
+{
+ ASSERT(valid());
+ return vkGetEventStatus(device, mHandle);
+}
+
+ANGLE_INLINE VkResult Event::set(VkDevice device) const
+{
+ ASSERT(valid());
+ return vkSetEvent(device, mHandle);
+}
+
+ANGLE_INLINE VkResult Event::reset(VkDevice device) const
+{
+ ASSERT(valid());
+ return vkResetEvent(device, mHandle);
+}
+
+// Fence implementation.
+ANGLE_INLINE void Fence::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyFence(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult Fence::init(VkDevice device, const VkFenceCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateFence(device, &createInfo, nullptr, &mHandle);
+}
+
+ANGLE_INLINE VkResult Fence::getStatus(VkDevice device) const
+{
+ ASSERT(valid());
+ return vkGetFenceStatus(device, mHandle);
+}
+
+ANGLE_INLINE VkResult Fence::wait(VkDevice device, uint64_t timeout) const
+{
+ ASSERT(valid());
+ return vkWaitForFences(device, 1, &mHandle, true, timeout);
+}
+
+// QueryPool implementation.
+ANGLE_INLINE void QueryPool::destroy(VkDevice device)
+{
+ if (valid())
+ {
+ vkDestroyQueryPool(device, mHandle, nullptr);
+ mHandle = VK_NULL_HANDLE;
+ }
+}
+
+ANGLE_INLINE VkResult QueryPool::init(VkDevice device, const VkQueryPoolCreateInfo &createInfo)
+{
+ ASSERT(!valid());
+ return vkCreateQueryPool(device, &createInfo, nullptr, &mHandle);
+}
+
+ANGLE_INLINE VkResult QueryPool::getResults(VkDevice device,
+ uint32_t firstQuery,
+ uint32_t queryCount,
+ size_t dataSize,
+ void *data,
+ VkDeviceSize stride,
+ VkQueryResultFlags flags) const
+{
+ ASSERT(valid());
+ return vkGetQueryPoolResults(device, mHandle, firstQuery, queryCount, dataSize, data, stride,
+ flags);
+}
+} // namespace vk
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_VULKAN_VK_WRAPPER_H_
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp
index 046fd78a66f..2c3eaa1414c 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.cpp
@@ -47,7 +47,7 @@ bool DisplayVkWin32::checkConfigSupport(egl::Config *config)
return true;
}
-const char *DisplayVkWin32::getWSIName() const
+const char *DisplayVkWin32::getWSIExtension() const
{
return VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.h
index 53e0df51870..79addc1b71a 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/DisplayVkWin32.h
@@ -29,7 +29,7 @@ class DisplayVkWin32 : public DisplayVk
egl::ConfigSet generateConfigs() override;
bool checkConfigSupport(egl::Config *config) override;
- const char *getWSIName() const override;
+ const char *getWSIExtension() const override;
};
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp
index 0368c7e5110..2d7d164857b 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.cpp
@@ -32,6 +32,12 @@ angle::Result WindowSurfaceVkWin32::createSurfaceVk(vk::Context *context, gl::Ex
ANGLE_VK_TRY(context, vkCreateWin32SurfaceKHR(context->getRenderer()->getInstance(),
&createInfo, nullptr, &mSurface));
+ return getCurrentWindowSize(context, extentsOut);
+}
+
+angle::Result WindowSurfaceVkWin32::getCurrentWindowSize(vk::Context *context,
+ gl::Extents *extentsOut)
+{
RECT rect;
ANGLE_VK_CHECK(context, GetClientRect(mNativeWindowType, &rect) == TRUE,
VK_ERROR_INITIALIZATION_FAILED);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h
index 064ece4f83f..7e06271ca3d 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/win32/WindowSurfaceVkWin32.h
@@ -25,6 +25,7 @@ class WindowSurfaceVkWin32 : public WindowSurfaceVk
private:
angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override;
+ angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override;
};
} // namespace rx
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.cpp
index 9e050de4c99..64722151821 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.cpp
@@ -17,6 +17,28 @@
namespace rx
{
+namespace
+{
+EGLint GetXcbVisualType(xcb_screen_t *screen)
+{
+ // Visual type is the class member of xcb_visualtype_t whose id matches the root visual.
+ for (xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(screen);
+ depth_iter.rem; xcb_depth_next(&depth_iter))
+ {
+ for (xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
+ visual_iter.rem; xcb_visualtype_next(&visual_iter))
+ {
+ if (screen->root_visual == visual_iter.data->visual_id)
+ {
+ return visual_iter.data->_class;
+ }
+ }
+ }
+
+ return EGL_NONE;
+}
+} // namespace
+
DisplayVkXcb::DisplayVkXcb(const egl::DisplayState &state)
: DisplayVk(state), mXcbConnection(nullptr)
{}
@@ -72,11 +94,23 @@ egl::ConfigSet DisplayVkXcb::generateConfigs()
bool DisplayVkXcb::checkConfigSupport(egl::Config *config)
{
// TODO(geofflang): Test for native support and modify the config accordingly.
- // anglebug.com/2692
+ // http://anglebug.com/2692
+
+ // Find the screen the window was created on:
+ xcb_screen_iterator_t screenIterator = xcb_setup_roots_iterator(xcb_get_setup(mXcbConnection));
+ ASSERT(screenIterator.rem);
+
+ xcb_screen_t *screen = screenIterator.data;
+ ASSERT(screen);
+
+ // Visual id is root_visual of the screen
+ config->nativeVisualID = screen->root_visual;
+ config->nativeVisualType = GetXcbVisualType(screen);
+
return true;
}
-const char *DisplayVkXcb::getWSIName() const
+const char *DisplayVkXcb::getWSIExtension() const
{
return VK_KHR_XCB_SURFACE_EXTENSION_NAME;
}
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h
index b14ef6a840c..6636e23731f 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/DisplayVkXcb.h
@@ -35,7 +35,7 @@ class DisplayVkXcb : public DisplayVk
egl::ConfigSet generateConfigs() override;
bool checkConfigSupport(egl::Config *config) override;
- const char *getWSIName() const override;
+ const char *getWSIExtension() const override;
private:
xcb_connection_t *mXcbConnection;
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.cpp b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.cpp
index 33ebc8b3a05..c9a5545f2d1 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.cpp
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.cpp
@@ -33,6 +33,12 @@ angle::Result WindowSurfaceVkXcb::createSurfaceVk(vk::Context *context, gl::Exte
ANGLE_VK_TRY(context, vkCreateXcbSurfaceKHR(context->getRenderer()->getInstance(), &createInfo,
nullptr, &mSurface));
+ return getCurrentWindowSize(context, extentsOut);
+}
+
+angle::Result WindowSurfaceVkXcb::getCurrentWindowSize(vk::Context *context,
+ gl::Extents *extentsOut)
+{
xcb_get_geometry_cookie_t cookie = xcb_get_geometry(mXcbConnection, mNativeWindowType);
xcb_get_geometry_reply_t *reply = xcb_get_geometry_reply(mXcbConnection, cookie, nullptr);
ASSERT(reply);
diff --git a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h
index 68f2a635a2d..037c2a5c263 100644
--- a/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h
+++ b/chromium/third_party/angle/src/libANGLE/renderer/vulkan/xcb/WindowSurfaceVkXcb.h
@@ -28,6 +28,7 @@ class WindowSurfaceVkXcb : public WindowSurfaceVk
private:
angle::Result createSurfaceVk(vk::Context *context, gl::Extents *extentsOut) override;
+ angle::Result getCurrentWindowSize(vk::Context *context, gl::Extents *extentsOut) override;
xcb_connection_t *mXcbConnection;
};