mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-24 16:49:50 +00:00
GL Cleanup: No longer redundantly store the shader ID inside the shader objects
This commit is contained in:
parent
a53d31a8d7
commit
c8b1064d20
@ -119,6 +119,8 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform)
|
||||
id.SetBit(VS_BIT_HAS_TEXCOORD, hasTexcoord);
|
||||
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.SetBits(VS_BIT_TEXCOORD_FMTSCALE, 2, 3);
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,7 +195,7 @@ std::string FragmentShaderDesc(const ShaderID &id) {
|
||||
|
||||
// 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 ComputeFragmentShaderID(ShaderID *id_out, uint32_t vertType) {
|
||||
void ComputeFragmentShaderID(ShaderID *id_out) {
|
||||
ShaderID id;
|
||||
if (gstate.isModeClear()) {
|
||||
// We only need one clear shader, so let's ignore the rest of the bits.
|
||||
|
@ -142,5 +142,5 @@ void ComputeVertexShaderID(ShaderID *id, u32 vertexType, bool useHWTransform);
|
||||
// of the current flora of shaders.
|
||||
std::string VertexShaderDesc(const ShaderID &id);
|
||||
|
||||
void ComputeFragmentShaderID(ShaderID *id, uint32_t vertType);
|
||||
void ComputeFragmentShaderID(ShaderID *id);
|
||||
std::string FragmentShaderDesc(const ShaderID &id);
|
||||
|
@ -593,14 +593,13 @@ void ShaderManagerDX9::DirtyLastShader() { // disables vertex arrays
|
||||
lastPShader_ = nullptr;
|
||||
}
|
||||
|
||||
|
||||
VSShader *ShaderManagerDX9::ApplyShader(int prim, u32 vertType) {
|
||||
bool useHWTransform = CanUseHardwareTransform(prim);
|
||||
|
||||
ShaderID VSID;
|
||||
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
|
||||
ShaderID FSID;
|
||||
ComputeFragmentShaderID(&FSID, vertType);
|
||||
ComputeFragmentShaderID(&FSID);
|
||||
|
||||
// Just update uniforms if this is the same shader as last time.
|
||||
if (lastVShader_ != nullptr && lastPShader_ != nullptr && VSID == lastVSID_ && FSID == lastFSID_) {
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "Core/Config.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/ELF/ParamSFO.h"
|
||||
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
@ -729,6 +730,7 @@ void GLES_GPU::BeginFrameInternal() {
|
||||
} else if (dumpThisFrame_) {
|
||||
dumpThisFrame_ = false;
|
||||
}
|
||||
|
||||
shaderManager_->DirtyShader();
|
||||
|
||||
// Not sure if this is really needed.
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "i18n/i18n.h"
|
||||
|
||||
Shader::Shader(const char *code, uint32_t glShaderType, bool useHWTransform, const ShaderID &shaderID)
|
||||
: id_(shaderID), failed_(false), useHWTransform_(useHWTransform) {
|
||||
: failed_(false), useHWTransform_(useHWTransform) {
|
||||
PROFILE_THIS_SCOPE("shadercomp");
|
||||
isFragment_ = glShaderType == GL_FRAGMENT_SHADER;
|
||||
source_ = code;
|
||||
@ -87,7 +87,7 @@ Shader::~Shader() {
|
||||
glDeleteShader(shader);
|
||||
}
|
||||
|
||||
LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTransform, LinkedShader *previous)
|
||||
LinkedShader::LinkedShader(ShaderID VSID, Shader *vs, ShaderID FSID, Shader *fs, bool useHWTransform)
|
||||
: useHWTransform_(useHWTransform), program(0), dirtyUniforms(0) {
|
||||
PROFILE_THIS_SCOPE("shaderlink");
|
||||
|
||||
@ -138,10 +138,10 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans
|
||||
ELOG("Could not link program:\n %s", buf);
|
||||
#endif
|
||||
ERROR_LOG(G3D, "Could not link program:\n %s", buf);
|
||||
ERROR_LOG(G3D, "VS desc:\n%s\n", vs->GetShaderString(SHADER_STRING_SHORT_DESC).c_str());
|
||||
ERROR_LOG(G3D, "FS desc:\n%s\n", fs->GetShaderString(SHADER_STRING_SHORT_DESC).c_str());
|
||||
std::string vs_source = vs->GetShaderString(SHADER_STRING_SOURCE_CODE);
|
||||
std::string fs_source = fs->GetShaderString(SHADER_STRING_SOURCE_CODE);
|
||||
ERROR_LOG(G3D, "VS desc:\n%s\n", vs->GetShaderString(SHADER_STRING_SHORT_DESC, VSID).c_str());
|
||||
ERROR_LOG(G3D, "FS desc:\n%s\n", fs->GetShaderString(SHADER_STRING_SHORT_DESC, FSID).c_str());
|
||||
std::string vs_source = vs->GetShaderString(SHADER_STRING_SOURCE_CODE, VSID);
|
||||
std::string fs_source = fs->GetShaderString(SHADER_STRING_SOURCE_CODE, FSID);
|
||||
ERROR_LOG(G3D, "VS:\n%s\n", vs_source.c_str());
|
||||
ERROR_LOG(G3D, "FS:\n%s\n", fs_source.c_str());
|
||||
Reporting::ReportMessage("Error in shader program link: info: %s / fs: %s / vs: %s", buf, fs_source.c_str(), vs_source.c_str());
|
||||
@ -179,8 +179,8 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans
|
||||
u_view = glGetUniformLocation(program, "u_view");
|
||||
u_world = glGetUniformLocation(program, "u_world");
|
||||
u_texmtx = glGetUniformLocation(program, "u_texmtx");
|
||||
if (vertTypeGetWeightMask(vertType) != GE_VTYPE_WEIGHT_NONE)
|
||||
numBones = TranslateNumBones(vertTypeGetNumBoneWeights(vertType));
|
||||
if (VSID.Bit(VS_BIT_ENABLE_BONES))
|
||||
numBones = TranslateNumBones(VSID.Bits(VS_BIT_BONES, 3) + 1);
|
||||
else
|
||||
numBones = 0;
|
||||
u_depthRange = glGetUniformLocation(program, "u_depthRange");
|
||||
@ -286,7 +286,6 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans
|
||||
glUniform1i(u_testtex, 2);
|
||||
// The rest, use the "dirty" mechanism.
|
||||
dirtyUniforms = DIRTY_ALL;
|
||||
use(vertType, previous);
|
||||
}
|
||||
|
||||
LinkedShader::~LinkedShader() {
|
||||
@ -383,9 +382,8 @@ static inline void ScaleProjMatrix(Matrix4x4 &in) {
|
||||
in.translateAndScale(trans, scale);
|
||||
}
|
||||
|
||||
void LinkedShader::use(u32 vertType, LinkedShader *previous) {
|
||||
void LinkedShader::use(const ShaderID &VSID, LinkedShader *previous) {
|
||||
glUseProgram(program);
|
||||
UpdateUniforms(vertType);
|
||||
int enable, disable;
|
||||
if (previous) {
|
||||
enable = attrMask & ~previous->attrMask;
|
||||
@ -409,7 +407,7 @@ void LinkedShader::stop() {
|
||||
}
|
||||
}
|
||||
|
||||
void LinkedShader::UpdateUniforms(u32 vertType) {
|
||||
void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) {
|
||||
u32 dirty = dirtyUniforms & availableUniforms;
|
||||
dirtyUniforms = 0;
|
||||
if (!dirty)
|
||||
@ -718,7 +716,7 @@ void LinkedShader::UpdateUniforms(u32 vertType) {
|
||||
}
|
||||
|
||||
ShaderManager::ShaderManager()
|
||||
: lastShader_(nullptr), globalDirty_(0xFFFFFFFF), shaderSwitchDirty_(0) {
|
||||
: lastShader_(nullptr), globalDirty_(0xFFFFFFFF), shaderSwitchDirty_(0), diskCacheDirty_(false) {
|
||||
codeBuffer_ = new char[16384];
|
||||
lastFSID_.set_invalid();
|
||||
lastVSID_.set_invalid();
|
||||
@ -749,6 +747,7 @@ void ShaderManager::Clear() {
|
||||
}
|
||||
|
||||
void ShaderManager::ClearCache(bool deleteThem) {
|
||||
// TODO: Recreate all from the diskcache when we come back.
|
||||
Clear();
|
||||
}
|
||||
|
||||
@ -768,16 +767,20 @@ void ShaderManager::DirtyLastShader() { // disables vertex arrays
|
||||
lastVShaderSame_ = false;
|
||||
}
|
||||
|
||||
// This is to be used when debugging why incompatible shaders are being linked, like is
|
||||
// happening as I write this in Tactics Ogre
|
||||
bool ShaderManager::DebugAreShadersCompatibleForLinking(Shader *vs, Shader *fs) {
|
||||
// ShaderID vsid = vs->ID();
|
||||
// ShaderID fsid = fs->ID();
|
||||
// TODO: Redo these checks.
|
||||
return true;
|
||||
Shader *ShaderManager::CompileFragmentShader(ShaderID FSID) {
|
||||
if (!GenerateFragmentShader(FSID, codeBuffer_)) {
|
||||
return nullptr;
|
||||
}
|
||||
return new Shader(codeBuffer_, GL_FRAGMENT_SHADER, false, FSID);
|
||||
}
|
||||
|
||||
Shader *ShaderManager::ApplyVertexShader(int prim, u32 vertType) {
|
||||
Shader *ShaderManager::CompileVertexShader(ShaderID VSID) {
|
||||
bool useHWTransform = VSID.Bit(VS_BIT_USE_HW_TRANSFORM);
|
||||
GenerateVertexShader(VSID, codeBuffer_);
|
||||
return new Shader(codeBuffer_, GL_VERTEX_SHADER, useHWTransform, VSID);
|
||||
}
|
||||
|
||||
Shader *ShaderManager::ApplyVertexShader(int prim, u32 vertType, ShaderID *VSID) {
|
||||
if (globalDirty_) {
|
||||
if (lastShader_)
|
||||
lastShader_->dirtyUniforms |= globalDirty_;
|
||||
@ -787,26 +790,23 @@ Shader *ShaderManager::ApplyVertexShader(int prim, u32 vertType) {
|
||||
|
||||
bool useHWTransform = CanUseHardwareTransform(prim);
|
||||
|
||||
ShaderID VSID;
|
||||
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
|
||||
ComputeVertexShaderID(VSID, vertType, useHWTransform);
|
||||
|
||||
// Just update uniforms if this is the same shader as last time.
|
||||
if (lastShader_ != 0 && VSID == lastVSID_) {
|
||||
if (lastShader_ != 0 && *VSID == lastVSID_) {
|
||||
lastVShaderSame_ = true;
|
||||
return lastShader_->vs_; // Already all set.
|
||||
} else {
|
||||
lastVShaderSame_ = false;
|
||||
}
|
||||
|
||||
lastVSID_ = VSID;
|
||||
lastVSID_ = *VSID;
|
||||
|
||||
VSCache::iterator vsIter = vsCache_.find(VSID);
|
||||
VSCache::iterator vsIter = vsCache_.find(*VSID);
|
||||
Shader *vs;
|
||||
if (vsIter == vsCache_.end()) {
|
||||
// Vertex shader not in cache. Let's compile it.
|
||||
GenerateVertexShader(VSID, codeBuffer_);
|
||||
vs = new Shader(codeBuffer_, GL_VERTEX_SHADER, useHWTransform, VSID);
|
||||
|
||||
vs = CompileVertexShader(*VSID);
|
||||
if (vs->Failed()) {
|
||||
I18NCategory *gr = GetI18NCategory("Graphics");
|
||||
ERROR_LOG(G3D, "Shader compilation failed, falling back to software transform");
|
||||
@ -821,21 +821,22 @@ Shader *ShaderManager::ApplyVertexShader(int prim, u32 vertType) {
|
||||
ShaderID vsidTemp;
|
||||
ComputeVertexShaderID(&vsidTemp, vertType, false);
|
||||
GenerateVertexShader(vsidTemp, codeBuffer_);
|
||||
vs = new Shader(codeBuffer_, GL_VERTEX_SHADER, false, VSID);
|
||||
vs = new Shader(codeBuffer_, GL_VERTEX_SHADER, false, vsidTemp);
|
||||
}
|
||||
|
||||
vsCache_[VSID] = vs;
|
||||
vsCache_[*VSID] = vs;
|
||||
diskCacheDirty_ = true;
|
||||
} else {
|
||||
vs = vsIter->second;
|
||||
}
|
||||
return vs;
|
||||
}
|
||||
|
||||
LinkedShader *ShaderManager::ApplyFragmentShader(Shader *vs, int prim, u32 vertType) {
|
||||
LinkedShader *ShaderManager::ApplyFragmentShader(ShaderID VSID, Shader *vs, u32 vertType, int prim) {
|
||||
ShaderID FSID;
|
||||
ComputeFragmentShaderID(&FSID, vertType);
|
||||
ComputeFragmentShaderID(&FSID);
|
||||
if (lastVShaderSame_ && FSID == lastFSID_) {
|
||||
lastShader_->UpdateUniforms(vertType);
|
||||
lastShader_->UpdateUniforms(vertType, VSID);
|
||||
return lastShader_;
|
||||
}
|
||||
|
||||
@ -845,11 +846,9 @@ LinkedShader *ShaderManager::ApplyFragmentShader(Shader *vs, int prim, u32 vertT
|
||||
Shader *fs;
|
||||
if (fsIter == fsCache_.end()) {
|
||||
// Fragment shader not in cache. Let's compile it.
|
||||
if (!GenerateFragmentShader(FSID, codeBuffer_)) {
|
||||
return nullptr;
|
||||
}
|
||||
fs = new Shader(codeBuffer_, GL_FRAGMENT_SHADER, vs->UseHWTransform(), FSID);
|
||||
fs = CompileFragmentShader(FSID);
|
||||
fsCache_[FSID] = fs;
|
||||
diskCacheDirty_ = true;
|
||||
} else {
|
||||
fs = fsIter->second;
|
||||
}
|
||||
@ -868,30 +867,28 @@ LinkedShader *ShaderManager::ApplyFragmentShader(Shader *vs, int prim, u32 vertT
|
||||
}
|
||||
shaderSwitchDirty_ = 0;
|
||||
|
||||
|
||||
if (ls == nullptr) {
|
||||
// Check if we can link these.
|
||||
#ifdef _DEBUG
|
||||
if (!DebugAreShadersCompatibleForLinking(vs, fs)) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
ls = new LinkedShader(vs, fs, vertType, vs->UseHWTransform(), lastShader_); // This does "use" automatically
|
||||
ls = new LinkedShader(VSID, vs, FSID, fs, vs->UseHWTransform()); // This does "use" automatically
|
||||
ls->use(VSID, lastShader_);
|
||||
const LinkedShaderCacheEntry entry(vs, fs, ls);
|
||||
linkedShaderCache_.push_back(entry);
|
||||
} else {
|
||||
ls->use(vertType, lastShader_);
|
||||
ls->use(VSID, lastShader_);
|
||||
}
|
||||
ls->UpdateUniforms(vertType, VSID);
|
||||
|
||||
lastShader_ = ls;
|
||||
return ls;
|
||||
}
|
||||
|
||||
std::string Shader::GetShaderString(DebugShaderStringType type) const {
|
||||
std::string Shader::GetShaderString(DebugShaderStringType type, ShaderID id) const {
|
||||
switch (type) {
|
||||
case SHADER_STRING_SOURCE_CODE:
|
||||
return source_;
|
||||
case SHADER_STRING_SHORT_DESC:
|
||||
return isFragment_ ? FragmentShaderDesc(id_) : VertexShaderDesc(id_);
|
||||
return isFragment_ ? FragmentShaderDesc(id) : VertexShaderDesc(id);
|
||||
default:
|
||||
return "N/A";
|
||||
}
|
||||
@ -933,7 +930,7 @@ std::string ShaderManager::DebugGetShaderString(std::string id, DebugShaderType
|
||||
if (iter == vsCache_.end()) {
|
||||
return "";
|
||||
}
|
||||
return iter->second->GetShaderString(stringType);
|
||||
return iter->second->GetShaderString(stringType, iter->first);
|
||||
}
|
||||
|
||||
case SHADER_TYPE_FRAGMENT:
|
||||
@ -942,7 +939,7 @@ std::string ShaderManager::DebugGetShaderString(std::string id, DebugShaderType
|
||||
if (iter == fsCache_.end()) {
|
||||
return "";
|
||||
}
|
||||
return iter->second->GetShaderString(stringType);
|
||||
return iter->second->GetShaderString(stringType, iter->first);
|
||||
}
|
||||
default:
|
||||
return "N/A";
|
||||
|
@ -43,12 +43,12 @@ enum {
|
||||
|
||||
class LinkedShader {
|
||||
public:
|
||||
LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTransform, LinkedShader *previous);
|
||||
LinkedShader(ShaderID VSID, Shader *vs, ShaderID FSID, Shader *fs, bool useHWTransform);
|
||||
~LinkedShader();
|
||||
|
||||
void use(u32 vertType, LinkedShader *previous);
|
||||
void use(const ShaderID &VSID, LinkedShader *previous);
|
||||
void stop();
|
||||
void UpdateUniforms(u32 vertType);
|
||||
void UpdateUniforms(u32 vertType, const ShaderID &VSID);
|
||||
|
||||
Shader *vs_;
|
||||
// Set to false if the VS failed, happens on Mali-400 a lot for complex shaders.
|
||||
@ -167,14 +167,12 @@ public:
|
||||
uint32_t shader;
|
||||
|
||||
bool Failed() const { return failed_; }
|
||||
bool UseHWTransform() const { return useHWTransform_; }
|
||||
const ShaderID &ID() const { return id_; }
|
||||
bool UseHWTransform() const { return useHWTransform_; } // only relevant for vtx shaders
|
||||
|
||||
std::string GetShaderString(DebugShaderStringType type) const;
|
||||
std::string GetShaderString(DebugShaderStringType type, ShaderID id) const;
|
||||
|
||||
private:
|
||||
std::string source_;
|
||||
ShaderID id_;
|
||||
bool failed_;
|
||||
bool useHWTransform_;
|
||||
bool isFragment_;
|
||||
@ -189,8 +187,8 @@ public:
|
||||
|
||||
// This is the old ApplyShader split into two parts, because of annoying information dependencies.
|
||||
// If you call ApplyVertexShader, you MUST call ApplyFragmentShader soon afterwards.
|
||||
Shader *ApplyVertexShader(int prim, u32 vertType);
|
||||
LinkedShader *ApplyFragmentShader(Shader *vs, int prim, u32 vertType);
|
||||
Shader *ApplyVertexShader(int prim, u32 vertType, ShaderID *VSID);
|
||||
LinkedShader *ApplyFragmentShader(ShaderID VSID, Shader *vs, u32 vertType, int prim);
|
||||
|
||||
void DirtyShader();
|
||||
void DirtyUniform(u32 what) {
|
||||
@ -207,7 +205,8 @@ public:
|
||||
|
||||
private:
|
||||
void Clear();
|
||||
static bool DebugAreShadersCompatibleForLinking(Shader *vs, Shader *fs);
|
||||
Shader *CompileFragmentShader(ShaderID id);
|
||||
Shader *CompileVertexShader(ShaderID id);
|
||||
|
||||
struct LinkedShaderCacheEntry {
|
||||
LinkedShaderCacheEntry(Shader *vs_, Shader *fs_, LinkedShader *ls_)
|
||||
@ -236,4 +235,6 @@ private:
|
||||
|
||||
typedef std::map<ShaderID, Shader *> VSCache;
|
||||
VSCache vsCache_;
|
||||
|
||||
bool diskCacheDirty_;
|
||||
};
|
||||
|
@ -641,7 +641,8 @@ void TransformDrawEngine::DoFlush() {
|
||||
GEPrimitiveType prim = prevPrim_;
|
||||
ApplyDrawState(prim);
|
||||
|
||||
Shader *vshader = shaderManager_->ApplyVertexShader(prim, lastVType_);
|
||||
ShaderID vsid;
|
||||
Shader *vshader = shaderManager_->ApplyVertexShader(prim, lastVType_, &vsid);
|
||||
|
||||
if (vshader->UseHWTransform()) {
|
||||
GLuint vbo = 0, ebo = 0;
|
||||
@ -833,7 +834,7 @@ rotateVBO:
|
||||
}
|
||||
|
||||
ApplyDrawStateLate();
|
||||
LinkedShader *program = shaderManager_->ApplyFragmentShader(vshader, prim, lastVType_);
|
||||
LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim);
|
||||
SetupDecFmtForDraw(program, dec_->GetDecVtxFmt(), vbo ? 0 : decoded);
|
||||
|
||||
if (useElements) {
|
||||
@ -870,7 +871,7 @@ rotateVBO:
|
||||
maxIndex, framebufferManager_, textureCache_, transformed, transformedExpanded, drawBuffer, numTrans, drawIndexed, &result, 1.0);
|
||||
ApplyDrawStateLate();
|
||||
|
||||
LinkedShader *program = shaderManager_->ApplyFragmentShader(vshader, prim, lastVType_);
|
||||
LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim);
|
||||
|
||||
if (result.action == SW_DRAW_PRIMITIVES) {
|
||||
if (result.setStencil) {
|
||||
|
Loading…
Reference in New Issue
Block a user