Pica: Add command processor.
This commit is contained in:
parent
98ad16a45b
commit
76a586de49
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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 "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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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" />
|
||||
|
|
Reference in New Issue