mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-08 23:07:31 +00:00
Use a common ShaderId class. Start moving shader ID code to GPU/Common
This commit is contained in:
parent
67cd018aca
commit
92389a4966
@ -1446,6 +1446,8 @@ add_library(GPU OBJECT
|
||||
GPU/Common/GPUStateUtils.h
|
||||
GPU/Common/DrawEngineCommon.cpp
|
||||
GPU/Common/DrawEngineCommon.h
|
||||
GPU/Common/ShaderId.cpp
|
||||
GPU/Common/ShaderId.h
|
||||
GPU/Common/SplineCommon.cpp
|
||||
GPU/Common/SplineCommon.h
|
||||
GPU/Common/SoftwareTransformCommon.cpp
|
||||
|
137
GPU/Common/ShaderId.cpp
Normal file
137
GPU/Common/ShaderId.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Core/Config.h"
|
||||
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/Common/ShaderId.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
|
||||
|
||||
std::string VertexShaderDesc(const ShaderID &id) {
|
||||
std::stringstream desc;
|
||||
desc << StringFromFormat("%08x:%08x ", id.d[1], id.d[0]);
|
||||
if (id.Bit(VS_BIT_IS_THROUGH)) desc << "THR ";
|
||||
if (id.Bit(VS_BIT_USE_HW_TRANSFORM)) desc << "HWX ";
|
||||
if (id.Bit(VS_BIT_HAS_COLOR)) desc << "C ";
|
||||
if (id.Bit(VS_BIT_HAS_TEXCOORD)) desc << "T ";
|
||||
if (id.Bit(VS_BIT_HAS_NORMAL)) desc << "N ";
|
||||
if (id.Bit(VS_BIT_LMODE)) desc << "LM ";
|
||||
if (id.Bit(VS_BIT_ENABLE_FOG)) desc << "Fog ";
|
||||
if (id.Bit(VS_BIT_NORM_REVERSE)) desc << "RevN ";
|
||||
if (id.Bit(VS_BIT_DO_TEXTURE)) desc << "Tex ";
|
||||
if (id.Bit(VS_BIT_DO_TEXTURE_PROJ)) desc << "TexProj ";
|
||||
if (id.Bit(VS_BIT_FLIP_TEXTURE)) desc << "Flip ";
|
||||
int uvgMode = id.Bits(VS_BIT_UVGEN_MODE, 2);
|
||||
const char *uvgModes[4] = { "UV ", "UVMtx ", "UVEnv ", "UVUnk " };
|
||||
int ls0 = id.Bits(VS_BIT_LS0, 2);
|
||||
int ls1 = id.Bits(VS_BIT_LS1, 2);
|
||||
|
||||
if (uvgMode) desc << uvgModes[uvgMode];
|
||||
if (id.Bit(VS_BIT_ENABLE_BONES)) desc << "Bones:" << (id.Bits(VS_BIT_BONES, 3) + 1) << " ";
|
||||
// Lights
|
||||
if (id.Bit(VS_BIT_LIGHTING_ENABLE)) {
|
||||
desc << "Light: ";
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (id.Bit(VS_BIT_LIGHT0_ENABLE + i) || (uvgMode == GE_TEXMAP_ENVIRONMENT_MAP && (ls0 == i || ls1 == i))) {
|
||||
desc << i << ": ";
|
||||
desc << "c:" << id.Bits(VS_BIT_LIGHT0_COMP + 4 * i, 2) << " t:" << id.Bits(VS_BIT_LIGHT0_TYPE + 4 * i, 2) << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id.Bits(VS_BIT_MATERIAL_UPDATE, 3)) desc << "MatUp:" << id.Bits(VS_BIT_MATERIAL_UPDATE, 3) << " ";
|
||||
if (id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2)) desc << "WScale " << id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2) << " ";
|
||||
if (id.Bits(VS_BIT_TEXCOORD_FMTSCALE, 2)) desc << "TCScale " << id.Bits(VS_BIT_TEXCOORD_FMTSCALE, 2) << " ";
|
||||
if (id.Bit(VS_BIT_FLATSHADE)) desc << "Flat ";
|
||||
|
||||
// TODO: More...
|
||||
|
||||
return desc.str();
|
||||
}
|
||||
|
||||
bool CanUseHardwareTransform(int prim) {
|
||||
if (!g_Config.bHardwareTransform)
|
||||
return false;
|
||||
return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES;
|
||||
}
|
||||
|
||||
void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform) {
|
||||
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
|
||||
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
bool doShadeMapping = doTexture && (gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP);
|
||||
bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT && !gstate.isModeClear();
|
||||
|
||||
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
|
||||
bool hasNormal = (vertType & GE_VTYPE_NRM_MASK) != 0;
|
||||
bool hasTexcoord = (vertType & GE_VTYPE_TC_MASK) != 0;
|
||||
bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear();
|
||||
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
|
||||
// lmode: && !isModeThrough!?
|
||||
|
||||
ShaderID id;
|
||||
id.SetBit(VS_BIT_LMODE, lmode);
|
||||
id.SetBit(VS_BIT_IS_THROUGH, gstate.isModeThrough());
|
||||
id.SetBit(VS_BIT_ENABLE_FOG, enableFog);
|
||||
id.SetBit(VS_BIT_HAS_COLOR, hasColor);
|
||||
|
||||
if (doTexture) {
|
||||
id.SetBit(VS_BIT_DO_TEXTURE);
|
||||
id.SetBit(VS_BIT_FLIP_TEXTURE, gstate_c.flipTexture);
|
||||
id.SetBit(VS_BIT_DO_TEXTURE_PROJ, doTextureProjection);
|
||||
}
|
||||
|
||||
if (useHWTransform) {
|
||||
id.SetBit(VS_BIT_USE_HW_TRANSFORM);
|
||||
id.SetBit(VS_BIT_HAS_NORMAL, hasNormal);
|
||||
|
||||
// UV generation mode. doShadeMapping is implicitly stored here.
|
||||
id.SetBits(VS_BIT_UVGEN_MODE, 2, gstate.getUVGenMode());
|
||||
|
||||
// The next bits are used differently depending on UVgen mode
|
||||
if (doTextureProjection) {
|
||||
id.SetBits(VS_BIT_UVPROJ_MODE, 2, gstate.getUVProjMode());
|
||||
} else if (doShadeMapping) {
|
||||
id.SetBits(VS_BIT_LS0, 2, gstate.getUVLS0());
|
||||
id.SetBits(VS_BIT_LS1, 2, gstate.getUVLS1());
|
||||
}
|
||||
|
||||
// Bones.
|
||||
bool enableBones = vertTypeIsSkinningEnabled(vertType);
|
||||
id.SetBit(VS_BIT_ENABLE_BONES, enableBones);
|
||||
if (enableBones) {
|
||||
id.SetBits(VS_BIT_BONES, 3, TranslateNumBones(vertTypeGetNumBoneWeights(vertType)) - 1);
|
||||
// 2 bits. We should probably send in the weight scalefactor as a uniform instead,
|
||||
// or simply preconvert all weights to floats.
|
||||
id.SetBits(VS_BIT_WEIGHT_FMTSCALE, 2, (vertType & GE_VTYPE_WEIGHT_MASK) >> GE_VTYPE_WEIGHT_SHIFT);
|
||||
}
|
||||
|
||||
// Okay, d[1] coming up. ==============
|
||||
if (gstate.isLightingEnabled() || doShadeMapping) {
|
||||
// doShadeMapping is stored as UVGenMode, so this is enough for isLightingEnabled.
|
||||
if (gstate.isLightingEnabled())
|
||||
id.SetBit(VS_BIT_LIGHTING_ENABLE);
|
||||
// Light bits
|
||||
for (int i = 0; i < 4; i++) {
|
||||
id.SetBit(VS_BIT_LIGHT0_ENABLE + i, gstate.isLightChanEnabled(i) != 0);
|
||||
if (gstate.isLightChanEnabled(i) || (doShadeMapping && (gstate.getUVLS0() == i || gstate.getUVLS1() == i))) {
|
||||
id.SetBits(VS_BIT_LIGHT0_COMP + 4 * i, 2, gstate.getLightComputation(i));
|
||||
id.SetBits(VS_BIT_LIGHT0_TYPE + 4 * i, 2, gstate.getLightType(i));
|
||||
}
|
||||
}
|
||||
id.SetBits(VS_BIT_MATERIAL_UPDATE, 3, gstate.getMaterialUpdate() & 7);
|
||||
}
|
||||
|
||||
id.SetBit(VS_BIT_NORM_REVERSE, gstate.areNormalsReversed());
|
||||
if (doTextureProjection && gstate.getUVProjMode() == GE_PROJMAP_UV) {
|
||||
id.SetBits(VS_BIT_TEXCOORD_FMTSCALE, 2, (vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT); // two bits
|
||||
} else {
|
||||
id.SetBit(VS_BIT_HAS_TEXCOORD, hasTexcoord);
|
||||
}
|
||||
}
|
||||
|
||||
id.SetBit(VS_BIT_FLATSHADE, doFlatShading);
|
||||
|
||||
*id_out = id;
|
||||
}
|
137
GPU/Common/ShaderId.h
Normal file
137
GPU/Common/ShaderId.h
Normal file
@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
// TODO: There will be additional bits, indicating that groups of these will be
|
||||
// sent to the shader and processed there. This will cut down the number of shaders ("ubershader approach")
|
||||
// This is probably only really worth doing for lighting and bones.
|
||||
enum {
|
||||
VS_BIT_LMODE = 0,
|
||||
VS_BIT_IS_THROUGH = 1,
|
||||
VS_BIT_ENABLE_FOG = 2,
|
||||
VS_BIT_HAS_COLOR = 3,
|
||||
VS_BIT_DO_TEXTURE = 4,
|
||||
VS_BIT_FLIP_TEXTURE = 5,
|
||||
VS_BIT_DO_TEXTURE_PROJ = 6,
|
||||
VS_BIT_USE_HW_TRANSFORM = 8,
|
||||
VS_BIT_HAS_NORMAL = 9, // conditioned on hw transform
|
||||
VS_BIT_NORM_REVERSE = 10,
|
||||
VS_BIT_HAS_TEXCOORD = 11, // 5 free after
|
||||
VS_BIT_UVGEN_MODE = 16,
|
||||
VS_BIT_UVPROJ_MODE = 18, // 2, can overlap with LS0
|
||||
VS_BIT_LS0 = 18, // 2
|
||||
VS_BIT_LS1 = 20, // 2
|
||||
VS_BIT_BONES = 22, // 3 should be enough, not 8
|
||||
VS_BIT_ENABLE_BONES = 30,
|
||||
VS_BIT_LIGHT0_COMP = 32, // 2 bits
|
||||
VS_BIT_LIGHT0_TYPE = 34, // 2 bits
|
||||
VS_BIT_LIGHT1_COMP = 36, // 2 bits
|
||||
VS_BIT_LIGHT1_TYPE = 38, // 2 bits
|
||||
VS_BIT_LIGHT2_COMP = 40, // 2 bits
|
||||
VS_BIT_LIGHT2_TYPE = 42, // 2 bits
|
||||
VS_BIT_LIGHT3_COMP = 44, // 2 bits
|
||||
VS_BIT_LIGHT3_TYPE = 46, // 2 bits
|
||||
VS_BIT_MATERIAL_UPDATE = 48, // 3 bits, 1 free after
|
||||
VS_BIT_LIGHT0_ENABLE = 52,
|
||||
VS_BIT_LIGHT1_ENABLE = 53,
|
||||
VS_BIT_LIGHT2_ENABLE = 54,
|
||||
VS_BIT_LIGHT3_ENABLE = 55,
|
||||
VS_BIT_LIGHTING_ENABLE = 56,
|
||||
VS_BIT_WEIGHT_FMTSCALE = 57, // only two bits, 1 free after
|
||||
VS_BIT_TEXCOORD_FMTSCALE = 60,
|
||||
VS_BIT_FLATSHADE = 62, // 1 free after
|
||||
};
|
||||
|
||||
|
||||
// Local
|
||||
enum {
|
||||
FS_BIT_CLEARMODE = 0,
|
||||
FS_BIT_DO_TEXTURE = 1,
|
||||
FS_BIT_TEXFUNC = 2, // 3 bits
|
||||
FS_BIT_TEXALPHA = 5,
|
||||
FS_BIT_FLIP_TEXTURE = 6,
|
||||
FS_BIT_SHADER_TEX_CLAMP = 7,
|
||||
FS_BIT_CLAMP_S = 8,
|
||||
FS_BIT_CLAMP_T = 9,
|
||||
FS_BIT_TEXTURE_AT_OFFSET = 10,
|
||||
FS_BIT_LMODE = 11,
|
||||
FS_BIT_ALPHA_TEST = 12,
|
||||
FS_BIT_ALPHA_TEST_FUNC = 13, // 3 bits
|
||||
FS_BIT_ALPHA_AGAINST_ZERO = 16,
|
||||
FS_BIT_COLOR_TEST = 17,
|
||||
FS_BIT_COLOR_TEST_FUNC = 18, // 2 bits
|
||||
FS_BIT_COLOR_AGAINST_ZERO = 20,
|
||||
FS_BIT_ENABLE_FOG = 21,
|
||||
FS_BIT_DO_TEXTURE_PROJ = 22,
|
||||
FS_BIT_COLOR_DOUBLE = 23,
|
||||
FS_BIT_STENCIL_TO_ALPHA = 24, // 2 bits
|
||||
FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE = 26, // 4 bits
|
||||
FS_BIT_REPLACE_LOGIC_OP_TYPE = 30, // 2 bits
|
||||
FS_BIT_REPLACE_BLEND = 32, // 3 bits
|
||||
FS_BIT_BLENDEQ = 35, // 3 bits
|
||||
FS_BIT_BLENDFUNC_A = 38, // 4 bits
|
||||
FS_BIT_BLENDFUNC_B = 42,
|
||||
FS_BIT_FLATSHADE = 46,
|
||||
};
|
||||
|
||||
struct ShaderID {
|
||||
ShaderID() {
|
||||
clear();
|
||||
}
|
||||
void clear() {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
|
||||
d[i] = 0;
|
||||
}
|
||||
}
|
||||
void set_invalid() {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
|
||||
d[i] = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
u32 d[2];
|
||||
bool operator < (const ShaderID &other) const {
|
||||
for (size_t i = 0; i < sizeof(d) / sizeof(u32); i++) {
|
||||
if (d[i] < other.d[i])
|
||||
return true;
|
||||
if (d[i] > other.d[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool operator == (const ShaderID &other) const {
|
||||
for (size_t i = 0; i < sizeof(d) / sizeof(u32); i++) {
|
||||
if (d[i] != other.d[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bit(int bit) const {
|
||||
return (d[bit >> 5] >> (bit & 31)) & 1;
|
||||
}
|
||||
// Does not handle crossing 32-bit boundaries
|
||||
int Bits(int bit, int count) const {
|
||||
const int mask = (1 << count) - 1;
|
||||
return (d[bit >> 5] >> (bit & 31)) & mask;
|
||||
}
|
||||
void SetBit(int bit, bool value = true) {
|
||||
if (value) {
|
||||
d[bit >> 5] |= 1 << (bit & 31);
|
||||
}
|
||||
}
|
||||
void SetBits(int bit, int count, int value) {
|
||||
if (value != 0) {
|
||||
const int mask = (1 << count) - 1;
|
||||
d[bit >> 5] |= (value & mask) << (bit & 31);
|
||||
}
|
||||
}
|
||||
|
||||
void ToString(std::string *dest) const {
|
||||
dest->resize(sizeof(d));
|
||||
memcpy(&(*dest)[0], d, sizeof(d));
|
||||
}
|
||||
void FromString(std::string src) {
|
||||
memcpy(d, &(src)[0], sizeof(d));
|
||||
}
|
||||
};
|
@ -314,7 +314,7 @@ static inline LogicOpReplaceType ReplaceLogicOpType() {
|
||||
|
||||
// Here we must take all the bits of the gstate that determine what the fragment shader will
|
||||
// look like, and concatenate them together into an ID.
|
||||
void ComputeFragmentShaderIDDX9(FragmentShaderIDDX9 *id) {
|
||||
void ComputeFragmentShaderIDDX9(ShaderID *id) {
|
||||
int id0 = 0;
|
||||
int id1 = 0;
|
||||
if (gstate.isModeClear()) {
|
||||
|
@ -19,34 +19,14 @@
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#include "GPU/Common/ShaderId.h"
|
||||
|
||||
// TODO: Bench both ways. Result may be different on old vs new hardware though..
|
||||
// #define DX9_USE_HW_ALPHA_TEST 1
|
||||
|
||||
namespace DX9 {
|
||||
|
||||
struct FragmentShaderIDDX9 {
|
||||
FragmentShaderIDDX9() {clear();}
|
||||
void clear() {d[0] = 0xFFFFFFFF; d[1] = 0xFFFFFFFF;}
|
||||
u32 d[2];
|
||||
bool operator < (const FragmentShaderIDDX9 &other) const {
|
||||
for (size_t i = 0; i < sizeof(d) / sizeof(u32); i++) {
|
||||
if (d[i] < other.d[i])
|
||||
return true;
|
||||
if (d[i] > other.d[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool operator == (const FragmentShaderIDDX9 &other) const {
|
||||
for (size_t i = 0; i < sizeof(d) / sizeof(u32); i++) {
|
||||
if (d[i] != other.d[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void ComputeFragmentShaderIDDX9(FragmentShaderIDDX9 *id);
|
||||
void ComputeFragmentShaderIDDX9(ShaderID *id);
|
||||
void GenerateFragmentShaderDX9(char *buffer);
|
||||
|
||||
enum StencilValueType {
|
||||
|
@ -593,9 +593,9 @@ void ShaderManagerDX9::DirtyLastShader() { // disables vertex arrays
|
||||
VSShader *ShaderManagerDX9::ApplyShader(int prim, u32 vertType) {
|
||||
bool useHWTransform = CanUseHardwareTransformDX9(prim);
|
||||
|
||||
VertexShaderIDDX9 VSID;
|
||||
ShaderID VSID;
|
||||
ComputeVertexShaderIDDX9(&VSID, vertType, useHWTransform);
|
||||
FragmentShaderIDDX9 FSID;
|
||||
ShaderID FSID;
|
||||
ComputeFragmentShaderIDDX9(&FSID);
|
||||
|
||||
// Just update uniforms if this is the same shader as last time.
|
||||
|
@ -17,11 +17,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "../../Globals.h"
|
||||
#include <map>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "Globals.h"
|
||||
#include "GPU/Directx9/VertexShaderGeneratorDX9.h"
|
||||
#include "GPU/Directx9/PixelShaderGeneratorDX9.h"
|
||||
#include "GPU/Common/ShaderId.h"
|
||||
#include "thin3d/d3dx9_loader.h"
|
||||
#include "math/lin/matrix4x4.h"
|
||||
|
||||
@ -149,8 +151,8 @@ private:
|
||||
|
||||
void Clear();
|
||||
|
||||
FragmentShaderIDDX9 lastFSID_;
|
||||
VertexShaderIDDX9 lastVSID_;
|
||||
ShaderID lastFSID_;
|
||||
ShaderID lastVSID_;
|
||||
|
||||
u32 globalDirty_;
|
||||
char *codeBuffer_;
|
||||
@ -158,10 +160,10 @@ private:
|
||||
VSShader *lastVShader_;
|
||||
PSShader *lastPShader_;
|
||||
|
||||
typedef std::map<FragmentShaderIDDX9, PSShader *> FSCache;
|
||||
typedef std::map<ShaderID, PSShader *> FSCache;
|
||||
FSCache fsCache_;
|
||||
|
||||
typedef std::map<VertexShaderIDDX9, VSShader *> VSCache;
|
||||
typedef std::map<ShaderID, VSShader *> VSCache;
|
||||
VSCache vsCache_;
|
||||
};
|
||||
|
||||
|
@ -43,7 +43,7 @@ bool CanUseHardwareTransformDX9(int prim) {
|
||||
}
|
||||
|
||||
// prim so we can special case for RECTANGLES :(
|
||||
void ComputeVertexShaderIDDX9(VertexShaderIDDX9 *id, u32 vertType, bool useHWTransform) {
|
||||
void ComputeVertexShaderIDDX9(ShaderID *id, u32 vertType, bool useHWTransform) {
|
||||
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
|
||||
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
bool doShadeMapping = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP;
|
||||
|
@ -19,6 +19,8 @@
|
||||
|
||||
#include "Globals.h"
|
||||
|
||||
#include "GPU/Common/ShaderID.h"
|
||||
|
||||
namespace DX9 {
|
||||
|
||||
// #define USE_BONE_ARRAY
|
||||
@ -52,7 +54,7 @@ struct VertexShaderIDDX9
|
||||
|
||||
bool CanUseHardwareTransformDX9(int prim);
|
||||
|
||||
void ComputeVertexShaderIDDX9(VertexShaderIDDX9 *id, u32 vertType, bool useHWTransform);
|
||||
void ComputeVertexShaderIDDX9(ShaderID *id, u32 vertType, bool useHWTransform);
|
||||
void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform);
|
||||
|
||||
// Collapse to less skinning shaders to reduce shader switching, which is expensive.
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/Config.h"
|
||||
#include "GPU/Common/GPUStateUtils.h"
|
||||
#include "GPU/Common/ShaderId.h"
|
||||
#include "GPU/GLES/FragmentShaderGenerator.h"
|
||||
#include "GPU/GLES/Framebuffer.h"
|
||||
#include "GPU/GLES/ShaderManager.h"
|
||||
@ -301,37 +302,6 @@ static inline LogicOpReplaceType ReplaceLogicOpType() {
|
||||
return LOGICOPTYPE_NORMAL;
|
||||
}
|
||||
|
||||
// Local
|
||||
enum {
|
||||
FS_BIT_CLEARMODE = 0,
|
||||
FS_BIT_DO_TEXTURE = 1,
|
||||
FS_BIT_TEXFUNC = 2, // 3 bits
|
||||
FS_BIT_TEXALPHA = 5,
|
||||
FS_BIT_FLIP_TEXTURE = 6,
|
||||
FS_BIT_SHADER_TEX_CLAMP = 7,
|
||||
FS_BIT_CLAMP_S = 8,
|
||||
FS_BIT_CLAMP_T = 9,
|
||||
FS_BIT_TEXTURE_AT_OFFSET = 10,
|
||||
FS_BIT_LMODE = 11,
|
||||
FS_BIT_ALPHA_TEST = 12,
|
||||
FS_BIT_ALPHA_TEST_FUNC = 13, // 3 bits
|
||||
FS_BIT_ALPHA_AGAINST_ZERO = 16,
|
||||
FS_BIT_COLOR_TEST = 17,
|
||||
FS_BIT_COLOR_TEST_FUNC = 18, // 2 bits
|
||||
FS_BIT_COLOR_AGAINST_ZERO = 20,
|
||||
FS_BIT_ENABLE_FOG = 21,
|
||||
FS_BIT_DO_TEXTURE_PROJ = 22,
|
||||
FS_BIT_COLOR_DOUBLE = 23,
|
||||
FS_BIT_STENCIL_TO_ALPHA = 24, // 2 bits
|
||||
FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE = 26, // 4 bits
|
||||
FS_BIT_REPLACE_LOGIC_OP_TYPE = 30, // 2 bits
|
||||
FS_BIT_REPLACE_BLEND = 32, // 3 bits
|
||||
FS_BIT_BLENDEQ = 35, // 3 bits
|
||||
FS_BIT_BLENDFUNC_A = 38, // 4 bits
|
||||
FS_BIT_BLENDFUNC_B = 42,
|
||||
FS_BIT_FLATSHADE = 46,
|
||||
};
|
||||
|
||||
static const char *alphaTestFuncs[] = { "NEVER", "ALWAYS", "==", "!=", "<", "<=", ">", ">=" };
|
||||
|
||||
std::string FragmentShaderDesc(const ShaderID &id) {
|
||||
|
@ -22,73 +22,12 @@
|
||||
#include <map>
|
||||
|
||||
#include "GPU/Common/ShaderCommon.h"
|
||||
#include "GPU/Common/ShaderId.h"
|
||||
#include "GPU/GLES/VertexShaderGenerator.h"
|
||||
#include "GPU/GLES/FragmentShaderGenerator.h"
|
||||
|
||||
class Shader;
|
||||
|
||||
struct ShaderID {
|
||||
ShaderID() {
|
||||
clear();
|
||||
}
|
||||
void clear() {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
|
||||
d[i] = 0;
|
||||
}
|
||||
}
|
||||
void set_invalid() {
|
||||
for (size_t i = 0; i < ARRAY_SIZE(d); i++) {
|
||||
d[i] = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
u32 d[2];
|
||||
bool operator < (const ShaderID &other) const {
|
||||
for (size_t i = 0; i < sizeof(d) / sizeof(u32); i++) {
|
||||
if (d[i] < other.d[i])
|
||||
return true;
|
||||
if (d[i] > other.d[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool operator == (const ShaderID &other) const {
|
||||
for (size_t i = 0; i < sizeof(d) / sizeof(u32); i++) {
|
||||
if (d[i] != other.d[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Bit(int bit) const {
|
||||
return (d[bit >> 5] >> (bit & 31)) & 1;
|
||||
}
|
||||
// Does not handle crossing 32-bit boundaries
|
||||
int Bits(int bit, int count) const {
|
||||
const int mask = (1 << count) - 1;
|
||||
return (d[bit >> 5] >> (bit & 31)) & mask;
|
||||
}
|
||||
void SetBit(int bit, bool value = true) {
|
||||
if (value) {
|
||||
d[bit >> 5] |= 1 << (bit & 31);
|
||||
}
|
||||
}
|
||||
void SetBits(int bit, int count, int value) {
|
||||
if (value != 0) {
|
||||
const int mask = (1 << count) - 1;
|
||||
d[bit >> 5] |= (value & mask) << (bit & 31);
|
||||
}
|
||||
}
|
||||
|
||||
void ToString(std::string *dest) const {
|
||||
dest->resize(sizeof(d));
|
||||
memcpy(&(*dest)[0], d, sizeof(d));
|
||||
}
|
||||
void FromString(std::string src) {
|
||||
memcpy(d, &(src)[0], sizeof(d));
|
||||
}
|
||||
};
|
||||
|
||||
// Pre-fetched attrs and uniforms
|
||||
enum {
|
||||
ATTR_POSITION = 0,
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "Core/Config.h"
|
||||
#include "GPU/GLES/VertexShaderGenerator.h"
|
||||
#include "GPU/GLES/ShaderManager.h"
|
||||
#include "GPU/Common/ShaderId.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
|
||||
// SDL 1.2 on Apple does not have support for OpenGL 3 and hence needs
|
||||
@ -43,171 +44,6 @@
|
||||
|
||||
#define WRITE p+=sprintf
|
||||
|
||||
// TODO: There will be additional bits, indicating that groups of these will be
|
||||
// sent to the shader and processed there. This will cut down the number of shaders ("ubershader approach")
|
||||
enum {
|
||||
VS_BIT_LMODE = 0,
|
||||
VS_BIT_IS_THROUGH = 1,
|
||||
VS_BIT_ENABLE_FOG = 2,
|
||||
VS_BIT_HAS_COLOR = 3,
|
||||
VS_BIT_DO_TEXTURE = 4,
|
||||
VS_BIT_FLIP_TEXTURE = 5,
|
||||
VS_BIT_DO_TEXTURE_PROJ = 6,
|
||||
VS_BIT_USE_HW_TRANSFORM = 8,
|
||||
VS_BIT_HAS_NORMAL = 9, // conditioned on hw transform
|
||||
VS_BIT_NORM_REVERSE = 10,
|
||||
VS_BIT_HAS_TEXCOORD = 11, // 5 free after
|
||||
VS_BIT_UVGEN_MODE = 16,
|
||||
VS_BIT_UVPROJ_MODE = 18, // 2, can overlap with LS0
|
||||
VS_BIT_LS0 = 18, // 2
|
||||
VS_BIT_LS1 = 20, // 2
|
||||
VS_BIT_BONES = 22, // 3 should be enough, not 8
|
||||
VS_BIT_ENABLE_BONES = 30,
|
||||
VS_BIT_LIGHT0_COMP = 32, // 2 bits
|
||||
VS_BIT_LIGHT0_TYPE = 34, // 2 bits
|
||||
VS_BIT_LIGHT1_COMP = 36, // 2 bits
|
||||
VS_BIT_LIGHT1_TYPE = 38, // 2 bits
|
||||
VS_BIT_LIGHT2_COMP = 40, // 2 bits
|
||||
VS_BIT_LIGHT2_TYPE = 42, // 2 bits
|
||||
VS_BIT_LIGHT3_COMP = 44, // 2 bits
|
||||
VS_BIT_LIGHT3_TYPE = 46, // 2 bits
|
||||
VS_BIT_MATERIAL_UPDATE = 48, // 3 bits, 1 free after
|
||||
VS_BIT_LIGHT0_ENABLE = 52,
|
||||
VS_BIT_LIGHT1_ENABLE = 53,
|
||||
VS_BIT_LIGHT2_ENABLE = 54,
|
||||
VS_BIT_LIGHT3_ENABLE = 55,
|
||||
VS_BIT_LIGHTING_ENABLE = 56,
|
||||
VS_BIT_WEIGHT_FMTSCALE = 57, // only two bits, 1 free after
|
||||
VS_BIT_TEXCOORD_FMTSCALE = 60,
|
||||
VS_BIT_FLATSHADE = 62, // 1 free after
|
||||
};
|
||||
|
||||
std::string VertexShaderDesc(const ShaderID &id) {
|
||||
std::stringstream desc;
|
||||
desc << StringFromFormat("%08x:%08x ", id.d[1], id.d[0]);
|
||||
if (id.Bit(VS_BIT_IS_THROUGH)) desc << "THR ";
|
||||
if (id.Bit(VS_BIT_USE_HW_TRANSFORM)) desc << "HWX ";
|
||||
if (id.Bit(VS_BIT_HAS_COLOR)) desc << "C ";
|
||||
if (id.Bit(VS_BIT_HAS_TEXCOORD)) desc << "T ";
|
||||
if (id.Bit(VS_BIT_HAS_NORMAL)) desc << "N ";
|
||||
if (id.Bit(VS_BIT_LMODE)) desc << "LM ";
|
||||
if (id.Bit(VS_BIT_ENABLE_FOG)) desc << "Fog ";
|
||||
if (id.Bit(VS_BIT_NORM_REVERSE)) desc << "RevN ";
|
||||
if (id.Bit(VS_BIT_DO_TEXTURE)) desc << "Tex ";
|
||||
if (id.Bit(VS_BIT_DO_TEXTURE_PROJ)) desc << "TexProj ";
|
||||
if (id.Bit(VS_BIT_FLIP_TEXTURE)) desc << "Flip ";
|
||||
int uvgMode = id.Bits(VS_BIT_UVGEN_MODE, 2);
|
||||
const char *uvgModes[4] = { "UV ", "UVMtx ", "UVEnv ", "UVUnk " };
|
||||
int ls0 = id.Bits(VS_BIT_LS0, 2);
|
||||
int ls1 = id.Bits(VS_BIT_LS1, 2);
|
||||
|
||||
if (uvgMode) desc << uvgModes[uvgMode];
|
||||
if (id.Bit(VS_BIT_ENABLE_BONES)) desc << "Bones:" << (id.Bits(VS_BIT_BONES, 3) + 1) << " ";
|
||||
// Lights
|
||||
if (id.Bit(VS_BIT_LIGHTING_ENABLE)) {
|
||||
desc << "Light: ";
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (id.Bit(VS_BIT_LIGHT0_ENABLE + i) || (uvgMode == GE_TEXMAP_ENVIRONMENT_MAP && (ls0 == i || ls1 == i))) {
|
||||
desc << i << ": ";
|
||||
desc << "c:" << id.Bits(VS_BIT_LIGHT0_COMP + 4 * i, 2) << " t:" << id.Bits(VS_BIT_LIGHT0_TYPE + 4 * i, 2) << " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id.Bits(VS_BIT_MATERIAL_UPDATE, 3)) desc << "MatUp:" << id.Bits(VS_BIT_MATERIAL_UPDATE, 3) << " ";
|
||||
if (id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2)) desc << "WScale " << id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2) << " ";
|
||||
if (id.Bits(VS_BIT_TEXCOORD_FMTSCALE, 2)) desc << "TCScale " << id.Bits(VS_BIT_TEXCOORD_FMTSCALE, 2) << " ";
|
||||
if (id.Bit(VS_BIT_FLATSHADE)) desc << "Flat ";
|
||||
|
||||
// TODO: More...
|
||||
|
||||
return desc.str();
|
||||
}
|
||||
|
||||
bool CanUseHardwareTransform(int prim) {
|
||||
if (!g_Config.bHardwareTransform)
|
||||
return false;
|
||||
return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES;
|
||||
}
|
||||
|
||||
void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform) {
|
||||
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
|
||||
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
bool doShadeMapping = doTexture && (gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP);
|
||||
bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT && !gstate.isModeClear();
|
||||
|
||||
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
|
||||
bool hasNormal = (vertType & GE_VTYPE_NRM_MASK) != 0;
|
||||
bool hasTexcoord = (vertType & GE_VTYPE_TC_MASK) != 0;
|
||||
bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear();
|
||||
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
|
||||
// lmode: && !isModeThrough!?
|
||||
|
||||
ShaderID id;
|
||||
id.SetBit(VS_BIT_LMODE, lmode);
|
||||
id.SetBit(VS_BIT_IS_THROUGH, gstate.isModeThrough());
|
||||
id.SetBit(VS_BIT_ENABLE_FOG, enableFog);
|
||||
id.SetBit(VS_BIT_HAS_COLOR, hasColor);
|
||||
|
||||
if (doTexture) {
|
||||
id.SetBit(VS_BIT_DO_TEXTURE);
|
||||
id.SetBit(VS_BIT_FLIP_TEXTURE, gstate_c.flipTexture);
|
||||
id.SetBit(VS_BIT_DO_TEXTURE_PROJ, doTextureProjection);
|
||||
}
|
||||
|
||||
if (useHWTransform) {
|
||||
id.SetBit(VS_BIT_USE_HW_TRANSFORM);
|
||||
id.SetBit(VS_BIT_HAS_NORMAL, hasNormal);
|
||||
|
||||
// UV generation mode. doShadeMapping is implicitly stored here.
|
||||
id.SetBits(VS_BIT_UVGEN_MODE, 2, gstate.getUVGenMode());
|
||||
|
||||
// The next bits are used differently depending on UVgen mode
|
||||
if (doTextureProjection) {
|
||||
id.SetBits(VS_BIT_UVPROJ_MODE, 2, gstate.getUVProjMode());
|
||||
} else if (doShadeMapping) {
|
||||
id.SetBits(VS_BIT_LS0, 2, gstate.getUVLS0());
|
||||
id.SetBits(VS_BIT_LS1, 2, gstate.getUVLS1());
|
||||
}
|
||||
|
||||
// Bones.
|
||||
bool enableBones = vertTypeIsSkinningEnabled(vertType);
|
||||
id.SetBit(VS_BIT_ENABLE_BONES, enableBones);
|
||||
if (enableBones) {
|
||||
id.SetBits(VS_BIT_BONES, 3, TranslateNumBones(vertTypeGetNumBoneWeights(vertType)) - 1);
|
||||
// 2 bits. We should probably send in the weight scalefactor as a uniform instead,
|
||||
// or simply preconvert all weights to floats.
|
||||
id.SetBits(VS_BIT_WEIGHT_FMTSCALE, 2, (vertType & GE_VTYPE_WEIGHT_MASK) >> GE_VTYPE_WEIGHT_SHIFT);
|
||||
}
|
||||
|
||||
// Okay, d[1] coming up. ==============
|
||||
if (gstate.isLightingEnabled() || doShadeMapping) {
|
||||
// doShadeMapping is stored as UVGenMode, so this is enough for isLightingEnabled.
|
||||
if (gstate.isLightingEnabled())
|
||||
id.SetBit(VS_BIT_LIGHTING_ENABLE);
|
||||
// Light bits
|
||||
for (int i = 0; i < 4; i++) {
|
||||
id.SetBit(VS_BIT_LIGHT0_ENABLE + i, gstate.isLightChanEnabled(i) != 0);
|
||||
if (gstate.isLightChanEnabled(i) || (doShadeMapping && (gstate.getUVLS0() == i || gstate.getUVLS1() == i))) {
|
||||
id.SetBits(VS_BIT_LIGHT0_COMP + 4 * i, 2, gstate.getLightComputation(i));
|
||||
id.SetBits(VS_BIT_LIGHT0_TYPE + 4 * i, 2, gstate.getLightType(i));
|
||||
}
|
||||
}
|
||||
id.SetBits(VS_BIT_MATERIAL_UPDATE, 3, gstate.getMaterialUpdate() & 7);
|
||||
}
|
||||
|
||||
id.SetBit(VS_BIT_NORM_REVERSE, gstate.areNormalsReversed());
|
||||
if (doTextureProjection && gstate.getUVProjMode() == GE_PROJMAP_UV) {
|
||||
id.SetBits(VS_BIT_TEXCOORD_FMTSCALE, 2, (vertType & GE_VTYPE_TC_MASK) >> GE_VTYPE_TC_SHIFT); // two bits
|
||||
} else {
|
||||
id.SetBit(VS_BIT_HAS_TEXCOORD, hasTexcoord);
|
||||
}
|
||||
}
|
||||
|
||||
id.SetBit(VS_BIT_FLATSHADE, doFlatShading);
|
||||
|
||||
*id_out = id;
|
||||
}
|
||||
|
||||
static const char * const boneWeightAttrDecl[9] = {
|
||||
"#ERROR#",
|
||||
"attribute mediump float w1;\n",
|
||||
|
@ -187,6 +187,7 @@
|
||||
<ClInclude Include="Common\IndexGenerator.h" />
|
||||
<ClInclude Include="Common\PostShader.h" />
|
||||
<ClInclude Include="Common\ShaderCommon.h" />
|
||||
<ClInclude Include="Common\ShaderId.h" />
|
||||
<ClInclude Include="Common\SoftwareTransformCommon.h" />
|
||||
<ClInclude Include="Common\SplineCommon.h" />
|
||||
<ClInclude Include="Common\TextureDecoderNEON.h">
|
||||
@ -250,6 +251,7 @@
|
||||
<ClCompile Include="Common\GPUDebugInterface.cpp" />
|
||||
<ClCompile Include="Common\IndexGenerator.cpp" />
|
||||
<ClCompile Include="Common\PostShader.cpp" />
|
||||
<ClCompile Include="Common\ShaderId.cpp" />
|
||||
<ClCompile Include="Common\SplineCommon.cpp" />
|
||||
<ClCompile Include="Common\TextureDecoderNEON.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
|
@ -198,6 +198,7 @@
|
||||
<ClInclude Include="Common\ShaderCommon.h">
|
||||
<Filter>Common</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Common\ShaderId.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Math3D.cpp">
|
||||
@ -377,5 +378,6 @@
|
||||
<ClCompile Include="GLES\GLStateCache.cpp">
|
||||
<Filter>GLES</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Common\ShaderId.cpp" />
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -47,6 +47,7 @@ SOURCES += $$P/GPU/GeDisasm.cpp \ # GPU
|
||||
$$P/GPU/Debugger/*.cpp \
|
||||
$$P/GPU/Common/DepalettizeShaderCommon.cpp \
|
||||
$$P/GPU/Common/GPUDebugInterface.cpp \
|
||||
$$P/GPU/Common/ShaderId.cpp \
|
||||
$$P/GPU/Common/IndexGenerator.cpp \
|
||||
$$P/GPU/Common/TextureDecoder.cpp \
|
||||
$$P/GPU/Common/TextureScalerCommon.cpp \
|
||||
|
@ -156,6 +156,7 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SRC)/GPU/Common/FramebufferCommon.cpp \
|
||||
$(SRC)/GPU/Common/GPUDebugInterface.cpp \
|
||||
$(SRC)/GPU/Common/IndexGenerator.cpp.arm \
|
||||
$(SRC)/GPU/Common/ShaderId.cpp.arm \
|
||||
$(SRC)/GPU/Common/SoftwareTransformCommon.cpp.arm \
|
||||
$(SRC)/GPU/Common/VertexDecoderCommon.cpp.arm \
|
||||
$(SRC)/GPU/Common/TextureCacheCommon.cpp.arm \
|
||||
|
Loading…
x
Reference in New Issue
Block a user