diff options
Diffstat (limited to 'src/video_core/engines')
-rw-r--r-- | src/video_core/engines/fermi_2d.cpp | 8 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 66 | ||||
-rw-r--r-- | src/video_core/engines/maxwell_3d.h | 17 | ||||
-rw-r--r-- | src/video_core/engines/shader_bytecode.h | 6 | ||||
-rw-r--r-- | src/video_core/engines/shader_header.h | 41 |
5 files changed, 86 insertions, 52 deletions
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index ec1a57226..540dcc52c 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp @@ -44,10 +44,10 @@ void Fermi2D::HandleSurfaceCopy() { const u32 src_blit_y2{ static_cast<u32>((regs.blit_src_y + (regs.blit_dst_height * regs.blit_dv_dy)) >> 32)}; - const MathUtil::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2}; - const MathUtil::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, - regs.blit_dst_x + regs.blit_dst_width, - regs.blit_dst_y + regs.blit_dst_height}; + const Common::Rectangle<u32> src_rect{src_blit_x1, src_blit_y1, src_blit_x2, src_blit_y2}; + const Common::Rectangle<u32> dst_rect{regs.blit_dst_x, regs.blit_dst_y, + regs.blit_dst_x + regs.blit_dst_width, + regs.blit_dst_y + regs.blit_dst_height}; if (!rasterizer.AccelerateSurfaceCopy(regs.src, regs.dst, src_rect, dst_rect)) { UNIMPLEMENTED(); diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 2d2136067..144e7fa82 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -107,21 +107,23 @@ void Maxwell3D::CallMacroMethod(u32 method, std::vector<u32> parameters) { void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { auto debug_context = system.GetGPUDebugContext(); + const u32 method = method_call.method; + // It is an error to write to a register other than the current macro's ARG register before it // has finished execution. if (executing_macro != 0) { - ASSERT(method_call.method == executing_macro + 1); + ASSERT(method == executing_macro + 1); } // Methods after 0xE00 are special, they're actually triggers for some microcode that was // uploaded to the GPU during initialization. - if (method_call.method >= MacroRegistersStart) { + if (method >= MacroRegistersStart) { // We're trying to execute a macro if (executing_macro == 0) { // A macro call must begin by writing the macro method's register, not its argument. - ASSERT_MSG((method_call.method % 2) == 0, + ASSERT_MSG((method % 2) == 0, "Can't start macro execution by writing to the ARGS register"); - executing_macro = method_call.method; + executing_macro = method; } macro_params.push_back(method_call.argument); @@ -133,66 +135,62 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { return; } - ASSERT_MSG(method_call.method < Regs::NUM_REGS, + ASSERT_MSG(method < Regs::NUM_REGS, "Invalid Maxwell3D register, increase the size of the Regs structure"); if (debug_context) { debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr); } - if (regs.reg_array[method_call.method] != method_call.argument) { - regs.reg_array[method_call.method] = method_call.argument; + if (regs.reg_array[method] != method_call.argument) { + regs.reg_array[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); + if (method >= first_rt_reg && + method < first_rt_reg + registers_per_rt * Regs::NumRenderTargets) { + const std::size_t rt_index = (method - first_rt_reg) / registers_per_rt; + dirty_flags.color_buffer.set(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)) { + if (method == MAXWELL3D_REG_INDEX(zeta_enable) || + method == MAXWELL3D_REG_INDEX(zeta_width) || + method == MAXWELL3D_REG_INDEX(zeta_height) || + (method >= MAXWELL3D_REG_INDEX(zeta) && + 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) { + if (method >= MAXWELL3D_REG_INDEX(shader_config[0]) && + 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 < - MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) { + if (method >= MAXWELL3D_REG_INDEX(vertex_attrib_format) && + method < MAXWELL3D_REG_INDEX(vertex_attrib_format) + regs.vertex_attrib_format.size()) { dirty_flags.vertex_attrib_format = true; } // Vertex buffer - if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_array) && - method_call.method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * 32) { - dirty_flags.vertex_array |= - 1u << ((method_call.method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2); - } else if (method_call.method >= MAXWELL3D_REG_INDEX(vertex_array_limit) && - method_call.method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * 32) { - dirty_flags.vertex_array |= - 1u << ((method_call.method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1); - } else if (method_call.method >= MAXWELL3D_REG_INDEX(instanced_arrays) && - method_call.method < MAXWELL3D_REG_INDEX(instanced_arrays) + 32) { - dirty_flags.vertex_array |= - 1u << (method_call.method - MAXWELL3D_REG_INDEX(instanced_arrays)); + if (method >= MAXWELL3D_REG_INDEX(vertex_array) && + method < MAXWELL3D_REG_INDEX(vertex_array) + 4 * 32) { + dirty_flags.vertex_array.set((method - MAXWELL3D_REG_INDEX(vertex_array)) >> 2); + } else if (method >= MAXWELL3D_REG_INDEX(vertex_array_limit) && + method < MAXWELL3D_REG_INDEX(vertex_array_limit) + 2 * 32) { + dirty_flags.vertex_array.set((method - MAXWELL3D_REG_INDEX(vertex_array_limit)) >> 1); + } else if (method >= MAXWELL3D_REG_INDEX(instanced_arrays) && + method < MAXWELL3D_REG_INDEX(instanced_arrays) + 32) { + dirty_flags.vertex_array.set(method - MAXWELL3D_REG_INDEX(instanced_arrays)); } } - switch (method_call.method) { + switch (method) { case MAXWELL3D_REG_INDEX(macros.data): { ProcessMacroUpload(method_call.argument); break; diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index 0e3873ffd..7fbf1026e 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -5,8 +5,10 @@ #pragma once #include <array> +#include <bitset> #include <unordered_map> #include <vector> + #include "common/assert.h" #include "common/bit_field.h" #include "common/common_funcs.h" @@ -503,7 +505,7 @@ public: f32 translate_z; INSERT_PADDING_WORDS(2); - MathUtil::Rectangle<s32> GetRect() const { + Common::Rectangle<s32> GetRect() const { return { GetX(), // left GetY() + GetHeight(), // top @@ -1094,19 +1096,18 @@ public: MemoryManager& memory_manager; struct DirtyFlags { - u8 color_buffer = 0xFF; - bool zeta_buffer = true; - - bool shaders = true; + std::bitset<8> color_buffer{0xFF}; + std::bitset<32> vertex_array{0xFFFFFFFF}; bool vertex_attrib_format = true; - u32 vertex_array = 0xFFFFFFFF; + bool zeta_buffer = true; + bool shaders = true; void OnMemoryWrite() { - color_buffer = 0xFF; zeta_buffer = true; shaders = true; - vertex_array = 0xFFFFFFFF; + color_buffer.set(); + vertex_array.set(); } }; diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 1f425f90b..252592edd 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -376,9 +376,9 @@ enum class R2pMode : u64 { }; enum class IpaInterpMode : u64 { - Linear = 0, - Perspective = 1, - Flat = 2, + Pass = 0, + Multiply = 1, + Constant = 2, Sc = 3, }; diff --git a/src/video_core/engines/shader_header.h b/src/video_core/engines/shader_header.h index cf2b76ff6..e86a7f04a 100644 --- a/src/video_core/engines/shader_header.h +++ b/src/video_core/engines/shader_header.h @@ -16,6 +16,13 @@ enum class OutputTopology : u32 { TriangleStrip = 7, }; +enum class AttributeUse : u8 { + Unused = 0, + Constant = 1, + Perspective = 2, + ScreenLinear = 3, +}; + // Documentation in: // http://download.nvidia.com/open-gpu-doc/Shader-Program-Header/1/Shader-Program-Header.html#ImapTexture struct Header { @@ -84,9 +91,15 @@ struct Header { } vtg; struct { - INSERT_PADDING_BYTES(3); // ImapSystemValuesA - INSERT_PADDING_BYTES(1); // ImapSystemValuesB - INSERT_PADDING_BYTES(32); // ImapGenericVector[32] + INSERT_PADDING_BYTES(3); // ImapSystemValuesA + INSERT_PADDING_BYTES(1); // ImapSystemValuesB + union { + BitField<0, 2, AttributeUse> x; + BitField<2, 2, AttributeUse> y; + BitField<4, 2, AttributeUse> w; + BitField<6, 2, AttributeUse> z; + u8 raw; + } imap_generic_vector[32]; INSERT_PADDING_BYTES(2); // ImapColor INSERT_PADDING_BYTES(2); // ImapSystemValuesC INSERT_PADDING_BYTES(10); // ImapFixedFncTexture[10] @@ -103,6 +116,28 @@ struct Header { const u32 bit = render_target * 4 + component; return omap.target & (1 << bit); } + AttributeUse GetAttributeIndexUse(u32 attribute, u32 index) const { + return static_cast<AttributeUse>( + (imap_generic_vector[attribute].raw >> (index * 2)) & 0x03); + } + AttributeUse GetAttributeUse(u32 attribute) const { + AttributeUse result = AttributeUse::Unused; + for (u32 i = 0; i < 4; i++) { + const auto index = GetAttributeIndexUse(attribute, i); + if (index == AttributeUse::Unused) { + continue; + } + if (result == AttributeUse::Unused || result == index) { + result = index; + continue; + } + LOG_CRITICAL(HW_GPU, "Generic Attribute Conflict in Interpolation Mode"); + if (index == AttributeUse::Perspective) { + result = index; + } + } + return result; + } } ps; }; |