|
|
|
@ -443,13 +443,12 @@ public:
|
|
|
|
|
}
|
|
|
|
|
declarations.AddNewLine();
|
|
|
|
|
|
|
|
|
|
// Append the sampler2D array for the used textures.
|
|
|
|
|
const size_t num_samplers = used_samplers.size();
|
|
|
|
|
if (num_samplers > 0) {
|
|
|
|
|
declarations.AddLine("uniform sampler2D " + SamplerEntry::GetArrayName(stage) + '[' +
|
|
|
|
|
std::to_string(num_samplers) + "];");
|
|
|
|
|
declarations.AddNewLine();
|
|
|
|
|
const auto& samplers = GetSamplers();
|
|
|
|
|
for (const auto& sampler : samplers) {
|
|
|
|
|
declarations.AddLine("uniform " + sampler.GetTypeString() + ' ' + sampler.GetName() +
|
|
|
|
|
';');
|
|
|
|
|
}
|
|
|
|
|
declarations.AddNewLine();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a list of constant buffer declarations
|
|
|
|
@ -461,13 +460,14 @@ public:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns a list of samplers used in the shader
|
|
|
|
|
std::vector<SamplerEntry> GetSamplers() const {
|
|
|
|
|
const std::vector<SamplerEntry>& GetSamplers() const {
|
|
|
|
|
return used_samplers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Returns the GLSL sampler used for the input shader sampler, and creates a new one if
|
|
|
|
|
/// necessary.
|
|
|
|
|
std::string AccessSampler(const Sampler& sampler) {
|
|
|
|
|
std::string AccessSampler(const Sampler& sampler, Tegra::Shader::TextureType type,
|
|
|
|
|
bool is_array) {
|
|
|
|
|
size_t offset = static_cast<size_t>(sampler.index.Value());
|
|
|
|
|
|
|
|
|
|
// If this sampler has already been used, return the existing mapping.
|
|
|
|
@ -476,12 +476,13 @@ public:
|
|
|
|
|
[&](const SamplerEntry& entry) { return entry.GetOffset() == offset; });
|
|
|
|
|
|
|
|
|
|
if (itr != used_samplers.end()) {
|
|
|
|
|
ASSERT(itr->GetType() == type && itr->IsArray() == is_array);
|
|
|
|
|
return itr->GetName();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Otherwise create a new mapping for this sampler
|
|
|
|
|
size_t next_index = used_samplers.size();
|
|
|
|
|
SamplerEntry entry{stage, offset, next_index};
|
|
|
|
|
SamplerEntry entry{stage, offset, next_index, type, is_array};
|
|
|
|
|
used_samplers.emplace_back(entry);
|
|
|
|
|
return entry.GetName();
|
|
|
|
|
}
|
|
|
|
@ -722,8 +723,8 @@ private:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Generates code representing a texture sampler.
|
|
|
|
|
std::string GetSampler(const Sampler& sampler) {
|
|
|
|
|
return regs.AccessSampler(sampler);
|
|
|
|
|
std::string GetSampler(const Sampler& sampler, Tegra::Shader::TextureType type, bool is_array) {
|
|
|
|
|
return regs.AccessSampler(sampler, type, is_array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -1753,10 +1754,35 @@ private:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OpCode::Id::TEX: {
|
|
|
|
|
const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
|
|
|
|
|
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
|
|
|
const std::string sampler = GetSampler(instr.sampler);
|
|
|
|
|
const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
|
|
|
|
|
ASSERT_MSG(instr.tex.array == 0, "TEX arrays unimplemented");
|
|
|
|
|
Tegra::Shader::TextureType texture_type{instr.tex.texture_type};
|
|
|
|
|
std::string coord;
|
|
|
|
|
|
|
|
|
|
switch (texture_type) {
|
|
|
|
|
case Tegra::Shader::TextureType::Texture1D: {
|
|
|
|
|
std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
|
|
|
coord = "float coords = " + x + ';';
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case Tegra::Shader::TextureType::Texture2D: {
|
|
|
|
|
std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
|
|
|
std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
|
|
|
coord = "vec2 coords = vec2(" + x + ", " + y + ");";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
|
|
|
|
|
static_cast<u32>(texture_type));
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
|
|
|
|
|
// Fallback to interpreting as a 2D texture for now
|
|
|
|
|
std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
|
|
|
std::string y = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
|
|
|
coord = "vec2 coords = vec2(" + x + ", " + y + ");";
|
|
|
|
|
texture_type = Tegra::Shader::TextureType::Texture2D;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string sampler = GetSampler(instr.sampler, texture_type, false);
|
|
|
|
|
// 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.
|
|
|
|
|
shader.AddLine("{");
|
|
|
|
@ -1778,20 +1804,65 @@ private:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OpCode::Id::TEXS: {
|
|
|
|
|
const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
|
|
|
|
|
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
|
|
|
|
|
const std::string sampler = GetSampler(instr.sampler);
|
|
|
|
|
const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
|
|
|
|
|
std::string coord;
|
|
|
|
|
Tegra::Shader::TextureType texture_type{instr.texs.GetTextureType()};
|
|
|
|
|
bool is_array{instr.texs.IsArrayTexture()};
|
|
|
|
|
|
|
|
|
|
switch (texture_type) {
|
|
|
|
|
case Tegra::Shader::TextureType::Texture2D: {
|
|
|
|
|
if (is_array) {
|
|
|
|
|
std::string index = regs.GetRegisterAsInteger(instr.gpr8);
|
|
|
|
|
std::string x = regs.GetRegisterAsFloat(instr.gpr8.Value() + 1);
|
|
|
|
|
std::string y = regs.GetRegisterAsFloat(instr.gpr20);
|
|
|
|
|
coord = "vec3 coords = vec3(" + x + ", " + y + ", " + index + ");";
|
|
|
|
|
} else {
|
|
|
|
|
std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
|
|
|
std::string y = regs.GetRegisterAsFloat(instr.gpr20);
|
|
|
|
|
coord = "vec2 coords = vec2(" + x + ", " + y + ");";
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
|
|
|
|
|
static_cast<u32>(texture_type));
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
|
|
|
|
|
// Fallback to interpreting as a 2D texture for now
|
|
|
|
|
std::string x = regs.GetRegisterAsFloat(instr.gpr8);
|
|
|
|
|
std::string y = regs.GetRegisterAsFloat(instr.gpr20);
|
|
|
|
|
coord = "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);
|
|
|
|
|
const std::string texture = "texture(" + sampler + ", coords)";
|
|
|
|
|
WriteTexsInstruction(instr, coord, texture);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case OpCode::Id::TLDS: {
|
|
|
|
|
const std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
|
|
|
|
|
const std::string op_b = regs.GetRegisterAsInteger(instr.gpr20);
|
|
|
|
|
const std::string sampler = GetSampler(instr.sampler);
|
|
|
|
|
const std::string coord = "ivec2 coords = ivec2(" + op_a + ", " + op_b + ");";
|
|
|
|
|
ASSERT(instr.tlds.GetTextureType() == Tegra::Shader::TextureType::Texture2D);
|
|
|
|
|
ASSERT(instr.tlds.IsArrayTexture() == false);
|
|
|
|
|
std::string coord;
|
|
|
|
|
|
|
|
|
|
switch (instr.tlds.GetTextureType()) {
|
|
|
|
|
case Tegra::Shader::TextureType::Texture2D: {
|
|
|
|
|
if (instr.tlds.IsArrayTexture()) {
|
|
|
|
|
LOG_CRITICAL(HW_GPU, "Unhandled 2d array texture");
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
} else {
|
|
|
|
|
std::string x = regs.GetRegisterAsInteger(instr.gpr8);
|
|
|
|
|
std::string y = regs.GetRegisterAsInteger(instr.gpr20);
|
|
|
|
|
coord = "ivec2 coords = ivec2(" + x + ", " + y + ");";
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
LOG_CRITICAL(HW_GPU, "Unhandled texture type {}",
|
|
|
|
|
static_cast<u32>(instr.tlds.GetTextureType()));
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
}
|
|
|
|
|
const std::string sampler = GetSampler(instr.sampler, instr.tlds.GetTextureType(),
|
|
|
|
|
instr.tlds.IsArrayTexture());
|
|
|
|
|
const std::string texture = "texelFetch(" + sampler + ", coords, 0)";
|
|
|
|
|
WriteTexsInstruction(instr, coord, texture);
|
|
|
|
|
break;
|
|
|
|
@ -1799,7 +1870,7 @@ private:
|
|
|
|
|
case OpCode::Id::TLD4: {
|
|
|
|
|
ASSERT(instr.tld4.texture_type == Tegra::Shader::TextureType::Texture2D);
|
|
|
|
|
ASSERT(instr.tld4.array == 0);
|
|
|
|
|
std::string coord{};
|
|
|
|
|
std::string coord;
|
|
|
|
|
|
|
|
|
|
switch (instr.tld4.texture_type) {
|
|
|
|
|
case Tegra::Shader::TextureType::Texture2D: {
|
|
|
|
@ -1814,7 +1885,8 @@ private:
|
|
|
|
|
UNREACHABLE();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string sampler = GetSampler(instr.sampler);
|
|
|
|
|
const std::string sampler =
|
|
|
|
|
GetSampler(instr.sampler, instr.tld4.texture_type, false);
|
|
|
|
|
// 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.
|
|
|
|
|
shader.AddLine("{");
|
|
|
|
@ -1840,7 +1912,8 @@ private:
|
|
|
|
|
const std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
|
|
|
|
|
const std::string op_b = regs.GetRegisterAsFloat(instr.gpr20);
|
|
|
|
|
// TODO(Subv): Figure out how the sampler type is encoded in the TLD4S instruction.
|
|
|
|
|
const std::string sampler = GetSampler(instr.sampler);
|
|
|
|
|
const std::string sampler =
|
|
|
|
|
GetSampler(instr.sampler, Tegra::Shader::TextureType::Texture2D, false);
|
|
|
|
|
const std::string coord = "vec2 coords = vec2(" + op_a + ", " + op_b + ");";
|
|
|
|
|
const std::string texture = "textureGather(" + sampler + ", coords, " +
|
|
|
|
|
std::to_string(instr.tld4s.component) + ')';
|
|
|
|
|