mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-11-29 23:06:23 -05:00
Rewrited TEX/TEXS (TEX Scalar). (#1826)
* Rewrited TEX/TEXS (TEX Scalar). * Style fixes. * Styles issues.
This commit is contained in:
parent
da5659fb87
commit
ab2108fb2a
1 changed files with 180 additions and 262 deletions
|
@ -1515,6 +1515,161 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<size_t, std::string> ValidateAndGetCoordinateElement(
|
||||||
|
const Tegra::Shader::TextureType texture_type, const bool depth_compare,
|
||||||
|
const bool is_array, const bool lod_bias_enabled, size_t max_coords, size_t max_inputs) {
|
||||||
|
const size_t coord_count = TextureCoordinates(texture_type);
|
||||||
|
|
||||||
|
size_t total_coord_count = coord_count + (is_array ? 1 : 0) + (depth_compare ? 1 : 0);
|
||||||
|
const size_t total_reg_count = total_coord_count + (lod_bias_enabled ? 1 : 0);
|
||||||
|
if (total_coord_count > max_coords || total_reg_count > max_inputs) {
|
||||||
|
UNIMPLEMENTED_MSG("Unsupported Texture operation");
|
||||||
|
total_coord_count = std::min(total_coord_count, max_coords);
|
||||||
|
}
|
||||||
|
// 1D.DC opengl is using a vec3 but 2nd component is ignored later.
|
||||||
|
total_coord_count +=
|
||||||
|
(depth_compare && !is_array && texture_type == Tegra::Shader::TextureType::Texture1D)
|
||||||
|
? 1
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
constexpr std::array<const char*, 5> coord_container{
|
||||||
|
{"", "float coord = (", "vec2 coord = vec2(", "vec3 coord = vec3(",
|
||||||
|
"vec4 coord = vec4("}};
|
||||||
|
|
||||||
|
return std::pair<size_t, std::string>(coord_count, coord_container[total_coord_count]);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetTextureCode(const Tegra::Shader::Instruction& instr,
|
||||||
|
const Tegra::Shader::TextureType texture_type,
|
||||||
|
const Tegra::Shader::TextureProcessMode process_mode,
|
||||||
|
const bool depth_compare, const bool is_array,
|
||||||
|
const size_t bias_offset) {
|
||||||
|
|
||||||
|
if ((texture_type == Tegra::Shader::TextureType::Texture3D &&
|
||||||
|
(is_array || depth_compare)) ||
|
||||||
|
(texture_type == Tegra::Shader::TextureType::TextureCube && is_array &&
|
||||||
|
depth_compare)) {
|
||||||
|
UNIMPLEMENTED_MSG("This method is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string sampler =
|
||||||
|
GetSampler(instr.sampler, texture_type, is_array, depth_compare);
|
||||||
|
|
||||||
|
const bool lod_needed = process_mode == Tegra::Shader::TextureProcessMode::LZ ||
|
||||||
|
process_mode == Tegra::Shader::TextureProcessMode::LL ||
|
||||||
|
process_mode == Tegra::Shader::TextureProcessMode::LLA;
|
||||||
|
|
||||||
|
const bool gl_lod_supported = !(
|
||||||
|
(texture_type == Tegra::Shader::TextureType::Texture2D && is_array && depth_compare) ||
|
||||||
|
(texture_type == Tegra::Shader::TextureType::TextureCube && !is_array &&
|
||||||
|
depth_compare));
|
||||||
|
|
||||||
|
const std::string read_method = lod_needed && gl_lod_supported ? "textureLod(" : "texture(";
|
||||||
|
std::string texture = read_method + sampler + ", coord";
|
||||||
|
|
||||||
|
if (process_mode != Tegra::Shader::TextureProcessMode::None) {
|
||||||
|
if (process_mode == Tegra::Shader::TextureProcessMode::LZ) {
|
||||||
|
if (gl_lod_supported) {
|
||||||
|
texture += ", 0";
|
||||||
|
} else {
|
||||||
|
// Lod 0 is emulated by a big negative bias
|
||||||
|
// in scenarios that are not supported by glsl
|
||||||
|
texture += ", -1000";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If present, lod or bias are always stored in the register indexed by the
|
||||||
|
// gpr20
|
||||||
|
// field with an offset depending on the usage of the other registers
|
||||||
|
texture += ',' + regs.GetRegisterAsFloat(instr.gpr20.Value() + bias_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
texture += ")";
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::string, std::string> GetTEXCode(
|
||||||
|
const Instruction& instr, const Tegra::Shader::TextureType texture_type,
|
||||||
|
const Tegra::Shader::TextureProcessMode process_mode, const bool depth_compare,
|
||||||
|
const bool is_array) {
|
||||||
|
const bool lod_bias_enabled = (process_mode != Tegra::Shader::TextureProcessMode::None &&
|
||||||
|
process_mode != Tegra::Shader::TextureProcessMode::LZ);
|
||||||
|
|
||||||
|
const auto [coord_count, coord_dcl] = ValidateAndGetCoordinateElement(
|
||||||
|
texture_type, depth_compare, is_array, lod_bias_enabled, 4, 5);
|
||||||
|
// If enabled arrays index is always stored in the gpr8 field
|
||||||
|
const u64 array_register = instr.gpr8.Value();
|
||||||
|
// First coordinate index is the gpr8 or gpr8 + 1 when arrays are used
|
||||||
|
const u64 coord_register = array_register + (is_array ? 1 : 0);
|
||||||
|
|
||||||
|
std::string coord = coord_dcl;
|
||||||
|
for (size_t i = 0; i < coord_count;) {
|
||||||
|
coord += regs.GetRegisterAsFloat(coord_register + i);
|
||||||
|
++i;
|
||||||
|
if (i != coord_count) {
|
||||||
|
coord += ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 1D.DC in opengl the 2nd component is ignored.
|
||||||
|
if (depth_compare && !is_array && texture_type == Tegra::Shader::TextureType::Texture1D) {
|
||||||
|
coord += ",0.0";
|
||||||
|
}
|
||||||
|
if (depth_compare) {
|
||||||
|
// Depth is always stored in the register signaled by gpr20
|
||||||
|
// or in the next register if lod or bias are used
|
||||||
|
const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0);
|
||||||
|
coord += ',' + regs.GetRegisterAsFloat(depth_register);
|
||||||
|
}
|
||||||
|
if (is_array) {
|
||||||
|
coord += ',' + regs.GetRegisterAsInteger(array_register);
|
||||||
|
}
|
||||||
|
coord += ");";
|
||||||
|
return std::make_pair(
|
||||||
|
coord, GetTextureCode(instr, texture_type, process_mode, depth_compare, is_array, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<std::string, std::string> GetTEXSCode(
|
||||||
|
const Instruction& instr, const Tegra::Shader::TextureType texture_type,
|
||||||
|
const Tegra::Shader::TextureProcessMode process_mode, const bool depth_compare,
|
||||||
|
const bool is_array) {
|
||||||
|
const bool lod_bias_enabled = (process_mode != Tegra::Shader::TextureProcessMode::None &&
|
||||||
|
process_mode != Tegra::Shader::TextureProcessMode::LZ);
|
||||||
|
|
||||||
|
const auto [coord_count, coord_dcl] = ValidateAndGetCoordinateElement(
|
||||||
|
texture_type, depth_compare, is_array, lod_bias_enabled, 4, 4);
|
||||||
|
// If enabled arrays index is always stored in the gpr8 field
|
||||||
|
const u64 array_register = instr.gpr8.Value();
|
||||||
|
// First coordinate index is stored in gpr8 field or (gpr8 + 1) when arrays are used
|
||||||
|
const u64 coord_register = array_register + (is_array ? 1 : 0);
|
||||||
|
const u64 last_coord_register =
|
||||||
|
(is_array || !(lod_bias_enabled || depth_compare) || (coord_count > 2))
|
||||||
|
? static_cast<u64>(instr.gpr20.Value())
|
||||||
|
: coord_register + 1;
|
||||||
|
|
||||||
|
std::string coord = coord_dcl;
|
||||||
|
for (size_t i = 0; i < coord_count; ++i) {
|
||||||
|
const bool last = (i == (coord_count - 1)) && (coord_count > 1);
|
||||||
|
coord += regs.GetRegisterAsFloat(last ? last_coord_register : coord_register + i);
|
||||||
|
if (!last) {
|
||||||
|
coord += ',';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth_compare) {
|
||||||
|
// Depth is always stored in the register signaled by gpr20
|
||||||
|
// or in the next register if lod or bias are used
|
||||||
|
const u64 depth_register = instr.gpr20.Value() + (lod_bias_enabled ? 1 : 0);
|
||||||
|
coord += ',' + regs.GetRegisterAsFloat(depth_register);
|
||||||
|
}
|
||||||
|
if (is_array) {
|
||||||
|
coord += ',' + regs.GetRegisterAsInteger(array_register);
|
||||||
|
}
|
||||||
|
coord += ");";
|
||||||
|
|
||||||
|
return std::make_pair(coord,
|
||||||
|
GetTextureCode(instr, texture_type, process_mode, depth_compare,
|
||||||
|
is_array, (coord_count > 2 ? 1 : 0)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiles a single instruction from Tegra to GLSL.
|
* Compiles a single instruction from Tegra to GLSL.
|
||||||
* @param offset the offset of the Tegra shader instruction.
|
* @param offset the offset of the Tegra shader instruction.
|
||||||
|
@ -2574,168 +2729,32 @@ private:
|
||||||
case OpCode::Id::TEX: {
|
case OpCode::Id::TEX: {
|
||||||
Tegra::Shader::TextureType texture_type{instr.tex.texture_type};
|
Tegra::Shader::TextureType texture_type{instr.tex.texture_type};
|
||||||
const bool is_array = instr.tex.array != 0;
|
const bool is_array = instr.tex.array != 0;
|
||||||
|
const bool depth_compare =
|
||||||
|
instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
|
||||||
|
const auto process_mode = instr.tex.GetTextureProcessMode();
|
||||||
UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
|
UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
|
||||||
"NODEP is not implemented");
|
"NODEP is not implemented");
|
||||||
UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
|
UNIMPLEMENTED_IF_MSG(instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::AOFFI),
|
||||||
"AOFFI is not implemented");
|
"AOFFI is not implemented");
|
||||||
|
|
||||||
const bool depth_compare =
|
const auto [coord, texture] =
|
||||||
instr.tex.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
|
GetTEXCode(instr, texture_type, process_mode, depth_compare, is_array);
|
||||||
u32 num_coordinates = TextureCoordinates(texture_type);
|
|
||||||
u32 start_index = 0;
|
|
||||||
std::string array_elem;
|
|
||||||
if (is_array) {
|
|
||||||
array_elem = regs.GetRegisterAsInteger(instr.gpr8);
|
|
||||||
start_index = 1;
|
|
||||||
}
|
|
||||||
const auto process_mode = instr.tex.GetTextureProcessMode();
|
|
||||||
u32 start_index_b = 0;
|
|
||||||
std::string lod_value;
|
|
||||||
if (process_mode != Tegra::Shader::TextureProcessMode::LZ &&
|
|
||||||
process_mode != Tegra::Shader::TextureProcessMode::None) {
|
|
||||||
start_index_b = 1;
|
|
||||||
lod_value = regs.GetRegisterAsFloat(instr.gpr20);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string depth_value;
|
|
||||||
if (depth_compare) {
|
|
||||||
depth_value = regs.GetRegisterAsFloat(instr.gpr20.Value() + start_index_b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool depth_compare_extra = false;
|
|
||||||
|
|
||||||
const auto scope = shader.Scope();
|
const auto scope = shader.Scope();
|
||||||
|
shader.AddLine(coord);
|
||||||
switch (num_coordinates) {
|
|
||||||
case 1: {
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index);
|
|
||||||
if (is_array) {
|
|
||||||
if (depth_compare) {
|
|
||||||
shader.AddLine("vec3 coords = vec3(" + x + ", " + depth_value + ", " +
|
|
||||||
array_elem + ");");
|
|
||||||
} else {
|
|
||||||
shader.AddLine("vec2 coords = vec2(" + x + ", " + array_elem + ");");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (depth_compare) {
|
|
||||||
shader.AddLine("vec2 coords = vec2(" + x + ", " + depth_value + ");");
|
|
||||||
} else {
|
|
||||||
shader.AddLine("float coords = " + x + ';');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index);
|
|
||||||
const std::string y =
|
|
||||||
regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index + 1);
|
|
||||||
if (is_array) {
|
|
||||||
if (depth_compare) {
|
|
||||||
shader.AddLine("vec4 coords = vec4(" + x + ", " + y + ", " +
|
|
||||||
depth_value + ", " + array_elem + ");");
|
|
||||||
} else {
|
|
||||||
shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " +
|
|
||||||
array_elem + ");");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (depth_compare) {
|
|
||||||
shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " +
|
|
||||||
depth_value + ");");
|
|
||||||
} else {
|
|
||||||
shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index);
|
|
||||||
const std::string y =
|
|
||||||
regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index + 1);
|
|
||||||
const std::string z =
|
|
||||||
regs.GetRegisterAsFloat(instr.gpr8.Value() + start_index + 2);
|
|
||||||
if (is_array) {
|
|
||||||
depth_compare_extra = depth_compare;
|
|
||||||
shader.AddLine("vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " +
|
|
||||||
array_elem + ");");
|
|
||||||
} else {
|
|
||||||
if (depth_compare) {
|
|
||||||
shader.AddLine("vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " +
|
|
||||||
depth_value + ");");
|
|
||||||
} else {
|
|
||||||
shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + z + ");");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
UNIMPLEMENTED_MSG("Unhandled coordinates number {}",
|
|
||||||
static_cast<u32>(num_coordinates));
|
|
||||||
|
|
||||||
// Fallback to interpreting as a 2D texture for now
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
||||||
const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
||||||
shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
|
|
||||||
texture_type = Tegra::Shader::TextureType::Texture2D;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string sampler =
|
|
||||||
GetSampler(instr.sampler, texture_type, is_array, depth_compare);
|
|
||||||
// Add an extra scope and declare the texture coords inside to prevent
|
|
||||||
// overwriting them in case they are used as outputs of the texs instruction.
|
|
||||||
|
|
||||||
const std::string texture = [&]() {
|
|
||||||
switch (instr.tex.GetTextureProcessMode()) {
|
|
||||||
case Tegra::Shader::TextureProcessMode::None:
|
|
||||||
if (depth_compare_extra) {
|
|
||||||
return "texture(" + sampler + ", coords, " + depth_value + ')';
|
|
||||||
}
|
|
||||||
return "texture(" + sampler + ", coords)";
|
|
||||||
case Tegra::Shader::TextureProcessMode::LZ:
|
|
||||||
if (depth_compare_extra) {
|
|
||||||
return "texture(" + sampler + ", coords, " + depth_value + ')';
|
|
||||||
}
|
|
||||||
return "textureLod(" + sampler + ", coords, 0.0)";
|
|
||||||
case Tegra::Shader::TextureProcessMode::LB:
|
|
||||||
case Tegra::Shader::TextureProcessMode::LBA:
|
|
||||||
// TODO: Figure if A suffix changes the equation at all.
|
|
||||||
if (depth_compare_extra) {
|
|
||||||
LOG_WARNING(
|
|
||||||
HW_GPU,
|
|
||||||
"OpenGL Limitation: can't set bias value along depth compare");
|
|
||||||
return "texture(" + sampler + ", coords, " + depth_value + ')';
|
|
||||||
}
|
|
||||||
return "texture(" + sampler + ", coords, " + lod_value + ')';
|
|
||||||
case Tegra::Shader::TextureProcessMode::LL:
|
|
||||||
case Tegra::Shader::TextureProcessMode::LLA:
|
|
||||||
// TODO: Figure if A suffix changes the equation at all.
|
|
||||||
if (depth_compare_extra) {
|
|
||||||
LOG_WARNING(
|
|
||||||
HW_GPU,
|
|
||||||
"OpenGL Limitation: can't set lod value along depth compare");
|
|
||||||
return "texture(" + sampler + ", coords, " + depth_value + ')';
|
|
||||||
}
|
|
||||||
return "textureLod(" + sampler + ", coords, " + lod_value + ')';
|
|
||||||
default:
|
|
||||||
UNIMPLEMENTED_MSG("Unhandled texture process mode {}",
|
|
||||||
static_cast<u32>(instr.tex.GetTextureProcessMode()));
|
|
||||||
if (depth_compare_extra) {
|
|
||||||
return "texture(" + sampler + ", coords, " + depth_value + ')';
|
|
||||||
}
|
|
||||||
return "texture(" + sampler + ", coords)";
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
|
|
||||||
if (depth_compare) {
|
if (depth_compare) {
|
||||||
regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false);
|
regs.SetRegisterToFloat(instr.gpr0, 0, texture, 1, 1, false);
|
||||||
} else {
|
} else {
|
||||||
|
shader.AddLine("vec4 texture_tmp = " + texture + ';');
|
||||||
std::size_t dest_elem{};
|
std::size_t dest_elem{};
|
||||||
for (std::size_t elem = 0; elem < 4; ++elem) {
|
for (std::size_t elem = 0; elem < 4; ++elem) {
|
||||||
if (!instr.tex.IsComponentEnabled(elem)) {
|
if (!instr.tex.IsComponentEnabled(elem)) {
|
||||||
// Skip disabled components
|
// Skip disabled components
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
regs.SetRegisterToFloat(instr.gpr0, elem, texture, 1, 4, false, dest_elem);
|
regs.SetRegisterToFloat(instr.gpr0, elem, "texture_tmp", 1, 4, false,
|
||||||
|
dest_elem);
|
||||||
++dest_elem;
|
++dest_elem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2743,129 +2762,28 @@ private:
|
||||||
}
|
}
|
||||||
case OpCode::Id::TEXS: {
|
case OpCode::Id::TEXS: {
|
||||||
Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
|
Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
|
||||||
bool is_array{instr.texs.IsArrayTexture()};
|
const bool is_array{instr.texs.IsArrayTexture()};
|
||||||
|
const bool depth_compare =
|
||||||
|
instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
|
||||||
|
const auto process_mode = instr.texs.GetTextureProcessMode();
|
||||||
UNIMPLEMENTED_IF_MSG(instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
|
UNIMPLEMENTED_IF_MSG(instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::NODEP),
|
||||||
"NODEP is not implemented");
|
"NODEP is not implemented");
|
||||||
|
|
||||||
const auto scope = shader.Scope();
|
const auto scope = shader.Scope();
|
||||||
|
|
||||||
const bool depth_compare =
|
const auto [coord, texture] =
|
||||||
instr.texs.UsesMiscMode(Tegra::Shader::TextureMiscMode::DC);
|
GetTEXSCode(instr, texture_type, process_mode, depth_compare, is_array);
|
||||||
u32 num_coordinates = TextureCoordinates(texture_type);
|
|
||||||
const auto process_mode = instr.texs.GetTextureProcessMode();
|
shader.AddLine(coord);
|
||||||
u32 lod_offset = 0;
|
|
||||||
if (process_mode == Tegra::Shader::TextureProcessMode::LL) {
|
if (!depth_compare) {
|
||||||
if (num_coordinates > 2) {
|
shader.AddLine("vec4 texture_tmp = " + texture + ';');
|
||||||
shader.AddLine("float lod_value = " +
|
|
||||||
regs.GetRegisterAsFloat(instr.gpr20.Value() + 1) + ';');
|
|
||||||
lod_offset = 2;
|
|
||||||
} else {
|
} else {
|
||||||
shader.AddLine("float lod_value = " + regs.GetRegisterAsFloat(instr.gpr20) +
|
shader.AddLine("vec4 texture_tmp = vec4(" + texture + ");");
|
||||||
';');
|
|
||||||
lod_offset = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (num_coordinates) {
|
WriteTexsInstruction(instr, "texture_tmp");
|
||||||
case 1: {
|
|
||||||
shader.AddLine("float coords = " + regs.GetRegisterAsFloat(instr.gpr8) + ';');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2: {
|
|
||||||
if (is_array) {
|
|
||||||
if (depth_compare) {
|
|
||||||
const std::string index = regs.GetRegisterAsInteger(instr.gpr8);
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
||||||
const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
|
|
||||||
const std::string z = regs.GetRegisterAsFloat(instr.gpr20.Value() + 1);
|
|
||||||
shader.AddLine("vec4 coords = vec4(" + x + ", " + y + ", " + z + ", " +
|
|
||||||
index + ");");
|
|
||||||
} else {
|
|
||||||
const std::string index = regs.GetRegisterAsInteger(instr.gpr8);
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
||||||
const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
|
|
||||||
shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + index +
|
|
||||||
");");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (lod_offset != 0) {
|
|
||||||
if (depth_compare) {
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
||||||
const std::string y =
|
|
||||||
regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
||||||
const std::string z =
|
|
||||||
regs.GetRegisterAsFloat(instr.gpr20.Value() + lod_offset);
|
|
||||||
shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + z +
|
|
||||||
");");
|
|
||||||
} else {
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
||||||
const std::string y =
|
|
||||||
regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
||||||
shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (depth_compare) {
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
||||||
const std::string y =
|
|
||||||
regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
||||||
const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
|
|
||||||
shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + z +
|
|
||||||
");");
|
|
||||||
} else {
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
||||||
const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
|
|
||||||
shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: {
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
||||||
const std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
||||||
const std::string z = regs.GetRegisterAsFloat(instr.gpr20);
|
|
||||||
shader.AddLine("vec3 coords = vec3(" + x + ", " + y + ", " + z + ");");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
UNIMPLEMENTED_MSG("Unhandled coordinates number {}",
|
|
||||||
static_cast<u32>(num_coordinates));
|
|
||||||
|
|
||||||
// Fallback to interpreting as a 2D texture for now
|
|
||||||
const std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
||||||
const std::string y = regs.GetRegisterAsFloat(instr.gpr20);
|
|
||||||
shader.AddLine("vec2 coords = vec2(" + x + ", " + y + ");");
|
|
||||||
texture_type = Tegra::Shader::TextureType::Texture2D;
|
|
||||||
is_array = false;
|
|
||||||
}
|
|
||||||
const std::string sampler =
|
|
||||||
GetSampler(instr.sampler, texture_type, is_array, depth_compare);
|
|
||||||
|
|
||||||
std::string texture = [&]() {
|
|
||||||
switch (process_mode) {
|
|
||||||
case Tegra::Shader::TextureProcessMode::None:
|
|
||||||
return "texture(" + sampler + ", coords)";
|
|
||||||
case Tegra::Shader::TextureProcessMode::LZ:
|
|
||||||
if (depth_compare && is_array) {
|
|
||||||
return "texture(" + sampler + ", coords)";
|
|
||||||
} else {
|
|
||||||
return "textureLod(" + sampler + ", coords, 0.0)";
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Tegra::Shader::TextureProcessMode::LL:
|
|
||||||
return "textureLod(" + sampler + ", coords, lod_value)";
|
|
||||||
default:
|
|
||||||
UNIMPLEMENTED_MSG("Unhandled texture process mode {}",
|
|
||||||
static_cast<u32>(instr.texs.GetTextureProcessMode()));
|
|
||||||
return "texture(" + sampler + ", coords)";
|
|
||||||
}
|
|
||||||
}();
|
|
||||||
if (depth_compare) {
|
|
||||||
texture = "vec4(" + texture + ')';
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteTexsInstruction(instr, texture);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpCode::Id::TLDS: {
|
case OpCode::Id::TLDS: {
|
||||||
|
|
Loading…
Reference in a new issue