mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-14 18:19:36 +01:00
Inject zero texcoords to avoid needing separate vshaders for UV-less formats.
Make injecting a dummy UV into an option on the vertex decoder
This commit is contained in:
1 parent
3d6647e0cf
commit
fc2334f4fa
10 files changed
+81
-68
No files matched your search
@@ -39,6 +39,7 @@ DrawEngineCommon::DrawEngineCommon() : decoderMap_(16) {
|
||||
decJitCache_ = new VertexDecoderJitCache();
|
||||
transformed = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
|
||||
transformedExpanded = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE);
|
||||
decOptions_.injectDummyUVIfMissing = true;
|
||||
}
|
||||
|
||||
DrawEngineCommon::~DrawEngineCommon() {
|
||||
|
||||
@@ -19,7 +19,6 @@ std::string VertexShaderDesc(const VShaderID &id) {
|
||||
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_NORM_REVERSE)) desc << "RevN ";
|
||||
@@ -76,7 +75,6 @@ void ComputeVertexShaderID(VShaderID *id_out, VertexDecoder *vertexDecoder, bool
|
||||
|
||||
bool vtypeHasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
|
||||
bool vtypeHasNormal = (vertType & GE_VTYPE_NRM_MASK) != 0;
|
||||
bool vtypeHasTexcoord = (vertType & GE_VTYPE_TC_MASK) != 0;
|
||||
|
||||
bool doBezier = gstate_c.submitType == SubmitType::HW_BEZIER;
|
||||
bool doSpline = gstate_c.submitType == SubmitType::HW_SPLINE;
|
||||
@@ -147,7 +145,6 @@ void ComputeVertexShaderID(VShaderID *id_out, VertexDecoder *vertexDecoder, bool
|
||||
}
|
||||
|
||||
id.SetBit(VS_BIT_NORM_REVERSE, gstate.areNormalsReversed());
|
||||
id.SetBit(VS_BIT_HAS_TEXCOORD, vtypeHasTexcoord);
|
||||
|
||||
if (useHWTessellation) {
|
||||
id.SetBit(VS_BIT_BEZIER, doBezier);
|
||||
|
||||
@@ -20,7 +20,6 @@ enum VShaderBit : uint8_t {
|
||||
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,
|
||||
VS_BIT_HAS_COLOR_TESS = 12, // 1 bit
|
||||
VS_BIT_HAS_TEXCOORD_TESS = 13, // 1 bit
|
||||
VS_BIT_NORM_REVERSE_TESS = 14, // 1 bit
|
||||
|
||||
@@ -109,6 +109,8 @@ static const JitLookup jitLookup[] = {
|
||||
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
|
||||
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
|
||||
|
||||
{&VertexDecoder::Step_TcDefault, &VertexDecoderJitCache::Jit_TcDefault},
|
||||
|
||||
{&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat},
|
||||
{&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat},
|
||||
{&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat},
|
||||
@@ -487,6 +489,12 @@ void VertexDecoderJitCache::Jit_WeightsFloatSkin() {
|
||||
Jit_ApplyWeights();
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcDefault() {
|
||||
MOVI(tempReg1, 0);
|
||||
STR(tempReg1, dstReg, dec_->decFmt.uvoff);
|
||||
STR(tempReg1, dstReg, dec_->decFmt.uvoff + 4);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcFloat() {
|
||||
LDR(tempReg1, srcReg, dec_->tcoff);
|
||||
LDR(tempReg2, srcReg, dec_->tcoff + 4);
|
||||
|
||||
@@ -40,6 +40,7 @@ static const ARM64Reg dstReg = X1;
|
||||
|
||||
static const ARM64Reg counterReg = W2;
|
||||
static const ARM64Reg tempReg1 = W3;
|
||||
static const ARM64Reg tempReg1_64 = X3;
|
||||
static const ARM64Reg tempRegPtr = X3;
|
||||
static const ARM64Reg tempReg2 = W4;
|
||||
static const ARM64Reg tempReg3 = W5;
|
||||
@@ -86,6 +87,8 @@ static const JitLookup jitLookup[] = {
|
||||
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
|
||||
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
|
||||
|
||||
{&VertexDecoder::Step_TcDefault, &VertexDecoderJitCache::Jit_TcDefault},
|
||||
|
||||
{&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat},
|
||||
{&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat},
|
||||
{&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat},
|
||||
@@ -592,6 +595,11 @@ void VertexDecoderJitCache::Jit_TcU16ThroughToFloat() {
|
||||
fp.STUR(64, neonScratchRegD, dstReg, dec_->decFmt.uvoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcDefault() {
|
||||
MOVI2R(tempReg1_64, 0);
|
||||
STR(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.uvoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcFloatThrough() {
|
||||
LDP(INDEX_SIGNED, tempReg1, tempReg2, srcReg, dec_->tcoff);
|
||||
STP(INDEX_SIGNED, tempReg1, tempReg2, dstReg, dec_->decFmt.uvoff);
|
||||
|
||||
@@ -270,9 +270,15 @@ void VertexDecoder::Step_WeightsFloatSkin() const {
|
||||
ComputeSkinMatrix(wdata);
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_TcDefault() const
|
||||
{
|
||||
uint64_t *uv = (uint64_t *)(decoded_ + decFmt.uvoff);
|
||||
// Write two zero floats in one instruction.
|
||||
*uv = 0;
|
||||
}
|
||||
|
||||
void VertexDecoder::Step_TcU8ToFloat() const
|
||||
{
|
||||
// u32 to write two bytes of zeroes for free.
|
||||
float *uv = (float *)(decoded_ + decFmt.uvoff);
|
||||
const u8 *uvdata = (const u8*)(ptr_ + tcoff);
|
||||
uv[0] = uvdata[0] * (1.0f / 128.0f);
|
||||
@@ -1163,6 +1169,11 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options,
|
||||
decFmt.uvfmt = DEC_FLOAT_2;
|
||||
}
|
||||
|
||||
decFmt.uvoff = decOff;
|
||||
decOff += DecFmtSize(decFmt.uvfmt);
|
||||
} else if (options.injectDummyUVIfMissing) {
|
||||
steps_[numSteps_++] = &VertexDecoder::Step_TcDefault;
|
||||
decFmt.uvfmt = DEC_FLOAT_2;
|
||||
decFmt.uvoff = decOff;
|
||||
decOff += DecFmtSize(decFmt.uvfmt);
|
||||
}
|
||||
|
||||
@@ -324,6 +324,7 @@ struct VertexDecoderOptions {
|
||||
bool expandAllWeightsToFloat;
|
||||
bool expand8BitNormalsToFloat;
|
||||
bool applySkinInDecode;
|
||||
bool injectDummyUVIfMissing;
|
||||
};
|
||||
|
||||
class VertexDecoder {
|
||||
@@ -353,6 +354,8 @@ public:
|
||||
void Step_WeightsU16Skin() const;
|
||||
void Step_WeightsFloatSkin() const;
|
||||
|
||||
void Step_TcDefault() const;
|
||||
|
||||
void Step_TcU8ToFloat() const;
|
||||
void Step_TcU16ToFloat() const;
|
||||
void Step_TcFloat() const;
|
||||
@@ -510,6 +513,8 @@ public:
|
||||
void Jit_WeightsU16Skin();
|
||||
void Jit_WeightsFloatSkin();
|
||||
|
||||
void Jit_TcDefault();
|
||||
|
||||
void Jit_TcU8ToFloat();
|
||||
void Jit_TcU16ToFloat();
|
||||
void Jit_TcFloat();
|
||||
|
||||
@@ -103,6 +103,8 @@ static const JitLookup jitLookup[] = {
|
||||
{&VertexDecoder::Step_WeightsU8ToFloat, &VertexDecoderJitCache::Jit_WeightsU8ToFloat},
|
||||
{&VertexDecoder::Step_WeightsU16ToFloat, &VertexDecoderJitCache::Jit_WeightsU16ToFloat},
|
||||
|
||||
{&VertexDecoder::Step_TcDefault, &VertexDecoderJitCache::Jit_TcDefault},
|
||||
|
||||
{&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat},
|
||||
{&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat},
|
||||
{&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat},
|
||||
@@ -721,6 +723,11 @@ void VertexDecoderJitCache::Jit_WeightsFloatSkin() {
|
||||
}
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcDefault() {
|
||||
PXOR(XMM3, R(XMM3));
|
||||
MOVQ_xmm(MDisp(dstReg, dec_->decFmt.uvoff), XMM3);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcU8ToFloat() {
|
||||
Jit_AnyU8ToFloat(dec_->tcoff, 16);
|
||||
MOVQ_xmm(MDisp(dstReg, dec_->decFmt.uvoff), XMM3);
|
||||
|
||||
@@ -186,7 +186,6 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
bool useHWTransform = id.Bit(VS_BIT_USE_HW_TRANSFORM);
|
||||
bool hasColor = id.Bit(VS_BIT_HAS_COLOR) || !useHWTransform;
|
||||
bool hasNormal = id.Bit(VS_BIT_HAS_NORMAL) && useHWTransform;
|
||||
bool hasTexcoord = id.Bit(VS_BIT_HAS_TEXCOORD) || !useHWTransform;
|
||||
bool flipNormal = id.Bit(VS_BIT_NORM_REVERSE);
|
||||
int ls0 = id.Bits(VS_BIT_LS0, 2);
|
||||
int ls1 = id.Bits(VS_BIT_LS1, 2);
|
||||
@@ -270,14 +269,13 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
if (!useHWTransform)
|
||||
WRITE(p, "layout (location = %d) in float fog;\n", (int)PspAttributeLocation::NORMAL);
|
||||
|
||||
if (hasTexcoord) {
|
||||
if (!useHWTransform && doTextureTransform && !isModeThrough) {
|
||||
WRITE(p, "layout (location = %d) in vec3 texcoord;\n", (int)PspAttributeLocation::TEXCOORD);
|
||||
texCoordInVec3 = true;
|
||||
} else {
|
||||
WRITE(p, "layout (location = %d) in vec2 texcoord;\n", (int)PspAttributeLocation::TEXCOORD);
|
||||
}
|
||||
if (!useHWTransform && doTextureTransform && !isModeThrough) {
|
||||
WRITE(p, "layout (location = %d) in vec3 texcoord;\n", (int)PspAttributeLocation::TEXCOORD);
|
||||
texCoordInVec3 = true;
|
||||
} else {
|
||||
WRITE(p, "layout (location = %d) in vec2 texcoord;\n", (int)PspAttributeLocation::TEXCOORD);
|
||||
}
|
||||
|
||||
if (hasColor) {
|
||||
WRITE(p, "layout (location = %d) in vec4 color0;\n", (int)PspAttributeLocation::COLOR0);
|
||||
if (lmode && !useHWTransform) // only software transform supplies color1 as vertex data
|
||||
@@ -379,9 +377,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
if (enableBones) {
|
||||
WRITE(p, " %s", boneWeightAttrDeclHLSL[numBoneWeights]);
|
||||
}
|
||||
if (hasTexcoord) {
|
||||
WRITE(p, " vec2 texcoord : TEXCOORD0;\n");
|
||||
}
|
||||
WRITE(p, " vec2 texcoord : TEXCOORD0;\n");
|
||||
if (hasColor) {
|
||||
WRITE(p, " vec4 color0 : COLOR0;\n");
|
||||
}
|
||||
@@ -393,13 +389,11 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
} else {
|
||||
WRITE(p, "struct VS_IN {\n");
|
||||
WRITE(p, " vec4 position : POSITION;\n");
|
||||
if (hasTexcoord) {
|
||||
if (doTextureTransform && !isModeThrough) {
|
||||
texCoordInVec3 = true;
|
||||
WRITE(p, " vec3 texcoord : TEXCOORD0;\n");
|
||||
} else {
|
||||
WRITE(p, " vec2 texcoord : TEXCOORD0;\n");
|
||||
}
|
||||
if (doTextureTransform && !isModeThrough) {
|
||||
texCoordInVec3 = true;
|
||||
WRITE(p, " vec3 texcoord : TEXCOORD0;\n");
|
||||
} else {
|
||||
WRITE(p, " vec2 texcoord : TEXCOORD0;\n");
|
||||
}
|
||||
if (hasColor) {
|
||||
WRITE(p, " vec4 color0 : COLOR0;\n");
|
||||
@@ -465,15 +459,13 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
*attrMask |= 1 << ATTR_NORMAL;
|
||||
}
|
||||
|
||||
if (hasTexcoord) {
|
||||
if (!useHWTransform && doTextureTransform && !isModeThrough) {
|
||||
WRITE(p, "%s vec3 texcoord;\n", compat.attribute);
|
||||
texCoordInVec3 = true;
|
||||
} else {
|
||||
WRITE(p, "%s vec2 texcoord;\n", compat.attribute);
|
||||
}
|
||||
*attrMask |= 1 << ATTR_TEXCOORD;
|
||||
if (!useHWTransform && doTextureTransform && !isModeThrough) {
|
||||
WRITE(p, "%s vec3 texcoord;\n", compat.attribute);
|
||||
texCoordInVec3 = true;
|
||||
} else {
|
||||
WRITE(p, "%s vec2 texcoord;\n", compat.attribute);
|
||||
}
|
||||
*attrMask |= 1 << ATTR_TEXCOORD;
|
||||
|
||||
if (hasColor) {
|
||||
WRITE(p, "%s lowp vec4 color0;\n", compat.attribute);
|
||||
@@ -783,12 +775,10 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
} else if (compat.shaderLanguage == HLSL_D3D9 || compat.shaderLanguage == HLSL_D3D11) {
|
||||
WRITE(p, "VS_OUT main(VS_IN In) {\n");
|
||||
WRITE(p, " VS_OUT Out;\n");
|
||||
if (hasTexcoord) {
|
||||
if (texCoordInVec3) {
|
||||
WRITE(p, " vec3 texcoord = In.texcoord;\n");
|
||||
} else {
|
||||
WRITE(p, " vec2 texcoord = In.texcoord;\n");
|
||||
}
|
||||
if (texCoordInVec3) {
|
||||
WRITE(p, " vec3 texcoord = In.texcoord;\n");
|
||||
} else {
|
||||
WRITE(p, " vec2 texcoord = In.texcoord;\n");
|
||||
}
|
||||
if (hasColor) {
|
||||
WRITE(p, " vec4 color0 = In.color0;\n");
|
||||
@@ -1204,23 +1194,15 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
case GE_TEXMAP_TEXTURE_COORDS: // Scale-offset. Easy.
|
||||
case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works.
|
||||
if (scaleUV) {
|
||||
if (hasTexcoord) {
|
||||
if (doBezier || doSpline)
|
||||
WRITE(p, " %sv_texcoord = vec3(tess.tex.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n", compat.vsOutPrefix);
|
||||
else
|
||||
WRITE(p, " %sv_texcoord = vec3(texcoord.xy * u_uvscaleoffset.xy, 0.0);\n", compat.vsOutPrefix);
|
||||
} else {
|
||||
WRITE(p, " %sv_texcoord = splat3(0.0);\n", compat.vsOutPrefix);
|
||||
}
|
||||
if (doBezier || doSpline)
|
||||
WRITE(p, " %sv_texcoord = vec3(tess.tex.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n", compat.vsOutPrefix);
|
||||
else
|
||||
WRITE(p, " %sv_texcoord = vec3(texcoord.xy * u_uvscaleoffset.xy, 0.0);\n", compat.vsOutPrefix);
|
||||
} else {
|
||||
if (hasTexcoord) {
|
||||
if (doBezier || doSpline)
|
||||
WRITE(p, " %sv_texcoord = vec3(tess.tex.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n", compat.vsOutPrefix);
|
||||
else
|
||||
WRITE(p, " %sv_texcoord = vec3(texcoord.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n", compat.vsOutPrefix);
|
||||
} else {
|
||||
WRITE(p, " %sv_texcoord = vec3(u_uvscaleoffset.zw, 0.0);\n", compat.vsOutPrefix);
|
||||
}
|
||||
if (doBezier || doSpline)
|
||||
WRITE(p, " %sv_texcoord = vec3(tess.tex.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n", compat.vsOutPrefix);
|
||||
else
|
||||
WRITE(p, " %sv_texcoord = vec3(texcoord.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n", compat.vsOutPrefix);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1237,14 +1219,10 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
case GE_PROJMAP_UV: // Use unscaled UV as source
|
||||
{
|
||||
// prescale is false here.
|
||||
if (hasTexcoord) {
|
||||
if (doBezier || doSpline)
|
||||
temp_tc = "vec4(tess.tex.xy, 0.0, 1.0)";
|
||||
else
|
||||
temp_tc = "vec4(texcoord.xy, 0.0, 1.0)";
|
||||
} else {
|
||||
temp_tc = "vec4(0.0, 0.0, 0.0, 1.0)";
|
||||
}
|
||||
if (doBezier || doSpline)
|
||||
temp_tc = "vec4(tess.tex.xy, 0.0, 1.0)";
|
||||
else
|
||||
temp_tc = "vec4(texcoord.xy, 0.0, 1.0)";
|
||||
}
|
||||
break;
|
||||
case GE_PROJMAP_NORMALIZED_NORMAL: // Use normalized transformed normal as source
|
||||
|
||||
@@ -32,8 +32,7 @@ class VertexDecoderTestHarness {
|
||||
static const int ROUNDS = 200;
|
||||
|
||||
public:
|
||||
VertexDecoderTestHarness()
|
||||
: dec_(nullptr), needsReset_(true), dstPos_(0), assertFailed_(false) {
|
||||
VertexDecoderTestHarness() {
|
||||
src_ = new u8[BUFFER_SIZE];
|
||||
dst_ = new u8[BUFFER_SIZE];
|
||||
cache_ = new VertexDecoderJitCache();
|
||||
@@ -285,13 +284,13 @@ private:
|
||||
u8 *dst_;
|
||||
VertexDecoderJitCache *cache_;
|
||||
VertexDecoderOptions options_;
|
||||
VertexDecoder *dec_;
|
||||
VertexDecoder *dec_ = nullptr;
|
||||
int indexLowerBound_;
|
||||
int indexUpperBound_;
|
||||
bool needsReset_;
|
||||
size_t srcPos_;
|
||||
size_t dstPos_;
|
||||
bool assertFailed_;
|
||||
bool needsReset_ = true;
|
||||
size_t srcPos_ = 0;
|
||||
size_t dstPos_ = 0;
|
||||
bool assertFailed_ = false;
|
||||
};
|
||||
|
||||
static bool TestVertex8() {
|
||||
|
||||
Reference in new issue
Block a user