diff --git a/CMakeLists.txt b/CMakeLists.txt index 670e5f437c..d4b2fdc242 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1529,6 +1529,8 @@ endif() set(GPU_SOURCES ${GPU_IMPLS} ${GPU_NEON} + GPU/Common/Draw2D.cpp + GPU/Common/Draw2D.h GPU/Common/DepalettizeShaderCommon.cpp GPU/Common/DepalettizeShaderCommon.h GPU/Common/FragmentShaderGenerator.cpp diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp new file mode 100644 index 0000000000..b827a3cf75 --- /dev/null +++ b/GPU/Common/Draw2D.cpp @@ -0,0 +1,123 @@ +// Copyright (c) 2014- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "Common/GPU/Shader.h" +#include "Common/GPU/ShaderWriter.h" +#include "Common/GPU/thin3d.h" +#include "Core/Config.h" +#include "Core/ConfigValues.h" +#include "Core/Reporting.h" +#include "GPU/Common/Draw2D.h" +#include "GPU/Common/DrawEngineCommon.h" +#include "GPU/Common/FramebufferManagerCommon.h" +#include "GPU/Common/TextureCacheCommon.h" + +static const InputDef inputs[2] = { + { "vec2", "a_position", "POSITION" }, + { "vec2", "a_texcoord", "TEXCOORD0" }, +}; + +static const VaryingDef varyings[1] = { + { "vec2", "v_texcoord", "TEXCOORD0", 0, "highp" }, +}; + +void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang, const Draw::Bugs &bugs) { + ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0); + writer.DeclareSampler2D("samp", 0); + writer.DeclareTexture2D("tex", 0); + writer.BeginFSMain(Slice::empty(), varyings); + writer.C(" vec4 outColor = ").SampleTexture2D("tex", "samp", "v_texcoord.xy").C(";\n"); + writer.EndFSMain("outColor"); +} + +void GenerateDraw2DVS(char *buffer, const ShaderLanguageDesc &lang) { + ShaderWriter writer(buffer, lang, ShaderStage::Vertex, nullptr, 0); + + writer.BeginVSMain(inputs, Slice::empty(), varyings); + + writer.C(" v_texcoord = a_texcoord;\n"); // yes, this should be right. Should be 2.0 in the far corners. + writer.C(" gl_Position = a_position;\n"); + writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign); + + writer.EndVSMain(varyings); +} + +// verts have positions in clip coordinates. +void FramebufferManagerCommon::Draw2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, float viewportWidth, float viewportHeight) { + using namespace Draw; + + if (!draw2DPipelineLinear_) { + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + + char *fsCode = new char[4000]; + char *vsCode = new char[4000]; + GenerateDraw2DFs(fsCode, shaderLanguageDesc, draw_->GetBugs()); + 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_(stencilUploadFs_ && stencilUploadVs_); + + InputLayoutDesc desc = { + { + { 16, false }, + }, + { + { 0, SEM_POSITION, DataFormat::R32G32_FLOAT, 0 }, + { 16, SEM_TEXCOORD0, DataFormat::R32G32_FLOAT, 8 }, + }, + }; + InputLayout *inputLayout = draw_->CreateInputLayout(desc); + + BlendState *blendOff = draw_->CreateBlendState({ false, 0xF }); + DepthStencilStateDesc dsDesc{}; + DepthStencilState *noDepthStencil = draw_->CreateDepthStencilState(dsDesc); + RasterState *rasterNoCull = draw_->CreateRasterState({}); + + PipelineDesc stencilWriteDesc{ + Primitive::TRIANGLE_STRIP, + { draw2DVs_, draw2DFs_ }, + inputLayout, noDepthStencil, blendOff, rasterNoCull, nullptr, + }; + draw2DPipelineLinear_ = draw_->CreateGraphicsPipeline(stencilWriteDesc); + _assert_(draw2DPipelineLinear_); + + delete[] fsCode; + delete[] vsCode; + + rasterNoCull->Release(); + blendOff->Release(); + noDepthStencil->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); + } + + draw_->BindPipeline(draw2DPipelineLinear_); + draw_->BindTextures(TEX_SLOT_PSP_TEXTURE, 1, &tex); + draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &draw2DSamplerLinear_); + draw_->DrawUP(verts, vertexCount); + + gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); +} diff --git a/GPU/Common/Draw2D.h b/GPU/Common/Draw2D.h new file mode 100644 index 0000000000..34c171e7a0 --- /dev/null +++ b/GPU/Common/Draw2D.h @@ -0,0 +1,9 @@ +#pragma once + +// For framebuffer copies and similar things that just require passthrough. +struct Draw2DVertex { + float x; + float y; + float u; + float v; +}; diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 9478bf34fd..fec63dcb81 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2492,6 +2492,10 @@ void FramebufferManagerCommon::DeviceLost() { DoRelease(stencilUploadVs_); DoRelease(stencilUploadSampler_); DoRelease(stencilUploadPipeline_); + DoRelease(draw2DPipelineLinear_); + DoRelease(draw2DSamplerLinear_); + DoRelease(draw2DVs_); + DoRelease(draw2DFs_); presentation_->DeviceLost(); draw_ = nullptr; } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 894d7266e8..5ec21e88b0 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -29,11 +29,11 @@ #include "Common/CommonTypes.h" #include "Common/Log.h" -#include "Core/MemMap.h" +#include "Common/GPU/thin3d.h" #include "GPU/GPU.h" #include "GPU/ge_constants.h" #include "GPU/GPUInterface.h" -#include "Common/GPU/thin3d.h" +#include "GPU/Common/Draw2D.h" enum { FB_USAGE_DISPLAYED_FRAMEBUFFER = 1, @@ -357,6 +357,8 @@ protected: virtual 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) = 0; virtual void Bind2DShader() = 0; + void Draw2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, float viewportWidth, float viewportHeight); + bool UpdateSize(); void FlushBeforeCopy(); @@ -473,4 +475,10 @@ protected: Draw::ShaderModule *stencilUploadVs_ = nullptr; Draw::ShaderModule *stencilUploadFs_ = nullptr; Draw::SamplerState *stencilUploadSampler_ = nullptr; + + // Draw2D pipelines + Draw::Pipeline *draw2DPipelineLinear_ = nullptr; + Draw::SamplerState *draw2DSamplerLinear_ = nullptr; + Draw::ShaderModule *draw2DVs_ = nullptr; + Draw::ShaderModule *draw2DFs_ = nullptr; }; diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index ae899f0cd2..ca6cd6a03d 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -338,6 +338,7 @@ + @@ -459,6 +460,7 @@ + @@ -666,4 +668,4 @@ - + \ No newline at end of file diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index 9c8d6b0f93..db9157dde0 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -264,6 +264,9 @@ Software + + Common + @@ -518,6 +521,9 @@ Software + + Common + @@ -535,4 +541,4 @@ Shaders - + \ No newline at end of file diff --git a/android/jni/Android.mk b/android/jni/Android.mk index b2e4e6fe37..03dd60d89e 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -319,6 +319,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/GPU/GPUState.cpp \ $(SRC)/GPU/GeConstants.cpp \ $(SRC)/GPU/GeDisasm.cpp \ + $(SRC)/GPU/Common/Draw2D.cpp \ $(SRC)/GPU/Common/DepalettizeShaderCommon.cpp \ $(SRC)/GPU/Common/FragmentShaderGenerator.cpp \ $(SRC)/GPU/Common/FramebufferManagerCommon.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index dc7c0bc987..37e42af0ee 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -315,6 +315,7 @@ SOURCES_C +=\ $(COMMONDIR)/GPU/OpenGL/gl3stub.c SOURCES_CXX += \ + $(GPUCOMMONDIR)/Draw2D.cpp \ $(GPUCOMMONDIR)/VertexDecoderCommon.cpp \ $(GPUCOMMONDIR)/GPUStateUtils.cpp \ $(GPUCOMMONDIR)/DrawEngineCommon.cpp \