diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index 7fcc34fd14..8a1667f181 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -45,6 +45,7 @@ std::string VertexShaderDesc(const ShaderID &id) { } } if (id.Bits(VS_BIT_MATERIAL_UPDATE, 3)) desc << "MatUp:" << id.Bits(VS_BIT_MATERIAL_UPDATE, 3) << " "; + if (id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2)) desc << "WScale " << id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2) << " "; if (id.Bit(VS_BIT_FLATSHADE)) desc << "Flat "; if (id.Bit(VS_BIT_BEZIER)) desc << "Bezier "; diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index 7606010b7e..8ef501a571 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -44,7 +44,8 @@ enum { VS_BIT_LIGHT2_ENABLE = 54, VS_BIT_LIGHT3_ENABLE = 55, VS_BIT_LIGHTING_ENABLE = 56, - // 57 - 61 are free. + VS_BIT_WEIGHT_FMTSCALE = 57, // only two bits + // 59 - 61 are free. VS_BIT_FLATSHADE = 62, // 1 bit VS_BIT_BEZIER = 63, // 1 bit // No more free diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index 8ae7f711f2..808ef71606 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -72,17 +72,21 @@ int DecFmtSize(u8 fmt) { } void DecVtxFormat::ComputeID() { - id = uvfmt | (c0fmt << 4) | (c1fmt << 8) | (nrmfmt << 12) | (posfmt << 16); + id = w0fmt | (w1fmt << 4) | (uvfmt << 8) | (c0fmt << 12) | (c1fmt << 16) | (nrmfmt << 20) | (posfmt << 24); } void DecVtxFormat::InitializeFromID(uint32_t id) { this->id = id; - uvfmt = (id & 0xF); - c0fmt = ((id >> 4) & 0xF); - c1fmt = ((id >> 8) & 0xF); - nrmfmt = ((id >> 12) & 0xF); - posfmt = ((id >> 16) & 0xF); - uvoff = 0; + w0fmt = ((id) & 0xF); + w1fmt = ((id >> 4) & 0xF); + uvfmt = ((id >> 8) & 0xF); + c0fmt = ((id >> 12) & 0xF); + c1fmt = ((id >> 16) & 0xF); + nrmfmt = ((id >> 20) & 0xF); + posfmt = ((id >> 24) & 0xF); + w0off = 0; + w1off = w0off + DecFmtSize(w0fmt); + uvoff = w1off + DecFmtSize(w1fmt); c0off = uvoff + DecFmtSize(uvfmt); c1off = c0off + DecFmtSize(c0fmt); nrmoff = c1off + DecFmtSize(c1fmt); diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 6acf5c48d8..9833eaac47 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -67,6 +67,8 @@ enum { int DecFmtSize(u8 fmt); struct DecVtxFormat { + u8 w0fmt; u8 w0off; // first 4 weights + u8 w1fmt; u8 w1off; // second 4 weights u8 uvfmt; u8 uvoff; u8 c0fmt; u8 c0off; // First color u8 c1fmt; u8 c1off; @@ -345,6 +347,61 @@ public: } } + void ReadWeights(float weights[8]) const { + const float *f = (const float *)(data_ + decFmt_.w0off); + const u8 *b = (const u8 *)(data_ + decFmt_.w0off); + const u16 *s = (const u16 *)(data_ + decFmt_.w0off); + switch (decFmt_.w0fmt) { + case DEC_FLOAT_1: + case DEC_FLOAT_2: + case DEC_FLOAT_3: + case DEC_FLOAT_4: + for (int i = 0; i <= decFmt_.w0fmt - DEC_FLOAT_1; i++) + weights[i] = f[i]; + break; + case DEC_U8_1: weights[0] = b[0] * (1.f / 128.f); break; + case DEC_U8_2: for (int i = 0; i < 2; i++) weights[i] = b[i] * (1.f / 128.f); break; + case DEC_U8_3: for (int i = 0; i < 3; i++) weights[i] = b[i] * (1.f / 128.f); break; + case DEC_U8_4: for (int i = 0; i < 4; i++) weights[i] = b[i] * (1.f / 128.f); break; + case DEC_U16_1: weights[0] = s[0] * (1.f / 32768.f); break; + case DEC_U16_2: for (int i = 0; i < 2; i++) weights[i] = s[i] * (1.f / 32768.f); break; + case DEC_U16_3: for (int i = 0; i < 3; i++) weights[i] = s[i] * (1.f / 32768.f); break; + case DEC_U16_4: for (int i = 0; i < 4; i++) weights[i] = s[i] * (1.f / 32768.f); break; + default: + ERROR_LOG_REPORT_ONCE(fmtw0, G3D, "Reader: Unsupported W0 Format %d", decFmt_.w0fmt); + memset(weights, 0, sizeof(float) * 8); + break; + } + + f = (const float *)(data_ + decFmt_.w1off); + b = (const u8 *)(data_ + decFmt_.w1off); + s = (const u16 *)(data_ + decFmt_.w1off); + switch (decFmt_.w1fmt) { + case 0: + // It's fine for there to be w0 weights but not w1. + break; + case DEC_FLOAT_1: + case DEC_FLOAT_2: + case DEC_FLOAT_3: + case DEC_FLOAT_4: + for (int i = 0; i <= decFmt_.w1fmt - DEC_FLOAT_1; i++) + weights[i+4] = f[i]; + break; + case DEC_U8_1: weights[4] = b[0] * (1.f / 128.f); break; + case DEC_U8_2: for (int i = 0; i < 2; i++) weights[i+4] = b[i] * (1.f / 128.f); break; + case DEC_U8_3: for (int i = 0; i < 3; i++) weights[i+4] = b[i] * (1.f / 128.f); break; + case DEC_U8_4: for (int i = 0; i < 4; i++) weights[i+4] = b[i] * (1.f / 128.f); break; + case DEC_U16_1: weights[4] = s[0] * (1.f / 32768.f); break; + case DEC_U16_2: for (int i = 0; i < 2; i++) weights[i+4] = s[i] * (1.f / 32768.f); break; + case DEC_U16_3: for (int i = 0; i < 3; i++) weights[i+4] = s[i] * (1.f / 32768.f); break; + case DEC_U16_4: for (int i = 0; i < 4; i++) weights[i+4] = s[i] * (1.f / 32768.f); break; + default: + ERROR_LOG_REPORT_ONCE(fmtw1, G3D, "Reader: Unsupported W1 Format %d", decFmt_.w1fmt); + memset(weights + 4, 0, sizeof(float) * 4); + break; + } + } + bool hasColor0() const { return decFmt_.c0fmt != 0; } bool hasColor1() const { return decFmt_.c1fmt != 0; } bool hasNormal() const { return decFmt_.nrmfmt != 0; } diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 35b81a3d89..29273e04a2 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -204,6 +204,18 @@ ID3D11InputLayout *DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshade D3D11_INPUT_ELEMENT_DESC VertexElements[8]; D3D11_INPUT_ELEMENT_DESC *VertexElement = &VertexElements[0]; + // Vertices Elements orders + // WEIGHT + if (decFmt.w0fmt != 0) { + VertexAttribSetup(VertexElement, decFmt.w0fmt, decFmt.w0off, "TEXCOORD", 1); + VertexElement++; + } + + if (decFmt.w1fmt != 0) { + VertexAttribSetup(VertexElement, decFmt.w1fmt, decFmt.w1off, "TEXCOORD", 2); + VertexElement++; + } + // TC if (decFmt.uvfmt != 0) { VertexAttribSetup(VertexElement, decFmt.uvfmt, decFmt.uvoff, "TEXCOORD", 0); diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index cc0da972bd..4d08c35dc4 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -101,6 +101,7 @@ public: // Applies dirty changes and copies the buffer. bool IsBaseDirty() { return true; } bool IsLightDirty() { return true; } + bool IsBoneDirty() { return true; } private: void Clear(); diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index a19c1f4116..99ee183863 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -175,6 +175,16 @@ IDirect3DVertexDeclaration9 *DrawEngineDX9::SetupDecFmtForDraw(VSShader *vshader D3DVERTEXELEMENT9 *VertexElement = &VertexElements[0]; // Vertices Elements orders + // WEIGHT + if (decFmt.w0fmt != 0) { + VertexAttribSetup(VertexElement, decFmt.w0fmt, decFmt.w0off, D3DDECLUSAGE_TEXCOORD, 1); + VertexElement++; + } + + if (decFmt.w1fmt != 0) { + VertexAttribSetup(VertexElement, decFmt.w1fmt, decFmt.w1off, D3DDECLUSAGE_TEXCOORD, 2); + VertexElement++; + } // TC if (decFmt.uvfmt != 0) { diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index 69cdeb89aa..20472eb2fc 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.cpp +++ b/GPU/Directx9/VertexShaderGeneratorDX9.cpp @@ -89,6 +89,9 @@ void GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage } } + int numBoneWeights = 0; + int boneWeightScale = id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2); + if (lang == HLSL_DX9) { WRITE(p, "#pragma warning( disable : 3571 )\n"); if (isModeThrough) { diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index 0acda4bd4d..9992630cdf 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -211,6 +211,8 @@ GLRInputLayout *DrawEngineGLES::SetupDecFmtForDraw(LinkedShader *program, const } std::vector entries; + VertexAttribSetup(ATTR_W1, decFmt.w0fmt, decFmt.stride, decFmt.w0off, entries); + VertexAttribSetup(ATTR_W2, decFmt.w1fmt, decFmt.stride, decFmt.w1off, entries); VertexAttribSetup(ATTR_TEXCOORD, decFmt.uvfmt, decFmt.stride, decFmt.uvoff, entries); VertexAttribSetup(ATTR_COLOR0, decFmt.c0fmt, decFmt.stride, decFmt.c0off, entries); VertexAttribSetup(ATTR_COLOR1, decFmt.c1fmt, decFmt.stride, decFmt.c1off, entries); diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index a585cbd174..9425589665 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -79,6 +79,8 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, semantics.push_back({ ATTR_POSITION, "position" }); semantics.push_back({ ATTR_TEXCOORD, "texcoord" }); semantics.push_back({ ATTR_NORMAL, "normal" }); + semantics.push_back({ ATTR_W1, "w1" }); + semantics.push_back({ ATTR_W2, "w2" }); semantics.push_back({ ATTR_COLOR0, "color0" }); semantics.push_back({ ATTR_COLOR1, "color1" }); @@ -788,7 +790,7 @@ std::string ShaderManagerGLES::DebugGetShaderString(std::string id, DebugShaderT // as sometimes these features might have an effect on the ID bits. #define CACHE_HEADER_MAGIC 0x83277592 -#define CACHE_VERSION 7 +#define CACHE_VERSION 10 struct CacheHeader { uint32_t magic; uint32_t version; diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 6c6efd5b3a..7f19a77e28 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -34,8 +34,10 @@ enum { ATTR_POSITION = 0, ATTR_TEXCOORD = 1, ATTR_NORMAL = 2, - ATTR_COLOR0 = 3, - ATTR_COLOR1 = 4, + ATTR_W1 = 3, + ATTR_W2 = 4, + ATTR_COLOR0 = 5, + ATTR_COLOR1 = 6, ATTR_COUNT, }; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index bdede4c84e..376460f910 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -76,6 +76,8 @@ static const DeclTypeInfo VComp[] = { }; static void VertexAttribSetup(VkVertexInputAttributeDescription *attr, int fmt, int offset, PspAttributeLocation location) { + assert(fmt != DEC_NONE); + assert(fmt < ARRAY_SIZE(VComp)); attr->location = (uint32_t)location; attr->binding = 0; attr->format = VComp[fmt].type; @@ -87,6 +89,12 @@ static void VertexAttribSetup(VkVertexInputAttributeDescription *attr, int fmt, // as we will only call this code when we need to create a new VkPipeline. static int SetupVertexAttribs(VkVertexInputAttributeDescription attrs[], const DecVtxFormat &decFmt) { int count = 0; + if (decFmt.w0fmt != 0) { + VertexAttribSetup(&attrs[count++], decFmt.w0fmt, decFmt.w0off, PspAttributeLocation::W1); + } + if (decFmt.w1fmt != 0) { + VertexAttribSetup(&attrs[count++], decFmt.w1fmt, decFmt.w1off, PspAttributeLocation::W2); + } if (decFmt.uvfmt != 0) { VertexAttribSetup(&attrs[count++], decFmt.uvfmt, decFmt.uvoff, PspAttributeLocation::TEXCOORD); } diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index 8c36edc25a..bf2e425b7f 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -350,7 +350,7 @@ VulkanFragmentShader *ShaderManagerVulkan::GetFragmentShaderFromModule(VkShaderM // instantaneous. #define CACHE_HEADER_MAGIC 0xff51f420 -#define CACHE_VERSION 9 +#define CACHE_VERSION 12 struct VulkanCacheHeader { uint32_t magic; uint32_t version;