processing / p5.js

p5.js is a client-side JS platform that empowers artists, designers, students, and anyone to learn to code and express themselves creatively on the web. It is based on the core principles of Processing. http://twitter.com/p5xjs —
http://p5js.org/
GNU Lesser General Public License v2.1
21.7k stars 3.34k forks source link

Line shaders not working on Chrome/Linux #6386

Open davepagurek opened 1 year ago

davepagurek commented 1 year ago

Most appropriate sub-area of p5.js?

p5.js version

1.7.0

Web browser and version

Chrome 108

Operating System

Amazon Linux

Steps to reproduce this

At work we do some cloud rendering of p5 via Chome/Puppeteer in AWS Batch. I noticed that WebGL lines were not showing up in our cloud exports (left) compared to in-browser on Chrome for Mac (right):

image

This is a screenshot of chrome://gpu from the cloud environment (click to expand):

We were able to fix our issue by changing the precision in the line vertex/fragment shader to be highp instead of mediump: https://github.com/processing/p5.js/blob/45ada83739efa51f6747fc037e95d4b7eb9b351f/src/webgl/shaders/line.vert#L21-L22

As I only have access to my Mac locally, what I don't know is if this is an issue with our setup on AWS or if this is a general issue on Linux. Is anyone else able to run this on Chrome for Linux and let me know if the line renders for you or not? If this is a general issue, then maybe we should update the line shader. But it might be a bug specifically in the drivers for this environment.

Snippet:

function setup() {
  createCanvas(400, 400, WEBGL);
}

function draw() {
  background(220);
  noFill();
  strokeWeight(5);
  bezier(
    -100, 100,
    -50, -100,
    50, -100,
    100, 100
  );
}

Live: https://editor.p5js.org/davepagurek/sketches/rhLpTaCeX

limzykenneth commented 1 year ago

I'll have access to my Linux machine by end of next week and can help test this if no one else get to this before then. Just ping me in case I forgot.

davepagurek commented 1 year ago

Thanks @limzykenneth!

asukaminato0721 commented 1 year ago

image

Brave 1.57.57 Chromium: 116.0.5845.163 (Official Build) (64-bit)
Revision d85db1f5df3b20ffecf96ab3f0dc7fca1d536955
OS Linux
JavaScript V8 11.6.189.19
davepagurek commented 1 year ago

Thanks @asukaminato0721! Looks like this may be a very specific driver bug then. I'm going to close this issue, but in case anyone else needs to work around this for their specific setup, I added this chunk of code to use highp precision lines:

const prevGetLineShader = p5.RendererGL.prototype._getLineShader
p5.RendererGL.prototype._getLineShader = function () {
  if (!this._defaultLineShader) {
    this._defaultLineShader = prevGetLineShader.call(this)
    this._defaultLineShader._vertSrc = this._defaultLineShader._vertSrc.replace(
      /mediump/g,
      'highp',
    )
    this._defaultLineShader._fragSrc = this._defaultLineShader._fragSrc.replace(
      /mediump/g,
      'highp',
    )
  }

  return this._defaultLineShader
}
davepagurek commented 10 months ago

Hey, little update to this: since https://github.com/processing/p5.js/commit/7cf062dc65204592d210041663e8d6a0cc468b5c I've been finding that on AWS linux, the color shader also doesn't work reliably, and shapes are disappearing. This definitely feels like a driver bug, and the combination of using GL ES 300 + mediump precision is causing it to break. The solution for me was to adapt the above comment to just replace mediump with highp everywhere:

const shadersToReplace = [
  ['_getImmediateModeShader', '_defaultImmediateModeShader'],
  ['_getNormalShader', '_defaultNormalShader'],
  ['_getColorShader', '_defaultColorShader'],
  ['_getPointShader', '_defaultPointShader'],
  ['_getLineShader', '_defaultLineShader'],
  ['_getFontShader', '_defaultFontShader'],
]

for (const [method, cacheKey] of shadersToReplace) {
  const prevMethod = P5.RendererGL.prototype[method]
  p5.RendererGL.prototype[method] = function () {
    if (!this[cacheKey]) {
      this[cacheKey] = prevMethod.call(this)
      this[cacheKey]._vertSrc = this[cacheKey]._vertSrc.replace(
        /mediump/g,
        'highp',
      )
      this[cacheKey]._fragSrc = this[cacheKey]._fragSrc.replace(
        /mediump/g,
        'highp',
      )
    }

    return this[cacheKey]
  }
}

At least for this use case of mine of cloud exports, a way to tell p5 to use highp everywhere would be useful. Has anyone else encountered anything similar?

I think when I asked before if this is reproducible on Linux, that might not have been enough, since most? all? desktop drivers ignore mediump and use highp. Maybe we should be testing this on mobile to see if we notice anything, since that's typically where shader precision actually does something?