Skip to content

Commit

Permalink
GPU: Correct shader gen with weights as floats.
Browse files Browse the repository at this point in the history
For now, this supports the option.  We should probably just move to
everything being floats, but we already prefer software skinning.

Fixes #13903.
  • Loading branch information
unknownbrackets committed Jan 10, 2021
1 parent e00f894 commit a73c15b
Show file tree
Hide file tree
Showing 15 changed files with 28 additions and 28 deletions.
4 changes: 2 additions & 2 deletions GPU/Common/ShaderId.cpp
Expand Up @@ -61,7 +61,7 @@ std::string VertexShaderDesc(const VShaderID &id) {
return desc.str();
}

void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform, bool useHWTessellation) {
void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat) {
bool isModeThrough = (vertType & GE_VTYPE_THROUGH) != 0;
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool doShadeMapping = doTexture && (gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP);
Expand Down Expand Up @@ -112,7 +112,7 @@ void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform,
id.SetBits(VS_BIT_BONES, 3, TranslateNumBones(vertTypeGetNumBoneWeights(vertType)) - 1);
// 2 bits. We should probably send in the weight scalefactor as a uniform instead,
// or simply preconvert all weights to floats.
id.SetBits(VS_BIT_WEIGHT_FMTSCALE, 2, (vertType & GE_VTYPE_WEIGHT_MASK) >> GE_VTYPE_WEIGHT_SHIFT);
id.SetBits(VS_BIT_WEIGHT_FMTSCALE, 2, weightsAsFloat ? 0 : (vertType & GE_VTYPE_WEIGHT_MASK) >> GE_VTYPE_WEIGHT_SHIFT);
}

if (gstate.isLightingEnabled()) {
Expand Down
2 changes: 1 addition & 1 deletion GPU/Common/ShaderId.h
Expand Up @@ -225,7 +225,7 @@ class Bugs;
}


void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform, bool useHWTessellation);
void ComputeVertexShaderID(VShaderID *id, uint32_t vertexType, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat);
// Generates a compact string that describes the shader. Useful in a list to get an overview
// of the current flora of shaders.
std::string VertexShaderDesc(const VShaderID &id);
Expand Down
6 changes: 3 additions & 3 deletions GPU/Common/VertexShaderGenerator.cpp
Expand Up @@ -822,17 +822,17 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
// Uncomment this to screw up bone shaders to check the vertex shader software fallback
// WRITE(p, "THIS SHOULD ERROR! #error");
if (numBoneWeights == 1 && ShaderLanguageIsOpenGL(compat.shaderLanguage))
WRITE(p, " %s skinMatrix = w1 * u_bone0", boneMatrix);
WRITE(p, " %s skinMatrix = mul(w1, u_bone0)", boneMatrix);
else
WRITE(p, " %s skinMatrix = w1.x * u_bone0", boneMatrix);
WRITE(p, " %s skinMatrix = mul(w1.x, u_bone0)", boneMatrix);
for (int i = 1; i < numBoneWeights; i++) {
const char *weightAttr = boneWeightAttr[i];
// workaround for "cant do .x of scalar" issue.
if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) {
if (numBoneWeights == 1 && i == 0) weightAttr = "w1";
if (numBoneWeights == 5 && i == 4) weightAttr = "w2";
}
WRITE(p, " + %s * u_bone%i", weightAttr, i);
WRITE(p, " + mul(%s, u_bone%i)", weightAttr, i);
}

WRITE(p, ";\n");
Expand Down
4 changes: 2 additions & 2 deletions GPU/D3D11/DrawEngineD3D11.cpp
Expand Up @@ -523,7 +523,7 @@ void DrawEngineD3D11::DoFlush() {

D3D11VertexShader *vshader;
D3D11FragmentShader *fshader;
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform, useHWTessellation_);
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, useHWTransform, useHWTessellation_, decOptions_.expandAllWeightsToFloat);
ID3D11InputLayout *inputLayout = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType());
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
Expand Down Expand Up @@ -609,7 +609,7 @@ void DrawEngineD3D11::DoFlush() {

D3D11VertexShader *vshader;
D3D11FragmentShader *fshader;
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false, false);
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false, false, decOptions_.expandAllWeightsToFloat);
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering());
Expand Down
4 changes: 2 additions & 2 deletions GPU/D3D11/ShaderManagerD3D11.cpp
Expand Up @@ -177,13 +177,13 @@ void ShaderManagerD3D11::BindUniforms() {
context_->PSSetConstantBuffers(0, 1, ps_cbs);
}

void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform, bool useHWTessellation) {
void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat) {
VShaderID VSID;
FShaderID FSID;

if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation);
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat);
} else {
VSID = lastVSID_;
}
Expand Down
2 changes: 1 addition & 1 deletion GPU/D3D11/ShaderManagerD3D11.h
Expand Up @@ -85,7 +85,7 @@ class ShaderManagerD3D11 : public ShaderManagerCommon {
ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel);
~ShaderManagerD3D11();

void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform, bool useHWTessellation);
void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat);
void ClearShaders();
void DirtyLastShader() override;

Expand Down
6 changes: 3 additions & 3 deletions GPU/Directx9/DrawEngineDX9.cpp
Expand Up @@ -324,7 +324,7 @@ void DrawEngineDX9::DoFlush() {
GEPrimitiveType prim = prevPrim_;
ApplyDrawState(prim);

VSShader *vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_);
VSShader *vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat);

if (vshader->UseHWTransform()) {
LPDIRECT3DVERTEXBUFFER9 vb_ = NULL;
Expand Down Expand Up @@ -505,7 +505,7 @@ void DrawEngineDX9::DoFlush() {
}

ApplyDrawStateLate();
vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_);
vshader = shaderManager_->ApplyShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat);
IDirect3DVertexDeclaration9 *pHardwareVertexDecl = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType());

if (pHardwareVertexDecl) {
Expand Down Expand Up @@ -568,7 +568,7 @@ void DrawEngineDX9::DoFlush() {
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);

ApplyDrawStateLate();
vshader = shaderManager_->ApplyShader(false, false, lastVType_);
vshader = shaderManager_->ApplyShader(false, false, lastVType_, decOptions_.expandAllWeightsToFloat);

if (result.action == SW_DRAW_PRIMITIVES) {
if (result.setStencil) {
Expand Down
6 changes: 3 additions & 3 deletions GPU/Directx9/ShaderManagerDX9.cpp
Expand Up @@ -541,15 +541,15 @@ void ShaderManagerDX9::DirtyLastShader() { // disables vertex arrays
lastPShader_ = nullptr;
}

VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType) {
VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat) {
// Always use software for flat shading to fix the provoking index.
bool tess = gstate_c.submitType == SubmitType::HW_BEZIER || gstate_c.submitType == SubmitType::HW_SPLINE;
useHWTransform = useHWTransform && (tess || gstate.getShadeMode() != GE_SHADE_FLAT);

VShaderID VSID;
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation);
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat);
} else {
VSID = lastVSID_;
}
Expand Down Expand Up @@ -598,7 +598,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat
}
delete vs;

ComputeVertexShaderID(&VSID, vertType, false, false);
ComputeVertexShaderID(&VSID, vertType, false, false, weightsAsFloat);

// TODO: Look for existing shader with the appropriate ID, use that instead of generating a new one - however, need to make sure
// that that shader ID is not used when computing the linked shader ID below, because then IDs won't match
Expand Down
2 changes: 1 addition & 1 deletion GPU/Directx9/ShaderManagerDX9.h
Expand Up @@ -80,7 +80,7 @@ class ShaderManagerDX9 : public ShaderManagerCommon {
~ShaderManagerDX9();

void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected
VSShader *ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType);
VSShader *ApplyShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat);
void DirtyShader();
void DirtyLastShader() override;

Expand Down
2 changes: 1 addition & 1 deletion GPU/GLES/DrawEngineGLES.cpp
Expand Up @@ -333,7 +333,7 @@ void DrawEngineGLES::DoFlush() {
GEPrimitiveType prim = prevPrim_;

VShaderID vsid;
Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, &vsid);
Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, &vsid);

GLRBuffer *vertexBuffer = nullptr;
GLRBuffer *indexBuffer = nullptr;
Expand Down
6 changes: 3 additions & 3 deletions GPU/GLES/ShaderManagerGLES.cpp
Expand Up @@ -656,10 +656,10 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) {
return new Shader(render_, codeBuffer_, desc, GL_VERTEX_SHADER, useHWTransform, attrMask, uniformMask);
}

Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, VShaderID *VSID) {
Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, VShaderID *VSID) {
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(VSID, vertType, useHWTransform, useHWTessellation);
ComputeVertexShaderID(VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat);
} else {
*VSID = lastVSID_;
}
Expand Down Expand Up @@ -690,7 +690,7 @@ Shader *ShaderManagerGLES::ApplyVertexShader(bool useHWTransform, bool useHWTess

// Can still work with software transform.
VShaderID vsidTemp;
ComputeVertexShaderID(&vsidTemp, vertType, false, false);
ComputeVertexShaderID(&vsidTemp, vertType, false, false, weightsAsFloat);
vs = CompileVertexShader(vsidTemp);
}

Expand Down
2 changes: 1 addition & 1 deletion GPU/GLES/ShaderManagerGLES.h
Expand Up @@ -146,7 +146,7 @@ class ShaderManagerGLES : public ShaderManagerCommon {

// This is the old ApplyShader split into two parts, because of annoying information dependencies.
// If you call ApplyVertexShader, you MUST call ApplyFragmentShader soon afterwards.
Shader *ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, VShaderID *VSID);
Shader *ApplyVertexShader(bool useHWTransform, bool useHWTessellation, u32 vertType, bool weightsAsFloat, VShaderID *VSID);
LinkedShader *ApplyFragmentShader(VShaderID VSID, Shader *vs, u32 vertType, bool useBufferedRendering);

void DeviceLost();
Expand Down
4 changes: 2 additions & 2 deletions GPU/Vulkan/DrawEngineVulkan.cpp
Expand Up @@ -818,7 +818,7 @@ void DrawEngineVulkan::DoFlush() {
ConvertStateToVulkanKey(*framebufferManager_, shaderManager_, prim, pipelineKey_, dynState_);
}

shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, true, useHWTessellation_); // usehwtransform
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat); // usehwtransform
_dbg_assert_msg_(vshader->UseHWTransform(), "Bad vshader");

Draw::NativeObject object = framebufferManager_->UseBufferedRendering() ? Draw::NativeObject::FRAMEBUFFER_RENDERPASS : Draw::NativeObject::BACKBUFFER_RENDERPASS;
Expand Down Expand Up @@ -939,7 +939,7 @@ void DrawEngineVulkan::DoFlush() {
sampler = nullSampler_;
}
if (!lastPipeline_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE) || prim != lastPrim_) {
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false, false); // usehwtransform
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, false, false, decOptions_.expandAllWeightsToFloat); // usehwtransform
_dbg_assert_msg_(!vshader->UseHWTransform(), "Bad vshader");
if (prim != lastPrim_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE)) {
ConvertStateToVulkanKey(*framebufferManager_, shaderManager_, prim, pipelineKey_, dynState_);
Expand Down
4 changes: 2 additions & 2 deletions GPU/Vulkan/ShaderManagerVulkan.cpp
Expand Up @@ -228,11 +228,11 @@ uint64_t ShaderManagerVulkan::UpdateUniforms(bool useBufferedRendering) {
return dirty;
}

void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform, bool useHWTessellation) {
void ShaderManagerVulkan::GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat) {
VShaderID VSID;
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation);
ComputeVertexShaderID(&VSID, vertType, useHWTransform, useHWTessellation, weightsAsFloat);
} else {
VSID = lastVSID_;
}
Expand Down
2 changes: 1 addition & 1 deletion GPU/Vulkan/ShaderManagerVulkan.h
Expand Up @@ -88,7 +88,7 @@ class ShaderManagerVulkan : public ShaderManagerCommon {

void DeviceRestore(VulkanContext *vulkan, Draw::DrawContext *draw);

void GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform, bool useHWTessellation);
void GetShaders(int prim, u32 vertType, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat);
void ClearShaders();
void DirtyShader();
void DirtyLastShader() override;
Expand Down

0 comments on commit a73c15b

Please sign in to comment.