mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Add an experiment with using a texture for tests.
Using an option for now so it's easy to test, if it works well we can maybe remove the option.
This commit is contained in:
parent
780ed765c7
commit
94c1271761
17 changed files with 362 additions and 55 deletions
|
@ -1327,6 +1327,8 @@ add_library(GPU OBJECT
|
|||
GPU/GLES/GLES_GPU.h
|
||||
GPU/GLES/FragmentShaderGenerator.cpp
|
||||
GPU/GLES/FragmentShaderGenerator.h
|
||||
GPU/GLES/FragmentTestCache.cpp
|
||||
GPU/GLES/FragmentTestCache.h
|
||||
GPU/GLES/Framebuffer.cpp
|
||||
GPU/GLES/Framebuffer.h
|
||||
GPU/GLES/ShaderManager.cpp
|
||||
|
|
|
@ -441,6 +441,7 @@ static ConfigSetting graphicsSettings[] = {
|
|||
|
||||
ReportedConfigSetting("MemBlockTransferGPU", &g_Config.bBlockTransferGPU, true),
|
||||
ReportedConfigSetting("DisableSlowFramebufEffects", &g_Config.bDisableSlowFramebufEffects, false),
|
||||
ReportedConfigSetting("FragmentTestCache", &g_Config.bFragmentTestCache, true),
|
||||
|
||||
ConfigSetting(false),
|
||||
};
|
||||
|
|
|
@ -161,6 +161,7 @@ public:
|
|||
bool bAlphaMaskHack;
|
||||
bool bBlockTransferGPU;
|
||||
bool bDisableSlowFramebufEffects;
|
||||
bool bFragmentTestCache;
|
||||
int iSplineBezierQuality; // 0 = low , 1 = Intermediate , 2 = High
|
||||
std::string sPostShaderName; // Off for off.
|
||||
|
||||
|
|
|
@ -567,9 +567,13 @@ void GenerateFragmentShader(char *buffer) {
|
|||
}
|
||||
|
||||
if (enableAlphaTest || enableColorTest) {
|
||||
WRITE(p, "uniform vec4 u_alphacolorref;\n");
|
||||
if (bitwiseOps && (enableColorTest || !alphaTestAgainstZero)) {
|
||||
WRITE(p, "uniform ivec4 u_alphacolormask;\n");
|
||||
if (g_Config.bFragmentTestCache) {
|
||||
WRITE(p, "uniform sampler2D testtex;\n");
|
||||
} else {
|
||||
WRITE(p, "uniform vec4 u_alphacolorref;\n");
|
||||
if (bitwiseOps && (enableColorTest || !alphaTestAgainstZero)) {
|
||||
WRITE(p, "uniform ivec4 u_alphacolormask;\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (stencilToAlpha && ReplaceAlphaWithStencilType() == STENCIL_VALUE_UNIFORM) {
|
||||
|
@ -592,22 +596,24 @@ void GenerateFragmentShader(char *buffer) {
|
|||
WRITE(p, "%s mediump vec2 v_texcoord;\n", varying);
|
||||
}
|
||||
|
||||
if (enableAlphaTest && !alphaTestAgainstZero) {
|
||||
if (bitwiseOps) {
|
||||
WRITE(p, "int roundAndScaleTo255i(in float x) { return int(floor(x * 255.0 + 0.5)); }\n");
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
WRITE(p, "float roundTo255thf(in mediump float x) { mediump float y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n");
|
||||
} else {
|
||||
WRITE(p, "float roundAndScaleTo255f(in float x) { return floor(x * 255.0 + 0.5); }\n");
|
||||
if (!g_Config.bFragmentTestCache) {
|
||||
if (enableAlphaTest && !alphaTestAgainstZero) {
|
||||
if (bitwiseOps) {
|
||||
WRITE(p, "int roundAndScaleTo255i(in float x) { return int(floor(x * 255.0 + 0.5)); }\n");
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
WRITE(p, "float roundTo255thf(in mediump float x) { mediump float y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n");
|
||||
} else {
|
||||
WRITE(p, "float roundAndScaleTo255f(in float x) { return floor(x * 255.0 + 0.5); }\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (enableColorTest) {
|
||||
if (bitwiseOps) {
|
||||
WRITE(p, "ivec3 roundAndScaleTo255iv(in vec3 x) { return ivec3(floor(x * 255.0 + 0.5)); }\n");
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
WRITE(p, "vec3 roundTo255thv(in vec3 x) { vec3 y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n");
|
||||
} else {
|
||||
WRITE(p, "vec3 roundAndScaleTo255v(in vec3 x) { return floor(x * 255.0 + 0.5); }\n");
|
||||
if (enableColorTest) {
|
||||
if (bitwiseOps) {
|
||||
WRITE(p, "ivec3 roundAndScaleTo255iv(in vec3 x) { return ivec3(floor(x * 255.0 + 0.5)); }\n");
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
WRITE(p, "vec3 roundTo255thv(in vec3 x) { vec3 y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n");
|
||||
} else {
|
||||
WRITE(p, "vec3 roundAndScaleTo255v(in vec3 x) { return floor(x * 255.0 + 0.5); }\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -748,51 +754,68 @@ void GenerateFragmentShader(char *buffer) {
|
|||
}
|
||||
|
||||
if (enableAlphaTest) {
|
||||
GEComparison alphaTestFunc = gstate.getAlphaTestFunction();
|
||||
const char *alphaTestFuncs[] = { "#", "#", " != ", " == ", " >= ", " > ", " <= ", " < " };
|
||||
if (alphaTestFuncs[alphaTestFunc][0] != '#') {
|
||||
if (alphaTestAgainstZero) {
|
||||
// When testing against 0 (extremely common), we can avoid some math.
|
||||
// 0.002 is approximately half of 1.0 / 255.0.
|
||||
if (alphaTestFunc == GE_COMP_NOTEQUAL || alphaTestFunc == GE_COMP_GREATER) {
|
||||
WRITE(p, " if (v.a < 0.002) discard;\n");
|
||||
} else {
|
||||
// Anything else is a test for == 0. Happens sometimes, actually...
|
||||
WRITE(p, " if (v.a > 0.002) discard;\n");
|
||||
}
|
||||
} else if (bitwiseOps) {
|
||||
WRITE(p, " if ((roundAndScaleTo255i(v.a) & u_alphacolormask.a) %s int(u_alphacolorref.a)) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
// Work around bad PVR driver problem where equality check + discard just doesn't work.
|
||||
if (alphaTestFunc != GE_COMP_NOTEQUAL)
|
||||
WRITE(p, " if (roundTo255thf(v.a) %s u_alphacolorref.a) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
if (alphaTestAgainstZero) {
|
||||
GEComparison alphaTestFunc = gstate.getAlphaTestFunction();
|
||||
// When testing against 0 (extremely common), we can avoid some math.
|
||||
// 0.002 is approximately half of 1.0 / 255.0.
|
||||
if (alphaTestFunc == GE_COMP_NOTEQUAL || alphaTestFunc == GE_COMP_GREATER) {
|
||||
WRITE(p, " if (v.a < 0.002) discard;\n");
|
||||
} else if (alphaTestFunc != GE_COMP_NEVER) {
|
||||
// Anything else is a test for == 0. Happens sometimes, actually...
|
||||
WRITE(p, " if (v.a > 0.002) discard;\n");
|
||||
} else {
|
||||
WRITE(p, " if (roundAndScaleTo255f(v.a) %s u_alphacolorref.a) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
// NEVER has been logged as used by games, although it makes little sense - statically failing.
|
||||
// Maybe we could discard the drawcall, but it's pretty rare. Let's just statically discard here.
|
||||
WRITE(p, " discard;\n");
|
||||
}
|
||||
} else if (g_Config.bFragmentTestCache) {
|
||||
WRITE(p, " float aResult = %s(testtex, vec2(v.a, 0)).a;\n", texture);
|
||||
WRITE(p, " if (aResult < 0.5) discard;\n", texture);
|
||||
} else {
|
||||
// NEVER has been logged as used by games, although it makes little sense - statically failing.
|
||||
// Maybe we could discard the drawcall, but it's pretty rare. Let's just statically discard here.
|
||||
WRITE(p, " discard;\n");
|
||||
GEComparison alphaTestFunc = gstate.getAlphaTestFunction();
|
||||
const char *alphaTestFuncs[] = { "#", "#", " != ", " == ", " >= ", " > ", " <= ", " < " };
|
||||
if (alphaTestFuncs[alphaTestFunc][0] != '#') {
|
||||
if (bitwiseOps) {
|
||||
WRITE(p, " if ((roundAndScaleTo255i(v.a) & u_alphacolormask.a) %s int(u_alphacolorref.a)) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
// Work around bad PVR driver problem where equality check + discard just doesn't work.
|
||||
if (alphaTestFunc != GE_COMP_NOTEQUAL) {
|
||||
WRITE(p, " if (roundTo255thf(v.a) %s u_alphacolorref.a) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
}
|
||||
} else {
|
||||
WRITE(p, " if (roundAndScaleTo255f(v.a) %s u_alphacolorref.a) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
}
|
||||
} else {
|
||||
// This means NEVER. See above.
|
||||
WRITE(p, " discard;\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enableColorTest) {
|
||||
GEComparison colorTestFunc = gstate.getColorTestFunction();
|
||||
const char *colorTestFuncs[] = { "#", "#", " != ", " == " };
|
||||
if (colorTestFuncs[colorTestFunc][0] != '#') {
|
||||
if (bitwiseOps) {
|
||||
// Apparently GLES3 does not support vector bitwise ops.
|
||||
WRITE(p, " ivec3 v_scaled = roundAndScaleTo255iv(v.rgb);\n");
|
||||
const char *maskedFragColor = "ivec3(v_scaled.r & u_alphacolormask.r, v_scaled.g & u_alphacolormask.g, v_scaled.b & u_alphacolormask.b)";
|
||||
const char *maskedColorRef = "ivec3(int(u_alphacolorref.r) & u_alphacolormask.r, int(u_alphacolorref.g) & u_alphacolormask.g, int(u_alphacolorref.b) & u_alphacolormask.b)";
|
||||
WRITE(p, " if (%s %s %s) discard;\n", maskedFragColor, colorTestFuncs[colorTestFunc], maskedColorRef);
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
WRITE(p, " if (roundTo255thv(v.rgb) %s u_alphacolorref.rgb) discard;\n", colorTestFuncs[colorTestFunc]);
|
||||
} else {
|
||||
WRITE(p, " if (roundAndScaleTo255v(v.rgb) %s u_alphacolorref.rgb) discard;\n", colorTestFuncs[colorTestFunc]);
|
||||
}
|
||||
if (g_Config.bFragmentTestCache) {
|
||||
WRITE(p, " float rResult = %s(testtex, vec2(v.r, 0)).r;\n", texture);
|
||||
WRITE(p, " float gResult = %s(testtex, vec2(v.g, 0)).g;\n", texture);
|
||||
WRITE(p, " float bResult = %s(testtex, vec2(v.b, 0)).b;\n", texture);
|
||||
WRITE(p, " if (rResult < 0.5 || gResult < 0.5 || bResult < 0.5) discard;\n", texture);
|
||||
} else {
|
||||
WRITE(p, " discard;\n");
|
||||
GEComparison colorTestFunc = gstate.getColorTestFunction();
|
||||
const char *colorTestFuncs[] = { "#", "#", " != ", " == " };
|
||||
if (colorTestFuncs[colorTestFunc][0] != '#') {
|
||||
if (bitwiseOps) {
|
||||
// Apparently GLES3 does not support vector bitwise ops.
|
||||
WRITE(p, " ivec3 v_scaled = roundAndScaleTo255iv(v.rgb);\n");
|
||||
const char *maskedFragColor = "ivec3(v_scaled.r & u_alphacolormask.r, v_scaled.g & u_alphacolormask.g, v_scaled.b & u_alphacolormask.b)";
|
||||
const char *maskedColorRef = "ivec3(int(u_alphacolorref.r) & u_alphacolormask.r, int(u_alphacolorref.g) & u_alphacolormask.g, int(u_alphacolorref.b) & u_alphacolormask.b)";
|
||||
WRITE(p, " if (%s %s %s) discard;\n", maskedFragColor, colorTestFuncs[colorTestFunc], maskedColorRef);
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_POWERVR) {
|
||||
WRITE(p, " if (roundTo255thv(v.rgb) %s u_alphacolorref.rgb) discard;\n", colorTestFuncs[colorTestFunc]);
|
||||
} else {
|
||||
WRITE(p, " if (roundAndScaleTo255v(v.rgb) %s u_alphacolorref.rgb) discard;\n", colorTestFuncs[colorTestFunc]);
|
||||
}
|
||||
} else {
|
||||
WRITE(p, " discard;\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
167
GPU/GLES/FragmentTestCache.cpp
Normal file
167
GPU/GLES/FragmentTestCache.cpp
Normal file
|
@ -0,0 +1,167 @@
|
|||
// Copyright (c) 2014- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "GPU/GLES/FragmentTestCache.h"
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
static const int FRAGTEST_TEXTURE_OLD_AGE = 123;
|
||||
|
||||
FragmentTestCache::FragmentTestCache() : textureCache_(NULL), lastTexture_(0) {
|
||||
scratchpad_ = new u8[256 * 4];
|
||||
}
|
||||
|
||||
FragmentTestCache::~FragmentTestCache() {
|
||||
Clear();
|
||||
delete [] scratchpad_;
|
||||
}
|
||||
|
||||
void FragmentTestCache::BindTestTexture(GLenum unit) {
|
||||
if (!g_Config.bFragmentTestCache) {
|
||||
return;
|
||||
}
|
||||
|
||||
const FragmentTestID id = GenerateTestID();
|
||||
const auto cached = cache_.find(id);
|
||||
if (cached != cache_.end()) {
|
||||
GLuint tex = cached->second.texture;
|
||||
if (tex == lastTexture_) {
|
||||
// Already bound, hurray.
|
||||
return;
|
||||
}
|
||||
glActiveTexture(unit);
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
// Always return to the default.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
return;
|
||||
}
|
||||
|
||||
const u8 rRef = (gstate.getColorTestRef() >> 0) & 0xFF;
|
||||
const u8 rMask = (gstate.getColorTestMask() >> 0) & 0xFF;
|
||||
const u8 gRef = (gstate.getColorTestRef() >> 8) & 0xFF;
|
||||
const u8 gMask = (gstate.getColorTestMask() >> 8) & 0xFF;
|
||||
const u8 bRef = (gstate.getColorTestRef() >> 16) & 0xFF;
|
||||
const u8 bMask = (gstate.getColorTestMask() >> 16) & 0xFF;
|
||||
const u8 aRef = gstate.getAlphaTestRef();
|
||||
const u8 aMask = gstate.getAlphaTestMask();
|
||||
const u8 refs[4] = {rRef, gRef, bRef, aRef};
|
||||
const u8 masks[4] = {rMask, gMask, bMask, aMask};
|
||||
const GEComparison funcs[4] = {gstate.getColorTestFunction(), gstate.getColorTestFunction(), gstate.getColorTestFunction(), gstate.getAlphaTestFunction()};
|
||||
const bool valid[4] = {gstate.isColorTestEnabled(), gstate.isColorTestEnabled(), gstate.isColorTestEnabled(), gstate.isAlphaTestEnabled()};
|
||||
|
||||
glActiveTexture(unit);
|
||||
// This will necessarily bind the texture.
|
||||
const GLuint tex = CreateCache(funcs, refs, masks, valid);
|
||||
// Always return to the default.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
FragmentTestTexture item;
|
||||
item.lastFrame = gpuStats.numFlips;
|
||||
item.texture = tex;
|
||||
cache_[id] = item;
|
||||
}
|
||||
|
||||
FragmentTestID FragmentTestCache::GenerateTestID() const {
|
||||
FragmentTestID id;
|
||||
// Let's just keep it simple, it's all in here.
|
||||
id.alpha = gstate.isAlphaTestEnabled() ? gstate.alphatest : 0;
|
||||
if (gstate.isColorTestEnabled()) {
|
||||
id.colorRefFunc = gstate.getColorTestFunction() | (gstate.getColorTestRef() << 8);
|
||||
id.colorMask = gstate.getColorTestMask();
|
||||
} else {
|
||||
id.colorRefFunc = 0;
|
||||
id.colorMask = 0;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
GLuint FragmentTestCache::CreateCache(const GEComparison funcs[4], const u8 refs[4], const u8 masks[4], const bool valid[4]) {
|
||||
// TODO: Might it be better to use GL_ALPHA for simple textures?
|
||||
// TODO: Experiment with 4-bit/etc. textures.
|
||||
|
||||
GLuint tex = textureCache_->AllocTextureName();
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
// Build the logic map.
|
||||
for (int color = 0; color < 256; ++color) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
bool res;
|
||||
if (valid[i]) {
|
||||
switch (funcs[i]) {
|
||||
case GE_COMP_NEVER:
|
||||
res = false;
|
||||
break;
|
||||
case GE_COMP_ALWAYS:
|
||||
res = true;
|
||||
break;
|
||||
case GE_COMP_EQUAL:
|
||||
res = (color & masks[i]) == (refs[i] & masks[i]);
|
||||
break;
|
||||
case GE_COMP_NOTEQUAL:
|
||||
res = (color & masks[i]) != (refs[i] & masks[i]);
|
||||
break;
|
||||
case GE_COMP_LESS:
|
||||
res = (color & masks[i]) < (refs[i] & masks[i]);
|
||||
break;
|
||||
case GE_COMP_LEQUAL:
|
||||
res = (color & masks[i]) <= (refs[i] & masks[i]);
|
||||
break;
|
||||
case GE_COMP_GREATER:
|
||||
res = (color & masks[i]) > (refs[i] & masks[i]);
|
||||
break;
|
||||
case GE_COMP_GEQUAL:
|
||||
res = (color & masks[i]) >= (refs[i] & masks[i]);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
res = true;
|
||||
}
|
||||
scratchpad_[color * 4 + i] = res ? 0xFF : 0;
|
||||
}
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, scratchpad_);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
void FragmentTestCache::Clear(bool deleteThem) {
|
||||
if (deleteThem) {
|
||||
for (auto tex = cache_.begin(); tex != cache_.end(); ++tex) {
|
||||
glDeleteTextures(1, &tex->second.texture);
|
||||
}
|
||||
}
|
||||
cache_.clear();
|
||||
lastTexture_ = 0;
|
||||
}
|
||||
|
||||
void FragmentTestCache::Decimate() {
|
||||
for (auto tex = cache_.begin(); tex != cache_.end(); ) {
|
||||
if (tex->second.lastFrame + FRAGTEST_TEXTURE_OLD_AGE < gpuStats.numFlips) {
|
||||
glDeleteTextures(1, &tex->second.texture);
|
||||
cache_.erase(tex++);
|
||||
} else {
|
||||
++tex;
|
||||
}
|
||||
}
|
||||
lastTexture_ = 0;
|
||||
}
|
83
GPU/GLES/FragmentTestCache.h
Normal file
83
GPU/GLES/FragmentTestCache.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
// Copyright (c) 2014- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "gfx_es2/gl_state.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/GLES/TextureCache.h"
|
||||
|
||||
struct FragmentTestID {
|
||||
union {
|
||||
struct {
|
||||
u32 alpha;
|
||||
u32 colorRefFunc;
|
||||
u32 colorMask;
|
||||
};
|
||||
u32 d[3];
|
||||
};
|
||||
|
||||
bool operator < (const FragmentTestID &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 FragmentTestID &other) const {
|
||||
for (size_t i = 0; i < sizeof(d) / sizeof(u32); i++) {
|
||||
if (d[i] != other.d[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct FragmentTestTexture {
|
||||
GLuint texture;
|
||||
int lastFrame;
|
||||
};
|
||||
|
||||
class FragmentTestCache {
|
||||
public:
|
||||
FragmentTestCache();
|
||||
~FragmentTestCache();
|
||||
|
||||
void SetTextureCache(TextureCache *tc) {
|
||||
textureCache_ = tc;
|
||||
}
|
||||
|
||||
void BindTestTexture(GLenum unit);
|
||||
|
||||
void Clear(bool deleteThem = true);
|
||||
void Decimate();
|
||||
|
||||
private:
|
||||
|
||||
GLuint CreateCache(const GEComparison funcs[4], const u8 refs[4], const u8 masks[4], const bool valid[4]);
|
||||
FragmentTestID GenerateTestID() const;
|
||||
|
||||
TextureCache *textureCache_;
|
||||
|
||||
std::map<FragmentTestID, FragmentTestTexture> cache_;
|
||||
u8 *scratchpad_;
|
||||
GLuint lastTexture_;
|
||||
};
|
|
@ -397,6 +397,7 @@ GLES_GPU::GLES_GPU()
|
|||
transformDraw_.SetShaderManager(shaderManager_);
|
||||
transformDraw_.SetTextureCache(&textureCache_);
|
||||
transformDraw_.SetFramebufferManager(&framebufferManager_);
|
||||
transformDraw_.SetFragmentTestCache(&fragmentTestCache_);
|
||||
framebufferManager_.Init();
|
||||
framebufferManager_.SetTextureCache(&textureCache_);
|
||||
framebufferManager_.SetShaderManager(shaderManager_);
|
||||
|
@ -404,6 +405,7 @@ GLES_GPU::GLES_GPU()
|
|||
textureCache_.SetFramebufferManager(&framebufferManager_);
|
||||
textureCache_.SetDepalShaderCache(&depalShaderCache_);
|
||||
textureCache_.SetShaderManager(shaderManager_);
|
||||
fragmentTestCache_.SetTextureCache(&textureCache_);
|
||||
|
||||
// Sanity check gstate
|
||||
if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) {
|
||||
|
@ -447,6 +449,7 @@ GLES_GPU::~GLES_GPU() {
|
|||
framebufferManager_.DestroyAllFBOs();
|
||||
shaderManager_->ClearCache(true);
|
||||
depalShaderCache_.Clear();
|
||||
fragmentTestCache_.Clear();
|
||||
delete shaderManager_;
|
||||
glstate.SetVSyncInterval(0);
|
||||
}
|
||||
|
@ -484,6 +487,7 @@ void GLES_GPU::DeviceLost() {
|
|||
// TransformDraw has registered as a GfxResourceHolder.
|
||||
shaderManager_->ClearCache(false);
|
||||
textureCache_.Clear(false);
|
||||
fragmentTestCache_.Clear(false);
|
||||
depalShaderCache_.Clear();
|
||||
framebufferManager_.DeviceLost();
|
||||
|
||||
|
@ -585,6 +589,7 @@ void GLES_GPU::BeginFrameInternal() {
|
|||
textureCache_.StartFrame();
|
||||
transformDraw_.DecimateTrackedVertexArrays();
|
||||
depalShaderCache_.Decimate();
|
||||
fragmentTestCache_.Decimate();
|
||||
|
||||
if (dumpNextFrame_) {
|
||||
NOTICE_LOG(G3D, "DUMPING THIS FRAME");
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "GPU/GLES/TransformPipeline.h"
|
||||
#include "GPU/GLES/TextureCache.h"
|
||||
#include "GPU/GLES/DepalettizeShader.h"
|
||||
#include "GPU/GLES/FragmentTestCache.h"
|
||||
|
||||
class ShaderManager;
|
||||
class LinkedShader;
|
||||
|
@ -173,6 +174,7 @@ private:
|
|||
TextureCache textureCache_;
|
||||
DepalShaderCache depalShaderCache_;
|
||||
TransformDrawEngine transformDraw_;
|
||||
FragmentTestCache fragmentTestCache_;
|
||||
ShaderManager *shaderManager_;
|
||||
|
||||
bool resized_;
|
||||
|
|
|
@ -147,6 +147,7 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans
|
|||
u_alphacolorref = glGetUniformLocation(program, "u_alphacolorref");
|
||||
u_alphacolormask = glGetUniformLocation(program, "u_alphacolormask");
|
||||
u_stencilReplaceValue = glGetUniformLocation(program, "u_stencilReplaceValue");
|
||||
u_testtex = glGetUniformLocation(program, "testtex");
|
||||
|
||||
u_fbotex = glGetUniformLocation(program, "fbotex");
|
||||
u_blendFixA = glGetUniformLocation(program, "u_blendFixA");
|
||||
|
@ -258,6 +259,7 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans
|
|||
// Default uniform values
|
||||
glUniform1i(u_tex, 0);
|
||||
glUniform1i(u_fbotex, 1);
|
||||
glUniform1i(u_testtex, 2);
|
||||
// The rest, use the "dirty" mechanism.
|
||||
dirtyUniforms = DIRTY_ALL;
|
||||
use(vertType, previous);
|
||||
|
|
|
@ -82,6 +82,7 @@ public:
|
|||
// Fragment processing inputs
|
||||
int u_alphacolorref;
|
||||
int u_alphacolormask;
|
||||
int u_testtex;
|
||||
int u_fogcolor;
|
||||
int u_fogcoef;
|
||||
|
||||
|
|
|
@ -639,6 +639,10 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
|
|||
} else {
|
||||
glstate.stencilTest.disable();
|
||||
}
|
||||
|
||||
if (gstate.isAlphaTestEnabled() || gstate.isColorTestEnabled()) {
|
||||
fragmentTestCache_->BindTestTexture(GL_TEXTURE2);
|
||||
}
|
||||
}
|
||||
|
||||
bool throughmode = gstate.isModeThrough();
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
|
||||
#include "GPU/Common/TextureDecoder.h"
|
||||
#include "GPU/Common/SplineCommon.h"
|
||||
#include "GPU/GLES/FragmentTestCache.h"
|
||||
#include "GPU/GLES/StateMapping.h"
|
||||
#include "GPU/GLES/TextureCache.h"
|
||||
#include "GPU/GLES/TransformPipeline.h"
|
||||
|
|
|
@ -29,6 +29,7 @@ class LinkedShader;
|
|||
class ShaderManager;
|
||||
class TextureCache;
|
||||
class FramebufferManager;
|
||||
class FragmentTestCache;
|
||||
struct TransformedVertex;
|
||||
|
||||
struct DecVtxFormat;
|
||||
|
@ -116,6 +117,9 @@ public:
|
|||
void SetFramebufferManager(FramebufferManager *fbManager) {
|
||||
framebufferManager_ = fbManager;
|
||||
}
|
||||
void SetFragmentTestCache(FragmentTestCache *testCache) {
|
||||
fragmentTestCache_ = testCache;
|
||||
}
|
||||
void InitDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
void GLLost();
|
||||
|
@ -236,6 +240,7 @@ private:
|
|||
ShaderManager *shaderManager_;
|
||||
TextureCache *textureCache_;
|
||||
FramebufferManager *framebufferManager_;
|
||||
FragmentTestCache *fragmentTestCache_;
|
||||
|
||||
enum { MAX_DEFERRED_DRAW_CALLS = 128 };
|
||||
DeferredDrawCall drawCalls[MAX_DEFERRED_DRAW_CALLS];
|
||||
|
|
|
@ -192,6 +192,7 @@
|
|||
<ClInclude Include="GeDisasm.h" />
|
||||
<ClInclude Include="GLES\DepalettizeShader.h" />
|
||||
<ClInclude Include="GLES\FragmentShaderGenerator.h" />
|
||||
<ClInclude Include="GLES\FragmentTestCache.h" />
|
||||
<ClInclude Include="GLES\Framebuffer.h" />
|
||||
<ClInclude Include="GLES\GLES_GPU.h" />
|
||||
<ClInclude Include="GLES\ShaderManager.h" />
|
||||
|
@ -245,6 +246,7 @@
|
|||
<ClCompile Include="GeDisasm.cpp" />
|
||||
<ClCompile Include="GLES\DepalettizeShader.cpp" />
|
||||
<ClCompile Include="GLES\FragmentShaderGenerator.cpp" />
|
||||
<ClCompile Include="GLES\FragmentTestCache.cpp" />
|
||||
<ClCompile Include="GLES\Framebuffer.cpp" />
|
||||
<ClCompile Include="GLES\GLES_GPU.cpp" />
|
||||
<ClCompile Include="GLES\ShaderManager.cpp" />
|
||||
|
|
|
@ -168,6 +168,9 @@
|
|||
<ClInclude Include="GLES\DepalettizeShader.h">
|
||||
<Filter>GLES</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GLES\FragmentTestCache.h">
|
||||
<Filter>GLES</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Math3D.cpp">
|
||||
|
@ -317,6 +320,9 @@
|
|||
<ClCompile Include="GLES\StencilBuffer.cpp">
|
||||
<Filter>GLES</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GLES\FragmentTestCache.cpp">
|
||||
<Filter>GLES</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
|
|
@ -28,6 +28,7 @@ SOURCES += $$P/GPU/GeDisasm.cpp \ # GPU
|
|||
$$P/GPU/Null/NullGpu.cpp \
|
||||
$$P/GPU/GLES/DepalettizeShader.cpp \
|
||||
$$P/GPU/GLES/FragmentShaderGenerator.cpp \
|
||||
$$P/GPU/GLES/FragmentTestCache.cpp \
|
||||
$$P/GPU/GLES/Framebuffer.cpp \
|
||||
$$P/GPU/GLES/GLES_GPU.cpp \
|
||||
$$P/GPU/GLES/ShaderManager.cpp \
|
||||
|
|
|
@ -155,6 +155,7 @@ EXEC_AND_LIB_FILES := \
|
|||
$(SRC)/GPU/GLES/ShaderManager.cpp.arm \
|
||||
$(SRC)/GPU/GLES/VertexShaderGenerator.cpp.arm \
|
||||
$(SRC)/GPU/GLES/FragmentShaderGenerator.cpp.arm \
|
||||
$(SRC)/GPU/GLES/FragmentTestCache.cpp.arm \
|
||||
$(SRC)/GPU/GLES/TextureScaler.cpp \
|
||||
$(SRC)/GPU/GLES/Spline.cpp \
|
||||
$(SRC)/GPU/Null/NullGpu.cpp \
|
||||
|
|
Loading…
Add table
Reference in a new issue