mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Actually queue up depth draws
This commit is contained in:
@@ -34,7 +34,6 @@ struct DepthDraw {
|
||||
bool cullEnabled;
|
||||
int cullMode;
|
||||
DepthScissor scissor;
|
||||
bool through;
|
||||
int vertexOffset;
|
||||
int indexOffset;
|
||||
int vertexCount;
|
||||
|
||||
@@ -932,7 +932,7 @@ Mat4F32 ComputeFinalProjMatrix() {
|
||||
return m;
|
||||
}
|
||||
|
||||
static bool CalculateDepthDraw(DepthDraw *draw, GEPrimitiveType prim, int vertexCount) {
|
||||
bool DrawEngineCommon::CalculateDepthDraw(DepthDraw *draw, GEPrimitiveType prim, int vertexCount) {
|
||||
switch (prim) {
|
||||
case GE_PRIM_INVALID:
|
||||
case GE_PRIM_KEEP_PREVIOUS:
|
||||
@@ -978,8 +978,13 @@ static bool CalculateDepthDraw(DepthDraw *draw, GEPrimitiveType prim, int vertex
|
||||
_dbg_assert_(gstate.isDepthWriteEnabled());
|
||||
}
|
||||
|
||||
draw->vertexOffset = 0;
|
||||
draw->indexOffset = 0;
|
||||
if (depthVertexCount_ + vertexCount >= DEPTH_INDEXBUFFER_SIZE) {
|
||||
// Can't add more.
|
||||
return false;
|
||||
}
|
||||
|
||||
draw->vertexOffset = depthVertexCount_;
|
||||
draw->indexOffset = depthIndexCount_;
|
||||
draw->vertexCount = vertexCount;
|
||||
draw->cullEnabled = gstate.isCullEnabled();
|
||||
draw->cullMode = gstate.getCullMode();
|
||||
@@ -1028,8 +1033,11 @@ void DrawEngineCommon::DepthRasterTransform(GEPrimitiveType prim, VertexDecoder
|
||||
// Copy indices.
|
||||
memcpy(depthIndices_ + draw.indexOffset, decIndex_, sizeof(uint16_t) * vertexCount);
|
||||
|
||||
// FUTURE SPLIT --- The above will always run on the main thread. The below can be split across workers.
|
||||
ExecuteDepthDraw(draw);
|
||||
// Commit
|
||||
depthIndexCount_ += vertexCount;
|
||||
depthVertexCount_ += numDec;
|
||||
|
||||
depthDraws_.push_back(draw);
|
||||
}
|
||||
|
||||
void DrawEngineCommon::DepthRasterPredecoded(GEPrimitiveType prim, const void *inVerts, int numDecoded, VertexDecoder *dec, int vertexCount) {
|
||||
@@ -1060,8 +1068,22 @@ void DrawEngineCommon::DepthRasterPredecoded(GEPrimitiveType prim, const void *i
|
||||
// Copy indices.
|
||||
memcpy(depthIndices_ + draw.indexOffset, decIndex_, sizeof(uint16_t) * vertexCount);
|
||||
|
||||
// FUTURE SPLIT --- The above will always run on the main thread. The below can be split across workers.
|
||||
ExecuteDepthDraw(draw);
|
||||
// Commit
|
||||
depthIndexCount_ += vertexCount;
|
||||
depthVertexCount_ += numDecoded;
|
||||
|
||||
depthDraws_.push_back(draw);
|
||||
}
|
||||
|
||||
void DrawEngineCommon::FlushQueuedDepth() {
|
||||
for (const auto &draw : depthDraws_) {
|
||||
ExecuteDepthDraw(draw);
|
||||
}
|
||||
|
||||
// Reset queue
|
||||
depthIndexCount_ = 0;
|
||||
depthVertexCount_ = 0;
|
||||
depthDraws_.clear();
|
||||
}
|
||||
|
||||
void DrawEngineCommon::ExecuteDepthDraw(const DepthDraw &draw) {
|
||||
@@ -1070,12 +1092,16 @@ void DrawEngineCommon::ExecuteDepthDraw(const DepthDraw &draw) {
|
||||
float *tz = (float *)(depthScreenVerts_ + DEPTH_SCREENVERTS_COMPONENT_COUNT * 2);
|
||||
|
||||
int outVertCount = 0;
|
||||
|
||||
const float *vertices = depthTransformed_ + 4 * draw.vertexOffset;
|
||||
const uint16_t *indices = depthIndices_ + draw.indexOffset;
|
||||
|
||||
switch (draw.prim) {
|
||||
case GE_PRIM_RECTANGLES:
|
||||
outVertCount = DepthRasterClipIndexedRectangles(tx, ty, tz, depthTransformed_ + 4 * draw.vertexOffset, depthIndices_ + draw.indexOffset, draw);
|
||||
outVertCount = DepthRasterClipIndexedRectangles(tx, ty, tz, vertices, indices, draw);
|
||||
break;
|
||||
case GE_PRIM_TRIANGLES:
|
||||
outVertCount = DepthRasterClipIndexedTriangles(tx, ty, tz, depthTransformed_ + 4 * draw.vertexOffset, depthIndices_ + draw.indexOffset, draw);
|
||||
outVertCount = DepthRasterClipIndexedTriangles(tx, ty, tz, vertices, indices, draw);
|
||||
break;
|
||||
default:
|
||||
_dbg_assert_(false);
|
||||
|
||||
@@ -164,6 +164,8 @@ public:
|
||||
return decoded_ + 12 * 65536;
|
||||
}
|
||||
|
||||
void FlushQueuedDepth();
|
||||
|
||||
protected:
|
||||
virtual bool UpdateUseHWTessellation(bool enabled) const { return enabled; }
|
||||
void UpdatePlanes();
|
||||
@@ -178,6 +180,7 @@ protected:
|
||||
void DepthRasterTransform(GEPrimitiveType prim, VertexDecoder *dec, uint32_t vertTypeID, int vertexCount);
|
||||
void DepthRasterPredecoded(GEPrimitiveType prim, const void *inVerts, int numDecoded, VertexDecoder *dec, int vertexCount);
|
||||
void ExecuteDepthDraw(const DepthDraw &draw);
|
||||
bool CalculateDepthDraw(DepthDraw *draw, GEPrimitiveType prim, int vertexCount);
|
||||
|
||||
static inline int IndexSize(u32 vtype) {
|
||||
const u32 indexType = (vtype & GE_VTYPE_IDX_MASK);
|
||||
@@ -360,4 +363,9 @@ protected:
|
||||
float *depthTransformed_ = nullptr;
|
||||
int *depthScreenVerts_ = nullptr;
|
||||
uint16_t *depthIndices_ = nullptr;
|
||||
|
||||
// Queue
|
||||
int depthVertexCount_ = 0;
|
||||
int depthIndexCount_ = 0;
|
||||
std::vector<DepthDraw> depthDraws_;
|
||||
};
|
||||
|
||||
@@ -3240,6 +3240,7 @@ void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb,
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::FlushBeforeCopy() {
|
||||
drawEngine_->FlushQueuedDepth();
|
||||
// Flush anything not yet drawn before blitting, downloading, or uploading.
|
||||
// This might be a stalled list, or unflushed before a block transfer, etc.
|
||||
// Only bother if any draws are pending.
|
||||
@@ -3247,7 +3248,8 @@ void FramebufferManagerCommon::FlushBeforeCopy() {
|
||||
// TODO: It's really bad that we are calling SetRenderFramebuffer here with
|
||||
// all the irrelevant state checking it'll use to decide what to do. Should
|
||||
// do something more focused here.
|
||||
SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason);
|
||||
bool changed;
|
||||
SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason, &changed);
|
||||
drawEngine_->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,13 +306,14 @@ public:
|
||||
void DestroyFramebuf(VirtualFramebuffer *v);
|
||||
|
||||
VirtualFramebuffer *DoSetRenderFrameBuffer(FramebufferHeuristicParams ¶ms, u32 skipDrawReason);
|
||||
VirtualFramebuffer *SetRenderFrameBuffer(bool framebufChanged, int skipDrawReason) {
|
||||
VirtualFramebuffer *SetRenderFrameBuffer(bool framebufChanged, int skipDrawReason, bool *changed) {
|
||||
// Inlining this part since it's so frequent.
|
||||
if (!framebufChanged && currentRenderVfb_) {
|
||||
currentRenderVfb_->last_frame_render = gpuStats.numFlips;
|
||||
currentRenderVfb_->dirtyAfterDisplay = true;
|
||||
if (!skipDrawReason)
|
||||
currentRenderVfb_->reallyDirtyAfterDisplay = true;
|
||||
*changed = false;
|
||||
return currentRenderVfb_;
|
||||
} else {
|
||||
// This is so that we will be able to drive DoSetRenderFramebuffer with inputs
|
||||
@@ -322,6 +323,7 @@ public:
|
||||
VirtualFramebuffer *vfb = DoSetRenderFrameBuffer(inputs, skipDrawReason);
|
||||
_dbg_assert_msg_(vfb, "DoSetRenderFramebuffer must return a valid framebuffer.");
|
||||
_dbg_assert_msg_(currentRenderVfb_, "DoSetRenderFramebuffer must set a valid framebuffer.");
|
||||
*changed = true;
|
||||
return vfb;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-2
@@ -1311,8 +1311,10 @@ void GPUCommon::FlushImm() {
|
||||
gstate_c.UpdateUVScaleOffset();
|
||||
|
||||
VirtualFramebuffer *vfb = nullptr;
|
||||
if (framebufferManager_)
|
||||
vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason);
|
||||
if (framebufferManager_) {
|
||||
bool changed;
|
||||
vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason, &changed);
|
||||
}
|
||||
if (vfb) {
|
||||
CheckDepthUsage(vfb);
|
||||
}
|
||||
|
||||
+28
-3
@@ -531,6 +531,7 @@ void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) {
|
||||
}
|
||||
|
||||
void GPUCommonHW::CopyDisplayToOutput(bool reallyDirty) {
|
||||
drawEngineCommon_->FlushQueuedDepth();
|
||||
// Flush anything left over.
|
||||
drawEngineCommon_->Flush();
|
||||
|
||||
@@ -949,11 +950,16 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
}
|
||||
|
||||
// This also makes skipping drawing very effective.
|
||||
VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason);
|
||||
bool changed;
|
||||
VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason, &changed);
|
||||
if (blueToAlpha) {
|
||||
vfb->usageFlags |= FB_USAGE_BLUE_TO_ALPHA;
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
drawEngineCommon_->FlushQueuedDepth();
|
||||
}
|
||||
|
||||
if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) {
|
||||
vertexCost_ = EstimatePerVertexCost();
|
||||
}
|
||||
@@ -1273,7 +1279,11 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) {
|
||||
gstate_c.framebufFormat = gstate.FrameBufFormat();
|
||||
|
||||
// This also make skipping drawing very effective.
|
||||
VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason);
|
||||
bool changed;
|
||||
VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason, &changed);
|
||||
if (changed) {
|
||||
drawEngineCommon_->FlushQueuedDepth();
|
||||
}
|
||||
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
|
||||
// TODO: Should this eat some cycles? Probably yes. Not sure if important.
|
||||
return;
|
||||
@@ -1345,7 +1355,11 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) {
|
||||
gstate_c.framebufFormat = gstate.FrameBufFormat();
|
||||
|
||||
// This also make skipping drawing very effective.
|
||||
VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason);
|
||||
bool changed;
|
||||
VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason, &changed);
|
||||
if (changed) {
|
||||
drawEngineCommon_->FlushQueuedDepth();
|
||||
}
|
||||
if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) {
|
||||
// TODO: Should this eat some cycles? Probably yes. Not sure if important.
|
||||
return;
|
||||
@@ -1415,6 +1429,7 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) {
|
||||
}
|
||||
|
||||
void GPUCommonHW::Execute_BlockTransferStart(u32 op, u32 diff) {
|
||||
drawEngineCommon_->FlushQueuedDepth();
|
||||
Flush();
|
||||
|
||||
PROFILE_THIS_SCOPE("block"); // don't include the flush in the profile, would be misleading.
|
||||
@@ -1763,6 +1778,16 @@ void GPUCommonHW::Execute_TexFlush(u32 op, u32 diff) {
|
||||
framebufferManager_->DiscardFramebufferCopy();
|
||||
}
|
||||
|
||||
u32 GPUCommonHW::DrawSync(int mode) {
|
||||
drawEngineCommon_->FlushQueuedDepth();
|
||||
return GPUCommon::DrawSync(mode);
|
||||
}
|
||||
|
||||
int GPUCommonHW::ListSync(int listid, int mode) {
|
||||
drawEngineCommon_->FlushQueuedDepth();
|
||||
return GPUCommon::ListSync(listid, mode);
|
||||
}
|
||||
|
||||
size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) {
|
||||
float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f;
|
||||
return snprintf(buffer, size,
|
||||
|
||||
@@ -42,6 +42,9 @@ public:
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
|
||||
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
|
||||
|
||||
u32 DrawSync(int mode) override;
|
||||
int ListSync(int listid, int mode) override;
|
||||
|
||||
bool FramebufferDirty() override;
|
||||
bool FramebufferReallyDirty() override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user