Skip to content

Commit

Permalink
Merge pull request #13637 from hrydgard/shaderblend-cleanup
Browse files Browse the repository at this point in the history
Shaderblend code cleanup
  • Loading branch information
hrydgard authored Nov 8, 2020
2 parents 0193fd2 + 7391abc commit 7632c12
Show file tree
Hide file tree
Showing 17 changed files with 139 additions and 172 deletions.
5 changes: 3 additions & 2 deletions GPU/Common/DrawEngineCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -502,7 +503,7 @@ bool DrawEngineCommon::ApplyShaderBlending() {
return false;
}

fboTexNeedBind_ = true;
*fboTexNeedsBind = true;

gstate_c.Dirty(DIRTY_SHADERBLEND);
return true;
Expand Down
4 changes: 2 additions & 2 deletions GPU/Common/DrawEngineCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class DrawEngineCommon {
// 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);
Expand Down Expand Up @@ -169,7 +169,7 @@ class DrawEngineCommon {
GEPrimitiveType prevPrim_ = GE_PRIM_INVALID;

// Shader blending state
bool fboTexNeedBind_ = false;
bool fboTexNeedsBind_ = false;
bool fboTexBound_ = false;

// Hardware tessellation
Expand Down
35 changes: 18 additions & 17 deletions GPU/Common/FragmentShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
bool earlyFragmentTests = ((!enableAlphaTest && !enableColorTest) || testForceToZero) && !gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT);
bool useAdrenoBugWorkaround = id.Bit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL);

bool readFramebufferTex = replaceBlend == REPLACE_BLEND_COPY_FBO && !gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH);

if (compat.shaderLanguage == ShaderLanguage::GLSL_VULKAN) {
if (earlyFragmentTests) {
WRITE(p, "layout (early_fragment_tests) in;\n");
Expand All @@ -116,10 +118,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
WRITE(p, "layout (binding = 0) uniform sampler2D tex;\n");
}

if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlend == REPLACE_BLEND_COPY_FBO) {
WRITE(p, "layout (binding = 1) uniform sampler2D fbotex;\n");
}
if (readFramebufferTex) {
WRITE(p, "layout (binding = 1) uniform sampler2D fbotex;\n");
}

if (shaderDepal) {
Expand Down Expand Up @@ -151,11 +151,13 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
if (compat.shaderLanguage == HLSL_D3D9) {
if (doTexture)
WRITE(p, "sampler tex : register(s0);\n");
if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlend == REPLACE_BLEND_COPY_FBO) {
WRITE(p, "vec2 u_fbotexSize : register(c%i);\n", CONST_PS_FBOTEXSIZE);
WRITE(p, "sampler fbotex : register(s1);\n");
}

if (readFramebufferTex) {
WRITE(p, "vec2 u_fbotexSize : register(c%i);\n", CONST_PS_FBOTEXSIZE);
WRITE(p, "sampler fbotex : register(s1);\n");
}

if (replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlendFuncA >= GE_SRCBLEND_FIXA) {
WRITE(p, "float3 u_blendFixA : register(c%i);\n", CONST_PS_BLENDFIXA);
}
Expand Down Expand Up @@ -244,11 +246,11 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
} else if (compat.shaderLanguage == HLSL_D3D9) {
if (doTexture)
WRITE(p, "sampler tex : register(s0);\n");
if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlend == REPLACE_BLEND_COPY_FBO) {
WRITE(p, "vec2 u_fbotexSize : register(c%i);\n", CONST_PS_FBOTEXSIZE);
WRITE(p, "sampler fbotex : register(s1);\n");
}
if (readFramebufferTex) {
WRITE(p, "vec2 u_fbotexSize : register(c%i);\n", CONST_PS_FBOTEXSIZE);
WRITE(p, "sampler fbotex : register(s1);\n");
}
if (replaceBlend > REPLACE_BLEND_STANDARD) {
if (replaceBlendFuncA >= GE_SRCBLEND_FIXA) {
WRITE(p, "float3 u_blendFixA : register(c%i);\n", CONST_PS_BLENDFIXA);
}
Expand Down Expand Up @@ -276,7 +278,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
if (enableFog) {
WRITE(p, "float3 u_fogcolor : register(c%i);\n", CONST_PS_FOGCOLOR);
}

} else if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) {
if (shaderDepal && gl_extensions.IsGLES) {
WRITE(p, "precision highp int;\n");
Expand All @@ -287,7 +288,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu

if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
*uniformMask |= DIRTY_SHADERBLEND;
if (!gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH) && replaceBlend == REPLACE_BLEND_COPY_FBO) {
if (readFramebufferTex) {
if (!compat.texelFetch) {
WRITE(p, "uniform vec2 u_fbotexSize;\n");
}
Expand Down Expand Up @@ -869,7 +870,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
}

if (replaceBlend == REPLACE_BLEND_2X_ALPHA || replaceBlend == REPLACE_BLEND_PRE_SRC_2X_ALPHA) {
WRITE(p, " v.a = v.a * 2.0;\n");
WRITE(p, " v.a *= 2.0;\n");
}
}

Expand Down
58 changes: 29 additions & 29 deletions GPU/Common/GPUStateUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ StencilValueType ReplaceAlphaWithStencilType() {
return STENCIL_VALUE_KEEP;
}

ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bufferFormat) {
ReplaceBlendType ReplaceBlendWithShader(bool allowFramebufferRead, GEBufferFormat bufferFormat) {
if (!gstate.isAlphaBlendEnabled() || gstate.isModeClear()) {
return REPLACE_BLEND_NO;
}
Expand All @@ -262,14 +262,14 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
// Let's get the non-factor modes out of the way first.
switch (eq) {
case GE_BLENDMODE_ABSDIFF:
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;

case GE_BLENDMODE_MIN:
case GE_BLENDMODE_MAX:
if (gstate_c.Supports(GPU_SUPPORTS_BLEND_MINMAX)) {
return REPLACE_BLEND_STANDARD;
} else {
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
}

default:
Expand All @@ -292,19 +292,19 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
return REPLACE_BLEND_2X_ALPHA;
// Can't double, we need the source color to be correct.
// Doubling only alpha would clamp the src alpha incorrectly.
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;

case GE_DSTBLEND_DOUBLEDSTALPHA:
case GE_DSTBLEND_DOUBLEINVDSTALPHA:
if (bufferFormat == GE_FORMAT_565)
return REPLACE_BLEND_2X_ALPHA;
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;

case GE_DSTBLEND_DOUBLESRCALPHA:
// We can't technically do this correctly (due to clamping) without reading the dst color.
// Using a copy isn't accurate either, though, when there's overlap.
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH))
return !allowShaderBlend ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return REPLACE_BLEND_PRE_SRC_2X_ALPHA;

case GE_DSTBLEND_DOUBLEINVSRCALPHA:
Expand All @@ -331,7 +331,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
return REPLACE_BLEND_STANDARD;
}
// Can't double, we need the source color to be correct.
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;

case GE_DSTBLEND_DOUBLEDSTALPHA:
case GE_DSTBLEND_DOUBLEINVDSTALPHA:
Expand All @@ -340,7 +340,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
// Doubling will have no effect here.
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_2X_SRC : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_SRC : REPLACE_BLEND_COPY_FBO;

case GE_DSTBLEND_DOUBLESRCALPHA:
case GE_DSTBLEND_DOUBLEINVSRCALPHA:
Expand All @@ -349,7 +349,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
}
// Double both src (for dst alpha) and alpha (for dst factor.)
// But to be accurate (clamping), we need to read the dst color.
return !allowShaderBlend ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;

case GE_DSTBLEND_SRCALPHA:
case GE_DSTBLEND_INVSRCALPHA:
Expand All @@ -361,7 +361,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
return REPLACE_BLEND_STANDARD;
}
// We can't technically do this correctly (due to clamping) without reading the dst alpha.
return !allowShaderBlend ? REPLACE_BLEND_2X_SRC : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_SRC : REPLACE_BLEND_COPY_FBO;
}

case GE_SRCBLEND_DOUBLEINVDSTALPHA:
Expand All @@ -375,14 +375,14 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;

case GE_DSTBLEND_DOUBLESRCALPHA:
case GE_DSTBLEND_DOUBLEINVSRCALPHA:
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_2X_ALPHA;
}
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;

case GE_DSTBLEND_SRCALPHA:
case GE_DSTBLEND_INVSRCALPHA:
Expand All @@ -393,15 +393,15 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
}

case GE_SRCBLEND_FIXA:
default:
switch (funcB) {
case GE_DSTBLEND_DOUBLESRCALPHA:
// Can't safely double alpha, will clamp.
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;

case GE_DSTBLEND_DOUBLEINVSRCALPHA:
// Doubling alpha is safe for the inverse, will clamp to zero either way.
Expand All @@ -412,7 +412,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;

case GE_DSTBLEND_FIXB:
default:
Expand Down Expand Up @@ -446,14 +446,14 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (funcA == GE_SRCBLEND_SRCALPHA || funcA == GE_SRCBLEND_INVSRCALPHA) {
// Can't safely double alpha, will clamp. However, a copy may easily be worse due to overlap.
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH))
return !allowShaderBlend ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_PRE_SRC_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return REPLACE_BLEND_PRE_SRC_2X_ALPHA;
} else {
// This means dst alpha/color is used in the src factor.
// Unfortunately, copying here causes overlap problems in Silent Hill games (it seems?)
// We will just hope that doubling alpha for the dst factor will not clamp too badly.
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH))
return !allowShaderBlend ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_2X_ALPHA : REPLACE_BLEND_COPY_FBO;
return REPLACE_BLEND_2X_ALPHA;
}

Expand All @@ -470,7 +470,7 @@ ReplaceBlendType ReplaceBlendWithShader(bool allowShaderBlend, GEBufferFormat bu
if (bufferFormat == GE_FORMAT_565) {
return REPLACE_BLEND_STANDARD;
}
return !allowShaderBlend ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;
return !allowFramebufferRead ? REPLACE_BLEND_STANDARD : REPLACE_BLEND_COPY_FBO;

default:
return REPLACE_BLEND_STANDARD;
Expand Down Expand Up @@ -906,7 +906,7 @@ static void ApplyLogicOp(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq &
}

// Try to simulate some common logic ops.
void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState) {
void ApplyStencilReplaceAndLogicOpIgnoreBlend(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState) {
StencilValueType stencilType = STENCIL_VALUE_KEEP;
if (replaceAlphaWithStencil == REPLACE_ALPHA_YES) {
stencilType = ReplaceAlphaWithStencilType();
Expand Down Expand Up @@ -958,7 +958,7 @@ void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, Gen

// Called even if AlphaBlendEnable == false - it also deals with stencil-related blend state.

void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
void ConvertBlendState(GenericBlendState &blendState, bool allowFramebufferRead) {
// Blending is a bit complex to emulate. This is due to several reasons:
//
// * Doubled blend modes (src, dst, inversed) aren't supported in OpenGL.
Expand All @@ -969,25 +969,25 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
//
// If we can't apply blending, we make a copy of the framebuffer and do it manually.

blendState.applyShaderBlending = false;
blendState.dirtyShaderBlend = false;
blendState.applyFramebufferRead = false;
blendState.dirtyShaderBlendFixValues = false;
blendState.useBlendColor = false;
blendState.replaceAlphaWithStencil = REPLACE_ALPHA_NO;

ReplaceBlendType replaceBlend = ReplaceBlendWithShader(allowShaderBlend, gstate.FrameBufFormat());
ReplaceBlendType replaceBlend = ReplaceBlendWithShader(allowFramebufferRead, gstate.FrameBufFormat());
ReplaceAlphaType replaceAlphaWithStencil = ReplaceAlphaWithStencil(replaceBlend);
bool usePreSrc = false;

switch (replaceBlend) {
case REPLACE_BLEND_NO:
blendState.resetShaderBlending = true;
blendState.resetFramebufferRead = true;
// We may still want to do something about stencil -> alpha.
ApplyStencilReplaceAndLogicOp(replaceAlphaWithStencil, blendState);
ApplyStencilReplaceAndLogicOpIgnoreBlend(replaceAlphaWithStencil, blendState);
return;

case REPLACE_BLEND_COPY_FBO:
blendState.applyShaderBlending = true;
blendState.resetShaderBlending = false;
blendState.applyFramebufferRead = true;
blendState.resetFramebufferRead = false;
blendState.replaceAlphaWithStencil = replaceAlphaWithStencil;
break;

Expand All @@ -1003,7 +1003,7 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
}

blendState.enabled = true;
blendState.resetShaderBlending = true;
blendState.resetFramebufferRead = true;

const GEBlendMode blendFuncEq = gstate.getBlendEq();
GEBlendSrcFactor blendFuncA = gstate.getBlendFuncA();
Expand Down Expand Up @@ -1071,7 +1071,7 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
glBlendFuncA = BlendFactor::ONE;
// Need to pull in the fixed color. TODO: If it hasn't changed, no need to dirty.
if (blendFuncA == GE_SRCBLEND_FIXA) {
blendState.dirtyShaderBlend = true;
blendState.dirtyShaderBlendFixValues = true;
}
}

Expand Down
8 changes: 4 additions & 4 deletions GPU/Common/GPUStateUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ enum class BlendEq : uint8_t {

struct GenericBlendState {
bool enabled;
bool resetShaderBlending;
bool applyShaderBlending;
bool dirtyShaderBlend;
bool resetFramebufferRead;
bool applyFramebufferRead;
bool dirtyShaderBlendFixValues;
ReplaceAlphaType replaceAlphaWithStencil;

BlendFactor srcColor;
Expand Down Expand Up @@ -158,7 +158,7 @@ struct GenericBlendState {
};

void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend);
void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState);
void ApplyStencilReplaceAndLogicOpIgnoreBlend(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState);

struct GenericStencilFuncState {
bool enabled;
Expand Down
4 changes: 3 additions & 1 deletion GPU/Common/ShaderId.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,9 @@ void ComputeFragmentShaderID(FShaderID *id_out, const Draw::Bugs &bugs) {
bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT;
bool useShaderDepal = gstate_c.useShaderDepal;

ReplaceBlendType replaceBlend = ReplaceBlendWithShader(gstate_c.allowShaderBlend, gstate.FrameBufFormat());
// Note how we here recompute some of the work already done in state mapping.
// Not ideal! At least we share the code.
ReplaceBlendType replaceBlend = ReplaceBlendWithShader(gstate_c.allowFramebufferRead, gstate.FrameBufFormat());
ReplaceAlphaType stencilToAlpha = ReplaceAlphaWithStencil(replaceBlend);

// All texfuncs except replace are the same for RGB as for RGBA with full alpha.
Expand Down
2 changes: 1 addition & 1 deletion GPU/D3D11/DrawEngineD3D11.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class DrawEngineD3D11 : public DrawEngineCommon {

void ApplyDrawState(int prim);
void ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRef);
void ResetShaderBlending();
void ResetFramebufferRead();

ID3D11InputLayout *SetupDecFmtForDraw(D3D11VertexShader *vshader, const DecVtxFormat &decFmt, u32 pspFmt);

Expand Down
Loading

0 comments on commit 7632c12

Please sign in to comment.