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
|
|
@ -10,8 +10,10 @@ endif()
|
|||
|
||||
set(SMOLV_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/smol-v/source")
|
||||
|
||||
add_executable(XenosRecomp
|
||||
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,18 +160,24 @@ 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)
|
||||
{
|
||||
dxil.insert(dxil.end(), reinterpret_cast<uint8_t *>(shader.dxil->GetBufferPointer()),
|
||||
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