summaryrefslogtreecommitdiffstats
path: root/src/video_core/engines
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/engines')
-rw-r--r--src/video_core/engines/maxwell_3d.cpp32
-rw-r--r--src/video_core/engines/maxwell_3d.h10
-rw-r--r--src/video_core/engines/shader_bytecode.h26
-rw-r--r--src/video_core/engines/shader_header.h2
4 files changed, 64 insertions, 6 deletions
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index b19b3a75a..a388b3944 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -37,6 +37,7 @@ void Maxwell3D::InitializeRegisterDefaults() {
regs.viewports[viewport].depth_range_near = 0.0f;
regs.viewports[viewport].depth_range_far = 1.0f;
}
+
// Doom and Bomberman seems to use the uninitialized registers and just enable blend
// so initialize blend registers with sane values
regs.blend.equation_rgb = Regs::Blend::Equation::Add;
@@ -66,6 +67,7 @@ void Maxwell3D::InitializeRegisterDefaults() {
regs.stencil_back_func_func = Regs::ComparisonOp::Always;
regs.stencil_back_func_mask = 0xFFFFFFFF;
regs.stencil_back_mask = 0xFFFFFFFF;
+
// TODO(Rodrigo): Most games do not set a point size. I think this is a case of a
// register carrying a default value. Assume it's OpenGL's default (1).
regs.point_size = 1.0f;
@@ -78,6 +80,9 @@ void Maxwell3D::InitializeRegisterDefaults() {
regs.color_mask[color_mask].B.Assign(1);
regs.color_mask[color_mask].A.Assign(1);
}
+
+ // Commercial games seem to assume this value is enabled and nouveau sets this value manually.
+ regs.rt_separate_frag_data = 1;
}
void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) {
@@ -135,6 +140,33 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
if (regs.reg_array[method_call.method] != method_call.argument) {
regs.reg_array[method_call.method] = method_call.argument;
+ // Color buffers
+ constexpr u32 first_rt_reg = MAXWELL3D_REG_INDEX(rt);
+ constexpr u32 registers_per_rt = sizeof(regs.rt[0]) / sizeof(u32);
+ if (method_call.method >= first_rt_reg &&
+ method_call.method < first_rt_reg + registers_per_rt * Regs::NumRenderTargets) {
+ const std::size_t rt_index = (method_call.method - first_rt_reg) / registers_per_rt;
+ dirty_flags.color_buffer |= 1u << static_cast<u32>(rt_index);
+ }
+
+ // Zeta buffer
+ constexpr u32 registers_in_zeta = sizeof(regs.zeta) / sizeof(u32);
+ if (method_call.method == MAXWELL3D_REG_INDEX(zeta_enable) ||
+ method_call.method == MAXWELL3D_REG_INDEX(zeta_width) ||
+ method_call.method == MAXWELL3D_REG_INDEX(zeta_height) ||
+ (method_call.method >= MAXWELL3D_REG_INDEX(zeta) &&
+ method_call.method < MAXWELL3D_REG_INDEX(zeta) + registers_in_zeta)) {
+ dirty_flags.zeta_buffer = true;
+ }
+
+ // Shader
+ constexpr u32 shader_registers_count =
+ sizeof(regs.shader_config[0]) * Regs::MaxShaderProgram / sizeof(u32);
+ if (method_call.method >= MAXWELL3D_REG_INDEX(shader_config[0]) &&
+ method_call.method < MAXWELL3D_REG_INDEX(shader_config[0]) + shader_registers_count) {
+ dirty_flags.shaders = true;
+ }
+
// Vertex format
if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) &&
method_call.method <
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index 25bb7604a..1f76aa670 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -164,6 +164,7 @@ public:
return 3;
default:
UNREACHABLE();
+ return 1;
}
}
@@ -871,6 +872,7 @@ public:
return 4;
}
UNREACHABLE();
+ return 1;
}
GPUVAddr StartAddress() const {
@@ -1087,10 +1089,18 @@ public:
MemoryManager& memory_manager;
struct DirtyFlags {
+ u8 color_buffer = 0xFF;
+ bool zeta_buffer = true;
+
+ bool shaders = true;
+
bool vertex_attrib_format = true;
u32 vertex_array = 0xFFFFFFFF;
void OnMemoryWrite() {
+ color_buffer = 0xFF;
+ zeta_buffer = true;
+ shaders = true;
vertex_array = 0xFFFFFFFF;
}
};
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 5ea094e64..9989825f8 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -208,6 +208,8 @@ enum class UniformType : u64 {
SignedShort = 3,
Single = 4,
Double = 5,
+ Quad = 6,
+ UnsignedQuad = 7,
};
enum class StoreType : u64 {
@@ -397,6 +399,10 @@ struct IpaMode {
bool operator!=(const IpaMode& a) const {
return !operator==(a);
}
+ bool operator<(const IpaMode& a) const {
+ return std::tie(interpolation_mode, sampling_mode) <
+ std::tie(a.interpolation_mode, a.sampling_mode);
+ }
};
enum class SystemVariable : u64 {
@@ -575,7 +581,7 @@ union Instruction {
union {
BitField<39, 2, u64> tab5cb8_2;
- BitField<41, 3, u64> tab5c68_1;
+ BitField<41, 3, u64> postfactor;
BitField<44, 2, u64> tab5c68_0;
BitField<48, 1, u64> negate_b;
} fmul;
@@ -609,7 +615,7 @@ union Instruction {
BitField<31, 1, u64> negate_b;
BitField<30, 1, u64> abs_b;
- BitField<47, 2, HalfType> type_b;
+ BitField<28, 2, HalfType> type_b;
BitField<35, 2, HalfType> type_c;
} alu_half;
@@ -644,6 +650,7 @@ union Instruction {
BitField<37, 2, HalfPrecision> precision;
BitField<32, 1, u64> saturate;
+ BitField<31, 1, u64> negate_b;
BitField<30, 1, u64> negate_c;
BitField<35, 2, HalfType> type_c;
} rr;
@@ -780,6 +787,12 @@ union Instruction {
} st_l;
union {
+ BitField<48, 3, UniformType> type;
+ BitField<46, 2, u64> cache_mode;
+ BitField<20, 24, s64> immediate_offset;
+ } ldg;
+
+ union {
BitField<0, 3, u64> pred0;
BitField<3, 3, u64> pred3;
BitField<7, 1, u64> abs_a;
@@ -1049,7 +1062,7 @@ union Instruction {
BitField<49, 1, u64> nodep_flag;
BitField<50, 3, u64> component_mask_selector;
BitField<53, 4, u64> texture_info;
- BitField<60, 1, u64> fp32_flag;
+ BitField<59, 1, u64> fp32_flag;
TextureType GetTextureType() const {
// The TEXS instruction has a weird encoding for the texture type.
@@ -1065,6 +1078,7 @@ union Instruction {
LOG_CRITICAL(HW_GPU, "Unhandled texture_info: {}",
static_cast<u32>(texture_info.Value()));
UNREACHABLE();
+ return TextureType::Texture1D;
}
TextureProcessMode GetTextureProcessMode() const {
@@ -1145,6 +1159,7 @@ union Instruction {
LOG_CRITICAL(HW_GPU, "Unhandled texture_info: {}",
static_cast<u32>(texture_info.Value()));
UNREACHABLE();
+ return TextureType::Texture1D;
}
TextureProcessMode GetTextureProcessMode() const {
@@ -1429,6 +1444,7 @@ public:
PredicateSetRegister,
RegisterSetPredicate,
Conversion,
+ Video,
Xmad,
Unknown,
};
@@ -1560,8 +1576,8 @@ private:
INST("11100000--------", Id::IPA, Type::Trivial, "IPA"),
INST("1111101111100---", Id::OUT_R, Type::Trivial, "OUT_R"),
INST("1110111111010---", Id::ISBERD, Type::Trivial, "ISBERD"),
- INST("01011111--------", Id::VMAD, Type::Trivial, "VMAD"),
- INST("0101000011110---", Id::VSETP, Type::Trivial, "VSETP"),
+ INST("01011111--------", Id::VMAD, Type::Video, "VMAD"),
+ INST("0101000011110---", Id::VSETP, Type::Video, "VSETP"),
INST("0011001-1-------", Id::FFMA_IMM, Type::Ffma, "FFMA_IMM"),
INST("010010011-------", Id::FFMA_CR, Type::Ffma, "FFMA_CR"),
INST("010100011-------", Id::FFMA_RC, Type::Ffma, "FFMA_RC"),
diff --git a/src/video_core/engines/shader_header.h b/src/video_core/engines/shader_header.h
index 99c34649f..cf2b76ff6 100644
--- a/src/video_core/engines/shader_header.h
+++ b/src/video_core/engines/shader_header.h
@@ -106,7 +106,7 @@ struct Header {
} ps;
};
- u64 GetLocalMemorySize() {
+ u64 GetLocalMemorySize() const {
return (common1.shader_local_memory_low_size |
(common2.shader_local_memory_high_size << 24));
}