samplerjit: Create a separate fetch func.

This allows nearest to become more similar to linear, where it applies the
texture function.
This commit is contained in:
Unknown W. Brackets 2021-12-31 10:35:26 -08:00
parent 3bc6009158
commit 06e954fe2a
7 changed files with 67 additions and 12 deletions

View File

@ -448,6 +448,9 @@ std::string DescribeSamplerID(const SamplerID &id) {
if (id.linear) {
name += ":LERP";
}
if (id.fetch) {
name += ":FETCH";
}
if (id.useTextureAlpha) {
name += ":A";
}

View File

@ -160,7 +160,7 @@ struct SamplerID {
bool useColorDoubling : 1;
bool hasStandardMips : 1;
bool hasAnyMips : 1;
bool : 1;
bool fetch : 1;
};
};

View File

@ -1326,13 +1326,15 @@ bool GetCurrentTexture(GPUDebugBuffer &buffer, int level)
buffer.Allocate(w, h, GE_FORMAT_8888, false);
Sampler::Funcs sampler = Sampler::GetFuncs();
SamplerID id;
ComputeSamplerID(&id);
Sampler::FetchFunc sampler = Sampler::GetFetchFunc(id);
u8 *texptr = Memory::GetPointer(texaddr);
u32 *row = (u32 *)buffer.GetData();
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
row[x] = Vec4<int>(sampler.nearest(x, y, texptr, texbufw, level)).ToRGBA();
row[x] = Vec4<int>(sampler(x, y, texptr, texbufw, level)).ToRGBA();
}
row += w;
}

View File

@ -91,7 +91,7 @@ void DrawSprite(const VertexData& v0, const VertexData& v1) {
ComputePixelFuncID(&pixelID);
ScreenCoords pprime(v0.screenpos.x, v0.screenpos.y, 0);
Sampler::NearestFunc nearestFunc = Sampler::GetNearestFunc(samplerID);
Sampler::FetchFunc fetchFunc = Sampler::GetFetchFunc(samplerID);
Rasterizer::SingleFunc drawPixel = Rasterizer::GetSingleFunc(pixelID);
DrawingCoords pos0 = TransformUnit::ScreenToDrawing(v0.screenpos);
@ -156,7 +156,7 @@ void DrawSprite(const VertexData& v0, const VertexData& v1) {
int s = s_start;
u16 *pixel = fb.Get16Ptr(pos0.x, y, gstate.FrameBufStride());
for (int x = pos0.x; x < pos1.x; x++) {
u32 tex_color = Vec4<int>(nearestFunc(s, t, texptr, texbufw, 0)).ToRGBA();
u32 tex_color = Vec4<int>(fetchFunc(s, t, texptr, texbufw, 0)).ToRGBA();
if (tex_color & 0xFF000000) {
DrawSinglePixel5551(pixel, tex_color, pixelID);
}
@ -174,7 +174,7 @@ void DrawSprite(const VertexData& v0, const VertexData& v1) {
u16 *pixel = fb.Get16Ptr(pos0.x, y, gstate.FrameBufStride());
for (int x = pos0.x; x < pos1.x; x++) {
Vec4<int> prim_color = v1.color0;
Vec4<int> tex_color = nearestFunc(s, t, texptr, texbufw, 0);
Vec4<int> tex_color = fetchFunc(s, t, texptr, texbufw, 0);
prim_color = Vec4<int>(ModulateRGBA(ToVec4IntArg(prim_color), ToVec4IntArg(tex_color)));
if (prim_color.a() > 0) {
DrawSinglePixel5551(pixel, prim_color.ToRGBA(), pixelID);
@ -194,7 +194,7 @@ void DrawSprite(const VertexData& v0, const VertexData& v1) {
// Not really that fast but faster than triangle.
for (int x = pos0.x; x < pos1.x; x++) {
Vec4<int> prim_color = v1.color0;
Vec4<int> tex_color = nearestFunc(s, t, texptr, texbufw, 0);
Vec4<int> tex_color = fetchFunc(s, t, texptr, texbufw, 0);
prim_color = GetTextureFunctionOutput(ToVec4IntArg(prim_color), ToVec4IntArg(tex_color));
drawPixel(x, y, z, 255, ToVec4IntArg(prim_color), pixelID);
s += ds;

View File

@ -41,6 +41,7 @@ namespace Sampler {
static Vec4IntResult SOFTRAST_CALL SampleNearest(int u, int v, const u8 *tptr, int bufw, int level);
static Vec4IntResult SOFTRAST_CALL SampleLinear(float s, float t, int x, int y, Vec4IntArg prim_color, const u8 **tptr, const int *bufw, int level, int levelFrac);
static Vec4IntResult SOFTRAST_CALL SampleFetch(int u, int v, const u8 *tptr, int bufw, int level);
std::mutex jitCacheLock;
SamplerJitCache *jitCache = nullptr;
@ -83,6 +84,16 @@ LinearFunc GetLinearFunc(SamplerID id) {
return &SampleLinear;
}
FetchFunc GetFetchFunc(SamplerID id) {
id.fetch = true;
FetchFunc jitted = jitCache->GetFetch(id);
if (jitted) {
return jitted;
}
return &SampleFetch;
}
SamplerJitCache::SamplerJitCache()
#if PPSSPP_ARCH(ARM64)
: fp(this)
@ -146,7 +157,7 @@ NearestFunc SamplerJitCache::GetNearest(const SamplerID &id) {
auto it = cache_.find(id);
if (it != cache_.end()) {
return it->second;
return (NearestFunc)it->second;
}
// TODO: What should be the min size? Can we even hit this?
@ -157,8 +168,8 @@ NearestFunc SamplerJitCache::GetNearest(const SamplerID &id) {
#if PPSSPP_ARCH(AMD64) && !PPSSPP_PLATFORM(UWP)
if (g_Config.bSoftwareRenderingJit) {
addresses_[id] = GetCodePointer();
NearestFunc func = Compile(id);
cache_[id] = func;
NearestFunc func = CompileNearest(id);
cache_[id] = (NearestFunc)func;
return func;
}
#endif
@ -189,6 +200,30 @@ LinearFunc SamplerJitCache::GetLinear(const SamplerID &id) {
return nullptr;
}
FetchFunc SamplerJitCache::GetFetch(const SamplerID &id) {
std::lock_guard<std::mutex> guard(jitCacheLock);
auto it = cache_.find(id);
if (it != cache_.end()) {
return (FetchFunc)it->second;
}
// TODO: What should be the min size? Can we even hit this?
if (GetSpaceLeft() < 16384) {
Clear();
}
#if PPSSPP_ARCH(AMD64) && !PPSSPP_PLATFORM(UWP)
if (g_Config.bSoftwareRenderingJit) {
addresses_[id] = GetCodePointer();
FetchFunc func = CompileFetch(id);
cache_[id] = (NearestFunc)func;
return func;
}
#endif
return nullptr;
}
template <unsigned int texel_size_bits>
static inline int GetPixelDataOffset(unsigned int row_pitch_pixels, unsigned int u, unsigned int v)
{
@ -349,6 +384,11 @@ static Vec4IntResult SOFTRAST_CALL SampleNearest(int u, int v, const u8 *tptr, i
return ToVec4IntResult(Vec4<int>::FromRGBA(c.v[0]));
}
static Vec4IntResult SOFTRAST_CALL SampleFetch(int u, int v, const u8 *tptr, int bufw, int level) {
Nearest4 c = SampleNearest<1>(&u, &v, tptr, bufw, level);
return ToVec4IntResult(Vec4<int>::FromRGBA(c.v[0]));
}
static inline int ClampUV(int v, int height) {
if (v >= height - 1)
return height - 1;

View File

@ -33,6 +33,9 @@ namespace Sampler {
#pragma GCC diagnostic ignored "-Wignored-attributes"
#endif
typedef Rasterizer::Vec4IntResult(SOFTRAST_CALL *FetchFunc)(int u, int v, const u8 *tptr, int bufw, int level);
FetchFunc GetFetchFunc(SamplerID id);
typedef Rasterizer::Vec4IntResult (SOFTRAST_CALL *NearestFunc)(int u, int v, const u8 *tptr, int bufw, int level);
NearestFunc GetNearestFunc(SamplerID id);
@ -64,12 +67,14 @@ public:
// Returns a pointer to the code to run.
NearestFunc GetNearest(const SamplerID &id);
LinearFunc GetLinear(const SamplerID &id);
FetchFunc GetFetch(const SamplerID &id);
void Clear();
std::string DescribeCodePtr(const u8 *ptr);
private:
NearestFunc Compile(const SamplerID &id);
FetchFunc CompileFetch(const SamplerID &id);
NearestFunc CompileNearest(const SamplerID &id);
LinearFunc CompileLinear(const SamplerID &id);
void Describe(const std::string &message);

View File

@ -33,7 +33,12 @@ extern u32 clut[4096];
namespace Sampler {
NearestFunc SamplerJitCache::Compile(const SamplerID &id) {
FetchFunc SamplerJitCache::CompileFetch(const SamplerID &id) {
// TODO: Make these different.
return CompileNearest(id);
}
NearestFunc SamplerJitCache::CompileNearest(const SamplerID &id) {
regCache_.SetupABI({
RegCache::GEN_ARG_U,
RegCache::GEN_ARG_V,