mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Merge pull request #13906 from unknownbrackets/skinning
GPU: Correct shader gen with weights as floats
This commit is contained in:
commit
5880ee4d68
@ -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);
|
||||
@ -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()) {
|
||||
|
@ -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);
|
||||
|
@ -822,9 +822,9 @@ 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.
|
||||
@ -832,7 +832,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
||||
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");
|
||||
|
@ -523,7 +523,7 @@ rotateVBO:
|
||||
|
||||
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);
|
||||
@ -609,7 +609,7 @@ rotateVBO:
|
||||
|
||||
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());
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ public:
|
||||
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;
|
||||
|
||||
|
@ -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;
|
||||
@ -505,7 +505,7 @@ rotateVBO:
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -568,7 +568,7 @@ rotateVBO:
|
||||
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) {
|
||||
|
@ -541,7 +541,7 @@ 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);
|
||||
@ -549,7 +549,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat
|
||||
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_;
|
||||
}
|
||||
@ -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
|
||||
|
@ -80,7 +80,7 @@ public:
|
||||
~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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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_;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ public:
|
||||
|
||||
// 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();
|
||||
|
@ -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;
|
||||
@ -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_);
|
||||
|
@ -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_;
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ public:
|
||||
|
||||
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;
|
||||
|
Loading…
Reference in New Issue
Block a user