#pragma once /** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2015 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** * * @modified Tom Clay, 2026 - Adapted for ReXGlue runtime */ #include #include #include #include #include #include #include #include #include #include namespace rex::graphics { class ShaderTranslator { public: virtual ~ShaderTranslator(); virtual uint64_t GetDefaultVertexShaderModification( uint32_t /*dynamic_addressable_register_count*/, Shader::HostVertexShaderType /*host_vertex_shader_type*/ = Shader::HostVertexShaderType::kVertex) const { return 0; } virtual uint64_t GetDefaultPixelShaderModification( uint32_t /*dynamic_addressable_register_count*/) const { return 0; } // AnalyzeUcode must be done on the shader before translating! bool TranslateAnalyzedShader(Shader::Translation& translation); protected: ShaderTranslator(); // Resets translator state before beginning translation. virtual void Reset(); // Shader and modification currently being translated. Shader::Translation& current_translation() const { return *translation_; } Shader& current_shader() const { return current_translation().shader(); } // Register count from SQ_PROGRAM_CNTL, stored by the implementation in its // modification bits. virtual uint32_t GetModificationRegisterCount() const { return xenos::kMaxShaderTempRegisters; } // True if the current shader is a vertex shader. bool is_vertex_shader() const { return current_shader().type() == xenos::ShaderType::kVertex; } // True if the current shader is a pixel shader. bool is_pixel_shader() const { return current_shader().type() == xenos::ShaderType::kPixel; } // Temporary register count, accessible via static and dynamic addressing. uint32_t register_count() const { return register_count_; } // Emits a translation error that will be passed back in the result. virtual void EmitTranslationError(const char* message, bool is_fatal = true); // Handles the start of translation. // At this point the vertex and texture bindings have been gathered. virtual void StartTranslation() {} // Handles the end of translation when all ucode has been processed. // Returns the translated shader binary. virtual std::vector CompleteTranslation() { return std::vector(); } // Handles post-translation tasks when the shader has been fully translated. virtual void PostTranslation() {} // Sets the host disassembly on a shader. void set_host_disassembly(Shader::Translation& translation, std::string value) { translation.host_disassembly_ = std::move(value); } // Pre-process a control-flow instruction before anything else. virtual void PreProcessControlFlowInstructions( std::vector /*instrs*/) {} // Handles translation for control flow label addresses. // This is triggered once for each label required (due to control flow // operations) before any of the instructions within the target exec. virtual void ProcessLabel(uint32_t /*cf_index*/) {} // Handles translation for control flow nop instructions. virtual void ProcessControlFlowNopInstruction(uint32_t /*cf_index*/) {} // Handles the start of a control flow instruction at the given address. virtual void ProcessControlFlowInstructionBegin(uint32_t /*cf_index*/) {} // Handles the end of a control flow instruction that began at the given // address. virtual void ProcessControlFlowInstructionEnd(uint32_t /*cf_index*/) {} // Handles translation for control flow exec instructions prior to their // contained ALU/fetch instructions. virtual void ProcessExecInstructionBegin(const ParsedExecInstruction& /*instr*/) {} // Handles translation for control flow exec instructions after their // contained ALU/fetch instructions. virtual void ProcessExecInstructionEnd(const ParsedExecInstruction& /*instr*/) {} // Handles translation for loop start instructions. virtual void ProcessLoopStartInstruction(const ParsedLoopStartInstruction& /*instr*/) {} // Handles translation for loop end instructions. virtual void ProcessLoopEndInstruction(const ParsedLoopEndInstruction& /*instr*/) {} // Handles translation for function call instructions. virtual void ProcessCallInstruction(const ParsedCallInstruction& /*instr*/) {} // Handles translation for function return instructions. virtual void ProcessReturnInstruction(const ParsedReturnInstruction& /*instr*/) {} // Handles translation for jump instructions. virtual void ProcessJumpInstruction(const ParsedJumpInstruction& /*instr*/) {} // Handles translation for alloc instructions. Memory exports for eM# // indicated by export_eM must be performed, regardless of the alloc type. virtual void ProcessAllocInstruction(const ParsedAllocInstruction& /*instr*/, uint8_t /*export_eM*/) {} // Handles translation for vertex fetch instructions. virtual void ProcessVertexFetchInstruction(const ParsedVertexFetchInstruction& /*instr*/) {} // Handles translation for texture fetch instructions. virtual void ProcessTextureFetchInstruction(const ParsedTextureFetchInstruction& /*instr*/) {} // Handles translation for ALU instructions. // memexport_eM_potentially_written_before needs to be handled by `kill` // instruction to make sure memory exports for the eM# writes earlier in // previous execs and the current exec are done before the invocation becomes // inactive. virtual void ProcessAluInstruction(const ParsedAluInstruction& /*instr*/, uint8_t /*memexport_eM_potentially_written_before*/) {} private: void TranslateControlFlowInstruction(const ucode::ControlFlowInstruction& cf); void TranslateExecInstructions(const ParsedExecInstruction& instr); // Current shader and modification being translated. Shader::Translation* translation_ = nullptr; // Accumulated translation errors. std::vector errors_; // Temporary register count, accessible via static and dynamic addressing. uint32_t register_count_ = 0; // Current control flow dword index. uint32_t cf_index_ = 0; // Kept for supporting vfetch_mini. ucode::VertexFetchInstruction previous_vfetch_full_; }; } // namespace rex::graphics