summaryrefslogtreecommitdiffstats
path: root/src/libs/dxvk-native-1.9.2a/src/dxso/dxso_decoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/dxso/dxso_decoder.cpp280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/libs/dxvk-native-1.9.2a/src/dxso/dxso_decoder.cpp b/src/libs/dxvk-native-1.9.2a/src/dxso/dxso_decoder.cpp
new file mode 100644
index 00000000..42d8d64b
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/dxso/dxso_decoder.cpp
@@ -0,0 +1,280 @@
+#include "dxso_decoder.h"
+
+#include "dxso_tables.h"
+
+namespace dxvk {
+
+ bool DxsoSemantic::operator== (const DxsoSemantic& b) const {
+ return usage == b.usage && usageIndex == b.usageIndex;
+ }
+
+ bool DxsoSemantic::operator!= (const DxsoSemantic& b) const {
+ return usage != b.usage || usageIndex != b.usageIndex;
+ }
+
+ uint32_t DxsoDecodeContext::decodeInstructionLength(uint32_t token) {
+ auto opcode = m_ctx.instruction.opcode;
+
+ uint32_t length = 0;
+ const auto& info = this->getProgramInfo();
+
+ // Comment ops have their own system for getting length.
+ if (opcode == DxsoOpcode::Comment)
+ return (token & 0x7fff0000) >> 16;
+
+ if (opcode == DxsoOpcode::End)
+ return 0;
+
+ // SM2.0 and above has the length of the op in instruction count baked into it.
+ // SM1.4 and below have fixed lengths and run off expectation.
+ // Phase does not respect the following rules. :shrug:
+ if (opcode != DxsoOpcode::Phase) {
+ if (info.majorVersion() >= 2)
+ length = (token & 0x0f000000) >> 24;
+ else
+ length = DxsoGetDefaultOpcodeLength(opcode);
+ }
+
+ // We've already logged this...
+ if (length == InvalidOpcodeLength)
+ return 0;
+
+ // SM 1.4 has an extra param on Tex and TexCoord
+ // As stated before, it also doesn't have the length of the op baked into the opcode
+ if (info.majorVersion() == 1
+ && info.minorVersion() == 4) {
+ switch (opcode) {
+ case DxsoOpcode::TexCoord:
+ case DxsoOpcode::Tex: length += 1;
+ default: break;
+ }
+ }
+
+ return length;
+ }
+
+ bool DxsoDecodeContext::relativeAddressingUsesToken(
+ DxsoInstructionArgumentType type) {
+ auto& info = this->getProgramInfo();
+
+ return (info.majorVersion() >= 2 && type == DxsoInstructionArgumentType::Source)
+ || (info.majorVersion() >= 3 && type == DxsoInstructionArgumentType::Destination);
+ }
+
+ void DxsoDecodeContext::decodeDeclaration(DxsoCodeIter& iter) {
+ uint32_t dclToken = iter.read();
+
+ m_ctx.dcl.textureType = static_cast<DxsoTextureType>((dclToken & 0x78000000) >> 27);
+ m_ctx.dcl.semantic.usage = static_cast<DxsoUsage>(dclToken & 0x0000000f);
+ m_ctx.dcl.semantic.usageIndex = (dclToken & 0x000f0000) >> 16;
+ }
+
+ void DxsoDecodeContext::decodeDefinition(DxsoOpcode opcode, DxsoCodeIter& iter) {
+ const uint32_t instructionLength = std::min(m_ctx.instruction.tokenLength - 1, 4u);
+
+ for (uint32_t i = 0; i < instructionLength; i++)
+ m_ctx.def.uint32[i] = iter.read();
+ }
+
+ void DxsoDecodeContext::decodeBaseRegister(
+ DxsoBaseRegister& reg,
+ uint32_t token) {
+ reg.id.type = static_cast<DxsoRegisterType>(
+ ((token & 0x00001800) >> 8)
+ | ((token & 0x70000000) >> 28));
+
+ reg.id.num = token & 0x000007ff;
+ }
+
+ void DxsoDecodeContext::decodeGenericRegister(
+ DxsoRegister& reg,
+ uint32_t token) {
+ this->decodeBaseRegister(reg, token);
+
+ reg.hasRelative = (token & (1 << 13)) == 8192;
+ reg.relative.id = DxsoRegisterId {
+ DxsoRegisterType::Addr, 0 };
+ reg.relative.swizzle = IdentitySwizzle;
+
+ reg.centroid = token & (4 << 20);
+ reg.partialPrecision = token & (2 << 20);
+ }
+
+ void DxsoDecodeContext::decodeRelativeRegister(
+ DxsoBaseRegister& reg,
+ uint32_t token) {
+ this->decodeBaseRegister(reg, token);
+
+ reg.swizzle = DxsoRegSwizzle(
+ uint8_t((token & 0x00ff0000) >> 16));
+ }
+
+ bool DxsoDecodeContext::decodeDestinationRegister(DxsoCodeIter& iter) {
+ uint32_t token = iter.read();
+
+ this->decodeGenericRegister(m_ctx.dst, token);
+
+ m_ctx.dst.mask = DxsoRegMask(
+ uint8_t((token & 0x000f0000) >> 16));
+
+ m_ctx.dst.saturate = (token & (1 << 20)) != 0;
+
+ m_ctx.dst.shift = (token & 0x0f000000) >> 24;
+ m_ctx.dst.shift = (m_ctx.dst.shift & 0x7) - (m_ctx.dst.shift & 0x8);
+
+ const bool extraToken =
+ relativeAddressingUsesToken(DxsoInstructionArgumentType::Destination);
+
+ if (m_ctx.dst.hasRelative && extraToken) {
+ this->decodeRelativeRegister(m_ctx.dst.relative, iter.read());
+ return true;
+ }
+
+ return false;
+ }
+
+ bool DxsoDecodeContext::decodeSourceRegister(uint32_t i, DxsoCodeIter& iter) {
+ if (i >= m_ctx.src.size())
+ throw DxvkError("DxsoDecodeContext::decodeSourceRegister: source register out of range.");
+
+ uint32_t token = iter.read();
+
+ this->decodeGenericRegister(m_ctx.src[i], token);
+
+ m_ctx.src[i].swizzle = DxsoRegSwizzle(
+ uint8_t((token & 0x00ff0000) >> 16));
+
+ m_ctx.src[i].modifier = static_cast<DxsoRegModifier>(
+ (token & 0x0f000000) >> 24);
+
+ const bool extraToken =
+ relativeAddressingUsesToken(DxsoInstructionArgumentType::Source);
+
+ if (m_ctx.src[i].hasRelative && extraToken) {
+ this->decodeRelativeRegister(m_ctx.src[i].relative, iter.read());
+ return true;
+ }
+
+ return false;
+ }
+
+
+ void DxsoDecodeContext::decodePredicateRegister(DxsoCodeIter& iter) {
+ uint32_t token = iter.read();
+
+ this->decodeGenericRegister(m_ctx.pred, token);
+
+ m_ctx.pred.swizzle = DxsoRegSwizzle(
+ uint8_t((token & 0x00ff0000) >> 16));
+
+ m_ctx.pred.modifier = static_cast<DxsoRegModifier>(
+ (token & 0x0f000000) >> 24);
+ }
+
+
+ bool DxsoDecodeContext::decodeInstruction(DxsoCodeIter& iter) {
+ uint32_t token = iter.read();
+
+ m_ctx.instructionIdx++;
+
+ m_ctx.instruction.opcode = static_cast<DxsoOpcode>(
+ token & 0x0000ffff);
+
+ m_ctx.instruction.predicated = token & (1 << 28);
+
+ m_ctx.instruction.coissue = token & 0x40000000;
+
+ m_ctx.instruction.specificData.uint32 =
+ (token & 0x00ff0000) >> 16;
+
+ m_ctx.instruction.tokenLength =
+ this->decodeInstructionLength(token);
+
+ uint32_t tokenLength =
+ m_ctx.instruction.tokenLength;
+
+ switch (m_ctx.instruction.opcode) {
+ case DxsoOpcode::If:
+ case DxsoOpcode::Ifc:
+ case DxsoOpcode::Rep:
+ case DxsoOpcode::Loop:
+ case DxsoOpcode::BreakC:
+ case DxsoOpcode::BreakP: {
+ uint32_t sourceIdx = 0;
+ for (uint32_t i = 0; i < tokenLength; i++) {
+ if (this->decodeSourceRegister(sourceIdx, iter))
+ i++;
+
+ sourceIdx++;
+ }
+ return true;
+ }
+
+ case DxsoOpcode::Dcl:
+ this->decodeDeclaration(iter);
+ this->decodeDestinationRegister(iter);
+ return true;
+
+ case DxsoOpcode::Def:
+ case DxsoOpcode::DefI:
+ case DxsoOpcode::DefB:
+ this->decodeDestinationRegister(iter);
+ this->decodeDefinition(
+ m_ctx.instruction.opcode, iter);
+ return true;
+
+ case DxsoOpcode::Comment:
+ iter = iter.skip(tokenLength);
+ return true;
+
+ default: {
+ uint32_t sourceIdx = 0;
+ for (uint32_t i = 0; i < tokenLength; i++) {
+ if (i == 0) {
+ if (this->decodeDestinationRegister(iter))
+ i++;
+ }
+ else if (i == 1 && m_ctx.instruction.predicated) {
+ // Relative addressing makes no sense
+ // for predicate registers.
+ this->decodePredicateRegister(iter);
+ }
+ else {
+ if (this->decodeSourceRegister(sourceIdx, iter))
+ i++;
+
+ sourceIdx++;
+ }
+ }
+ return true;
+ }
+
+ case DxsoOpcode::End:
+ return false;
+ }
+ }
+
+ std::ostream& operator << (std::ostream& os, DxsoUsage usage) {
+ switch (usage) {
+ case DxsoUsage::Position: os << "Position"; break;
+ case DxsoUsage::BlendWeight: os << "BlendWeight"; break;
+ case DxsoUsage::BlendIndices: os << "BlendIndices"; break;
+ case DxsoUsage::Normal: os << "Normal"; break;
+ case DxsoUsage::PointSize: os << "PointSize"; break;
+ case DxsoUsage::Texcoord: os << "Texcoord"; break;
+ case DxsoUsage::Tangent: os << "Tangent"; break;
+ case DxsoUsage::Binormal: os << "Binormal"; break;
+ case DxsoUsage::TessFactor: os << "TessFactor"; break;
+ case DxsoUsage::PositionT: os << "PositionT"; break;
+ case DxsoUsage::Color: os << "Color"; break;
+ case DxsoUsage::Fog: os << "Fog"; break;
+ case DxsoUsage::Depth: os << "Depth"; break;
+ case DxsoUsage::Sample: os << "Sample"; break;
+ default:
+ os << "Invalid Format (" << static_cast<uint32_t>(usage) << ")"; break;
+ }
+
+ return os;
+ }
+
+} \ No newline at end of file