| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- // Copyright 2018 yuzu Emulator Project
- // Licensed under GPLv2 or any later version
- // Refer to the license.txt file included.
- #pragma once
- #include <array>
- #include <unordered_map>
- #include <vector>
- #include "common/bit_field.h"
- #include "common/common_funcs.h"
- #include "common/common_types.h"
- #include "video_core/memory_manager.h"
- namespace Tegra {
- namespace Engines {
- class Maxwell3D final {
- public:
- explicit Maxwell3D(MemoryManager& memory_manager);
- ~Maxwell3D() = default;
- /// Write the value to the register identified by method.
- void WriteReg(u32 method, u32 value, u32 remaining_params);
- /// Uploads the code for a GPU macro program associated with the specified entry.
- void SubmitMacroCode(u32 entry, std::vector<u32> code);
- /// Register structure of the Maxwell3D engine.
- /// TODO(Subv): This structure will need to be made bigger as more registers are discovered.
- struct Regs {
- static constexpr size_t NUM_REGS = 0xE36;
- static constexpr size_t NumCBData = 16;
- static constexpr size_t NumVertexArrays = 32;
- static constexpr size_t MaxShaderProgram = 6;
- static constexpr size_t MaxShaderStage = 5;
- // Maximum number of const buffers per shader stage.
- static constexpr size_t MaxConstBuffers = 16;
- enum class QueryMode : u32 {
- Write = 0,
- Sync = 1,
- };
- enum class ShaderProgram : u32 {
- VertexA = 0,
- VertexB = 1,
- TesselationControl = 2,
- TesselationEval = 3,
- Geometry = 4,
- Fragment = 5,
- };
- enum class ShaderStage : u32 {
- Vertex = 0,
- TesselationControl = 1,
- TesselationEval = 2,
- Geometry = 3,
- Fragment = 4,
- };
- union {
- struct {
- INSERT_PADDING_WORDS(0x582);
- struct {
- u32 code_address_high;
- u32 code_address_low;
- GPUVAddr CodeAddress() const {
- return static_cast<GPUVAddr>(
- (static_cast<GPUVAddr>(code_address_high) << 32) | code_address_low);
- }
- } code_address;
- INSERT_PADDING_WORDS(1);
- struct {
- u32 vertex_end_gl;
- u32 vertex_begin_gl;
- } draw;
- INSERT_PADDING_WORDS(0x139);
- struct {
- u32 query_address_high;
- u32 query_address_low;
- u32 query_sequence;
- union {
- u32 raw;
- BitField<0, 2, QueryMode> mode;
- BitField<4, 1, u32> fence;
- BitField<12, 4, u32> unit;
- } query_get;
- GPUVAddr QueryAddress() const {
- return static_cast<GPUVAddr>(
- (static_cast<GPUVAddr>(query_address_high) << 32) | query_address_low);
- }
- } query;
- INSERT_PADDING_WORDS(0x3C);
- struct {
- union {
- BitField<0, 12, u32> stride;
- BitField<12, 1, u32> enable;
- };
- u32 start_high;
- u32 start_low;
- u32 divisor;
- GPUVAddr StartAddress() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_high) << 32) |
- start_low);
- }
- } vertex_array[NumVertexArrays];
- INSERT_PADDING_WORDS(0x40);
- struct {
- u32 limit_high;
- u32 limit_low;
- GPUVAddr LimitAddress() const {
- return static_cast<GPUVAddr>((static_cast<GPUVAddr>(limit_high) << 32) |
- limit_low);
- }
- } vertex_array_limit[NumVertexArrays];
- struct {
- union {
- BitField<0, 1, u32> enable;
- BitField<4, 4, ShaderProgram> program;
- };
- u32 start_id;
- INSERT_PADDING_WORDS(1);
- u32 gpr_alloc;
- ShaderStage type;
- INSERT_PADDING_WORDS(9);
- } shader_config[MaxShaderProgram];
- INSERT_PADDING_WORDS(0x8C);
- struct {
- u32 cb_size;
- u32 cb_address_high;
- u32 cb_address_low;
- u32 cb_pos;
- u32 cb_data[NumCBData];
- GPUVAddr BufferAddress() const {
- return static_cast<GPUVAddr>(
- (static_cast<GPUVAddr>(cb_address_high) << 32) | cb_address_low);
- }
- } const_buffer;
- INSERT_PADDING_WORDS(0x10);
- struct {
- union {
- u32 raw_config;
- BitField<0, 1, u32> valid;
- BitField<4, 5, u32> index;
- };
- INSERT_PADDING_WORDS(7);
- } cb_bind[MaxShaderStage];
- INSERT_PADDING_WORDS(0x56);
- u32 tex_cb_index;
- INSERT_PADDING_WORDS(0x4B3);
- };
- std::array<u32, NUM_REGS> reg_array;
- };
- } regs{};
- static_assert(sizeof(Regs) == Regs::NUM_REGS * sizeof(u32), "Maxwell3D Regs has wrong size");
- struct State {
- struct ConstBufferInfo {
- GPUVAddr address;
- u32 index;
- u32 size;
- bool enabled;
- };
- struct ShaderProgramInfo {
- Regs::ShaderStage stage;
- Regs::ShaderProgram program;
- GPUVAddr address;
- };
- struct ShaderStageInfo {
- std::array<ConstBufferInfo, Regs::MaxConstBuffers> const_buffers;
- };
- std::array<ShaderStageInfo, Regs::MaxShaderStage> shader_stages;
- std::array<ShaderProgramInfo, Regs::MaxShaderProgram> shader_programs;
- };
- State state{};
- private:
- MemoryManager& memory_manager;
- std::unordered_map<u32, std::vector<u32>> uploaded_macros;
- /// Macro method that is currently being executed / being fed parameters.
- u32 executing_macro = 0;
- /// Parameters that have been submitted to the macro call so far.
- std::vector<u32> macro_params;
- /**
- * Call a macro on this engine.
- * @param method Method to call
- * @param parameters Arguments to the method call
- */
- void CallMacroMethod(u32 method, const std::vector<u32>& parameters);
- /// Handles a write to the QUERY_GET register.
- void ProcessQueryGet();
- /// Handles a write to the CB_BIND register.
- void ProcessCBBind(Regs::ShaderStage stage);
- /// Handles a write to the VERTEX_END_GL register, triggering a draw.
- void DrawArrays();
- /// Method call handlers
- void SetShader(const std::vector<u32>& parameters);
- struct MethodInfo {
- const char* name;
- u32 arguments;
- void (Maxwell3D::*handler)(const std::vector<u32>& parameters);
- };
- static const std::unordered_map<u32, MethodInfo> method_handlers;
- };
- #define ASSERT_REG_POSITION(field_name, position) \
- static_assert(offsetof(Maxwell3D::Regs, field_name) == position * 4, \
- "Field " #field_name " has invalid position")
- ASSERT_REG_POSITION(code_address, 0x582);
- ASSERT_REG_POSITION(draw, 0x585);
- ASSERT_REG_POSITION(query, 0x6C0);
- ASSERT_REG_POSITION(vertex_array[0], 0x700);
- ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0);
- ASSERT_REG_POSITION(shader_config[0], 0x800);
- ASSERT_REG_POSITION(const_buffer, 0x8E0);
- ASSERT_REG_POSITION(cb_bind[0], 0x904);
- ASSERT_REG_POSITION(tex_cb_index, 0x982);
- #undef ASSERT_REG_POSITION
- } // namespace Engines
- } // namespace Tegra
|