Add a flags parameter to InvalidateCachedState and rename it Invalidate.

Also rename the old InvalidationFlags enum to InvalidateCallbackFlags.
This commit is contained in:
Henrik Rydgård 2022-12-01 19:15:38 +01:00
parent 2067ae127a
commit 331d024a8c
24 changed files with 89 additions and 76 deletions

View file

@ -99,7 +99,7 @@ public:
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
void InvalidateCachedState() override;
void Invalidate(InvalidationFlags flags) override;
void BindTextures(int start, int count, Texture **textures, TextureBindFlags flags) override;
void BindNativeTexture(int index, void *nativeTexture) override;
@ -1080,17 +1080,19 @@ void D3D11DrawContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
context_->Unmap(curPipeline_->dynamicUniforms, 0);
}
void D3D11DrawContext::InvalidateCachedState() {
// This is a signal to forget all our state caching.
curBlend_ = nullptr;
curDepthStencil_ = nullptr;
curRaster_ = nullptr;
curPS_ = nullptr;
curVS_ = nullptr;
curGS_ = nullptr;
curInputLayout_ = nullptr;
curTopology_ = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
curPipeline_ = nullptr;
void D3D11DrawContext::Invalidate(InvalidationFlags flags) {
if (flags & InvalidationFlags::CACHED_RENDER_STATE) {
// This is a signal to forget all our state caching.
curBlend_ = nullptr;
curDepthStencil_ = nullptr;
curRaster_ = nullptr;
curPS_ = nullptr;
curVS_ = nullptr;
curGS_ = nullptr;
curInputLayout_ = nullptr;
curTopology_ = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
curPipeline_ = nullptr;
}
}
void D3D11DrawContext::BindPipeline(Pipeline *pipeline) {
@ -1698,7 +1700,7 @@ void D3D11DrawContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Ren
}
if (invalidationCallback_) {
invalidationCallback_(InvalidationFlags::RENDER_PASS_STATE);
invalidationCallback_(InvalidationCallbackFlags::RENDER_PASS_STATE);
}
}

View file

@ -610,7 +610,7 @@ public:
void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override;
void InvalidateCachedState() override;
void Invalidate(InvalidationFlags flags) override;
void SetInvalidationCallback(InvalidationCallback callback) override {
invalidationCallback_ = callback;
@ -650,8 +650,10 @@ private:
InvalidationCallback invalidationCallback_;
};
void D3D9Context::InvalidateCachedState() {
curPipeline_ = nullptr;
void D3D9Context::Invalidate(InvalidationFlags flags) {
if (flags & InvalidationFlags::CACHED_RENDER_STATE) {
curPipeline_ = nullptr;
}
}
// TODO: Move this detection elsewhere when it's needed elsewhere, not before. It's ugly.
@ -1323,7 +1325,7 @@ void D3D9Context::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPa
dxstate.viewport.restore();
if (invalidationCallback_) {
invalidationCallback_(InvalidationFlags::RENDER_PASS_STATE);
invalidationCallback_(InvalidationCallbackFlags::RENDER_PASS_STATE);
}
}

View file

@ -3,9 +3,14 @@
#include "Common/Common.h"
enum class InvalidationFlags {
RENDER_PASS_STATE = 1,
COMMAND_BUFFER_STATE = 2,
CACHED_RENDER_STATE = 1,
};
ENUM_CLASS_BITOPS(InvalidationFlags);
typedef std::function<void(InvalidationFlags)> InvalidationCallback;
enum class InvalidationCallbackFlags {
RENDER_PASS_STATE = 1,
COMMAND_BUFFER_STATE = 2,
};
ENUM_CLASS_BITOPS(InvalidationCallbackFlags);
typedef std::function<void(InvalidationCallbackFlags)> InvalidationCallback;

View file

@ -356,7 +356,7 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende
}
if (invalidationCallback_) {
invalidationCallback_(InvalidationFlags::RENDER_PASS_STATE);
invalidationCallback_(InvalidationCallbackFlags::RENDER_PASS_STATE);
}
}

View file

@ -467,7 +467,7 @@ public:
void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override {}
void InvalidateCachedState() override;
void Invalidate(InvalidationFlags flags) override;
void SetInvalidationCallback(InvalidationCallback callback) override {
renderManager_.SetInvalidationCallback(callback);
@ -761,18 +761,20 @@ void OpenGLContext::EndFrame() {
renderManager_.EndPushBuffer(frameData.push); // upload the data!
renderManager_.Finish();
InvalidateCachedState();
Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
}
void OpenGLContext::InvalidateCachedState() {
// Unbind stuff.
for (auto &texture : boundTextures_) {
texture = nullptr;
void OpenGLContext::Invalidate(InvalidationFlags flags) {
if (flags & InvalidationFlags::CACHED_RENDER_STATE) {
// Unbind stuff.
for (auto &texture : boundTextures_) {
texture = nullptr;
}
for (auto &sampler : boundSamplers_) {
sampler = nullptr;
}
curPipeline_ = nullptr;
}
for (auto &sampler : boundSamplers_) {
sampler = nullptr;
}
curPipeline_ = nullptr;
}
InputLayout *OpenGLContext::CreateInputLayout(const InputLayoutDesc &desc) {

View file

@ -752,7 +752,7 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
}
if (invalidationCallback_) {
invalidationCallback_(InvalidationFlags::RENDER_PASS_STATE);
invalidationCallback_(InvalidationCallbackFlags::RENDER_PASS_STATE);
}
}
@ -1213,7 +1213,7 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) {
// Called from main thread.
void VulkanRenderManager::FlushSync() {
if (invalidationCallback_) {
invalidationCallback_(InvalidationFlags::COMMAND_BUFFER_STATE);
invalidationCallback_(InvalidationCallbackFlags::COMMAND_BUFFER_STATE);
}
int curFrame = vulkan_->GetCurFrame();

View file

@ -526,5 +526,5 @@ private:
SimpleStat totalGPUTimeMs_;
SimpleStat renderCPUTimeMs_;
std::function<void(InvalidationFlags)> invalidationCallback_;
std::function<void(InvalidationCallbackFlags)> invalidationCallback_;
};

View file

@ -498,7 +498,7 @@ public:
void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override;
void InvalidateCachedState() override;
void Invalidate(InvalidationFlags flags) override;
void InvalidateFramebuffer(FBInvalidationStage stage, uint32_t channels) override;
@ -1021,20 +1021,22 @@ void VKContext::EndFrame() {
push_ = nullptr;
// Unbind stuff, to avoid accidentally relying on it across frames (and provide some protection against forgotten unbinds of deleted things).
InvalidateCachedState();
Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
}
void VKContext::InvalidateCachedState() {
curPipeline_ = nullptr;
void VKContext::Invalidate(InvalidationFlags flags) {
if (flags & InvalidationFlags::CACHED_RENDER_STATE) {
curPipeline_ = nullptr;
for (auto &view : boundImageView_) {
view = VK_NULL_HANDLE;
}
for (auto &sampler : boundSamplers_) {
sampler = nullptr;
}
for (auto &texture : boundTextures_) {
texture = nullptr;
for (auto &view : boundImageView_) {
view = VK_NULL_HANDLE;
}
for (auto &sampler : boundSamplers_) {
sampler = nullptr;
}
for (auto &texture : boundTextures_) {
texture = nullptr;
}
}
}

View file

@ -737,7 +737,7 @@ public:
// Clear state cached within thin3d. Must be called after directly calling API functions.
// Note that framebuffer state (which framebuffer is bounds) may not be cached.
// Must not actually perform any API calls itself since this can be called when no framebuffer is bound for rendering.
virtual void InvalidateCachedState() = 0;
virtual void Invalidate(InvalidationFlags flags) = 0;
virtual void BindPipeline(Pipeline *pipeline) = 0;

View file

@ -330,7 +330,7 @@ void Draw2D::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCoun
draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, linearFilter ? &draw2DSamplerLinear_ : &draw2DSamplerNearest_);
draw_->DrawUP(verts, vertexCount);
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE | DIRTY_VERTEXSHADER_STATE);
}

View file

@ -664,7 +664,7 @@ void FramebufferManagerCommon::CopyToDepthFromOverlappingFramebuffers(VirtualFra
// for (auto &source : sources) {
if (!sources.empty()) {
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
auto &source = sources.back();
if (source.channel == RASTER_DEPTH) {
@ -804,7 +804,7 @@ void FramebufferManagerCommon::CopyToColorFromOverlappingFramebuffers(VirtualFra
std::sort(sources.begin(), sources.end());
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
bool tookActions = false;
@ -961,7 +961,7 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir
RebindFramebuffer("After BlitFramebufferDepth");
}
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
}
void FramebufferManagerCommon::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) {
@ -1137,7 +1137,7 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int
gpuStats.numUploads++;
pixelsTex->Release();
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
gstate_c.Dirty(DIRTY_ALL_RENDER_STATE);
}
@ -2777,7 +2777,7 @@ void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb,
}
}
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
textureCache_->ForgetLastTexture();
RebindFramebuffer("RebindFramebuffer - ReadFramebufferToMemory");
}
@ -2840,7 +2840,7 @@ void FramebufferManagerCommon::DownloadFramebufferForClut(u32 fb_address, u32 lo
}
void FramebufferManagerCommon::RebindFramebuffer(const char *tag) {
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
shaderManager_->DirtyLastShader();
if (currentRenderVfb_ && currentRenderVfb_->fbo) {
draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, tag);
@ -3064,7 +3064,7 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
BlitUsingRaster(srcFBO, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, false, dst->renderScaleFactor, pipeline, tag);
}
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
gstate_c.Dirty(DIRTY_ALL_RENDER_STATE);
}

View file

@ -605,7 +605,7 @@ void PresentationCommon::UpdateUniforms(bool hasVideo) {
}
void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u0, float v0, float u1, float v1) {
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
// TODO: If shader objects have been created by now, we might have received errors.
// GLES can have the shader fail later, shader->failed / shader->error.
@ -869,7 +869,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u
DoRelease(srcTexture_);
// Unbinds all textures and samplers too, needed since sometimes a MakePixelTexture is deleted etc.
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
previousUniforms_ = uniforms;
}

View file

@ -357,7 +357,7 @@ bool FramebufferManagerCommon::PerformWriteStencilFromMemory(u32 addr, int size,
}
tex->Release();
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
gstate_c.Dirty(DIRTY_ALL_RENDER_STATE);
return true;
}

View file

@ -2187,7 +2187,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
CheckAlphaResult alphaStatus = CheckCLUTAlpha((const uint8_t *)clutBufRaw_, clutFormat, clutTotalColors);
gstate_c.SetTextureFullAlpha(alphaStatus == CHECKALPHA_FULL);
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
InvalidateLastTexture();
return;
}
@ -2262,7 +2262,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
CheckAlphaResult alphaStatus = CheckCLUTAlpha((const uint8_t *)clutBufRaw_, clutFormat, clutTotalColors);
gstate_c.SetTextureFullAlpha(alphaStatus == CHECKALPHA_FULL);
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
shaderManager_->DirtyLastShader();
} else {
framebufferManager_->RebindFramebuffer("ApplyTextureFramebuffer");
@ -2363,7 +2363,7 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) {
// We don't know about alpha at all.
gstate_c.SetTextureFullAlpha(false);
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
shaderManager_->DirtyLastShader();
SamplerCacheKey samplerKey = GetFramebufferSamplingParams(texWidth, texHeight);

View file

@ -327,8 +327,8 @@ VertexArrayInfoD3D11::~VertexArrayInfoD3D11() {
}
// In D3D, we're synchronous and state carries over so all we reset here on a new step is the viewport/scissor.
void DrawEngineD3D11::Invalidate(InvalidationFlags flags) {
if (flags & InvalidationFlags::RENDER_PASS_STATE) {
void DrawEngineD3D11::Invalidate(InvalidationCallbackFlags flags) {
if (flags & InvalidationCallbackFlags::RENDER_PASS_STATE) {
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
}
}

View file

@ -155,7 +155,7 @@ public:
void ClearInputLayoutMap();
private:
void Invalidate(InvalidationFlags flags);
void Invalidate(InvalidationCallbackFlags flags);
void DoFlush();

View file

@ -131,7 +131,7 @@ void GPU_D3D11::BuildReportingInfo() {
}
void GPU_D3D11::DeviceLost() {
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
// Simply drop all caches and textures.
// FBOs appear to survive? Or no?
shaderManagerD3D11_->ClearShaders();

View file

@ -312,8 +312,8 @@ void DrawEngineDX9::BeginFrame() {
}
// In D3D, we're synchronous and state carries over so all we reset here on a new step is the viewport/scissor.
void DrawEngineDX9::Invalidate(InvalidationFlags flags) {
if (flags & InvalidationFlags::RENDER_PASS_STATE) {
void DrawEngineDX9::Invalidate(InvalidationCallbackFlags flags) {
if (flags & InvalidationCallbackFlags::RENDER_PASS_STATE) {
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
}
}

View file

@ -144,7 +144,7 @@ protected:
void DecimateTrackedVertexArrays();
private:
void Invalidate(InvalidationFlags flags);
void Invalidate(InvalidationCallbackFlags flags);
void DoFlush();
void ApplyDrawState(int prim);

View file

@ -247,8 +247,8 @@ void *DrawEngineGLES::DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bind
// A new render step means we need to flush any dynamic state. Really, any state that is reset in
// GLQueueRunner::PerformRenderPass.
void DrawEngineGLES::Invalidate(InvalidationFlags flags) {
if (flags & InvalidationFlags::RENDER_PASS_STATE) {
void DrawEngineGLES::Invalidate(InvalidationCallbackFlags flags) {
if (flags & InvalidationCallbackFlags::RENDER_PASS_STATE) {
// Dirty everything that has dynamic state that will need re-recording.
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
}

View file

@ -116,7 +116,7 @@ protected:
bool UpdateUseHWTessellation(bool enable) override;
private:
void Invalidate(InvalidationFlags flags);
void Invalidate(InvalidationCallbackFlags flags);
void InitDeviceObjects();
void DestroyDeviceObjects();

View file

@ -492,7 +492,7 @@ void GPUCommon::BeginHostFrame() {
void GPUCommon::EndHostFrame() {
// Probably not necessary.
if (draw_) {
draw_->InvalidateCachedState();
draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE);
}
}

View file

@ -544,11 +544,11 @@ void MarkUnreliable(VertexArrayInfoVulkan *vai) {
// For now we just leave it in the pushbuffer.
}
void DrawEngineVulkan::Invalidate(InvalidationFlags flags) {
if (flags & InvalidationFlags::COMMAND_BUFFER_STATE) {
void DrawEngineVulkan::Invalidate(InvalidationCallbackFlags flags) {
if (flags & InvalidationCallbackFlags::COMMAND_BUFFER_STATE) {
GetCurFrame().frameDescSetUpdated = false;
}
if (flags & InvalidationFlags::RENDER_PASS_STATE) {
if (flags & InvalidationCallbackFlags::RENDER_PASS_STATE) {
// If have a new render pass, dirty our dynamic state so it gets re-set.
//
// Dirty everything that has dynamic state that will need re-recording.

View file

@ -209,7 +209,7 @@ public:
}
private:
void Invalidate(InvalidationFlags flags);
void Invalidate(InvalidationCallbackFlags flags);
struct FrameData;
void ApplyDrawStateLate(VulkanRenderManager *renderManager, bool applyStencilRef, uint8_t stencilRef, bool useBlendConstant);