From 49db27b6d3c243514f536ff75969bf0c00061c6c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 May 2020 09:57:01 -0700 Subject: [PATCH 1/6] GPU: Avoid immediate postshader FBO recreate. Before, we created things at the wrong size, then recreated at the right. Now we just start at the correct size once. --- GPU/Common/FramebufferCommon.cpp | 5 ++--- GPU/D3D11/GPU_D3D11.cpp | 2 +- GPU/Directx9/GPU_DX9.cpp | 2 +- GPU/GLES/FramebufferManagerGLES.cpp | 2 -- GPU/GLES/GPU_GLES.cpp | 2 +- GPU/Vulkan/FramebufferVulkan.cpp | 6 ------ GPU/Vulkan/FramebufferVulkan.h | 2 -- GPU/Vulkan/GPU_Vulkan.cpp | 2 +- 8 files changed, 6 insertions(+), 17 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index e3701b6d48..612c558864 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -45,7 +45,6 @@ FramebufferManagerCommon::FramebufferManagerCommon(Draw::DrawContext *draw) : draw_(draw), displayFormat_(GE_FORMAT_565) { presentation_ = new PresentationCommon(draw); - UpdateSize(); } FramebufferManagerCommon::~FramebufferManagerCommon() { @@ -70,8 +69,8 @@ FramebufferManagerCommon::~FramebufferManagerCommon() { } void FramebufferManagerCommon::Init() { - BeginFrame(); - presentation_->UpdatePostShader(); + // We may need to override the render size if the shader is upscaling or SSAA. + Resized(); } bool FramebufferManagerCommon::UpdateSize() { diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 29faefeef3..6e497064c7 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -87,10 +87,10 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) drawEngine_.SetShaderManager(shaderManagerD3D11_); drawEngine_.SetTextureCache(textureCacheD3D11_); drawEngine_.SetFramebufferManager(framebufferManagerD3D11_); - framebufferManagerD3D11_->Init(); framebufferManagerD3D11_->SetTextureCache(textureCacheD3D11_); framebufferManagerD3D11_->SetShaderManager(shaderManagerD3D11_); framebufferManagerD3D11_->SetDrawEngine(&drawEngine_); + framebufferManagerD3D11_->Init(); textureCacheD3D11_->SetFramebufferManager(framebufferManagerD3D11_); textureCacheD3D11_->SetDepalShaderCache(depalShaderCache_); textureCacheD3D11_->SetShaderManager(shaderManagerD3D11_); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 1b4aaf857b..6290f14010 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -70,10 +70,10 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) drawEngine_.SetShaderManager(shaderManagerDX9_); drawEngine_.SetTextureCache(textureCacheDX9_); drawEngine_.SetFramebufferManager(framebufferManagerDX9_); - framebufferManagerDX9_->Init(); framebufferManagerDX9_->SetTextureCache(textureCacheDX9_); framebufferManagerDX9_->SetShaderManager(shaderManagerDX9_); framebufferManagerDX9_->SetDrawEngine(&drawEngine_); + framebufferManagerDX9_->Init(); textureCacheDX9_->SetFramebufferManager(framebufferManagerDX9_); textureCacheDX9_->SetDepalShaderCache(&depalShaderCache_); textureCacheDX9_->SetShaderManager(shaderManagerDX9_); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 0800a8b917..d4b0b7405f 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -111,8 +111,6 @@ FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw, GLRender void FramebufferManagerGLES::Init() { FramebufferManagerCommon::Init(); - // Workaround for upscaling shaders where we force x1 resolution without saving it - Resized(); CompileDraw2DProgram(); } diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 81a53c3dc8..5cf1ec1b41 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -71,10 +71,10 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) drawEngine_.SetTextureCache(textureCacheGL_); drawEngine_.SetFramebufferManager(framebufferManagerGL_); drawEngine_.SetFragmentTestCache(&fragmentTestCache_); - framebufferManagerGL_->Init(); framebufferManagerGL_->SetTextureCache(textureCacheGL_); framebufferManagerGL_->SetShaderManager(shaderManagerGL_); framebufferManagerGL_->SetDrawEngine(&drawEngine_); + framebufferManagerGL_->Init(); depalShaderCache_.Init(); textureCacheGL_->SetFramebufferManager(framebufferManagerGL_); textureCacheGL_->SetDepalShaderCache(&depalShaderCache_); diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index 5bb733ddb0..fb1f6139ef 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -170,12 +170,6 @@ void FramebufferManagerVulkan::NotifyClear(bool clearColor, bool clearAlpha, boo } } -void FramebufferManagerVulkan::Init() { - FramebufferManagerCommon::Init(); - // Workaround for upscaling shaders where we force x1 resolution without saving it - Resized(); -} - void FramebufferManagerVulkan::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) { float texCoords[8] = { u0,v0, diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index d17d836216..042e12565b 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -46,8 +46,6 @@ public: // x,y,w,h are relative to destW, destH which fill out the target completely. void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) override; - virtual void Init() override; - void BeginFrameVulkan(); // there's a BeginFrame in the base class, which this calls void EndFrame(); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 6cd2493f5a..9290eef466 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -72,10 +72,10 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) drawEngine_.SetShaderManager(shaderManagerVulkan_); drawEngine_.SetPipelineManager(pipelineManager_); framebufferManagerVulkan_->SetVulkan2D(&vulkan2D_); - framebufferManagerVulkan_->Init(); framebufferManagerVulkan_->SetTextureCache(textureCacheVulkan_); framebufferManagerVulkan_->SetDrawEngine(&drawEngine_); framebufferManagerVulkan_->SetShaderManager(shaderManagerVulkan_); + framebufferManagerVulkan_->Init(); textureCacheVulkan_->SetDepalShaderCache(&depalShaderCache_); textureCacheVulkan_->SetFramebufferManager(framebufferManagerVulkan_); textureCacheVulkan_->SetShaderManager(shaderManagerVulkan_); From 230fe82ee6b18525284b21a0ff686e586b476d5d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 May 2020 10:02:12 -0700 Subject: [PATCH 2/6] GPU: Alternate FBOs for chained postshaders. If you apply 4 in a row at the same resolution, we only need two actual FBOs. This will use less VRAM. --- GPU/Common/PresentationCommon.cpp | 31 +++++++++++++++++++++++++++---- GPU/Common/PresentationCommon.h | 8 ++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index c8b638f3ce..337a26d83c 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -258,13 +258,10 @@ bool PresentationCommon::BuildPostShader(const ShaderInfo *shaderInfo, const Sha nextHeight = (int)h; } - // No depth/stencil for post processing - Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ nextWidth, nextHeight, 1, 1, false, Draw::FBO_8888 }); - if (!fbo) { + if (!AllocateFramebuffer(nextWidth, nextHeight)) { pipeline->Release(); return false; } - postShaderFramebuffers_.push_back(fbo); } postShaderPipelines_.push_back(pipeline); @@ -272,6 +269,31 @@ bool PresentationCommon::BuildPostShader(const ShaderInfo *shaderInfo, const Sha return true; } +bool PresentationCommon::AllocateFramebuffer(int w, int h) { + using namespace Draw; + + // First, let's try to find a framebuffer of the right size that is NOT the most recent. + Framebuffer *last = postShaderFramebuffers_.empty() ? nullptr : postShaderFramebuffers_.back(); + for (const auto &prev : postShaderFBOUsage_) { + if (prev.w == w && prev.h == h && prev.fbo != last) { + // Great, this one's perfect. Ref it for when we release. + prev.fbo->AddRef(); + postShaderFramebuffers_.push_back(prev.fbo); + return true; + } + } + + // No depth/stencil for post processing + Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, false, Draw::FBO_8888 }); + if (!fbo) { + return false; + } + + postShaderFBOUsage_.push_back({ fbo, w, h }); + postShaderFramebuffers_.push_back(fbo); + return true; +} + void PresentationCommon::ShowPostShaderError(const std::string &errorString) { // let's show the first line of the error string as an OSM. std::set blacklistedLines; @@ -406,6 +428,7 @@ void PresentationCommon::DestroyPostShader() { DoReleaseVector(postShaderPipelines_); DoReleaseVector(postShaderFramebuffers_); postShaderInfo_.clear(); + postShaderFBOUsage_.clear(); } Draw::ShaderModule *PresentationCommon::CompileShaderModule(Draw::ShaderStage stage, ShaderLanguage lang, const std::string &src, std::string *errorString) { diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index eae2834abf..13b89f4ca7 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -112,6 +112,7 @@ protected: Draw::ShaderModule *CompileShaderModule(Draw::ShaderStage stage, ShaderLanguage lang, const std::string &src, std::string *errorString); Draw::Pipeline *CreatePipeline(std::vector shaders, bool postShader, const Draw::UniformBufferDesc *uniformDesc); bool BuildPostShader(const ShaderInfo *shaderInfo, const ShaderInfo *next); + bool AllocateFramebuffer(int w, int h); void BindSource(); @@ -145,4 +146,11 @@ protected: bool usePostShader_ = false; bool restorePostShader_ = false; ShaderLanguage lang_; + + struct PrevFBO { + Draw::Framebuffer *fbo; + int w; + int h; + }; + std::vector postShaderFBOUsage_; }; From 44a73363bd072b515ffcc7ed1c4ac4657b31f508 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 May 2020 10:34:11 -0700 Subject: [PATCH 3/6] Draw: Use uniform locs for GLES, add samplers. So that we can initialize and bind samplers. --- ext/native/thin3d/GLQueueRunner.cpp | 6 +++--- ext/native/thin3d/GLQueueRunner.h | 4 ++-- ext/native/thin3d/GLRenderManager.h | 10 +++++----- ext/native/thin3d/thin3d_gl.cpp | 23 ++++++++++++++++++----- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/ext/native/thin3d/GLQueueRunner.cpp b/ext/native/thin3d/GLQueueRunner.cpp index 20c5bf7800..0e8dd9020c 100644 --- a/ext/native/thin3d/GLQueueRunner.cpp +++ b/ext/native/thin3d/GLQueueRunner.cpp @@ -923,9 +923,9 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) { case GLRRenderCommand::UNIFORMMATRIX: { assert(curProgram); - int loc = c.uniform4.loc ? *c.uniform4.loc : -1; - if (c.uniform4.name) { - loc = curProgram->GetUniformLoc(c.uniform4.name); + int loc = c.uniformMatrix4.loc ? *c.uniformMatrix4.loc : -1; + if (c.uniformMatrix4.name) { + loc = curProgram->GetUniformLoc(c.uniformMatrix4.name); } if (loc >= 0) { glUniformMatrix4fv(loc, 1, false, c.uniformMatrix4.m); diff --git a/ext/native/thin3d/GLQueueRunner.h b/ext/native/thin3d/GLQueueRunner.h index 41bceedb20..8a00da610a 100644 --- a/ext/native/thin3d/GLQueueRunner.h +++ b/ext/native/thin3d/GLQueueRunner.h @@ -116,13 +116,13 @@ struct GLRRenderData { } drawIndexed; struct { const char *name; // if null, use loc - GLint *loc; // NOTE: This is a pointer so we can immediately use things that are "queried" during program creation. + const GLint *loc; // NOTE: This is a pointer so we can immediately use things that are "queried" during program creation. GLint count; float v[4]; } uniform4; struct { const char *name; // if null, use loc - GLint *loc; + const GLint *loc; float m[16]; } uniformMatrix4; struct { diff --git a/ext/native/thin3d/GLRenderManager.h b/ext/native/thin3d/GLRenderManager.h index 377344b073..e579eb7b10 100644 --- a/ext/native/thin3d/GLRenderManager.h +++ b/ext/native/thin3d/GLRenderManager.h @@ -630,7 +630,7 @@ public: curRenderStep_->commands.push_back(data); } - void SetUniformI(GLint *loc, int count, const int *udata) { + void SetUniformI(const GLint *loc, int count, const int *udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); #ifdef _DEBUG assert(curProgram_); @@ -642,7 +642,7 @@ public: curRenderStep_->commands.push_back(data); } - void SetUniformI1(GLint *loc, int udata) { + void SetUniformI1(const GLint *loc, int udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); #ifdef _DEBUG assert(curProgram_); @@ -654,7 +654,7 @@ public: curRenderStep_->commands.push_back(data); } - void SetUniformF(GLint *loc, int count, const float *udata) { + void SetUniformF(const GLint *loc, int count, const float *udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); #ifdef _DEBUG assert(curProgram_); @@ -666,7 +666,7 @@ public: curRenderStep_->commands.push_back(data); } - void SetUniformF1(GLint *loc, const float udata) { + void SetUniformF1(const GLint *loc, const float udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); #ifdef _DEBUG assert(curProgram_); @@ -690,7 +690,7 @@ public: curRenderStep_->commands.push_back(data); } - void SetUniformM4x4(GLint *loc, const float *udata) { + void SetUniformM4x4(const GLint *loc, const float *udata) { _dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER); #ifdef _DEBUG assert(curProgram_); diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 8eadd95644..273463466d 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -323,6 +323,8 @@ public: // TODO: Optimize by getting the locations first and putting in a custom struct UniformBufferDesc dynamicUniforms; + GLint samplerLocs_[8]; + std::vector dynamicUniformLocs_; GLRProgram *program_ = nullptr; private: @@ -960,6 +962,10 @@ Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) { return nullptr; } } + if (desc.uniformDesc) { + pipeline->dynamicUniforms = *desc.uniformDesc; + pipeline->dynamicUniformLocs_.resize(desc.uniformDesc->uniforms.size()); + } ILOG("Linking shaders."); if (pipeline->LinkShaders()) { // Build the rest of the virtual pipeline object. @@ -972,8 +978,6 @@ Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) { pipeline->blend->AddRef(); pipeline->raster->AddRef(); pipeline->inputLayout->AddRef(); - if (desc.uniformDesc) - pipeline->dynamicUniforms = *desc.uniformDesc; return pipeline; } else { ELOG("Failed to create pipeline - shaders failed to link"); @@ -1046,7 +1050,14 @@ bool OpenGLPipeline::LinkShaders() { semantics.push_back({ SEM_POSITION, "a_position" }); semantics.push_back({ SEM_TEXCOORD0, "a_texcoord0" }); std::vector queries; + queries.push_back({ &samplerLocs_[0], "sampler0" }); + queries.push_back({ &samplerLocs_[1], "sampler1" }); + for (size_t i = 0; i < dynamicUniforms.uniforms.size(); ++i) { + queries.push_back({ &dynamicUniformLocs_[i], dynamicUniforms.uniforms[i].name }); + } std::vector initialize; + initialize.push_back({ &samplerLocs_[0], 0, 0 }); + initialize.push_back({ &samplerLocs_[1], 0, 1 }); program_ = render_->CreateProgram(linkShaders, semantics, queries, initialize, false); return true; } @@ -1066,17 +1077,19 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) { Crash(); } - for (auto &uniform : curPipeline_->dynamicUniforms.uniforms) { + for (size_t i = 0; i < curPipeline_->dynamicUniforms.uniforms.size(); ++i) { + const auto &uniform = curPipeline_->dynamicUniforms.uniforms[i]; + const GLint &loc = curPipeline_->dynamicUniformLocs_[i]; const float *data = (const float *)((uint8_t *)ub + uniform.offset); switch (uniform.type) { case UniformType::FLOAT1: case UniformType::FLOAT2: case UniformType::FLOAT3: case UniformType::FLOAT4: - renderManager_.SetUniformF(uniform.name, 1 + (int)uniform.type - (int)UniformType::FLOAT1, data); + renderManager_.SetUniformF(&loc, 1 + (int)uniform.type - (int)UniformType::FLOAT1, data); break; case UniformType::MATRIX4X4: - renderManager_.SetUniformM4x4(uniform.name, data); + renderManager_.SetUniformM4x4(&loc, data); break; } } From ed4719a9b6bc86805d7d4aa64eeae12b19f92a9b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 May 2020 10:44:21 -0700 Subject: [PATCH 4/6] Draw: Fix textures and samplers at an offset. --- ext/native/thin3d/thin3d_d3d9.cpp | 2 +- ext/native/thin3d/thin3d_gl.cpp | 6 +++--- ext/native/thin3d/thin3d_vulkan.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ext/native/thin3d/thin3d_d3d9.cpp b/ext/native/thin3d/thin3d_d3d9.cpp index b4d446ed9d..f8531661ba 100644 --- a/ext/native/thin3d/thin3d_d3d9.cpp +++ b/ext/native/thin3d/thin3d_d3d9.cpp @@ -540,7 +540,7 @@ public: void BindTextures(int start, int count, Texture **textures) override; void BindSamplerStates(int start, int count, SamplerState **states) override { for (int i = 0; i < count; ++i) { - D3D9SamplerState *s = static_cast(states[start + i]); + D3D9SamplerState *s = static_cast(states[i]); s->Apply(device_, start + i); } } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 273463466d..f8c6c11a2e 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -389,7 +389,7 @@ public: } for (int i = 0; i < count; i++) { int index = i + start; - boundSamplers_[index] = static_cast(states[index]); + boundSamplers_[index] = static_cast(states[i]); } } @@ -989,9 +989,9 @@ Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) { void OpenGLContext::BindTextures(int start, int count, Texture **textures) { maxTextures_ = std::max(maxTextures_, start + count); for (int i = start; i < start + count; i++) { - OpenGLTexture *glTex = static_cast(textures[i]); + OpenGLTexture *glTex = static_cast(textures[i - start]); if (!glTex) { - boundTextures_[i] = 0; + boundTextures_[i] = nullptr; renderManager_.BindTexture(i, nullptr); continue; } diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index c89b079c68..9161b0904f 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -669,7 +669,7 @@ RasterState *VKContext::CreateRasterState(const RasterStateDesc &desc) { void VKContext::BindSamplerStates(int start, int count, SamplerState **state) { for (int i = start; i < start + count; i++) { - boundSamplers_[i] = (VKSamplerState *)state[i]; + boundSamplers_[i] = (VKSamplerState *)state[i - start]; } } @@ -1201,7 +1201,7 @@ void VKContext::UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, void VKContext::BindTextures(int start, int count, Texture **textures) { for (int i = start; i < start + count; i++) { - boundTextures_[i] = static_cast(textures[i]); + boundTextures_[i] = static_cast(textures[i - start]); boundImageView_[i] = boundTextures_[i] ? boundTextures_[i]->GetImageView() : GetNullTexture()->GetImageView(); } } From 8f8098ed2442ab9d259b35d43c3aa5f8affeb76d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 May 2020 10:47:39 -0700 Subject: [PATCH 5/6] GPU: Add sampler1 for postshader orig source. --- GPU/Common/PresentationCommon.cpp | 14 +++++++++----- GPU/Common/PresentationCommon.h | 2 +- GPU/Common/ShaderTranslation.cpp | 9 ++++++++- GPU/GLES/DepalettizeShaderGLES.cpp | 7 ++++--- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index 337a26d83c..4df4b43716 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -491,11 +491,11 @@ void PresentationCommon::SourceFramebuffer(Draw::Framebuffer *fb, int bufferWidt srcHeight_ = bufferHeight; } -void PresentationCommon::BindSource() { +void PresentationCommon::BindSource(int binding) { if (srcTexture_) { - draw_->BindTexture(0, srcTexture_); + draw_->BindTexture(binding, srcTexture_); } else if (srcFramebuffer_) { - draw_->BindFramebufferAsTexture(srcFramebuffer_, 0, Draw::FB_COLOR_BIT, 0); + draw_->BindFramebufferAsTexture(srcFramebuffer_, binding, Draw::FB_COLOR_BIT, 0); } else { assert(false); } @@ -611,8 +611,9 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u if (usePostShaderOutput) { draw_->BindFramebufferAsTexture(postShaderFramebuffers_[i - 1], 0, Draw::FB_COLOR_BIT, 0); } else { - BindSource(); + BindSource(0); } + BindSource(1); int nextWidth, nextHeight; draw_->GetFramebufferDimensions(postShaderFramebuffer, &nextWidth, &nextHeight); @@ -628,6 +629,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u Draw::SamplerState *sampler = useNearest || shaderInfo->isUpscalingFilter ? samplerNearest_ : samplerLinear_; draw_->BindSamplerStates(0, 1, &sampler); + draw_->BindSamplerStates(1, 1, &sampler); draw_->BindVertexBuffers(0, 1, &vdata_, &postVertsOffset); draw_->BindIndexBuffer(idata_, 0); @@ -658,8 +660,9 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u if (usePostShaderOutput) { draw_->BindFramebufferAsTexture(postShaderFramebuffers_.back(), 0, Draw::FB_COLOR_BIT, 0); } else { - BindSource(); + BindSource(0); } + BindSource(1); if (isFinalAtOutputResolution) { PostShaderUniforms uniforms; @@ -676,6 +679,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u Draw::SamplerState *sampler = useNearest ? samplerNearest_ : samplerLinear_; draw_->BindSamplerStates(0, 1, &sampler); + draw_->BindSamplerStates(1, 1, &sampler); auto setViewport = [&](float x, float y, float w, float h) { Draw::Viewport viewport{ x, y, w, h, 0.0f, 1.0f }; diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h index 13b89f4ca7..ee0822ea0a 100644 --- a/GPU/Common/PresentationCommon.h +++ b/GPU/Common/PresentationCommon.h @@ -114,7 +114,7 @@ protected: bool BuildPostShader(const ShaderInfo *shaderInfo, const ShaderInfo *next); bool AllocateFramebuffer(int w, int h); - void BindSource(); + void BindSource(int binding); void GetCardboardSettings(CardboardSettings *cardboardSettings); void CalculatePostShaderUniforms(int bufferWidth, int bufferHeight, int targetWidth, int targetHeight, const ShaderInfo *shaderInfo, PostShaderUniforms *uniforms); diff --git a/GPU/Common/ShaderTranslation.cpp b/GPU/Common/ShaderTranslation.cpp index 192e59f186..2361ba9e11 100644 --- a/GPU/Common/ShaderTranslation.cpp +++ b/GPU/Common/ShaderTranslation.cpp @@ -140,6 +140,10 @@ std::string Postprocess(std::string code, ShaderLanguage lang, Draw::ShaderStage out << "sampler2D sampler0 : register(s0);\n"; continue; } + if (line == "uniform sampler2D sampler1;" && lang == HLSL_DX9) { + out << "sampler2D sampler1 : register(s1);\n"; + continue; + } if (line.find("uniform float") != std::string::npos) { continue; } @@ -181,7 +185,10 @@ bool ConvertToVulkanGLSL(std::string *dest, TranslatedShaderMetadata *destMetada if (line.find("uniform bool") != std::string::npos) { continue; } else if (line.find("uniform sampler2D") == 0) { - line = "layout(set = 0, binding = 1) " + line; + if (line.find("sampler0") != line.npos) + line = "layout(set = 0, binding = 1) " + line; + else + line = "layout(set = 0, binding = 2) " + line; } else if (line.find("uniform ") != std::string::npos) { continue; } else if (2 == sscanf(line.c_str(), "varying vec%d v_texcoord%d;", &vecSize, &num)) { diff --git a/GPU/GLES/DepalettizeShaderGLES.cpp b/GPU/GLES/DepalettizeShaderGLES.cpp index 5abe33d77c..348411e082 100644 --- a/GPU/GLES/DepalettizeShaderGLES.cpp +++ b/GPU/GLES/DepalettizeShaderGLES.cpp @@ -21,7 +21,8 @@ #include "Common/Log.h" #include "Common/StringUtils.h" #include "Core/Reporting.h" -#include "DepalettizeShaderGLES.h" +#include "GPU/GLES/DepalettizeShaderGLES.h" +#include "GPU/GLES/DrawEngineGLES.h" #include "GPU/GLES/TextureCacheGLES.h" #include "GPU/Common/DepalettizeShaderCommon.h" @@ -178,8 +179,8 @@ DepalShader *DepalShaderCacheGLES::GetDepalettizeShader(uint32_t clutMode, GEBuf queries.push_back({ &depal->u_pal, "pal" }); std::vector initializer; - initializer.push_back({ &depal->u_tex, 0, 0 }); - initializer.push_back({ &depal->u_pal, 0, 3 }); + initializer.push_back({ &depal->u_tex, 0, TEX_SLOT_PSP_TEXTURE }); + initializer.push_back({ &depal->u_pal, 0, TEX_SLOT_CLUT }); std::vector shaders{ vertexShader_, fragShader }; From 9bfd2abb12266e9f0ce2f8e42401e1a663c0ebc3 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 May 2020 10:50:11 -0700 Subject: [PATCH 6/6] Draw: Allow 2 textures bound in Vulkan. Not working properly though... --- ext/native/thin3d/thin3d_vulkan.cpp | 77 +++++++++++++++++------------ 1 file changed, 45 insertions(+), 32 deletions(-) diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index 9161b0904f..cdcadbea29 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -39,6 +39,7 @@ // We use a simple descriptor set for all rendering: 1 sampler, 1 texture, 1 UBO binding point. // binding 0 - uniform data // binding 1 - sampler +// binding 2 - sampler // // Vertex data lives in a separate namespace (location = 0, 1, etc) @@ -290,14 +291,20 @@ class VKTexture; class VKBuffer; class VKSamplerState; +enum { + MAX_BOUND_TEXTURES = 2 +}; + struct DescriptorSetKey { - VkImageView imageView_; - VKSamplerState *sampler_; + VkImageView imageViews_[MAX_BOUND_TEXTURES]; + VKSamplerState *samplers_[MAX_BOUND_TEXTURES]; VkBuffer buffer_; bool operator < (const DescriptorSetKey &other) const { - if (imageView_ < other.imageView_) return true; else if (imageView_ > other.imageView_) return false; - if (sampler_ < other.sampler_) return true; else if (sampler_ > other.sampler_) return false; + for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) { + if (imageViews_[i] < other.imageViews_[i]) return true; else if (imageViews_[i] > other.imageViews_[i]) return false; + if (samplers_[i] < other.samplers_[i]) return true; else if (samplers_[i] > other.samplers_[i]) return false; + } if (buffer_ < other.buffer_) return true; else if (buffer_ > other.buffer_) return false; return false; } @@ -505,7 +512,6 @@ private: int queueFamilyIndex_; enum { - MAX_BOUND_TEXTURES = 2, MAX_FRAME_COMMAND_BUFFERS = 256, }; VKTexture *boundTextures_[MAX_BOUND_TEXTURES]{}; @@ -790,7 +796,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) VkDescriptorPoolSize dpTypes[2]; dpTypes[0].descriptorCount = 200; dpTypes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; - dpTypes[1].descriptorCount = 200; + dpTypes[1].descriptorCount = 200 * MAX_BOUND_TEXTURES; dpTypes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; VkDescriptorPoolCreateInfo dp{ VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO }; @@ -811,21 +817,24 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit) } // binding 0 - uniform data - // binding 1 - combined sampler/image - VkDescriptorSetLayoutBinding bindings[2]; + // binding 1 - combined sampler/image 0 + // binding 2 - combined sampler/image 1 + VkDescriptorSetLayoutBinding bindings[MAX_BOUND_TEXTURES + 1]; bindings[0].descriptorCount = 1; bindings[0].pImmutableSamplers = nullptr; bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT; bindings[0].binding = 0; - bindings[1].descriptorCount = 1; - bindings[1].pImmutableSamplers = nullptr; - bindings[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - bindings[1].binding = 1; + for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) { + bindings[i + 1].descriptorCount = 1; + bindings[i + 1].pImmutableSamplers = nullptr; + bindings[i + 1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[i + 1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[i + 1].binding = i + 1; + } VkDescriptorSetLayoutCreateInfo dsl = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; - dsl.bindingCount = 2; + dsl.bindingCount = ARRAY_SIZE(bindings); dsl.pBindings = bindings; VkResult res = vkCreateDescriptorSetLayout(device_, &dsl, nullptr, &descriptorSetLayout_); assert(VK_SUCCESS == res); @@ -903,8 +912,10 @@ VkDescriptorSet VKContext::GetOrCreateDescriptorSet(VkBuffer buf) { FrameData *frame = &frame_[vulkan_->GetCurFrame()]; - key.imageView_ = boundTextures_[0] ? boundTextures_[0]->GetImageView() : boundImageView_[0]; - key.sampler_ = boundSamplers_[0]; + for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) { + key.imageViews_[i] = boundTextures_[i] ? boundTextures_[i]->GetImageView() : boundImageView_[i]; + key.samplers_[i] = boundSamplers_[i]; + } key.buffer_ = buf; auto iter = frame->descSets_.find(key); @@ -927,7 +938,7 @@ VkDescriptorSet VKContext::GetOrCreateDescriptorSet(VkBuffer buf) { VkDescriptorImageInfo imageDesc; - VkWriteDescriptorSet writes[2] = {}; + VkWriteDescriptorSet writes[1 + MAX_BOUND_TEXTURES] = {}; // If handles are NULL for whatever buggy reason, it's best to leave the descriptors // unwritten instead of trying to write a zero, which is not legal. @@ -946,24 +957,26 @@ VkDescriptorSet VKContext::GetOrCreateDescriptorSet(VkBuffer buf) { numWrites++; } - if (key.imageView_ && boundSamplers_[0] && boundSamplers_[0]->GetSampler()) { - imageDesc.imageView = key.imageView_ ? key.imageView_ : VK_NULL_HANDLE; - imageDesc.sampler = boundSamplers_[0] ? boundSamplers_[0]->GetSampler() : VK_NULL_HANDLE; + for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) { + if (key.imageViews_[i] && key.samplers_[i] && key.samplers_[i]->GetSampler()) { + imageDesc.imageView = key.imageViews_[i]; + imageDesc.sampler = key.samplers_[i]->GetSampler(); #ifdef VULKAN_USE_GENERAL_LAYOUT_FOR_COLOR - imageDesc.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + imageDesc.imageLayout = VK_IMAGE_LAYOUT_GENERAL; #else - imageDesc.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + imageDesc.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; #endif - writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - writes[numWrites].dstSet = descSet; - writes[numWrites].dstArrayElement = 0; - writes[numWrites].dstBinding = 1; - writes[numWrites].pBufferInfo = nullptr; - writes[numWrites].pImageInfo = &imageDesc; - writes[numWrites].pTexelBufferView = nullptr; - writes[numWrites].descriptorCount = 1; - writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - numWrites++; + writes[numWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + writes[numWrites].dstSet = descSet; + writes[numWrites].dstArrayElement = 0; + writes[numWrites].dstBinding = i + 1; + writes[numWrites].pBufferInfo = nullptr; + writes[numWrites].pImageInfo = &imageDesc; + writes[numWrites].pTexelBufferView = nullptr; + writes[numWrites].descriptorCount = 1; + writes[numWrites].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + numWrites++; + } } vkUpdateDescriptorSets(device_, numWrites, writes, 0, nullptr);