Permalink
Browse files

Merge pull request #10186 from hrydgard/immediate-draws

Incomplete implementation of immediate draws through the 0xF0-0xF9 GPU registers.
  • Loading branch information...
unknownbrackets committed Nov 25, 2017
2 parents ce81826 + 89f0ffc commit 5655b799a58a67ff681b8631474c156444c67c8a
Showing with 137 additions and 40 deletions.
  1. +1 −1 Core/HLE/sceIo.cpp
  2. +2 −2 Core/HLE/scePower.cpp
  3. +2 −24 GPU/Common/VertexDecoderCommon.h
  4. +83 −10 GPU/GPUCommon.cpp
  5. +35 −0 GPU/GPUCommon.h
  6. +14 −3 GPU/GPUState.h
@@ -2330,7 +2330,7 @@ static int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr,
case 0x01020004:
// TODO: Should not work for umd0:/, ms0:/, etc.
// TODO: Should probably move this to something common between ISOFileSystem and VirtualDiscSystem.
INFO_LOG(SCEIO, "sceIoIoctl: Asked for file offset of file %i", id);
DEBUG_LOG(SCEIO, "sceIoIoctl: Asked for file offset of file %d", id);
if (Memory::IsValidAddress(outdataPtr) && outlen >= 4) {
u32 offset = (u32)pspFileSystem.GetSeekPos(f->handle);
Memory::Write_U32(offset, outdataPtr);
@@ -431,7 +431,7 @@ static u32 scePowerSetBusClockFrequency(u32 busfreq) {
static u32 scePowerGetCpuClockFrequencyInt() {
int cpuFreq = CoreTiming::GetClockFrequencyMHz();
INFO_LOG(HLE,"%i=scePowerGetCpuClockFrequencyInt()", cpuFreq);
DEBUG_LOG(HLE,"%i=scePowerGetCpuClockFrequencyInt()", cpuFreq);
return cpuFreq;
}
@@ -447,7 +447,7 @@ static u32 scePowerGetBusClockFrequencyInt() {
static float scePowerGetCpuClockFrequencyFloat() {
int cpuFreq = CoreTiming::GetClockFrequencyMHz();
INFO_LOG(HLE, "%f=scePowerGetCpuClockFrequencyFloat()", (float)cpuFreq);
DEBUG_LOG(HLE, "%f=scePowerGetCpuClockFrequencyFloat()", (float)cpuFreq);
return (float) cpuFreq;
}
@@ -26,6 +26,8 @@
#include "Core/Reporting.h"
#include "GPU/ge_constants.h"
#include "GPU/Common/ShaderCommon.h"
#include "GPU/GPUCommon.h"
#if PPSSPP_ARCH(ARM)
#include "Common/ArmEmitter.h"
#elif PPSSPP_ARCH(ARM64)
@@ -78,30 +80,6 @@ struct DecVtxFormat {
void ComputeID();
};
struct TransformedVertex
{
union {
struct {
float x, y, z, fog; // in case of morph, preblend during decode
};
float pos[4];
};
union {
struct {
float u; float v; float w; // scaled by uscale, vscale, if there
};
float uv[3];
};
union {
u8 color0[4]; // prelit
u32 color0_32;
};
union {
u8 color1[4]; // prelit
u32 color1_32;
};
};
void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBound, u16 *indexUpperBound);
inline int RoundUp4(int x) {
@@ -303,16 +303,16 @@ const CommonCommandTableEntry commonCommandTable[] = {
{ GE_CMD_BONEMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_BoneMtxData },
// Vertex Screen/Texture/Color
{ GE_CMD_VSCX, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VSCY, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VSCZ, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VTCS, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VTCT, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VTCQ, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VCV, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VAP, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VFC, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VSCV, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
{ GE_CMD_VSCX },
{ GE_CMD_VSCY },
{ GE_CMD_VSCZ },
{ GE_CMD_VTCS },
{ GE_CMD_VTCT },
{ GE_CMD_VTCQ },
{ GE_CMD_VCV },
{ GE_CMD_VAP, FLAG_EXECUTE, 0, &GPUCommon::Execute_ImmVertexAlphaPrim },
{ GE_CMD_VFC },
{ GE_CMD_VSCV },
// "Missing" commands (gaps in the sequence)
{ GE_CMD_UNKNOWN_03, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown },
@@ -1808,6 +1808,79 @@ void GPUCommon::Execute_MorphWeight(u32 op, u32 diff) {
gstate_c.morphWeights[(op >> 24) - GE_CMD_MORPHWEIGHT0] = getFloat24(op);
}
void GPUCommon::Execute_ImmVertexAlphaPrim(u32 op, u32 diff) {
// Safety check.
if (immCount_ >= MAX_IMMBUFFER_SIZE) {
// Only print once for each overrun.
if (immCount_ == MAX_IMMBUFFER_SIZE) {
ERROR_LOG_REPORT_ONCE(exceed_imm_buffer, G3D, "Exceeded immediate draw buffer size");
}
if (immCount_ < 0x7fffffff) // Paranoia :)
immCount_++;
return;
}
uint32_t data = op & 0xFFFFFF;
TransformedVertex &v = immBuffer_[immCount_++];
// Formula deduced from ThrillVille's clear.
int offsetX = gstate.getOffsetX16();
int offsetY = gstate.getOffsetY16();
v.x = ((gstate.imm_vscx & 0xFFFFFF) - offsetX) / 16.0f;
v.y = ((gstate.imm_vscy & 0xFFFFFF) - offsetY) / 16.0f;
v.z = gstate.imm_vscz & 0xFFFF;
v.u = getFloat24(gstate.imm_vtcs);
v.v = getFloat24(gstate.imm_vtct);
v.w = getFloat24(gstate.imm_vtcq);
v.color0_32 = (gstate.imm_cv & 0xFFFFFF) | (gstate.imm_ap << 24);
v.fog = 0.0f; // we have no information about the scale here
v.color1_32 = gstate.imm_scv & 0xFFFFFF;
int prim = (op >> 8) & 0x7;
if (prim != GE_PRIM_KEEP_PREVIOUS) {
immPrim_ = (GEPrimitiveType)prim;
} else if (prim == GE_PRIM_KEEP_PREVIOUS && immCount_ == 2) {
// Instead of finding a proper point to flush, we just emit a full rectangle every time one
// is finished.
FlushImm();
} else {
ERROR_LOG_REPORT_ONCE(imm_draw_prim, G3D, "Immediate draw: Unexpected primitive %d at count %d", prim, immCount_);
}
}
void GPUCommon::FlushImm() {
SetDrawType(DRAW_PRIM, immPrim_);
framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason);
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
// No idea how many cycles to skip, heh.
return;
}
UpdateUVScaleOffset();
// Instead of plumbing through properly (we'd need to inject these pretransformed vertices in the middle
// of SoftwareTransform(), which would take a lot of refactoring), we'll cheat and just turn these into
// through vertices.
// Since the only known use is Thrillville and it only uses it to clear, we just use color and pos.
struct ImmVertex {
uint32_t color;
float xyz[3];
};
ImmVertex temp[MAX_IMMBUFFER_SIZE];
for (int i = 0; i < immCount_; i++) {
temp[i].color = immBuffer_[i].color0_32;
temp[i].xyz[0] = immBuffer_[i].pos[0];
temp[i].xyz[1] = immBuffer_[i].pos[1];
temp[i].xyz[2] = immBuffer_[i].pos[2];
}
int vtype = GE_VTYPE_POS_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_THROUGH;
int bytesRead;
drawEngineCommon_->DispatchSubmitPrim(temp, nullptr, immPrim_, immCount_, vtype, &bytesRead);
drawEngineCommon_->DispatchFlush();
// TOOD: In the future, make a special path for these.
// drawEngineCommon_->DispatchSubmitImm(immBuffer_, immCount_);
immCount_ = 0;
}
void GPUCommon::ExecuteOp(u32 op, u32 diff) {
const u32 cmd = op >> 24;
@@ -39,6 +39,29 @@ enum {
FLAG_DIRTYONCHANGE = 64, // NOTE: Either this or FLAG_EXECUTE*, not both!
};
struct TransformedVertex {
union {
struct {
float x, y, z, fog; // in case of morph, preblend during decode
};
float pos[4];
};
union {
struct {
float u; float v; float w; // scaled by uscale, vscale, if there
};
float uv[3];
};
union {
u8 color0[4]; // prelit
u32 color0_32;
};
union {
u8 color1[4]; // prelit
u32 color1_32;
};
};
class GPUCommon : public GPUInterface, public GPUDebugInterface {
public:
GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
@@ -124,6 +147,8 @@ class GPUCommon : public GPUInterface, public GPUDebugInterface {
void Execute_MorphWeight(u32 op, u32 diff);
void Execute_ImmVertexAlphaPrim(u32 op, u32 diff);
void Execute_Unknown(u32 op, u32 diff);
int EstimatePerVertexCost();
@@ -291,7 +316,17 @@ class GPUCommon : public GPUInterface, public GPUDebugInterface {
DrawType lastDraw_;
GEPrimitiveType lastPrim_;
// No idea how big this buffer needs to be.
enum {
MAX_IMMBUFFER_SIZE = 32,
};
TransformedVertex immBuffer_[MAX_IMMBUFFER_SIZE];
int immCount_ = 0;
GEPrimitiveType immPrim_;
private:
void FlushImm();
// Debug stats.
double timeSteppingStarted_;
double timeSpentStepping_;
@@ -185,9 +185,20 @@ struct GPUgstate {
transfersrcpos,
transferdstpos,
pad99,
transfersize; // 0xEE
u32 pad05[0xFF- 0xEE];
transfersize, // 0xEE
pad100, // 0xEF
imm_vscx, // 0xF0
imm_vscy,
imm_vscz,
imm_vtcs,
imm_vtct,
imm_vtcq,
imm_cv,
imm_ap,
imm_fc,
imm_scv; // 0xF9
// In the unlikely case we ever add anything else here, don't forget to update the padding on the next line!
u32 pad05[0xFF- 0xF9];
};
};

0 comments on commit 5655b79

Please sign in to comment.