Skip to content

Commit

Permalink
Merge pull request #9242 from xebra/hw_tess_gles3
Browse files Browse the repository at this point in the history
Fix #9240
  • Loading branch information
hrydgard committed Jan 27, 2017
2 parents a1ec735 + a460acf commit bf104f1
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 66 deletions.
128 changes: 86 additions & 42 deletions GPU/GLES/DrawEngineGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ DrawEngineGLES::DrawEngineGLES()
InitDeviceObjects();
register_gl_resource_holder(this);

tessDataTransfer = new TessellationDataTransferGLES();
tessDataTransfer = new TessellationDataTransferGLES(gl_extensions.VersionGEThan(3, 0, 0));
}

DrawEngineGLES::~DrawEngineGLES() {
Expand Down Expand Up @@ -1119,55 +1119,99 @@ 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);
}
#ifndef USING_GLES2
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 (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]);
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);
}
}

// Texcoords
if (hasTexCoords) {
glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_1D, data_tex[1]);
// 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);
if (prevSizeTex < size) {
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB32F, size, 0, GL_RGB, GL_FLOAT, (GLfloat*)tex);
prevSizeTex = size;
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, size, GL_RGB, GL_FLOAT, (GLfloat*)tex);
glTexSubImage1D(GL_TEXTURE_1D, 0, 0, sizeColor, GL_RGBA, GL_FLOAT, (GLfloat*)col);
}
} else
#endif
{
// 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);
}
}

// 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);
}
// 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);
}
3 changes: 2 additions & 1 deletion GPU/GLES/DrawEngineGLES.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,9 @@ class DrawEngineGLES : public DrawEngineCommon, public GfxResourceHolder {
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() {
Expand Down
64 changes: 41 additions & 23 deletions GPU/GLES/VertexShaderGeneratorGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,22 @@ 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;

if (gl_extensions.IsGLES) {
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");

Expand All @@ -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";
}
}
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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");
Expand All @@ -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)
Expand All @@ -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");
Expand Down

0 comments on commit bf104f1

Please sign in to comment.