mirror of
				https://github.com/hedge-dev/XenosRecomp.git
				synced 2025-10-30 07:12:17 +00:00 
			
		
		
		
	Compare commits
	
		
			2 commits
		
	
	
		
			db0aefa529
			...
			18145fa4c5
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 18145fa4c5 | ||
|   | f70589d684 | 
					 5 changed files with 362 additions and 102 deletions
				
			
		|  | @ -10,8 +10,10 @@ endif() | ||||||
| 
 | 
 | ||||||
| set(SMOLV_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/smol-v/source") | set(SMOLV_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/smol-v/source") | ||||||
| 
 | 
 | ||||||
| add_executable(XenosRecomp  | add_executable(XenosRecomp | ||||||
|     constant_table.h |     constant_table.h | ||||||
|  |     air_compiler.cpp | ||||||
|  |     air_compiler.h | ||||||
|     dxc_compiler.cpp |     dxc_compiler.cpp | ||||||
|     dxc_compiler.h |     dxc_compiler.h | ||||||
|     main.cpp |     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.h" | ||||||
| #include "shader_recompiler.h" | #include "shader_recompiler.h" | ||||||
| #include "dxc_compiler.h" | #include "dxc_compiler.h" | ||||||
|  | #include "air_compiler.h" | ||||||
| 
 | 
 | ||||||
| static std::unique_ptr<uint8_t[]> readAllBytes(const char* filePath, size_t& fileSize) | static std::unique_ptr<uint8_t[]> readAllBytes(const char* filePath, size_t& fileSize) | ||||||
| { | { | ||||||
|  | @ -26,6 +27,7 @@ struct RecompiledShader | ||||||
|     uint8_t* data = nullptr; |     uint8_t* data = nullptr; | ||||||
|     IDxcBlob* dxil = nullptr; |     IDxcBlob* dxil = nullptr; | ||||||
|     std::vector<uint8_t> spirv; |     std::vector<uint8_t> spirv; | ||||||
|  |     std::vector<uint8_t> air; | ||||||
|     uint32_t specConstantsMask = 0; |     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!"); |                 assert(*(reinterpret_cast<uint32_t *>(shader.dxil->GetBufferPointer()) + 1) != 0 && "DXIL was not signed properly!"); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  | #ifdef XENOS_RECOMP_AIR | ||||||
|  |                 shader.air = AirCompiler::compile(recompiler.out); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|                 IDxcBlob* spirv = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, false, true); |                 IDxcBlob* spirv = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, false, true); | ||||||
|                 assert(spirv != nullptr); |                 assert(spirv != nullptr); | ||||||
| 
 | 
 | ||||||
|  | @ -154,18 +160,24 @@ int main(int argc, char** argv) | ||||||
| 
 | 
 | ||||||
|         std::vector<uint8_t> dxil; |         std::vector<uint8_t> dxil; | ||||||
|         std::vector<uint8_t> spirv; |         std::vector<uint8_t> spirv; | ||||||
|  |         std::vector<uint8_t> air; | ||||||
| 
 | 
 | ||||||
|         for (auto& [hash, shader] : shaders) |         for (auto& [hash, shader] : shaders) | ||||||
|         { |         { | ||||||
|             f.println("\t{{ 0x{:X}, {}, {}, {}, {}, {} }},", |             f.println("\t{{ 0x{:X}, {}, {}, {}, {}, {}, {}, {} }},", | ||||||
|                 hash, dxil.size(), (shader.dxil != nullptr) ? shader.dxil->GetBufferSize() : 0, spirv.size(), shader.spirv.size(), shader.specConstantsMask); |                 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) |             if (shader.dxil != nullptr) | ||||||
|             { |             { | ||||||
|                 dxil.insert(dxil.end(), reinterpret_cast<uint8_t *>(shader.dxil->GetBufferPointer()), |                 dxil.insert(dxil.end(), reinterpret_cast<uint8_t *>(shader.dxil->GetBufferPointer()), | ||||||
|                     reinterpret_cast<uint8_t *>(shader.dxil->GetBufferPointer()) + shader.dxil->GetBufferSize()); |                     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()); |             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()); |         f.println("const size_t g_dxilCacheDecompressedSize = {};", dxil.size()); | ||||||
| #endif | #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..."); |         fmt::println("Compressing SPIRV cache..."); | ||||||
| 
 | 
 | ||||||
|         std::vector<uint8_t> spirvCompressed(ZSTD_compressBound(spirv.size())); |         std::vector<uint8_t> spirvCompressed(ZSTD_compressBound(spirv.size())); | ||||||
|  |  | ||||||
|  | @ -417,6 +417,12 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|         SCALAR_CONSTANT_1 |         SCALAR_CONSTANT_1 | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     struct OperationResult | ||||||
|  |     { | ||||||
|  |         std::string expression; | ||||||
|  |         size_t componentCount; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     auto op = [&](size_t operand) |     auto op = [&](size_t operand) | ||||||
|         { |         { | ||||||
|             size_t reg = 0; |             size_t reg = 0; | ||||||
|  | @ -521,16 +527,16 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             std::string result; |             OperationResult opResult {}; | ||||||
| 
 | 
 | ||||||
|             if (negate) |             if (negate) | ||||||
|                 result += '-'; |                 opResult.expression += '-'; | ||||||
| 
 | 
 | ||||||
|             if (abs) |             if (abs) | ||||||
|                 result += "abs("; |                 opResult.expression += "abs("; | ||||||
| 
 | 
 | ||||||
|             result += regFormatted; |             opResult.expression += regFormatted; | ||||||
|             result += '.'; |             opResult.expression += '.'; | ||||||
| 
 | 
 | ||||||
|             switch (operand) |             switch (operand) | ||||||
|             { |             { | ||||||
|  | @ -562,8 +568,10 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
| 
 | 
 | ||||||
|                 for (size_t i = 0; i < 4; i++) |                 for (size_t i = 0; i < 4; i++) | ||||||
|                 { |                 { | ||||||
|                     if ((mask >> i) & 0x1) |                     if ((mask >> i) & 0x1) { | ||||||
|                         result += SWIZZLES[((swizzle >> (i * 2)) + i) & 0x3]; |                         opResult.componentCount++; | ||||||
|  |                         opResult.expression += SWIZZLES[((swizzle >> (i * 2)) + i) & 0x3]; | ||||||
|  |                     } | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 break; |                 break; | ||||||
|  | @ -571,41 +579,43 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
| 
 | 
 | ||||||
|             case SCALAR_0: |             case SCALAR_0: | ||||||
|             case SCALAR_CONSTANT_0: |             case SCALAR_CONSTANT_0: | ||||||
|                 result += SWIZZLES[((swizzle >> 6) + 3) & 0x3]; |                 opResult.componentCount = 1; | ||||||
|  |                 opResult.expression += SWIZZLES[((swizzle >> 6) + 3) & 0x3]; | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case SCALAR_1: |             case SCALAR_1: | ||||||
|             case SCALAR_CONSTANT_1: |             case SCALAR_CONSTANT_1: | ||||||
|                 result += SWIZZLES[swizzle & 0x3]; |                 opResult.componentCount = 1; | ||||||
|  |                 opResult.expression += SWIZZLES[swizzle & 0x3]; | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (abs) |             if (abs) | ||||||
|                 result += ")"; |                 opResult.expression += ")"; | ||||||
| 
 | 
 | ||||||
|             return result; |             return opResult; | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|     switch (instr.vectorOpcode) |     switch (instr.vectorOpcode) | ||||||
|     { |     { | ||||||
|     case AluVectorOpcode::KillEq: |     case AluVectorOpcode::KillEq: | ||||||
|         indent(); |         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; |         break; | ||||||
|      |      | ||||||
|     case AluVectorOpcode::KillGt: |     case AluVectorOpcode::KillGt: | ||||||
|         indent(); |         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; |         break; | ||||||
|      |      | ||||||
|     case AluVectorOpcode::KillGe: |     case AluVectorOpcode::KillGe: | ||||||
|         indent(); |         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; |         break; | ||||||
|      |      | ||||||
|     case AluVectorOpcode::KillNe: |     case AluVectorOpcode::KillNe: | ||||||
|         indent(); |         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; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -674,7 +684,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|     if (instr.vectorOpcode >= AluVectorOpcode::SetpEqPush && instr.vectorOpcode <= AluVectorOpcode::SetpGePush) |     if (instr.vectorOpcode >= AluVectorOpcode::SetpEqPush && instr.vectorOpcode <= AluVectorOpcode::SetpGePush) | ||||||
|     { |     { | ||||||
|         indent(); |         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) |         switch (instr.vectorOpcode) | ||||||
|         { |         { | ||||||
|  | @ -697,7 +707,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|     else if (instr.vectorOpcode >= AluVectorOpcode::MaxA) |     else if (instr.vectorOpcode >= AluVectorOpcode::MaxA) | ||||||
|     { |     { | ||||||
|         indent(); |         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; |     uint32_t vectorWriteMask = instr.vectorWriteMask; | ||||||
|  | @ -732,87 +742,169 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
| 
 | 
 | ||||||
|         out += " = "; |         out += " = "; | ||||||
| 
 | 
 | ||||||
|  |         bool scalarRegWrite = vectorWriteSize <= 1; | ||||||
|  | 
 | ||||||
|         if (vectorWriteSize > 1) |         if (vectorWriteSize > 1) | ||||||
|             print("(float{})(", vectorWriteSize); |             print("(float{})(", vectorWriteSize); | ||||||
|         else |         else | ||||||
|             out += "(float)("; |             out += "(float)(("; | ||||||
| 
 | 
 | ||||||
|         if (instr.vectorSaturate) |         if (instr.vectorSaturate) | ||||||
|             out += "saturate("; |             out += "saturate("; | ||||||
| 
 | 
 | ||||||
|  |         size_t operationResultComponentCount; | ||||||
|  | 
 | ||||||
|         switch (instr.vectorOpcode) |         switch (instr.vectorOpcode) | ||||||
|         { |         { | ||||||
|         case AluVectorOpcode::Add: |         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: |         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::Max: | ||||||
|         case AluVectorOpcode::MaxA: |         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: |         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: |         case AluVectorOpcode::Seq: | ||||||
|             print("{} == {}", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 1; | ||||||
|  |             print("{} == {}", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Sgt: |         case AluVectorOpcode::Sgt: | ||||||
|             print("{} > {}", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 1; | ||||||
|  |             print("{} > {}", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Sge: |         case AluVectorOpcode::Sge: | ||||||
|             print("{} >= {}", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 1; | ||||||
|  |             print("{} >= {}", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Sne: |         case AluVectorOpcode::Sne: | ||||||
|             print("{} != {}", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 1; | ||||||
|  |             print("{} != {}", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Frc: |         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: |         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: |         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: |         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: |         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: |         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: |         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::Dp4: | ||||||
|         case AluVectorOpcode::Dp3: |         case AluVectorOpcode::Dp3: | ||||||
|             print("dot({}, {})", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 1; | ||||||
|  |             print("dot({}, {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Dp2Add: |         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: |         case AluVectorOpcode::Cube: | ||||||
|  |             operationResultComponentCount = 4; | ||||||
|             println("\n#ifdef __air__"); |             println("\n#ifdef __air__"); | ||||||
|             indent(); |             indent(); | ||||||
|             print("cube(r{}, &cubeMapData)", instr.src1Register); |             print("cube(r{}, &cubeMapData)", instr.src1Register); | ||||||
|  | @ -823,41 +915,61 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Max4: |         case AluVectorOpcode::Max4: | ||||||
|             print("max4({})", op(VECTOR_0)); |             operationResultComponentCount = 4; | ||||||
|  |             print("max4({})", op(VECTOR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::SetpEqPush: |         case AluVectorOpcode::SetpEqPush: | ||||||
|         case AluVectorOpcode::SetpNePush: |         case AluVectorOpcode::SetpNePush: | ||||||
|         case AluVectorOpcode::SetpGtPush: |         case AluVectorOpcode::SetpGtPush: | ||||||
|         case AluVectorOpcode::SetpGePush: |         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: |         case AluVectorOpcode::KillEq: | ||||||
|             print("any({} == {})", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 1; | ||||||
|  |             print("any({} == {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::KillGt: |         case AluVectorOpcode::KillGt: | ||||||
|             print("any({} > {})", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 1; | ||||||
|  |             print("any({} > {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::KillGe: |         case AluVectorOpcode::KillGe: | ||||||
|             print("any({} >= {})", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 1; | ||||||
|  |             print("any({} >= {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::KillNe: |         case AluVectorOpcode::KillNe: | ||||||
|             print("any({} != {})", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 1; | ||||||
|  |             print("any({} != {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluVectorOpcode::Dst: |         case AluVectorOpcode::Dst: | ||||||
|             print("dst({}, {})", op(VECTOR_0), op(VECTOR_1)); |             operationResultComponentCount = 4; | ||||||
|  |             print("dst({}, {})", op(VECTOR_0).expression, op(VECTOR_1).expression); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | 		out += ")"; | ||||||
|  | 
 | ||||||
|  |         if (scalarRegWrite) { | ||||||
|  |             if (operationResultComponentCount > 1) | ||||||
|  |                 out += ".x"; | ||||||
|  | 
 | ||||||
|  |             out += ")"; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if (instr.vectorSaturate) |         if (instr.vectorSaturate) | ||||||
|             out += ')'; |             out += ')'; | ||||||
| 
 | 
 | ||||||
|         out += ");\n"; |         out += ";\n"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (instr.scalarOpcode != AluScalarOpcode::RetainPrev) |     if (instr.scalarOpcode != AluScalarOpcode::RetainPrev) | ||||||
|  | @ -870,27 +982,27 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|             switch (instr.scalarOpcode) |             switch (instr.scalarOpcode) | ||||||
|             { |             { | ||||||
|             case AluScalarOpcode::SetpEq: |             case AluScalarOpcode::SetpEq: | ||||||
|                 print("{} == 0.0", op(SCALAR_0)); |                 print("{} == 0.0", op(SCALAR_0).expression); | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case AluScalarOpcode::SetpNe: |             case AluScalarOpcode::SetpNe: | ||||||
|                 print("{} != 0.0", op(SCALAR_0)); |                 print("{} != 0.0", op(SCALAR_0).expression); | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case AluScalarOpcode::SetpGt: |             case AluScalarOpcode::SetpGt: | ||||||
|                 print("{} > 0.0", op(SCALAR_0)); |                 print("{} > 0.0", op(SCALAR_0).expression); | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case AluScalarOpcode::SetpGe: |             case AluScalarOpcode::SetpGe: | ||||||
|                 print("{} >= 0.0", op(SCALAR_0)); |                 print("{} >= 0.0", op(SCALAR_0).expression); | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case AluScalarOpcode::SetpInv: |             case AluScalarOpcode::SetpInv: | ||||||
|                 print("{} == 1.0", op(SCALAR_0)); |                 print("{} == 1.0", op(SCALAR_0).expression); | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case AluScalarOpcode::SetpPop: |             case AluScalarOpcode::SetpPop: | ||||||
|                 print("{} - 1.0 <= 0.0", op(SCALAR_0)); |                 print("{} - 1.0 <= 0.0", op(SCALAR_0).expression); | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case AluScalarOpcode::SetpClr: |             case AluScalarOpcode::SetpClr: | ||||||
|  | @ -898,7 +1010,7 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|                 break; |                 break; | ||||||
| 
 | 
 | ||||||
|             case AluScalarOpcode::SetpRstr: |             case AluScalarOpcode::SetpRstr: | ||||||
|                 print("{} == 0.0", op(SCALAR_0)); |                 print("{} == 0.0", op(SCALAR_0).expression); | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -913,87 +1025,87 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|         switch (instr.scalarOpcode) |         switch (instr.scalarOpcode) | ||||||
|         { |         { | ||||||
|         case AluScalarOpcode::Adds: |         case AluScalarOpcode::Adds: | ||||||
|             print("{} + {}", op(SCALAR_0), op(SCALAR_1)); |             print("{} + {}", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::AddsPrev: |         case AluScalarOpcode::AddsPrev: | ||||||
|             print("{} + ps", op(SCALAR_0)); |             print("{} + ps", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Muls: |         case AluScalarOpcode::Muls: | ||||||
|             print("{} * {}", op(SCALAR_0), op(SCALAR_1)); |             print("{} * {}", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::MulsPrev: |         case AluScalarOpcode::MulsPrev: | ||||||
|         case AluScalarOpcode::MulsPrev2: |         case AluScalarOpcode::MulsPrev2: | ||||||
|             print("{} * ps", op(SCALAR_0)); |             print("{} * ps", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Maxs: |         case AluScalarOpcode::Maxs: | ||||||
|         case AluScalarOpcode::MaxAs: |         case AluScalarOpcode::MaxAs: | ||||||
|         case AluScalarOpcode::MaxAsf: |         case AluScalarOpcode::MaxAsf: | ||||||
|             print("max({}, {})", op(SCALAR_0), op(SCALAR_1)); |             print("max({}, {})", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Mins: |         case AluScalarOpcode::Mins: | ||||||
|             print("min({}, {})", op(SCALAR_0), op(SCALAR_1)); |             print("min({}, {})", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Seqs: |         case AluScalarOpcode::Seqs: | ||||||
|             print("{} == 0.0", op(SCALAR_0)); |             print("{} == 0.0", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Sgts: |         case AluScalarOpcode::Sgts: | ||||||
|             print("{} > 0.0", op(SCALAR_0)); |             print("{} > 0.0", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Sges: |         case AluScalarOpcode::Sges: | ||||||
|             print("{} >= 0.0", op(SCALAR_0)); |             print("{} >= 0.0", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Snes: |         case AluScalarOpcode::Snes: | ||||||
|             print("{} != 0.0", op(SCALAR_0)); |             print("{} != 0.0", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Frcs: |         case AluScalarOpcode::Frcs: | ||||||
|             print("frac({})", op(SCALAR_0)); |             print("frac({})", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Truncs: |         case AluScalarOpcode::Truncs: | ||||||
|             print("trunc({})", op(SCALAR_0)); |             print("trunc({})", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Floors: |         case AluScalarOpcode::Floors: | ||||||
|             print("floor({})", op(SCALAR_0)); |             print("floor({})", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Exp: |         case AluScalarOpcode::Exp: | ||||||
|             print("exp2({})", op(SCALAR_0)); |             print("exp2({})", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Logc: |         case AluScalarOpcode::Logc: | ||||||
|         case AluScalarOpcode::Log: |         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; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Rcpc: |         case AluScalarOpcode::Rcpc: | ||||||
|         case AluScalarOpcode::Rcpf: |         case AluScalarOpcode::Rcpf: | ||||||
|         case AluScalarOpcode::Rcp: |         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; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Rsqc: |         case AluScalarOpcode::Rsqc: | ||||||
|         case AluScalarOpcode::Rsqf: |         case AluScalarOpcode::Rsqf: | ||||||
|         case AluScalarOpcode::Rsq: |         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; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Subs: |         case AluScalarOpcode::Subs: | ||||||
|             print("{} - {}", op(SCALAR_0), op(SCALAR_1)); |             print("{} - {}", op(SCALAR_0).expression, op(SCALAR_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::SubsPrev: |         case AluScalarOpcode::SubsPrev: | ||||||
|             print("{} - ps", op(SCALAR_0)); |             print("{} - ps", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::SetpEq: |         case AluScalarOpcode::SetpEq: | ||||||
|  | @ -1004,11 +1116,11 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::SetpInv: |         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; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::SetpPop: |         case AluScalarOpcode::SetpPop: | ||||||
|             print("p0 ? 0.0 : ({} - 1.0)", op(SCALAR_0)); |             print("p0 ? 0.0 : ({} - 1.0)", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::SetpClr: |         case AluScalarOpcode::SetpClr: | ||||||
|  | @ -1016,54 +1128,54 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::SetpRstr: |         case AluScalarOpcode::SetpRstr: | ||||||
|             print("p0 ? 0.0 : {}", op(SCALAR_0)); |             print("p0 ? 0.0 : {}", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::KillsEq: |         case AluScalarOpcode::KillsEq: | ||||||
|             print("{} == 0.0", op(SCALAR_0)); |             print("{} == 0.0", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::KillsGt: |         case AluScalarOpcode::KillsGt: | ||||||
|             print("{} > 0.0", op(SCALAR_0)); |             print("{} > 0.0", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::KillsGe: |         case AluScalarOpcode::KillsGe: | ||||||
|             print("{} >= 0.0", op(SCALAR_0)); |             print("{} >= 0.0", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::KillsNe: |         case AluScalarOpcode::KillsNe: | ||||||
|             print("{} != 0.0", op(SCALAR_0)); |             print("{} != 0.0", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::KillsOne: |         case AluScalarOpcode::KillsOne: | ||||||
|             print("{} == 1.0", op(SCALAR_0)); |             print("{} == 1.0", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Sqrt: |         case AluScalarOpcode::Sqrt: | ||||||
|             print("sqrt({})", op(SCALAR_0)); |             print("sqrt({})", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Mulsc0: |         case AluScalarOpcode::Mulsc0: | ||||||
|         case AluScalarOpcode::Mulsc1: |         case AluScalarOpcode::Mulsc1: | ||||||
|             print("{} * {}", op(SCALAR_CONSTANT_0), op(SCALAR_CONSTANT_1)); |             print("{} * {}", op(SCALAR_CONSTANT_0).expression, op(SCALAR_CONSTANT_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Addsc0: |         case AluScalarOpcode::Addsc0: | ||||||
|         case AluScalarOpcode::Addsc1: |         case AluScalarOpcode::Addsc1: | ||||||
|             print("{} + {}", op(SCALAR_CONSTANT_0), op(SCALAR_CONSTANT_1)); |             print("{} + {}", op(SCALAR_CONSTANT_0).expression, op(SCALAR_CONSTANT_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Subsc0: |         case AluScalarOpcode::Subsc0: | ||||||
|         case AluScalarOpcode::Subsc1: |         case AluScalarOpcode::Subsc1: | ||||||
|             print("{} - {}", op(SCALAR_CONSTANT_0), op(SCALAR_CONSTANT_1)); |             print("{} - {}", op(SCALAR_CONSTANT_0).expression, op(SCALAR_CONSTANT_1).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Sin: |         case AluScalarOpcode::Sin: | ||||||
|             print("sin({})", op(SCALAR_0)); |             print("sin({})", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case AluScalarOpcode::Cos: |         case AluScalarOpcode::Cos: | ||||||
|             print("cos({})", op(SCALAR_0)); |             print("cos({})", op(SCALAR_0).expression); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -1076,11 +1188,11 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) | ||||||
|         { |         { | ||||||
|         case AluScalarOpcode::MaxAs: |         case AluScalarOpcode::MaxAs: | ||||||
|             indent(); |             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;      |             break;      | ||||||
|         case AluScalarOpcode::MaxAsf: |         case AluScalarOpcode::MaxAsf: | ||||||
|             indent(); |             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; |             break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue