mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Replace the "GetCurrentStepId"-based state invalidation with callbacks
This commit is contained in:
parent
a1c61abdda
commit
70d1d8fa07
21 changed files with 140 additions and 115 deletions
|
@ -606,6 +606,7 @@ add_library(Common STATIC
|
|||
Common/File/FileDescriptor.cpp
|
||||
Common/File/FileDescriptor.h
|
||||
Common/GPU/DataFormat.h
|
||||
Common/GPU/MiscTypes.h
|
||||
Common/GPU/thin3d.cpp
|
||||
Common/GPU/thin3d.h
|
||||
Common/GPU/thin3d_create.h
|
||||
|
|
|
@ -432,6 +432,7 @@
|
|||
<ClInclude Include="GPU\D3D9\D3D9ShaderCompiler.h" />
|
||||
<ClInclude Include="GPU\D3D9\D3D9StateCache.h" />
|
||||
<ClInclude Include="GPU\DataFormat.h" />
|
||||
<ClInclude Include="GPU\MiscTypes.h" />
|
||||
<ClInclude Include="GPU\OpenGL\DataFormatGL.h" />
|
||||
<ClInclude Include="GPU\OpenGL\gl3stub.h" />
|
||||
<ClInclude Include="GPU\OpenGL\GLFeatures.h" />
|
||||
|
|
|
@ -452,6 +452,9 @@
|
|||
<ClInclude Include="Render\ManagedTexture.h">
|
||||
<Filter>Render</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="GPU\MiscTypes.h">
|
||||
<Filter>GPU</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ABI.cpp" />
|
||||
|
|
|
@ -163,8 +163,8 @@ public:
|
|||
|
||||
void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override;
|
||||
|
||||
int GetCurrentStepId() const override {
|
||||
return stepId_;
|
||||
void SetInvalidationCallback(InvalidationCallback callback) override {
|
||||
invalidationCallback_ = callback;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -177,7 +177,6 @@ private:
|
|||
ID3D11DeviceContext *context_;
|
||||
ID3D11Device1 *device1_;
|
||||
ID3D11DeviceContext1 *context1_;
|
||||
int stepId_ = -1;
|
||||
|
||||
ID3D11Texture2D *bbRenderTargetTex_ = nullptr; // NOT OWNED
|
||||
ID3D11RenderTargetView *bbRenderTargetView_ = nullptr;
|
||||
|
@ -216,6 +215,8 @@ private:
|
|||
ID3D11Buffer *nextIndexBuffer_ = nullptr;
|
||||
int nextIndexBufferOffset_ = 0;
|
||||
|
||||
InvalidationCallback invalidationCallback_;
|
||||
|
||||
// Dynamic state
|
||||
float blendFactor_[4]{};
|
||||
bool blendFactorDirty_ = false;
|
||||
|
@ -399,7 +400,6 @@ void D3D11DrawContext::HandleEvent(Event ev, int width, int height, void *param1
|
|||
// Make sure that we don't eliminate the next time the render target is set.
|
||||
curRenderTargetView_ = nullptr;
|
||||
curDepthStencilView_ = nullptr;
|
||||
stepId_ = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1500,13 +1500,11 @@ void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x
|
|||
D3D11_BOX srcBox{ (UINT)x, (UINT)y, (UINT)z, (UINT)(x + width), (UINT)(y + height), (UINT)(z + depth) };
|
||||
context_->CopySubresourceRegion(dstTex, dstLevel, dstX, dstY, dstZ, srcTex, level, &srcBox);
|
||||
}
|
||||
stepId_++;
|
||||
}
|
||||
|
||||
bool D3D11DrawContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) {
|
||||
// Unfortunately D3D11 has no equivalent to this, gotta render a quad. Well, in some cases we can issue a copy instead.
|
||||
Crash();
|
||||
stepId_++;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1652,7 +1650,6 @@ bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channel
|
|||
if (!useGlobalPacktex) {
|
||||
packTex->Release();
|
||||
}
|
||||
stepId_++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1699,7 +1696,9 @@ void D3D11DrawContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Ren
|
|||
context_->ClearDepthStencilView(curDepthStencilView_, mask, rp.clearDepth, rp.clearStencil);
|
||||
}
|
||||
|
||||
stepId_++;
|
||||
if (invalidationCallback_) {
|
||||
invalidationCallback_(InvalidationFlags::RENDER_PASS_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
void D3D11DrawContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int layer) {
|
||||
|
|
|
@ -610,18 +610,17 @@ public:
|
|||
|
||||
void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override;
|
||||
|
||||
int GetCurrentStepId() const override {
|
||||
return stepId_;
|
||||
}
|
||||
|
||||
void InvalidateCachedState() override;
|
||||
|
||||
void SetInvalidationCallback(InvalidationCallback callback) override {
|
||||
invalidationCallback_ = callback;
|
||||
}
|
||||
|
||||
private:
|
||||
LPDIRECT3D9 d3d_;
|
||||
LPDIRECT3D9EX d3dEx_;
|
||||
LPDIRECT3DDEVICE9 device_;
|
||||
LPDIRECT3DDEVICE9EX deviceEx_;
|
||||
int stepId_ = -1;
|
||||
int adapterId_ = -1;
|
||||
D3DADAPTER_IDENTIFIER9 identifier_{};
|
||||
D3DCAPS9 d3dCaps_;
|
||||
|
@ -647,6 +646,8 @@ private:
|
|||
|
||||
// Dynamic state
|
||||
uint8_t stencilRef_ = 0;
|
||||
|
||||
InvalidationCallback invalidationCallback_;
|
||||
};
|
||||
|
||||
void D3D9Context::InvalidateCachedState() {
|
||||
|
@ -1319,7 +1320,10 @@ void D3D9Context::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPa
|
|||
dxstate.scissorRect.restore();
|
||||
dxstate.scissorTest.restore();
|
||||
dxstate.viewport.restore();
|
||||
stepId_++;
|
||||
|
||||
if (invalidationCallback_) {
|
||||
invalidationCallback_(InvalidationFlags::RENDER_PASS_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t D3D9Context::GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) {
|
||||
|
@ -1398,7 +1402,6 @@ bool D3D9Context::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
stepId_++;
|
||||
return SUCCEEDED(device_->StretchRect(srcSurf, &srcRect, dstSurf, &dstRect, (filter == FB_BLIT_LINEAR && channelBits == FB_COLOR_BIT) ? D3DTEXF_LINEAR : D3DTEXF_POINT));
|
||||
}
|
||||
|
||||
|
@ -1519,7 +1522,6 @@ void D3D9Context::HandleEvent(Event ev, int width, int height, void *param1, voi
|
|||
device_->GetDepthStencilSurface(&deviceDSsurf);
|
||||
break;
|
||||
case Event::PRESENTED:
|
||||
stepId_ = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
11
Common/GPU/MiscTypes.h
Normal file
11
Common/GPU/MiscTypes.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common/Common.h"
|
||||
|
||||
enum class InvalidationFlags {
|
||||
RENDER_PASS_STATE = 1,
|
||||
COMMAND_BUFFER_STATE = 2,
|
||||
};
|
||||
ENUM_CLASS_BITOPS(InvalidationFlags);
|
||||
|
||||
typedef std::function<void(InvalidationFlags)> InvalidationCallback;
|
|
@ -354,6 +354,10 @@ void GLRenderManager::BindFramebufferAsRenderTarget(GLRFramebuffer *fb, GLRRende
|
|||
step->dependencies.insert(fb);
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidationCallback_) {
|
||||
invalidationCallback_(InvalidationFlags::RENDER_PASS_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
void GLRenderManager::BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit) {
|
||||
|
@ -480,7 +484,6 @@ void GLRenderManager::BeginFrame() {
|
|||
// In GL, we have to do deletes on the submission thread.
|
||||
|
||||
insideFrame_ = true;
|
||||
renderStepOffset_ = 0;
|
||||
}
|
||||
|
||||
void GLRenderManager::Finish() {
|
||||
|
@ -612,9 +615,6 @@ void GLRenderManager::Run(int frame) {
|
|||
}
|
||||
|
||||
void GLRenderManager::FlushSync() {
|
||||
// TODO: Reset curRenderStep_?
|
||||
renderStepOffset_ += (int)steps_.size();
|
||||
|
||||
int curFrame = curFrame_;
|
||||
FrameData &frameData = frameData_[curFrame];
|
||||
{
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <condition_variable>
|
||||
|
||||
#include "Common/GPU/OpenGL/GLCommon.h"
|
||||
#include "Common/GPU/MiscTypes.h"
|
||||
#include "Common/Data/Convert/SmallDataConvert.h"
|
||||
#include "Common/Log.h"
|
||||
#include "GLQueueRunner.h"
|
||||
|
@ -368,6 +369,9 @@ public:
|
|||
GLRenderManager() {}
|
||||
~GLRenderManager();
|
||||
|
||||
void SetInvalidationCallback(InvalidationCallback callback) {
|
||||
invalidationCallback_ = callback;
|
||||
}
|
||||
void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {
|
||||
queueRunner_.SetErrorCallback(callback, userdata);
|
||||
}
|
||||
|
@ -980,12 +984,6 @@ public:
|
|||
skipGLCalls_ = true;
|
||||
}
|
||||
|
||||
// Gets a frame-unique ID of the current step being recorded. Can be used to figure out
|
||||
// when the current step has changed, which means the caller will need to re-record its state.
|
||||
int GetCurrentStepId() const {
|
||||
return renderStepOffset_ + (int)steps_.size();
|
||||
}
|
||||
|
||||
private:
|
||||
void BeginSubmitFrame(int frame);
|
||||
void EndSubmitFrame(int frame);
|
||||
|
@ -1033,8 +1031,7 @@ private:
|
|||
|
||||
// Submission time state
|
||||
bool insideFrame_ = false;
|
||||
// This is the offset within this frame, in case of a mid-frame sync.
|
||||
int renderStepOffset_ = 0;
|
||||
|
||||
GLRStep *curRenderStep_ = nullptr;
|
||||
std::vector<GLRStep *> steps_;
|
||||
std::vector<GLRInitStep> initSteps_;
|
||||
|
@ -1074,4 +1071,6 @@ private:
|
|||
GLRProgram *curProgram_ = nullptr;
|
||||
#endif
|
||||
Draw::DeviceCaps caps_{};
|
||||
|
||||
InvalidationCallback invalidationCallback_;
|
||||
};
|
||||
|
|
|
@ -466,12 +466,12 @@ public:
|
|||
|
||||
void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override {}
|
||||
|
||||
int GetCurrentStepId() const override {
|
||||
return renderManager_.GetCurrentStepId();
|
||||
}
|
||||
|
||||
void InvalidateCachedState() override;
|
||||
|
||||
void SetInvalidationCallback(InvalidationCallback callback) {
|
||||
renderManager_.SetInvalidationCallback(callback);
|
||||
}
|
||||
|
||||
private:
|
||||
void ApplySamplers();
|
||||
|
||||
|
|
|
@ -668,8 +668,6 @@ void VulkanRenderManager::BeginFrame(bool enableProfiling, bool enableLogProfile
|
|||
insideFrame_ = true;
|
||||
vulkan_->BeginFrame(enableLogProfiler ? GetInitCmd() : VK_NULL_HANDLE);
|
||||
|
||||
renderStepOffset_ = 0;
|
||||
|
||||
frameData.profile.timestampDescriptions.clear();
|
||||
if (frameData.profilingEnabled_) {
|
||||
// For various reasons, we need to always use an init cmd buffer in this case to perform the vkCmdResetQueryPool,
|
||||
|
@ -956,6 +954,10 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR
|
|||
data.clear.clearMask = lateClearMask;
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
if (invalidationCallback_) {
|
||||
invalidationCallback_(InvalidationFlags::RENDER_PASS_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
bool VulkanRenderManager::CopyFramebufferToMemorySync(VKRFramebuffer *src, VkImageAspectFlags aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag) {
|
||||
|
@ -1414,7 +1416,9 @@ void VulkanRenderManager::Run(VKRRenderThreadTask &task) {
|
|||
|
||||
// Called from main thread.
|
||||
void VulkanRenderManager::FlushSync() {
|
||||
renderStepOffset_ += (int)steps_.size();
|
||||
if (invalidationCallback_) {
|
||||
invalidationCallback_(InvalidationFlags::COMMAND_BUFFER_STATE);
|
||||
}
|
||||
|
||||
int curFrame = vulkan_->GetCurFrame();
|
||||
FrameData &frameData = frameData_[curFrame];
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "Common/Data/Convert/SmallDataConvert.h"
|
||||
#include "Common/Math/math_util.h"
|
||||
#include "Common/GPU/DataFormat.h"
|
||||
#include "Common/GPU/MiscTypes.h"
|
||||
#include "Common/GPU/Vulkan/VulkanQueueRunner.h"
|
||||
|
||||
// Forward declaration
|
||||
|
@ -235,6 +236,10 @@ public:
|
|||
// Zaps queued up commands. Use if you know there's a risk you've queued up stuff that has already been deleted. Can happen during in-game shutdown.
|
||||
void Wipe();
|
||||
|
||||
void SetInvalidationCallback(InvalidationCallback callback) {
|
||||
invalidationCallback_ = callback;
|
||||
}
|
||||
|
||||
// This starts a new step containing a render pass (unless it can be trivially merged into the previous one, which is pretty common).
|
||||
//
|
||||
// After a "CopyFramebuffer" or the other functions that start "steps", you need to call this beforce
|
||||
|
@ -475,12 +480,6 @@ public:
|
|||
|
||||
VkCommandBuffer GetInitCmd();
|
||||
|
||||
// Gets a frame-unique ID of the current step being recorded. Can be used to figure out
|
||||
// when the current step has changed, which means the caller will need to re-record its state.
|
||||
int GetCurrentStepId() const {
|
||||
return renderStepOffset_ + (int)steps_.size();
|
||||
}
|
||||
|
||||
bool CreateBackbuffers();
|
||||
void DestroyBackbuffers();
|
||||
|
||||
|
@ -520,7 +519,6 @@ private:
|
|||
void DrainCompileQueue();
|
||||
|
||||
void Run(VKRRenderThreadTask &task);
|
||||
void BeginSubmitFrame(int frame);
|
||||
|
||||
// Bad for performance but sometimes necessary for synchronous CPU readbacks (screenshots and whatnot).
|
||||
void FlushSync();
|
||||
|
@ -548,7 +546,6 @@ private:
|
|||
bool run_ = false;
|
||||
|
||||
// This is the offset within this frame, in case of a mid-frame sync.
|
||||
int renderStepOffset_ = 0;
|
||||
VKRStep *curRenderStep_ = nullptr;
|
||||
bool curStepHasViewport_ = false;
|
||||
bool curStepHasScissor_ = false;
|
||||
|
@ -587,4 +584,6 @@ private:
|
|||
SimpleStat initTimeMs_;
|
||||
SimpleStat totalGPUTimeMs_;
|
||||
SimpleStat renderCPUTimeMs_;
|
||||
|
||||
std::function<void(InvalidationFlags)> invalidationCallback_;
|
||||
};
|
||||
|
|
|
@ -498,14 +498,14 @@ public:
|
|||
|
||||
void HandleEvent(Event ev, int width, int height, void *param1, void *param2) override;
|
||||
|
||||
int GetCurrentStepId() const override {
|
||||
return renderManager_.GetCurrentStepId();
|
||||
}
|
||||
|
||||
void InvalidateCachedState() override;
|
||||
|
||||
void InvalidateFramebuffer(FBInvalidationStage stage, uint32_t channels) override;
|
||||
|
||||
void SetInvalidationCallback(InvalidationCallback callback) {
|
||||
renderManager_.SetInvalidationCallback(callback);
|
||||
}
|
||||
|
||||
private:
|
||||
VulkanTexture *GetNullTexture();
|
||||
VulkanContext *vulkan_ = nullptr;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "Common/Common.h"
|
||||
#include "Common/GPU/DataFormat.h"
|
||||
#include "Common/GPU/Shader.h"
|
||||
#include "Common/GPU/MiscTypes.h"
|
||||
#include "Common/Data/Collections/Slice.h"
|
||||
|
||||
namespace Lin {
|
||||
|
@ -769,7 +770,9 @@ public:
|
|||
// This is called when we launch a new game, so any collected internal stats in the backends don't carry over.
|
||||
virtual void ResetStats() {}
|
||||
|
||||
virtual int GetCurrentStepId() const = 0;
|
||||
// Used by the DrawEngines to know when they have to re-apply some state.
|
||||
// Not very elegant, but more elegant than the old passId hack.
|
||||
virtual void SetInvalidationCallback(InvalidationCallback callback) = 0;
|
||||
|
||||
protected:
|
||||
ShaderModule *vsPresets_[VS_MAX_PRESET];
|
||||
|
|
|
@ -113,6 +113,8 @@ void DrawEngineD3D11::InitDeviceObjects() {
|
|||
|
||||
tessDataTransferD3D11 = new TessellationDataTransferD3D11(context_, device_);
|
||||
tessDataTransfer = tessDataTransferD3D11;
|
||||
|
||||
draw_->SetInvalidationCallback(std::bind(&DrawEngineD3D11::Invalidate, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void DrawEngineD3D11::ClearTrackedVertexArrays() {
|
||||
|
@ -136,6 +138,8 @@ void DrawEngineD3D11::NotifyConfigChanged() {
|
|||
}
|
||||
|
||||
void DrawEngineD3D11::DestroyDeviceObjects() {
|
||||
draw_->SetInvalidationCallback(InvalidationCallback());
|
||||
|
||||
ClearTrackedVertexArrays();
|
||||
ClearInputLayoutMap();
|
||||
delete tessDataTransferD3D11;
|
||||
|
@ -322,19 +326,18 @@ VertexArrayInfoD3D11::~VertexArrayInfoD3D11() {
|
|||
ebo->Release();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
|
||||
textureCache_->ForgetLastTexture();
|
||||
}
|
||||
}
|
||||
|
||||
// The inline wrapper in the header checks for numDrawCalls == 0
|
||||
void DrawEngineD3D11::DoFlush() {
|
||||
gpuStats.numFlushes++;
|
||||
|
||||
// In D3D, we're synchronous and state carries over so all we reset here on a new step is the viewport/scissor.
|
||||
int curRenderStepId = draw_->GetCurrentStepId();
|
||||
if (lastRenderStepId_ != curRenderStepId) {
|
||||
// Dirty everything that has dynamic state that will need re-recording.
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
|
||||
textureCache_->ForgetLastTexture();
|
||||
lastRenderStepId_ = curRenderStepId;
|
||||
}
|
||||
|
||||
bool textureNeedsApply = false;
|
||||
if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) {
|
||||
textureCache_->SetTexture();
|
||||
|
|
|
@ -155,6 +155,8 @@ public:
|
|||
void ClearInputLayoutMap();
|
||||
|
||||
private:
|
||||
void Invalidate(InvalidationFlags flags);
|
||||
|
||||
void DoFlush();
|
||||
|
||||
void ApplyDrawState(int prim);
|
||||
|
|
|
@ -126,10 +126,11 @@ DrawEngineDX9::~DrawEngineDX9() {
|
|||
}
|
||||
|
||||
void DrawEngineDX9::InitDeviceObjects() {
|
||||
|
||||
draw_->SetInvalidationCallback(std::bind(&DrawEngineDX9::Invalidate, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void DrawEngineDX9::DestroyDeviceObjects() {
|
||||
draw_->SetInvalidationCallback(InvalidationCallback());
|
||||
ClearTrackedVertexArrays();
|
||||
}
|
||||
|
||||
|
@ -310,18 +311,17 @@ void DrawEngineDX9::BeginFrame() {
|
|||
lastRenderStepId_ = -1;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
|
||||
}
|
||||
}
|
||||
|
||||
// The inline wrapper in the header checks for numDrawCalls == 0
|
||||
void DrawEngineDX9::DoFlush() {
|
||||
gpuStats.numFlushes++;
|
||||
|
||||
// In D3D, we're synchronous and state carries over so all we reset here on a new step is the viewport/scissor.
|
||||
int curRenderStepId = draw_->GetCurrentStepId();
|
||||
if (lastRenderStepId_ != curRenderStepId) {
|
||||
// Dirty everything that has dynamic state that will need re-recording.
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
|
||||
lastRenderStepId_ = curRenderStepId;
|
||||
}
|
||||
|
||||
bool textureNeedsApply = false;
|
||||
if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) {
|
||||
textureCache_->SetTexture();
|
||||
|
|
|
@ -144,6 +144,7 @@ protected:
|
|||
void DecimateTrackedVertexArrays();
|
||||
|
||||
private:
|
||||
void Invalidate(InvalidationFlags flags);
|
||||
void DoFlush();
|
||||
|
||||
void ApplyDrawState(int prim);
|
||||
|
|
|
@ -117,9 +117,13 @@ void DrawEngineGLES::InitDeviceObjects() {
|
|||
entries.push_back({ ATTR_COLOR1, 3, GL_UNSIGNED_BYTE, GL_TRUE, vertexSize, offsetof(TransformedVertex, color1) });
|
||||
entries.push_back({ ATTR_NORMAL, 1, GL_FLOAT, GL_FALSE, vertexSize, offsetof(TransformedVertex, fog) });
|
||||
softwareInputLayout_ = render_->CreateInputLayout(entries);
|
||||
|
||||
draw_->SetInvalidationCallback(std::bind(&DrawEngineGLES::Invalidate, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
void DrawEngineGLES::DestroyDeviceObjects() {
|
||||
draw_->SetInvalidationCallback(InvalidationCallback());
|
||||
|
||||
// Beware: this could be called twice in a row, sometimes.
|
||||
for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) {
|
||||
if (!frameData_[i].pushVertex && !frameData_[i].pushIndex)
|
||||
|
@ -238,22 +242,22 @@ void *DrawEngineGLES::DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bind
|
|||
return dest;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// 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);
|
||||
textureCache_->ForgetLastTexture();
|
||||
}
|
||||
}
|
||||
|
||||
void DrawEngineGLES::DoFlush() {
|
||||
PROFILE_THIS_SCOPE("flush");
|
||||
FrameData &frameData = frameData_[render_->GetCurFrame()];
|
||||
|
||||
gpuStats.numFlushes++;
|
||||
|
||||
// A new render step means we need to flush any dynamic state. Really, any state that is reset in
|
||||
// GLQueueRunner::PerformRenderPass.
|
||||
int curRenderStepId = render_->GetCurrentStepId();
|
||||
if (lastRenderStepId_ != curRenderStepId) {
|
||||
// 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);
|
||||
textureCache_->ForgetLastTexture();
|
||||
lastRenderStepId_ = curRenderStepId;
|
||||
}
|
||||
|
||||
bool textureNeedsApply = false;
|
||||
if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) {
|
||||
textureCache_->SetTexture();
|
||||
|
|
|
@ -84,7 +84,6 @@ public:
|
|||
void BeginFrame();
|
||||
void EndFrame();
|
||||
|
||||
|
||||
// So that this can be inlined
|
||||
void Flush() {
|
||||
if (!numDrawCalls)
|
||||
|
@ -117,6 +116,8 @@ protected:
|
|||
bool UpdateUseHWTessellation(bool enable) override;
|
||||
|
||||
private:
|
||||
void Invalidate(InvalidationFlags flags);
|
||||
|
||||
void InitDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include "Common/Data/Convert/SmallDataConvert.h"
|
||||
#include "Common/Profiler/Profiler.h"
|
||||
|
@ -150,7 +151,7 @@ void DrawEngineVulkan::InitDeviceObjects() {
|
|||
dpTypes[2].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
dpTypes[3].descriptorCount = DEFAULT_DESC_POOL_SIZE; // TODO: Use a separate layout when no spline stuff is needed to reduce the need for these.
|
||||
dpTypes[3].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
||||
dpTypes[4].descriptorCount = 1; // For the frame global uniform buffer.
|
||||
dpTypes[4].descriptorCount = DEFAULT_DESC_POOL_SIZE; // For the frame global uniform buffer. Might need to allocate multiple times.
|
||||
dpTypes[4].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
|
||||
VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO };
|
||||
|
@ -204,6 +205,8 @@ void DrawEngineVulkan::InitDeviceObjects() {
|
|||
|
||||
tessDataTransferVulkan = new TessellationDataTransferVulkan(vulkan);
|
||||
tessDataTransfer = tessDataTransferVulkan;
|
||||
|
||||
draw_->SetInvalidationCallback(std::bind(&DrawEngineVulkan::Invalidate, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
DrawEngineVulkan::~DrawEngineVulkan() {
|
||||
|
@ -234,7 +237,14 @@ void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) {
|
|||
}
|
||||
|
||||
void DrawEngineVulkan::DestroyDeviceObjects() {
|
||||
VulkanContext *vulkan = draw_ ? (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT) : nullptr;
|
||||
if (!draw_) {
|
||||
// We've already done this from LostDevice.
|
||||
return;
|
||||
}
|
||||
|
||||
VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT);
|
||||
|
||||
draw_->SetInvalidationCallback(InvalidationCallback());
|
||||
|
||||
delete tessDataTransferVulkan;
|
||||
tessDataTransfer = nullptr;
|
||||
|
@ -283,8 +293,6 @@ void DrawEngineVulkan::BeginFrame() {
|
|||
|
||||
lastPipeline_ = nullptr;
|
||||
|
||||
lastRenderStepId_ = -1;
|
||||
|
||||
FrameData *frame = &GetCurFrame();
|
||||
|
||||
// First reset all buffers, then begin. This is so that Reset can free memory and Begin can allocate it,
|
||||
|
@ -536,6 +544,21 @@ void MarkUnreliable(VertexArrayInfoVulkan *vai) {
|
|||
// For now we just leave it in the pushbuffer.
|
||||
}
|
||||
|
||||
void DrawEngineVulkan::Invalidate(InvalidationFlags flags) {
|
||||
if (flags & InvalidationFlags::COMMAND_BUFFER_STATE) {
|
||||
GetCurFrame().frameDescSetUpdated = false;
|
||||
}
|
||||
if (flags & InvalidationFlags::RENDER_PASS_STATE) {
|
||||
// If have a new render pass, dirty our dynamic state so it gets re-set.
|
||||
// We have to do this again after the last possible place in DoFlush that can cause a renderpass switch
|
||||
// like a shader blend blit or similar. But before we actually set the 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_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
|
||||
lastPipeline_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// The inline wrapper in the header checks for numDrawCalls == 0
|
||||
void DrawEngineVulkan::DoFlush() {
|
||||
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
|
@ -545,18 +568,6 @@ void DrawEngineVulkan::DoFlush() {
|
|||
|
||||
gpuStats.numFlushes++;
|
||||
|
||||
// If have a new render pass, dirty our dynamic state so it gets re-set.
|
||||
// We have to do this again after the last possible place in DoFlush that can cause a renderpass switch
|
||||
// like a shader blend blit or similar. But before we actually set the state!
|
||||
int curRenderStepId = renderManager->GetCurrentStepId();
|
||||
if (lastRenderStepId_ != curRenderStepId) {
|
||||
// Dirty everything that has dynamic state that will need re-recording.
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_BLEND_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
|
||||
textureCache_->ForgetLastTexture();
|
||||
lastRenderStepId_ = curRenderStepId;
|
||||
lastPipeline_ = nullptr;
|
||||
}
|
||||
|
||||
bool tess = gstate_c.submitType == SubmitType::HW_BEZIER || gstate_c.submitType == SubmitType::HW_SPLINE;
|
||||
|
||||
bool textureNeedsApply = false;
|
||||
|
@ -785,16 +796,6 @@ void DrawEngineVulkan::DoFlush() {
|
|||
}
|
||||
BindShaderBlendTex(); // This might cause copies so important to do before BindPipeline.
|
||||
|
||||
// If have a new render pass, dirty our dynamic state so it gets re-set.
|
||||
// WARNING: We have to do this AFTER the last possible place in DoFlush that can cause a renderpass switch
|
||||
// like a shader blend blit or similar. But before we actually set the state!
|
||||
int curRenderStepId = renderManager->GetCurrentStepId();
|
||||
if (lastRenderStepId_ != curRenderStepId) {
|
||||
// Dirty everything that has dynamic state that will need re-recording.
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_BLEND_STATE);
|
||||
lastRenderStepId_ = curRenderStepId;
|
||||
}
|
||||
|
||||
renderManager->BindPipeline(pipeline->pipeline, pipeline->pipelineFlags, pipelineLayout_);
|
||||
if (pipeline != lastPipeline_) {
|
||||
if (lastPipeline_ && !(lastPipeline_->UsesBlendConstant() && pipeline->UsesBlendConstant())) {
|
||||
|
@ -928,16 +929,6 @@ void DrawEngineVulkan::DoFlush() {
|
|||
}
|
||||
BindShaderBlendTex(); // This might cause copies so super important to do before BindPipeline.
|
||||
|
||||
// If have a new render pass, dirty our dynamic state so it gets re-set.
|
||||
// WARNING: We have to do this AFTER the last possible place in DoFlush that can cause a renderpass switch
|
||||
// like a shader blend blit or similar. But before we actually set the state!
|
||||
int curRenderStepId = renderManager->GetCurrentStepId();
|
||||
if (lastRenderStepId_ != curRenderStepId) {
|
||||
// Dirty everything that has dynamic state that will need re-recording.
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_BLEND_STATE);
|
||||
lastRenderStepId_ = curRenderStepId;
|
||||
}
|
||||
|
||||
renderManager->BindPipeline(pipeline->pipeline, pipeline->pipelineFlags, pipelineLayout_);
|
||||
if (pipeline != lastPipeline_) {
|
||||
if (lastPipeline_ && !lastPipeline_->UsesBlendConstant() && pipeline->UsesBlendConstant()) {
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
#include "GPU/Common/GPUStateUtils.h"
|
||||
#include "GPU/Vulkan/StateMappingVulkan.h"
|
||||
#include "GPU/Vulkan/VulkanRenderManager.h"
|
||||
|
||||
struct DecVtxFormat;
|
||||
struct UVScale;
|
||||
|
@ -208,6 +209,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
void Invalidate(InvalidationFlags flags);
|
||||
|
||||
struct FrameData;
|
||||
void ApplyDrawStateLate(VulkanRenderManager *renderManager, bool applyStencilRef, uint8_t stencilRef, bool useBlendConstant);
|
||||
void ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManager, ShaderManagerVulkan *shaderManager, int prim, VulkanPipelineRasterStateKey &key, VulkanDynamicState &dynState);
|
||||
|
@ -308,6 +311,4 @@ private:
|
|||
|
||||
// Hardware tessellation
|
||||
TessellationDataTransferVulkan *tessDataTransferVulkan;
|
||||
|
||||
int lastRenderStepId_ = -1;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue