Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copy color to depth, defer depth buffer copies #15858

Merged
merged 7 commits into from
Aug 20, 2022
36 changes: 32 additions & 4 deletions GPU/Common/Draw2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "GPU/Common/DrawEngineCommon.h"
#include "GPU/Common/FramebufferManagerCommon.h"
#include "GPU/Common/TextureCacheCommon.h"
#include "GPU/Common/GPUStateUtils.h"

static const InputDef inputs[2] = {
{ "vec2", "a_position", Draw::SEM_POSITION },
Expand Down Expand Up @@ -58,6 +59,20 @@ RasterChannel GenerateDraw2DDepthFs(ShaderWriter &writer) {
return RASTER_DEPTH;
}

RasterChannel GenerateDraw2D565ToDepthFs(ShaderWriter &writer) {
writer.DeclareSamplers(samplers);
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings, FSFLAG_WRITEDEPTH);
writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n");
// Unlike when just copying a depth buffer, here we're generating new depth values so we'll
// have to apply the scaling.
DepthScaleFactors factors = GetDepthScaleFactors();
writer.C(" vec3 rgb = ").SampleTexture2D("tex", "v_texcoord.xy").C(".xyz;\n");
writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n");
writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.scale, factors.offset);
writer.EndFSMain("outColor", FSFLAG_WRITEDEPTH);
return RASTER_DEPTH;
}

void GenerateDraw2DVS(ShaderWriter &writer) {
writer.BeginVSMain(inputs, Slice<UniformDef>::empty(), varyings);

Expand Down Expand Up @@ -159,31 +174,44 @@ Draw::Pipeline *FramebufferManagerCommon::Create2DPipeline(RasterChannel (*gener
return pipeline;
}

void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel) {
void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, Draw2DShader shader) {
using namespace Draw;

Ensure2DResources();

const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();

switch (channel) {
case RASTER_COLOR:
switch (shader) {
case DRAW2D_COPY_COLOR:
if (!draw2DPipelineColor_) {
draw2DPipelineColor_ = Create2DPipeline(&GenerateDraw2DFs);
}
draw_->BindPipeline(draw2DPipelineColor_);
break;

case RASTER_DEPTH:
case DRAW2D_COPY_DEPTH:
if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
// Can't do it
return;
}
if (!draw2DPipelineDepth_) {
draw2DPipelineDepth_ = Create2DPipeline(&GenerateDraw2DDepthFs);
linearFilter = false;
}
draw_->BindPipeline(draw2DPipelineDepth_);
break;

case DRAW2D_565_TO_DEPTH:
if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
// Can't do it
return;
}
if (!draw2DPipeline565ToDepth_) {
draw2DPipeline565ToDepth_ = Create2DPipeline(&GenerateDraw2D565ToDepthFs);
linearFilter = false;
}
draw_->BindPipeline(draw2DPipeline565ToDepth_);
break;
}

if (tex) {
Expand Down
19 changes: 19 additions & 0 deletions GPU/Common/Draw2D.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
#pragma once

#include "GPU/GPU.h"

// For framebuffer copies and similar things that just require passthrough.
struct Draw2DVertex {
float x;
float y;
float u;
float v;
};

enum Draw2DShader {
DRAW2D_COPY_COLOR,
DRAW2D_COPY_DEPTH,
DRAW2D_565_TO_DEPTH,
};

inline RasterChannel Draw2DSourceChannel(Draw2DShader shader) {
switch (shader) {
case DRAW2D_COPY_DEPTH:
return RASTER_DEPTH;
case DRAW2D_COPY_COLOR:
case DRAW2D_565_TO_DEPTH:
default:
return RASTER_COLOR;
}
}
29 changes: 2 additions & 27 deletions GPU/Common/FragmentShaderGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
bool shaderDepal = id.Bit(FS_BIT_SHADER_DEPAL) && !texture3D; // combination with texture3D not supported. Enforced elsewhere too.
bool bgraTexture = id.Bit(FS_BIT_BGRA_TEXTURE);
bool colorWriteMask = id.Bit(FS_BIT_COLOR_WRITEMASK) && compat.bitwiseOps;
bool colorToDepth = id.Bit(FS_BIT_COLOR_TO_DEPTH);

GEComparison alphaTestFunc = (GEComparison)id.Bits(FS_BIT_ALPHA_TEST_FUNC, 3);
GEComparison colorTestFunc = (GEComparison)id.Bits(FS_BIT_COLOR_TEST_FUNC, 2);
Expand Down Expand Up @@ -123,7 +122,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
bool readFramebufferTex = readFramebuffer && !gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH);

bool needFragCoord = readFramebuffer || gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT);
bool writeDepth = gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT) || colorToDepth;
bool writeDepth = gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT);

if (shaderDepal && !doTexture) {
*errorString = "depal requires a texture";
Expand All @@ -136,11 +135,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
}

if (compat.shaderLanguage == ShaderLanguage::GLSL_VULKAN) {
if (colorToDepth) {
WRITE(p, "precision highp int;\n");
WRITE(p, "precision highp float;\n");
}

if (useDiscardStencilBugWorkaround && !gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) {
WRITE(p, "layout (depth_unchanged) out float gl_FragDepth;\n");
}
Expand Down Expand Up @@ -293,7 +287,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
WRITE(p, "};\n");
}
} else if (ShaderLanguageIsOpenGL(compat.shaderLanguage)) {
if ((shaderDepal || colorWriteMask || colorToDepth) && gl_extensions.IsGLES) {
if ((shaderDepal || colorWriteMask) && gl_extensions.IsGLES) {
WRITE(p, "precision highp int;\n");
}

Expand Down Expand Up @@ -461,9 +455,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
WRITE(p, "PS_OUT main( PS_IN In ) {\n");
WRITE(p, " PS_OUT outfragment;\n");
WRITE(p, " vec4 target;\n");
if (colorToDepth) {
WRITE(p, " float gl_FragDepth;\n");
}
} else {
WRITE(p, "void main() {\n");
}
Expand Down Expand Up @@ -1070,22 +1061,6 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
WRITE(p, " %s = vec4(0.0, 0.0, 0.0, %s.z); // blue to alpha\n", compat.fragColor0, compat.fragColor0);
}

if (colorToDepth) {
DepthScaleFactors factors = GetDepthScaleFactors();

if (compat.bitwiseOps) {
WRITE(p, " highp float depthValue = float(int(%s.x * 31.99) | (int(%s.y * 63.99) << 5) | (int(%s.z * 31.99) << 11)) / 65535.0;\n", "v", "v", "v"); // compat.fragColor0, compat.fragColor0, compat.fragColor0);
} else {
// D3D9-compatible alternative
WRITE(p, " highp float depthValue = (floor(%s.x * 31.99) + floor(%s.y * 63.99) * 32.0 + floor(%s.z * 31.99) * 2048.0) / 65535.0;\n", "v", "v", "v"); // compat.fragColor0, compat.fragColor0, compat.fragColor0);
}
if (factors.scale != 1.0 || factors.offset != 0.0) {
WRITE(p, " gl_FragDepth = (depthValue / %f) + %f;\n", factors.scale / 65535.0f, factors.offset);
} else {
WRITE(p, " gl_FragDepth = depthValue;\n");
}
}

if (gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) {
const double scale = DepthSliceFactor() * 65535.0;

Expand Down
Loading