mirror of
				https://github.com/hedge-dev/XenosRecomp.git
				synced 2025-10-30 07:12:17 +00:00 
			
		
		
		
	Compare commits
	
		
			3 commits
		
	
	
		
			ad36f68eb3
			...
			1e39d70a37
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 1e39d70a37 | ||
|   | 18145fa4c5 | ||
|   | f70589d684 | 
					 5 changed files with 362 additions and 102 deletions
				
			
		|  | @ -12,6 +12,8 @@ set(SMOLV_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/smol-v/source") | |||
| 
 | ||||
| add_executable(XenosRecomp | ||||
|     constant_table.h | ||||
|     air_compiler.cpp | ||||
|     air_compiler.h | ||||
|     dxc_compiler.cpp | ||||
|     dxc_compiler.h | ||||
|     main.cpp | ||||
|  |  | |||
							
								
								
									
										109
									
								
								XenosRecomp/air_compiler.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								XenosRecomp/air_compiler.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,109 @@ | |||
| #include "air_compiler.h" | ||||
| 
 | ||||
| #include <iostream> | ||||
| #include <spawn.h> | ||||
| #include <unistd.h> | ||||
| #include <sys/wait.h> | ||||
| #include <cstdio> | ||||
| 
 | ||||
| std::vector<uint8_t> AirCompiler::compile(const std::string& shaderSource) { | ||||
|     // First, generate AIR from shader source
 | ||||
|     std::string inputFile = ".metal"; | ||||
|     int tmpFD = makeTemporaryFile(inputFile); | ||||
|     write(tmpFD, shaderSource.data(), shaderSource.size()); | ||||
|     close(tmpFD); | ||||
| 
 | ||||
|     std::string irFile = ".ir"; | ||||
|     tmpFD = makeTemporaryFile(irFile); | ||||
|     close(tmpFD); | ||||
| 
 | ||||
|     pid_t pid; | ||||
|     char* airArgv[] = { "xcrun", "-sdk", "macosx", "metal", "-o", irFile.data(), "-c", inputFile.data(), "-D__air__", "-DUNLEASHED_RECOMP", "-Wno-unused-variable", nullptr }; | ||||
| 
 | ||||
|     if (posix_spawn(&pid, "/usr/bin/xcrun", nullptr, nullptr, airArgv, nullptr) != 0) { | ||||
|         unlink(inputFile.data()); | ||||
|         unlink(irFile.data()); | ||||
|         fmt::println("Failed to spawn AIR xcrun process"); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     int status; | ||||
| 
 | ||||
|     if (waitpid(pid, &status, 0) == -1) { | ||||
|         unlink(inputFile.data()); | ||||
|         unlink(irFile.data()); | ||||
|         fmt::println("Failed to wait AIR xcrun process"); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { | ||||
|         unlink(inputFile.data()); | ||||
|         unlink(irFile.data()); | ||||
|         fmt::println("AIR xcrun exited with code {}", WEXITSTATUS(status)); | ||||
|         fmt::println("{}", shaderSource); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     unlink(inputFile.data()); | ||||
| 
 | ||||
|     // Now we need to turn the AIR into a .metallib
 | ||||
|     std::string libFile = ".metallib"; | ||||
|     tmpFD = makeTemporaryFile(libFile); | ||||
|     close(tmpFD); | ||||
| 
 | ||||
|     char* libArgv[] = { "xcrun", "-sdk", "macosx", "metallib", "-o", libFile.data(), irFile.data(), nullptr }; | ||||
| 
 | ||||
|     if (posix_spawn(&pid, "/usr/bin/xcrun", nullptr, nullptr, libArgv, nullptr) != 0) { | ||||
|         unlink(irFile.data()); | ||||
|         unlink(libFile.data()); | ||||
|         fmt::println("Failed to spawn .metallib xcrun process"); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     if (waitpid(pid, &status, 0) == -1) { | ||||
|         unlink(irFile.data()); | ||||
|         unlink(libFile.data()); | ||||
|         fmt::println("Failed to wait .metallib xcrun process"); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { | ||||
|         unlink(irFile.data()); | ||||
|         unlink(libFile.data()); | ||||
|         fmt::println(".metallib exited with code {}", WEXITSTATUS(status)); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     // Read from built .metallib
 | ||||
|     FILE* file = fopen(libFile.data(), "rb"); | ||||
|     fseek(file, 0, SEEK_END); | ||||
|     size_t fileSize = ftell(file); | ||||
|     fseek(file, 0, SEEK_SET); | ||||
|     auto data = std::vector<uint8_t>(fileSize); | ||||
|     fread(data.data(), 1, fileSize, file); | ||||
|     fclose(file); | ||||
| 
 | ||||
|     // Cleanup temporary files
 | ||||
|     unlink(irFile.data()); | ||||
|     unlink(libFile.data()); | ||||
| 
 | ||||
|     return data; | ||||
| } | ||||
| 
 | ||||
| int AirCompiler::makeTemporaryFile(std::string &extension) { | ||||
|     const std::string path = "/tmp/xenos_metal_XXXXXX"; | ||||
| 
 | ||||
|     size_t size = path.size() + extension.size() + 1; | ||||
|     char fullTemplate[size]; | ||||
|     snprintf(fullTemplate, size, "%s%s", path.c_str(), extension.c_str()); | ||||
| 
 | ||||
|     int tmpFD = mkstemps(fullTemplate, extension.size()); | ||||
|     if (tmpFD == -1) { | ||||
|         fmt::println("Failed to open temporary file, \"{}\"!", std::string(fullTemplate)); | ||||
|         unlink(fullTemplate); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     extension = fullTemplate; | ||||
|     return tmpFD; | ||||
| } | ||||
							
								
								
									
										9
									
								
								XenosRecomp/air_compiler.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								XenosRecomp/air_compiler.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | |||
| #pragma once | ||||
| 
 | ||||
| struct AirCompiler | ||||
| { | ||||
|     static std::vector<uint8_t> compile(const std::string& shaderSource); | ||||
| 
 | ||||
| private: | ||||
|     static int makeTemporaryFile(std::string& extension); | ||||
| }; | ||||
|  | @ -1,6 +1,7 @@ | |||
| #include "shader.h" | ||||
| #include "shader_recompiler.h" | ||||
| #include "dxc_compiler.h" | ||||
| #include "air_compiler.h" | ||||
| 
 | ||||
| static std::unique_ptr<uint8_t[]> readAllBytes(const char* filePath, size_t& fileSize) | ||||
| { | ||||
|  | @ -26,6 +27,7 @@ struct RecompiledShader | |||
|     uint8_t* data = nullptr; | ||||
|     IDxcBlob* dxil = nullptr; | ||||
|     std::vector<uint8_t> spirv; | ||||
|     std::vector<uint8_t> air; | ||||
|     uint32_t specConstantsMask = 0; | ||||
| }; | ||||
| 
 | ||||
|  | @ -133,6 +135,10 @@ int main(int argc, char** argv) | |||
|                 assert(*(reinterpret_cast<uint32_t *>(shader.dxil->GetBufferPointer()) + 1) != 0 && "DXIL was not signed properly!"); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef XENOS_RECOMP_AIR | ||||
|                 shader.air = AirCompiler::compile(recompiler.out); | ||||
| #endif | ||||
| 
 | ||||
|                 IDxcBlob* spirv = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, false, true); | ||||
|                 assert(spirv != nullptr); | ||||
| 
 | ||||
|  | @ -154,11 +160,13 @@ int main(int argc, char** argv) | |||
| 
 | ||||
|         std::vector<uint8_t> dxil; | ||||
|         std::vector<uint8_t> spirv; | ||||
|         std::vector<uint8_t> air; | ||||
| 
 | ||||
|         for (auto& [hash, shader] : shaders) | ||||
|         { | ||||
|             f.println("\t{{ 0x{:X}, {}, {}, {}, {}, {} }},", | ||||
|                 hash, dxil.size(), (shader.dxil != nullptr) ? shader.dxil->GetBufferSize() : 0, spirv.size(), shader.spirv.size(), shader.specConstantsMask); | ||||
|             f.println("\t{{ 0x{:X}, {}, {}, {}, {}, {}, {}, {} }},", | ||||
|                 hash, dxil.size(), (shader.dxil != nullptr) ? shader.dxil->GetBufferSize() : 0, | ||||
|                 spirv.size(), shader.spirv.size(), air.size(), shader.air.size(), shader.specConstantsMask); | ||||
| 
 | ||||
|             if (shader.dxil != nullptr) | ||||
|             { | ||||
|  | @ -166,6 +174,10 @@ int main(int argc, char** argv) | |||
|                     reinterpret_cast<uint8_t *>(shader.dxil->GetBufferPointer()) + shader.dxil->GetBufferSize()); | ||||
|             } | ||||
| 
 | ||||
| #ifdef XENOS_RECOMP_AIR | ||||
|             air.insert(air.end(), shader.air.begin(), shader.air.end()); | ||||
| #endif | ||||
| 
 | ||||
|             spirv.insert(spirv.end(), shader.spirv.begin(), shader.spirv.end()); | ||||
|         } | ||||
| 
 | ||||
|  | @ -189,6 +201,22 @@ int main(int argc, char** argv) | |||
|         f.println("const size_t g_dxilCacheDecompressedSize = {};", dxil.size()); | ||||
| #endif | ||||
| 
 | ||||
| #ifdef XENOS_RECOMP_AIR | ||||
|         fmt::println("Compressing AIR cache..."); | ||||
| 
 | ||||
|         std::vector<uint8_t> airCompressed(ZSTD_compressBound(air.size())); | ||||
|         airCompressed.resize(ZSTD_compress(airCompressed.data(), airCompressed.size(), air.data(), air.size(), level)); | ||||
| 
 | ||||
|         f.print("const uint8_t g_compressedAirCache[] = {{"); | ||||
| 
 | ||||
|         for (auto data : airCompressed) | ||||
|             f.print("{},", data); | ||||
| 
 | ||||
|         f.println("}};"); | ||||
|         f.println("const size_t g_airCacheCompressedSize = {};", airCompressed.size()); | ||||
|         f.println("const size_t g_airCacheDecompressedSize = {};", air.size()); | ||||
| #endif | ||||
| 
 | ||||
|         fmt::println("Compressing SPIRV cache..."); | ||||
| 
 | ||||
|         std::vector<uint8_t> spirvCompressed(ZSTD_compressBound(spirv.size())); | ||||
|  |  | |||
|  | @ -417,6 +417,12 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|         SCALAR_CONSTANT_1 | ||||
|     }; | ||||
| 
 | ||||
|     struct OperationResult | ||||
|     { | ||||
|         std::string expression; | ||||
|         size_t componentCount; | ||||
|     }; | ||||
| 
 | ||||
|     auto op = [&](size_t operand) | ||||
|         { | ||||
|             size_t reg = 0; | ||||
|  | @ -521,16 +527,16 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             std::string result; | ||||
|             OperationResult opResult {}; | ||||
| 
 | ||||
|             if (negate) | ||||
|                 result += '-'; | ||||
|                 opResult.expression += '-'; | ||||
| 
 | ||||
|             if (abs) | ||||
|                 result += "abs("; | ||||
|                 opResult.expression += "abs("; | ||||
| 
 | ||||
|             result += regFormatted; | ||||
|             result += '.'; | ||||
|             opResult.expression += regFormatted; | ||||
|             opResult.expression += '.'; | ||||
| 
 | ||||
|             switch (operand) | ||||
|             { | ||||
|  | @ -562,8 +568,10 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
| 
 | ||||
|                 for (size_t i = 0; i < 4; i++) | ||||
|                 { | ||||
|                     if ((mask >> i) & 0x1) | ||||
|                         result += SWIZZLES[((swizzle >> (i * 2)) + i) & 0x3]; | ||||
|                     if ((mask >> i) & 0x1) { | ||||
|                         opResult.componentCount++; | ||||
|                         opResult.expression += SWIZZLES[((swizzle >> (i * 2)) + i) & 0x3]; | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
|  | @ -571,41 +579,43 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
| 
 | ||||
|             case SCALAR_0: | ||||
|             case SCALAR_CONSTANT_0: | ||||
|                 result += SWIZZLES[((swizzle >> 6) + 3) & 0x3]; | ||||
|                 opResult.componentCount = 1; | ||||
|                 opResult.expression += SWIZZLES[((swizzle >> 6) + 3) & 0x3]; | ||||
|                 break; | ||||
| 
 | ||||
|             case SCALAR_1: | ||||
|             case SCALAR_CONSTANT_1: | ||||
|                 result += SWIZZLES[swizzle & 0x3]; | ||||
|                 opResult.componentCount = 1; | ||||
|                 opResult.expression += SWIZZLES[swizzle & 0x3]; | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             if (abs) | ||||
|                 result += ")"; | ||||
|                 opResult.expression += ")"; | ||||
| 
 | ||||
|             return result; | ||||
|             return opResult; | ||||
|         }; | ||||
| 
 | ||||
|     switch (instr.vectorOpcode) | ||||
|     { | ||||
|     case AluVectorOpcode::KillEq: | ||||
|         indent(); | ||||
|         println("clip(any({} == {}) ? -1 : 1);", op(VECTOR_0), op(VECTOR_1)); | ||||
|         println("clip(any({} == {}) ? -1 : 1);", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|         break; | ||||
|      | ||||
|     case AluVectorOpcode::KillGt: | ||||
|         indent(); | ||||
|         println("clip(any({} > {}) ? -1 : 1);", op(VECTOR_0), op(VECTOR_1)); | ||||
|         println("clip(any({} > {}) ? -1 : 1);", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|         break; | ||||
|      | ||||
|     case AluVectorOpcode::KillGe: | ||||
|         indent(); | ||||
|         println("clip(any({} >= {}) ? -1 : 1);", op(VECTOR_0), op(VECTOR_1)); | ||||
|         println("clip(any({} >= {}) ? -1 : 1);", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|         break; | ||||
|      | ||||
|     case AluVectorOpcode::KillNe: | ||||
|         indent(); | ||||
|         println("clip(any({} != {}) ? -1 : 1);", op(VECTOR_0), op(VECTOR_1)); | ||||
|         println("clip(any({} != {}) ? -1 : 1);", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|  | @ -674,7 +684,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|     if (instr.vectorOpcode >= AluVectorOpcode::SetpEqPush && instr.vectorOpcode <= AluVectorOpcode::SetpGePush) | ||||
|     { | ||||
|         indent(); | ||||
|         print("p0 = {} == 0.0 && {} ", op(VECTOR_0), op(VECTOR_1)); | ||||
|         print("p0 = {} == 0.0 && {} ", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
| 
 | ||||
|         switch (instr.vectorOpcode) | ||||
|         { | ||||
|  | @ -697,7 +707,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|     else if (instr.vectorOpcode >= AluVectorOpcode::MaxA) | ||||
|     { | ||||
|         indent(); | ||||
|         println("a0 = (int)clamp(floor(({}).w + 0.5), -256.0, 255.0);", op(VECTOR_0)); | ||||
|         println("a0 = (int)clamp(floor(({}).w + 0.5), -256.0, 255.0);", op(VECTOR_0).expression); | ||||
|     } | ||||
| 
 | ||||
|     uint32_t vectorWriteMask = instr.vectorWriteMask; | ||||
|  | @ -732,87 +742,169 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
| 
 | ||||
|         out += " = "; | ||||
| 
 | ||||
|         bool scalarRegWrite = vectorWriteSize <= 1; | ||||
| 
 | ||||
|         if (vectorWriteSize > 1) | ||||
|             print("(float{})(", vectorWriteSize); | ||||
|         else | ||||
|             out += "(float)("; | ||||
|             out += "(float)(("; | ||||
| 
 | ||||
|         if (instr.vectorSaturate) | ||||
|             out += "saturate("; | ||||
| 
 | ||||
|         size_t operationResultComponentCount; | ||||
| 
 | ||||
|         switch (instr.vectorOpcode) | ||||
|         { | ||||
|         case AluVectorOpcode::Add: | ||||
|             print("{} + {}", op(VECTOR_0), op(VECTOR_1)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 auto v1 = op(VECTOR_1); | ||||
|                 operationResultComponentCount = std::max(v0.componentCount, v1.componentCount); | ||||
| 
 | ||||
|                 print("{} + {}", v0.expression, v1.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::Mul: | ||||
|             print("{} * {}", op(VECTOR_0), op(VECTOR_1)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 auto v1 = op(VECTOR_1); | ||||
|                 operationResultComponentCount = std::max(v0.componentCount, v1.componentCount); | ||||
| 
 | ||||
|                 print("{} * {}", v0.expression, v1.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::Max: | ||||
|         case AluVectorOpcode::MaxA: | ||||
|             print("max({}, {})", op(VECTOR_0), op(VECTOR_1)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 auto v1 = op(VECTOR_1); | ||||
|                 operationResultComponentCount = v0.componentCount; | ||||
| 
 | ||||
|                 print("max({}, {})", v0.expression, v1.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::Min: | ||||
|             print("min({}, {})", op(VECTOR_0), op(VECTOR_1)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 auto v1 = op(VECTOR_1); | ||||
|                 operationResultComponentCount = v0.componentCount; | ||||
| 
 | ||||
|                 print("min({}, {})", v0.expression, v1.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::Seq: | ||||
|             print("{} == {}", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 1; | ||||
|             print("{} == {}", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::Sgt: | ||||
|             print("{} > {}", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 1; | ||||
|             print("{} > {}", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::Sge: | ||||
|             print("{} >= {}", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 1; | ||||
|             print("{} >= {}", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::Sne: | ||||
|             print("{} != {}", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 1; | ||||
|             print("{} != {}", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::Frc: | ||||
|             print("frac({})", op(VECTOR_0)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 operationResultComponentCount = v0.componentCount; | ||||
| 
 | ||||
|                 print("frac({})", v0.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::Trunc: | ||||
|             print("trunc({})", op(VECTOR_0)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 operationResultComponentCount = v0.componentCount; | ||||
| 
 | ||||
|                 print("trunc({})", v0.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::Floor: | ||||
|             print("floor({})", op(VECTOR_0)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 operationResultComponentCount = v0.componentCount; | ||||
| 
 | ||||
|                 print("floor({})", v0.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::Mad: | ||||
|             print("{} * {} + {}", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 auto v1 = op(VECTOR_1); | ||||
|                 auto v2 = op(VECTOR_2); | ||||
|                 operationResultComponentCount = std::max(std::max(v0.componentCount, v1.componentCount), v2.componentCount); | ||||
| 
 | ||||
|                 print("{} * {} + {}", v0.expression, v1.expression, v2.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::CndEq: | ||||
|             print("selectWrapper({} == 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 auto v1 = op(VECTOR_1); | ||||
|                 auto v2 = op(VECTOR_2); | ||||
|                 operationResultComponentCount = std::max(v1.componentCount, v2.componentCount); | ||||
| 
 | ||||
|                 print("selectWrapper({} == 0.0, {}, {})", v0.expression, v1.expression, v2.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::CndGe: | ||||
|             print("selectWrapper({} >= 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 auto v1 = op(VECTOR_1); | ||||
|                 auto v2 = op(VECTOR_2); | ||||
|                 operationResultComponentCount = std::max(v1.componentCount, v2.componentCount); | ||||
| 
 | ||||
|                 print("selectWrapper({} >= 0.0, {}, {})", v0.expression, v1.expression, v2.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::CndGt: | ||||
|             print("selectWrapper({} > 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 auto v1 = op(VECTOR_1); | ||||
|                 auto v2 = op(VECTOR_2); | ||||
|                 operationResultComponentCount = std::max(v1.componentCount, v2.componentCount); | ||||
| 
 | ||||
|                 print("selectWrapper({} > 0.0, {}, {})", v0.expression, v1.expression, v2.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::Dp4: | ||||
|         case AluVectorOpcode::Dp3: | ||||
|             print("dot({}, {})", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 1; | ||||
|             print("dot({}, {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::Dp2Add: | ||||
|             print("dot({}, {}) + {}", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v2 = op(VECTOR_2); | ||||
|                 operationResultComponentCount = v2.componentCount; | ||||
| 
 | ||||
|                 print("dot({}, {}) + {}", op(VECTOR_0).expression, op(VECTOR_1).expression, v2.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::Cube: | ||||
|             operationResultComponentCount = 4; | ||||
|             println("\n#ifdef __air__"); | ||||
|             indent(); | ||||
|             print("cube(r{}, &cubeMapData)", instr.src1Register); | ||||
|  | @ -823,41 +915,61 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::Max4: | ||||
|             print("max4({})", op(VECTOR_0)); | ||||
|             operationResultComponentCount = 4; | ||||
|             print("max4({})", op(VECTOR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::SetpEqPush: | ||||
|         case AluVectorOpcode::SetpNePush: | ||||
|         case AluVectorOpcode::SetpGtPush: | ||||
|         case AluVectorOpcode::SetpGePush: | ||||
|             print("p0 ? 0.0 : {} + 1.0", op(VECTOR_0)); | ||||
|             break; | ||||
|             { | ||||
|                 auto v0 = op(VECTOR_0); | ||||
|                 operationResultComponentCount = v0.componentCount; | ||||
| 
 | ||||
|                 print("p0 ? 0.0 : {} + 1.0", v0.expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|         case AluVectorOpcode::KillEq: | ||||
|             print("any({} == {})", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 1; | ||||
|             print("any({} == {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::KillGt: | ||||
|             print("any({} > {})", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 1; | ||||
|             print("any({} > {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::KillGe: | ||||
|             print("any({} >= {})", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 1; | ||||
|             print("any({} >= {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::KillNe: | ||||
|             print("any({} != {})", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 1; | ||||
|             print("any({} != {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluVectorOpcode::Dst: | ||||
|             print("dst({}, {})", op(VECTOR_0), op(VECTOR_1)); | ||||
|             operationResultComponentCount = 4; | ||||
|             print("dst({}, {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
| 		out += ")"; | ||||
| 
 | ||||
|         if (scalarRegWrite) { | ||||
|             if (operationResultComponentCount > 1) | ||||
|                 out += ".x"; | ||||
| 
 | ||||
|             out += ")"; | ||||
|         } | ||||
| 
 | ||||
|         if (instr.vectorSaturate) | ||||
|             out += ')'; | ||||
| 
 | ||||
|         out += ");\n"; | ||||
|         out += ";\n"; | ||||
|     } | ||||
| 
 | ||||
|     if (instr.scalarOpcode != AluScalarOpcode::RetainPrev) | ||||
|  | @ -870,27 +982,27 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|             switch (instr.scalarOpcode) | ||||
|             { | ||||
|             case AluScalarOpcode::SetpEq: | ||||
|                 print("{} == 0.0", op(SCALAR_0)); | ||||
|                 print("{} == 0.0", op(SCALAR_0).expression); | ||||
|                 break; | ||||
| 
 | ||||
|             case AluScalarOpcode::SetpNe: | ||||
|                 print("{} != 0.0", op(SCALAR_0)); | ||||
|                 print("{} != 0.0", op(SCALAR_0).expression); | ||||
|                 break; | ||||
| 
 | ||||
|             case AluScalarOpcode::SetpGt: | ||||
|                 print("{} > 0.0", op(SCALAR_0)); | ||||
|                 print("{} > 0.0", op(SCALAR_0).expression); | ||||
|                 break; | ||||
| 
 | ||||
|             case AluScalarOpcode::SetpGe: | ||||
|                 print("{} >= 0.0", op(SCALAR_0)); | ||||
|                 print("{} >= 0.0", op(SCALAR_0).expression); | ||||
|                 break; | ||||
| 
 | ||||
|             case AluScalarOpcode::SetpInv: | ||||
|                 print("{} == 1.0", op(SCALAR_0)); | ||||
|                 print("{} == 1.0", op(SCALAR_0).expression); | ||||
|                 break; | ||||
| 
 | ||||
|             case AluScalarOpcode::SetpPop: | ||||
|                 print("{} - 1.0 <= 0.0", op(SCALAR_0)); | ||||
|                 print("{} - 1.0 <= 0.0", op(SCALAR_0).expression); | ||||
|                 break; | ||||
| 
 | ||||
|             case AluScalarOpcode::SetpClr: | ||||
|  | @ -898,7 +1010,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|                 break; | ||||
| 
 | ||||
|             case AluScalarOpcode::SetpRstr: | ||||
|                 print("{} == 0.0", op(SCALAR_0)); | ||||
|                 print("{} == 0.0", op(SCALAR_0).expression); | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|  | @ -913,87 +1025,87 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|         switch (instr.scalarOpcode) | ||||
|         { | ||||
|         case AluScalarOpcode::Adds: | ||||
|             print("{} + {}", op(SCALAR_0), op(SCALAR_1)); | ||||
|             print("{} + {}", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::AddsPrev: | ||||
|             print("{} + ps", op(SCALAR_0)); | ||||
|             print("{} + ps", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Muls: | ||||
|             print("{} * {}", op(SCALAR_0), op(SCALAR_1)); | ||||
|             print("{} * {}", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::MulsPrev: | ||||
|         case AluScalarOpcode::MulsPrev2: | ||||
|             print("{} * ps", op(SCALAR_0)); | ||||
|             print("{} * ps", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Maxs: | ||||
|         case AluScalarOpcode::MaxAs: | ||||
|         case AluScalarOpcode::MaxAsf: | ||||
|             print("max({}, {})", op(SCALAR_0), op(SCALAR_1)); | ||||
|             print("max({}, {})", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Mins: | ||||
|             print("min({}, {})", op(SCALAR_0), op(SCALAR_1)); | ||||
|             print("min({}, {})", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Seqs: | ||||
|             print("{} == 0.0", op(SCALAR_0)); | ||||
|             print("{} == 0.0", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Sgts: | ||||
|             print("{} > 0.0", op(SCALAR_0)); | ||||
|             print("{} > 0.0", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Sges: | ||||
|             print("{} >= 0.0", op(SCALAR_0)); | ||||
|             print("{} >= 0.0", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Snes: | ||||
|             print("{} != 0.0", op(SCALAR_0)); | ||||
|             print("{} != 0.0", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Frcs: | ||||
|             print("frac({})", op(SCALAR_0)); | ||||
|             print("frac({})", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Truncs: | ||||
|             print("trunc({})", op(SCALAR_0)); | ||||
|             print("trunc({})", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Floors: | ||||
|             print("floor({})", op(SCALAR_0)); | ||||
|             print("floor({})", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Exp: | ||||
|             print("exp2({})", op(SCALAR_0)); | ||||
|             print("exp2({})", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Logc: | ||||
|         case AluScalarOpcode::Log: | ||||
|             print("clamp(log2({}), FLT_MIN, FLT_MAX)", op(SCALAR_0)); | ||||
|             print("clamp(log2({}), FLT_MIN, FLT_MAX)", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Rcpc: | ||||
|         case AluScalarOpcode::Rcpf: | ||||
|         case AluScalarOpcode::Rcp: | ||||
|             print("clamp(rcp({}), FLT_MIN, FLT_MAX)", op(SCALAR_0)); | ||||
|             print("clamp(rcp({}), FLT_MIN, FLT_MAX)", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Rsqc: | ||||
|         case AluScalarOpcode::Rsqf: | ||||
|         case AluScalarOpcode::Rsq: | ||||
|             print("clamp(rsqrt({}), FLT_MIN, FLT_MAX)", op(SCALAR_0)); | ||||
|             print("clamp(rsqrt({}), FLT_MIN, FLT_MAX)", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Subs: | ||||
|             print("{} - {}", op(SCALAR_0), op(SCALAR_1)); | ||||
|             print("{} - {}", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::SubsPrev: | ||||
|             print("{} - ps", op(SCALAR_0)); | ||||
|             print("{} - ps", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::SetpEq: | ||||
|  | @ -1004,11 +1116,11 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::SetpInv: | ||||
|             print("{0} == 0.0 ? 1.0 : {0}", op(SCALAR_0)); | ||||
|             print("{0} == 0.0 ? 1.0 : {0}", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::SetpPop: | ||||
|             print("p0 ? 0.0 : ({} - 1.0)", op(SCALAR_0)); | ||||
|             print("p0 ? 0.0 : ({} - 1.0)", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::SetpClr: | ||||
|  | @ -1016,54 +1128,54 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::SetpRstr: | ||||
|             print("p0 ? 0.0 : {}", op(SCALAR_0)); | ||||
|             print("p0 ? 0.0 : {}", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::KillsEq: | ||||
|             print("{} == 0.0", op(SCALAR_0)); | ||||
|             print("{} == 0.0", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::KillsGt: | ||||
|             print("{} > 0.0", op(SCALAR_0)); | ||||
|             print("{} > 0.0", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::KillsGe: | ||||
|             print("{} >= 0.0", op(SCALAR_0)); | ||||
|             print("{} >= 0.0", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::KillsNe: | ||||
|             print("{} != 0.0", op(SCALAR_0)); | ||||
|             print("{} != 0.0", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::KillsOne: | ||||
|             print("{} == 1.0", op(SCALAR_0)); | ||||
|             print("{} == 1.0", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Sqrt: | ||||
|             print("sqrt({})", op(SCALAR_0)); | ||||
|             print("sqrt({})", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Mulsc0: | ||||
|         case AluScalarOpcode::Mulsc1: | ||||
|             print("{} * {}", op(SCALAR_CONSTANT_0), op(SCALAR_CONSTANT_1)); | ||||
|             print("{} * {}", op(SCALAR_CONSTANT_0).expression, op(SCALAR_CONSTANT_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Addsc0: | ||||
|         case AluScalarOpcode::Addsc1: | ||||
|             print("{} + {}", op(SCALAR_CONSTANT_0), op(SCALAR_CONSTANT_1)); | ||||
|             print("{} + {}", op(SCALAR_CONSTANT_0).expression, op(SCALAR_CONSTANT_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Subsc0: | ||||
|         case AluScalarOpcode::Subsc1: | ||||
|             print("{} - {}", op(SCALAR_CONSTANT_0), op(SCALAR_CONSTANT_1)); | ||||
|             print("{} - {}", op(SCALAR_CONSTANT_0).expression, op(SCALAR_CONSTANT_1).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Sin: | ||||
|             print("sin({})", op(SCALAR_0)); | ||||
|             print("sin({})", op(SCALAR_0).expression); | ||||
|             break; | ||||
| 
 | ||||
|         case AluScalarOpcode::Cos: | ||||
|             print("cos({})", op(SCALAR_0)); | ||||
|             print("cos({})", op(SCALAR_0).expression); | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|  | @ -1076,11 +1188,11 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | |||
|         { | ||||
|         case AluScalarOpcode::MaxAs: | ||||
|             indent(); | ||||
|             println("a0 = (int)clamp(floor({} + 0.5), -256.0, 255.0);", op(SCALAR_0)); | ||||
|             println("a0 = (int)clamp(floor({} + 0.5), -256.0, 255.0);", op(SCALAR_0).expression); | ||||
|             break;      | ||||
|         case AluScalarOpcode::MaxAsf: | ||||
|             indent(); | ||||
|             println("a0 = (int)clamp(floor({}), -256.0, 255.0);", op(SCALAR_0)); | ||||
|             println("a0 = (int)clamp(floor({}), -256.0, 255.0);", op(SCALAR_0).expression); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue