diff --git a/.rive_head b/.rive_head index 7c235e94..da0fd667 100644 --- a/.rive_head +++ b/.rive_head @@ -1 +1 @@ -1b51fe394e81445b8e6c990780ed104ee582fde4 +d8d42c0f130ec1f7d70a9e4ca3cffb1f6e3b9860 diff --git a/renderer/include/rive/renderer/gpu.hpp b/renderer/include/rive/renderer/gpu.hpp index 9004dcf4..9316ae07 100644 --- a/renderer/include/rive/renderer/gpu.hpp +++ b/renderer/include/rive/renderer/gpu.hpp @@ -109,15 +109,58 @@ struct PlatformFeatures // Required for @ENABLE_CLIP_RECT in msaa mode. bool supportsClipPlanes = false; bool avoidFlatVaryings = false; - // Invert Y when drawing to offscreen render targets? (Gradient and - // tessellation textures.) - bool invertOffscreenY = false; - // Specifies whether the graphics layer appends a negation of Y to on-screen - // vertex shaders that needs to be undone. - bool uninvertOnScreenY = false; - // Does the built-in pixel coordinate in the fragment shader go bottom-up or - // top-down? - bool fragCoordBottomUp = false; + // clipSpaceBottomUp specifies whether the top of the viewport, in clip + // coordinates, is at Y=+1 (OpenGL, Metal, D3D, WebGPU) or Y=-1 (Vulkan). + // + // framebufferBottomUp specifies whether "row 0" of the framebuffer is the + // bottom of the image (OpenGL) or the top (Metal, D3D, WebGPU, Vulkan). + // + // + // OpenGL + // (clipSpaceBottomUp=true, framebufferBottomUp=true) + // + // Rive Pixel Space Clip Space Framebuffer + // + // 0 -----------> ^ +1 ^ height + // | width | | + // | -1 | +1 | + // | ===> <------|------> ===> | + // | | | + // | | | width + // v height v -1 0 -----------> + // + // + // + // Metal/D3D/WebGPU + // (clipSpaceBottomUp=true, framebufferBottomUp=false) + // + // Rive Pixel Space Clip Space Framebuffer + // + // 0 -----------> ^ +1 0 -----------> + // | width | | width + // | -1 | +1 | + // | ===> <------|------> ===> | + // | | | + // | | | + // v height v -1 v height + // + // + // + // Vulkan + // (clipSpaceBottomUp=false, framebufferBottomUp=false) + // + // Rive Pixel Space Clip Space Framebuffer + // + // 0 -----------> ^ -1 0 -----------> + // | width | | width + // | -1 | +1 | + // | ===> <------|------> ===> | + // | | | + // | | | + // v height v +1 v height + // + bool clipSpaceBottomUp = false; + bool framebufferBottomUp = false; // Backend cannot initialize PLS with typical clear/load APIs in atomic // mode. Issue a "DrawType::atomicInitialize" draw instead. bool atomicPLSMustBeInitializedAsDraw = false; 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 50de93bc..f134643f 100644 --- a/renderer/include/rive/renderer/webgpu/render_context_webgpu_impl.hpp +++ b/renderer/include/rive/renderer/webgpu/render_context_webgpu_impl.hpp @@ -69,13 +69,17 @@ class RenderContextWebGPUImpl : public RenderContextHelperImpl { PixelLocalStorageType plsType = PixelLocalStorageType::none; bool disableStorageBuffers = false; + // Invert Y when drawing to client-provided RenderTargets. + // TODO: We may need to eventually make this configurable + // per-RenderTarget. + bool invertRenderTargetY = false; + // Invert the front face when drawing to client-provied RenderTargets. + bool invertRenderTargetFrontFace = false; }; - static std::unique_ptr MakeContext( - wgpu::Device, - wgpu::Queue, - const ContextOptions&, - const gpu::PlatformFeatures& baselinePlatformFeatures = {}); + static std::unique_ptr MakeContext(wgpu::Device, + wgpu::Queue, + const ContextOptions&); virtual ~RenderContextWebGPUImpl(); @@ -93,11 +97,9 @@ class RenderContextWebGPUImpl : public RenderContextHelperImpl const uint8_t imageDataRGBA[]) override; protected: - RenderContextWebGPUImpl( - wgpu::Device device, - wgpu::Queue queue, - const ContextOptions&, - const gpu::PlatformFeatures& baselinePlatformFeatures); + RenderContextWebGPUImpl(wgpu::Device device, + wgpu::Queue queue, + const ContextOptions&); // Create the BindGroupLayout that binds the PLS attachments as textures. // This is not necessary on all implementations. @@ -124,9 +126,11 @@ class RenderContextWebGPUImpl : public RenderContextHelperImpl EmJsHandle* renderPassJSHandleIfNeeded); wgpu::Device device() const { return m_device; } - wgpu::FrontFace frontFaceForOnScreenDraws() const + wgpu::FrontFace frontFaceForRenderTargetDraws() const { - return m_frontFaceForOnScreenDraws; + return m_contextOptions.invertRenderTargetFrontFace + ? wgpu::FrontFace::CCW + : wgpu::FrontFace::CW; } wgpu::PipelineLayout drawPipelineLayout() const { @@ -160,15 +164,6 @@ class RenderContextWebGPUImpl : public RenderContextHelperImpl const wgpu::Queue m_queue; const ContextOptions m_contextOptions; - // PLS always expects CW, but when using "glsl-raw" shaders, we may need to - // use CCW. This is because the WebGPU layer might actually flip our - // frontFace if it anticipates negating our Y coordinate in the vertex - // shader. But when we use raw-glsl shaders, the WebGPU layer doesn't - // actually get a chance to negate Y like it thinks it will. Therefore, we - // emit the wrong frontFace, in anticipation of it getting flipped into the - // correct frontFace on its way to the driver. - wgpu::FrontFace m_frontFaceForOnScreenDraws; - // Draws emulated render-pass load/store actions for // EXT_shader_pixel_local_storage. class LoadStoreEXTPipeline; diff --git a/renderer/src/d3d/render_context_d3d_impl.cpp b/renderer/src/d3d/render_context_d3d_impl.cpp index ae1bb1e2..57c5c7cf 100644 --- a/renderer/src/d3d/render_context_d3d_impl.cpp +++ b/renderer/src/d3d/render_context_d3d_impl.cpp @@ -163,7 +163,8 @@ RenderContextD3DImpl::RenderContextD3DImpl( m_gpu(std::move(gpu)), m_gpuContext(std::move(gpuContext)) { - m_platformFeatures.invertOffscreenY = true; + m_platformFeatures.clipSpaceBottomUp = true; + m_platformFeatures.framebufferBottomUp = false; m_platformFeatures.supportsRasterOrdering = d3dCapabilities.supportsRasterizerOrderedViews; m_platformFeatures.supportsFragmentShaderAtomics = true; diff --git a/renderer/src/gl/render_context_gl_impl.cpp b/renderer/src/gl/render_context_gl_impl.cpp index 40ed1769..2ad63ba5 100644 --- a/renderer/src/gl/render_context_gl_impl.cpp +++ b/renderer/src/gl/render_context_gl_impl.cpp @@ -73,7 +73,8 @@ RenderContextGLImpl::RenderContextGLImpl( // (5-10%) improvement from not using flat varyings. m_platformFeatures.avoidFlatVaryings = true; } - m_platformFeatures.fragCoordBottomUp = true; + m_platformFeatures.clipSpaceBottomUp = true; + m_platformFeatures.framebufferBottomUp = true; std::vector generalDefines; if (!m_capabilities.ARB_shader_storage_buffer_object) @@ -685,6 +686,8 @@ RenderContextGLImpl::DrawShader::DrawShader( { defines.push_back(GLSL_RENDER_MODE_MSAA); } + assert(renderContextImpl->platformFeatures().framebufferBottomUp); + defines.push_back(GLSL_FRAMEBUFFER_BOTTOM_UP); std::vector sources; sources.push_back(glsl::constants); diff --git a/renderer/src/gpu.cpp b/renderer/src/gpu.cpp index 476ef739..015c401b 100644 --- a/renderer/src/gpu.cpp +++ b/renderer/src/gpu.cpp @@ -430,11 +430,20 @@ FlushUniforms::InverseViewports::InverseViewports( const PlatformFeatures& platformFeatures) { float4 numerators = 2; - if (platformFeatures.invertOffscreenY) + // When rendering to the gradient and tessellation textures, ensure that + // row 0 in input coordinates gets written to row 0 in texture memory. + // This requires a Y inversion if clip space and framebuffer space have + // opposing senses of which way is up. + if (platformFeatures.clipSpaceBottomUp != + platformFeatures.framebufferBottomUp) { numerators.xy = -numerators.xy; } - if (platformFeatures.uninvertOnScreenY) + // When drawing to a render target, ensure that Y=0 (in Rive pixel space) + // gets drawn to the top of thew viewport. + // This requires a Y inversion if Rive pixel space and clip space have + // opposing senses of which way is up. + if (platformFeatures.clipSpaceBottomUp) { numerators.w = -numerators.w; } @@ -570,7 +579,7 @@ void PaintAuxData::set(const Mat2D& viewMatrix, { Mat2D paintMatrix; viewMatrix.invert(&paintMatrix); - if (platformFeatures.fragCoordBottomUp) + if (platformFeatures.framebufferBottomUp) { // Flip _fragCoord.y. paintMatrix = @@ -646,7 +655,7 @@ void PaintAuxData::set(const Mat2D& viewMatrix, if (clipRectInverseMatrix != nullptr) { Mat2D m = clipRectInverseMatrix->inverseMatrix(); - if (platformFeatures.fragCoordBottomUp) + if (platformFeatures.framebufferBottomUp) { // Flip _fragCoord.y. m = m * Mat2D(1, 0, 0, -1, 0, renderTarget->height()); diff --git a/renderer/src/metal/render_context_metal_impl.mm b/renderer/src/metal/render_context_metal_impl.mm index d2fc7101..81c3b281 100644 --- a/renderer/src/metal/render_context_metal_impl.mm +++ b/renderer/src/metal/render_context_metal_impl.mm @@ -343,7 +343,8 @@ void onUnmapAndSubmitBuffer(int bufferIdx, size_t mapSizeInBytes) override // It appears, so far, that we don't need to use flat interpolation for path // IDs on any Apple device, and it's faster not to. m_platformFeatures.avoidFlatVaryings = true; - m_platformFeatures.invertOffscreenY = true; + m_platformFeatures.clipSpaceBottomUp = true; + m_platformFeatures.framebufferBottomUp = false; #if defined(RIVE_IOS) || defined(RIVE_XROS) || defined(RIVE_APPLETVOS) m_platformFeatures.supportsRasterOrdering = true; m_platformFeatures.supportsFragmentShaderAtomics = false; diff --git a/renderer/src/shaders/color_ramp.glsl b/renderer/src/shaders/color_ramp.glsl index 040f5eae..546313fd 100644 --- a/renderer/src/shaders/color_ramp.glsl +++ b/renderer/src/shaders/color_ramp.glsl @@ -83,11 +83,9 @@ VERTEX_MAIN(@colorRampVertexMain, Attrs, attrs, _vertexID, _instanceID) } v_rampColor = unpackColorInt(columnWithinSpan <= 1 ? @a_span.z : @a_span.w); - float4 pos; - pos.x = x * 2. - 1.; - pos.y = - y * uniforms.gradInverseViewportY - sign(uniforms.gradInverseViewportY); - pos.zw = float2(0, 1); + float4 pos = pixel_coord_to_clip_coord(float2(x, y), + 2., + uniforms.gradInverseViewportY); VARYING_PACK(v_rampColor); EMIT_VERTEX(pos); diff --git a/renderer/src/shaders/common.glsl b/renderer/src/shaders/common.glsl index 959c9039..b32475c3 100644 --- a/renderer/src/shaders/common.glsl +++ b/renderer/src/shaders/common.glsl @@ -185,12 +185,21 @@ UNIFORM_BLOCK_END(uniforms) #ifdef @VERTEX +INLINE float4 pixel_coord_to_clip_coord(float2 pixelCoord, + float inverseViewportX, + float inverseViewportY) +{ + return float4(pixelCoord.x * inverseViewportX - 1., + pixelCoord.y * inverseViewportY - sign(inverseViewportY), + 0., + 1.); +} + +// Defined as a macro because 'uniforms' isn't always available at global scope. #define RENDER_TARGET_COORD_TO_CLIP_COORD(COORD) \ - float4((COORD).x* uniforms.renderTargetInverseViewportX - 1., \ - (COORD).y * -uniforms.renderTargetInverseViewportY + \ - sign(uniforms.renderTargetInverseViewportY), \ - .0, \ - 1.) + pixel_coord_to_clip_coord(COORD, \ + uniforms.renderTargetInverseViewportX, \ + uniforms.renderTargetInverseViewportY) #ifndef @RENDER_MODE_MSAA // Calculates the Manhattan distance in pixels from the given pixelPosition, to diff --git a/renderer/src/shaders/draw_path.glsl b/renderer/src/shaders/draw_path.glsl index 21ed0b40..08ddc524 100644 --- a/renderer/src/shaders/draw_path.glsl +++ b/renderer/src/shaders/draw_path.glsl @@ -130,7 +130,7 @@ VERTEX_MAIN(@drawVertexMain, Attrs, attrs, _vertexID, _instanceID) // Paint matrices operate on the fragment shader's "_fragCoord", which is // bottom-up in GL. float2 fragCoord = vertexPosition; -#ifdef FRAG_COORD_BOTTOM_UP +#ifdef @FRAMEBUFFER_BOTTOM_UP fragCoord.y = float(uniforms.renderTargetHeight) - fragCoord.y; #endif @@ -234,6 +234,9 @@ VERTEX_MAIN(@drawVertexMain, Attrs, attrs, _vertexID, _instanceID) if (!shouldDiscardVertex) { pos = RENDER_TARGET_COORD_TO_CLIP_COORD(vertexPosition); +#ifdef @POST_INVERT_Y + pos.y = -pos.y; +#endif #ifdef @RENDER_MODE_MSAA pos.z = normalize_z_index(pathZIndex); #endif diff --git a/renderer/src/shaders/glsl.glsl b/renderer/src/shaders/glsl.glsl index b3b4bf4d..d63bb28b 100644 --- a/renderer/src/shaders/glsl.glsl +++ b/renderer/src/shaders/glsl.glsl @@ -533,10 +533,6 @@ #define MUL(A, B) ((A) * (B)) -#ifndef @TARGET_VULKAN -#define FRAG_COORD_BOTTOM_UP -#endif - precision highp float; precision highp int; diff --git a/renderer/src/shaders/tessellate.glsl b/renderer/src/shaders/tessellate.glsl index bcf34986..53a37d72 100644 --- a/renderer/src/shaders/tessellate.glsl +++ b/renderer/src/shaders/tessellate.glsl @@ -217,11 +217,9 @@ VERTEX_MAIN(@tessellateVertexMain, Attrs, attrs, _vertexID, _instanceID) } v_contourIDWithFlags = contourIDWithFlags; - float4 pos; - pos.x = coord.x * (2. / TESS_TEXTURE_WIDTH) - 1.; - pos.y = coord.y * uniforms.tessInverseViewportY - - sign(uniforms.tessInverseViewportY); - pos.zw = float2(0, 1); + float4 pos = pixel_coord_to_clip_coord(coord, + 2. / TESS_TEXTURE_WIDTH, + uniforms.tessInverseViewportY); VARYING_PACK(v_p0p1); VARYING_PACK(v_p2p3); diff --git a/renderer/src/vulkan/render_context_vulkan_impl.cpp b/renderer/src/vulkan/render_context_vulkan_impl.cpp index c3947dc9..ba1a806d 100644 --- a/renderer/src/vulkan/render_context_vulkan_impl.cpp +++ b/renderer/src/vulkan/render_context_vulkan_impl.cpp @@ -2104,8 +2104,8 @@ RenderContextVulkanImpl::RenderContextVulkanImpl( features.fragmentStoresAndAtomics; m_platformFeatures.supportsClockwiseAtomicRendering = features.fragmentStoresAndAtomics; - m_platformFeatures.invertOffscreenY = false; - m_platformFeatures.uninvertOnScreenY = true; + m_platformFeatures.clipSpaceBottomUp = false; + m_platformFeatures.framebufferBottomUp = false; m_platformFeatures.maxCoverageBufferLength = std::min(features.maxStorageBufferRange, 1u << 28) / sizeof(uint32_t); diff --git a/renderer/src/webgpu/render_context_webgpu_impl.cpp b/renderer/src/webgpu/render_context_webgpu_impl.cpp index e581d701..2a1043f8 100644 --- a/renderer/src/webgpu/render_context_webgpu_impl.cpp +++ b/renderer/src/webgpu/render_context_webgpu_impl.cpp @@ -212,6 +212,10 @@ class RenderContextWebGPUImpl::LoadStoreEXTPipeline glsl << "#pragma shader_stage(fragment)\n"; glsl << "#define " GLSL_FRAGMENT " true\n"; glsl << "#define " GLSL_ENABLE_CLIPPING " true\n"; + if (context->m_contextOptions.invertRenderTargetY) + { + glsl << "#define " GLSL_POST_INVERT_Y " true\n"; + } BuildLoadStoreEXTGLSL(glsl, actions); fragmentShader = m_fragmentShaderHandle.compileShaderModule(context->m_device, @@ -241,7 +245,7 @@ class RenderContextWebGPUImpl::LoadStoreEXTPipeline .primitive = { .topology = wgpu::PrimitiveTopology::TriangleStrip, - .frontFace = context->m_frontFaceForOnScreenDraws, + .frontFace = context->frontFaceForRenderTargetDraws(), .cullMode = wgpu::CullMode::Back, }, .fragment = &fragmentState, @@ -574,22 +578,26 @@ class RenderContextWebGPUImpl::DrawPipeline { const char* language; const char* versionString; + std::ostringstream glsl; + auto addDefine = [&glsl](const char* name) { + glsl << "#define " << name << " true\n"; + }; if (plsType == PixelLocalStorageType::EXT_shader_pixel_local_storage) { language = "glsl-raw"; versionString = "#version 310 es"; + if (context->m_contextOptions.invertRenderTargetY) + { + addDefine(GLSL_POST_INVERT_Y); + } } else { language = "glsl"; versionString = "#version 460"; + addDefine(GLSL_TARGET_VULKAN); } - - std::ostringstream glsl; - auto addDefine = [&glsl](const char* name) { - glsl << "#define " << name << " true\n"; - }; if (plsType == PixelLocalStorageType::EXT_shader_pixel_local_storage) { @@ -598,7 +606,6 @@ class RenderContextWebGPUImpl::DrawPipeline glsl << "#else\n"; glsl << "#extension GL_EXT_samplerless_texture_functions : " "enable\n"; - addDefine(GLSL_TARGET_VULKAN); // If we are being compiled by SPIRV transpiler for // introspection, GL_EXT_shader_pixel_local_storage will not be // defined. @@ -609,7 +616,6 @@ class RenderContextWebGPUImpl::DrawPipeline { glsl << "#extension GL_EXT_samplerless_texture_functions : " "enable\n"; - addDefine(GLSL_TARGET_VULKAN); addDefine(plsType == PixelLocalStorageType::subpassLoad ? GLSL_PLS_IMPL_SUBPASS_LOAD : GLSL_PLS_IMPL_NONE); @@ -810,39 +816,19 @@ class RenderContextWebGPUImpl::DrawPipeline RenderContextWebGPUImpl::RenderContextWebGPUImpl( wgpu::Device device, wgpu::Queue queue, - const ContextOptions& contextOptions, - const PlatformFeatures& baselinePlatformFeatures) : + const ContextOptions& contextOptions) : m_device(device), m_queue(queue), m_contextOptions(contextOptions), - m_frontFaceForOnScreenDraws(wgpu::FrontFace::CW), m_colorRampPipeline(std::make_unique(m_device)), m_tessellatePipeline( std::make_unique(m_device, m_contextOptions)) { - m_platformFeatures = baselinePlatformFeatures; // All backends currently use raster ordered shaders. // TODO: update this flag once we have msaa and atomic modes. m_platformFeatures.supportsRasterOrdering = true; - m_platformFeatures.invertOffscreenY = true; - - if (m_contextOptions.plsType == - PixelLocalStorageType::EXT_shader_pixel_local_storage && - baselinePlatformFeatures.uninvertOnScreenY) - { - // We will use "glsl-raw" in order to access - // EXT_shader_pixel_local_storage, so the WebGPU layer won't actually - // get a chance to negate Y like it thinks it will. - m_platformFeatures.uninvertOnScreenY = false; - // PLS always expects CW, but in this case, we need to specify CCW. This - // is because the WebGPU layer thinks it's going to negate Y in our - // shader, and will therefore also flip our frontFace. However, since we - // will use raw-glsl shaders, the WebGPU layer won't actually get a - // chance to negate Y like it thinks it will. Therefore, we emit the - // wrong frontFace, in anticipation of it getting flipped into the - // correct frontFace on its way to the driver. - m_frontFaceForOnScreenDraws = wgpu::FrontFace::CCW; - } + m_platformFeatures.clipSpaceBottomUp = true; + m_platformFeatures.framebufferBottomUp = false; } void RenderContextWebGPUImpl::initGPUObjects() @@ -1084,6 +1070,10 @@ void RenderContextWebGPUImpl::initGPUObjects() glsl << "#define gl_VertexID gl_VertexIndex\n"; glsl << "#endif\n"; glsl << "#define " GLSL_ENABLE_CLIPPING " true\n"; + if (m_contextOptions.invertRenderTargetY) + { + glsl << "#define " GLSL_POST_INVERT_Y " true\n"; + } BuildLoadStoreEXTGLSL(glsl, LoadStoreActionsEXT::none); m_loadStoreEXTVertexShader = m_loadStoreEXTVertexShaderHandle.compileShaderModule( @@ -1671,7 +1661,7 @@ wgpu::RenderPipeline RenderContextWebGPUImpl::makeDrawPipeline( .primitive = { .topology = wgpu::PrimitiveTopology::TriangleList, - .frontFace = m_frontFaceForOnScreenDraws, + .frontFace = frontFaceForRenderTargetDraws(), .cullMode = DrawTypeIsImageDraw(drawType) ? wgpu::CullMode::None : wgpu::CullMode::Back, @@ -2247,8 +2237,7 @@ void RenderContextWebGPUImpl::flush(const FlushDescriptor& desc) std::unique_ptr RenderContextWebGPUImpl::MakeContext( wgpu::Device device, wgpu::Queue queue, - const ContextOptions& contextOptions, - const gpu::PlatformFeatures& baselinePlatformFeatures) + const ContextOptions& contextOptions) { std::unique_ptr impl; switch (contextOptions.plsType) @@ -2256,19 +2245,13 @@ std::unique_ptr RenderContextWebGPUImpl::MakeContext( case PixelLocalStorageType::subpassLoad: #ifdef RIVE_WEBGPU impl = std::unique_ptr( - new RenderContextWebGPUVulkan(device, - queue, - contextOptions, - baselinePlatformFeatures)); + new RenderContextWebGPUVulkan(device, queue, contextOptions)); break; #endif case PixelLocalStorageType::EXT_shader_pixel_local_storage: case PixelLocalStorageType::none: impl = std::unique_ptr( - new RenderContextWebGPUImpl(device, - queue, - contextOptions, - baselinePlatformFeatures)); + new RenderContextWebGPUImpl(device, queue, contextOptions)); break; } impl->initGPUObjects(); diff --git a/renderer/src/webgpu/render_context_webgpu_vulkan.cpp b/renderer/src/webgpu/render_context_webgpu_vulkan.cpp index ea4749ee..8ed5027c 100644 --- a/renderer/src/webgpu/render_context_webgpu_vulkan.cpp +++ b/renderer/src/webgpu/render_context_webgpu_vulkan.cpp @@ -230,7 +230,7 @@ wgpu::RenderPipeline RenderContextWebGPUVulkan::makeDrawPipeline( emscripten_webgpu_export_shader_module(vertexShader.Get()), emscripten_webgpu_export_shader_module(fragmentShader.Get()), emscripten_webgpu_export_pipeline_layout(drawPipelineLayout().Get()), - frontFaceForOnScreenDraws() == wgpu::FrontFace::CW)); + frontFaceForRenderTargetDraws() == wgpu::FrontFace::CW)); static_assert(COLOR_PLANE_IDX == 0); static_assert(CLIP_PLANE_IDX == 1); static_assert(SCRATCH_COLOR_PLANE_IDX == 2); diff --git a/renderer/src/webgpu/render_context_webgpu_vulkan.hpp b/renderer/src/webgpu/render_context_webgpu_vulkan.hpp index 0bfef123..f91557e8 100644 --- a/renderer/src/webgpu/render_context_webgpu_vulkan.hpp +++ b/renderer/src/webgpu/render_context_webgpu_vulkan.hpp @@ -41,15 +41,10 @@ class RenderContextWebGPUVulkan : public RenderContextWebGPUImpl private: friend class RenderContextWebGPUImpl; - RenderContextWebGPUVulkan( - wgpu::Device device, - wgpu::Queue queue, - const ContextOptions& contextOptions, - const gpu::PlatformFeatures& baselinePlatformFeatures) : - RenderContextWebGPUImpl(device, - queue, - contextOptions, - baselinePlatformFeatures) + RenderContextWebGPUVulkan(wgpu::Device device, + wgpu::Queue queue, + const ContextOptions& contextOptions) : + RenderContextWebGPUImpl(device, queue, contextOptions) { assert(contextOptions.plsType == PixelLocalStorageType::subpassLoad); m_platformFeatures.supportsRasterOrdering = true; diff --git a/renderer/webgpu_player/rive.js b/renderer/webgpu_player/rive.js index fd9bd009..ce6d2f73 100644 --- a/renderer/webgpu_player/rive.js +++ b/renderer/webgpu_player/rive.js @@ -27,7 +27,6 @@ function RiveInitialize(device, queue, canvasWidth, canvasHeight, - invertedY, pixelLocalStorageType, maxVertexStorageBlocks) { @@ -35,7 +34,6 @@ function RiveInitialize(device, JsValStore.add(queue), canvasWidth, canvasHeight, - invertedY, pixelLocalStorageType, maxVertexStorageBlocks); } diff --git a/renderer/webgpu_player/webgpu_player.cpp b/renderer/webgpu_player/webgpu_player.cpp index 2b632538..66d75265 100644 --- a/renderer/webgpu_player/webgpu_player.cpp +++ b/renderer/webgpu_player/webgpu_player.cpp @@ -40,9 +40,9 @@ static std::unique_ptr s_renderer; void riveInitPlayer(int w, int h, + bool invertRenderTargetFrontFace, wgpu::Device gpu, wgpu::Queue queue, - const gpu::PlatformFeatures& platformFeatures, PixelLocalStorageType plsType, int maxVertexStorageBlocks) { @@ -50,14 +50,14 @@ void riveInitPlayer(int w, .plsType = plsType, .disableStorageBuffers = maxVertexStorageBlocks < gpu::kMaxStorageBuffers, + .invertRenderTargetY = h < 0, + .invertRenderTargetFrontFace = invertRenderTargetFrontFace, }; - s_renderContext = RenderContextWebGPUImpl::MakeContext(gpu, - queue, - contextOptions, - platformFeatures); + s_renderContext = + RenderContextWebGPUImpl::MakeContext(gpu, queue, contextOptions); s_renderTarget = s_renderContext->static_impl_cast() - ->makeRenderTarget(wgpu::TextureFormat::BGRA8Unorm, w, h); + ->makeRenderTarget(wgpu::TextureFormat::BGRA8Unorm, w, abs(h)); s_renderer = std::make_unique(s_renderContext.get()); } @@ -73,24 +73,19 @@ extern "C" int queueID, int canvasWidth, int canvasHeight, - bool invertedY, + bool invertRenderTargetFrontFace, int pixelLocalStorageType, int maxVertexStorageBlocks) { s_deviceHandle = EmJsHandle(deviceID); s_queueHandle = EmJsHandle(queueID); - gpu::PlatformFeatures platformFeatures; - if (invertedY) - { - platformFeatures.uninvertOnScreenY = true; - } riveInitPlayer( canvasWidth, canvasHeight, + invertRenderTargetFrontFace, wgpu::Device::Acquire( emscripten_webgpu_import_device(s_deviceHandle.get())), emscripten_webgpu_import_queue(s_queueHandle.get()), - platformFeatures, static_cast(pixelLocalStorageType), maxVertexStorageBlocks); } @@ -556,9 +551,9 @@ int main(int argc, const char** argv) riveInitPlayer(w, h, + /*invertRenderTargetFrontFace=*/false, device.Get(), device.GetQueue(), - PlatformFeatures{}, PixelLocalStorageType::none, 8);