[spline/bezier]Fix compatibility for GLES.

This commit is contained in:
xebra 2017-01-26 22:17:31 +09:00
parent a1ec735f6c
commit 0e6c2b00cf
3 changed files with 126 additions and 65 deletions

View file

@ -148,7 +148,7 @@ DrawEngineGLES::DrawEngineGLES()
InitDeviceObjects();
register_gl_resource_holder(this);
tessDataTransfer = new TessellationDataTransferGLES();
tessDataTransfer = new TessellationDataTransferGLES(!gl_extensions.IsGLES && gl_extensions.VersionGEThan(3, 0, 0));
}
DrawEngineGLES::~DrawEngineGLES() {
@ -1119,54 +1119,96 @@ bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const {
}
void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) {
#ifdef USING_GLES2
#define GL_TEXTURE_1D GL_TEXTURE_2D
#define glTexImage1D(t, l, ifmt, w, br, fmt, type, p) glTexImage2D(t, l, ifmt, w, 1, br, fmt, type, p)
#define glTexSubImage1D(t, l, xo, w, fmt, type, p) glTexSubImage2D(t, l, xo, 0, w, 1, fmt, type, p)
#endif
// Position
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_1D, data_tex[0]);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (prevSize < size) {
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB32F, size, 0, GL_RGB, GL_FLOAT, (GLfloat*)pos);
prevSize = size;
} else {
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, size, GL_RGB, GL_FLOAT, (GLfloat*)pos);
}
// Texcoords
if (hasTexCoords) {
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_1D, data_tex[1]);
if (isAllowTexture1D) {
// Position
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_1D, data_tex[0]);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (prevSizeTex < size) {
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB32F, size, 0, GL_RGB, GL_FLOAT, (GLfloat*)tex);
prevSizeTex = size;
if (prevSize < size) {
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB32F, size, 0, GL_RGB, GL_FLOAT, (GLfloat*)pos);
prevSize = size;
} else {
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, size, GL_RGB, GL_FLOAT, (GLfloat*)tex);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, size, GL_RGB, GL_FLOAT, (GLfloat*)pos);
}
}
// Color
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_1D, data_tex[2]);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int sizeColor = hasColor ? size : 1;
if (prevSizeCol < sizeColor) {
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, sizeColor, 0, GL_RGBA, GL_FLOAT, (GLfloat*)col);
prevSizeCol = sizeColor;
// Texcoords
if (hasTexCoords) {
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_1D, data_tex[1]);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (prevSizeTex < size) {
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB32F, size, 0, GL_RGB, GL_FLOAT, (GLfloat*)tex);
prevSizeTex = size;
} else {
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, size, GL_RGB, GL_FLOAT, (GLfloat*)tex);
}
}
// Color
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_1D, data_tex[2]);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int sizeColor = hasColor ? size : 1;
if (prevSizeCol < sizeColor) {
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA32F, sizeColor, 0, GL_RGBA, GL_FLOAT, (GLfloat*)col);
prevSizeCol = sizeColor;
} else {
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, sizeColor, GL_RGBA, GL_FLOAT, (GLfloat*)col);
}
} else {
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, sizeColor, GL_RGBA, GL_FLOAT, (GLfloat*)col);
// Position
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, data_tex[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (prevSize < size) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, size, 1, 0, GL_RGB, GL_FLOAT, (GLfloat*)pos);
prevSize = size;
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, 1, GL_RGB, GL_FLOAT, (GLfloat*)pos);
}
// Texcoords
if (hasTexCoords) {
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, data_tex[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (prevSizeTex < size) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, size, 1, 0, GL_RGB, GL_FLOAT, (GLfloat*)tex);
prevSizeTex = size;
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size, 1, GL_RGB, GL_FLOAT, (GLfloat*)tex);
}
}
// Color
glActiveTexture(GL_TEXTURE5);
glBindTexture(GL_TEXTURE_2D, data_tex[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int sizeColor = hasColor ? size : 1;
if (prevSizeCol < sizeColor) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, sizeColor, 1, 0, GL_RGBA, GL_FLOAT, (GLfloat*)col);
prevSizeCol = sizeColor;
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, sizeColor, 1, GL_RGBA, GL_FLOAT, (GLfloat*)col);
}
}
glActiveTexture(GL_TEXTURE0);

View file

@ -247,8 +247,9 @@ private:
class TessellationDataTransferGLES : public TessellationDataTransfer {
private:
int data_tex[3];
bool isAllowTexture1D;
public:
TessellationDataTransferGLES() : TessellationDataTransfer(), data_tex() {
TessellationDataTransferGLES(bool isAllowTexture1D) : TessellationDataTransfer(), data_tex(), isAllowTexture1D(isAllowTexture1D) {
glGenTextures(3, (GLuint*)data_tex);
}
~TessellationDataTransferGLES() {

View file

@ -105,6 +105,8 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
const char *varying = "varying";
const char *attribute = "attribute";
const char * const * boneWeightDecl = boneWeightAttrDecl;
const char *texelFetch = NULL;
bool isAllowTexture1D = false;
bool highpFog = false;
bool highpTexcoord = false;
@ -112,8 +114,13 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
if (gstate_c.featureFlags & GPU_SUPPORTS_GLSL_ES_300) {
WRITE(p, "#version 300 es\n");
glslES30 = true;
texelFetch = "texelFetch";
} else {
WRITE(p, "#version 100\n"); // GLSL ES 1.0
if (gl_extensions.EXT_gpu_shader4) {
WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n");
texelFetch = "texelFetch2D";
}
}
WRITE(p, "precision highp float;\n");
@ -126,10 +133,21 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
if (gl_extensions.VersionGEThan(3, 3, 0)) {
glslES30 = true;
WRITE(p, "#version 330\n");
texelFetch = "texelFetch";
isAllowTexture1D = true;
} else if (gl_extensions.VersionGEThan(3, 0, 0)) {
WRITE(p, "#version 130\n");
if (gl_extensions.EXT_gpu_shader4) {
WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n");
texelFetch = "texelFetch";
isAllowTexture1D = true;
}
} else {
WRITE(p, "#version 110\n");
if (gl_extensions.EXT_gpu_shader4) {
WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n");
texelFetch = "texelFetch2D";
}
}
}
@ -327,7 +345,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
// Hardware tessellation
if (doBezier || doSpline) {
const char *sampler = gl_extensions.IsGLES ? "sampler2D" : "sampler1D";
const char *sampler = !isAllowTexture1D ? "sampler2D" : "sampler1D";
WRITE(p, "uniform %s u_tess_pos_tex;\n", sampler);
WRITE(p, "uniform %s u_tess_tex_tex;\n", sampler);
WRITE(p, "uniform %s u_tess_col_tex;\n", sampler);
@ -355,31 +373,31 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
WRITE(p, "void spline_knot(ivec2 num_patches, ivec2 type, out vec2 knot[6], ivec2 patch_pos) {\n");
WRITE(p, " for (int i = 0; i < 6; ++i) {\n");
WRITE(p, " knot[i] = vec2(i + patch_pos.x - 2, i + patch_pos.y - 2);\n");
WRITE(p, " knot[i] = vec2(float(i + patch_pos.x - 2), float(i + patch_pos.y - 2));\n");
WRITE(p, " }\n");
WRITE(p, " if ((type.x & 1) != 0) {\n");
WRITE(p, " if (patch_pos.x <= 2)\n");
WRITE(p, " knot[0].x = 0;\n");
WRITE(p, " knot[0].x = 0.0;\n");
WRITE(p, " if (patch_pos.x <= 1)\n");
WRITE(p, " knot[1].x = 0;\n");
WRITE(p, " knot[1].x = 0.0;\n");
WRITE(p, " }\n");
WRITE(p, " if ((type.x & 2) != 0) {\n");
WRITE(p, " if (patch_pos.x >= (num_patches.x - 2))\n");
WRITE(p, " knot[5].x = num_patches.x;\n");
WRITE(p, " knot[5].x = float(num_patches.x);\n");
WRITE(p, " if (patch_pos.x == (num_patches.x - 1))\n");
WRITE(p, " knot[4].x = num_patches.x;\n");
WRITE(p, " knot[4].x = float(num_patches.x);\n");
WRITE(p, " }\n");
WRITE(p, " if ((type.y & 1) != 0) {\n");
WRITE(p, " if (patch_pos.y <= 2)\n");
WRITE(p, " knot[0].y = 0;\n");
WRITE(p, " knot[0].y = 0.0;\n");
WRITE(p, " if (patch_pos.y <= 1)\n");
WRITE(p, " knot[1].y = 0;\n");
WRITE(p, " knot[1].y = 0.0;\n");
WRITE(p, " }\n");
WRITE(p, " if ((type.y & 2) != 0) {\n");
WRITE(p, " if (patch_pos.y >= (num_patches.y - 2))\n");
WRITE(p, " knot[5].y = num_patches.y;\n");
WRITE(p, " knot[5].y = float(num_patches.y);\n");
WRITE(p, " if (patch_pos.y == (num_patches.y - 1))\n");
WRITE(p, " knot[4].y = num_patches.y;\n");
WRITE(p, " knot[4].y = float(num_patches.y);\n");
WRITE(p, " }\n");
WRITE(p, "}\n");
@ -449,18 +467,18 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
WRITE(p, " vec2 _tex[16];\n");
WRITE(p, " vec4 _col[16];\n");
WRITE(p, " int num_patches_u = %s;\n", doBezier ? "(u_spline_count_u - 1) / 3" : "u_spline_count_u - 3");
WRITE(p, " int u = int(mod(gl_InstanceID, num_patches_u));\n");
WRITE(p, " int v = (gl_InstanceID / num_patches_u);\n");
WRITE(p, " int u = int(mod(float(gl_InstanceID), float(num_patches_u)));\n");
WRITE(p, " int v = gl_InstanceID / num_patches_u;\n");
WRITE(p, " ivec2 patch_pos = ivec2(u, v);\n");
WRITE(p, " for (int i = 0; i < 4; i++) {\n");
WRITE(p, " for (int j = 0; j < 4; j++) {\n");
WRITE(p, " int index = (i + v%s) * u_spline_count_u + (j + u%s);\n", doBezier ? " * 3" : "", doBezier ? " * 3" : "");
const char *index = gl_extensions.IsGLES ? "ivec2(index, 0)" : "index";
WRITE(p, " _pos[i * 4 + j] = texelFetch(u_tess_pos_tex, %s, 0).xyz;\n", index);
const char *index = !isAllowTexture1D ? "ivec2(index, 0)" : "index";
WRITE(p, " _pos[i * 4 + j] = %s(u_tess_pos_tex, %s, 0).xyz;\n", texelFetch, index);
if (doTexture && hasTexcoord && hasTexcoordTess)
WRITE(p, " _tex[i * 4 + j] = texelFetch(u_tess_tex_tex, %s, 0).xy;\n", index);
WRITE(p, " _tex[i * 4 + j] = %s(u_tess_tex_tex, %s, 0).xy;\n", texelFetch, index);
if (hasColor && hasColorTess)
WRITE(p, " _col[i * 4 + j] = texelFetch(u_tess_col_tex, %s, 0).rgba;\n", index);
WRITE(p, " _col[i * 4 + j] = %s(u_tess_col_tex, %s, 0).rgba;\n", texelFetch, index);
WRITE(p, " }\n");
WRITE(p, " }\n");
WRITE(p, " vec2 tess_pos = position.xy;\n");
@ -476,20 +494,20 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
WRITE(p, " ivec2 spline_type = ivec2(u_spline_type_u, u_spline_type_v);\n");
WRITE(p, " vec2 knots[6];\n");
WRITE(p, " spline_knot(spline_num_patches, spline_type, knots, patch_pos);\n");
WRITE(p, " spline_weight(tess_pos + patch_pos, knots, weights);\n");
WRITE(p, " spline_weight(tess_pos + vec2(patch_pos), knots, weights);\n");
}
WRITE(p, " vec3 pos = tess_sample(_pos, weights);\n");
if (doTexture && hasTexcoord) {
if (hasTexcoordTess)
WRITE(p, " vec2 tex = tess_sample(_tex, weights);\n");
else
WRITE(p, " vec2 tex = tess_pos + patch_pos;\n");
WRITE(p, " vec2 tex = tess_pos + vec2(patch_pos);\n");
}
if (hasColor) {
if (hasColorTess)
WRITE(p, " vec4 col = tess_sample(_col, weights);\n");
else
WRITE(p, " vec4 col = texelFetch(u_tess_col_tex, %s, 0).rgba;\n", gl_extensions.IsGLES ? "ivec2(0, 0)" : "0");
WRITE(p, " vec4 col = %s(u_tess_col_tex, %s, 0).rgba;\n", texelFetch, !isAllowTexture1D ? "ivec2(0, 0)" : "0");
}
if (hasNormal) {
// Curved surface is probably always need to compute normal(not sampling from control points)
@ -515,19 +533,19 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) {
WRITE(p, " vec2 tess_next_v = vec2(0.0, normal.y);\n");
// Right
WRITE(p, " vec2 tess_pos_r = tess_pos + tess_next_u;\n");
WRITE(p, " spline_weight(tess_pos_r + patch_pos, knots, weights);\n");
WRITE(p, " spline_weight(tess_pos_r + vec2(patch_pos), knots, weights);\n");
WRITE(p, " vec3 pos_r = tess_sample(_pos, weights);\n");
// Left
WRITE(p, " vec2 tess_pos_l = tess_pos - tess_next_u;\n");
WRITE(p, " spline_weight(tess_pos_l + patch_pos, knots, weights);\n");
WRITE(p, " spline_weight(tess_pos_l + vec2(patch_pos), knots, weights);\n");
WRITE(p, " vec3 pos_l = tess_sample(_pos, weights);\n");
// Down
WRITE(p, " vec2 tess_pos_d = tess_pos + tess_next_v;\n");
WRITE(p, " spline_weight(tess_pos_d + patch_pos, knots, weights);\n");
WRITE(p, " spline_weight(tess_pos_d + vec2(patch_pos), knots, weights);\n");
WRITE(p, " vec3 pos_d = tess_sample(_pos, weights);\n");
// Up
WRITE(p, " vec2 tess_pos_u = tess_pos - tess_next_v;\n");
WRITE(p, " spline_weight(tess_pos_u + patch_pos, knots, weights);\n");
WRITE(p, " spline_weight(tess_pos_u + vec2(patch_pos), knots, weights);\n");
WRITE(p, " vec3 pos_u = tess_sample(_pos, weights);\n");
WRITE(p, " vec3 du = pos_r - pos_l;\n");