mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Use glBindAttribLocation to simplify shader usage a little.
This commit is contained in:
parent
df29da0b13
commit
0ecac31abd
@ -44,7 +44,7 @@ Shader::Shader(const char *code, uint32_t shaderType, bool useHWTransform) : fai
|
||||
OutputDebugStringUTF8(code);
|
||||
#endif
|
||||
shader = glCreateShader(shaderType);
|
||||
glShaderSource(shader, 1, &code, 0);
|
||||
glShaderSource(shader, 1, &code, 0);
|
||||
glCompileShader(shader);
|
||||
GLint success;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||
@ -73,13 +73,35 @@ Shader::~Shader() {
|
||||
glDeleteShader(shader);
|
||||
}
|
||||
|
||||
static int glGetAttribLocationL(int program, const char *name) {
|
||||
int attrLoc = glGetAttribLocation(program, name);
|
||||
ERROR_LOG(HLE, "Attr Loc: %i %i %s", program, attrLoc, name);
|
||||
return attrLoc;
|
||||
}
|
||||
|
||||
LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTransform)
|
||||
: useHWTransform_(useHWTransform), program(0), dirtyUniforms(0) {
|
||||
program = glCreateProgram();
|
||||
|
||||
glAttachShader(program, vs->shader);
|
||||
glAttachShader(program, fs->shader);
|
||||
|
||||
// Bind attribute locations to fixed locations so that they're
|
||||
// the same in all shaders. We can use this later to minimize the calls to
|
||||
// glEnableVertexAttribArray and glDisableVertexAttribArray.
|
||||
glBindAttribLocation(program, ATTR_POSITION, "a_position");
|
||||
glBindAttribLocation(program, ATTR_TEXCOORD, "a_texcoord");
|
||||
glBindAttribLocation(program, ATTR_NORMAL, "a_normal");
|
||||
glBindAttribLocation(program, ATTR_W1, "a_w1");
|
||||
glBindAttribLocation(program, ATTR_W2, "a_w2");
|
||||
glBindAttribLocation(program, ATTR_COLOR0, "a_color0");
|
||||
glBindAttribLocation(program, ATTR_COLOR1, "a_color1");
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
glDetachShader(program, vs->shader);
|
||||
glDetachShader(program, fs->shader);
|
||||
|
||||
GLint linkStatus = GL_FALSE;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
|
||||
if (linkStatus != GL_TRUE) {
|
||||
@ -162,13 +184,16 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans
|
||||
u_lightspecular[i] = glGetUniformLocation(program, temp);
|
||||
}
|
||||
|
||||
a_position = glGetAttribLocation(program, "a_position");
|
||||
a_color0 = glGetAttribLocation(program, "a_color0");
|
||||
a_color1 = glGetAttribLocation(program, "a_color1");
|
||||
a_texcoord = glGetAttribLocation(program, "a_texcoord");
|
||||
a_normal = glGetAttribLocation(program, "a_normal");
|
||||
a_weight0123 = glGetAttribLocation(program, "a_w1");
|
||||
a_weight4567 = glGetAttribLocation(program, "a_w2");
|
||||
attrMask = 0;
|
||||
if (-1 != glGetAttribLocationL(program, "a_position")) attrMask |= 1 << ATTR_POSITION;
|
||||
if (-1 != glGetAttribLocationL(program, "a_texcoord")) attrMask |= 1 << ATTR_TEXCOORD;
|
||||
if (-1 != glGetAttribLocationL(program, "a_normal")) attrMask |= 1 << ATTR_NORMAL;
|
||||
if (-1 != glGetAttribLocationL(program, "a_w1")) attrMask |= 1 << ATTR_W1;
|
||||
if (-1 != glGetAttribLocationL(program, "a_w2")) attrMask |= 1 << ATTR_W2;
|
||||
if (-1 != glGetAttribLocationL(program, "a_color0")) attrMask |= 1 << ATTR_COLOR0;
|
||||
if (-1 != glGetAttribLocationL(program, "a_color1")) attrMask |= 1 << ATTR_COLOR1;
|
||||
|
||||
ELOG("AttrMask: %02x", attrMask);
|
||||
|
||||
glUseProgram(program);
|
||||
|
||||
@ -262,23 +287,19 @@ static void SetMatrix4x3(int uniform, const float *m4x3) {
|
||||
void LinkedShader::use(u32 vertType) {
|
||||
glUseProgram(program);
|
||||
updateUniforms(vertType);
|
||||
glEnableVertexAttribArray(a_position);
|
||||
if (a_texcoord != -1) glEnableVertexAttribArray(a_texcoord);
|
||||
if (a_color0 != -1) glEnableVertexAttribArray(a_color0);
|
||||
if (a_color1 != -1) glEnableVertexAttribArray(a_color1);
|
||||
if (a_normal != -1) glEnableVertexAttribArray(a_normal);
|
||||
if (a_weight0123 != -1) glEnableVertexAttribArray(a_weight0123);
|
||||
if (a_weight4567 != -1) glEnableVertexAttribArray(a_weight4567);
|
||||
glEnableVertexAttribArray(0);
|
||||
for (int i = 1; i < ATTR_COUNT; i++) {
|
||||
if (attrMask & (1 << i))
|
||||
glEnableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
|
||||
void LinkedShader::stop() {
|
||||
glDisableVertexAttribArray(a_position);
|
||||
if (a_texcoord != -1) glDisableVertexAttribArray(a_texcoord);
|
||||
if (a_color0 != -1) glDisableVertexAttribArray(a_color0);
|
||||
if (a_color1 != -1) glDisableVertexAttribArray(a_color1);
|
||||
if (a_normal != -1) glDisableVertexAttribArray(a_normal);
|
||||
if (a_weight0123 != -1) glDisableVertexAttribArray(a_weight0123);
|
||||
if (a_weight4567 != -1) glDisableVertexAttribArray(a_weight4567);
|
||||
glDisableVertexAttribArray(0);
|
||||
for (int i = 1; i < ATTR_COUNT; i++) {
|
||||
if (attrMask & (1 << i))
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
|
||||
void LinkedShader::updateUniforms(u32 vertType) {
|
||||
@ -331,10 +352,10 @@ void LinkedShader::updateUniforms(u32 vertType) {
|
||||
if (gstate.isModeThrough()) {
|
||||
// We never get here because we don't use HW transform with through mode.
|
||||
// Although - why don't we?
|
||||
uvscaleoff[0] = gstate_c.uv.uScale / gstate_c.curTextureWidth;
|
||||
uvscaleoff[1] = gstate_c.uv.vScale / gstate_c.curTextureHeight;
|
||||
uvscaleoff[2] = gstate_c.uv.uOff / gstate_c.curTextureWidth;
|
||||
uvscaleoff[3] = gstate_c.uv.vOff / gstate_c.curTextureHeight;
|
||||
uvscaleoff[0] = gstate_c.uv.uScale / (float)gstate_c.curTextureWidth;
|
||||
uvscaleoff[1] = gstate_c.uv.vScale / (float)gstate_c.curTextureHeight;
|
||||
uvscaleoff[2] = gstate_c.uv.uOff / (float)gstate_c.curTextureWidth;
|
||||
uvscaleoff[3] = gstate_c.uv.vOff / (float)gstate_c.curTextureHeight;
|
||||
glUniform4fv(u_uvscaleoffset, 1, uvscaleoff);
|
||||
} else {
|
||||
int w = gstate.getTextureWidth(0);
|
||||
@ -372,7 +393,6 @@ void LinkedShader::updateUniforms(u32 vertType) {
|
||||
|
||||
// TODO: Could even set all bones in one go if they're all dirty.
|
||||
#ifdef USE_BONE_ARRAY
|
||||
|
||||
if (u_bone != -1) {
|
||||
float allBones[8 * 16];
|
||||
|
||||
|
@ -25,8 +25,20 @@
|
||||
|
||||
class Shader;
|
||||
|
||||
class LinkedShader
|
||||
{
|
||||
// Pre-fetched attrs and uniforms
|
||||
enum {
|
||||
ATTR_POSITION = 0,
|
||||
ATTR_TEXCOORD = 1,
|
||||
ATTR_NORMAL = 2,
|
||||
ATTR_W1 = 3,
|
||||
ATTR_W2 = 4,
|
||||
ATTR_COLOR0 = 5,
|
||||
ATTR_COLOR1 = 6,
|
||||
|
||||
ATTR_COUNT,
|
||||
};
|
||||
|
||||
class LinkedShader {
|
||||
public:
|
||||
LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTransform);
|
||||
~LinkedShader();
|
||||
@ -41,14 +53,8 @@ public:
|
||||
uint32_t program;
|
||||
u32 dirtyUniforms;
|
||||
|
||||
// Pre-fetched attrs and uniforms
|
||||
int a_position;
|
||||
int a_color0;
|
||||
int a_color1;
|
||||
int a_texcoord;
|
||||
int a_normal;
|
||||
int a_weight0123;
|
||||
int a_weight4567;
|
||||
// Present attributes in the shader.
|
||||
int attrMask; // 1 << ATTR_ ... or-ed together.
|
||||
|
||||
int u_tex;
|
||||
int u_proj;
|
||||
@ -63,7 +69,7 @@ public:
|
||||
int u_bone[8];
|
||||
#endif
|
||||
int numBones;
|
||||
|
||||
|
||||
// Fragment processing inputs
|
||||
int u_alphacolorref;
|
||||
int u_colormask;
|
||||
|
@ -329,13 +329,13 @@ static inline void VertexAttribSetup(int attrib, int fmt, int stride, u8 *ptr) {
|
||||
|
||||
// TODO: Use VBO and get rid of the vertexData pointers - with that, we will supply only offsets
|
||||
static void SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt, u8 *vertexData) {
|
||||
VertexAttribSetup(program->a_weight0123, decFmt.w0fmt, decFmt.stride, vertexData + decFmt.w0off);
|
||||
VertexAttribSetup(program->a_weight4567, decFmt.w1fmt, decFmt.stride, vertexData + decFmt.w1off);
|
||||
VertexAttribSetup(program->a_texcoord, decFmt.uvfmt, decFmt.stride, vertexData + decFmt.uvoff);
|
||||
VertexAttribSetup(program->a_color0, decFmt.c0fmt, decFmt.stride, vertexData + decFmt.c0off);
|
||||
VertexAttribSetup(program->a_color1, decFmt.c1fmt, decFmt.stride, vertexData + decFmt.c1off);
|
||||
VertexAttribSetup(program->a_normal, decFmt.nrmfmt, decFmt.stride, vertexData + decFmt.nrmoff);
|
||||
VertexAttribSetup(program->a_position, decFmt.posfmt, decFmt.stride, vertexData + decFmt.posoff);
|
||||
VertexAttribSetup(ATTR_W1, decFmt.w0fmt, decFmt.stride, vertexData + decFmt.w0off);
|
||||
VertexAttribSetup(ATTR_W2, decFmt.w1fmt, decFmt.stride, vertexData + decFmt.w1off);
|
||||
VertexAttribSetup(ATTR_TEXCOORD, decFmt.uvfmt, decFmt.stride, vertexData + decFmt.uvoff);
|
||||
VertexAttribSetup(ATTR_COLOR0, decFmt.c0fmt, decFmt.stride, vertexData + decFmt.c0off);
|
||||
VertexAttribSetup(ATTR_COLOR1, decFmt.c1fmt, decFmt.stride, vertexData + decFmt.c1off);
|
||||
VertexAttribSetup(ATTR_NORMAL, decFmt.nrmfmt, decFmt.stride, vertexData + decFmt.nrmoff);
|
||||
VertexAttribSetup(ATTR_POSITION, decFmt.posfmt, decFmt.stride, vertexData + decFmt.posoff);
|
||||
}
|
||||
|
||||
// The verts are in the order: BR BL TL TR
|
||||
@ -375,7 +375,6 @@ static void RotateUVThrough(TransformedVertex v[4]) {
|
||||
SwapUVs(v[1], v[3]);
|
||||
}
|
||||
|
||||
|
||||
// Clears on the PSP are best done by drawing a series of vertical strips
|
||||
// in clear mode. This tries to detect that.
|
||||
bool TransformDrawEngine::IsReallyAClear(int numVerts) const {
|
||||
@ -395,7 +394,7 @@ bool TransformDrawEngine::IsReallyAClear(int numVerts) const {
|
||||
memcpy(&vcolor, transformed[i].color0, 4);
|
||||
if (vcolor != matchcolor || transformed[i].z != matchz)
|
||||
return false;
|
||||
|
||||
|
||||
if ((i & 1) == 0) {
|
||||
// Top left of a rectangle
|
||||
if (transformed[i].y != 0)
|
||||
@ -598,7 +597,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
uv[1] = vscale * (ruv[1]*gstate_c.uv.vScale + gstate_c.uv.vOff);
|
||||
uv[2] = 1.0f;
|
||||
break;
|
||||
|
||||
|
||||
case GE_TEXMAP_TEXTURE_MATRIX:
|
||||
{
|
||||
// Projection mapping
|
||||
@ -607,11 +606,11 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
case GE_PROJMAP_POSITION: // Use model space XYZ as source
|
||||
source = pos;
|
||||
break;
|
||||
|
||||
|
||||
case GE_PROJMAP_UV: // Use unscaled UV as source
|
||||
source = Vec3f(ruv[0], ruv[1], 0.0f);
|
||||
break;
|
||||
|
||||
|
||||
case GE_PROJMAP_NORMALIZED_NORMAL: // Use normalized normal as source
|
||||
if (reader.hasNormal()) {
|
||||
source = Vec3f(norm).Normalized();
|
||||
@ -620,7 +619,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
source = Vec3f(0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case GE_PROJMAP_NORMAL: // Use non-normalized normal as source!
|
||||
if (reader.hasNormal()) {
|
||||
source = Vec3f(norm);
|
||||
@ -638,7 +637,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
uv[2] = uvw[2];
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case GE_TEXMAP_ENVIRONMENT_MAP:
|
||||
// Shade mapping - use two light sources to generate U and V.
|
||||
{
|
||||
@ -650,15 +649,16 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
uv[2] = 1.0f;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
// Illegal
|
||||
ERROR_LOG_REPORT(G3D, "Impossible UV gen mode? %d", gstate.getUVGenMode());
|
||||
break;
|
||||
}
|
||||
|
||||
uv[0] = uv[0] * widthFactor;
|
||||
uv[1] = uv[1] * heightFactor;
|
||||
|
||||
|
||||
// Transform the coord by the view matrix.
|
||||
Vec3ByMatrix43(v, out, gstate.viewMatrix);
|
||||
fogCoef = (v[2] + fog_end) * fog_slope;
|
||||
@ -765,6 +765,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
// Apparently, non-through RotateUV just breaks things.
|
||||
// If we find a game where it helps, we'll just have to figure out how they differ.
|
||||
// Possibly, it has something to do with flipped viewport Y axis, which a few games use.
|
||||
// One game might be one of the Metal Gear ones, can't find the issue right now though.
|
||||
// else
|
||||
// RotateUV(trans);
|
||||
|
||||
@ -779,19 +780,19 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: Add a post-transform cache here for multi-RECTANGLES only.
|
||||
// Might help for text drawing.
|
||||
|
||||
// these spam the gDebugger log.
|
||||
const int vertexSize = sizeof(transformed[0]);
|
||||
|
||||
|
||||
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glVertexAttribPointer(program->a_position, 4, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer);
|
||||
if (program->a_texcoord != -1) glVertexAttribPointer(program->a_texcoord, doTextureProjection ? 3 : 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 4 * 4);
|
||||
if (program->a_color0 != -1) glVertexAttribPointer(program->a_color0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 7 * 4);
|
||||
if (program->a_color1 != -1) glVertexAttribPointer(program->a_color1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 8 * 4);
|
||||
glVertexAttribPointer(ATTR_POSITION, 4, GL_FLOAT, GL_FALSE, vertexSize, drawBuffer);
|
||||
int attrMask = program->attrMask;
|
||||
if (attrMask & (1 << ATTR_TEXCOORD)) glVertexAttribPointer(ATTR_TEXCOORD, doTextureProjection ? 3 : 2, GL_FLOAT, GL_FALSE, vertexSize, ((uint8_t*)drawBuffer) + 4 * 4);
|
||||
if (attrMask & (1 << ATTR_COLOR0)) glVertexAttribPointer(ATTR_COLOR0, 4, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 7 * 4);
|
||||
if (attrMask & (1 << ATTR_COLOR1)) glVertexAttribPointer(ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, ((uint8_t*)drawBuffer) + 8 * 4);
|
||||
if (drawIndexed) {
|
||||
//#ifdef USING_GLES2
|
||||
glDrawElements(glprim[prim], numTrans, GL_UNSIGNED_SHORT, inds);
|
||||
|
Loading…
Reference in New Issue
Block a user