Skip to content

Commit

Permalink
Fix up android browserstack gms
Browse files Browse the repository at this point in the history
* Vivo Y21 has a bug when feathering to the screen. Always feather offscreen on PowerVR devices.

* Reorder GPU resource bindings to put buffers first. GLES3 can have a hard limit as low as 7 on buffer indices, but textures can always go up to at least 31.

* Be more conservative with fp32 render targets. Only use r32f on ES when EXT_float_blend is supported, even if we're on a 3.2 context. On desktop, require ARB_color_buffer_float.

* Fix an uninitialized shader variable in MSAA mode.

* Fix eval_feathered_fill() to return half. It was accidentally returning float.

Diffs=
5153dac481 Fix up android browserstack gms (#9076)

Co-authored-by: Chris Dalton <[email protected]>
  • Loading branch information
csmartdalton and csmartdalton committed Feb 20, 2025
1 parent 061ba6b commit d27fada
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 165 deletions.
2 changes: 1 addition & 1 deletion .rive_head
Original file line number Diff line number Diff line change
@@ -1 +1 @@
63c22338aa4ae1ff4dd872ed7ed9ee096baf6b48
5153dac481f44db86b07528b35d31051b4118fff
1 change: 1 addition & 0 deletions renderer/include/rive/renderer/draw.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ class PathDraw : public Draw
protected:
static CoverageType SelectCoverageType(const RiveRenderPaint*,
float matrixMaxScale,
const gpu::PlatformFeatures&,
gpu::InterlockMode);

// Prepares to draw the path by tessellating a fan around its midpoint.
Expand Down
6 changes: 6 additions & 0 deletions renderer/include/rive/renderer/gpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ struct PlatformFeatures
// Required for @ENABLE_CLIP_RECT in msaa mode.
bool supportsClipPlanes = false;
bool avoidFlatVaryings = false;
// Vivo Y21 (PowerVR Rogue GE8320; OpenGL ES 3.2 build 1.13@5776728a) seems
// to hit some sort of reset condition that corrupts pixel local storage
// when rendering a complex feather. Provide a workaround that allows the
// implementation to opt in to always feathering to the atlas instead of
// rendering directly to the screen.
bool alwaysFeatherToAtlas = false;
// clipSpaceBottomUp specifies whether the top of the viewport, in clip
// coordinates, is at Y=+1 (OpenGL, Metal, D3D, WebGPU) or Y=-1 (Vulkan).
//
Expand Down
24 changes: 14 additions & 10 deletions renderer/src/draw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,21 +371,24 @@ void Draw::releaseRefs() { safe_unref(m_imageTextureRef); }
PathDraw::CoverageType PathDraw::SelectCoverageType(
const RiveRenderPaint* paint,
float matrixMaxScale,
const gpu::PlatformFeatures& platformFeatures,
gpu::InterlockMode interlockMode)
{
if (interlockMode == gpu::InterlockMode::msaa)
if (paint->getFeather() != 0)
{
return paint->getFeather() != 0 ? CoverageType::atlas
: CoverageType::msaa;
if (platformFeatures.alwaysFeatherToAtlas ||
interlockMode == gpu::InterlockMode::msaa ||
// Always switch to the atlas once we can render quarter-resultion.
find_atlas_feather_scale_factor(
find_feather_radius(paint->getFeather()),
matrixMaxScale) <= .5f)
{
return CoverageType::atlas;
}
}
// Switch to the feather atlas once we can render quarter-resultion
// feathers.
if (paint->getFeather() != 0 &&
find_atlas_feather_scale_factor(
find_feather_radius(paint->getFeather()),
matrixMaxScale) <= .5f)
if (interlockMode == gpu::InterlockMode::msaa)
{
return CoverageType::atlas;
return CoverageType::msaa;
}
if (interlockMode == gpu::InterlockMode::clockwiseAtomic)
{
Expand All @@ -407,6 +410,7 @@ DrawUniquePtr PathDraw::Make(RenderContext* context,
CoverageType coverageType =
SelectCoverageType(paint,
matrix.findMaxScale(),
context->platformFeatures(),
context->frameInterlockMode());

// Compute the screen-space bounding box.
Expand Down
102 changes: 45 additions & 57 deletions renderer/src/gl/render_context_gl_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ const char atomic_draw[] = "";
#include "generated/shaders/atomic_draw.glsl.hpp"
#endif

// Offset all PLS texture indices by 1 so we, and others who share our GL
// context, can use GL_TEXTURE0 as a scratch texture index.
constexpr static int kPLSTexIdxOffset = 1;

namespace rive::gpu
{
RenderContextGLImpl::RenderContextGLImpl(
Expand Down Expand Up @@ -74,6 +70,14 @@ RenderContextGLImpl::RenderContextGLImpl(
// (5-10%) improvement from not using flat varyings.
m_platformFeatures.avoidFlatVaryings = true;
}
if (m_capabilities.isPowerVR)
{
// Vivo Y21 (PowerVR Rogue GE8320; OpenGL ES 3.2 build 1.13@5776728a)
// seems to hit some sort of reset condition that corrupts pixel local
// storage when rendering a complex feather. For now, feather directly
// to the screen on PowerVR; always go offscreen.
m_platformFeatures.alwaysFeatherToAtlas = true;
}
m_platformFeatures.clipSpaceBottomUp = true;
m_platformFeatures.framebufferBottomUp = true;

Expand Down Expand Up @@ -114,7 +118,7 @@ RenderContextGLImpl::RenderContextGLImpl(

// Emulate the feather texture1d array as a texture2d since GLES doesn't
// have texture1d.
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + FEATHER_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + FEATHER_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, m_featherTexture);
glTexStorage2D(GL_TEXTURE_2D,
1,
Expand Down Expand Up @@ -169,10 +173,10 @@ RenderContextGLImpl::RenderContextGLImpl(
// buffers as textures.
glutils::Uniform1iByName(m_tessellateProgram,
GLSL_pathBuffer,
kPLSTexIdxOffset + PATH_BUFFER_IDX);
PATH_BUFFER_IDX);
glutils::Uniform1iByName(m_tessellateProgram,
GLSL_contourBuffer,
kPLSTexIdxOffset + CONTOUR_BUFFER_IDX);
CONTOUR_BUFFER_IDX);
}

m_state->bindVAO(m_tessellateVAO);
Expand Down Expand Up @@ -271,16 +275,16 @@ RenderContextGLImpl::~RenderContextGLImpl()

void RenderContextGLImpl::invalidateGLState()
{
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + TESS_VERTEX_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + TESS_VERTEX_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, m_tessVertexTexture);

glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + GRAD_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + GRAD_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, m_gradientTexture);

glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + FEATHER_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + FEATHER_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, m_featherTexture);

glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + ATLAS_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + ATLAS_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, m_atlasTexture);

m_state->invalidate();
Expand All @@ -293,9 +297,9 @@ void RenderContextGLImpl::unbindGLInternalResources()
m_state->bindBuffer(GL_ARRAY_BUFFER, 0);
m_state->bindBuffer(GL_UNIFORM_BUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
for (int i = 0; i <= CONTOUR_BUFFER_IDX; ++i)
for (int i = 0; i <= DEFAULT_BINDINGS_SET_SIZE; ++i)
{
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + i);
glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
Expand Down Expand Up @@ -331,7 +335,7 @@ rcp<Texture> RenderContextGLImpl::makeImageTexture(
{
GLuint textureID;
glGenTextures(1, &textureID);
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + IMAGE_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + IMAGE_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexStorage2D(GL_TEXTURE_2D, mipLevelCount, GL_RGBA8, width, height);
glTexSubImage2D(GL_TEXTURE_2D,
Expand Down Expand Up @@ -549,7 +553,7 @@ class TexelBufferRingWebGL : public BufferRing
{
auto [updateWidth, updateHeight] =
gpu::StorageTextureSize(bindingSizeInBytes, m_bufferStructure);
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + bindingIdx);
glActiveTexture(GL_TEXTURE0 + bindingIdx);
glBindTexture(GL_TEXTURE_2D, m_textures[submittedBufferIdx()]);
glTexSubImage2D(GL_TEXTURE_2D,
0,
Expand Down Expand Up @@ -612,7 +616,7 @@ void RenderContextGLImpl::resizeGradientTexture(uint32_t width, uint32_t height)
}

glGenTextures(1, &m_gradientTexture);
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + GRAD_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + GRAD_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, m_gradientTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
glutils::SetTexture2DSamplingParams(GL_LINEAR, GL_LINEAR);
Expand All @@ -636,7 +640,7 @@ void RenderContextGLImpl::resizeTessellationTexture(uint32_t width,
}

glGenTextures(1, &m_tessVertexTexture);
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + TESS_VERTEX_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + TESS_VERTEX_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, m_tessVertexTexture);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32UI, width, height);
glutils::SetTexture2DSamplingParams(GL_NEAREST, GL_NEAREST);
Expand Down Expand Up @@ -673,18 +677,16 @@ void RenderContextGLImpl::AtlasProgram::compile(
FLUSH_UNIFORM_BUFFER_IDX);
glutils::Uniform1iByName(m_program,
GLSL_tessVertexTexture,
kPLSTexIdxOffset + TESS_VERTEX_TEXTURE_IDX);
TESS_VERTEX_TEXTURE_IDX);
glutils::Uniform1iByName(m_program,
GLSL_featherTexture,
kPLSTexIdxOffset + FEATHER_TEXTURE_IDX);
FEATHER_TEXTURE_IDX);
if (!capabilities.ARB_shader_storage_buffer_object)
{
glutils::Uniform1iByName(m_program,
GLSL_pathBuffer,
kPLSTexIdxOffset + PATH_BUFFER_IDX);
glutils::Uniform1iByName(m_program, GLSL_pathBuffer, PATH_BUFFER_IDX);
glutils::Uniform1iByName(m_program,
GLSL_contourBuffer,
kPLSTexIdxOffset + CONTOUR_BUFFER_IDX);
CONTOUR_BUFFER_IDX);
}
if (!capabilities.ANGLE_base_vertex_base_instance_shader_builtin)
{
Expand All @@ -702,7 +704,7 @@ void RenderContextGLImpl::resizeAtlasTexture(uint32_t width, uint32_t height)
}

m_atlasTexture = glutils::Texture();
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + ATLAS_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + ATLAS_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, m_atlasTexture);
glTexStorage2D(
GL_TEXTURE_2D,
Expand Down Expand Up @@ -998,15 +1000,13 @@ RenderContextGLImpl::DrawProgram::DrawProgram(
{
glutils::Uniform1iByName(m_id,
GLSL_tessVertexTexture,
kPLSTexIdxOffset + TESS_VERTEX_TEXTURE_IDX);
TESS_VERTEX_TEXTURE_IDX);
}
// Since atomic mode emits the color of the *previous* path, it needs the
// gradient texture bound for every draw.
if (isPathDraw || interlockMode == gpu::InterlockMode::atomics)
{
glutils::Uniform1iByName(m_id,
GLSL_gradTexture,
kPLSTexIdxOffset + GRAD_TEXTURE_IDX);
glutils::Uniform1iByName(m_id, GLSL_gradTexture, GRAD_TEXTURE_IDX);
}
if ((isTessellationDraw &&
(shaderFeatures & ShaderFeatures::ENABLE_FEATHER)) ||
Expand All @@ -1015,46 +1015,38 @@ RenderContextGLImpl::DrawProgram::DrawProgram(
assert(isPathDraw || interlockMode == gpu::InterlockMode::atomics);
glutils::Uniform1iByName(m_id,
GLSL_featherTexture,
kPLSTexIdxOffset + FEATHER_TEXTURE_IDX);
FEATHER_TEXTURE_IDX);
}
// Atomic mode doesn't support image paints on paths.
if (shaderMiscFlags & gpu::ShaderMiscFlags::atlasCoverage)
{
glutils::Uniform1iByName(m_id,
GLSL_atlasTexture,
kPLSTexIdxOffset + ATLAS_TEXTURE_IDX);
glutils::Uniform1iByName(m_id, GLSL_atlasTexture, ATLAS_TEXTURE_IDX);
}
if (isImageDraw ||
(isPathDraw && interlockMode != gpu::InterlockMode::atomics))
{
glutils::Uniform1iByName(m_id,
GLSL_imageTexture,
kPLSTexIdxOffset + IMAGE_TEXTURE_IDX);
glutils::Uniform1iByName(m_id, GLSL_imageTexture, IMAGE_TEXTURE_IDX);
}
if (!renderContextImpl->m_capabilities.ARB_shader_storage_buffer_object)
{
// Our GL driver doesn't support storage buffers. We polyfill these
// buffers as textures.
if (isPathDraw)
{
glutils::Uniform1iByName(m_id,
GLSL_pathBuffer,
kPLSTexIdxOffset + PATH_BUFFER_IDX);
glutils::Uniform1iByName(m_id, GLSL_pathBuffer, PATH_BUFFER_IDX);
}
if (isPathDraw || interlockMode == gpu::InterlockMode::atomics)
{
glutils::Uniform1iByName(m_id,
GLSL_paintBuffer,
kPLSTexIdxOffset + PAINT_BUFFER_IDX);
glutils::Uniform1iByName(m_id, GLSL_paintBuffer, PAINT_BUFFER_IDX);
glutils::Uniform1iByName(m_id,
GLSL_paintAuxBuffer,
kPLSTexIdxOffset + PAINT_AUX_BUFFER_IDX);
PAINT_AUX_BUFFER_IDX);
}
if (isTessellationDraw)
{
glutils::Uniform1iByName(m_id,
GLSL_contourBuffer,
kPLSTexIdxOffset + CONTOUR_BUFFER_IDX);
CONTOUR_BUFFER_IDX);
}
}
if (interlockMode == gpu::InterlockMode::msaa &&
Expand All @@ -1063,7 +1055,7 @@ RenderContextGLImpl::DrawProgram::DrawProgram(
{
glutils::Uniform1iByName(m_id,
GLSL_dstColorTexture,
kPLSTexIdxOffset + DST_COLOR_TEXTURE_IDX);
DST_COLOR_TEXTURE_IDX);
}
if (!renderContextImpl->m_capabilities
.ANGLE_base_vertex_base_instance_shader_builtin)
Expand Down Expand Up @@ -1261,7 +1253,7 @@ void RenderContextGLImpl::flush(const FlushDescriptor& desc)
{
// PowerVR needs an extra little update to the gradient texture to
// help with synchronization.
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + GRAD_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + GRAD_TEXTURE_IDX);
uint32_t nullData = 0;
glTexSubImage2D(GL_TEXTURE_2D,
0,
Expand Down Expand Up @@ -1507,8 +1499,8 @@ void RenderContextGLImpl::flush(const FlushDescriptor& desc)
{
// Set up an internal texture to copy the framebuffer into, for
// in-shader blending.
renderTarget->bindInternalDstTexture(
GL_TEXTURE0 + kPLSTexIdxOffset + DST_COLOR_TEXTURE_IDX);
renderTarget->bindInternalDstTexture(GL_TEXTURE0 +
DST_COLOR_TEXTURE_IDX);
}
}
}
Expand Down Expand Up @@ -1554,7 +1546,7 @@ void RenderContextGLImpl::flush(const FlushDescriptor& desc)
if (auto imageTextureGL =
static_cast<const TextureGLImpl*>(batch.imageTexture))
{
glActiveTexture(GL_TEXTURE0 + kPLSTexIdxOffset + IMAGE_TEXTURE_IDX);
glActiveTexture(GL_TEXTURE0 + IMAGE_TEXTURE_IDX);
glBindTexture(GL_TEXTURE_2D, imageTextureGL->textureID());
}

Expand Down Expand Up @@ -2125,12 +2117,6 @@ std::unique_ptr<RenderContext> RenderContextGLImpl::MakeContext(
// versions are reported as extensions.
if (capabilities.isGLES)
{
if (capabilities.isContextVersionAtLeast(3, 2))
{
// Floating point render targets became core in OpenGL ES 3.2.
capabilities.EXT_color_buffer_half_float = true;
capabilities.EXT_float_blend = true;
}
if (capabilities.isContextVersionAtLeast(3, 1))
{
capabilities.ARB_shader_storage_buffer_object = true;
Expand All @@ -2147,9 +2133,6 @@ std::unique_ptr<RenderContext> RenderContextGLImpl::MakeContext(
capabilities.ARB_shader_storage_buffer_object = true;
}
capabilities.EXT_clip_cull_distance = true;
// Floating point render targets became core in OpenGL 3.0.
capabilities.EXT_color_buffer_half_float = true;
capabilities.EXT_float_blend = true;
}

#ifndef RIVE_WEBGL
Expand Down Expand Up @@ -2241,6 +2224,11 @@ std::unique_ptr<RenderContext> RenderContextGLImpl::MakeContext(
{
capabilities.EXT_float_blend = true;
}
else if (strcmp(ext, "GL_ARB_color_buffer_float") == 0)
{
capabilities.EXT_color_buffer_half_float = true;
capabilities.EXT_float_blend = true;
}
else if (strcmp(ext, "GL_EXT_shader_framebuffer_fetch") == 0)
{
capabilities.EXT_shader_framebuffer_fetch = true;
Expand Down
Loading

0 comments on commit d27fada

Please sign in to comment.