From d6e75cf95cebe4e7c6ff18542894f2ec76051fca Mon Sep 17 00:00:00 2001 From: Chris Dalton Date: Thu, 16 Jul 2026 17:53:26 -0600 Subject: [PATCH] wagyublend --- .../webgpu/render_context_webgpu_impl.hpp | 2 + renderer/src/render_context.cpp | 5 + .../src/webgpu/render_context_webgpu_impl.cpp | 125 +++++++++++++++--- .../wagyu-port/include/webgpu/webgpu_wagyu.h | 63 ++++++--- .../common/offscreen_render_target_webgpu.cpp | 1 + tests/common/testing_window_wgpu.cpp | 43 +++++- 6 files changed, 200 insertions(+), 39 deletions(-) diff --git a/renderer/include/rive/renderer/webgpu/render_context_webgpu_impl.hpp b/renderer/include/rive/renderer/webgpu/render_context_webgpu_impl.hpp index b9cb68e90..94a0ce86f 100644 --- a/renderer/include/rive/renderer/webgpu/render_context_webgpu_impl.hpp +++ b/renderer/include/rive/renderer/webgpu/render_context_webgpu_impl.hpp @@ -274,6 +274,7 @@ class RenderTargetWebGPU : public RenderTarget protected: RenderTargetWebGPU(wgpu::Device device, + const gpu::PlatformFeatures&, const RenderContextWebGPUImpl::Capabilities&, wgpu::TextureFormat framebufferFormat, uint32_t width, @@ -299,6 +300,7 @@ class RenderTargetWebGPU : public RenderTarget const wgpu::Device m_device; const wgpu::TextureFormat m_framebufferFormat; wgpu::TextureUsage m_transientPLSUsage; + wgpu::TextureUsage m_transientMSAAUsage; wgpu::Texture m_targetTexture; wgpu::Texture m_coverageTexture; diff --git a/renderer/src/render_context.cpp b/renderer/src/render_context.cpp index f5eeca0f7..0c2013e07 100644 --- a/renderer/src/render_context.cpp +++ b/renderer/src/render_context.cpp @@ -136,6 +136,11 @@ RenderContext::RenderContext(std::unique_ptr impl) : // directly by pathID. m_maxPathID(MaxPathID(m_impl->platformFeatures().pathIDGranularity) - 1) { + // Validate platformFeatures: if supportsBlendAdvancedCoherentKHR is set, + // supportsBlendAdvancedKHR must also be. + assert(!m_impl->platformFeatures().supportsBlendAdvancedCoherentKHR || + m_impl->platformFeatures().supportsBlendAdvancedKHR); + #ifdef RIVE_GENERATE_FEATHER_LUT float table[GAUSSIAN_TABLE_SIZE]; generate_gausian_integral_table(table); diff --git a/renderer/src/webgpu/render_context_webgpu_impl.cpp b/renderer/src/webgpu/render_context_webgpu_impl.cpp index 881c43327..ed18b1f54 100644 --- a/renderer/src/webgpu/render_context_webgpu_impl.cpp +++ b/renderer/src/webgpu/render_context_webgpu_impl.cpp @@ -112,17 +112,6 @@ constexpr static auto RIVE_FRONT_FACE = wgpu::FrontFace::CW; constexpr static uint32_t MSAA_SAMPLE_COUNT = 4u; -constexpr static WGPUBlendComponent BLEND_COMPONENT_SRC_OVER = { - .operation = WGPUBlendOperation_Add, - .srcFactor = WGPUBlendFactor_One, - .dstFactor = WGPUBlendFactor_OneMinusSrcAlpha, -}; - -constexpr static WGPUBlendState BLEND_STATE_SRC_OVER = { - .color = BLEND_COMPONENT_SRC_OVER, - .alpha = BLEND_COMPONENT_SRC_OVER, -}; - constexpr static WGPUStencilFaceState STENCIL_FACE_STATE_DISABLED = { .compare = WGPUCompareFunction_Always, .failOp = WGPUStencilOperation_Keep, @@ -795,7 +784,7 @@ class RenderContextWebGPUImpl::ColorRampPipeline wgpu::ShaderModule vertexShaderModule, fragmentShaderModule; #ifdef RIVE_WAGYU - if (impl->m_capabilities.backendType == wgpu::BackendType::OpenGLES) + if (false) { // Rive shaders tend to be long and prone to vendor bugs in the // compiler. Instead of wgsl, send down the raw Rive GLSL sources, @@ -932,7 +921,7 @@ class RenderContextWebGPUImpl::TessellatePipeline wgpu::ShaderModule vertexShaderModule, fragmentShaderModule; #ifdef RIVE_WAGYU - if (impl->m_capabilities.backendType == wgpu::BackendType::OpenGLES) + if (false) { // Rive shaders tend to be long and prone to vendor bugs in the // compiler. Instead of wgsl, send down the raw Rive GLSL sources, @@ -1095,7 +1084,7 @@ class RenderContextWebGPUImpl::AtlasPipeline wgpu::ShaderModule vertexShaderModule; wgpu::ShaderModule fillFragmentShaderModule, strokeFragmentShaderModule; #ifdef RIVE_WAGYU - if (impl->m_capabilities.backendType == wgpu::BackendType::OpenGLES) + if (false) { // Rive shaders tend to be long and prone to vendor bugs in the // compiler. Instead of wgsl, send down the raw Rive GLSL sources, @@ -1878,6 +1867,15 @@ RenderContextWebGPUImpl::RenderContextWebGPUImpl( } m_platformFeatures.atomicPLSInitNeedsDraw = true; +#ifdef RIVE_WAGYU + // We can only use advanced blend if the client enabled it when setting up + // the device. + m_platformFeatures.supportsBlendAdvancedKHR = + m_platformFeatures.supportsBlendAdvancedCoherentKHR = + m_device.HasFeature(static_cast( + WGPUFeatureName_WagyuBlendEquationAdvancedCoherent)); +#endif + m_platformFeatures.clipSpaceBottomUp = true; m_platformFeatures.framebufferBottomUp = false; m_platformFeatures.msaaColorPreserveNeedsDraw = true; @@ -2092,6 +2090,7 @@ RenderContextWebGPUImpl::~RenderContextWebGPUImpl() {} RenderTargetWebGPU::RenderTargetWebGPU( wgpu::Device device, + const gpu::PlatformFeatures& platformFeatures, const RenderContextWebGPUImpl::Capabilities& capabilities, wgpu::TextureFormat framebufferFormat, uint32_t width, @@ -2100,6 +2099,7 @@ RenderTargetWebGPU::RenderTargetWebGPU( m_device(std::move(device)), m_framebufferFormat(framebufferFormat), m_transientPLSUsage(wgpu::TextureUsage::RenderAttachment), + m_transientMSAAUsage(wgpu::TextureUsage::RenderAttachment), m_targetTextureView{} // Will be configured later by setTargetTexture(). { #ifdef RIVE_WAGYU @@ -2111,6 +2111,16 @@ RenderTargetWebGPU::RenderTargetWebGPU( WGPUTextureUsage_WagyuInputAttachment | WGPUTextureUsage_WagyuTransientAttachment); } + // if (platformFeatures.supportsBlendAdvancedKHR) + // { + // // Since we support advanced blend, we don't need to interrupt MSAA + // // render passes to read the framebuffer, so the MSAA buffer can be + // // transient. + // // IS THIS WHERE I USE WGPUTextureUsage_WagyuMSAAResolveSource TOO?? + // m_transientMSAAUsage |= static_cast( + // WGPUTextureUsage_WagyuTransientAttachment | + // WGPUTextureUsage_WagyuMSAAResolveSource); + // } #endif } @@ -2174,7 +2184,7 @@ wgpu::TextureView RenderTargetWebGPU::msaaColorTextureView() if (m_msaaColorTexture == nullptr) { wgpu::TextureDescriptor desc = { - .usage = wgpu::TextureUsage::RenderAttachment, + .usage = m_transientMSAAUsage, .size = {static_cast(width()), static_cast(height())}, .format = m_framebufferFormat, @@ -2259,6 +2269,7 @@ rcp RenderContextWebGPUImpl::makeRenderTarget( uint32_t height) { return rcp(new RenderTargetWebGPU(m_device, + m_platformFeatures, m_capabilities, framebufferFormat, width, @@ -2992,6 +3003,71 @@ static void appendImageDrawInstanceAttribs( }); } +static WGPUBlendOperation wgpuBlendOp(gpu::BlendEquation blendEquation) +{ + switch (blendEquation) + { + case gpu::BlendEquation::none: + case gpu::BlendEquation::srcOver: + case gpu::BlendEquation::plus: + return WGPUBlendOperation_Add; + case gpu::BlendEquation::min: + return WGPUBlendOperation_Min; + case gpu::BlendEquation::max: + return WGPUBlendOperation_Max; +#ifdef RIVE_WAGYU + case gpu::BlendEquation::multiply: + return WGPUBlendOperation_WagyuMultiply; + case gpu::BlendEquation::screen: + return WGPUBlendOperation_WagyuScreen; + case gpu::BlendEquation::overlay: + return WGPUBlendOperation_WagyuOverlay; + case gpu::BlendEquation::darken: + return WGPUBlendOperation_WagyuDarken; + case gpu::BlendEquation::lighten: + return WGPUBlendOperation_WagyuLighten; + case gpu::BlendEquation::colorDodge: + return WGPUBlendOperation_WagyuColorDodge; + case gpu::BlendEquation::colorBurn: + return WGPUBlendOperation_WagyuColorBurn; + case gpu::BlendEquation::hardLight: + return WGPUBlendOperation_WagyuHardLight; + case gpu::BlendEquation::softLight: + return WGPUBlendOperation_WagyuSoftLight; + case gpu::BlendEquation::difference: + return WGPUBlendOperation_WagyuDifference; + case gpu::BlendEquation::exclusion: + return WGPUBlendOperation_WagyuExclusion; + case gpu::BlendEquation::hue: + return WGPUBlendOperation_WagyuHue; + case gpu::BlendEquation::saturation: + return WGPUBlendOperation_WagyuSaturation; + case gpu::BlendEquation::color: + return WGPUBlendOperation_WagyuColor; + case gpu::BlendEquation::luminosity: + return WGPUBlendOperation_WagyuLuminosity; +#else + case gpu::BlendEquation::multiply: + case gpu::BlendEquation::screen: + case gpu::BlendEquation::overlay: + case gpu::BlendEquation::darken: + case gpu::BlendEquation::lighten: + case gpu::BlendEquation::colorDodge: + case gpu::BlendEquation::colorBurn: + case gpu::BlendEquation::hardLight: + case gpu::BlendEquation::softLight: + case gpu::BlendEquation::difference: + case gpu::BlendEquation::exclusion: + case gpu::BlendEquation::hue: + case gpu::BlendEquation::saturation: + case gpu::BlendEquation::color: + case gpu::BlendEquation::luminosity: + RIVE_UNREACHABLE(); +#endif + } + RIVE_UNREACHABLE(); +} + wgpu::RenderPipeline RenderContextWebGPUImpl::makeDrawPipeline( gpu::DrawType drawType, gpu::ShaderFeatures shaderFeatures, @@ -3148,17 +3224,26 @@ wgpu::RenderPipeline RenderContextWebGPUImpl::makeDrawPipeline( } #endif + const WGPUBlendComponent blendComponent = { + .operation = wgpuBlendOp(pipelineState.blendEquation), + .srcFactor = WGPUBlendFactor_One, + .dstFactor = WGPUBlendFactor_OneMinusSrcAlpha, + }; + + const WGPUBlendState blendState = { + .color = blendComponent, + .alpha = blendComponent, + }; + StackVector colorAttachments; assert(colorAttachments.size() == COLOR_PLANE_IDX); - assert(pipelineState.blendEquation == gpu::BlendEquation::none || - pipelineState.blendEquation == gpu::BlendEquation::srcOver); colorAttachments.push_back({ .nextInChain = extraColorTargetState, .format = static_cast(framebufferFormat), - .blend = (pipelineState.blendEquation == gpu::BlendEquation::srcOver) - ? &BLEND_STATE_SRC_OVER - : nullptr, + .blend = (pipelineState.blendEquation == gpu::BlendEquation::none) + ? nullptr + : &blendState, .writeMask = pipelineState.colorWriteEnabled ? WGPUColorWriteMask_All : WGPUColorWriteMask_None, }); diff --git a/renderer/src/webgpu/wagyu-port/include/webgpu/webgpu_wagyu.h b/renderer/src/webgpu/wagyu-port/include/webgpu/webgpu_wagyu.h index c3e559742..9caaf9367 100644 --- a/renderer/src/webgpu/wagyu-port/include/webgpu/webgpu_wagyu.h +++ b/renderer/src/webgpu/wagyu-port/include/webgpu/webgpu_wagyu.h @@ -22,21 +22,22 @@ typedef struct WGPUWagyuExternalTextureImpl *WGPUWagyuExternalTexture WGPU_OBJEC // These values extend the WGPUSType enum set from webgpu.h typedef enum WGPUSType_Wagyu { - WGPUSType_WagyuAdapterInfo = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0001, - WGPUSType_WagyuColorTargetState = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0002, - WGPUSType_WagyuCommandEncoderDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0003, - WGPUSType_WagyuComputePipelineDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0004, - WGPUSType_WagyuDeviceDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0005, - WGPUSType_WagyuExternalTextureBindingEntry = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0006, - WGPUSType_WagyuExternalTextureBindingLayout = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0007, - WGPUSType_WagyuFragmentState = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0008, - WGPUSType_WagyuInputTextureBindingLayout = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0009, - WGPUSType_WagyuRenderPassDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000A, - WGPUSType_WagyuRenderPipelineDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000B, - WGPUSType_WagyuShaderModuleDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000C, - WGPUSType_WagyuSurfaceConfiguration = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000D, - WGPUSType_WagyuTextureDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000E, - WGPUSType_WagyuForce32 = 0x7FFFFFFF + WGPUSType_WagyuAdapterInfo = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0001, + WGPUSType_WagyuColorTargetState = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0002, + WGPUSType_WagyuCommandEncoderDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0003, + WGPUSType_WagyuComputePipelineDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0004, + WGPUSType_WagyuDeviceDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0005, + WGPUSType_WagyuExternalTextureBindingEntry = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0006, + WGPUSType_WagyuExternalTextureBindingLayout = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0007, + WGPUSType_WagyuFragmentState = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0008, + WGPUSType_WagyuInputTextureBindingLayout = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0009, + WGPUSType_WagyuRenderPassDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000A, + WGPUSType_WagyuRenderPipelineDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000B, + WGPUSType_WagyuShaderModuleDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000C, + WGPUSType_WagyuSurfaceConfiguration = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000D, + WGPUSType_WagyuTextureDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000E, + WGPUSType_WagyuDeviceWantsValidationDescriptor = WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000F, + WGPUSType_WagyuForce32 = 0x7FFFFFFF } WGPUSType_Wagyu WGPU_ENUM_ATTRIBUTE; typedef enum WGPUWagyuDeviceFlushStatus @@ -65,6 +66,28 @@ typedef enum WGPUWagyuShaderLanguage WGPUWagyuShaderLanguage_Force32 = 0x7FFFFFFF } WGPUWagyuShaderLanguage WGPU_ENUM_ATTRIBUTE; +// Wagyu-namespaced values extending upstream enums. Allocated from the reserved +// range so they do not collide with future upstream additions. +static const WGPUFeatureName WGPUFeatureName_WagyuBlendEquationAdvancedCoherent = (WGPUFeatureName)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0001); + +// Advanced blend equations (set as the WGPUBlendComponent.operation; the factors +// are ignored). Requires the WagyuBlendEquationAdvancedCoherent feature. +static const WGPUBlendOperation WGPUBlendOperation_WagyuMultiply = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0001); +static const WGPUBlendOperation WGPUBlendOperation_WagyuScreen = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0002); +static const WGPUBlendOperation WGPUBlendOperation_WagyuOverlay = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0003); +static const WGPUBlendOperation WGPUBlendOperation_WagyuDarken = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0004); +static const WGPUBlendOperation WGPUBlendOperation_WagyuLighten = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0005); +static const WGPUBlendOperation WGPUBlendOperation_WagyuColorDodge = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0006); +static const WGPUBlendOperation WGPUBlendOperation_WagyuColorBurn = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0007); +static const WGPUBlendOperation WGPUBlendOperation_WagyuHardLight = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0008); +static const WGPUBlendOperation WGPUBlendOperation_WagyuSoftLight = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x0009); +static const WGPUBlendOperation WGPUBlendOperation_WagyuDifference = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000A); +static const WGPUBlendOperation WGPUBlendOperation_WagyuExclusion = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000B); +static const WGPUBlendOperation WGPUBlendOperation_WagyuHue = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000C); +static const WGPUBlendOperation WGPUBlendOperation_WagyuSaturation = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000D); +static const WGPUBlendOperation WGPUBlendOperation_WagyuColor = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000E); +static const WGPUBlendOperation WGPUBlendOperation_WagyuLuminosity = (WGPUBlendOperation)(WGPU_WAGYU_RESERVED_RANGE_BASE + 0x000F); + typedef enum WGPUWagyuWGSLFeatureType { WGPUWagyuWGSLFeatureType_Testing = 0x00000001, @@ -81,6 +104,7 @@ static const WGPUWagyuFragmentStateFeaturesFlags WGPUWagyuFragmentStateFeaturesF // These values extend the WGPUTextureUsage enum set from webgpu.h static const WGPUTextureUsage WGPUTextureUsage_WagyuInputAttachment = (WGPUTextureUsage)(0x0000000040000000); static const WGPUTextureUsage WGPUTextureUsage_WagyuTransientAttachment = (WGPUTextureUsage)(0x0000000020000000); +static const WGPUTextureUsage WGPUTextureUsage_WagyuMSAAResolveSource = (WGPUTextureUsage)(0x0000000080000000); // Forward declarations for callbacks struct WGPUWagyuDevicePipelineBinaryCacheStatistics; @@ -187,6 +211,15 @@ typedef struct WGPUWagyuDeviceDescriptor #define WGPU_WAGYU_DEVICE_DESCRIPTOR_INIT \ WGPU_WAGYU_MAKE_INIT_STRUCT(WGPUWagyuDeviceDescriptor, { /*.chain*/ WGPU_WAGYU_CHAIN_INIT(WGPUSType_WagyuDeviceDescriptor) _wgpu_COMMA /*.dataBufferNeedsDetach*/ WGPUOptionalBool_Undefined _wgpu_COMMA /*.wantsIndirectRendering*/ WGPUOptionalBool_Undefined _wgpu_COMMA /*.wantsBufferClear*/ WGPUOptionalBool_Undefined _wgpu_COMMA /*.wantsTextureClear*/ WGPUOptionalBool_Undefined _wgpu_COMMA }) +typedef struct WGPUWagyuDeviceWantsValidationDescriptor +{ + WGPUChainedStruct chain; + WGPUOptionalBool wantsValidation; +} WGPUWagyuDeviceWantsValidationDescriptor WGPU_STRUCTURE_ATTRIBUTE; + +#define WGPU_WAGYU_DEVICE_VALIDATION_INIT \ + WGPU_WAGYU_MAKE_INIT_STRUCT(WGPUWagyuDeviceWantsValidationDescriptor, { /*.chain*/ WGPU_WAGYU_CHAIN_INIT(WGPUSType_WagyuDeviceWantsValidationDescriptor) _wgpu_COMMA /*.wantsValidation*/ WGPUOptionalBool_Undefined _wgpu_COMMA }) + typedef struct WGPUWagyuDeviceFlushCallbackInfo { WGPUChainedStruct *nextInChain; diff --git a/tests/common/offscreen_render_target_webgpu.cpp b/tests/common/offscreen_render_target_webgpu.cpp index 264339373..8204a7d95 100644 --- a/tests/common/offscreen_render_target_webgpu.cpp +++ b/tests/common/offscreen_render_target_webgpu.cpp @@ -58,6 +58,7 @@ class OffscreenRenderTargetWebGPU : public rive_tests::OffscreenRenderTarget uint32_t width, uint32_t height) : RenderTargetWebGPU(impl->device(), + impl->platformFeatures(), impl->capabilities(), format, width, diff --git a/tests/common/testing_window_wgpu.cpp b/tests/common/testing_window_wgpu.cpp index de43c9ffc..feefd8edb 100644 --- a/tests/common/testing_window_wgpu.cpp +++ b/tests/common/testing_window_wgpu.cpp @@ -12,7 +12,6 @@ TestingWindow* TestingWindow::MakeWGPU(const BackendParams&) { return nullptr; } #include "common/offscreen_render_target.hpp" #include "rive/renderer/rive_renderer.hpp" -#include "rive/renderer/rive_render_image.hpp" #include "rive/renderer/webgpu/render_context_webgpu_impl.hpp" #include @@ -146,6 +145,22 @@ class TestingWindowWGPU : public TestingWindow } #endif + std::vector requiredFeatures; +#ifdef RIVE_WAGYU + // Request coherent advanced blend when the adapter advertises it. This + // enables Rive to take the "supportsBlendAdvancedCoherentKHR" path on + // MSAA, and skip the framebuffer copies and renderPass interruptions + // for advanced blend. + if (m_adapter.HasFeature(static_cast( + WGPUFeatureName_WagyuBlendEquationAdvancedCoherent))) + { + requiredFeatures.push_back(static_cast( + WGPUFeatureName_WagyuBlendEquationAdvancedCoherent)); + } +#endif + deviceDesc.requiredFeatureCount = requiredFeatures.size(); + deviceDesc.requiredFeatures = requiredFeatures.data(); + m_adapter.RequestDevice( &deviceDesc, wgpu::CallbackMode::AllowSpontaneous, @@ -226,12 +241,32 @@ class TestingWindowWGPU : public TestingWindow wgpu::AdapterInfo adapterInfo; m_adapter.GetInfo(&adapterInfo); - printf("==== WGPU device: %s %s %s (%s, %s) ====\n", + printf("==== WGPU device: %s %s %s (%s", adapterInfo.vendor.data, adapterInfo.device.data, adapterInfo.description.data, - wgpu_backend_name(impl()->capabilities().backendType), - pls_impl_name(impl()->capabilities())); + wgpu_backend_name(impl()->capabilities().backendType)); +#ifdef RIVE_WAGYU + switch (impl()->capabilities().plsType) + { + case RenderContextWebGPUImpl::PixelLocalStorageType:: + GL_EXT_shader_pixel_local_storage: + printf(", GL_EXT_shader_pixel_local_storage"); + break; + case RenderContextWebGPUImpl::PixelLocalStorageType:: + VK_EXT_rasterization_order_attachment_access: + printf(", VK_EXT_rasterization_order_attachment_access"); + break; + case RenderContextWebGPUImpl::PixelLocalStorageType::none: + break; + } +#endif + if (m_renderContext->platformFeatures() + .supportsBlendAdvancedCoherentKHR) + { + printf(", WagyuBlendEquationAdvancedCoherent"); + } + printf(") ====\n"); } rive::Factory* factory() override { return m_renderContext.get(); }