mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Merge pull request #21784 from hrydgard/smarter-2d-filter
Smart 2D texture filtering: Use the new vertex path to check for pixel mapping in transformed geometry
This commit is contained in:
@@ -461,6 +461,11 @@ static bool TestBoundingBoxFast(const float *cullMatrix, const void *vdata, cons
|
||||
flags |= ClipInfoFlags::SoftClipCull;
|
||||
}
|
||||
|
||||
if (minProjZ == maxProjZ) {
|
||||
// Probably a 2D draw. Send it through software transform!
|
||||
flags |= ClipInfoFlags::FlatZ | ClipInfoFlags::SoftClipCull;
|
||||
}
|
||||
|
||||
if (needFragmentDepthClamp() && (minProjZ < 0 || maxProjZ > 65535)) {
|
||||
if (gstate_c.Use(GPU_USE_DEPTH_CLAMP)) {
|
||||
flags |= ClipInfoFlags::DepthClamp;
|
||||
|
||||
@@ -73,16 +73,6 @@ struct alignas(16) Plane8 {
|
||||
float Test(int i, const float f[3]) const { return x[i] * f[0] + y[i] * f[1] + z[i] * f[2] + w[i]; }
|
||||
};
|
||||
|
||||
enum class ClipInfoFlags {
|
||||
Valid = 1,
|
||||
SoftClipCull = 2,
|
||||
DepthClamp = 8,
|
||||
DepthClampFragment = 16,
|
||||
MinMaxZClip = 32,
|
||||
MinMaxZDiscard = 64,
|
||||
};
|
||||
ENUM_CLASS_BITOPS(ClipInfoFlags);
|
||||
|
||||
class DrawEngineCommon {
|
||||
public:
|
||||
DrawEngineCommon();
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "Core/System.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/Math3D.h"
|
||||
#include "GPU/GPUDefinitions.h"
|
||||
#include "GPU/GPUStateSIMDUtil.h"
|
||||
#include "GPU/Common/FramebufferManagerCommon.h"
|
||||
#include "GPU/Common/GPUStateUtils.h"
|
||||
@@ -667,44 +668,48 @@ static SoftwareTransformAction ProjectClipAndExpand(SoftwareTransformParams &par
|
||||
// We might actually write more vertics at the end of transformed.
|
||||
|
||||
drawIndexCount = vertexCount;
|
||||
|
||||
result->pixelMapped = false;
|
||||
|
||||
if (throughmode) {
|
||||
// Nothing to do, pass the vertices right through as-is. Well, we can go look for pixel mapping,
|
||||
// but we don't do any projection, culling or clipping.
|
||||
if (g_Config.bSmart2DTexFiltering && !gstate_c.textureIsVideo) {
|
||||
// We check some common cases for pixel mapping.
|
||||
// TODO: It's not really optimal that some previous step has removed the triangle strip.
|
||||
if (vertexCount <= 6 && prim == GE_PRIM_TRIANGLES) {
|
||||
// It's enough to check UV deltas vs pos deltas between vertex pairs:
|
||||
// 0-1 1-3 3-2 2-0. Maybe can even skip the last one. Probably some simple math can get us that sequence.
|
||||
// Unfortunately we need to reverse the previous UV scaling operation. Fortunately these are powers of two
|
||||
// so the operations are exact.
|
||||
bool pixelMapped = true;
|
||||
const u16 *indsIn = (const u16 *)inds;
|
||||
const float uscale = gstate_c.curTextureWidth;
|
||||
const float vscale = gstate_c.curTextureHeight;
|
||||
for (int t = 0; t < vertexCount; t += 3) {
|
||||
struct { int a; int b; } pairs[] = {{0, 1}, {1, 2}, {2, 0}};
|
||||
for (int i = 0; i < ARRAY_SIZE(pairs); i++) {
|
||||
int a = indsIn[t + pairs[i].a];
|
||||
int b = indsIn[t + pairs[i].b];
|
||||
float du = fabsf((transformed[a].u - transformed[b].u) * uscale);
|
||||
float dv = fabsf((transformed[a].v - transformed[b].v) * vscale);
|
||||
float dx = fabsf(transformed[a].x - transformed[b].x);
|
||||
float dy = fabsf(transformed[a].y - transformed[b].y);
|
||||
if (du != dx || dv != dy) {
|
||||
pixelMapped = false;
|
||||
}
|
||||
}
|
||||
if (!pixelMapped) {
|
||||
break;
|
||||
}
|
||||
// Let's go look for pixel mapping.
|
||||
bool lookForPixelMapping = throughmode;
|
||||
if (!lookForPixelMapping) {
|
||||
// If not throughmode, we can still have pixel mapping if the clip info is valid and flat Z, since that means no clipping or perspective correction will be applied.
|
||||
if (((u32)params.clipInfoFlags & ((u32)(ClipInfoFlags::Valid | ClipInfoFlags::FlatZ))) == (u32)(ClipInfoFlags::Valid | ClipInfoFlags::FlatZ)) {
|
||||
lookForPixelMapping = true;
|
||||
}
|
||||
}
|
||||
if (lookForPixelMapping && g_Config.bSmart2DTexFiltering && !gstate_c.textureIsVideo) {
|
||||
// We check some common cases for pixel mapping.
|
||||
// It's enough to check UV deltas vs pos deltas between vertex pairs:
|
||||
// 0-1 1-3 3-2 2-0. Maybe can even skip the last one. Probably some simple math can get us that sequence.
|
||||
// Unfortunately we need to reverse the previous UV scaling operation. Fortunately these are powers of two
|
||||
// so the operations are exact.
|
||||
bool pixelMapped = true;
|
||||
const u16 *indsIn = (const u16 *)inds;
|
||||
const float uscale = gstate_c.curTextureWidth;
|
||||
const float vscale = gstate_c.curTextureHeight;
|
||||
for (int t = 0; t < vertexCount; t += 3) {
|
||||
struct { int a; int b; } pairs[] = {{0, 1}, {1, 2}, {2, 0}};
|
||||
for (int i = 0; i < ARRAY_SIZE(pairs); i++) {
|
||||
int a = indsIn[t + pairs[i].a];
|
||||
int b = indsIn[t + pairs[i].b];
|
||||
float du = fabsf((transformed[a].u - transformed[b].u) * uscale);
|
||||
float dv = fabsf((transformed[a].v - transformed[b].v) * vscale);
|
||||
float dx = fabsf(transformed[a].x - transformed[b].x);
|
||||
float dy = fabsf(transformed[a].y - transformed[b].y);
|
||||
if (du != dx || dv != dy) {
|
||||
pixelMapped = false;
|
||||
}
|
||||
result->pixelMapped = pixelMapped;
|
||||
}
|
||||
if (!pixelMapped) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result->pixelMapped = pixelMapped;
|
||||
}
|
||||
|
||||
if (!throughmode) {
|
||||
// Culling and clipping needs to be done here, it doesn't happen in the shader in the case of software transform.
|
||||
// However, fast culling should already have taken care of the Z<-W and Z>W culling, but we check for it on a per-triangle
|
||||
// basis here anyway.
|
||||
|
||||
@@ -62,6 +62,7 @@ struct SoftwareTransformParams {
|
||||
u8 *decoded;
|
||||
TransformedVertex *transformed;
|
||||
TransformedVertex *transformedExpanded;
|
||||
ClipInfoFlags clipInfoFlags;
|
||||
bool allowClear;
|
||||
bool allowSeparateAlphaClear;
|
||||
bool everUsedEqualDepth;
|
||||
|
||||
@@ -436,6 +436,7 @@ void DrawEngineD3D11::Flush() {
|
||||
params.transformedExpanded = transformedExpanded_;
|
||||
params.allowClear = true;
|
||||
params.allowSeparateAlphaClear = false; // D3D11 doesn't support separate alpha clears
|
||||
params.clipInfoFlags = clipInfoFlags_;
|
||||
|
||||
const SoftwareTransformAction action = RunSoftwareTransform(params, prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, VERTEX_BUFFER_MAX, vertexCount, inds, RemainingIndices(inds), &result);
|
||||
|
||||
|
||||
@@ -388,6 +388,7 @@ void DrawEngineGLES::Flush() {
|
||||
params.transformedExpanded = transformedExpanded_;
|
||||
params.allowClear = true; // Clear in OpenGL respects scissor rects, so we'll use it.
|
||||
params.allowSeparateAlphaClear = true;
|
||||
params.clipInfoFlags = clipInfoFlags_;
|
||||
|
||||
const SoftwareTransformAction action = RunSoftwareTransform(params, prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, VERTEX_BUFFER_MAX, vertexCount, inds, RemainingIndices(inds), &result);
|
||||
|
||||
|
||||
+4
-4
@@ -965,7 +965,7 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
const bool isTriangle = IsTrianglePrim(prim);
|
||||
|
||||
bool canExtend = isTriangle;
|
||||
u32 vertexType = gstate.vertType;
|
||||
GEVertexType vertexType = (GEVertexType)gstate.vertType;
|
||||
if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
|
||||
u32 indexAddr = gstate_c.indexAddr;
|
||||
const int indexShift = ((vertexType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT) - 1;
|
||||
@@ -1046,7 +1046,7 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
if (!drawEngineCommon_->SubmitPrim(verts, inds, prim, count, decoder, vertTypeID, true, &bytesRead, flags)) {
|
||||
canExtend = false;
|
||||
}
|
||||
onePassed = true;
|
||||
// onePassed = true;
|
||||
} else {
|
||||
// Still need to advance bytesRead.
|
||||
drawEngineCommon_->SkipPrim(prim, count, decoder, &bytesRead);
|
||||
@@ -1131,7 +1131,7 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
canExtend = false;
|
||||
}
|
||||
// As soon as one passes, assume we don't need to check the rest of this batch.
|
||||
onePassed = true;
|
||||
// onePassed = true;
|
||||
} else {
|
||||
// Still need to advance bytesRead.
|
||||
drawEngineCommon_->SkipPrim(newPrim, count, decoder, &bytesRead);
|
||||
@@ -1150,7 +1150,7 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
goto bail;
|
||||
drawEngineCommon_->FlushSkin();
|
||||
canExtend = false; // TODO: Might support extending between some vertex types in the future.
|
||||
vertexType = data;
|
||||
vertexType = (GEVertexType)(data);
|
||||
vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning);
|
||||
decoder = drawEngineCommon_->GetVertexDecoder(vertTypeID);
|
||||
}
|
||||
|
||||
@@ -195,6 +195,17 @@ enum {
|
||||
FLAG_DIRTYONCHANGE = 64, // NOTE: Either this or FLAG_EXECUTE*, not both!
|
||||
};
|
||||
|
||||
enum class ClipInfoFlags {
|
||||
Valid = 1,
|
||||
SoftClipCull = 2,
|
||||
FlatZ = 4,
|
||||
DepthClamp = 8,
|
||||
DepthClampFragment = 16,
|
||||
MinMaxZClip = 32,
|
||||
MinMaxZDiscard = 64,
|
||||
};
|
||||
ENUM_CLASS_BITOPS(ClipInfoFlags);
|
||||
|
||||
struct TransformedVertex {
|
||||
union {
|
||||
struct {
|
||||
|
||||
@@ -297,7 +297,7 @@ void DrawEngineVulkan::Flush() {
|
||||
gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255);
|
||||
}
|
||||
|
||||
if (textureNeedsApply) {
|
||||
if (textureNeedsApply || true) {
|
||||
textureCache_->ApplyTexture();
|
||||
textureCache_->GetVulkanHandles(imageView, sampler);
|
||||
if (imageView == VK_NULL_HANDLE)
|
||||
@@ -449,6 +449,7 @@ void DrawEngineVulkan::Flush() {
|
||||
params.allowClear = framebufferManager_->UseBufferedRendering();
|
||||
params.allowSeparateAlphaClear = false;
|
||||
params.everUsedEqualDepth = everUsedEqualDepth_;
|
||||
params.clipInfoFlags = clipInfoFlags_;
|
||||
|
||||
const SoftwareTransformAction action = RunSoftwareTransform(params, prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, VERTEX_BUFFER_MAX, vertexCount, inds, RemainingIndices(inds), &result);
|
||||
|
||||
|
||||
+46
-43
@@ -280,58 +280,60 @@ enum GECommand : uint8_t {
|
||||
|
||||
const char *GeCmdToString(GECommand cmd);
|
||||
|
||||
#define GE_VTYPE_TRANSFORM (0<<23)
|
||||
#define GE_VTYPE_THROUGH (1<<23)
|
||||
#define GE_VTYPE_THROUGH_MASK (1<<23)
|
||||
enum GEVertexType : uint32_t {
|
||||
GE_VTYPE_TRANSFORM = (0<<23),
|
||||
GE_VTYPE_THROUGH = (1<<23),
|
||||
GE_VTYPE_THROUGH_MASK = (1<<23),
|
||||
|
||||
#define GE_VTYPE_TC_NONE (0<<0)
|
||||
#define GE_VTYPE_TC_8BIT (1<<0)
|
||||
#define GE_VTYPE_TC_16BIT (2<<0)
|
||||
#define GE_VTYPE_TC_FLOAT (3<<0)
|
||||
#define GE_VTYPE_TC_MASK (3<<0)
|
||||
#define GE_VTYPE_TC_SHIFT 0
|
||||
GE_VTYPE_TC_NONE = (0<<0),
|
||||
GE_VTYPE_TC_8BIT = (1<<0),
|
||||
GE_VTYPE_TC_16BIT = (2<<0),
|
||||
GE_VTYPE_TC_FLOAT = (3<<0),
|
||||
GE_VTYPE_TC_MASK = (3<<0),
|
||||
GE_VTYPE_TC_SHIFT = 0,
|
||||
|
||||
#define GE_VTYPE_COL_NONE (0<<2)
|
||||
#define GE_VTYPE_COL_565 (4<<2)
|
||||
#define GE_VTYPE_COL_5551 (5<<2)
|
||||
#define GE_VTYPE_COL_4444 (6<<2)
|
||||
#define GE_VTYPE_COL_8888 (7<<2)
|
||||
#define GE_VTYPE_COL_MASK (7<<2)
|
||||
#define GE_VTYPE_COL_SHIFT 2
|
||||
GE_VTYPE_COL_NONE = (0<<2),
|
||||
GE_VTYPE_COL_565 = (4<<2),
|
||||
GE_VTYPE_COL_5551 = (5<<2),
|
||||
GE_VTYPE_COL_4444 = (6<<2),
|
||||
GE_VTYPE_COL_8888 = (7<<2),
|
||||
GE_VTYPE_COL_MASK = (7<<2),
|
||||
GE_VTYPE_COL_SHIFT = 2,
|
||||
|
||||
#define GE_VTYPE_NRM_NONE (0<<5)
|
||||
#define GE_VTYPE_NRM_8BIT (1<<5)
|
||||
#define GE_VTYPE_NRM_16BIT (2<<5)
|
||||
#define GE_VTYPE_NRM_FLOAT (3<<5)
|
||||
#define GE_VTYPE_NRM_MASK (3<<5)
|
||||
#define GE_VTYPE_NRM_SHIFT 5
|
||||
GE_VTYPE_NRM_NONE = (0<<5),
|
||||
GE_VTYPE_NRM_8BIT = (1<<5),
|
||||
GE_VTYPE_NRM_16BIT = (2<<5),
|
||||
GE_VTYPE_NRM_FLOAT = (3<<5),
|
||||
GE_VTYPE_NRM_MASK = (3<<5),
|
||||
GE_VTYPE_NRM_SHIFT = 5,
|
||||
|
||||
// No NONE, there is always a position.
|
||||
#define GE_VTYPE_POS_8BIT (1<<7)
|
||||
#define GE_VTYPE_POS_16BIT (2<<7)
|
||||
#define GE_VTYPE_POS_FLOAT (3<<7)
|
||||
#define GE_VTYPE_POS_MASK (3<<7)
|
||||
#define GE_VTYPE_POS_SHIFT 7
|
||||
// No NONE, there is always a position.
|
||||
GE_VTYPE_POS_8BIT = (1<<7),
|
||||
GE_VTYPE_POS_16BIT = (2<<7),
|
||||
GE_VTYPE_POS_FLOAT = (3<<7),
|
||||
GE_VTYPE_POS_MASK = (3<<7),
|
||||
GE_VTYPE_POS_SHIFT = 7,
|
||||
|
||||
#define GE_VTYPE_WEIGHT_NONE (0<<9)
|
||||
#define GE_VTYPE_WEIGHT_8BIT (1<<9)
|
||||
#define GE_VTYPE_WEIGHT_16BIT (2<<9)
|
||||
#define GE_VTYPE_WEIGHT_FLOAT (3<<9)
|
||||
#define GE_VTYPE_WEIGHT_MASK (3<<9)
|
||||
#define GE_VTYPE_WEIGHT_SHIFT 9
|
||||
GE_VTYPE_WEIGHT_NONE = (0<<9),
|
||||
GE_VTYPE_WEIGHT_8BIT = (1<<9),
|
||||
GE_VTYPE_WEIGHT_16BIT = (2<<9),
|
||||
GE_VTYPE_WEIGHT_FLOAT = (3<<9),
|
||||
GE_VTYPE_WEIGHT_MASK = (3<<9),
|
||||
GE_VTYPE_WEIGHT_SHIFT = 9,
|
||||
|
||||
#define GE_VTYPE_WEIGHTCOUNT_MASK (7<<14)
|
||||
#define GE_VTYPE_WEIGHTCOUNT_SHIFT 14
|
||||
GE_VTYPE_WEIGHTCOUNT_MASK = (7<<14),
|
||||
GE_VTYPE_WEIGHTCOUNT_SHIFT = 14,
|
||||
|
||||
#define GE_VTYPE_MORPHCOUNT_MASK (7<<18)
|
||||
#define GE_VTYPE_MORPHCOUNT_SHIFT 18
|
||||
GE_VTYPE_MORPHCOUNT_MASK = (7<<18),
|
||||
GE_VTYPE_MORPHCOUNT_SHIFT = 18,
|
||||
|
||||
#define GE_VTYPE_IDX_NONE (0<<11)
|
||||
#define GE_VTYPE_IDX_8BIT (1<<11)
|
||||
#define GE_VTYPE_IDX_16BIT (2<<11)
|
||||
#define GE_VTYPE_IDX_32BIT (3<<11)
|
||||
#define GE_VTYPE_IDX_MASK (3<<11)
|
||||
GE_VTYPE_IDX_NONE = (0<<11),
|
||||
GE_VTYPE_IDX_8BIT = (1<<11),
|
||||
GE_VTYPE_IDX_16BIT = (2<<11),
|
||||
GE_VTYPE_IDX_32BIT = (3<<11),
|
||||
GE_VTYPE_IDX_MASK = (3<<11),
|
||||
#define GE_VTYPE_IDX_SHIFT 11
|
||||
};
|
||||
|
||||
#define GE_CLEARMODE_COLOR (1<<8)
|
||||
#define GE_CLEARMODE_ALPHA (1<<9) //or stencil?
|
||||
@@ -347,6 +349,7 @@ const char *GeCmdToString(GECommand cmd);
|
||||
#define GE_IMM_FOG 0x00400000
|
||||
#define GE_IMM_DITHER 0x00800000
|
||||
|
||||
|
||||
enum GEMatrixType {
|
||||
GE_MTX_BONE0 = 0,
|
||||
GE_MTX_BONE1,
|
||||
|
||||
Reference in New Issue
Block a user