From 0e6c2b00cf5ebc214e0e54288714653fe31fe4ea Mon Sep 17 00:00:00 2001 From: xebra Date: Thu, 26 Jan 2017 22:17:31 +0900 Subject: [PATCH] [spline/bezier]Fix compatibility for GLES. --- GPU/GLES/DrawEngineGLES.cpp | 124 +++++++++++++++++-------- GPU/GLES/DrawEngineGLES.h | 3 +- GPU/GLES/VertexShaderGeneratorGLES.cpp | 64 ++++++++----- 3 files changed, 126 insertions(+), 65 deletions(-) diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index a4deeb4a0e..7f5bb85f80 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -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); diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index f085fe40f8..87016aca8a 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -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() { diff --git a/GPU/GLES/VertexShaderGeneratorGLES.cpp b/GPU/GLES/VertexShaderGeneratorGLES.cpp index e6e99b9c6a..5ac1cd88c4 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.cpp +++ b/GPU/GLES/VertexShaderGeneratorGLES.cpp @@ -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");