Use draws for alpha/stencil only clear in Vulkan.

This commit is contained in:
Unknown W. Brackets 2016-03-12 13:37:08 -08:00 committed by Henrik Rydgard
parent ba7deb7c9a
commit 8efbcf8d42
5 changed files with 64 additions and 17 deletions

View File

@ -129,8 +129,14 @@ static bool IsReallyAClear(const TransformedVertex *transformed, int numVerts) {
}
void SoftwareTransform(
int prim, u8 *decoded, int vertexCount, u32 vertType, u16 *&inds, int indexType,
const DecVtxFormat &decVtxFormat, int &maxIndex, FramebufferManagerCommon *fbman, TextureCacheCommon *texCache, TransformedVertex *transformed, TransformedVertex *transformedExpanded, TransformedVertex *&drawBuffer, int &numTrans, bool &drawIndexed, SoftwareTransformResult *result, float ySign) {
int prim, int vertexCount, u32 vertType, u16 *&inds, int indexType,
const DecVtxFormat &decVtxFormat, int &maxIndex, TransformedVertex *&drawBuffer, int &numTrans, bool &drawIndexed, const SoftwareTransformParams *params, SoftwareTransformResult *result) {
u8 *decoded = params->decoded;
FramebufferManagerCommon *fbman = params->fbman;
TextureCacheCommon *texCache = params->texCache;
TransformedVertex *transformed = params->transformed;
TransformedVertex *transformedExpanded = params->transformedExpanded;
float ySign = 1.0f;
bool throughmode = (vertType & GE_VTYPE_THROUGH_MASK) != 0;
bool lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
@ -406,11 +412,14 @@ void SoftwareTransform(
// Experiment: Disable on PowerVR (see issue #6290)
// TODO: This bleeds outside the play area in non-buffered mode. Big deal? Probably not.
if (maxIndex > 1 && gstate.isModeClear() && prim == GE_PRIM_RECTANGLES && IsReallyAClear(transformed, maxIndex) && gl_extensions.gpuVendor != GPU_VENDOR_POWERVR) { // && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) {
result->color = transformed[1].color0_32;
// Need to rescale from a [0, 1] float. This is the final transformed value.
result->depth = ToScaledDepth((s16)(int)(transformed[1].z * 65535.0f));
result->action = SW_CLEAR;
return;
bool separateAlphaClear = gstate.isClearModeColorMask() != gstate.isClearModeAlphaMask();
if (params->allowSeparateAlphaClear || !separateAlphaClear) {
result->color = transformed[1].color0_32;
// Need to rescale from a [0, 1] float. This is the final transformed value.
result->depth = ToScaledDepth((s16)(int)(transformed[1].z * 65535.0f));
result->action = SW_CLEAR;
return;
}
}
// This means we're using a framebuffer (and one that isn't big enough.)

View File

@ -38,5 +38,14 @@ struct SoftwareTransformResult {
u8 stencilValue;
};
void SoftwareTransform(int prim, u8 *decoded, int vertexCount, u32 vertexType, u16 *&inds, int indexType, const DecVtxFormat &decVtxFormat, int &maxIndex, FramebufferManagerCommon *fbman, TextureCacheCommon *texCache, TransformedVertex *transformed, TransformedVertex *transformedExpanded, TransformedVertex *&drawBuffer,
int &numTrans, bool &drawIndexed, SoftwareTransformResult *result, float ySign);
struct SoftwareTransformParams {
u8 *decoded;
TransformedVertex *transformed;
TransformedVertex *transformedExpanded;
FramebufferManagerCommon *fbman;
TextureCacheCommon *texCache;
bool allowSeparateAlphaClear;
};
void SoftwareTransform(int prim, int vertexCount, u32 vertexType, u16 *&inds, int indexType, const DecVtxFormat &decVtxFormat, int &maxIndex, TransformedVertex *&drawBuffer,
int &numTrans, bool &drawIndexed, const SoftwareTransformParams *params, SoftwareTransformResult *result);

View File

@ -828,11 +828,20 @@ rotateVBO:
SoftwareTransformResult result;
memset(&result, 0, sizeof(result));
SoftwareTransformParams params;
memset(&params, 0, sizeof(params));
params.decoded = decoded;
params.transformed = transformed;
params.transformedExpanded = transformedExpanded;
params.fbman = framebufferManager_;
params.texCache = textureCache_;
params.allowSeparateAlphaClear = true;
int maxIndex = indexGen.MaxIndex();
SoftwareTransform(
prim, decoded, indexGen.VertexCount(),
prim, indexGen.VertexCount(),
dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(),
maxIndex, framebufferManager_, textureCache_, transformed, transformedExpanded, drawBuffer, numTrans, drawIndexed, &result, 1.0f);
maxIndex, drawBuffer, numTrans, drawIndexed, &params, &result);
ApplyDrawStateLate();
vshader = shaderManager_->ApplyShader(prim, lastVType_);

View File

@ -890,11 +890,21 @@ rotateVBO:
SoftwareTransformResult result;
memset(&result, 0, sizeof(result));
// TODO: Keep this static? Faster than repopulating?
SoftwareTransformParams params;
memset(&params, 0, sizeof(params));
params.decoded = decoded;
params.transformed = transformed;
params.transformedExpanded = transformedExpanded;
params.fbman = framebufferManager_;
params.texCache = textureCache_;
params.allowSeparateAlphaClear = true;
int maxIndex = indexGen.MaxIndex();
SoftwareTransform(
prim, decoded, indexGen.VertexCount(),
prim, indexGen.VertexCount(),
dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(),
maxIndex, framebufferManager_, textureCache_, transformed, transformedExpanded, drawBuffer, numTrans, drawIndexed, &result, 1.0);
maxIndex, drawBuffer, numTrans, drawIndexed, &params, &result);
ApplyDrawStateLate();
LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim);

View File

@ -591,11 +591,20 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
SoftwareTransformResult result;
memset(&result, 0, sizeof(result));
SoftwareTransformParams params;
memset(&params, 0, sizeof(params));
params.decoded = decoded;
params.transformed = transformed;
params.transformedExpanded = transformedExpanded;
params.fbman = framebufferManager_;
params.texCache = textureCache_;
params.allowSeparateAlphaClear = false;
int maxIndex = indexGen.MaxIndex();
SoftwareTransform(
prim, decoded, indexGen.VertexCount(),
prim, indexGen.VertexCount(),
dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(),
maxIndex, framebufferManager_, textureCache_, transformed, transformedExpanded, drawBuffer, numTrans, drawIndexed, &result, 1.0f);
maxIndex, drawBuffer, numTrans, drawIndexed, &params, &result);
// 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.
@ -657,8 +666,9 @@ void DrawEngineVulkan::DoFlush(VkCommandBuffer cmd) {
vkCmdDraw(cmd_, numTrans, 1, 0, 0);
}
} else if (result.action == SW_CLEAR) {
// TODO: Support clearing only color and not alpha, or vice versa. This is not supported (probably for good reason) by vkCmdClearColorAttachment
// so we will have to simply draw a rectangle instead.
// Note: we won't get here if the clear is alpha but not color, or color but not alpha.
// A rectangle will be used instead.
// TODO: If this is the first clear in a frame, translate to a cleared attachment load instead.
int mask = gstate.isClearModeColorMask() ? 1 : 0;
if (gstate.isClearModeAlphaMask()) mask |= 2;