Move display list management to common GPU class

This commit is contained in:
Florent Castelli 2012-12-28 21:58:00 +01:00
parent f9133c1a56
commit 6eec4f5d7f
13 changed files with 176 additions and 163 deletions

View File

@ -806,6 +806,8 @@ add_library(GPU OBJECT
GPU/GPUInterface.h
GPU/GeDisasm.cpp
GPU/GeDisasm.h
GPU/GPUCommon.cpp
GPU/GPUCommon.h
GPU/GPUState.cpp
GPU/GPUState.h
GPU/Math3D.cpp

View File

@ -25,17 +25,12 @@
#include "../GPU/GPUState.h"
#include "../GPU/GPUInterface.h"
// TODO: This doesn't really belong here
static int state;
void __GeInit()
{
state = 0;
}
void __GeDoState(PointerWrap &p)
{
p.Do(state);
p.Do(gstate);
p.Do(gstate_c);
@ -74,12 +69,7 @@ u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, u32 callbackId,
listAddress, stallAddress, callbackId, optParamAddr);
//if (!stallAddress)
// stallAddress = listAddress;
u32 listID = gpu->EnqueueList(listAddress, stallAddress);
// HACKY
if (listID)
state = SCE_GE_LIST_STALLING;
else
state = SCE_GE_LIST_COMPLETED;
u32 listID = gpu->EnqueueList(listAddress, stallAddress, false);
DEBUG_LOG(HLE, "List %i enqueued.", listID);
//return display list ID
@ -94,12 +84,7 @@ u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, u32 callbackId,
listAddress, stallAddress, callbackId, optParamAddr);
//if (!stallAddress)
// stallAddress = listAddress;
u32 listID = gpu->EnqueueList(listAddress, stallAddress);
// HACKY
if (listID)
state = SCE_GE_LIST_STALLING;
else
state = SCE_GE_LIST_COMPLETED;
u32 listID = gpu->EnqueueList(listAddress, stallAddress, true);
DEBUG_LOG(HLE, "List %i enqueued.", listID);
//return display list ID
@ -117,6 +102,9 @@ void sceGeListUpdateStallAddr(u32 displayListID, u32 stallAddress)
int sceGeListSync(u32 displayListID, u32 mode) //0 : wait for completion 1:check and return
{
DEBUG_LOG(HLE, "sceGeListSync(dlid=%08x, mode=%08x)", displayListID, mode);
if(mode == 1) {
return gpu->listStatus(displayListID);
}
return 0;
}

View File

@ -1,4 +1,5 @@
set(SRCS
GPUCommon.cpp
GPUState.cpp
Math3D.cpp
GLES/DisplayListInterpreter.cpp

View File

@ -162,9 +162,9 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight)
displayFramebufPtr_(0),
renderWidth_(renderWidth),
renderHeight_(renderHeight),
dlIdGenerator(1),
dumpThisFrame_(false),
dumpNextFrame_(false) {
dumpNextFrame_(false)
{
renderWidthFactor_ = (float)renderWidth / 480.0f;
renderHeightFactor_ = (float)renderHeight / 272.0f;
shaderManager_ = new ShaderManager();
@ -386,16 +386,15 @@ void GLES_GPU::EndDebugDraw() {
// Render queue
bool GLES_GPU::ProcessDLQueue() {
std::vector<DisplayList>::iterator iter = dlQueue.begin();
while (!(iter == dlQueue.end())) {
bool GLES_GPU::ProcessDLQueue()
{
DisplayListQueue::iterator iter = dlQueue.begin();
while (!(iter == dlQueue.end()))
{
DisplayList &l = *iter;
dcontext.pc = l.listpc;
dcontext.stallAddr = l.stall;
// //DEBUG_LOG(G3D,"Okay, starting DL execution at %08 - stall = %08x", context.pc, stallAddr);
if (!InterpretList()) {
l.listpc = dcontext.pc;
l.stall = dcontext.stallAddr;
// DEBUG_LOG(G3D,"Okay, starting DL execution at %08 - stall = %08x", context.pc, stallAddr);
if (!InterpretList(l))
{
return false;
} else {
//At the end, we can remove it from the queue and continue
@ -407,32 +406,8 @@ bool GLES_GPU::ProcessDLQueue() {
return true; //no more lists!
}
u32 GLES_GPU::EnqueueList(u32 listpc, u32 stall) {
DisplayList dl;
dl.id = dlIdGenerator++;
dl.listpc = listpc & 0xFFFFFFF;
dl.stall = stall & 0xFFFFFFF;
dlQueue.push_back(dl);
if (!ProcessDLQueue())
return dl.id;
else
return 0;
}
void GLES_GPU::UpdateStall(int listid, u32 newstall) {
// this needs improvement....
for (std::vector<DisplayList>::iterator iter = dlQueue.begin(); iter != dlQueue.end(); iter++)
{
DisplayList &l = *iter;
if (l.id == listid)
{
l.stall = newstall & 0xFFFFFFF;
}
}
ProcessDLQueue();
}
void GLES_GPU::DrawSync(int mode) {
void GLES_GPU::DrawSync(int mode)
{
transformDraw_.Flush();
}
@ -547,7 +522,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
{
u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF;
if (Memory::IsValidAddress(target)) {
dcontext.pc = target - 4; // pc will be increased after we return, counteract that
currentList->pc = target - 4; // pc will be increased after we return, counteract that
} else {
ERROR_LOG(G3D, "JUMP to illegal address %08x - ignoring??", target);
}
@ -556,21 +531,21 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
case GE_CMD_CALL:
{
u32 retval = dcontext.pc + 4;
u32 retval = currentList->pc + 4;
if (stackptr == ARRAY_SIZE(stack)) {
ERROR_LOG(G3D, "CALL: Stack full!");
} else {
stack[stackptr++] = retval;
u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0xFFFFFFF;
dcontext.pc = target - 4; // pc will be increased after we return, counteract that
currentList->pc = target - 4; // pc will be increased after we return, counteract that
}
}
break;
case GE_CMD_RET:
{
u32 target = (dcontext.pc & 0xF0000000) | (stack[--stackptr] & 0x0FFFFFFF);
dcontext.pc = target - 4;
u32 target = (currentList->pc & 0xF0000000) | (stack[--stackptr] & 0x0FFFFFFF);
currentList->pc = target - 4;
}
break;
@ -590,6 +565,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
switch (prev >> 24) {
case GE_CMD_SIGNAL:
{
currentList->status = PSP_GE_LIST_END_REACHED;
// TODO: see http://code.google.com/p/jpcsp/source/detail?r=2935#
int behaviour = (prev >> 16) & 0xFF;
int signal = prev & 0xFFFF;
@ -624,6 +600,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
}
break;
case GE_CMD_FINISH:
currentList->status = PSP_GE_LIST_DONE;
finished = true;
break;
default:
@ -641,7 +618,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
break;
case GE_CMD_ORIGIN:
gstate.offsetAddr = dcontext.pc & 0xFFFFFF;
gstate.offsetAddr = currentList->pc & 0xFFFFFF;
break;
case GE_CMD_VERTEXTYPE:
@ -1095,13 +1072,14 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
break;
default:
DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, dcontext.pc);
DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, currentList->pc);
break;
}
}
bool GLES_GPU::InterpretList()
bool GLES_GPU::InterpretList(DisplayList &list)
{
currentList = &list;
// Reset stackptr for safety
stackptr = 0;
u32 op = 0;
@ -1109,14 +1087,17 @@ bool GLES_GPU::InterpretList()
finished = false;
while (!finished)
{
if (!Memory::IsValidAddress(dcontext.pc)) {
ERROR_LOG(G3D, "DL PC = %08x WTF!!!!", dcontext.pc);
list.status = PSP_GE_LIST_DRAWING;
if (!Memory::IsValidAddress(list.pc)) {
ERROR_LOG(G3D, "DL PC = %08x WTF!!!!", list.pc);
return true;
}
if (dcontext.pc == dcontext.stallAddr)
if (list.pc == list.stall)
{
list.status = PSP_GE_LIST_STALL_REACHED;
return false;
op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory
}
op = Memory::ReadUnchecked_U32(list.pc); //read from memory
u32 cmd = op >> 24;
u32 diff = op ^ gstate.cmdmem[cmd];
if (flushBeforeCommand_[cmd] == 1 || (diff && flushBeforeCommand_[cmd] == 2))
@ -1124,15 +1105,15 @@ bool GLES_GPU::InterpretList()
// TODO: Add a compiler flag to remove stuff like this at very-final build time.
if (dumpThisFrame_) {
char temp[256];
GeDisassembleOp(dcontext.pc, op, prev, temp);
NOTICE_LOG(G3D, "%08x: %s", dcontext.pc, temp);
GeDisassembleOp(list.pc, op, prev, temp);
NOTICE_LOG(G3D, "%08x: %s", list.pc, temp);
}
gstate.cmdmem[cmd] = op;
ExecuteOp(op, diff);
dcontext.pc += 4;
list.pc += 4;
prev = op;
}
return true;

View File

@ -18,9 +18,9 @@
#pragma once
#include <list>
#include <vector>
#include <deque>
#include "../GPUInterface.h"
#include "../GPUCommon.h"
#include "Framebuffer.h"
#include "VertexDecoder.h"
#include "TransformPipeline.h"
@ -29,16 +29,14 @@
class ShaderManager;
class LinkedShader;
class GLES_GPU : public GPUInterface
class GLES_GPU : public GPUCommon
{
public:
GLES_GPU(int renderWidth, int renderHeight);
~GLES_GPU();
virtual void InitClear();
virtual u32 EnqueueList(u32 listpc, u32 stall);
virtual void UpdateStall(int listid, u32 newstall);
virtual void ExecuteOp(u32 op, u32 diff);
virtual bool InterpretList();
virtual bool InterpretList(DisplayList &list);
virtual void DrawSync(int mode);
virtual void Continue();
virtual void Break();
@ -88,18 +86,6 @@ private:
u32 stallAddr;
};
CmdProcessorState dcontext;
int dlIdGenerator;
struct DisplayList {
int id;
u32 listpc;
u32 stall;
};
std::vector<DisplayList> dlQueue;
u32 prev;
u32 stack[2];
u32 stackptr;

View File

@ -128,6 +128,7 @@
<ClInclude Include="GLES\VertexDecoder.h" />
<ClInclude Include="GLES\VertexShaderGenerator.h" />
<ClInclude Include="GeDisasm.h" />
<ClInclude Include="GPUCommon.h" />
<ClInclude Include="GPUInterface.h" />
<ClInclude Include="GPUState.h" />
<ClInclude Include="Math3D.h" />
@ -147,6 +148,7 @@
</ClCompile>
<ClCompile Include="GLES\VertexShaderGenerator.cpp" />
<ClCompile Include="GeDisasm.cpp" />
<ClCompile Include="GPUCommon.cpp" />
<ClCompile Include="GPUState.cpp" />
<ClCompile Include="Math3D.cpp" />
<ClCompile Include="Null\NullGpu.cpp" />
@ -162,4 +164,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -60,6 +60,10 @@
<ClInclude Include="GLES\IndexGenerator.h">
<Filter>GLES</Filter>
</ClInclude>
<ClInclude Include="GeDisasm.h" />
<ClInclude Include="GPUCommon.h">
<Filter>Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Math3D.cpp">
@ -101,6 +105,10 @@
<ClCompile Include="GLES\IndexGenerator.cpp">
<Filter>GLES</Filter>
</ClCompile>
<ClCompile Include="GeDisasm.cpp" />
<ClCompile Include="GPUCommon.cpp">
<Filter>Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="CMakeLists.txt" />

49
GPU/GPUCommon.cpp Normal file
View File

@ -0,0 +1,49 @@
#include "GPUCommon.h"
static int dlIdGenerator = 1;
void init() {
dlIdGenerator = 1;
}
int GPUCommon::listStatus(int listid)
{
for(DisplayListQueue::iterator it(dlQueue.begin()); it != dlQueue.end(); ++it)
{
if(it->id == listid)
{
return it->status;
}
}
return 0x80000100; // INVALID_ID
}
u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, bool head)
{
DisplayList dl;
dl.id = dlIdGenerator++;
dl.pc = listpc & 0xFFFFFFF;
dl.stall = stall & 0xFFFFFFF;
dl.status = PSP_GE_LIST_QUEUED;
if(head)
dlQueue.push_front(dl);
else
dlQueue.push_back(dl);
ProcessDLQueue();
return dl.id;
}
void GPUCommon::UpdateStall(int listid, u32 newstall)
{
// this needs improvement....
for (DisplayListQueue::iterator iter = dlQueue.begin(); iter != dlQueue.end(); iter++)
{
DisplayList &l = *iter;
if (l.id == listid)
{
l.stall = newstall & 0xFFFFFFF;
}
}
ProcessDLQueue();
}

24
GPU/GPUCommon.h Normal file
View File

@ -0,0 +1,24 @@
#pragma once
#include "GPUInterface.h"
class GPUCommon : public GPUInterface
{
public:
GPUCommon() :
dlIdGenerator(1),
currentList(NULL)
{}
virtual bool ProcessDLQueue() = 0;
virtual void UpdateStall(int listid, u32 newstall);
virtual u32 EnqueueList(u32 listpc, u32 stall, bool head);
virtual int listStatus(int listid);
protected:
typedef std::deque<DisplayList> DisplayListQueue;
int dlIdGenerator;
DisplayList *currentList;
DisplayListQueue dlQueue;
};

View File

@ -18,6 +18,25 @@
#pragma once
#include "../Globals.h"
#include <deque>
enum DisplayListStatus
{
PSP_GE_LIST_DONE = 0, // reached finish+end
PSP_GE_LIST_QUEUED = 1, // in queue, not stalled
PSP_GE_LIST_DRAWING = 2, // drawing
PSP_GE_LIST_STALL_REACHED = 3, // stalled
PSP_GE_LIST_END_REACHED = 4, // reached signal+end, in jpcsp but not in pspsdk?
PSP_GE_LIST_CANCEL_DONE = 5, // canceled?
};
struct DisplayList
{
int id;
u32 pc;
u32 stall;
DisplayListStatus status;
};
class GPUInterface
{
@ -29,13 +48,14 @@ public:
// Draw queue management
// TODO: Much of this should probably be shared between the different GPU implementations.
virtual u32 EnqueueList(u32 listpc, u32 stall) = 0;
virtual u32 EnqueueList(u32 listpc, u32 stall, bool head) = 0;
virtual void UpdateStall(int listid, u32 newstall) = 0;
virtual void DrawSync(int mode) = 0;
virtual void Continue() = 0;
virtual void ExecuteOp(u32 op, u32 diff) = 0;
virtual bool InterpretList() = 0;
virtual bool InterpretList(DisplayList& list) = 0;
virtual int listStatus(int listid) = 0;
// Framebuffer management
virtual void SetDisplayFramebuffer(u32 framebuf, u32 stride, int format) = 0;

View File

@ -95,7 +95,8 @@ void ReapplyGfxState()
for (int i = GE_CMD_VERTEXTYPE; i < GE_CMD_BONEMATRIXNUMBER; i++)
{
gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF);
if(i != GE_CMD_ORIGIN)
gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF);
}
// Can't write to bonematrixnumber here

View File

@ -22,29 +22,11 @@
#include "../../Core/MemMap.h"
#include "../../Core/HLE/sceKernelInterrupt.h"
struct DisplayState
{
u32 pc;
u32 stallAddr;
};
static DisplayState dcontext;
struct DisplayList
{
int id;
u32 listpc;
u32 stall;
};
static std::vector<DisplayList> dlQueue;
static u32 prev;
static u32 stack[2];
static u32 stackptr = 0;
static bool finished;
static int dlIdGenerator = 1;
NullGPU::NullGPU()
{
@ -59,17 +41,13 @@ NullGPU::~NullGPU()
bool NullGPU::ProcessDLQueue()
{
std::vector<DisplayList>::iterator iter = dlQueue.begin();
DisplayListQueue::iterator iter = dlQueue.begin();
while (!(iter == dlQueue.end()))
{
DisplayList &l = *iter;
dcontext.pc = l.listpc;
dcontext.stallAddr = l.stall;
// DEBUG_LOG(G3D,"Okay, starting DL execution at %08 - stall = %08x", context.pc, stallAddr);
if (!InterpretList())
if (!InterpretList(l))
{
l.listpc = dcontext.pc;
l.stall = dcontext.stallAddr;
return false;
}
else
@ -83,34 +61,6 @@ bool NullGPU::ProcessDLQueue()
return true; //no more lists!
}
u32 NullGPU::EnqueueList(u32 listpc, u32 stall)
{
DisplayList dl;
dl.id = dlIdGenerator++;
dl.listpc = listpc&0xFFFFFFF;
dl.stall = stall&0xFFFFFFF;
dlQueue.push_back(dl);
if (!ProcessDLQueue())
return dl.id;
else
return 0;
}
void NullGPU::UpdateStall(int listid, u32 newstall)
{
// this needs improvement....
for (std::vector<DisplayList>::iterator iter = dlQueue.begin(); iter != dlQueue.end(); iter++)
{
DisplayList &l = *iter;
if (l.id == listid)
{
l.stall = newstall & 0xFFFFFFF;
}
}
ProcessDLQueue();
}
void NullGPU::DrawSync(int mode)
{
if (mode == 0) // Wait for completion
@ -187,18 +137,18 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
case GE_CMD_JUMP:
{
u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF;
DEBUG_LOG(G3D,"DL CMD JUMP - %08x to %08x", dcontext.pc, target);
dcontext.pc = target - 4; // pc will be increased after we return, counteract that
DEBUG_LOG(G3D,"DL CMD JUMP - %08x to %08x", currentList->pc, target);
currentList->pc = target - 4; // pc will be increased after we return, counteract that
}
break;
case GE_CMD_CALL:
{
u32 retval = dcontext.pc + 4;
u32 retval = currentList->pc + 4;
stack[stackptr++] = retval;
u32 target = (((gstate.base & 0x00FF0000) << 8) | (op & 0xFFFFFC)) & 0xFFFFFFF;
DEBUG_LOG(G3D,"DL CMD CALL - %08x to %08x, ret=%08x", dcontext.pc, target, retval);
dcontext.pc = target - 4; // pc will be increased after we return, counteract that
DEBUG_LOG(G3D,"DL CMD CALL - %08x to %08x, ret=%08x", currentList->pc, target, retval);
currentList->pc = target - 4; // pc will be increased after we return, counteract that
}
break;
@ -206,8 +156,8 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
//TODO : debug!
{
u32 target = stack[--stackptr] & 0xFFFFFFF;
DEBUG_LOG(G3D,"DL CMD RET - from %08x to %08x", dcontext.pc, target);
dcontext.pc = target - 4;
DEBUG_LOG(G3D,"DL CMD RET - from %08x to %08x", currentList->pc, target);
currentList->pc = target - 4;
}
break;
@ -234,7 +184,7 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
break;
case GE_CMD_ORIGIN:
gstate.offsetAddr = dcontext.pc & 0xFFFFFF;
gstate.offsetAddr = currentList->pc & 0xFFFFFF;
break;
case GE_CMD_VERTEXTYPE:
@ -807,15 +757,16 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
break;
default:
DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, dcontext.pc);
DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, currentList->pc);
break;
//ETC...
}
}
bool NullGPU::InterpretList()
bool NullGPU::InterpretList(DisplayList &list)
{
currentList = &list;
// Reset stackptr for safety
stackptr = 0;
u32 op = 0;
@ -823,17 +774,19 @@ bool NullGPU::InterpretList()
finished = false;
while (!finished)
{
if (dcontext.pc == dcontext.stallAddr)
if (currentList->pc == currentList->stall)
{
currentList->status = PSP_GE_LIST_STALL_REACHED;
return false;
op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory
}
op = Memory::ReadUnchecked_U32(currentList->pc); //read from memory
u32 cmd = op >> 24;
u32 diff = op ^ gstate.cmdmem[cmd];
gstate.cmdmem[cmd] = op; // crashes if I try to put the whole op there??
ExecuteOp(op, diff);
dcontext.pc += 4;
currentList->pc += 4;
prev = op;
}
return true;

View File

@ -17,20 +17,18 @@
#pragma once
#include "../GPUInterface.h"
#include "../GPUCommon.h"
class ShaderManager;
class NullGPU : public GPUInterface
class NullGPU : public GPUCommon
{
public:
NullGPU();
~NullGPU();
virtual void InitClear() {}
virtual u32 EnqueueList(u32 listpc, u32 stall);
virtual void UpdateStall(int listid, u32 newstall);
virtual void ExecuteOp(u32 op, u32 diff);
virtual bool InterpretList();
virtual bool InterpretList(DisplayList &list);
virtual void Continue();
virtual void DrawSync(int mode);
virtual void EnableInterrupts(bool enable) {