Permalink
Browse files

All: Only recompute the vertex shader ID when dirty

  • Loading branch information...
hrydgard committed Jan 30, 2017
1 parent f01da87 commit 56cd991833efb6baf08b80d2d3cdf5b0fbf02f11
@@ -33,7 +33,6 @@
#include "GPU/Common/GPUStateUtils.h"
bool CanUseHardwareTransform(int prim) {
if (!g_Config.bHardwareTransform)
return false;
@@ -119,7 +119,8 @@ void DrawEngineD3D11::ClearTrackedVertexArrays() {
void DrawEngineD3D11::ClearInputLayoutMap() {
for (auto &decl : inputLayoutMap_) {
decl.second->Release();
if (decl.second)
decl.second->Release();
}
inputLayoutMap_.clear();
}
@@ -467,6 +467,8 @@ void FramebufferManagerD3D11::BindPostShader(const PostShaderUniforms &uniforms)
context_->Unmap(postConstants_, 0);
context_->VSSetConstantBuffers(0, 1, &postConstants_); // Probably not necessary
context_->PSSetConstantBuffers(0, 1, &postConstants_);
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
}
void FramebufferManagerD3D11::RebindFramebuffer() {
@@ -510,7 +512,7 @@ void FramebufferManagerD3D11::ReformatFramebufferFrom(VirtualFramebuffer *vfb, G
}
RebindFramebuffer();
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE);
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE);
}
static void CopyPixelDepthOnly(u32 *dstp, const u32 *srcp, size_t c) {
@@ -713,7 +715,7 @@ void FramebufferManagerD3D11::SimpleBlit(
context_->IASetVertexBuffers(0, 1, &quadBuffer_, &stride, &offset);
context_->Draw(4, 0);
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE);
}
void FramebufferManagerD3D11::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) {
View
@@ -445,12 +445,18 @@ void GPU_D3D11::ExecuteOp(u32 op, u32 diff) {
}
void GPU_D3D11::Execute_VertexType(u32 op, u32 diff) {
if (diff)
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) {
gstate_c.Dirty(DIRTY_UVSCALEOFFSET);
if (diff & GE_VTYPE_THROUGH_MASK)
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
}
}
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
@@ -466,6 +472,8 @@ void GPU_D3D11::Execute_VertexTypeSkinning(u32 op, u32 diff) {
gstate_c.deferredVertTypeDirty = 0;
}
}
if (diff & GE_VTYPE_THROUGH_MASK)
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
}
void GPU_D3D11::Execute_Prim(u32 op, u32 diff) {
@@ -474,12 +482,11 @@ void GPU_D3D11::Execute_Prim(u32 op, u32 diff) {
u32 data = op & 0xFFFFFF;
u32 count = data & 0xFFFF;
// Upper bits are ignored.
GEPrimitiveType prim = static_cast<GEPrimitiveType>((data >> 16) & 7);
if (count == 0)
return;
// Upper bits are ignored.
GEPrimitiveType prim = static_cast<GEPrimitiveType>((data >> 16) & 7);
SetDrawType(DRAW_PRIM, prim);
// Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though.
@@ -139,6 +139,7 @@ void ShaderManagerD3D11::DirtyLastShader() {
lastVSID_.clear();
lastVShader_ = nullptr;
lastFShader_ = nullptr;
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
}
uint64_t ShaderManagerD3D11::UpdateUniforms() {
@@ -178,7 +179,13 @@ void ShaderManagerD3D11::BindUniforms() {
void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform) {
ShaderID VSID;
ShaderID FSID;
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
} else {
VSID = lastVSID_;
}
ComputeFragmentShaderID(&FSID);
// Just update uniforms if this is the same shader as last time.
View
@@ -412,12 +412,18 @@ void GPU_DX9::ExecuteOp(u32 op, u32 diff) {
}
void GPU_DX9::Execute_VertexType(u32 op, u32 diff) {
if (diff)
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) {
gstate_c.Dirty(DIRTY_UVSCALEOFFSET);
if (diff & GE_VTYPE_THROUGH_MASK)
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
}
}
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
@@ -433,6 +439,8 @@ void GPU_DX9::Execute_VertexTypeSkinning(u32 op, u32 diff) {
gstate_c.deferredVertTypeDirty = 0;
}
}
if (diff & GE_VTYPE_THROUGH_MASK)
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
}
void GPU_DX9::Execute_Prim(u32 op, u32 diff) {
@@ -441,12 +449,10 @@ void GPU_DX9::Execute_Prim(u32 op, u32 diff) {
u32 data = op & 0xFFFFFF;
u32 count = data & 0xFFFF;
// Upper bits are ignored.
GEPrimitiveType prim = static_cast<GEPrimitiveType>((data >> 16) & 7);
if (count == 0)
return;
// Upper bits are ignored.
GEPrimitiveType prim = static_cast<GEPrimitiveType>((data >> 16) & 7);
SetDrawType(DRAW_PRIM, prim);
// Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though.
@@ -555,7 +555,13 @@ VSShader *ShaderManagerDX9::ApplyShader(int prim, u32 vertType) {
bool useHWTransform = CanUseHardwareTransform(prim);
ShaderID VSID;
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(&VSID, vertType, useHWTransform);
} else {
VSID = lastVSID_;
}
ShaderID FSID;
ComputeFragmentShaderID(&FSID);
View
@@ -627,12 +627,11 @@ void GPU_GLES::Execute_Prim(u32 op, u32 diff) {
u32 data = op & 0xFFFFFF;
u32 count = data & 0xFFFF;
// Upper bits are ignored.
GEPrimitiveType prim = static_cast<GEPrimitiveType>((data >> 16) & 7);
if (count == 0)
return;
// Upper bits are ignored.
GEPrimitiveType prim = static_cast<GEPrimitiveType>((data >> 16) & 7);
SetDrawType(DRAW_PRIM, prim);
// Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though.
@@ -690,6 +689,8 @@ void GPU_GLES::Execute_Prim(u32 op, u32 diff) {
}
void GPU_GLES::Execute_VertexType(u32 op, u32 diff) {
if (diff)
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) {
gstate_c.Dirty(DIRTY_UVSCALEOFFSET);
if (diff & GE_VTYPE_THROUGH_MASK)
@@ -698,6 +699,8 @@ 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
@@ -747,7 +747,7 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid) {
}
ShaderManagerGLES::ShaderManagerGLES()
: lastShader_(nullptr), shaderSwitchDirty_(0), diskCacheDirty_(false) {
: lastShader_(nullptr), shaderSwitchDirtyUniforms_(0), diskCacheDirty_(false) {
codeBuffer_ = new char[16384];
lastFSID_.set_invalid();
lastVSID_.set_invalid();
@@ -788,7 +788,7 @@ void ShaderManagerGLES::DirtyShader() {
lastVSID_.set_invalid();
DirtyLastShader();
gstate_c.Dirty(DIRTY_ALL_UNIFORMS);
shaderSwitchDirty_ = 0;
shaderSwitchDirtyUniforms_ = 0;
}
void ShaderManagerGLES::DirtyLastShader() { // disables vertex arrays
@@ -816,22 +816,25 @@ Shader *ShaderManagerGLES::ApplyVertexShader(int prim, u32 vertType, ShaderID *V
if (dirty) {
if (lastShader_)
lastShader_->dirtyUniforms |= dirty;
shaderSwitchDirty_ |= dirty;
shaderSwitchDirtyUniforms_ |= dirty;
gstate_c.CleanUniforms();
}
bool useHWTransform = CanUseHardwareTransform(prim);
ComputeVertexShaderID(VSID, vertType, useHWTransform);
if (gstate_c.IsDirty(DIRTY_VERTEXSHADER_STATE)) {
gstate_c.Clean(DIRTY_VERTEXSHADER_STATE);
ComputeVertexShaderID(VSID, vertType, useHWTransform);
} else {
*VSID = lastVSID_;
}
// Just update uniforms if this is the same shader as last time.
if (lastShader_ != 0 && *VSID == lastVSID_) {
lastVShaderSame_ = true;
return lastShader_->vs_; // Already all set.
} else {
lastVShaderSame_ = false;
}
lastVSID_ = *VSID;
VSCache::iterator vsIter = vsCache_.find(*VSID);
@@ -890,7 +893,7 @@ LinkedShader *ShaderManagerGLES::ApplyFragmentShader(ShaderID VSID, Shader *vs,
// Okay, we have both shaders. Let's see if there's a linked one.
LinkedShader *ls = nullptr;
u64 switchDirty = shaderSwitchDirty_;
u64 switchDirty = shaderSwitchDirtyUniforms_;
for (auto iter = linkedShaderCache_.begin(); iter != linkedShaderCache_.end(); ++iter) {
// Deferred dirtying! Let's see if we can make this even more clever later.
iter->ls->dirtyUniforms |= switchDirty;
@@ -899,7 +902,7 @@ LinkedShader *ShaderManagerGLES::ApplyFragmentShader(ShaderID VSID, Shader *vs,
ls = iter->ls;
}
}
shaderSwitchDirty_ = 0;
shaderSwitchDirtyUniforms_ = 0;
if (ls == nullptr) {
@@ -188,7 +188,7 @@ class ShaderManagerGLES : public ShaderManagerCommon {
ShaderID lastVSID_;
LinkedShader *lastShader_;
u64 shaderSwitchDirty_;
u64 shaderSwitchDirtyUniforms_;
char *codeBuffer_;
typedef std::map<ShaderID, Shader *> FSCache;
View
@@ -56,33 +56,33 @@ const CommonCommandTableEntry commonCommandTable[] = {
{ GE_CMD_FOG2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOEF },
// These affect the fragment shader so need flushing.
{ GE_CMD_CLEARMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE },
{ GE_CMD_TEXTUREMAPENABLE, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_FOGENABLE, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_CLEARMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_TEXTUREMAPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_FOGENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_TEXMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS },
{ GE_CMD_TEXSHADELS, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_SHADEMODE, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_TEXSHADELS, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_SHADEMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_TEXFUNC, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_COLORTEST, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_ALPHATESTENABLE, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_COLORTESTENABLE, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_COLORTESTMASK, FLAG_FLUSHBEFOREONCHANGE, DIRTY_ALPHACOLORMASK },
// These change the vertex shader so need flushing.
{ GE_CMD_REVERSENORMAL, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTINGENABLE, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTENABLE0, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTENABLE1, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTENABLE2, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTENABLE3, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTTYPE0, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTTYPE1, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTTYPE2, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTTYPE3, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_MATERIALUPDATE, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_REVERSENORMAL, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_LIGHTINGENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_LIGHTENABLE0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_LIGHTENABLE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_LIGHTENABLE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_LIGHTENABLE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_LIGHTTYPE0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_LIGHTTYPE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_LIGHTTYPE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_LIGHTTYPE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_MATERIALUPDATE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
// These change both shaders so need flushing.
{ GE_CMD_LIGHTMODE, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_LIGHTMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_TEXFILTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS },
{ GE_CMD_TEXWRAP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS },
@@ -109,7 +109,7 @@ const CommonCommandTableEntry commonCommandTable[] = {
{ GE_CMD_LOGICOP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE },
{ GE_CMD_LOGICOPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE },
{ GE_CMD_TEXMAPMODE, FLAG_FLUSHBEFOREONCHANGE, 0 },
{ GE_CMD_TEXMAPMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_TEXSCALEU, FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_TexScaleU },
{ GE_CMD_TEXSCALEV, FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_TexScaleV },
{ GE_CMD_TEXOFFSETU, FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_TexOffsetU },
@@ -161,7 +161,7 @@ const CommonCommandTableEntry commonCommandTable[] = {
// Control spline/bezier patches. Don't really require flushing as such, but meh.
{ GE_CMD_PATCHDIVISION, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_PATCHPRIMITIVE, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_PATCHFACING, FLAG_FLUSHBEFOREONCHANGE },
{ GE_CMD_PATCHFACING, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE },
{ GE_CMD_PATCHCULLENABLE, FLAG_FLUSHBEFOREONCHANGE },
// Can probably ignore this one as we don't support AA lines.
View
@@ -229,13 +229,13 @@ class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface {
protected:
void SetDrawType(DrawType type, GEPrimitiveType prim) {
if (type != lastDraw_) {
gstate_c.Dirty(DIRTY_UVSCALEOFFSET);
gstate_c.Dirty(DIRTY_UVSCALEOFFSET | DIRTY_VERTEXSHADER_STATE);
lastDraw_ = type;
}
// Prim == RECTANGLES can cause CanUseHardwareTransform to flip, so we need to dirty.
// Also, culling may be affected.
if ((prim == GE_PRIM_RECTANGLES) != (lastPrim_ == GE_PRIM_RECTANGLES)) {
gstate_c.Dirty(DIRTY_RASTER_STATE);
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE);
lastPrim_ = prim;
}
}
@@ -348,6 +348,7 @@ class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface {
bool interruptsEnabled_;
bool resized_;
DrawType lastDraw_;
GEPrimitiveType lastPrim_;
private:
@@ -456,12 +456,11 @@ void GPU_Vulkan::Execute_Prim(u32 op, u32 diff) {
u32 data = op & 0xFFFFFF;
u32 count = data & 0xFFFF;
// Upper bits are ignored.
GEPrimitiveType prim = static_cast<GEPrimitiveType>((data >> 16) & 7);
if (count == 0)
return;
// Upper bits are ignored.
GEPrimitiveType prim = static_cast<GEPrimitiveType>((data >> 16) & 7);
SetDrawType(DRAW_PRIM, prim);
// Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though.
@@ -522,8 +521,12 @@ void GPU_Vulkan::Execute_Prim(u32 op, u32 diff) {
}
void GPU_Vulkan::Execute_VertexType(u32 op, u32 diff) {
if (diff)
gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE);
if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) {
gstate_c.Dirty(DIRTY_UVSCALEOFFSET);
if (diff & GE_VTYPE_THROUGH_MASK)
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
}
}
Oops, something went wrong.

0 comments on commit 56cd991

Please sign in to comment.