diff --git a/src/xenia/gpu/shader.h b/src/xenia/gpu/shader.h index 5653bf49e..78505e6a1 100644 --- a/src/xenia/gpu/shader.h +++ b/src/xenia/gpu/shader.h @@ -492,6 +492,22 @@ struct ParsedAluInstruction { // Describes each source operand. InstructionOperand operands[3]; + // If this is a valid eA write (MAD with a stream constant), returns the index + // of the stream float constant, otherwise returns UINT32_MAX. + uint32_t GetMemExportStreamConstant() const { + if (result.storage_target == InstructionStorageTarget::kExportAddress && + is_vector_type() && vector_opcode == ucode::AluVectorOpcode::kMad && + result.has_all_writes() && + operands[2].storage_source == + InstructionStorageSource::kConstantFloat && + operands[2].storage_addressing_mode == + InstructionStorageAddressingMode::kStatic && + operands[2].is_standard_swizzle()) { + return operands[2].storage_index; + } + return UINT32_MAX; + } + // Disassembles the instruction into ucode assembly text. void Disassemble(StringBuffer* out) const; }; diff --git a/src/xenia/gpu/shader_translator.cc b/src/xenia/gpu/shader_translator.cc index 900ec42b2..e829e665f 100644 --- a/src/xenia/gpu/shader_translator.cc +++ b/src/xenia/gpu/shader_translator.cc @@ -145,6 +145,15 @@ bool ShaderTranslator::TranslateInternal(Shader* shader) { GatherInstructionInformation(cf_a); GatherInstructionInformation(cf_b); } + // Cleanup invalid/unneeded memexport allocs. + for (uint32_t i = 0; i < kMaxMemExports; ++i) { + if (!memexport_eM_written_[i]) { + memexport_eA_written_ &= ~(1u << i); + } + } + if (memexport_eA_written_ == 0) { + memexport_stream_constants_.clear(); + } StartTranslation();