mirror of
https://github.com/rive-app/rive-cpp.git
synced 2026-01-18 21:21:17 +01:00
fix(webgpu): Fix Y orientation on GL zero and nonzero FBOs (#10623) 454b0d2db1
Co-authored-by: Chris Dalton <99840794+csmartdalton@users.noreply.github.com>
This commit is contained in:
@@ -1 +1 @@
|
||||
ec8b00c206d9842b618d1368617155cb0bfaae62
|
||||
454b0d2db1370c47b3eafbc325d9295200b4e803
|
||||
|
||||
@@ -20,14 +20,7 @@ class RenderContextWebGPUImpl : public RenderContextHelperImpl
|
||||
{
|
||||
public:
|
||||
struct ContextOptions
|
||||
{
|
||||
// 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;
|
||||
};
|
||||
{};
|
||||
|
||||
enum class PixelLocalStorageType
|
||||
{
|
||||
@@ -102,12 +95,6 @@ private:
|
||||
wgpu::LoadOp,
|
||||
const wgpu::Color& clearColor);
|
||||
|
||||
wgpu::FrontFace frontFaceForRenderTargetDraws() const
|
||||
{
|
||||
return m_contextOptions.invertRenderTargetFrontFace
|
||||
? wgpu::FrontFace::CCW
|
||||
: wgpu::FrontFace::CW;
|
||||
}
|
||||
wgpu::PipelineLayout drawPipelineLayout() const
|
||||
{
|
||||
return m_drawPipelineLayout;
|
||||
@@ -118,10 +105,6 @@ private:
|
||||
|
||||
void generateMipmaps(wgpu::Texture);
|
||||
|
||||
// PLS always expects a clockwise front face.
|
||||
constexpr static wgpu::FrontFace kFrontFaceForOffscreenDraws =
|
||||
wgpu::FrontFace::CW;
|
||||
|
||||
std::unique_ptr<BufferRing> makeUniformBufferRing(
|
||||
size_t capacityInBytes) override;
|
||||
std::unique_ptr<BufferRing> makeStorageBufferRing(
|
||||
@@ -211,7 +194,7 @@ public:
|
||||
return m_framebufferFormat;
|
||||
}
|
||||
|
||||
void setTargetTextureView(wgpu::TextureView);
|
||||
void setTargetTextureView(wgpu::TextureView, wgpu::Texture);
|
||||
|
||||
protected:
|
||||
RenderTargetWebGPU(wgpu::Device device,
|
||||
@@ -225,6 +208,7 @@ private:
|
||||
|
||||
const wgpu::TextureFormat m_framebufferFormat;
|
||||
|
||||
wgpu::Texture m_targetTexture;
|
||||
wgpu::Texture m_coverageTexture;
|
||||
wgpu::Texture m_clipTexture;
|
||||
wgpu::Texture m_scratchColorTexture;
|
||||
@@ -244,6 +228,7 @@ public:
|
||||
m_textureView(m_texture.CreateView())
|
||||
{}
|
||||
|
||||
wgpu::Texture texture() const { return m_texture; }
|
||||
wgpu::TextureView textureView() const { return m_textureView; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -283,7 +283,8 @@ public:
|
||||
m_currentSurfaceTextureView =
|
||||
wgpuTextureCreateView(m_currentSurfaceTexture.texture,
|
||||
&textureViewDesc);
|
||||
m_renderTarget->setTargetTextureView(m_currentSurfaceTextureView);
|
||||
m_renderTarget->setTargetTextureView(m_currentSurfaceTextureView,
|
||||
m_currentSurfaceTexture.texture);
|
||||
m_renderContext->beginFrame(std::move(frameDescriptor));
|
||||
}
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@ IMAGE_MESH_VERTEX_MAIN(@drawVertexMain,
|
||||
}
|
||||
#endif // ENABLE_CLIP_RECT
|
||||
float4 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(imageDrawUniforms.zIndex);
|
||||
#endif
|
||||
|
||||
@@ -54,6 +54,8 @@ using TextureDataLayout = TexelCopyBufferLayout;
|
||||
}; // namespace wgpu
|
||||
#endif
|
||||
|
||||
constexpr static auto RIVE_FRONT_FACE = wgpu::FrontFace::CW;
|
||||
|
||||
#ifdef RIVE_WAGYU
|
||||
#include <webgpu/webgpu_wagyu.h>
|
||||
|
||||
@@ -199,7 +201,7 @@ public:
|
||||
.primitive =
|
||||
{
|
||||
.topology = wgpu::PrimitiveTopology::TriangleStrip,
|
||||
.frontFace = context->frontFaceForRenderTargetDraws(),
|
||||
.frontFace = RIVE_FRONT_FACE,
|
||||
.cullMode = wgpu::CullMode::None,
|
||||
},
|
||||
.fragment = &fragmentState,
|
||||
@@ -339,7 +341,7 @@ public:
|
||||
.primitive =
|
||||
{
|
||||
.topology = wgpu::PrimitiveTopology::TriangleStrip,
|
||||
.frontFace = kFrontFaceForOffscreenDraws,
|
||||
.frontFace = RIVE_FRONT_FACE,
|
||||
.cullMode = wgpu::CullMode::None,
|
||||
},
|
||||
.fragment = &fragmentState,
|
||||
@@ -497,7 +499,7 @@ public:
|
||||
.primitive =
|
||||
{
|
||||
.topology = wgpu::PrimitiveTopology::TriangleList,
|
||||
.frontFace = kFrontFaceForOffscreenDraws,
|
||||
.frontFace = RIVE_FRONT_FACE,
|
||||
.cullMode = wgpu::CullMode::None,
|
||||
},
|
||||
.fragment = &fragmentState,
|
||||
@@ -677,7 +679,7 @@ public:
|
||||
.primitive =
|
||||
{
|
||||
.topology = wgpu::PrimitiveTopology::TriangleList,
|
||||
.frontFace = kFrontFaceForOffscreenDraws,
|
||||
.frontFace = RIVE_FRONT_FACE,
|
||||
.cullMode = wgpu::CullMode::Back,
|
||||
},
|
||||
.fragment = &fragmentState,
|
||||
@@ -709,7 +711,8 @@ class RenderContextWebGPUImpl::DrawPipeline
|
||||
public:
|
||||
DrawPipeline(RenderContextWebGPUImpl* context,
|
||||
DrawType drawType,
|
||||
gpu::ShaderFeatures shaderFeatures)
|
||||
gpu::ShaderFeatures shaderFeatures,
|
||||
bool targetIsGLFBO0)
|
||||
{
|
||||
wgpu::ShaderModule vertexShader, fragmentShader;
|
||||
#ifdef RIVE_WAGYU
|
||||
@@ -730,7 +733,7 @@ public:
|
||||
{
|
||||
language = WGPUWagyuShaderLanguage_GLSLRAW;
|
||||
versionString = "#version 310 es";
|
||||
if (context->m_contextOptions.invertRenderTargetY)
|
||||
if (!targetIsGLFBO0)
|
||||
{
|
||||
addDefine(GLSL_POST_INVERT_Y);
|
||||
}
|
||||
@@ -1403,10 +1406,6 @@ 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 =
|
||||
compile_shader_module_wagyu(m_device,
|
||||
@@ -1545,8 +1544,10 @@ RenderTargetWebGPU::RenderTargetWebGPU(
|
||||
m_scratchColorTextureView = m_scratchColorTexture.CreateView();
|
||||
}
|
||||
|
||||
void RenderTargetWebGPU::setTargetTextureView(wgpu::TextureView textureView)
|
||||
void RenderTargetWebGPU::setTargetTextureView(wgpu::TextureView textureView,
|
||||
wgpu::Texture texture)
|
||||
{
|
||||
m_targetTexture = texture;
|
||||
m_targetTextureView = textureView;
|
||||
}
|
||||
|
||||
@@ -2300,8 +2301,7 @@ wgpu::RenderPipeline RenderContextWebGPUImpl::makeDrawPipeline(
|
||||
.primitive =
|
||||
{
|
||||
.topology = WGPUPrimitiveTopology_TriangleList,
|
||||
.frontFace =
|
||||
static_cast<WGPUFrontFace>(frontFaceForRenderTargetDraws()),
|
||||
.frontFace = static_cast<WGPUFrontFace>(RIVE_FRONT_FACE),
|
||||
.cullMode = DrawTypeIsImageDraw(drawType) ? WGPUCullMode_None
|
||||
: WGPUCullMode_Back,
|
||||
},
|
||||
@@ -2930,16 +2930,28 @@ void RenderContextWebGPUImpl::flush(const FlushDescriptor& desc)
|
||||
}
|
||||
|
||||
// Setup the pipeline for this specific drawType and shaderFeatures.
|
||||
bool targetIsGLFBO0 = false;
|
||||
#ifdef RIVE_WAGYU
|
||||
if (m_capabilities.backendType == wgpu::BackendType::OpenGLES)
|
||||
{
|
||||
targetIsGLFBO0 = wgpuWagyuTextureIsSwapchain(
|
||||
renderTarget->m_targetTexture.Get());
|
||||
}
|
||||
#endif
|
||||
uint32_t webgpuShaderKey =
|
||||
(gpu::ShaderUniqueKey(drawType,
|
||||
batch.shaderFeatures,
|
||||
gpu::InterlockMode::rasterOrdering,
|
||||
gpu::ShaderMiscFlags::none)
|
||||
<< 1) |
|
||||
static_cast<uint32_t>(targetIsGLFBO0);
|
||||
const DrawPipeline& drawPipeline =
|
||||
m_drawPipelines
|
||||
.try_emplace(
|
||||
gpu::ShaderUniqueKey(drawType,
|
||||
batch.shaderFeatures,
|
||||
gpu::InterlockMode::rasterOrdering,
|
||||
gpu::ShaderMiscFlags::none),
|
||||
this,
|
||||
drawType,
|
||||
batch.shaderFeatures)
|
||||
.try_emplace(webgpuShaderKey,
|
||||
this,
|
||||
drawType,
|
||||
batch.shaderFeatures,
|
||||
targetIsGLFBO0)
|
||||
.first->second;
|
||||
drawPass.SetPipeline(
|
||||
drawPipeline.renderPipeline(renderTarget->framebufferFormat()));
|
||||
|
||||
@@ -226,7 +226,7 @@ extern "C" EM_BOOL animationFrame(double time, void* userData)
|
||||
scene->draw(renderer.get());
|
||||
renderer->restore();
|
||||
|
||||
renderTarget->setTargetTextureView(textureView);
|
||||
renderTarget->setTargetTextureView(textureView, texture);
|
||||
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
renderContext->flush({
|
||||
.renderTarget = renderTarget.get(),
|
||||
|
||||
@@ -130,7 +130,7 @@ private:
|
||||
width,
|
||||
height,
|
||||
renderContextImpl->device().CreateTexture(&textureDesc));
|
||||
setTargetTextureView(texture->textureView());
|
||||
setTargetTextureView(texture->textureView(), texture->texture());
|
||||
m_renderImage =
|
||||
rive::make_rcp<rive::RiveRenderImage>(std::move(texture));
|
||||
}
|
||||
@@ -326,14 +326,16 @@ public:
|
||||
m_renderTarget =
|
||||
m_renderContext->static_impl_cast<RenderContextWebGPUImpl>()
|
||||
->makeRenderTarget(m_format, m_width, m_height);
|
||||
m_renderTarget->setTargetTextureView(m_overflowTextureView);
|
||||
m_renderTarget->setTargetTextureView(m_overflowTextureView,
|
||||
m_overflowTexture);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_renderTarget =
|
||||
m_renderContext->static_impl_cast<RenderContextWebGPUImpl>()
|
||||
->makeRenderTarget(m_format, surfaceWidth, surfaceHeight);
|
||||
m_renderTarget->setTargetTextureView(m_currentCanvasTextureView);
|
||||
m_renderTarget->setTargetTextureView(m_currentCanvasTextureView,
|
||||
m_currentCanvasTexture);
|
||||
}
|
||||
|
||||
rive::gpu::RenderContext::FrameDescriptor frameDescriptor = {
|
||||
@@ -400,16 +402,16 @@ public:
|
||||
{
|
||||
assert(m_format == wgpu::TextureFormat::RGBA8Unorm ||
|
||||
m_format == wgpu::TextureFormat::BGRA8Unorm);
|
||||
const uint32_t rowBytesInReadBuff =
|
||||
math::round_up_to_multiple_of<256>(m_width * 4);
|
||||
bool invertY = false;
|
||||
#ifdef RIVE_WAGYU
|
||||
if (impl()->capabilities().backendType ==
|
||||
wgpu::BackendType::OpenGLES)
|
||||
{
|
||||
invertY = true;
|
||||
}
|
||||
invertY =
|
||||
impl()->capabilities().backendType ==
|
||||
wgpu::BackendType::OpenGLES &&
|
||||
wgpuWagyuTextureIsSwapchain(m_currentCanvasTexture.Get()) &&
|
||||
m_overflowTexture == nullptr;
|
||||
#endif
|
||||
const uint32_t rowBytesInReadBuff =
|
||||
math::round_up_to_multiple_of<256>(m_width * 4);
|
||||
|
||||
// Create a buffer to receive the pixels.
|
||||
if (!m_pixelReadBuff)
|
||||
@@ -426,8 +428,9 @@ public:
|
||||
// Blit the framebuffer into m_pixelReadBuff.
|
||||
wgpu::CommandEncoder readEncoder = m_device.CreateCommandEncoder();
|
||||
wgpu::TexelCopyTextureInfo srcTexture = {
|
||||
.texture = m_overflowTexture ? m_overflowTexture
|
||||
: m_currentCanvasTexture,
|
||||
.texture = m_overflowTexture != nullptr
|
||||
? m_overflowTexture
|
||||
: m_currentCanvasTexture,
|
||||
.origin = {0,
|
||||
invertY ? m_renderTarget->height() - m_height : 0,
|
||||
0},
|
||||
|
||||
Reference in New Issue
Block a user