Преглед изворни кода

Pica: Add command processor.

Tony Wasserka пре 12 година
родитељ
комит
76a586de49

+ 1 - 1
src/citra_qt/debugger/graphics_cmdlists.cpp

@@ -78,7 +78,7 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const
         // index refers to a specific command
         const GraphicsDebugger::PicaCommandList& cmdlist = command_lists[item->parent->index].second;
         const GraphicsDebugger::PicaCommand& cmd = cmdlist[item->index];
-        const Pica::CommandHeader& header = cmd.GetHeader();
+        const Pica::CommandProcessor::CommandHeader& header = cmd.GetHeader();
 
         if (role == Qt::DisplayRole) {
             QString content;

+ 5 - 3
src/core/hw/gpu.cpp

@@ -14,6 +14,7 @@
 
 #include "core/hw/gpu.h"
 
+#include "video_core/command_processor.h"
 #include "video_core/video_core.h"
 
 
@@ -143,14 +144,15 @@ inline void Write(u32 addr, const T data) {
         break;
     }
 
+    // Seems like writing to this register triggers processing
     case GPU_REG_INDEX(command_processor_config.trigger):
     {
         const auto& config = g_regs.command_processor_config;
         if (config.trigger & 1)
         {
-            // u32* buffer = (u32*)Memory::GetPointer(config.GetPhysicalAddress());
-            ERROR_LOG(GPU, "Beginning 0x%08x bytes of commands from address 0x%08x", config.size, config.GetPhysicalAddress());
-            // TODO: Process command list!
+            u32* buffer = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalAddress()));
+            u32 size = config.size << 3;
+            Pica::CommandProcessor::ProcessCommandList(buffer, size);
         }
         break;
     }

+ 5 - 2
src/video_core/CMakeLists.txt

@@ -1,11 +1,14 @@
-set(SRCS    video_core.cpp
+set(SRCS    command_processor.cpp
             utils.cpp
+            video_core.cpp
             renderer_opengl/renderer_opengl.cpp)
 
-set(HEADERS math.h
+set(HEADERS command_processor.h
+            math.h
             utils.h
             video_core.h
             renderer_base.h
+            video_core.h
             renderer_opengl/renderer_opengl.h)
 
 add_library(video_core STATIC ${SRCS} ${HEADERS})

+ 60 - 0
src/video_core/command_processor.cpp

@@ -0,0 +1,60 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include "pica.h"
+#include "command_processor.h"
+
+
+namespace Pica {
+
+Regs registers;
+
+namespace CommandProcessor {
+
+static inline void WritePicaReg(u32 id, u32 value) {
+    u32 old_value = registers[id];
+    registers[id] = value;
+
+    switch(id) {
+        // TODO: Perform actions for anything which requires special treatment here...
+
+        default:
+            break;
+    }
+}
+
+static std::ptrdiff_t ExecuteCommandBlock(const u32* first_command_word) {
+    const CommandHeader& header = *(const CommandHeader*)(&first_command_word[1]);
+
+    u32* read_pointer = (u32*)first_command_word;
+
+    // TODO: Take parameter mask into consideration!
+
+    WritePicaReg(header.cmd_id, *read_pointer);
+    read_pointer += 2;
+
+    for (int i = 1; i < 1+header.extra_data_length; ++i) {
+        u32 cmd = header.cmd_id + ((header.group_commands) ? i : 0);
+        WritePicaReg(cmd, *read_pointer);
+        ++read_pointer;
+    }
+
+    // align read pointer to 8 bytes
+    if ((first_command_word - read_pointer) % 2)
+        ++read_pointer;
+
+    return read_pointer - first_command_word;
+}
+
+void ProcessCommandList(const u32* list, u32 size) {
+    u32* read_pointer = (u32*)list;
+
+    while (read_pointer < list + size) {
+        read_pointer += ExecuteCommandBlock(read_pointer);
+    }
+}
+
+} // namespace
+
+} // namespace

+ 31 - 0
src/video_core/command_processor.h

@@ -0,0 +1,31 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/bit_field.h"
+#include "common/common_types.h"
+
+#include "pica.h"
+
+namespace Pica {
+
+namespace CommandProcessor {
+
+union CommandHeader {
+    u32 hex;
+
+    BitField< 0, 16, u32> cmd_id;
+    BitField<16,  4, u32> parameter_mask;
+    BitField<20, 11, u32> extra_data_length;
+    BitField<31,  1, u32> group_commands;
+};
+static_assert(std::is_standard_layout<CommandHeader>::value == true, "CommandHeader does not use standard layout");
+static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!");
+
+void ProcessCommandList(const u32* list, u32 size);
+
+} // namespace
+
+} // namespace

+ 5 - 3
src/video_core/gpu_debugger.h

@@ -11,6 +11,8 @@
 #include "common/log.h"
 
 #include "core/hle/service/gsp.h"
+
+#include "command_processor.h"
 #include "pica.h"
 
 class GraphicsDebugger
@@ -20,10 +22,10 @@ public:
     // A vector of commands represented by their raw byte sequence
     struct PicaCommand : public std::vector<u32>
     {
-        const Pica::CommandHeader& GetHeader() const
+        const Pica::CommandProcessor::CommandHeader& GetHeader() const
         {
             const u32& val = at(1);
-            return *(Pica::CommandHeader*)&val;
+            return *(Pica::CommandProcessor::CommandHeader*)&val;
         }
     };
 
@@ -99,7 +101,7 @@ public:
         PicaCommandList cmdlist;
         for (u32* parse_pointer = command_list; parse_pointer < command_list + size_in_words;)
         {
-            const Pica::CommandHeader header = static_cast<Pica::CommandHeader>(parse_pointer[1]);
+            const Pica::CommandProcessor::CommandHeader& header = *(Pica::CommandProcessor::CommandHeader*)(&parse_pointer[1]);
 
             cmdlist.push_back(PicaCommand());
             auto& cmd = cmdlist.back();

+ 2 - 0
src/video_core/pica.h

@@ -161,6 +161,8 @@ ASSERT_REG_POSITION(vertex_descriptor, 0x200);
 // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value anyway.
 static_assert(sizeof(Regs) == 0x300 * sizeof(u32), "Invalid total size of register set");
 
+extern Regs registers; // TODO: Not sure if we want to have one global instance for this
+
 
 struct float24 {
     static float24 FromFloat32(float val) {

+ 2 - 0
src/video_core/video_core.vcxproj

@@ -20,10 +20,12 @@
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="renderer_opengl\renderer_opengl.cpp" />
+    <ClCompile Include="command_processor.cpp" />
     <ClCompile Include="utils.cpp" />
     <ClCompile Include="video_core.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="command_processor.h" />
     <ClInclude Include="gpu_debugger.h" />
     <ClInclude Include="math.h" />
     <ClInclude Include="pica.h" />

+ 2 - 0
src/video_core/video_core.vcxproj.filters

@@ -9,6 +9,7 @@
     <ClCompile Include="renderer_opengl\renderer_opengl.cpp">
       <Filter>renderer_opengl</Filter>
     </ClCompile>
+    <ClCompile Include="command_processor.cpp" />
     <ClCompile Include="utils.cpp" />
     <ClCompile Include="video_core.cpp" />
   </ItemGroup>
@@ -16,6 +17,7 @@
     <ClInclude Include="renderer_opengl\renderer_opengl.h">
       <Filter>renderer_opengl</Filter>
     </ClInclude>
+    <ClInclude Include="command_processor.h" />
     <ClInclude Include="gpu_debugger.h" />
     <ClInclude Include="math.h" />
     <ClInclude Include="pica.h" />