gl4es icon indicating copy to clipboard operation
gl4es copied to clipboard

Skia shader cause a compilation error

Open afxgroup opened this issue 6 months ago • 4 comments

I'm trying to use Skia library with GL4ES. If shaders are not involved everything seems to work while once a shader is involved an compilation error occur. This is the shader created by GL4ES:

#version 110
#extension GL_EXT_shader_non_constant_global_initializers : enable
precision highp float;
float dFdx(float p) {return 0.0001;}
vec2 dFdx(vec2 p) {return vec2(0.0001);}
float clamp(float f, int a, int b) {
 return clamp(f, float(a), float(b));
}
float clamp(float f, float a, int b) {
 return clamp(f, a, float(b));
}
float clamp(float f, int a, float b) {
 return clamp(f, float(a), b);
}
vec2 clamp(vec2 f, int a, int b) {
 return clamp(f, float(a), float(b));
}
vec2 clamp(vec2 f, float a, int b) {
 return clamp(f, a, float(b));
}
vec2 clamp(vec2 f, int a, float b) {
 return clamp(f, float(a), b);
}
vec3 clamp(vec3 f, int a, int b) {
 return clamp(f, float(a), float(b));
}
vec3 clamp(vec3 f, float a, int b) {
 return clamp(f, a, float(b));
}
vec3 clamp(vec3 f, int a, float b) {
 return clamp(f, float(a), b);
}
vec4 clamp(vec4 f, int a, int b) {
 return clamp(f, float(a), float(b));
}
vec4 clamp(vec4 f, float a, int b) {
 return clamp(f, a, float(b));
}
vec4 clamp(vec4 f, int a, float b) {
 return clamp(f, float(a), b);
}
vec3 dFdx(vec3 p) {return vec3(0.0001);}
float dFdy(float p) {return 0.0001;}
vec2 dFdy(vec2 p) {return vec2(0.0001);}
vec3 dFdy(vec3 p) {return vec3(0.0001);}
float fwidth(float p) {return abs(dFdx(p))+abs(dFdy(p));}
vec2 fwidth(vec2 p) {return abs(dFdx(p))+abs(dFdy(p));}
vec3 fwidth(vec3 p) {return abs(dFdx(p))+abs(dFdy(p));}
#define GL4ES
precision highp int;


varying vec4 vcolor_S0;
varying vec2 varccoord_S0;
void main() {
	vec4 outputColor_S0 = vcolor_S0;
	float x_plus_1 = varccoord_S0.x;
	float y = varccoord_S0.y;
	float coverage;
	if (0.00000 == x_plus_1) {
		coverage = y;
	} else {
		float fn = x_plus_1 * (x_plus_1 - 2.00000);
		fn = ((y) * (y) + (fn));
		float fnwidth = fwidth(fn);
		coverage = 0.500000 - fn / fnwidth;
		coverage = clamp(coverage, 0.00000, 1.00000);
	}
	coverage = float(coverage >= 0.500000);
	vec4 outputCoverage_S0 = vec4(coverage);
	{
		gl_FragColor = outputColor_S0 * outputCoverage_S0;
	}
}

You can try it here:

https://shader-playground.timjones.io/82f451461cb682120eece7c3aa6094f7

This is the code i'm using as test:

#include "GLFW/glfw3.h"
#define SK_GANESH
#define SK_GL
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/gl/GrGLDirectContext.h"
#include "include/gpu/ganesh/gl/GrGLInterface.h"
#include "include/gpu/ganesh/gl/GrGLAssembleInterface.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkSurface.h"
#include "include/core/SkFont.h"

#include <stdio.h>
#include <stdlib.h>

//uncomment the two lines below to enable correct color spaces
//#define GL_FRAMEBUFFER_SRGB 0x8DB9
//#define GL_SRGB8_ALPHA8 0x8C43

GrDirectContext* sContext = nullptr;
SkSurface* sSurface = nullptr;

void error_callback(int error, const char* description) {
        fputs(description, stderr);
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) {
        if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
                glfwSetWindowShouldClose(window, GL_TRUE);
}

void init_skia(int w, int h) {
        auto interface = GrGLMakeNativeInterface();
        if (interface == nullptr) {
                //backup plan. see https://gist.github.com/ad8e/dd150b775ae6aa4d5cf1a092e4713add?permalink_comment_id=4680136#gistcomment-4680136
                interface = GrGLMakeAssembledInterface(
                        nullptr, (GrGLGetProc) * [](void*, const char* p) -> void* { return (void*)glfwGetProcAddress(p); });
        }
        sContext = GrDirectContexts::MakeGL(interface).release();

        GrGLFramebufferInfo framebufferInfo;
        framebufferInfo.fFBOID = 0; // assume default framebuffer
        // We are always using OpenGL and we use RGBA8 internal format for both RGBA and BGRA configs in OpenGL.
        //(replace line below with this one to enable correct color spaces) framebufferInfo.fFormat = GL_SRGB8_ALPHA8;
        framebufferInfo.fFormat = GL_RGBA8;

        SkColorType colorType = kRGBA_8888_SkColorType;
        GrBackendRenderTarget backendRenderTarget = GrBackendRenderTargets::MakeGL(w, h,
                0, // sample count
                0, // stencil bits
                framebufferInfo);

        //(replace line below with this one to enable correct color spaces) sSurface = SkSurfaces::WrapBackendRenderTarget(sContext, backendRenderTarget>
        sSurface = SkSurfaces::WrapBackendRenderTarget(sContext, backendRenderTarget, kBottomLeft_GrSurfaceOrigin, colorType, nullptr, nullptr).release(>
        if (sSurface == nullptr) abort();
}

void cleanup_skia() {
        delete sSurface;
        delete sContext;
}

const int kWidth = 960;
const int kHeight = 640;

int main(void) {
        GLFWwindow* window;
        glfwSetErrorCallback(error_callback);
        if (!glfwInit()) {
                exit(EXIT_FAILURE);
        }

        //glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
        //glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
        //glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
        //glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        //(uncomment to enable correct color spaces) glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);
        glfwWindowHint(GLFW_STENCIL_BITS, 0);
        //glfwWindowHint(GLFW_ALPHA_BITS, 0);
        glfwWindowHint(GLFW_DEPTH_BITS, 0);

        window = glfwCreateWindow(kWidth, kHeight, "Simple example", NULL, NULL);
        if (!window) {
                glfwTerminate();
                exit(EXIT_FAILURE);
        }
        glfwMakeContextCurrent(window);
        //(uncomment to enable correct color spaces) glEnable(GL_FRAMEBUFFER_SRGB);

        init_skia(kWidth, kHeight);

        glfwSwapInterval(1);
        glfwSetKeyCallback(window, key_callback);
        // Draw to the surface via its SkCanvas.
        SkCanvas* canvas = sSurface->getCanvas(); // We don't manage this pointer's lifetime.
        SkFont font; 
        font.setSize(24);

        while (!glfwWindowShouldClose(window)) {
                glfwWaitEvents();
                SkPaint paint;
                paint.setColor(SK_ColorWHITE);
                canvas->drawPaint(paint);
                paint.setColor(SK_ColorBLUE);
                canvas->drawRect({100, 200, 300, 500}, paint);
                canvas->drawCircle(100, 100, 64, paint);
                canvas->drawString("Hello AmigaOS4! We are working hard!", 10, 20, font, paint);
                sContext->flush();

                glfwSwapBuffers(window);
        }

        cleanup_skia();

        glfwDestroyWindow(window);
        glfwTerminate();
        exit(EXIT_SUCCESS);
}

If you comment the drawString you will not have any error

afxgroup avatar Jun 20 '25 07:06 afxgroup

Do you have the compilation error mesdsage?

ptitSeb avatar Jun 20 '25 07:06 ptitSeb

ERROR: 3:1: 'redefinition of built-in function' : not supported with this profile: es
ERROR: 3:1: 'highp' : overloaded functions must have the same parameter precision qualifiers for argument 1
ERROR: 74:0: '' : compilation terminated 
ERROR: 3 compilation errors.  No code generated.

afxgroup avatar Jun 20 '25 07:06 afxgroup

Any idea?

afxgroup avatar Jun 24 '25 12:06 afxgroup

Hey, sorry, I was busy with some other projects.

It's strange there is a redefinition there.

It's like it doesn like precision highp float; (wich is valid), or if it doesn't like it after #extension GL_EXT_shader_non_constant_global_initializers : enable maybe?

ptitSeb avatar Jun 24 '25 15:06 ptitSeb