Split the depth copy shader into depth copy and depth encode, dynamic depth scale in Draw2D

This commit is contained in:
Henrik Rydgård 2023-02-10 09:41:18 +01:00
parent a083a65f77
commit 1938fa44d4
5 changed files with 68 additions and 31 deletions

View file

@ -114,7 +114,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) {
break;
case GE_FORMAT_DEPTH16:
// Decode depth buffer.
writer.C(" float depth = (color.x - z_offset) * z_scale;\n");
writer.C(" float depth = (color.x - z_offset) * z_scale * 65535.0f;\n");
if (config.bufferFormat == GE_FORMAT_DEPTH16 && config.textureFormat == GE_TFMT_5650) {
// Convert depth to 565, without going through a CLUT.

View file

@ -39,11 +39,12 @@ static const SamplerDef samplers[1] = {
{ 0, "tex", SamplerFlags::ARRAY_ON_VULKAN },
};
const UniformDef g_draw2Duniforms[4] = {
const UniformDef g_draw2Duniforms[5] = {
{ "vec2", "texSize", 0 },
{ "float", "scaleFactor", 1},
{ "float", "z_scale", 2 },
{ "float", "z_offset", 3 },
{ "float", "z_scale_inv", 3 },
{ "float", "z_offset", 4 },
};
struct Draw2DUB {
@ -51,6 +52,7 @@ struct Draw2DUB {
float texSizeY;
float scaleFactor;
float zScale;
float zScaleInv;
float zOffset;
};
@ -58,7 +60,8 @@ const UniformBufferDesc draw2DUBDesc{ sizeof(Draw2DUB), {
{ "texSize", -1, 0, UniformType::FLOAT2, 0 },
{ "scaleFactor", -1, 1, UniformType::FLOAT1, 8 },
{ "z_scale", -1, 1, UniformType::FLOAT1, 12 },
{ "z_offset", -1, 1, UniformType::FLOAT1, 16 },
{ "z_scale_inv", -1, 1, UniformType::FLOAT1, 16 },
{ "z_offset", -1, 1, UniformType::FLOAT1, 20 },
} };
Draw2DPipelineInfo GenerateDraw2DCopyColorFs(ShaderWriter &writer) {
@ -100,23 +103,41 @@ Draw2DPipelineInfo GenerateDraw2DCopyDepthFs(ShaderWriter &writer) {
writer.EndFSMain("outColor");
return Draw2DPipelineInfo{
"draw2d_copy_r16_to_depth",
"draw2d_copy_depth",
RASTER_DEPTH, // Unused in this case, I think.
RASTER_DEPTH,
};
}
Draw2DPipelineInfo GenerateDraw2DEncodeDepthFs(ShaderWriter &writer) {
writer.SetFlags(ShaderWriterFlags::FS_WRITE_DEPTH);
writer.HighPrecisionFloat();
writer.DeclareSamplers(samplers);
writer.BeginFSMain(g_draw2Duniforms, varyings);
writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n");
writer.C(" float depthValue = ").SampleTexture2D("tex", "v_texcoord.xy").C(".x;\n");
writer.C(" gl_FragDepth = (depthValue * z_scale_inv) + z_offset;\n");
writer.EndFSMain("outColor");
return Draw2DPipelineInfo{
"draw2d_copy_r16_to_depth",
RASTER_COLOR,
RASTER_DEPTH,
};
}
Draw2DPipelineInfo GenerateDraw2D565ToDepthFs(ShaderWriter &writer) {
writer.SetFlags(ShaderWriterFlags::FS_WRITE_DEPTH);
writer.HighPrecisionFloat();
writer.DeclareSamplers(samplers);
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings);
writer.BeginFSMain(g_draw2Duniforms, varyings);
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(gstate_c.UseFlags());
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.ScaleU16(), factors.Offset());
writer.F(" float depthValue = ((floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0)) / 65535.0; \n");
writer.C(" gl_FragDepth = (depthValue * z_scale_inv) + z_offset;\n");
writer.EndFSMain("outColor");
return Draw2DPipelineInfo{
@ -128,6 +149,7 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthFs(ShaderWriter &writer) {
Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) {
writer.SetFlags(ShaderWriterFlags::FS_WRITE_DEPTH);
writer.HighPrecisionFloat();
writer.DeclareSamplers(samplers);
writer.BeginFSMain(g_draw2Duniforms, varyings);
writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n");
@ -140,11 +162,11 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) {
writer.C(" float in_strip = mod(coord.y, strip);\n");
writer.C(" coord.y = coord.y - in_strip + strip - in_strip;\n");
writer.C(" coord /= tsize;\n");
writer.C(" vec3 rgb = ").SampleTexture2D("tex", "coord").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.ScaleU16(), factors.Offset());
writer.C(" highp vec3 rgb = ").SampleTexture2D("tex", "coord").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.C(" gl_FragDepth = z_offset + ((depthValue / 65535.0) * z_scale_inv);\n");
writer.EndFSMain("outColor");
return Draw2DPipelineInfo{
"draw2d_565_to_depth_deswizzle",
RASTER_COLOR,
@ -253,7 +275,7 @@ Draw2DPipeline *Draw2D::Create2DPipeline(std::function<Draw2DPipelineInfo (Shade
};
InputLayout *inputLayout = draw_->CreateInputLayout(desc);
BlendState *blend = draw_->CreateBlendState({ false, info.writeChannel == RASTER_COLOR ? 0xF : 0 });
BlendState *blend = draw_->CreateBlendState({ false, info.writeChannel == RASTER_COLOR ? 0xF : 0x0 });
DepthStencilStateDesc dsDesc{};
if (info.writeChannel == RASTER_DEPTH) {
@ -326,6 +348,7 @@ void Draw2D::DrawStrip2D(Draw::Texture *tex, const Draw2DVertex *verts, int vert
DepthScaleFactors zScaleFactors = GetDepthScaleFactors(gstate_c.UseFlags());
ub.zScale = zScaleFactors.Scale();
ub.zScaleInv = 1.0f / ub.zScale;
ub.zOffset = zScaleFactors.Offset();
draw_->BindPipeline(pipeline->pipeline);
@ -352,10 +375,10 @@ Draw2DPipeline *FramebufferManagerCommon::Get2DPipeline(Draw2DShader shader) {
switch (shader) {
case DRAW2D_COPY_COLOR:
if (!draw2DPipelineColor_) {
draw2DPipelineColor_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyColorFs);
if (!draw2DPipelineCopyColor_) {
draw2DPipelineCopyColor_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyColorFs);
}
pipeline = draw2DPipelineColor_;
pipeline = draw2DPipelineCopyColor_;
break;
case DRAW2D_COPY_COLOR_RECT2LIN:
@ -364,16 +387,26 @@ Draw2DPipeline *FramebufferManagerCommon::Get2DPipeline(Draw2DShader shader) {
}
pipeline = draw2DPipelineColorRect2Lin_;
break;
case DRAW2D_COPY_R16_TO_DEPTH:
case DRAW2D_COPY_DEPTH:
if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
// Can't do it
return nullptr;
}
if (!draw2DPipelineDepth_) {
draw2DPipelineDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyDepthFs);
if (!draw2DPipelineCopyDepth_) {
draw2DPipelineCopyDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyDepthFs);
}
pipeline = draw2DPipelineDepth_;
pipeline = draw2DPipelineCopyDepth_;
break;
case DRAW2D_ENCODE_R16_TO_DEPTH:
if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
// Can't do it
return nullptr;
}
if (!draw2DPipelineEncodeDepth_) {
draw2DPipelineEncodeDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DEncodeDepthFs);
}
pipeline = draw2DPipelineEncodeDepth_;
break;
case DRAW2D_565_TO_DEPTH:

View file

@ -13,7 +13,8 @@ struct Draw2DVertex {
enum Draw2DShader {
DRAW2D_COPY_COLOR,
DRAW2D_COPY_R16_TO_DEPTH,
DRAW2D_COPY_DEPTH,
DRAW2D_ENCODE_R16_TO_DEPTH,
DRAW2D_565_TO_DEPTH,
DRAW2D_565_TO_DEPTH_DESWIZZLE,
DRAW2D_COPY_COLOR_RECT2LIN,
@ -21,9 +22,10 @@ enum Draw2DShader {
inline RasterChannel Draw2DSourceChannel(Draw2DShader shader) {
switch (shader) {
case DRAW2D_COPY_R16_TO_DEPTH:
case DRAW2D_COPY_DEPTH:
return RASTER_DEPTH;
case DRAW2D_COPY_COLOR:
case DRAW2D_ENCODE_R16_TO_DEPTH:
case DRAW2D_565_TO_DEPTH:
case DRAW2D_565_TO_DEPTH_DESWIZZLE:
default:
@ -38,7 +40,7 @@ struct Draw2DPipelineInfo {
Slice<SamplerDef> samplers;
};
extern const UniformDef g_draw2Duniforms[4];
extern const UniformDef g_draw2Duniforms[5];
struct Draw2DPipeline {
Draw::Pipeline *pipeline;

View file

@ -974,7 +974,7 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir
// Some GPUs can copy depth but only if stencil gets to come along for the ride. We only want to use this if there is no blit functionality.
if (useRaster) {
BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_R16_TO_DEPTH), "BlitDepthRaster");
BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_DEPTH), "BlitDepthRaster");
} else if (useCopy) {
draw_->CopyFramebufferImage(src->fbo, 0, 0, 0, 0, dst->fbo, 0, 0, 0, 0, w, h, 1, Draw::FB_DEPTH_BIT, "CopyFramebufferDepth");
RebindFramebuffer("After BlitFramebufferDepth");
@ -2964,9 +2964,10 @@ void FramebufferManagerCommon::ReleasePipelines() {
DoRelease(stencilReadbackPipeline_);
DoRelease(depthReadbackSampler_);
DoRelease(depthReadbackPipeline_);
DoRelease(draw2DPipelineColor_);
DoRelease(draw2DPipelineCopyColor_);
DoRelease(draw2DPipelineColorRect2Lin_);
DoRelease(draw2DPipelineDepth_);
DoRelease(draw2DPipelineCopyDepth_);
DoRelease(draw2DPipelineEncodeDepth_);
DoRelease(draw2DPipeline565ToDepth_);
DoRelease(draw2DPipeline565ToDepthDeswizzle_);
}
@ -3036,7 +3037,7 @@ void FramebufferManagerCommon::DrawActiveTexture(float x, float y, float w, floa
// Rearrange to strip form.
std::swap(coord[2], coord[3]);
draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_COPY_R16_TO_DEPTH : DRAW2D_COPY_COLOR));
draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_ENCODE_R16_TO_DEPTH : DRAW2D_COPY_COLOR));
gstate_c.Dirty(DIRTY_ALL_RENDER_STATE);
}
@ -3135,7 +3136,7 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2,
channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST, tag);
} else {
Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_R16_TO_DEPTH);
Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_DEPTH);
Draw::Framebuffer *srcFBO = src->fbo;
if (src == dst) {
Draw::Framebuffer *tempFBO = GetTempFBO(TempFBO::BLIT, src->renderWidth, src->renderHeight);

View file

@ -605,9 +605,10 @@ protected:
Draw::SamplerState *depthReadbackSampler_ = nullptr;
// Draw2D pipelines
Draw2DPipeline *draw2DPipelineColor_ = nullptr;
Draw2DPipeline *draw2DPipelineCopyColor_ = nullptr;
Draw2DPipeline *draw2DPipelineColorRect2Lin_ = nullptr;
Draw2DPipeline *draw2DPipelineDepth_ = nullptr;
Draw2DPipeline *draw2DPipelineCopyDepth_ = nullptr;
Draw2DPipeline *draw2DPipelineEncodeDepth_ = nullptr;
Draw2DPipeline *draw2DPipeline565ToDepth_ = nullptr;
Draw2DPipeline *draw2DPipeline565ToDepthDeswizzle_ = nullptr;