More work on detangling the concepts and making things make more sense.

This commit is contained in:
Henrik Rydgård 2020-11-08 13:14:23 +01:00
parent 3d289594f9
commit 391b8155c5
9 changed files with 32 additions and 69 deletions

View File

@ -480,8 +480,9 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr,
return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH));
}
bool DrawEngineCommon::ApplyShaderBlending() {
bool DrawEngineCommon::ApplyFramebufferRead(bool *fboTexNeedsBind) {
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
*fboTexNeedsBind = false;
return true;
}
@ -502,7 +503,7 @@ bool DrawEngineCommon::ApplyShaderBlending() {
return false;
}
fboTexNeedBind_ = true;
*fboTexNeedsBind = true;
gstate_c.Dirty(DIRTY_SHADERBLEND);
return true;

View File

@ -112,7 +112,7 @@ protected:
// Vertex decoding
void DecodeVertsStep(u8 *dest, int &i, int &decodedVerts);
bool ApplyShaderBlending();
bool ApplyFramebufferRead(bool *fboTexNeedsBind);
inline int IndexSize(u32 vtype) const {
const u32 indexType = (vtype & GE_VTYPE_IDX_MASK);
@ -169,7 +169,7 @@ protected:
GEPrimitiveType prevPrim_ = GE_PRIM_INVALID;
// Shader blending state
bool fboTexNeedBind_ = false;
bool fboTexNeedsBind_ = false;
bool fboTexBound_ = false;
// Hardware tessellation

View File

@ -159,13 +159,14 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
GenericBlendState blendState;
ConvertBlendState(blendState, gstate_c.allowFramebufferRead);
if (blendState.applyFramebufferRead) {
if (ApplyShaderBlending()) {
if (ApplyFramebufferRead(&fboTexNeedsBind_)) {
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState);
} else {
// Until next time, force it off.
ResetFramebufferRead();
gstate_c.SetAllowFramebufferRead(false);
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
} else if (blendState.resetFramebufferRead) {
ResetFramebufferRead();
@ -446,11 +447,11 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
void DrawEngineD3D11::ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRef) {
if (!gstate.isModeClear()) {
if (fboTexNeedBind_) {
if (fboTexNeedsBind_) {
framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY);
// No sampler required, we do a plain Load in the pixel shader.
fboTexBound_ = true;
fboTexNeedBind_ = false;
fboTexNeedsBind_ = false;
}
textureCache_->ApplyTexture();
}

View File

@ -150,7 +150,7 @@ private:
void ApplyDrawState(int prim);
void ApplyDrawStateLate();
void ResetShaderBlending();
void ResetFramebufferRead();
IDirect3DVertexDeclaration9 *SetupDecFmtForDraw(VSShader *vshader, const DecVtxFormat &decFmt, u32 pspFmt);

View File

@ -90,7 +90,7 @@ static const D3DSTENCILOP stencilOps[] = {
D3DSTENCILOP_KEEP, // reserved
};
inline void DrawEngineDX9::ResetShaderBlending() {
inline void DrawEngineDX9::ResetFramebufferRead() {
if (fboTexBound_) {
device_->SetTexture(1, nullptr);
fboTexBound_ = false;
@ -130,16 +130,17 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
ConvertBlendState(blendState, gstate_c.allowFramebufferRead);
if (blendState.applyFramebufferRead) {
if (ApplyShaderBlending()) {
if (ApplyFramebufferRead(&fboTexNeedsBind_)) {
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState);
} else {
// Until next time, force it off.
ResetShaderBlending();
ResetFramebufferRead();
gstate_c.SetAllowFramebufferRead(false);
}
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetShaderBlending();
ResetFramebufferRead();
}
if (blendState.enabled) {
@ -166,20 +167,6 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
bool bmask = ((gstate.pmskc >> 16) & 0xFF) < 128;
bool amask = (gstate.pmska & 0xFF) < 128;
#ifndef MOBILE_DEVICE
u8 abits = (gstate.pmska >> 0) & 0xFF;
u8 rbits = (gstate.pmskc >> 0) & 0xFF;
u8 gbits = (gstate.pmskc >> 8) & 0xFF;
u8 bbits = (gstate.pmskc >> 16) & 0xFF;
if ((rbits != 0 && rbits != 0xFF) || (gbits != 0 && gbits != 0xFF) || (bbits != 0 && bbits != 0xFF)) {
WARN_LOG_REPORT_ONCE(rgbmask, G3D, "Unsupported RGB mask: r=%02x g=%02x b=%02x", rbits, gbits, bbits);
}
if (abits != 0 && abits != 0xFF) {
// The stencil part of the mask is supported.
WARN_LOG_REPORT_ONCE(amask, G3D, "Unsupported alpha/stencil mask: %02x", abits);
}
#endif
// Let's not write to alpha if stencil isn't enabled.
if (IsStencilTestOutputDisabled()) {
amask = false;
@ -297,14 +284,14 @@ void DrawEngineDX9::ApplyDrawStateLate() {
if (!gstate.isModeClear()) {
textureCache_->ApplyTexture();
if (fboTexNeedBind_) {
if (fboTexNeedsBind_) {
// Note that this is positions, not UVs, that we need the copy from.
framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY);
// If we are rendering at a higher resolution, linear is probably best for the dest color.
device_->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device_->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
fboTexBound_ = true;
fboTexNeedBind_ = false;
fboTexNeedsBind_ = false;
}
// TODO: Test texture?

View File

@ -193,7 +193,7 @@ private:
void DoFlush();
void ApplyDrawState(int prim);
void ApplyDrawStateLate(bool setStencil, int stencilValue);
void ResetShaderBlending();
void ResetFramebufferRead();
GLRInputLayout *SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt);

View File

@ -121,7 +121,7 @@ static const GLushort logicOps[] = {
};
#endif
inline void DrawEngineGLES::ResetShaderBlending() {
inline void DrawEngineGLES::ResetFramebufferRead() {
if (fboTexBound_) {
GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
renderManager->BindTexture(TEX_SLOT_SHADERBLEND_SRC, nullptr);
@ -170,19 +170,19 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
ConvertBlendState(blendState, gstate_c.allowFramebufferRead);
if (blendState.applyFramebufferRead) {
if (ApplyShaderBlending()) {
if (ApplyFramebufferRead(&fboTexNeedsBind_)) {
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState);
// We copy the framebuffer here, as doing so will wipe any blend state if we do it later.
if (fboTexNeedBind_) {
if (fboTexNeedsBind_) {
// Note that this is positions, not UVs, that we need the copy from.
// TODO: If the device doesn't support blit, this will corrupt the currently applied texture.
framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY);
// If we are rendering at a higher resolution, linear is probably best for the dest color.
renderManager->SetTextureSampler(1, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f);
fboTexBound_ = true;
fboTexNeedBind_ = false;
fboTexNeedsBind_ = false;
framebufferManager_->RebindFramebuffer("RebindFramebuffer - ApplyDrawState");
// Must dirty blend state here so we re-copy next time. Example: Lunar's spell effects.
@ -190,11 +190,12 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
}
} else {
// Until next time, force it off.
ResetShaderBlending();
ResetFramebufferRead();
gstate_c.SetAllowFramebufferRead(false);
}
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
} else if (blendState.resetFramebufferRead) {
ResetShaderBlending();
ResetFramebufferRead();
}
if (blendState.enabled) {
@ -220,19 +221,6 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
bool gmask = ((gstate.pmskc >> 8) & 0xFF) < 128;
bool bmask = ((gstate.pmskc >> 16) & 0xFF) < 128;
#ifndef MOBILE_DEVICE
u8 abits = (gstate.pmska >> 0) & 0xFF;
u8 rbits = (gstate.pmskc >> 0) & 0xFF;
u8 gbits = (gstate.pmskc >> 8) & 0xFF;
u8 bbits = (gstate.pmskc >> 16) & 0xFF;
if ((rbits != 0 && rbits != 0xFF) || (gbits != 0 && gbits != 0xFF) || (bbits != 0 && bbits != 0xFF)) {
WARN_LOG_REPORT_ONCE(rgbmask, G3D, "Unsupported RGB mask: r=%02x g=%02x b=%02x", rbits, gbits, bbits);
}
if (abits != 0 && abits != 0xFF) {
// The stencil part of the mask is supported.
WARN_LOG_REPORT_ONCE(amask, G3D, "Unsupported alpha/stencil mask: %02x", abits);
}
#endif
int mask = (int)rmask | ((int)gmask << 1) | ((int)bmask << 2) | ((int)amask << 3);
if (blendState.enabled) {
renderManager->SetBlendAndMask(mask, blendState.enabled,

View File

@ -199,7 +199,7 @@ private:
void ApplyDrawStateLate(VulkanRenderManager *renderManager, bool applyStencilRef, uint8_t stencilRef, bool useBlendConstant);
void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerVulkan *shaderManager, int prim, VulkanPipelineRasterStateKey &key, VulkanDynamicState &dynState);
void BindShaderBlendTex();
void ResetShaderBlending();
void ResetFramebufferRead();
void InitDeviceObjects();
void DestroyDeviceObjects();

View File

@ -122,7 +122,7 @@ static const VkLogicOp logicOps[] = {
VK_LOGIC_OP_SET,
};
void DrawEngineVulkan::ResetShaderBlending() {
void DrawEngineVulkan::ResetFramebufferRead() {
boundSecondary_ = VK_NULL_HANDLE;
}
@ -166,18 +166,18 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
ConvertBlendState(blendState, gstate_c.allowFramebufferRead);
if (blendState.applyFramebufferRead) {
if (ApplyShaderBlending()) {
if (ApplyFramebufferRead(&fboTexNeedsBind_)) {
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(blendState.replaceAlphaWithStencil, blendState);
} else {
// Until next time, force it off.
ResetShaderBlending();
ResetFramebufferRead();
gstate_c.SetAllowFramebufferRead(false);
// Make sure we recompute the fragment shader ID to one that doesn't try to use shader blending.
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE);
}
} else if (blendState.resetFramebufferRead) {
ResetShaderBlending();
ResetFramebufferRead();
}
if (blendState.enabled) {
@ -213,20 +213,6 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
bool bmask = ((gstate.pmskc >> 16) & 0xFF) < 128;
bool amask = (gstate.pmska & 0xFF) < 128;
#ifndef MOBILE_DEVICE
u8 abits = (gstate.pmska >> 0) & 0xFF;
u8 rbits = (gstate.pmskc >> 0) & 0xFF;
u8 gbits = (gstate.pmskc >> 8) & 0xFF;
u8 bbits = (gstate.pmskc >> 16) & 0xFF;
if ((rbits != 0 && rbits != 0xFF) || (gbits != 0 && gbits != 0xFF) || (bbits != 0 && bbits != 0xFF)) {
WARN_LOG_REPORT_ONCE(rgbmask, G3D, "Unsupported RGB mask: r=%02x g=%02x b=%02x", rbits, gbits, bbits);
}
if (abits != 0 && abits != 0xFF) {
// The stencil part of the mask is supported.
WARN_LOG_REPORT_ONCE(amask, G3D, "Unsupported alpha/stencil mask: %02x", abits);
}
#endif
// Let's not write to alpha if stencil isn't enabled.
if (IsStencilTestOutputDisabled()) {
amask = false;
@ -395,13 +381,13 @@ void DrawEngineVulkan::BindShaderBlendTex() {
// TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)?
if (!gstate.isModeClear()) {
// TODO: Test texture?
if (fboTexNeedBind_) {
if (fboTexNeedsBind_) {
// Note that this is positions, not UVs, that we need the copy from.
framebufferManager_->BindFramebufferAsColorTexture(1, framebufferManager_->GetCurrentRenderVFB(), BINDFBCOLOR_MAY_COPY);
// If we are rendering at a higher resolution, linear is probably best for the dest color.
boundSecondary_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE1_IMAGEVIEW);
fboTexBound_ = true;
fboTexNeedBind_ = false;
fboTexNeedsBind_ = false;
}
}