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:
Henrik Rydgård committed 2023-01-12 12:38:02 +01:00
1 parent 3d6647e0cf
commit fc2334f4fa
10 files changed
+81 -68

No files matched your search

+1
View File
@@ -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() {
-3
View File
@@ -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);
-1
View File
@@ -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
+8
View File
@@ -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);
+8
View File
@@ -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);
+12 -1
View File
@@ -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);
}
+5
View File
@@ -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();
+7
View File
@@ -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);
+34 -56
View File
@@ -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
+6 -7
View File
@@ -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() {