Pica: Add command processor.

merge-requests/60/head
Tony Wasserka 2014-07-26 14:42:46 +07:00
parent 98ad16a45b
commit 76a586de49
9 changed files with 113 additions and 9 deletions

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

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

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

@ -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

@ -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

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

@ -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. // 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"); 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 { struct float24 {
static float24 FromFloat32(float val) { static float24 FromFloat32(float val) {

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

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