diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 90bec0ecfe..6dd922f1c1 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -100,8 +100,6 @@ public: } void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; - uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) override; - void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; void InvalidateCachedState() override; @@ -1709,21 +1707,6 @@ uint64_t D3D11DrawContext::GetNativeObject(NativeObject obj, void *srcObject) { } } -uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) { - D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; - switch (channelBit) { - case FB_COLOR_BIT: return (uintptr_t)fb->colorTex; - case FB_DEPTH_BIT: return (uintptr_t)fb->depthStencilTex; - case FB_COLOR_BIT | FB_VIEW_BIT: return (uintptr_t)fb->colorRTView; - case FB_DEPTH_BIT | FB_VIEW_BIT: return (uintptr_t)fb->depthStencilRTView; - case FB_COLOR_BIT | FB_FORMAT_BIT: return (uintptr_t)fb->colorFormat; - case FB_DEPTH_BIT | FB_FORMAT_BIT: return (uintptr_t)fb->depthStencilFormat; - case FB_STENCIL_BIT | FB_FORMAT_BIT: return (uintptr_t)fb->depthStencilFormat; - default: - return 0; - } -} - void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; if (fb) { diff --git a/Common/GPU/ShaderWriter.cpp b/Common/GPU/ShaderWriter.cpp index d57a855ac7..900e2d1160 100644 --- a/Common/GPU/ShaderWriter.cpp +++ b/Common/GPU/ShaderWriter.cpp @@ -313,6 +313,9 @@ void ShaderWriter::EndVSMain(Slice varyings) { case HLSL_D3D11: case HLSL_D3D9: C(" VS_OUTPUT vs_out;\n"); + if (strlen(lang_.viewportYSign)) { + F(" gl_Position.y *= %s1.0;\n", lang_.viewportYSign); + } C(" vs_out.pos = gl_Position;\n"); for (auto &varying : varyings) { F(" vs_out.%s = %s;\n", varying.name, varying.name); diff --git a/Common/GPU/ShaderWriter.h b/Common/GPU/ShaderWriter.h index 9d16f2bf9a..f07d4159f5 100644 --- a/Common/GPU/ShaderWriter.h +++ b/Common/GPU/ShaderWriter.h @@ -43,7 +43,7 @@ enum FSFlags { class ShaderWriter { public: - ShaderWriter(char *buffer, const ShaderLanguageDesc &lang, ShaderStage stage, const char **gl_extensions, size_t num_gl_extensions) : p_(buffer), lang_(lang), stage_(stage) { + ShaderWriter(char *buffer, const ShaderLanguageDesc &lang, ShaderStage stage, const char **gl_extensions = nullptr, size_t num_gl_extensions = 0) : p_(buffer), lang_(lang), stage_(stage) { Preamble(gl_extensions, num_gl_extensions); } ShaderWriter(const ShaderWriter &) = delete; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 3b0f0d10e6..72236d5e74 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -395,8 +395,6 @@ public: } void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; - uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) override; - void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; void SetScissorRect(int left, int top, int width, int height) override; @@ -1580,24 +1578,6 @@ void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChanne boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, attachment); } -uintptr_t VKContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) { - if (!fbo) - return 0; - - VKFramebuffer *fb = (VKFramebuffer *)fbo; - VkImageView view = VK_NULL_HANDLE; - switch (channelBit) { - case FB_COLOR_BIT: - view = fb->GetFB()->color.imageView; - break; - case FB_DEPTH_BIT: - case FB_STENCIL_BIT: - view = fb->GetFB()->depth.imageView; - break; - } - return (uintptr_t)view; -} - void VKContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { VKFramebuffer *fb = (VKFramebuffer *)fbo; if (fb) { diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index cbd5cafef1..7dfa09fc7e 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -605,12 +605,15 @@ public: virtual void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {} // Partial pipeline state, used to create pipelines. (in practice, in d3d11 they'll use the native state objects directly). + // TODO: Possibly ditch these and just put the descs directly in PipelineDesc since only D3D11 benefits. virtual DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) = 0; virtual BlendState *CreateBlendState(const BlendStateDesc &desc) = 0; virtual SamplerState *CreateSamplerState(const SamplerStateDesc &desc) = 0; virtual RasterState *CreateRasterState(const RasterStateDesc &desc) = 0; // virtual ComputePipeline CreateComputePipeline(const ComputePipelineDesc &desc) = 0 virtual InputLayout *CreateInputLayout(const InputLayoutDesc &desc) = 0; + virtual ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag = "thin3d") = 0; + virtual Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) = 0; // Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them. ShaderModule *GetVshaderPreset(VertexShaderPreset preset) { return vsPresets_[preset]; } @@ -623,9 +626,6 @@ public: // On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one. virtual Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) = 0; - virtual ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag = "thin3d") = 0; - virtual Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) = 0; - // Copies data from the CPU over into the buffer, at a specific offset. This does not change the size of the buffer and cannot write outside it. virtual void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) = 0; @@ -646,7 +646,7 @@ public: // binding must be < MAX_TEXTURE_SLOTS (0, 1 are okay if it's 2). virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) = 0; - // deprecated + // deprecated, only used by D3D9 virtual uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) { return 0; } diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index c35cc0e41f..0ec0b6c66c 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -264,7 +264,7 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, c } void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Fragment); writer.DeclareSamplers(samplers); writer.HighPrecisionFloat(); writer.BeginFSMain(Slice::empty(), varyings, FSFLAG_NONE); @@ -289,9 +289,6 @@ void GenerateDepalVs(char *buffer, const ShaderLanguageDesc &lang) { writer.BeginVSMain(vsInputs, Slice::empty(), varyings); writer.C(" v_texcoord = a_texcoord0;\n"); writer.C(" gl_Position = vec4(a_position, 0.0, 1.0);\n"); - if (strlen(lang.viewportYSign)) { - writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign); - } writer.EndVSMain(varyings); } diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 882da8590f..1a89c45fd4 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -40,7 +40,7 @@ static const SamplerDef samplers[1] = { }; void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Fragment); writer.DeclareSamplers(samplers); writer.BeginFSMain(Slice::empty(), varyings, FSFLAG_NONE); writer.C(" vec4 outColor = ").SampleTexture2D("tex", "v_texcoord.xy").C(";\n"); @@ -48,7 +48,7 @@ void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang) { } void GenerateDraw2DDepthFs(char *buffer, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Fragment); writer.DeclareSamplers(samplers); writer.BeginFSMain(Slice::empty(), varyings, FSFLAG_WRITEDEPTH); writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); @@ -57,35 +57,66 @@ void GenerateDraw2DDepthFs(char *buffer, const ShaderLanguageDesc &lang) { } void GenerateDraw2DVS(char *buffer, const ShaderLanguageDesc &lang) { - ShaderWriter writer(buffer, lang, ShaderStage::Vertex, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Vertex); writer.BeginVSMain(inputs, Slice::empty(), varyings); writer.C(" v_texcoord = a_texcoord0;\n"); // yes, this should be right. Should be 2.0 in the far corners. writer.C(" gl_Position = vec4(a_position, 0.0, 1.0);\n"); - writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign); writer.EndVSMain(varyings); } -// verts have positions in clip coordinates. +void FramebufferManagerCommon::Ensure2DResources() { + using namespace Draw; + + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + + if (!draw2DVs_) { + char *vsCode = new char[4000]; + GenerateDraw2DVS(vsCode, shaderLanguageDesc); + draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs"); + _assert_(draw2DVs_); + delete[] vsCode; + } + + if (!draw2DSamplerLinear_) { + SamplerStateDesc descLinear{}; + descLinear.magFilter = TextureFilter::LINEAR; + descLinear.minFilter = TextureFilter::LINEAR; + descLinear.mipFilter = TextureFilter::LINEAR; + descLinear.wrapU = TextureAddressMode::CLAMP_TO_EDGE; + descLinear.wrapV = TextureAddressMode::CLAMP_TO_EDGE; + draw2DSamplerLinear_ = draw_->CreateSamplerState(descLinear); + } + + if (!draw2DSamplerNearest_) { + SamplerStateDesc descNearest{}; + descNearest.magFilter = TextureFilter::NEAREST; + descNearest.minFilter = TextureFilter::NEAREST; + descNearest.mipFilter = TextureFilter::NEAREST; + descNearest.wrapU = TextureAddressMode::CLAMP_TO_EDGE; + descNearest.wrapV = TextureAddressMode::CLAMP_TO_EDGE; + draw2DSamplerNearest_ = draw_->CreateSamplerState(descNearest); + } +} + void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel) { using namespace Draw; - if (!draw2DPipelineColor_) { - const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + Ensure2DResources(); + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + + if (!draw2DPipelineColor_) { char *fsCode = new char[4000]; char *fsDepthCode = new char[4000]; - char *vsCode = new char[4000]; GenerateDraw2DFs(fsCode, shaderLanguageDesc); GenerateDraw2DDepthFs(fsDepthCode, shaderLanguageDesc); - GenerateDraw2DVS(vsCode, shaderLanguageDesc); draw2DFs_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs"); - draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs"); - _assert_(draw2DFs_ && draw2DVs_); + _assert_(draw2DFs_); if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { draw2DFsDepth_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs"); @@ -94,7 +125,8 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver draw2DFsDepth_ = nullptr; } - InputLayoutDesc desc = { + // verts have positions in 2D clip coordinates. + static const InputLayoutDesc desc = { { { 16, false }, }, @@ -139,7 +171,6 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver } delete[] fsCode; - delete[] vsCode; rasterNoCull->Release(); blendOff->Release(); @@ -147,29 +178,20 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver noDepthStencil->Release(); depthWriteAlways->Release(); inputLayout->Release(); - - SamplerStateDesc descLinear{}; - descLinear.magFilter = TextureFilter::LINEAR; - descLinear.minFilter = TextureFilter::LINEAR; - descLinear.mipFilter = TextureFilter::LINEAR; - descLinear.wrapU = TextureAddressMode::CLAMP_TO_EDGE; - descLinear.wrapV = TextureAddressMode::CLAMP_TO_EDGE; - draw2DSamplerLinear_= draw_->CreateSamplerState(descLinear); - - SamplerStateDesc descNearest{}; - descLinear.magFilter = TextureFilter::NEAREST; - descLinear.minFilter = TextureFilter::NEAREST; - descLinear.mipFilter = TextureFilter::NEAREST; - descLinear.wrapU = TextureAddressMode::CLAMP_TO_EDGE; - descLinear.wrapV = TextureAddressMode::CLAMP_TO_EDGE; - draw2DSamplerNearest_ = draw_->CreateSamplerState(descNearest); } - if (channel == RASTER_DEPTH && !draw2DPipelineDepth_) { - return; + switch (channel) { + case RASTER_DEPTH: + if (!draw2DPipelineDepth_) { + return; + } + draw_->BindPipeline(draw2DPipelineDepth_); + break; + case RASTER_COLOR: + draw_->BindPipeline(draw2DPipelineColor_); + break; } - draw_->BindPipeline(channel == RASTER_COLOR ? draw2DPipelineColor_ : draw2DPipelineDepth_); if (tex) { draw_->BindTextures(TEX_SLOT_PSP_TEXTURE, 1, &tex); } diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 0da6dc00ca..a755a5aab1 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -114,7 +114,7 @@ void FramebufferManagerCommon::SetDisplayFramebuffer(u32 framebuf, u32 stride, G GPURecord::NotifyDisplay(framebuf, stride, format); } -VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) { +VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) const { addr &= 0x3FFFFFFF; VirtualFramebuffer *match = nullptr; for (size_t i = 0; i < vfbs_.size(); ++i) { @@ -689,163 +689,6 @@ void FramebufferManagerCommon::NotifyRenderFramebufferUpdated(VirtualFramebuffer } } -// Can't easily dynamically create these strings, we just pass along the pointer. -static const char *reinterpretStrings[3][3] = { - { - "self_reinterpret_565", - "reinterpret_565_to_5551", - "reinterpret_565_to_4444", - }, - { - "reinterpret_5551_to_565", - "self_reinterpret_5551", - "reinterpret_5551_to_4444", - }, - { - "reinterpret_4444_to_565", - "reinterpret_4444_to_5551", - "self_reinterpret_4444", - }, -}; - -void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat) { - if (!useBufferedRendering_ || !vfb->fbo) { - return; - } - - _assert_(newFormat != oldFormat); - // The caller is responsible for updating the format. - _assert_(newFormat == vfb->format); - - ShaderLanguage lang = draw_->GetShaderLanguageDesc().shaderLanguage; - - // Copy image required for now, might get rid of this later. - bool doReinterpret = PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && - (lang == HLSL_D3D11 || lang == GLSL_VULKAN || lang == GLSL_3xx) && - draw_->GetDeviceCaps().framebufferCopySupported; - - if (!doReinterpret) { - // Fake reinterpret - just clear the way we always did on Vulkan. Just clear color and stencil. - if (oldFormat == GE_FORMAT_565) { - // We have to bind here instead of clear, since it can be that no framebuffer is bound. - // The backend can sometimes directly optimize it to a clear. - - // Games that are marked as doing reinterpret just ignore this - better to keep the data than to clear. - // Fixes #13717. - if (!PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && !PSP_CoreParameter().compat.flags().BlueToAlpha) { - draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "FakeReinterpret"); - // Need to dirty anything that has command buffer dynamic state, in case we started a new pass above. - // Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager. - gstate_c.Dirty(DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE); - - if (currentRenderVfb_ != vfb) { - // In case ReinterpretFramebuffer was called from the texture manager. - draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After FakeReinterpret"); - } - } - } - return; - } - - // We only reinterpret between 16 - bit formats, for now. - if (!IsGeBufferFormat16BitColor(oldFormat) || !IsGeBufferFormat16BitColor(newFormat)) { - // 16->32 and 32->16 will require some more specialized shaders. - return; - } - - char *vsCode = nullptr; - char *fsCode = nullptr; - - if (!reinterpretVS_) { - vsCode = new char[4000]; - const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); - GenerateReinterpretVertexShader(vsCode, shaderLanguageDesc); - reinterpretVS_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "reinterpret_vs"); - _assert_(reinterpretVS_); - } - - if (!reinterpretSampler_) { - Draw::SamplerStateDesc samplerDesc{}; - samplerDesc.magFilter = Draw::TextureFilter::LINEAR; - samplerDesc.minFilter = Draw::TextureFilter::LINEAR; - reinterpretSampler_ = draw_->CreateSamplerState(samplerDesc); - } - - if (!reinterpretVBuf_) { - reinterpretVBuf_ = draw_->CreateBuffer(12 * 3, Draw::BufferUsageFlag::DYNAMIC | Draw::BufferUsageFlag::VERTEXDATA); - } - - // See if we need to create a new pipeline. - - Draw::Pipeline *pipeline = reinterpretFromTo_[(int)oldFormat][(int)newFormat]; - if (!pipeline) { - fsCode = new char[4000]; - const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); - GenerateReinterpretFragmentShader(fsCode, oldFormat, newFormat, shaderLanguageDesc); - Draw::ShaderModule *reinterpretFS = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "reinterpret_fs"); - _assert_(reinterpretFS); - - std::vector shaders; - shaders.push_back(reinterpretVS_); - shaders.push_back(reinterpretFS); - - using namespace Draw; - Draw::PipelineDesc desc{}; - // We use a "fullscreen triangle". - // TODO: clear the stencil buffer. Hard to actually initialize it with the new alpha, though possible - let's see if - // we need it. - DepthStencilState *depth = draw_->CreateDepthStencilState({ false, false, Comparison::LESS }); - BlendState *blendstateOff = draw_->CreateBlendState({ false, 0xF }); - RasterState *rasterNoCull = draw_->CreateRasterState({}); - - // No uniforms for these, only a single texture input. - PipelineDesc pipelineDesc{ Primitive::TRIANGLE_LIST, shaders, nullptr, depth, blendstateOff, rasterNoCull, nullptr }; - pipeline = draw_->CreateGraphicsPipeline(pipelineDesc); - _assert_(pipeline != nullptr); - reinterpretFromTo_[(int)oldFormat][(int)newFormat] = pipeline; - - depth->Release(); - blendstateOff->Release(); - rasterNoCull->Release(); - reinterpretFS->Release(); - } - - // Copy to a temp framebuffer. - Draw::Framebuffer *temp = GetTempFBO(TempFBO::REINTERPRET, vfb->renderWidth, vfb->renderHeight); - - // Ideally on Vulkan this should be using the original framebuffer as an input attachment, allowing it to read from - // itself while writing. - draw_->InvalidateCachedState(); - draw_->CopyFramebufferImage(vfb->fbo, 0, 0, 0, 0, temp, 0, 0, 0, 0, vfb->renderWidth, vfb->renderHeight, 1, Draw::FBChannel::FB_COLOR_BIT, "reinterpret_prep"); - draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, reinterpretStrings[(int)oldFormat][(int)newFormat]); - draw_->BindPipeline(pipeline); - draw_->BindFramebufferAsTexture(temp, 0, Draw::FBChannel::FB_COLOR_BIT, 0); - draw_->BindSamplerStates(0, 1, &reinterpretSampler_); - draw_->SetScissorRect(0, 0, vfb->renderWidth, vfb->renderHeight); - Draw::Viewport vp = Draw::Viewport{ 0.0f, 0.0f, (float)vfb->renderWidth, (float)vfb->renderHeight, 0.0f, 1.0f }; - draw_->SetViewports(1, &vp); - // Vertex buffer not used - vertices generated in shader. - // TODO: Switch to a vertex buffer for GLES2/D3D9 compat. - draw_->BindVertexBuffers(0, 1, &reinterpretVBuf_, nullptr); - draw_->Draw(3, 0); - draw_->InvalidateCachedState(); - - // Unbind. - draw_->BindTexture(0, nullptr); - - shaderManager_->DirtyLastShader(); - textureCache_->ForgetLastTexture(); - - gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); - - if (currentRenderVfb_ != vfb) { - // In case ReinterpretFramebuffer was called from the texture manager. - draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After reinterpret"); - } - delete[] vsCode; - delete[] fsCode; -} - void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) { ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height); @@ -2480,7 +2323,7 @@ void FramebufferManagerCommon::RebindFramebuffer(const char *tag) { } } -std::vector FramebufferManagerCommon::GetFramebufferList() { +std::vector FramebufferManagerCommon::GetFramebufferList() const { std::vector list; for (size_t i = 0; i < vfbs_.size(); ++i) { diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index ca995fda06..624d20a3d0 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -249,7 +249,7 @@ public: } } void RebindFramebuffer(const char *tag); - std::vector GetFramebufferList(); + std::vector GetFramebufferList() const; void CopyDisplayToOutput(bool reallyDirty); @@ -276,25 +276,25 @@ public: size_t NumVFBs() const { return vfbs_.size(); } - u32 PrevDisplayFramebufAddr() { + u32 PrevDisplayFramebufAddr() const { return prevDisplayFramebuf_ ? prevDisplayFramebuf_->fb_address : 0; } - u32 DisplayFramebufAddr() { + u32 DisplayFramebufAddr() const { return displayFramebuf_ ? displayFramebuf_->fb_address : 0; } - u32 DisplayFramebufStride() { + u32 DisplayFramebufStride() const { return displayFramebuf_ ? displayStride_ : 0; } - GEBufferFormat DisplayFramebufFormat() { + GEBufferFormat DisplayFramebufFormat() const { return displayFramebuf_ ? displayFormat_ : GE_FORMAT_INVALID; } - bool UseBufferedRendering() { + bool UseBufferedRendering() const { return useBufferedRendering_; } - bool MayIntersectFramebuffer(u32 start) { + bool MayIntersectFramebuffer(u32 start) const { // Clear the cache/kernel bits. start = start & 0x3FFFFFFF; // Most games only have two framebuffers at the start. @@ -308,8 +308,8 @@ public: return currentRenderVfb_; } // TODO: Break out into some form of FBO manager - VirtualFramebuffer *GetVFBAt(u32 addr); - VirtualFramebuffer *GetDisplayVFB() { + VirtualFramebuffer *GetVFBAt(u32 addr) const; + VirtualFramebuffer *GetDisplayVFB() const { return GetVFBAt(displayFramebufPtr_); } @@ -349,7 +349,7 @@ public: virtual bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer); virtual bool GetOutputFramebuffer(GPUDebugBuffer &buffer); - const std::vector &Framebuffers() { + const std::vector &Framebuffers() const { return vfbs_; } void ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat); @@ -361,6 +361,7 @@ protected: 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); void DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel); + void Ensure2DResources(); bool UpdateSize(); diff --git a/GPU/Common/ReinterpretFramebuffer.cpp b/GPU/Common/ReinterpretFramebuffer.cpp index 71b0b24910..bf77181fa7 100644 --- a/GPU/Common/ReinterpretFramebuffer.cpp +++ b/GPU/Common/ReinterpretFramebuffer.cpp @@ -4,7 +4,10 @@ #include "Common/GPU/ShaderWriter.h" #include "Common/Log.h" #include "Common/GPU/thin3d.h" +#include "Core/System.h" #include "GPU/Common/ReinterpretFramebuffer.h" +#include "GPU/Common/FramebufferManagerCommon.h" +#include "GPU/Common/TextureCacheCommon.h" static const VaryingDef varyings[1] = { { "vec2", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" }, @@ -17,12 +20,10 @@ static const SamplerDef samplers[1] = { // TODO: We could possibly have an option to preserve any extra color precision? But gonna start without it. // Requires full size integer math. It would be possible to make a floating point-only version with lots of // modulo and stuff, might do it one day. -bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang) { - if (!lang.bitwiseOps) { - return false; - } +void GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang) { + _assert_(lang.bitwiseOps); - ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0); + ShaderWriter writer(buffer, lang, ShaderStage::Fragment); writer.HighPrecisionFloat(); @@ -69,24 +70,175 @@ bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBuff } writer.EndFSMain("outColor", FSFLAG_NONE); - return true; } -bool GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang) { - if (!lang.bitwiseOps) { - return false; - } - ShaderWriter writer(buffer, lang, ShaderStage::Vertex, nullptr, 0); +void GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang) { + _assert_(lang.bitwiseOps); + ShaderWriter writer(buffer, lang, ShaderStage::Vertex); writer.BeginVSMain(Slice::empty(), Slice::empty(), varyings); writer.C(" float x = -1.0 + float((gl_VertexIndex & 1) << 2);\n"); writer.C(" float y = -1.0 + float((gl_VertexIndex & 2) << 1);\n"); writer.C(" v_texcoord = (vec2(x, y) + vec2(1.0, 1.0)) * 0.5;\n"); - if (strlen(lang.viewportYSign)) { - writer.F(" y *= %s1.0;\n", lang.viewportYSign); - } writer.C(" gl_Position = vec4(x, y, 0.0, 1.0);\n"); writer.EndVSMain(varyings); - return true; +} + + +// Can't easily dynamically create these strings, we just pass along the pointer. +static const char *reinterpretStrings[3][3] = { + { + "self_reinterpret_565", + "reinterpret_565_to_5551", + "reinterpret_565_to_4444", + }, + { + "reinterpret_5551_to_565", + "self_reinterpret_5551", + "reinterpret_5551_to_4444", + }, + { + "reinterpret_4444_to_565", + "reinterpret_4444_to_5551", + "self_reinterpret_4444", + }, +}; + +void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat) { + if (!useBufferedRendering_ || !vfb->fbo) { + return; + } + + _assert_(newFormat != oldFormat); + // The caller is responsible for updating the format. + _assert_(newFormat == vfb->format); + + ShaderLanguage lang = draw_->GetShaderLanguageDesc().shaderLanguage; + + // Copy image required for now, might get rid of this later. + bool doReinterpret = PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && + (lang == HLSL_D3D11 || lang == GLSL_VULKAN || lang == GLSL_3xx) && + draw_->GetDeviceCaps().framebufferCopySupported; + + if (!doReinterpret) { + // Fake reinterpret - just clear the way we always did on Vulkan. Just clear color and stencil. + if (oldFormat == GE_FORMAT_565) { + // We have to bind here instead of clear, since it can be that no framebuffer is bound. + // The backend can sometimes directly optimize it to a clear. + + // Games that are marked as doing reinterpret just ignore this - better to keep the data than to clear. + // Fixes #13717. + if (!PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && !PSP_CoreParameter().compat.flags().BlueToAlpha) { + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "FakeReinterpret"); + // Need to dirty anything that has command buffer dynamic state, in case we started a new pass above. + // Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager. + gstate_c.Dirty(DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE); + + if (currentRenderVfb_ != vfb) { + // In case ReinterpretFramebuffer was called from the texture manager. + draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After FakeReinterpret"); + } + } + } + return; + } + + // We only reinterpret between 16 - bit formats, for now. + if (!IsGeBufferFormat16BitColor(oldFormat) || !IsGeBufferFormat16BitColor(newFormat)) { + // 16->32 and 32->16 will require some more specialized shaders. + return; + } + + char *vsCode = nullptr; + char *fsCode = nullptr; + + if (!reinterpretVS_) { + vsCode = new char[4000]; + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + GenerateReinterpretVertexShader(vsCode, shaderLanguageDesc); + reinterpretVS_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "reinterpret_vs"); + _assert_(reinterpretVS_); + } + + if (!reinterpretSampler_) { + Draw::SamplerStateDesc samplerDesc{}; + samplerDesc.magFilter = Draw::TextureFilter::LINEAR; + samplerDesc.minFilter = Draw::TextureFilter::LINEAR; + reinterpretSampler_ = draw_->CreateSamplerState(samplerDesc); + } + + if (!reinterpretVBuf_) { + reinterpretVBuf_ = draw_->CreateBuffer(12 * 3, Draw::BufferUsageFlag::DYNAMIC | Draw::BufferUsageFlag::VERTEXDATA); + } + + // See if we need to create a new pipeline. + + Draw::Pipeline *pipeline = reinterpretFromTo_[(int)oldFormat][(int)newFormat]; + if (!pipeline) { + fsCode = new char[4000]; + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + GenerateReinterpretFragmentShader(fsCode, oldFormat, newFormat, shaderLanguageDesc); + Draw::ShaderModule *reinterpretFS = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "reinterpret_fs"); + _assert_(reinterpretFS); + + std::vector shaders; + shaders.push_back(reinterpretVS_); + shaders.push_back(reinterpretFS); + + using namespace Draw; + Draw::PipelineDesc desc{}; + // We use a "fullscreen triangle". + // TODO: clear the stencil buffer. Hard to actually initialize it with the new alpha, though possible - let's see if + // we need it. + DepthStencilState *depth = draw_->CreateDepthStencilState({ false, false, Comparison::LESS }); + BlendState *blendstateOff = draw_->CreateBlendState({ false, 0xF }); + RasterState *rasterNoCull = draw_->CreateRasterState({}); + + // No uniforms for these, only a single texture input. + PipelineDesc pipelineDesc{ Primitive::TRIANGLE_LIST, shaders, nullptr, depth, blendstateOff, rasterNoCull, nullptr }; + pipeline = draw_->CreateGraphicsPipeline(pipelineDesc); + _assert_(pipeline != nullptr); + reinterpretFromTo_[(int)oldFormat][(int)newFormat] = pipeline; + + depth->Release(); + blendstateOff->Release(); + rasterNoCull->Release(); + reinterpretFS->Release(); + } + + // Copy to a temp framebuffer. + Draw::Framebuffer *temp = GetTempFBO(TempFBO::REINTERPRET, vfb->renderWidth, vfb->renderHeight); + + // Ideally on Vulkan this should be using the original framebuffer as an input attachment, allowing it to read from + // itself while writing. + draw_->InvalidateCachedState(); + draw_->CopyFramebufferImage(vfb->fbo, 0, 0, 0, 0, temp, 0, 0, 0, 0, vfb->renderWidth, vfb->renderHeight, 1, Draw::FBChannel::FB_COLOR_BIT, "reinterpret_prep"); + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, reinterpretStrings[(int)oldFormat][(int)newFormat]); + draw_->BindPipeline(pipeline); + draw_->BindFramebufferAsTexture(temp, 0, Draw::FBChannel::FB_COLOR_BIT, 0); + draw_->BindSamplerStates(0, 1, &reinterpretSampler_); + draw_->SetScissorRect(0, 0, vfb->renderWidth, vfb->renderHeight); + Draw::Viewport vp = Draw::Viewport{ 0.0f, 0.0f, (float)vfb->renderWidth, (float)vfb->renderHeight, 0.0f, 1.0f }; + draw_->SetViewports(1, &vp); + // Vertex buffer not used - vertices generated in shader. + // TODO: Switch to a vertex buffer for GLES2/D3D9 compat. + draw_->BindVertexBuffers(0, 1, &reinterpretVBuf_, nullptr); + draw_->Draw(3, 0); + draw_->InvalidateCachedState(); + + // Unbind. + draw_->BindTexture(0, nullptr); + + shaderManager_->DirtyLastShader(); + textureCache_->ForgetLastTexture(); + + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); + + if (currentRenderVfb_ != vfb) { + // In case ReinterpretFramebuffer was called from the texture manager. + draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After reinterpret"); + } + delete[] vsCode; + delete[] fsCode; } diff --git a/GPU/Common/ReinterpretFramebuffer.h b/GPU/Common/ReinterpretFramebuffer.h index e45472a321..5819366887 100644 --- a/GPU/Common/ReinterpretFramebuffer.h +++ b/GPU/Common/ReinterpretFramebuffer.h @@ -4,8 +4,8 @@ #include "GPU/GPUCommon.h" #include "Common/GPU/ShaderWriter.h" -bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang); +void GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang); // Just a single one. Can probably be shared with a lot of similar use cases. // Generates the coordinates for a fullscreen triangle. -bool GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang); +void GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang); diff --git a/GPU/Common/StencilCommon.cpp b/GPU/Common/StencilCommon.cpp index 950c84dd35..acac2967ed 100644 --- a/GPU/Common/StencilCommon.cpp +++ b/GPU/Common/StencilCommon.cpp @@ -123,7 +123,6 @@ void GenerateStencilVs(char *buffer, const ShaderLanguageDesc &lang) { writer.C(" v_texcoord = a_position * 2.0;\n"); // yes, this should be right. Should be 2.0 in the far corners. } writer.C(" gl_Position = vec4(v_texcoord * 2.0 - vec2(1.0, 1.0), 0.0, 1.0);\n"); - writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign); writer.EndVSMain(varyings); } diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 599e5718fa..f05bc499fe 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -20,74 +20,14 @@ #include #include "Common/Common.h" -#include "Common/Data/Convert/ColorConv.h" #include "Common/GPU/thin3d.h" -#include "Core/MemMap.h" -#include "Core/Config.h" -#include "Core/ConfigValues.h" -#include "Core/System.h" -#include "Core/Reporting.h" -#include "GPU/ge_constants.h" -#include "GPU/GPUState.h" -#include "GPU/Debugger/Stepping.h" #include "GPU/Common/FramebufferManagerCommon.h" #include "GPU/Common/PresentationCommon.h" -#include "GPU/Common/TextureDecoder.h" #include "GPU/D3D11/FramebufferManagerD3D11.h" -#include "GPU/D3D11/ShaderManagerD3D11.h" -#include "GPU/D3D11/TextureCacheD3D11.h" -#include "GPU/D3D11/DrawEngineD3D11.h" - -#ifdef _M_SSE -#include -#endif FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) : FramebufferManagerCommon(draw) { - device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); - context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); - featureLevel_ = (D3D_FEATURE_LEVEL)draw->GetNativeObject(Draw::NativeObject::FEATURE_LEVEL); - presentation_->SetLanguage(HLSL_D3D11); preferredPixelsFormat_ = Draw::DataFormat::B8G8R8A8_UNORM; } - -static void CopyPixelDepthOnly(u32 *dstp, const u32 *srcp, size_t c) { - size_t x = 0; - -#ifdef _M_SSE - size_t sseSize = (c / 4) * 4; - const __m128i srcMask = _mm_set1_epi32(0x00FFFFFF); - const __m128i dstMask = _mm_set1_epi32(0xFF000000); - __m128i *dst = (__m128i *)dstp; - const __m128i *src = (const __m128i *)srcp; - - for (; x < sseSize; x += 4) { - const __m128i bits24 = _mm_and_si128(_mm_load_si128(src), srcMask); - const __m128i bits8 = _mm_and_si128(_mm_load_si128(dst), dstMask); - _mm_store_si128(dst, _mm_or_si128(bits24, bits8)); - dst++; - src++; - } -#endif - - // Copy the remaining pixels that didn't fit in SSE. - for (; x < c; ++x) { - memcpy(dstp + x, srcp + x, 3); - } -} - -// Nobody calls this yet. -void FramebufferManagerD3D11::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) { - if (!vfb->fbo) { - ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0"); - return; - } - - const u32 z_address = vfb->z_address; - // TODO -} - -void FramebufferManagerD3D11::EndFrame() { -} diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 17ba33ec58..fc280e9de6 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -34,13 +34,4 @@ class ShaderManagerD3D11; class FramebufferManagerD3D11 : public FramebufferManagerCommon { public: FramebufferManagerD3D11(Draw::DrawContext *draw); - - void EndFrame(); - -private: - void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); - - ID3D11Device *device_; - ID3D11DeviceContext *context_; - D3D_FEATURE_LEVEL featureLevel_; }; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 23798640ee..ba41521fde 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -232,7 +232,6 @@ void GPU_D3D11::BeginFrame() { textureCacheD3D11_->StartFrame(); drawEngine_.BeginFrame(); - // fragmentTestCache_.Decimate(); shaderManagerD3D11_->DirtyLastShader(); @@ -255,9 +254,7 @@ void GPU_D3D11::CopyDisplayToOutput(bool reallyDirty) { context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], blendColor, 0xFFFFFFFF); framebufferManagerD3D11_->CopyDisplayToOutput(reallyDirty); - framebufferManagerD3D11_->EndFrame(); - // shaderManager_->EndFrame(); shaderManagerD3D11_->DirtyLastShader(); gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index fe2cf594fd..65da1a0773 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -280,7 +280,6 @@ void GPU_DX9::ReapplyGfxState() { void GPU_DX9::BeginFrame() { textureCacheDX9_->StartFrame(); drawEngine_.BeginFrame(); - // fragmentTestCache_.Decimate(); GPUCommon::BeginFrame(); shaderManagerDX9_->DirtyShader(); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index f9e04803a7..48503bdc15 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -36,7 +36,6 @@ #include "GPU/Debugger/Stepping.h" #include "GPU/GLES/FramebufferManagerGLES.h" #include "GPU/GLES/TextureCacheGLES.h" -#include "GPU/GLES/DrawEngineGLES.h" #include "GPU/GLES/ShaderManagerGLES.h" FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render) : diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index b859aefd9c..5e5793ad16 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -61,6 +61,4 @@ private: int u_depthDownloadFactor = -1; int u_depthDownloadShift = -1; int u_depthDownloadTo8 = -1; - - DrawEngineGLES *drawEngineGL_ = nullptr; }; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 2996348b54..a0deb403aa 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2969,7 +2969,7 @@ bool GPUCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) { return framebufferManager_ ? framebufferManager_->GetOutputFramebuffer(buffer) : false; } -std::vector GPUCommon::GetFramebufferList() { +std::vector GPUCommon::GetFramebufferList() const { return framebufferManager_->GetFramebufferList(); } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 9a9db7b062..59298d8e92 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -230,11 +230,11 @@ public: const std::list& GetDisplayLists() override { return dlQueue; } - std::vector GetFramebufferList() override; + std::vector GetFramebufferList() const override; void ClearShaderCache() override {} void CleanupBeforeUI() override {} - s64 GetListTicks(int listid) override { + s64 GetListTicks(int listid) const override { if (listid >= 0 && listid < DisplayListMaxCount) { return dls[listid].waitTicks; } diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 1d2c74021a..832897f598 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -253,8 +253,8 @@ public: virtual void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) = 0; virtual const std::list& GetDisplayLists() = 0; // TODO: Currently Qt only, needs to be cleaned up. - virtual std::vector GetFramebufferList() = 0; - virtual s64 GetListTicks(int listid) = 0; + virtual std::vector GetFramebufferList() const = 0; + virtual s64 GetListTicks(int listid) const = 0; // For debugging. The IDs returned are opaque, do not poke in them or display them in any way. virtual std::vector DebugGetShaderIDs(DebugShaderType type) = 0; diff --git a/unittest/TestShaderGenerators.cpp b/unittest/TestShaderGenerators.cpp index 1a5d6b4164..19b0b0d2e9 100644 --- a/unittest/TestShaderGenerators.cpp +++ b/unittest/TestShaderGenerators.cpp @@ -181,19 +181,23 @@ bool TestReinterpretShaders() { bool failed = false; for (int k = 0; k < ARRAY_SIZE(languages); k++) { + printf("=== %s ===\n\n", ShaderLanguageToString(languages[k])); + ShaderLanguageDesc desc(languages[k]); - if (!GenerateReinterpretVertexShader(buffer, desc)) { - printf("Failed!\n%s\n", buffer); + + // These require bitwise operations. + if (!desc.bitwiseOps) { + continue; + } + + GenerateReinterpretVertexShader(buffer, desc); + std::string errorMessage; + if (!TestCompileShader(buffer, languages[k], ShaderStage::Vertex, &errorMessage)) { + printf("Error compiling fragment shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str()); failed = true; + return false; } else { - std::string errorMessage; - if (!TestCompileShader(buffer, languages[k], ShaderStage::Vertex, &errorMessage)) { - printf("Error compiling fragment shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str()); - failed = true; - return false; - } else { - //printf("===\n%s\n===\n", buffer); - } + //printf("===\n%s\n===\n", buffer); } } @@ -201,23 +205,25 @@ bool TestReinterpretShaders() { printf("=== %s ===\n\n", ShaderLanguageToString(languages[k])); ShaderLanguageDesc desc(languages[k]); + + // These require bitwise operations. + if (!desc.bitwiseOps) { + continue; + } + std::string errorMessage; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i == j) continue; // useless shader! - if (!GenerateReinterpretFragmentShader(buffer, fmts[i], fmts[j], desc)) { - printf("Failed!\n%s\n", buffer); + GenerateReinterpretFragmentShader(buffer, fmts[i], fmts[j], desc); + if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) { + printf("Error compiling fragment shader %d:\n\n%s\n\n%s\n", (int)j, LineNumberString(buffer).c_str(), errorMessage.c_str()); failed = true; + return false; } else { - if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) { - printf("Error compiling fragment shader %d:\n\n%s\n\n%s\n", (int)j, LineNumberString(buffer).c_str(), errorMessage.c_str()); - failed = true; - return false; - } else { - printf("===\n%s\n===\n", buffer); - } + printf("===\n%s\n===\n", buffer); } } }