Can't dirty VERTEXSHADER_STATE before the flush in Execute_VertexTypeSkinning, causes obscure bugs when software skinning is enabled

This commit is contained in:
Henrik Rydgård 2017-08-15 14:21:38 +02:00
parent c4ccf5b734
commit 983bb3bd0f
6 changed files with 9 additions and 10 deletions

View File

@ -79,7 +79,7 @@ enum : uint64_t {
DIRTY_WORLDMATRIX = 1ULL << 21,
DIRTY_VIEWMATRIX = 1ULL << 22,
DIRTY_TEXMATRIX = 1ULL << 23,
DIRTY_BONEMATRIX0 = 1ULL << 24,
DIRTY_BONEMATRIX0 = 1ULL << 24, // NOTE: These must be under 32
DIRTY_BONEMATRIX1 = 1ULL << 25,
DIRTY_BONEMATRIX2 = 1ULL << 26,
DIRTY_BONEMATRIX3 = 1ULL << 27,

View File

@ -119,11 +119,14 @@ struct ShaderID {
bool Bit(int bit) const {
return (d[bit >> 5] >> (bit & 31)) & 1;
}
// Does not handle crossing 32-bit boundaries
// Does not handle crossing 32-bit boundaries. count must be 30 or smaller.
int Bits(int bit, int count) const {
const int mask = (1 << count) - 1;
return (d[bit >> 5] >> (bit & 31)) & mask;
}
uint32_t Word(int word) const {
return d[word];
}
void SetBit(int bit, bool value = true) {
if (value) {
d[bit >> 5] |= 1 << (bit & 31);

View File

@ -455,8 +455,6 @@ void GPU_D3D11::Execute_VertexType(u32 op, u32 diff) {
}
void GPU_D3D11::Execute_VertexTypeSkinning(u32 op, u32 diff) {
if (diff)
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
// Don't flush when weight count changes, unless morph is enabled.
if ((diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) || (op & GE_VTYPE_MORPHCOUNT_MASK) != 0) {
// Restore and flush
@ -471,6 +469,7 @@ void GPU_D3D11::Execute_VertexTypeSkinning(u32 op, u32 diff) {
gstate_c.Dirty(gstate_c.deferredVertTypeDirty);
gstate_c.deferredVertTypeDirty = 0;
}
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
}
if (diff & GE_VTYPE_THROUGH_MASK)
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE);

View File

@ -422,8 +422,6 @@ void GPU_DX9::Execute_VertexType(u32 op, u32 diff) {
}
void GPU_DX9::Execute_VertexTypeSkinning(u32 op, u32 diff) {
if (diff)
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
// Don't flush when weight count changes, unless morph is enabled.
if ((diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) || (op & GE_VTYPE_MORPHCOUNT_MASK) != 0) {
// Restore and flush
@ -438,6 +436,7 @@ void GPU_DX9::Execute_VertexTypeSkinning(u32 op, u32 diff) {
gstate_c.Dirty(gstate_c.deferredVertTypeDirty);
gstate_c.deferredVertTypeDirty = 0;
}
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
}
if (diff & GE_VTYPE_THROUGH_MASK)
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);

View File

@ -699,8 +699,6 @@ void GPU_GLES::Execute_VertexType(u32 op, u32 diff) {
}
void GPU_GLES::Execute_VertexTypeSkinning(u32 op, u32 diff) {
if (diff)
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
// Don't flush when weight count changes, unless morph is enabled.
if ((diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) || (op & GE_VTYPE_MORPHCOUNT_MASK) != 0) {
// Restore and flush
@ -715,6 +713,7 @@ void GPU_GLES::Execute_VertexTypeSkinning(u32 op, u32 diff) {
gstate_c.Dirty(gstate_c.deferredVertTypeDirty);
gstate_c.deferredVertTypeDirty = 0;
}
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
}
if (diff & GE_VTYPE_THROUGH_MASK)
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE);

View File

@ -531,8 +531,6 @@ void GPU_Vulkan::Execute_VertexType(u32 op, u32 diff) {
}
void GPU_Vulkan::Execute_VertexTypeSkinning(u32 op, u32 diff) {
if (diff)
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
// Don't flush when weight count changes, unless morph is enabled.
if ((diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) || (op & GE_VTYPE_MORPHCOUNT_MASK) != 0) {
// Restore and flush
@ -547,6 +545,7 @@ void GPU_Vulkan::Execute_VertexTypeSkinning(u32 op, u32 diff) {
gstate_c.Dirty(gstate_c.deferredVertTypeDirty);
gstate_c.deferredVertTypeDirty = 0;
}
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
}
if (diff & GE_VTYPE_THROUGH_MASK)
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE);