mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-12 00:59:41 +01:00
Merge pull request #10186 from hrydgard/immediate-draws
Incomplete implementation of immediate draws through the 0xF0-0xF9 GPU registers.
This commit is contained in:
6 files changed
+137
-40
No files matched your search
+1
-1
@@ -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) {
|
||||
|
||||
+83
-10
@@ -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 @@ public:
|
||||
|
||||
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 @@ protected:
|
||||
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_;
|
||||
|
||||
+14
-3
@@ -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];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user