summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/engines/shader_bytecode.h19
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp36
2 files changed, 43 insertions, 12 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index eff0c35a1..51cf4af9f 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -16,10 +16,6 @@ struct Register {
constexpr Register(u64 value) : value(value) {}
- constexpr u64 GetIndex() const {
- return value;
- }
-
constexpr operator u64() const {
return value;
}
@@ -71,6 +67,19 @@ union Attribute {
u64 value;
};
+union Sampler {
+ Sampler() = default;
+
+ constexpr Sampler(u64 value) : value(value) {}
+
+ enum class Index : u64 {
+ Sampler_0 = 8,
+ };
+
+ BitField<36, 13, Index> index;
+ u64 value;
+};
+
union Uniform {
BitField<20, 14, u64> offset;
BitField<34, 5, u64> index;
@@ -295,7 +304,6 @@ union Instruction {
BitField<20, 8, Register> gpr20;
BitField<20, 7, SubOp> sub_op;
BitField<28, 8, Register> gpr28;
- BitField<36, 13, u64> imm36;
BitField<39, 8, Register> gpr39;
union {
@@ -316,6 +324,7 @@ union Instruction {
Attribute attribute;
Uniform uniform;
+ Sampler sampler;
u64 hex;
};
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index ba3aa7dd1..a8f1ac5b5 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -17,6 +17,7 @@ using Tegra::Shader::Attribute;
using Tegra::Shader::Instruction;
using Tegra::Shader::OpCode;
using Tegra::Shader::Register;
+using Tegra::Shader::Sampler;
using Tegra::Shader::SubOp;
using Tegra::Shader::Uniform;
@@ -186,13 +187,13 @@ private:
}
/// Generates code representing a temporary (GPR) register.
- std::string GetRegister(const Register& reg) {
- if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg.GetIndex() < 4) {
+ std::string GetRegister(const Register& reg, unsigned elem = 0) {
+ if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) {
// GPRs 0-3 are output color for the fragment shader
- return std::string{"color."} + "rgba"[reg.GetIndex()];
+ return std::string{"color."} + "rgba"[reg + elem];
}
- return *declr_register.insert("register_" + std::to_string(reg)).first;
+ return *declr_register.insert("register_" + std::to_string(reg + elem)).first;
}
/// Generates code representing a uniform (C buffer) register.
@@ -201,6 +202,15 @@ private:
return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']';
}
+ /// Generates code representing a texture sampler.
+ std::string GetSampler(const Sampler& sampler) const {
+ // TODO(Subv): Support more than just texture sampler 0
+ ASSERT_MSG(sampler.index == Sampler::Index::Sampler_0, "unsupported");
+ const unsigned index{static_cast<unsigned>(sampler.index.Value()) -
+ static_cast<unsigned>(Sampler::Index::Sampler_0)};
+ return "tex[" + std::to_string(index) + "]";
+ }
+
/**
* Adds code that calls a subroutine.
* @param subroutine the subroutine to call.
@@ -245,7 +255,7 @@ private:
switch (OpCode::GetInfo(instr.opcode).type) {
case OpCode::Type::Arithmetic: {
- ASSERT(!instr.alu.abs_d);
+ ASSERT_MSG(!instr.alu.abs_d, "unimplemented");
std::string dest = GetRegister(instr.gpr0);
std::string op_a = instr.alu.negate_a ? "-" : "";
@@ -330,15 +340,27 @@ private:
switch (instr.opcode.EffectiveOpCode()) {
case OpCode::Id::LD_A: {
- ASSERT(instr.attribute.fmt20.size == 0);
+ ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4);
break;
}
case OpCode::Id::ST_A: {
- ASSERT(instr.attribute.fmt20.size == 0);
+ ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1);
break;
}
+ case OpCode::Id::TEXS: {
+ ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested");
+ const std::string op_a = GetRegister(instr.gpr8);
+ const std::string op_b = GetRegister(instr.gpr20);
+ const std::string sampler = GetSampler(instr.sampler);
+ const std::string coord = "vec2(" + op_a + ", " + op_b + ")";
+ const std::string texture = "texture(" + sampler + ", " + coord + ")";
+ for (unsigned elem = 0; elem < instr.attribute.fmt20.size; ++elem) {
+ SetDest(elem, GetRegister(instr.gpr0, elem), texture, 1, 4);
+ }
+ break;
+ }
default: {
LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: 0x%02x (%s): 0x%08x",
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),