diff options
| author | 2014-05-18 22:50:41 +0200 | |
|---|---|---|
| committer | 2014-06-12 06:10:54 -0400 | |
| commit | 4c2bff61e5e8409cd25a5db396ce3574486f94b1 (patch) | |
| tree | 39110e36491ec9c6b3e938b7c2223b33fc3db5b5 /src | |
| parent | Further refine GPU command list debugging. (diff) | |
| download | yuzu-4c2bff61e5e8409cd25a5db396ce3574486f94b1.tar.gz yuzu-4c2bff61e5e8409cd25a5db396ce3574486f94b1.tar.xz yuzu-4c2bff61e5e8409cd25a5db396ce3574486f94b1.zip | |
Pica: Use some template magic to define register structures efficiently.
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/common.vcxproj | 3 | ||||
| -rw-r--r-- | src/common/common.vcxproj.filters | 5 | ||||
| -rw-r--r-- | src/common/register_set.h | 161 | ||||
| -rw-r--r-- | src/video_core/pica.h | 127 |
4 files changed, 268 insertions, 28 deletions
diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 86295a480..1f5c714c3 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj | |||
| @@ -182,6 +182,7 @@ | |||
| 182 | <ClInclude Include="mem_arena.h" /> | 182 | <ClInclude Include="mem_arena.h" /> |
| 183 | <ClInclude Include="msg_handler.h" /> | 183 | <ClInclude Include="msg_handler.h" /> |
| 184 | <ClInclude Include="platform.h" /> | 184 | <ClInclude Include="platform.h" /> |
| 185 | <ClInclude Include="register_set.h" /> | ||
| 185 | <ClInclude Include="scm_rev.h" /> | 186 | <ClInclude Include="scm_rev.h" /> |
| 186 | <ClInclude Include="std_condition_variable.h" /> | 187 | <ClInclude Include="std_condition_variable.h" /> |
| 187 | <ClInclude Include="std_mutex.h" /> | 188 | <ClInclude Include="std_mutex.h" /> |
| @@ -221,4 +222,4 @@ | |||
| 221 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | 222 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
| 222 | <ImportGroup Label="ExtensionTargets"> | 223 | <ImportGroup Label="ExtensionTargets"> |
| 223 | </ImportGroup> | 224 | </ImportGroup> |
| 224 | </Project> \ No newline at end of file | 225 | </Project> |
diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index 84cfa8837..e8c4ce360 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | <ClInclude Include="atomic.h" /> | 4 | <ClInclude Include="atomic.h" /> |
| 5 | <ClInclude Include="atomic_gcc.h" /> | 5 | <ClInclude Include="atomic_gcc.h" /> |
| 6 | <ClInclude Include="atomic_win32.h" /> | 6 | <ClInclude Include="atomic_win32.h" /> |
| 7 | <ClInclude Include="bit_field.h" /> | ||
| 7 | <ClInclude Include="break_points.h" /> | 8 | <ClInclude Include="break_points.h" /> |
| 8 | <ClInclude Include="chunk_file.h" /> | 9 | <ClInclude Include="chunk_file.h" /> |
| 9 | <ClInclude Include="common.h" /> | 10 | <ClInclude Include="common.h" /> |
| @@ -28,6 +29,7 @@ | |||
| 28 | <ClInclude Include="memory_util.h" /> | 29 | <ClInclude Include="memory_util.h" /> |
| 29 | <ClInclude Include="msg_handler.h" /> | 30 | <ClInclude Include="msg_handler.h" /> |
| 30 | <ClInclude Include="platform.h" /> | 31 | <ClInclude Include="platform.h" /> |
| 32 | <ClInclude Include="register_set.h" /> | ||
| 31 | <ClInclude Include="std_condition_variable.h" /> | 33 | <ClInclude Include="std_condition_variable.h" /> |
| 32 | <ClInclude Include="std_mutex.h" /> | 34 | <ClInclude Include="std_mutex.h" /> |
| 33 | <ClInclude Include="std_thread.h" /> | 35 | <ClInclude Include="std_thread.h" /> |
| @@ -39,7 +41,6 @@ | |||
| 39 | <ClInclude Include="utf8.h" /> | 41 | <ClInclude Include="utf8.h" /> |
| 40 | <ClInclude Include="symbols.h" /> | 42 | <ClInclude Include="symbols.h" /> |
| 41 | <ClInclude Include="scm_rev.h" /> | 43 | <ClInclude Include="scm_rev.h" /> |
| 42 | <ClInclude Include="bit_field.h" /> | ||
| 43 | <ClInclude Include="thread_queue_list.h" /> | 44 | <ClInclude Include="thread_queue_list.h" /> |
| 44 | </ItemGroup> | 45 | </ItemGroup> |
| 45 | <ItemGroup> | 46 | <ItemGroup> |
| @@ -65,4 +66,4 @@ | |||
| 65 | <ItemGroup> | 66 | <ItemGroup> |
| 66 | <Text Include="CMakeLists.txt" /> | 67 | <Text Include="CMakeLists.txt" /> |
| 67 | </ItemGroup> | 68 | </ItemGroup> |
| 68 | </Project> \ No newline at end of file | 69 | </Project> |
diff --git a/src/common/register_set.h b/src/common/register_set.h new file mode 100644 index 000000000..0418551b3 --- /dev/null +++ b/src/common/register_set.h | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | // Copyright 2014 Tony Wasserka | ||
| 8 | // All rights reserved. | ||
| 9 | // | ||
| 10 | // Redistribution and use in source and binary forms, with or without | ||
| 11 | // modification, are permitted provided that the following conditions are met: | ||
| 12 | // | ||
| 13 | // * Redistributions of source code must retain the above copyright | ||
| 14 | // notice, this list of conditions and the following disclaimer. | ||
| 15 | // * Redistributions in binary form must reproduce the above copyright | ||
| 16 | // notice, this list of conditions and the following disclaimer in the | ||
| 17 | // documentation and/or other materials provided with the distribution. | ||
| 18 | // * Neither the name of the owner nor the names of its contributors may | ||
| 19 | // be used to endorse or promote products derived from this software | ||
| 20 | // without specific prior written permission. | ||
| 21 | // | ||
| 22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| 23 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| 24 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| 25 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| 26 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| 27 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| 28 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| 29 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| 30 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 31 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 32 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | |||
| 34 | /* | ||
| 35 | * Standardized way to define a group of registers and corresponding data structures. To define | ||
| 36 | * a new register set, first define struct containing an enumeration called "Id" containing | ||
| 37 | * all register IDs and a template union called "Struct". Specialize the Struct union for any | ||
| 38 | * register ID which needs to be accessed in a specialized way. You can then declare the object | ||
| 39 | * containing all register values using the RegisterSet<BaseType, DefiningStruct> type, where | ||
| 40 | * BaseType is the underlying type of each register (e.g. u32). | ||
| 41 | * Of course, you'll usually want to implement the Struct template such that they are of the same | ||
| 42 | * size as BaseType. However, it's also possible to make it larger, e.g. when you want to describe | ||
| 43 | * multiple registers with the same structure. | ||
| 44 | * | ||
| 45 | * Example: | ||
| 46 | * | ||
| 47 | * struct Regs { | ||
| 48 | * enum Id : u32 { | ||
| 49 | * Value1 = 0, | ||
| 50 | * Value2 = 1, | ||
| 51 | * Value3 = 2, | ||
| 52 | * NumIds = 3 | ||
| 53 | * }; | ||
| 54 | * | ||
| 55 | * // declare register definition structures | ||
| 56 | * template<Id id> | ||
| 57 | * union Struct; | ||
| 58 | * }; | ||
| 59 | * | ||
| 60 | * // Define register set object | ||
| 61 | * RegisterSet<u32, CommandIds> registers; | ||
| 62 | * | ||
| 63 | * // define register definition structures | ||
| 64 | * template<> | ||
| 65 | * union Regs::Struct<Regs::Value1> { | ||
| 66 | * BitField<0, 4, u32> some_field; | ||
| 67 | * BitField<4, 3, u32> some_other_field; | ||
| 68 | * }; | ||
| 69 | * | ||
| 70 | * Usage in external code (within SomeNamespace scope): | ||
| 71 | * | ||
| 72 | * For a register which maps to a single index: | ||
| 73 | * registers.Get<Regs::Value1>().some_field = some_value; | ||
| 74 | * | ||
| 75 | * For a register which maps to different indices, e.g. a group of similar registers | ||
| 76 | * registers.Get<Regs::Value1>(index).some_field = some_value; | ||
| 77 | * | ||
| 78 | * | ||
| 79 | * @tparam BaseType Base type used for storing individual registers, e.g. u32 | ||
| 80 | * @tparam RegDefinition Class defining an enumeration called "Id" and a template<Id id> union, as described above. | ||
| 81 | * @note RegDefinition::Id needs to have an enum value called NumIds defining the number of registers to be allocated. | ||
| 82 | */ | ||
| 83 | template<typename BaseType, typename RegDefinition> | ||
| 84 | struct RegisterSet { | ||
| 85 | // Register IDs | ||
| 86 | using Id = typename RegDefinition::Id; | ||
| 87 | |||
| 88 | // type used for *this | ||
| 89 | using ThisType = RegisterSet<BaseType, RegDefinition>; | ||
| 90 | |||
| 91 | // Register definition structs, defined in RegDefinition | ||
| 92 | template<Id id> | ||
| 93 | using Struct = typename RegDefinition::template Struct<id>; | ||
| 94 | |||
| 95 | |||
| 96 | /* | ||
| 97 | * Lookup register with the given id and return it as the corresponding structure type. | ||
| 98 | * @note This just forwards the arguments to Get(Id). | ||
| 99 | */ | ||
| 100 | template<Id id> | ||
| 101 | const Struct<id>& Get() const { | ||
| 102 | return Get<id>(id); | ||
| 103 | } | ||
| 104 | |||
| 105 | /* | ||
| 106 | * Lookup register with the given id and return it as the corresponding structure type. | ||
| 107 | * @note This just forwards the arguments to Get(Id). | ||
| 108 | */ | ||
| 109 | template<Id id> | ||
| 110 | Struct<id>& Get() { | ||
| 111 | return Get<id>(id); | ||
| 112 | } | ||
| 113 | |||
| 114 | /* | ||
| 115 | * Lookup register with the given index and return it as the corresponding structure type. | ||
| 116 | * @todo Is this portable with regards to structures larger than BaseType? | ||
| 117 | * @note if index==id, you don't need to specify the function parameter. | ||
| 118 | */ | ||
| 119 | template<Id id> | ||
| 120 | const Struct<id>& Get(const Id& index) const { | ||
| 121 | const int idx = static_cast<size_t>(index); | ||
| 122 | return *reinterpret_cast<const Struct<id>*>(&raw[idx]); | ||
| 123 | } | ||
| 124 | |||
| 125 | /* | ||
| 126 | * Lookup register with the given index and return it as the corresponding structure type. | ||
| 127 | * @note This just forwards the arguments to the const version of Get(Id). | ||
| 128 | * @note if index==id, you don't need to specify the function parameter. | ||
| 129 | */ | ||
| 130 | template<Id id> | ||
| 131 | Struct<id>& Get(const Id& index) { | ||
| 132 | return const_cast<Struct<id>&>(GetThis().Get<id>(index)); | ||
| 133 | } | ||
| 134 | |||
| 135 | /* | ||
| 136 | * Plain array access. | ||
| 137 | * @note If you want to have this casted to a register defininition struct, use Get() instead. | ||
| 138 | */ | ||
| 139 | const BaseType& operator[] (const Id& id) const { | ||
| 140 | return raw[static_cast<size_t>(id)]; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* | ||
| 144 | * Plain array access. | ||
| 145 | * @note If you want to have this casted to a register defininition struct, use Get() instead. | ||
| 146 | * @note This operator just forwards its argument to the const version. | ||
| 147 | */ | ||
| 148 | BaseType& operator[] (const Id& id) { | ||
| 149 | return const_cast<BaseType&>(GetThis()[id]); | ||
| 150 | } | ||
| 151 | |||
| 152 | private: | ||
| 153 | /* | ||
| 154 | * Returns a const reference to "this". | ||
| 155 | */ | ||
| 156 | const ThisType& GetThis() const { | ||
| 157 | return static_cast<const ThisType&>(*this); | ||
| 158 | } | ||
| 159 | |||
| 160 | BaseType raw[Id::NumIds]; | ||
| 161 | }; | ||
diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 7cbc45f98..f0fa3aba9 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h | |||
| @@ -9,45 +9,122 @@ | |||
| 9 | 9 | ||
| 10 | #include "common/bit_field.h" | 10 | #include "common/bit_field.h" |
| 11 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 12 | #include "common/register_set.h" | ||
| 12 | 13 | ||
| 13 | namespace Pica { | 14 | namespace Pica { |
| 14 | 15 | ||
| 15 | enum class CommandId : u32 | 16 | struct Regs { |
| 16 | { | 17 | enum Id : u32 { |
| 17 | ViewportSizeX = 0x41, | 18 | ViewportSizeX = 0x41, |
| 18 | ViewportInvSizeX = 0x42, | 19 | ViewportInvSizeX = 0x42, |
| 19 | ViewportSizeY = 0x43, | 20 | ViewportSizeY = 0x43, |
| 20 | ViewportInvSizeY = 0x44, | 21 | ViewportInvSizeY = 0x44, |
| 21 | ViewportCorner = 0x68, | 22 | ViewportCorner = 0x68, |
| 22 | DepthBufferFormat = 0x116, | 23 | DepthBufferFormat = 0x116, |
| 23 | ColorBufferFormat = 0x117, | 24 | ColorBufferFormat = 0x117, |
| 24 | DepthBufferAddress = 0x11C, | 25 | DepthBufferAddress = 0x11C, |
| 25 | ColorBufferAddress = 0x11D, | 26 | ColorBufferAddress = 0x11D, |
| 26 | ColorBufferSize = 0x11E, | 27 | ColorBufferSize = 0x11E, |
| 28 | |||
| 29 | VertexArrayBaseAddr = 0x200, | ||
| 30 | VertexDescriptor = 0x201, // 0x202 | ||
| 31 | VertexAttributeOffset = 0x203, // 0x206,0x209,0x20C,0x20F,0x212,0x215,0x218,0x21B,0x21E,0x221,0x224 | ||
| 32 | VertexAttributeInfo0 = 0x204, // 0x207,0x20A,0x20D,0x210,0x213,0x216,0x219,0x21C,0x21F,0x222,0x225 | ||
| 33 | VertexAttributeInfo1 = 0x205, // 0x208,0x20B,0x20E,0x211,0x214,0x217,0x21A,0x21D,0x220,0x223,0x226 | ||
| 34 | |||
| 35 | NumIds = 0x300, | ||
| 36 | }; | ||
| 37 | |||
| 38 | template<Id id> | ||
| 39 | union Struct; | ||
| 27 | }; | 40 | }; |
| 28 | 41 | ||
| 42 | static inline Regs::Id VertexAttributeOffset(int n) | ||
| 43 | { | ||
| 44 | return static_cast<Regs::Id>(0x203 + 3*n); | ||
| 45 | } | ||
| 46 | |||
| 47 | static inline Regs::Id VertexAttributeInfo0(int n) | ||
| 48 | { | ||
| 49 | return static_cast<Regs::Id>(0x204 + 3*n); | ||
| 50 | } | ||
| 51 | |||
| 52 | static inline Regs::Id VertexAttributeInfo1(int n) | ||
| 53 | { | ||
| 54 | return static_cast<Regs::Id>(0x205 + 3*n); | ||
| 55 | } | ||
| 56 | |||
| 29 | union CommandHeader { | 57 | union CommandHeader { |
| 30 | CommandHeader(u32 h) : hex(h) {} | 58 | CommandHeader(u32 h) : hex(h) {} |
| 31 | 59 | ||
| 32 | u32 hex; | 60 | u32 hex; |
| 33 | 61 | ||
| 34 | BitField< 0, 16, CommandId> cmd_id; | 62 | BitField< 0, 16, Regs::Id> cmd_id; |
| 35 | BitField<16, 4, u32> parameter_mask; | 63 | BitField<16, 4, u32> parameter_mask; |
| 36 | BitField<20, 11, u32> extra_data_length; | 64 | BitField<20, 11, u32> extra_data_length; |
| 37 | BitField<31, 1, u32> group_commands; | 65 | BitField<31, 1, u32> group_commands; |
| 38 | }; | 66 | }; |
| 39 | 67 | ||
| 40 | static std::map<CommandId, const char*> command_names = { | 68 | static std::map<Regs::Id, const char*> command_names = { |
| 41 | {CommandId::ViewportSizeX, "ViewportSizeX" }, | 69 | {Regs::ViewportSizeX, "ViewportSizeX" }, |
| 42 | {CommandId::ViewportInvSizeX, "ViewportInvSizeX" }, | 70 | {Regs::ViewportInvSizeX, "ViewportInvSizeX" }, |
| 43 | {CommandId::ViewportSizeY, "ViewportSizeY" }, | 71 | {Regs::ViewportSizeY, "ViewportSizeY" }, |
| 44 | {CommandId::ViewportInvSizeY, "ViewportInvSizeY" }, | 72 | {Regs::ViewportInvSizeY, "ViewportInvSizeY" }, |
| 45 | {CommandId::ViewportCorner, "ViewportCorner" }, | 73 | {Regs::ViewportCorner, "ViewportCorner" }, |
| 46 | {CommandId::DepthBufferFormat, "DepthBufferFormat" }, | 74 | {Regs::DepthBufferFormat, "DepthBufferFormat" }, |
| 47 | {CommandId::ColorBufferFormat, "ColorBufferFormat" }, | 75 | {Regs::ColorBufferFormat, "ColorBufferFormat" }, |
| 48 | {CommandId::DepthBufferAddress, "DepthBufferAddress" }, | 76 | {Regs::DepthBufferAddress, "DepthBufferAddress" }, |
| 49 | {CommandId::ColorBufferAddress, "ColorBufferAddress" }, | 77 | {Regs::ColorBufferAddress, "ColorBufferAddress" }, |
| 50 | {CommandId::ColorBufferSize, "ColorBufferSize" }, | 78 | {Regs::ColorBufferSize, "ColorBufferSize" }, |
| 51 | }; | 79 | }; |
| 52 | 80 | ||
| 53 | } | 81 | template<> |
| 82 | union Regs::Struct<Regs::ViewportSizeX> { | ||
| 83 | BitField<0, 24, u32> value; | ||
| 84 | }; | ||
| 85 | |||
| 86 | template<> | ||
| 87 | union Regs::Struct<Regs::ViewportSizeY> { | ||
| 88 | BitField<0, 24, u32> value; | ||
| 89 | }; | ||
| 90 | |||
| 91 | template<> | ||
| 92 | union Regs::Struct<Regs::VertexDescriptor> { | ||
| 93 | enum class Format : u64 { | ||
| 94 | BYTE = 0, | ||
| 95 | UBYTE = 1, | ||
| 96 | SHORT = 2, | ||
| 97 | FLOAT = 3, | ||
| 98 | }; | ||
| 99 | |||
| 100 | BitField< 0, 2, Format> format0; | ||
| 101 | BitField< 2, 2, u64> size0; // number of elements minus 1 | ||
| 102 | BitField< 4, 2, Format> format1; | ||
| 103 | BitField< 6, 2, u64> size1; | ||
| 104 | BitField< 8, 2, Format> format2; | ||
| 105 | BitField<10, 2, u64> size2; | ||
| 106 | BitField<12, 2, Format> format3; | ||
| 107 | BitField<14, 2, u64> size3; | ||
| 108 | BitField<16, 2, Format> format4; | ||
| 109 | BitField<18, 2, u64> size4; | ||
| 110 | BitField<20, 2, Format> format5; | ||
| 111 | BitField<22, 2, u64> size5; | ||
| 112 | BitField<24, 2, Format> format6; | ||
| 113 | BitField<26, 2, u64> size6; | ||
| 114 | BitField<28, 2, Format> format7; | ||
| 115 | BitField<30, 2, u64> size7; | ||
| 116 | BitField<32, 2, Format> format8; | ||
| 117 | BitField<34, 2, u64> size8; | ||
| 118 | BitField<36, 2, Format> format9; | ||
| 119 | BitField<38, 2, u64> size9; | ||
| 120 | BitField<40, 2, Format> format10; | ||
| 121 | BitField<42, 2, u64> size10; | ||
| 122 | BitField<44, 2, Format> format11; | ||
| 123 | BitField<46, 2, u64> size11; | ||
| 124 | |||
| 125 | BitField<48, 12, u64> attribute_mask; | ||
| 126 | BitField<60, 4, u64> num_attributes; // number of total attributes minus 1 | ||
| 127 | }; | ||
| 128 | |||
| 129 | |||
| 130 | } // namespace | ||