diff --git a/impeller/fixtures/stroke.comp b/impeller/fixtures/stroke.comp index 5bb16d76a1731..57d9555546d29 100644 --- a/impeller/fixtures/stroke.comp +++ b/impeller/fixtures/stroke.comp @@ -17,6 +17,7 @@ layout(binding = 0) buffer Polyline { polyline; layout(binding = 1) buffer VertexBuffer { + uint count; vec2 position[]; } vertex_buffer; @@ -40,6 +41,8 @@ void main() { return; } + atomicAdd(vertex_buffer.count, 4); + vec2 offset = compute_offset(ident); uint index = ident - 1; vertex_buffer.position[index * 4 + 0] = polyline.data[ident - 1] + offset; diff --git a/impeller/renderer/backend/gles/context_gles.cc b/impeller/renderer/backend/gles/context_gles.cc index a9de32f2c3df3..85e1bd3ee8f78 100644 --- a/impeller/renderer/backend/gles/context_gles.cc +++ b/impeller/renderer/backend/gles/context_gles.cc @@ -81,6 +81,7 @@ ContextGLES::ContextGLES(std::unique_ptr gl, .SetSupportsFramebufferFetch(false) .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) .SetDefaultStencilFormat(PixelFormat::kS8UInt) + .SetSupportsCompute(false, false) .Build(); } diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index c9f0dd9c24216..70c76592aa5fa 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -90,6 +90,14 @@ #endif { + bool supports_subgroups = false; + // Refer to the "SIMD-scoped reduction operations" feature in the table + // below: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf + if (@available(ios 13.0, tvos 13.0, macos 10.15, *)) { + supports_subgroups = [device supportsFamily:MTLGPUFamilyApple7] || + [device supportsFamily:MTLGPUFamilyMac2]; + } + device_capabilities_ = DeviceCapabilitiesBuilder() .SetHasThreadingRestrictions(false) @@ -99,6 +107,7 @@ .SetSupportsFramebufferFetch(SupportsFramebufferFetch()) .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) .SetDefaultStencilFormat(PixelFormat::kS8UInt) + .SetSupportsCompute(true, supports_subgroups) .Build(); } diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index a71731d16627a..c1ac785848c6f 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -557,6 +557,8 @@ ContextVK::ContextVK( .SetSupportsFramebufferFetch(false) .SetDefaultColorFormat(PixelFormat::kB8G8R8A8UNormInt) .SetDefaultStencilFormat(PixelFormat::kS8UInt) + // TODO(110622): detect this and enable. + .SetSupportsCompute(false, false) .Build(); graphics_command_pool_ = std::move(graphics_command_pool.value); descriptor_pool_ = std::move(descriptor_pool.value); diff --git a/impeller/renderer/compute_subgroup_unittests.cc b/impeller/renderer/compute_subgroup_unittests.cc index ff4ea32a2bc3e..5ebcb339ce466 100644 --- a/impeller/renderer/compute_subgroup_unittests.cc +++ b/impeller/renderer/compute_subgroup_unittests.cc @@ -35,6 +35,7 @@ TEST_P(ComputeTest, HeartCubicsToStrokeVertices) { auto context = GetContext(); ASSERT_TRUE(context); + ASSERT_TRUE(context->GetDeviceCapabilities().SupportsComputeSubgroups()); auto cmd_buffer = context->CreateCommandBuffer(); auto pass = cmd_buffer->CreateComputePass(); @@ -182,6 +183,7 @@ TEST_P(ComputeTest, HeartCubicsToStrokeVertices) { auto* v = reinterpret_cast*>( vertex_buffer->AsBufferView().contents); + EXPECT_EQ(v->count, golden_heart_vertices.size()); for (size_t i = 0; i < golden_heart_vertices.size(); i += 1) { EXPECT_LT(std::abs(golden_heart_vertices[i].x - v->position[i].x), 1e-3); EXPECT_LT(std::abs(golden_heart_vertices[i].y - v->position[i].y), 1e-3); @@ -197,6 +199,7 @@ TEST_P(ComputeTest, QuadsToPolyline) { using QS = QuadPolylineComputeShader; auto context = GetContext(); ASSERT_TRUE(context); + ASSERT_TRUE(context->GetDeviceCapabilities().SupportsComputeSubgroups()); auto cmd_buffer = context->CreateCommandBuffer(); auto pass = cmd_buffer->CreateComputePass(); @@ -259,7 +262,6 @@ TEST_P(ComputeTest, QuadsToPolyline) { EXPECT_LT(std::abs(p->data[i].x - golden_heart_points[i].x), 1e-3); EXPECT_LT(std::abs(p->data[i].y - golden_heart_points[i].y), 1e-3); } - latch.Signal(); })); diff --git a/impeller/renderer/compute_unittests.cc b/impeller/renderer/compute_unittests.cc index ca8162d309293..cfa50e042d8e8 100644 --- a/impeller/renderer/compute_unittests.cc +++ b/impeller/renderer/compute_unittests.cc @@ -28,6 +28,8 @@ TEST_P(ComputeTest, CanCreateComputePass) { using CS = SampleComputeShader; auto context = GetContext(); ASSERT_TRUE(context); + ASSERT_TRUE(context->GetDeviceCapabilities().SupportsCompute()); + using SamplePipelineBuilder = ComputePipelineBuilder; auto pipeline_desc = SamplePipelineBuilder::MakeDefaultPipelineDescriptor(*context); @@ -114,6 +116,7 @@ TEST_P(ComputeTest, MultiStageInputAndOutput) { auto context = GetContext(); ASSERT_TRUE(context); + ASSERT_TRUE(context->GetDeviceCapabilities().SupportsCompute()); auto pipeline_desc_1 = Stage1PipelineBuilder::MakeDefaultPipelineDescriptor(*context); diff --git a/impeller/renderer/device_capabilities.cc b/impeller/renderer/device_capabilities.cc index 9bb9e3702d239..bf88bbc4c5f6b 100644 --- a/impeller/renderer/device_capabilities.cc +++ b/impeller/renderer/device_capabilities.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "impeller/renderer/device_capabilities.h" +#include "device_capabilities.h" namespace impeller { @@ -12,14 +13,18 @@ IDeviceCapabilities::IDeviceCapabilities(bool has_threading_restrictions, bool supports_texture_to_texture_blits, bool supports_framebuffer_fetch, PixelFormat default_color_format, - PixelFormat default_stencil_format) + PixelFormat default_stencil_format, + bool supports_compute, + bool supports_compute_subgroups) : has_threading_restrictions_(has_threading_restrictions), supports_offscreen_msaa_(supports_offscreen_msaa), supports_ssbo_(supports_ssbo), supports_texture_to_texture_blits_(supports_texture_to_texture_blits), supports_framebuffer_fetch_(supports_framebuffer_fetch), default_color_format_(default_color_format), - default_stencil_format_(default_stencil_format) {} + default_stencil_format_(default_stencil_format), + supports_compute_(supports_compute), + supports_compute_subgroups_(supports_compute_subgroups) {} IDeviceCapabilities::~IDeviceCapabilities() = default; @@ -51,6 +56,14 @@ PixelFormat IDeviceCapabilities::GetDefaultStencilFormat() const { return default_stencil_format_; } +bool IDeviceCapabilities::SupportsCompute() const { + return supports_compute_; +} + +bool IDeviceCapabilities::SupportsComputeSubgroups() const { + return supports_compute_subgroups_; +} + DeviceCapabilitiesBuilder::DeviceCapabilitiesBuilder() = default; DeviceCapabilitiesBuilder::~DeviceCapabilitiesBuilder() = default; @@ -97,6 +110,14 @@ DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetDefaultStencilFormat( return *this; } +DeviceCapabilitiesBuilder& DeviceCapabilitiesBuilder::SetSupportsCompute( + bool value, + bool subgroups) { + supports_compute_ = value; + supports_compute_subgroups_ = subgroups; + return *this; +} + std::unique_ptr DeviceCapabilitiesBuilder::Build() { FML_CHECK(default_color_format_.has_value()) << "Default color format not set"; @@ -110,7 +131,9 @@ std::unique_ptr DeviceCapabilitiesBuilder::Build() { supports_texture_to_texture_blits_, // supports_framebuffer_fetch_, // *default_color_format_, // - *default_stencil_format_ // + *default_stencil_format_, // + supports_compute_, // + supports_compute_subgroups_ // ); return std::unique_ptr(capabilities); } diff --git a/impeller/renderer/device_capabilities.h b/impeller/renderer/device_capabilities.h index 697b8f5d531a0..f74d95c27f494 100644 --- a/impeller/renderer/device_capabilities.h +++ b/impeller/renderer/device_capabilities.h @@ -29,6 +29,9 @@ class IDeviceCapabilities { PixelFormat GetDefaultStencilFormat() const; + bool SupportsCompute() const; + bool SupportsComputeSubgroups() const; + private: IDeviceCapabilities(bool has_threading_restrictions, bool supports_offscreen_msaa, @@ -36,7 +39,9 @@ class IDeviceCapabilities { bool supports_texture_to_texture_blits, bool supports_framebuffer_fetch, PixelFormat default_color_format, - PixelFormat default_stencil_format); + PixelFormat default_stencil_format, + bool supports_compute, + bool supports_compute_subgroups); friend class DeviceCapabilitiesBuilder; @@ -47,6 +52,8 @@ class IDeviceCapabilities { bool supports_framebuffer_fetch_ = false; PixelFormat default_color_format_; PixelFormat default_stencil_format_; + bool supports_compute_ = false; + bool supports_compute_subgroups_ = false; FML_DISALLOW_COPY_AND_ASSIGN(IDeviceCapabilities); }; @@ -71,6 +78,8 @@ class DeviceCapabilitiesBuilder { DeviceCapabilitiesBuilder& SetDefaultStencilFormat(PixelFormat value); + DeviceCapabilitiesBuilder& SetSupportsCompute(bool value, bool subgroups); + std::unique_ptr Build(); private: @@ -79,6 +88,8 @@ class DeviceCapabilitiesBuilder { bool supports_ssbo_ = false; bool supports_texture_to_texture_blits_ = false; bool supports_framebuffer_fetch_ = false; + bool supports_compute_ = false; + bool supports_compute_subgroups_ = false; std::optional default_color_format_ = std::nullopt; std::optional default_stencil_format_ = std::nullopt;