mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Implement depth clamp (for safe cases) in the software transform pipeline, and make sure triangle culling is always done.
This commit is contained in:
@@ -109,7 +109,7 @@ static bool IsReallyAClear(const TransformedVertex *transformed, int numVerts, f
|
||||
}
|
||||
|
||||
// At the end, this calls ProjectClipAndExpand which will expand rectangles as necessary, or apply culling.
|
||||
void SoftwareTransform::Transform(const float projMtx[16], Lin::Vec3 vpScale, Lin::Vec3 vpOffset, int prim, u32 vertType, const DecVtxFormat &decVtxFormat, int &numDecodedVerts, int vertsSize, int vertexCount, u16 *&inds, int indsSize, SoftwareTransformResult *result) {
|
||||
SoftwareTransformAction SoftwareTransform::Transform(const float projMtx[16], Lin::Vec3 vpScale, Lin::Vec3 vpOffset, int prim, u32 vertType, const DecVtxFormat &decVtxFormat, int &numDecodedVerts, int vertsSize, int vertexCount, u16 *&inds, int indsSize, SoftwareTransformResult *result) {
|
||||
u8 *decoded = params_.decoded;
|
||||
TransformedVertex *transformed = params_.transformed;
|
||||
bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0;
|
||||
@@ -209,9 +209,8 @@ void SoftwareTransform::Transform(const float projMtx[16], Lin::Vec3 vpScale, Li
|
||||
if (!(params_.everUsedEqualDepth && gstate.isClearModeDepthMask() && result->depth > 0.0f && result->depth < 1.0f)) {
|
||||
result->color = transformed[1].color0_32;
|
||||
result->depth = depth;
|
||||
result->action = SW_CLEAR;
|
||||
gpuStats.perFrame.numClears++;
|
||||
return;
|
||||
return SW_CLEAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -363,23 +362,15 @@ void SoftwareTransform::Transform(const float projMtx[16], Lin::Vec3 vpScale, Li
|
||||
fogCoef = (v[2] + fog_end) * fog_slope;
|
||||
|
||||
// Then transform by the projection.
|
||||
float xyzw[4];
|
||||
Vec3ByMatrix44(xyzw, v, projMtx);
|
||||
|
||||
// Here we also need to do the perspective device and apply the viewport.
|
||||
// TODO: Move this to ProjectClipAndExpand.
|
||||
float recip = 1.0f / xyzw[3];
|
||||
Lin::Vec3 xyz = vpOffset + vpScale.scaledBy(Lin::Vec3(xyzw[0] * recip, xyzw[1] * recip, xyzw[2] * recip));
|
||||
transformed[index].x = xyz.x;
|
||||
transformed[index].y = xyz.y;
|
||||
transformed[index].z = xyz.z;
|
||||
transformed[index].pos[3] = xyzw[3];
|
||||
Vec3ByMatrix44(transformed[index].pos, v, projMtx);
|
||||
|
||||
transformed[index].fog = fogCoef;
|
||||
memcpy(&transformed[index].uv, uv, 3 * sizeof(float));
|
||||
transformed[index].color0_32 = c0.ToRGBA();
|
||||
transformed[index].color1_32 = c1.ToRGBA();
|
||||
|
||||
// Projection happens later in ProjectClipAndExpand.
|
||||
|
||||
// Vertex depth rounding is done in the shader, to simulate the 16-bit depth buffer.
|
||||
}
|
||||
}
|
||||
@@ -401,12 +392,28 @@ void SoftwareTransform::Transform(const float projMtx[16], Lin::Vec3 vpScale, Li
|
||||
}
|
||||
}
|
||||
|
||||
_dbg_assert_(result->action == SW_NOT_READY);
|
||||
|
||||
ProjectClipAndExpand(prim, vertexCount, vertType, inds, indsSize, numDecodedVerts, vertsSize, result);
|
||||
return ProjectClipAndExpand(prim, vertexCount, vertType, inds, indsSize, numDecodedVerts, vertsSize, result);
|
||||
}
|
||||
|
||||
void SoftwareTransform::ProjectClipAndExpand(int prim, int vertexCount, u32 vertType, u16 *&inds, int indsSize, int &numDecodedVerts, int vertsSize, SoftwareTransformResult *result) {
|
||||
// Modifies the vertices in-place. Applies viewport and projection.
|
||||
// TODO: SIMD.
|
||||
void SoftwareTransform::ProjectVertices(TransformedVertex *transformed, int vertexCount) {
|
||||
Lin::Vec3 vpOffset(gstate.getViewportXCenter(), gstate.getViewportYCenter(), gstate.getViewportZCenter());
|
||||
Lin::Vec3 vpScale(gstate.getViewportXScale(), gstate.getViewportYScale(), gstate.getViewportZScale());
|
||||
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
// Here we also need to do the perspective device and apply the viewport.
|
||||
// TODO: Move this to ProjectClipAndExpand.
|
||||
const float w = transformed[i].pos_w;
|
||||
const float recip = 1.0f / w;
|
||||
Lin::Vec3 xyz = vpOffset + vpScale.scaledBy(Lin::Vec3(transformed[i].x * recip, transformed[i].y * recip, transformed[i].z * recip));
|
||||
transformed[i].x = xyz.x;
|
||||
transformed[i].y = xyz.y;
|
||||
transformed[i].z = xyz.z;
|
||||
}
|
||||
}
|
||||
|
||||
SoftwareTransformAction SoftwareTransform::ProjectClipAndExpand(int prim, int vertexCount, u32 vertType, u16 *&inds, int indsSize, int &numDecodedVerts, int vertsSize, SoftwareTransformResult *result) {
|
||||
TransformedVertex *transformed = params_.transformed;
|
||||
TransformedVertex *transformedExpanded = params_.transformedExpanded;
|
||||
bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0;
|
||||
@@ -419,10 +426,15 @@ void SoftwareTransform::ProjectClipAndExpand(int prim, int vertexCount, u32 vert
|
||||
bool useBufferedRendering = fbman->UseBufferedRendering();
|
||||
|
||||
if (prim == GE_PRIM_RECTANGLES) {
|
||||
// TODO: We're now able to cull here.
|
||||
if (!throughmode) {
|
||||
ProjectVertices(transformed, numDecodedVerts);
|
||||
}
|
||||
|
||||
if (!ExpandRectangles(vertexCount, numDecodedVerts, vertsSize, inds, indsSize, transformed, transformedExpanded, numTrans, throughmode, &result->pixelMapped)) {
|
||||
result->drawNumTrans = 0;
|
||||
result->pixelMapped = false;
|
||||
return;
|
||||
return SW_CULLED;
|
||||
}
|
||||
result->drawBuffer = transformedExpanded;
|
||||
|
||||
@@ -440,26 +452,71 @@ void SoftwareTransform::ProjectClipAndExpand(int prim, int vertexCount, u32 vert
|
||||
}
|
||||
}
|
||||
} else if (prim == GE_PRIM_POINTS) {
|
||||
if (!throughmode) {
|
||||
ProjectVertices(transformed, numDecodedVerts);
|
||||
}
|
||||
|
||||
result->pixelMapped = false;
|
||||
if (!ExpandPoints(vertexCount, numDecodedVerts, vertsSize, inds, indsSize, transformed, transformedExpanded, numTrans, throughmode)) {
|
||||
result->drawNumTrans = 0;
|
||||
return;
|
||||
return SW_CULLED;
|
||||
}
|
||||
result->drawBuffer = transformedExpanded;
|
||||
} else if (prim == GE_PRIM_LINES) {
|
||||
if (!throughmode) {
|
||||
ProjectVertices(transformed, numDecodedVerts);
|
||||
}
|
||||
|
||||
result->pixelMapped = false;
|
||||
if (!ExpandLines(vertexCount, numDecodedVerts, vertsSize, inds, indsSize, transformed, transformedExpanded, numTrans, throughmode)) {
|
||||
result->drawNumTrans = 0;
|
||||
return;
|
||||
return SW_CULLED;
|
||||
}
|
||||
result->drawBuffer = transformedExpanded;
|
||||
} else {
|
||||
// We can simply draw the unexpanded buffer.
|
||||
} else if (prim == GE_PRIM_TRIANGLES) {
|
||||
// Triangles. We can simply draw the unexpanded buffer, although we do also take the opportunity to perform culling.
|
||||
numTrans = vertexCount;
|
||||
result->pixelMapped = false;
|
||||
|
||||
// If we don't support custom cull in the shader, process it here.
|
||||
if (!gstate_c.Use(GPU_USE_CULL_DISTANCE) && vertexCount > 0 && !throughmode) {
|
||||
if (throughmode) {
|
||||
// Nothing to do, pass the vertices right through as-is. Well, we can go look for pixel mapping, but we don't do any culling or clipping.
|
||||
if (g_Config.bSmart2DTexFiltering && !gstate_c.textureIsVideo) {
|
||||
// We check some common cases for pixel mapping.
|
||||
// TODO: It's not really optimal that some previous step has removed the triangle strip.
|
||||
if (vertexCount <= 6 && prim == GE_PRIM_TRIANGLES) {
|
||||
// It's enough to check UV deltas vs pos deltas between vertex pairs:
|
||||
// 0-1 1-3 3-2 2-0. Maybe can even skip the last one. Probably some simple math can get us that sequence.
|
||||
// Unfortunately we need to reverse the previous UV scaling operation. Fortunately these are powers of two
|
||||
// so the operations are exact.
|
||||
bool pixelMapped = true;
|
||||
const u16 *indsIn = (const u16 *)inds;
|
||||
const float uscale = gstate_c.curTextureWidth;
|
||||
const float vscale = gstate_c.curTextureHeight;
|
||||
for (int t = 0; t < vertexCount; t += 3) {
|
||||
struct { int a; int b; } pairs[] = {{0, 1}, {1, 2}, {2, 0}};
|
||||
for (int i = 0; i < ARRAY_SIZE(pairs); i++) {
|
||||
int a = indsIn[t + pairs[i].a];
|
||||
int b = indsIn[t + pairs[i].b];
|
||||
float du = fabsf((transformed[a].u - transformed[b].u) * uscale);
|
||||
float dv = fabsf((transformed[a].v - transformed[b].v) * vscale);
|
||||
float dx = fabsf(transformed[a].x - transformed[b].x);
|
||||
float dy = fabsf(transformed[a].y - transformed[b].y);
|
||||
if (du != dx || dv != dy) {
|
||||
pixelMapped = false;
|
||||
}
|
||||
}
|
||||
if (!pixelMapped) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
result->pixelMapped = pixelMapped;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Culling and clipping needs to be done here, it doesn't happen in the shader in the case of software transform.
|
||||
// However, fast culling should already have taken care of the Z<-W and Z>W culling, but we check for it on a per-triangle
|
||||
// basis here anyway.
|
||||
|
||||
const u16 *indsIn = (const u16 *)inds;
|
||||
u16 *newInds = inds + vertexCount;
|
||||
u16 *indsOut = newInds;
|
||||
@@ -468,28 +525,34 @@ void SoftwareTransform::ProjectClipAndExpand(int prim, int vertexCount, u32 vert
|
||||
outsideZ.resize(vertexCount);
|
||||
|
||||
// First, check inside/outside directions for each index.
|
||||
// We are still in clip space here, so we can cull aggressively in Z.
|
||||
// TODO: This is so cheap now that we can probably avoid the buffer and just do the work below.
|
||||
for (int i = 0; i < vertexCount; ++i) {
|
||||
float z = truncateToFloat24(transformed[indsIn[i]].z);
|
||||
float z = transformed[indsIn[i]].z;
|
||||
float w = transformed[indsIn[i]].pos_w;
|
||||
if (z > w)
|
||||
if (z > w) {
|
||||
outsideZ[i] = 1;
|
||||
else if (z < -w)
|
||||
} else if (z < -w) {
|
||||
outsideZ[i] = -1;
|
||||
else
|
||||
} else {
|
||||
outsideZ[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Now, for each primitive type, throw away the indices if:
|
||||
// - Depth clamp on, and ALL verts are outside *in the same direction*.
|
||||
// - Depth clamp off, and ANY vert is outside.
|
||||
if (prim == GE_PRIM_TRIANGLES && gstate.isDepthClipEnabled()) {
|
||||
u16 *origInds = inds;
|
||||
|
||||
// TODO: We should either merge the two loops, or avoid the second loop if no culling is needed.
|
||||
|
||||
// Now, for each triangle, throw away the indices if:
|
||||
// - Depth clip/clamp on, and ALL verts are outside *in the same direction*.
|
||||
// - Depth clip/clamp off, and ANY vert is outside.
|
||||
if (gstate.isDepthClipEnabled()) {
|
||||
numTrans = 0;
|
||||
for (int i = 0; i < vertexCount - 2; i += 3) {
|
||||
if (outsideZ[i + 0] != 0 && outsideZ[i + 0] == outsideZ[i + 1] && outsideZ[i + 0] == outsideZ[i + 2]) {
|
||||
// All outside, and all the same direction. Nuke this triangle.
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(indsOut, indsIn + i, 3 * sizeof(uint16_t));
|
||||
indsOut += 3;
|
||||
numTrans += 3;
|
||||
@@ -511,46 +574,47 @@ void SoftwareTransform::ProjectClipAndExpand(int prim, int vertexCount, u32 vert
|
||||
|
||||
inds = newInds;
|
||||
}
|
||||
} else if (throughmode && g_Config.bSmart2DTexFiltering && !gstate_c.textureIsVideo) {
|
||||
// We check some common cases for pixel mapping.
|
||||
// TODO: It's not really optimal that some previous step has removed the triangle strip.
|
||||
if (vertexCount <= 6 && prim == GE_PRIM_TRIANGLES) {
|
||||
// It's enough to check UV deltas vs pos deltas between vertex pairs:
|
||||
// 0-1 1-3 3-2 2-0. Maybe can even skip the last one. Probably some simple math can get us that sequence.
|
||||
// Unfortunately we need to reverse the previous UV scaling operation. Fortunately these are powers of two
|
||||
// so the operations are exact.
|
||||
bool pixelMapped = true;
|
||||
const u16 *indsIn = (const u16 *)inds;
|
||||
const float uscale = gstate_c.curTextureWidth;
|
||||
const float vscale = gstate_c.curTextureHeight;
|
||||
for (int t = 0; t < vertexCount; t += 3) {
|
||||
struct { int a; int b; } pairs[] = { {0, 1}, {1, 2}, {2, 0} };
|
||||
for (int i = 0; i < ARRAY_SIZE(pairs); i++) {
|
||||
int a = indsIn[t + pairs[i].a];
|
||||
int b = indsIn[t + pairs[i].b];
|
||||
float du = fabsf((transformed[a].u - transformed[b].u) * uscale);
|
||||
float dv = fabsf((transformed[a].v - transformed[b].v) * vscale);
|
||||
float dx = fabsf(transformed[a].x - transformed[b].x);
|
||||
float dy = fabsf(transformed[a].y - transformed[b].y);
|
||||
if (du != dx || dv != dy) {
|
||||
pixelMapped = false;
|
||||
}
|
||||
}
|
||||
if (!pixelMapped) {
|
||||
break;
|
||||
|
||||
// Now that we're done culling and generating clipped vertices if needed (not yet implemented), we go ahead and project.
|
||||
ProjectVertices(transformed, numDecodedVerts);
|
||||
|
||||
// Alright! Now, we can clamp the far plane, if the hardware lacks support for doing it for us.
|
||||
// Now, this can only be done exactly if all vertices in a triangle are beyond the far plane. If not
|
||||
// we need to cut it in two parts to clamp accurately. However, in most cases that matter, this is fine.
|
||||
if (!gstate_c.Use(GPU_USE_DEPTH_CLAMP) && gstate.isDepthClipEnabled() && gstate.getDepthRangeMax() == 0xFFFF) {
|
||||
for (int i = 0; i < vertexCount - 2; i += 3) {
|
||||
bool v0InFront = transformed[indsIn[i]].z < 0.0f;
|
||||
bool v1InFront = transformed[indsIn[i + 1]].z < 0.0f;
|
||||
bool v2InFront = transformed[indsIn[i + 2]].z < 0.0f;
|
||||
|
||||
bool v0Beyond = transformed[indsIn[i]].z >= 65535.0f;
|
||||
bool v1Beyond = transformed[indsIn[i + 1]].z >= 65535.0f;
|
||||
bool v2Beyond = transformed[indsIn[i + 2]].z >= 65535.0f;
|
||||
|
||||
// Clamp the Z when we detect it's safe to do so.
|
||||
// Fixes the sky problem in Shadow of Destiny (#9545)
|
||||
if (v0Beyond && v1Beyond && v2Beyond) {
|
||||
transformed[indsIn[i]].z = 65535.0f;
|
||||
transformed[indsIn[i + 1]].z = 65535.0f;
|
||||
transformed[indsIn[i + 2]].z = 65535.0f;
|
||||
} else if (v0InFront && v1InFront && v2InFront) {
|
||||
transformed[indsIn[i]].z = 0.0f;
|
||||
transformed[indsIn[i + 1]].z = 0.0f;
|
||||
transformed[indsIn[i + 2]].z = 0.0f;
|
||||
}
|
||||
}
|
||||
result->pixelMapped = pixelMapped;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_dbg_assert_(false);
|
||||
}
|
||||
|
||||
if (gstate.isModeClear()) {
|
||||
gpuStats.perFrame.numClears++;
|
||||
}
|
||||
|
||||
result->action = SW_DRAW_INDEXED;
|
||||
result->drawNumTrans = numTrans;
|
||||
return SW_DRAW_INDEXED;
|
||||
}
|
||||
|
||||
bool SoftwareTransform::ExpandRectangles(int vertexCount, int &numDecodedVerts, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int &numTrans, bool throughmode, bool *pixelMappedExactly) const {
|
||||
|
||||
@@ -28,13 +28,12 @@ class FramebufferManagerCommon;
|
||||
class TextureCacheCommon;
|
||||
|
||||
enum SoftwareTransformAction {
|
||||
SW_NOT_READY,
|
||||
SW_DRAW_INDEXED,
|
||||
SW_CLEAR,
|
||||
SW_CULLED, // don't draw
|
||||
};
|
||||
|
||||
struct SoftwareTransformResult {
|
||||
SoftwareTransformAction action;
|
||||
u32 color;
|
||||
float depth;
|
||||
|
||||
@@ -71,11 +70,13 @@ public:
|
||||
SoftwareTransform(SoftwareTransformParams ¶ms) : params_(params) {}
|
||||
|
||||
// indsSize is in indices, not bytes.
|
||||
void Transform(const float projMtx[16], Lin::Vec3 vpScale, Lin::Vec3 vpOffset, int prim, u32 vertexType, const DecVtxFormat &decVtxFormat, int &numDecodedVerts, int vertsSize, int vertexCount, u16 *&inds, int indsSize, SoftwareTransformResult *result);
|
||||
SoftwareTransformAction Transform(const float projMtx[16], Lin::Vec3 vpScale, Lin::Vec3 vpOffset, int prim, u32 vertexType, const DecVtxFormat &decVtxFormat, int &numDecodedVerts, int vertsSize, int vertexCount, u16 *&inds, int indsSize, SoftwareTransformResult *result);
|
||||
|
||||
protected:
|
||||
// NOTE: The viewport must be up to date!
|
||||
void ProjectClipAndExpand(int prim, int vertexCount, u32 vertType, u16 *&inds, int indsSize, int &numDecodedVerts, int vertsSize, SoftwareTransformResult *result);
|
||||
SoftwareTransformAction ProjectClipAndExpand(int prim, int vertexCount, u32 vertType, u16 *&inds, int indsSize, int &numDecodedVerts, int vertsSize, SoftwareTransformResult *result);
|
||||
|
||||
static void ProjectVertices(TransformedVertex *transformed, int vertexCount);
|
||||
bool ExpandRectangles(int vertexCount, int &numDecodedVerts, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int &numTrans, bool throughmode, bool *pixelMappedExactly) const;
|
||||
static bool ExpandLines(int vertexCount, int &numDecodedVerts, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int &numTrans, bool throughmode) ;
|
||||
static bool ExpandPoints(int vertexCount, int &numDecodedVerts, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int &numTrans, bool throughmode) ;
|
||||
|
||||
@@ -423,7 +423,7 @@ void DrawEngineD3D11::Flush() {
|
||||
params.allowSeparateAlphaClear = false; // D3D11 doesn't support separate alpha clears
|
||||
|
||||
SoftwareTransform swTransform(params);
|
||||
swTransform.Transform(gstate.projMatrix, gstate.getViewportScale(), gstate.getViewportOffset(), prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, VERTEX_BUFFER_MAX, vertexCount, inds, RemainingIndices(inds), &result);
|
||||
const SoftwareTransformAction action = swTransform.Transform(gstate.projMatrix, gstate.getViewportScale(), gstate.getViewportOffset(), prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, VERTEX_BUFFER_MAX, vertexCount, inds, RemainingIndices(inds), &result);
|
||||
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
@@ -439,7 +439,7 @@ void DrawEngineD3D11::Flush() {
|
||||
ApplyDrawState(prim);
|
||||
ApplyDrawStateLate(result.setStencil, result.stencilValue);
|
||||
|
||||
if (result.action == SW_DRAW_INDEXED) {
|
||||
if (action == SW_DRAW_INDEXED) {
|
||||
D3D11VertexShader *vshader;
|
||||
D3D11FragmentShader *fshader;
|
||||
shaderManager_->GetShaders(prim, swDec->VertexType(), &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true);
|
||||
@@ -474,7 +474,7 @@ void DrawEngineD3D11::Flush() {
|
||||
pushInds_->EndPush(context_);
|
||||
context_->IASetIndexBuffer(pushInds_->Buf(), DXGI_FORMAT_R16_UINT, iOffset);
|
||||
context_->DrawIndexed(result.drawNumTrans, 0, 0);
|
||||
} else if (result.action == SW_CLEAR) {
|
||||
} else if (action == SW_CLEAR) {
|
||||
u32 clearColor = result.color;
|
||||
float clearDepth = result.depth;
|
||||
|
||||
|
||||
@@ -371,7 +371,7 @@ void DrawEngineGLES::Flush() {
|
||||
params.allowSeparateAlphaClear = true;
|
||||
|
||||
SoftwareTransform swTransform(params);
|
||||
swTransform.Transform(gstate.projMatrix, gstate.getViewportScale(), gstate.getViewportOffset(), prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, VERTEX_BUFFER_MAX, vertexCount, inds, RemainingIndices(inds), &result);
|
||||
const SoftwareTransformAction action = swTransform.Transform(gstate.projMatrix, gstate.getViewportScale(), gstate.getViewportOffset(), prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, VERTEX_BUFFER_MAX, vertexCount, inds, RemainingIndices(inds), &result);
|
||||
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
@@ -396,13 +396,13 @@ void DrawEngineGLES::Flush() {
|
||||
goto bail;
|
||||
}
|
||||
|
||||
if (result.action == SW_DRAW_INDEXED) {
|
||||
if (action == SW_DRAW_INDEXED) {
|
||||
vertexBufferOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, numDecodedVerts_ * sizeof(TransformedVertex), 4, &vertexBuffer);
|
||||
indexBufferOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(uint16_t) * result.drawNumTrans, 2, &indexBuffer);
|
||||
render_->DrawIndexed(
|
||||
softwareInputLayout_, vertexBuffer, vertexBufferOffset, indexBuffer, indexBufferOffset,
|
||||
glprim[prim], result.drawNumTrans, GL_UNSIGNED_SHORT);
|
||||
} else if (result.action == SW_CLEAR) {
|
||||
} else if (action == SW_CLEAR) {
|
||||
u32 clearColor = result.color;
|
||||
float clearDepth = result.depth;
|
||||
|
||||
|
||||
+2
-2
@@ -585,11 +585,11 @@ u32 GPUCommonHW::CheckGPUFeatures() const {
|
||||
features |= GPU_USE_BLEND_MINMAX;
|
||||
}
|
||||
|
||||
if (draw_->GetDeviceCaps().maxClipDistances >= 3) {
|
||||
if (draw_->GetDeviceCaps().maxClipDistances >= 3 && g_Config.bHardwareTransform) {
|
||||
features |= GPU_USE_CLIP_DISTANCE;
|
||||
}
|
||||
|
||||
if (draw_->GetDeviceCaps().maxCullDistances >= 1) {
|
||||
if (draw_->GetDeviceCaps().maxCullDistances >= 1 && g_Config.bHardwareTransform) {
|
||||
features |= GPU_USE_CULL_DISTANCE;
|
||||
}
|
||||
|
||||
|
||||
@@ -433,14 +433,14 @@ void DrawEngineVulkan::Flush() {
|
||||
params.everUsedEqualDepth = everUsedEqualDepth_;
|
||||
|
||||
SoftwareTransform swTransform(params);
|
||||
swTransform.Transform(gstate.projMatrix, gstate.getViewportScale(), gstate.getViewportOffset(), prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, VERTEX_BUFFER_MAX, vertexCount, inds, RemainingIndices(inds), &result);
|
||||
const SoftwareTransformAction action = swTransform.Transform(gstate.projMatrix, gstate.getViewportScale(), gstate.getViewportOffset(), prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, VERTEX_BUFFER_MAX, vertexCount, inds, RemainingIndices(inds), &result);
|
||||
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
|
||||
// Only here, where we know whether to clear or to draw primitives, should we actually set the current framebuffer! Because that gives use the opportunity
|
||||
// to use a "pre-clear" render pass, for high efficiency on tilers.
|
||||
if (result.action == SW_DRAW_INDEXED) {
|
||||
if (action == SW_DRAW_INDEXED) {
|
||||
if (textureNeedsApply) {
|
||||
gstate_c.pixelMapped = result.pixelMapped;
|
||||
gstate_c.dstSquared = false;
|
||||
@@ -528,7 +528,7 @@ void DrawEngineVulkan::Flush() {
|
||||
u32 vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, numDecodedVerts_ * sizeof(TransformedVertex), 4, &vbuf);
|
||||
u32 ibOffset = (uint32_t)pushIndex_->Push(inds, sizeof(short) * result.drawNumTrans, 4, &ibuf);
|
||||
renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1);
|
||||
} else if (result.action == SW_CLEAR) {
|
||||
} else if (action == SW_CLEAR) {
|
||||
// Note: we won't get here if the clear is alpha but not color, or color but not alpha.
|
||||
bool clearColor = gstate.isClearModeColorMask();
|
||||
bool clearAlpha = gstate.isClearModeAlphaMask(); // and stencil
|
||||
|
||||
Reference in New Issue
Block a user