mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 09:39:33 +01:00
Merge pull request #15815 from hrydgard/depth-blit-using-raster
Depth blit using raster
This commit is contained in:
23 files changed
+220
-89
No files matched your search
@@ -269,6 +269,7 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
|
||||
caps_.fragmentShaderInt32Supported = true;
|
||||
caps_.anisoSupported = true;
|
||||
caps_.textureNPOTFullySupported = true;
|
||||
caps_.fragmentShaderDepthWriteSupported = true;
|
||||
|
||||
D3D11_FEATURE_DATA_D3D11_OPTIONS options{};
|
||||
HRESULT result = device_->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &options, sizeof(options));
|
||||
|
||||
@@ -669,6 +669,7 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID
|
||||
caps_.framebufferSeparateDepthCopySupported = false;
|
||||
caps_.texture3DSupported = true;
|
||||
caps_.textureNPOTFullySupported = true;
|
||||
caps_.fragmentShaderDepthWriteSupported = true;
|
||||
|
||||
if (d3d) {
|
||||
D3DDISPLAYMODE displayMode;
|
||||
|
||||
@@ -560,6 +560,13 @@ OpenGLContext::OpenGLContext() {
|
||||
gl_extensions.IsCoreContext || gl_extensions.GLES3 ||
|
||||
gl_extensions.ARB_texture_non_power_of_two || gl_extensions.OES_texture_npot;
|
||||
|
||||
if (gl_extensions.IsGLES) {
|
||||
caps_.fragmentShaderDepthWriteSupported = gl_extensions.GLES3;
|
||||
// There's also GL_EXT_frag_depth but it's rare along with 2.0. Most chips that support it are simply 3.0 chips.
|
||||
} else {
|
||||
caps_.fragmentShaderDepthWriteSupported = true;
|
||||
}
|
||||
|
||||
// Interesting potential hack for emulating GL_DEPTH_CLAMP (use a separate varying, force depth in fragment shader):
|
||||
// This will induce a performance penalty on many architectures though so a blanket enable of this
|
||||
// is probably not a good idea.
|
||||
|
||||
@@ -212,7 +212,7 @@ void ShaderWriter::BeginVSMain(Slice<InputDef> inputs, Slice<UniformDef> uniform
|
||||
}
|
||||
}
|
||||
|
||||
void ShaderWriter::BeginFSMain(Slice<UniformDef> uniforms, Slice<VaryingDef> varyings) {
|
||||
void ShaderWriter::BeginFSMain(Slice<UniformDef> uniforms, Slice<VaryingDef> varyings, FSFlags flags) {
|
||||
_assert_(this->stage_ == ShaderStage::Fragment);
|
||||
switch (lang_.shaderLanguage) {
|
||||
case HLSL_D3D11:
|
||||
@@ -226,29 +226,56 @@ void ShaderWriter::BeginFSMain(Slice<UniformDef> uniforms, Slice<VaryingDef> var
|
||||
C("};\n");
|
||||
}
|
||||
|
||||
if (flags & FSFLAG_WRITEDEPTH) {
|
||||
C("float gl_FragDepth;\n");
|
||||
}
|
||||
|
||||
C("struct PS_OUT {\n");
|
||||
C(" vec4 target : SV_Target0;\n");
|
||||
if (flags & FSFLAG_WRITEDEPTH) {
|
||||
C(" float depth : SV_Depth;\n");
|
||||
}
|
||||
C("};\n");
|
||||
|
||||
// Let's do the varyings as parameters to main, no struct.
|
||||
C("vec4 main(");
|
||||
C("PS_OUT main(");
|
||||
for (auto &varying : varyings) {
|
||||
F(" %s %s : %s, ", varying.type, varying.name, semanticNames[varying.semantic]);
|
||||
}
|
||||
// Erase the last comma
|
||||
Rewind(2);
|
||||
|
||||
F(") : SV_Target0 {\n");
|
||||
F(") {\n");
|
||||
C(" PS_OUT ps_out;\n");
|
||||
if (flags & FSFLAG_WRITEDEPTH) {
|
||||
C(" float gl_FragDepth;\n");
|
||||
}
|
||||
break;
|
||||
case HLSL_D3D9:
|
||||
C("struct PS_OUT {\n");
|
||||
C(" vec4 target : SV_Target0;\n");
|
||||
if (flags & FSFLAG_WRITEDEPTH) {
|
||||
C(" float depth : DEPTH;\n");
|
||||
}
|
||||
C("};\n");
|
||||
|
||||
for (auto &uniform : uniforms) {
|
||||
F(" %s %s : register(c%d);\n", uniform.type, uniform.name, uniform.index);
|
||||
}
|
||||
// Let's do the varyings as parameters to main, no struct.
|
||||
C("vec4 main(");
|
||||
C("PS_OUT main(");
|
||||
for (auto &varying : varyings) {
|
||||
F(" %s %s : %s, ", varying.type, varying.name, semanticNames[varying.semantic]);
|
||||
}
|
||||
// Erase the last comma
|
||||
Rewind(2);
|
||||
|
||||
F(") : COLOR {\n");
|
||||
F(") {\n");
|
||||
C(" PS_OUT ps_out;\n");
|
||||
if (flags & FSFLAG_WRITEDEPTH) {
|
||||
C(" float gl_FragDepth;\n");
|
||||
}
|
||||
|
||||
break;
|
||||
case GLSL_VULKAN:
|
||||
for (auto &varying : varyings) {
|
||||
@@ -299,12 +326,16 @@ void ShaderWriter::EndVSMain(Slice<VaryingDef> varyings) {
|
||||
C("}\n");
|
||||
}
|
||||
|
||||
void ShaderWriter::EndFSMain(const char *vec4_color_variable) {
|
||||
void ShaderWriter::EndFSMain(const char *vec4_color_variable, FSFlags flags) {
|
||||
_assert_(this->stage_ == ShaderStage::Fragment);
|
||||
switch (lang_.shaderLanguage) {
|
||||
case HLSL_D3D11:
|
||||
case HLSL_D3D9:
|
||||
F(" return %s;\n", vec4_color_variable);
|
||||
F(" ps_out.target = %s;\n", vec4_color_variable);
|
||||
if (flags & FSFLAG_WRITEDEPTH) {
|
||||
C(" ps_out.depth = gl_FragDepth;\n");
|
||||
}
|
||||
C(" return ps_out;\n");
|
||||
break;
|
||||
case GLSL_VULKAN:
|
||||
default: // OpenGL
|
||||
|
||||
@@ -36,6 +36,11 @@ struct VaryingDef {
|
||||
const char *precision;
|
||||
};
|
||||
|
||||
enum FSFlags {
|
||||
FSFLAG_NONE = 0,
|
||||
FSFLAG_WRITEDEPTH = 1,
|
||||
};
|
||||
|
||||
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) {
|
||||
@@ -82,11 +87,11 @@ public:
|
||||
|
||||
// Simple shaders with no special tricks.
|
||||
void BeginVSMain(Slice<InputDef> inputs, Slice<UniformDef> uniforms, Slice<VaryingDef> varyings);
|
||||
void BeginFSMain(Slice<UniformDef> uniforms, Slice<VaryingDef> varyings);
|
||||
void BeginFSMain(Slice<UniformDef> uniforms, Slice<VaryingDef> varyings, FSFlags flags);
|
||||
|
||||
// For simple shaders that output a single color, we can deal with this generically.
|
||||
void EndVSMain(Slice<VaryingDef> varyings);
|
||||
void EndFSMain(const char *vec4_color_variable);
|
||||
void EndFSMain(const char *vec4_color_variable, FSFlags flags);
|
||||
|
||||
|
||||
void Rewind(size_t offset) {
|
||||
|
||||
@@ -793,6 +793,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
|
||||
caps_.texture3DSupported = true;
|
||||
caps_.fragmentShaderInt32Supported = true;
|
||||
caps_.textureNPOTFullySupported = true;
|
||||
caps_.fragmentShaderDepthWriteSupported = true;
|
||||
|
||||
auto deviceProps = vulkan->GetPhysicalDeviceProperties(vulkan_->GetCurrentPhysicalDeviceIndex()).properties;
|
||||
switch (deviceProps.vendorID) {
|
||||
|
||||
@@ -541,6 +541,7 @@ struct DeviceCaps {
|
||||
bool texture3DSupported;
|
||||
bool fragmentShaderInt32Supported;
|
||||
bool textureNPOTFullySupported;
|
||||
bool fragmentShaderDepthWriteSupported;
|
||||
|
||||
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
|
||||
};
|
||||
|
||||
@@ -267,7 +267,7 @@ void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLangua
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0);
|
||||
writer.DeclareSamplers(samplers);
|
||||
writer.HighPrecisionFloat();
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings);
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings, FSFLAG_NONE);
|
||||
switch (lang.shaderLanguage) {
|
||||
case HLSL_D3D9:
|
||||
case GLSL_1xx:
|
||||
@@ -281,7 +281,7 @@ void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLangua
|
||||
default:
|
||||
_assert_msg_(false, "Depal shader language not supported: %d", (int)lang.shaderLanguage);
|
||||
}
|
||||
writer.EndFSMain("outColor");
|
||||
writer.EndFSMain("outColor", FSFLAG_NONE);
|
||||
}
|
||||
|
||||
void GenerateDepalVs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
|
||||
+56
-12
@@ -39,12 +39,21 @@ static const SamplerDef samplers[1] = {
|
||||
{ "tex" },
|
||||
};
|
||||
|
||||
void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang, const Draw::Bugs &bugs) {
|
||||
void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0);
|
||||
writer.DeclareSamplers(samplers);
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings);
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings, FSFLAG_NONE);
|
||||
writer.C(" vec4 outColor = ").SampleTexture2D("tex", "v_texcoord.xy").C(";\n");
|
||||
writer.EndFSMain("outColor");
|
||||
writer.EndFSMain("outColor", FSFLAG_NONE);
|
||||
}
|
||||
|
||||
void GenerateDraw2DDepthFs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0);
|
||||
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");
|
||||
writer.C(" gl_FragDepth = ").SampleTexture2D("tex", "v_texcoord.xy").C(".x;\n");
|
||||
writer.EndFSMain("outColor", FSFLAG_WRITEDEPTH);
|
||||
}
|
||||
|
||||
void GenerateDraw2DVS(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
@@ -60,15 +69,17 @@ void GenerateDraw2DVS(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
}
|
||||
|
||||
// verts have positions in clip coordinates.
|
||||
void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter) {
|
||||
void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel) {
|
||||
using namespace Draw;
|
||||
|
||||
if (!draw2DPipelineLinear_) {
|
||||
if (!draw2DPipelineColor_) {
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
|
||||
char *fsCode = new char[4000];
|
||||
char *fsDepthCode = new char[4000];
|
||||
char *vsCode = new char[4000];
|
||||
GenerateDraw2DFs(fsCode, shaderLanguageDesc, draw_->GetBugs());
|
||||
GenerateDraw2DFs(fsCode, shaderLanguageDesc);
|
||||
GenerateDraw2DDepthFs(fsDepthCode, shaderLanguageDesc);
|
||||
GenerateDraw2DVS(vsCode, shaderLanguageDesc);
|
||||
|
||||
draw2DFs_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs");
|
||||
@@ -76,6 +87,13 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver
|
||||
|
||||
_assert_(draw2DFs_ && draw2DVs_);
|
||||
|
||||
if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
|
||||
draw2DFsDepth_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs");
|
||||
_assert_(draw2DFsDepth_);
|
||||
} else {
|
||||
draw2DFsDepth_ = nullptr;
|
||||
}
|
||||
|
||||
InputLayoutDesc desc = {
|
||||
{
|
||||
{ 16, false },
|
||||
@@ -88,24 +106,46 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver
|
||||
InputLayout *inputLayout = draw_->CreateInputLayout(desc);
|
||||
|
||||
BlendState *blendOff = draw_->CreateBlendState({ false, 0xF });
|
||||
DepthStencilStateDesc dsDesc{};
|
||||
DepthStencilState *noDepthStencil = draw_->CreateDepthStencilState(dsDesc);
|
||||
BlendState *blendDiscard = draw_->CreateBlendState({ false, 0x0 });
|
||||
|
||||
DepthStencilState *noDepthStencil = draw_->CreateDepthStencilState(DepthStencilStateDesc{});
|
||||
RasterState *rasterNoCull = draw_->CreateRasterState({});
|
||||
|
||||
PipelineDesc stencilWriteDesc{
|
||||
DepthStencilStateDesc dsWriteDesc{};
|
||||
dsWriteDesc.depthTestEnabled = true;
|
||||
dsWriteDesc.depthWriteEnabled = true;
|
||||
dsWriteDesc.depthCompare = Draw::Comparison::ALWAYS;
|
||||
DepthStencilState *depthWriteAlways = draw_->CreateDepthStencilState(dsWriteDesc);
|
||||
|
||||
PipelineDesc draw2DColorPipelineDesc{
|
||||
Primitive::TRIANGLE_STRIP,
|
||||
{ draw2DVs_, draw2DFs_ },
|
||||
inputLayout, noDepthStencil, blendOff, rasterNoCull, nullptr,
|
||||
};
|
||||
draw2DPipelineLinear_ = draw_->CreateGraphicsPipeline(stencilWriteDesc);
|
||||
_assert_(draw2DPipelineLinear_);
|
||||
|
||||
draw2DPipelineColor_ = draw_->CreateGraphicsPipeline(draw2DColorPipelineDesc);
|
||||
|
||||
PipelineDesc draw2DDepthPipelineDesc{
|
||||
Primitive::TRIANGLE_STRIP,
|
||||
{ draw2DVs_, draw2DFsDepth_ },
|
||||
inputLayout, depthWriteAlways, blendDiscard, rasterNoCull, nullptr,
|
||||
};
|
||||
|
||||
if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
|
||||
draw2DPipelineDepth_ = draw_->CreateGraphicsPipeline(draw2DDepthPipelineDesc);
|
||||
_assert_(draw2DPipelineDepth_);
|
||||
} else {
|
||||
draw2DPipelineDepth_ = nullptr;
|
||||
}
|
||||
|
||||
delete[] fsCode;
|
||||
delete[] vsCode;
|
||||
|
||||
rasterNoCull->Release();
|
||||
blendOff->Release();
|
||||
blendDiscard->Release();
|
||||
noDepthStencil->Release();
|
||||
depthWriteAlways->Release();
|
||||
inputLayout->Release();
|
||||
|
||||
SamplerStateDesc descLinear{};
|
||||
@@ -125,7 +165,11 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver
|
||||
draw2DSamplerNearest_ = draw_->CreateSamplerState(descNearest);
|
||||
}
|
||||
|
||||
draw_->BindPipeline(draw2DPipelineLinear_);
|
||||
if (channel == RASTER_DEPTH && !draw2DPipelineDepth_) {
|
||||
return;
|
||||
}
|
||||
|
||||
draw_->BindPipeline(channel == RASTER_COLOR ? draw2DPipelineColor_ : draw2DPipelineDepth_);
|
||||
if (tex) {
|
||||
draw_->BindTextures(TEX_SLOT_PSP_TEXTURE, 1, &tex);
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
||||
WARN_LOG_ONCE(color_equal_z, G3D, "Framebuffer bound with color addr == z addr, likely will not use Z in this pass: %08x", params.fb_address);
|
||||
}
|
||||
|
||||
FramebufferRenderMode mode = FB_MODE_NORMAL;
|
||||
RasterMode mode = RASTER_MODE_NORMAL;
|
||||
|
||||
// Find a matching framebuffer
|
||||
VirtualFramebuffer *vfb = nullptr;
|
||||
@@ -331,7 +331,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
||||
// Seems impractical to use the other 16-bit formats for this due to the limited control over alpha,
|
||||
// so we'll simply only support 565.
|
||||
if (params.fmt == GE_FORMAT_565) {
|
||||
mode = FB_MODE_COLOR_TO_DEPTH;
|
||||
mode = RASTER_MODE_COLOR_TO_DEPTH;
|
||||
break;
|
||||
}
|
||||
} else if (v->fb_stride == params.fb_stride && v->format == params.fmt) {
|
||||
@@ -368,7 +368,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
||||
}
|
||||
}
|
||||
|
||||
if (mode == FB_MODE_COLOR_TO_DEPTH) {
|
||||
if (mode == RASTER_MODE_COLOR_TO_DEPTH) {
|
||||
// Lookup in the depth tracking to find which VFB has the latest version of this Z buffer.
|
||||
// Then bind it in color-to-depth mode.
|
||||
//
|
||||
@@ -564,6 +564,8 @@ void FramebufferManagerCommon::DestroyFramebuf(VirtualFramebuffer *v) {
|
||||
void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) {
|
||||
_dbg_assert_(src && dst);
|
||||
|
||||
_dbg_assert_(src != dst);
|
||||
|
||||
// Check that the depth address is even the same before actually blitting.
|
||||
bool matchingDepthBuffer = src->z_address == dst->z_address && src->z_stride != 0 && dst->z_stride != 0;
|
||||
bool matchingSize = (src->width == dst->width || (src->width == 512 && dst->width == 480) || (src->width == 480 && dst->width == 512)) && src->height == dst->height;
|
||||
@@ -579,7 +581,20 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir
|
||||
return;
|
||||
}
|
||||
|
||||
gpuStats.numDepthCopies++;
|
||||
bool useCopy = draw_->GetDeviceCaps().framebufferSeparateDepthCopySupported || (!draw_->GetDeviceCaps().framebufferDepthBlitSupported && draw_->GetDeviceCaps().framebufferCopySupported);
|
||||
bool useBlit = draw_->GetDeviceCaps().framebufferDepthBlitSupported;
|
||||
|
||||
bool useRaster = draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported;
|
||||
|
||||
// Could do an attempt at optimization - if destination already bound, draw depth using raster.
|
||||
// Let's experiment later, commented out for now. Currently we fall back to raster as a last resort here.
|
||||
|
||||
/*
|
||||
if (currentRenderVfb_ == dst) {
|
||||
useCopy = false;
|
||||
useBlit = false;
|
||||
}
|
||||
*/
|
||||
|
||||
int w = std::min(src->renderWidth, dst->renderWidth);
|
||||
int h = std::min(src->renderHeight, dst->renderHeight);
|
||||
@@ -587,14 +602,20 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir
|
||||
// TODO: It might even be advantageous on some GPUs to do this copy using a fragment shader that writes to Z, that way upcoming commands can just continue that render pass.
|
||||
|
||||
// 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 (draw_->GetDeviceCaps().framebufferSeparateDepthCopySupported || (!draw_->GetDeviceCaps().framebufferDepthBlitSupported && draw_->GetDeviceCaps().framebufferCopySupported)) {
|
||||
if (useCopy) {
|
||||
draw_->CopyFramebufferImage(src->fbo, 0, 0, 0, 0, dst->fbo, 0, 0, 0, 0, w, h, 1, Draw::FB_DEPTH_BIT, "BlitFramebufferDepth");
|
||||
RebindFramebuffer("After BlitFramebufferDepth");
|
||||
} else if (draw_->GetDeviceCaps().framebufferDepthBlitSupported) {
|
||||
} else if (useBlit) {
|
||||
// We'll accept whether we get a separate depth blit or not...
|
||||
draw_->BlitFramebuffer(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST, "BlitFramebufferDepth");
|
||||
RebindFramebuffer("After BlitFramebufferDepth");
|
||||
} else if (useRaster) {
|
||||
BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, RasterChannel::RASTER_DEPTH);
|
||||
}
|
||||
|
||||
draw_->InvalidateCachedState();
|
||||
|
||||
gpuStats.numDepthCopies++;
|
||||
dst->last_frame_depth_updated = gpuStats.numFlips;
|
||||
}
|
||||
|
||||
@@ -2495,11 +2516,13 @@ void FramebufferManagerCommon::DeviceLost() {
|
||||
DoRelease(stencilUploadVs_);
|
||||
DoRelease(stencilUploadSampler_);
|
||||
DoRelease(stencilUploadPipeline_);
|
||||
DoRelease(draw2DPipelineLinear_);
|
||||
DoRelease(draw2DPipelineColor_);
|
||||
DoRelease(draw2DPipelineDepth_);
|
||||
DoRelease(draw2DSamplerNearest_);
|
||||
DoRelease(draw2DSamplerLinear_);
|
||||
DoRelease(draw2DVs_);
|
||||
DoRelease(draw2DFs_);
|
||||
DoRelease(draw2DFsDepth_);
|
||||
presentation_->DeviceLost();
|
||||
draw_ = nullptr;
|
||||
}
|
||||
@@ -2557,15 +2580,18 @@ void FramebufferManagerCommon::DrawActiveTexture(float x, float y, float w, floa
|
||||
// Rearrange to strip form.
|
||||
std::swap(coord[2], coord[3]);
|
||||
|
||||
DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0);
|
||||
DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, RASTER_COLOR);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp, const char *tag) {
|
||||
RasterChannel channel = RASTER_COLOR;
|
||||
|
||||
if (!dst->fbo || !src->fbo || !useBufferedRendering_) {
|
||||
// This can happen if they recently switched from non-buffered.
|
||||
if (useBufferedRendering_) {
|
||||
// Just bind the back buffer for rendering, forget about doing anything else as we're in a weird state.
|
||||
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "BlitFramebuffer");
|
||||
}
|
||||
return;
|
||||
@@ -2638,30 +2664,39 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
|
||||
const bool xOverlap = src == dst && srcX2 > dstX1 && srcX1 < dstX2;
|
||||
const bool yOverlap = src == dst && srcY2 > dstY1 && srcY1 < dstY2;
|
||||
if (sameSize && srcInsideBounds && dstInsideBounds && !(xOverlap && yOverlap)) {
|
||||
draw_->CopyFramebufferImage(src->fbo, 0, srcX1, srcY1, 0, dst->fbo, 0, dstX1, dstY1, 0, dstX2 - dstX1, dstY2 - dstY1, 1, Draw::FB_COLOR_BIT, tag);
|
||||
draw_->CopyFramebufferImage(src->fbo, 0, srcX1, srcY1, 0, dst->fbo, 0, dstX1, dstY1, 0, dstX2 - dstX1, dstY2 - dstY1, 1,
|
||||
channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, tag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (useBlit) {
|
||||
draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, Draw::FB_COLOR_BIT, Draw::FB_BLIT_NEAREST, tag);
|
||||
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 {
|
||||
Draw::Framebuffer *srcFBO = src->fbo;
|
||||
if (src == dst) {
|
||||
Draw::Framebuffer *tempFBO = GetTempFBO(TempFBO::BLIT, src->renderWidth, src->renderHeight);
|
||||
BlitUsingRaster(src->fbo, srcX1, srcY1, srcX2, srcY2, tempFBO, dstX1, dstY1, dstX2, dstY2, false);
|
||||
BlitUsingRaster(src->fbo, srcX1, srcY1, srcX2, srcY2, tempFBO, dstX1, dstY1, dstX2, dstY2, false, channel);
|
||||
srcFBO = tempFBO;
|
||||
}
|
||||
BlitUsingRaster(srcFBO, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, false);
|
||||
BlitUsingRaster(srcFBO, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, false, channel);
|
||||
}
|
||||
|
||||
draw_->InvalidateCachedState();
|
||||
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE);
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::BlitUsingRaster(
|
||||
Draw::Framebuffer *src, float srcX1, float srcY1, float srcX2, float srcY2,
|
||||
Draw::Framebuffer *dest, float destX1, float destY1, float destX2, float destY2,
|
||||
bool linearFilter) {
|
||||
bool linearFilter,
|
||||
RasterChannel channel) {
|
||||
|
||||
if (channel == RASTER_DEPTH) {
|
||||
_dbg_assert_(draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported);
|
||||
}
|
||||
|
||||
int destW, destH, srcW, srcH;
|
||||
draw_->GetFramebufferDimensions(src, &srcW, &srcH);
|
||||
@@ -2678,17 +2713,16 @@ void FramebufferManagerCommon::BlitUsingRaster(
|
||||
{ -1.0f + 2.0f * dX * destX2, -(1.0f - 2.0f * dY * destY2), sX * srcX2, sY * srcY2 },
|
||||
};
|
||||
|
||||
if (dest != currentRenderVfb_->fbo) {
|
||||
// Unbind the texture first to avoid the D3D11 hazard check (can't set render target to things bound as textures and vice versa, not even temporarily).
|
||||
draw_->BindTexture(0, nullptr);
|
||||
draw_->BindFramebufferAsRenderTarget(dest, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "BlitUsingRaster");
|
||||
}
|
||||
draw_->BindFramebufferAsTexture(src, 0, Draw::FB_COLOR_BIT, 0);
|
||||
// Unbind the texture first to avoid the D3D11 hazard check (can't set render target to things bound as textures and vice versa, not even temporarily).
|
||||
draw_->BindTexture(0, nullptr);
|
||||
// This will get optimized away in case it's already bound (in VK and GL at least..)
|
||||
draw_->BindFramebufferAsRenderTarget(dest, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "BlitUsingRaster");
|
||||
draw_->BindFramebufferAsTexture(src, 0, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, 0);
|
||||
|
||||
Draw::Viewport vp{ 0.0f, 0.0f, (float)dest->Width(), (float)dest->Height(), 0.0f, 1.0f };
|
||||
draw_->SetViewports(1, &vp);
|
||||
draw_->SetScissorRect(0, 0, (int)dest->Width(), (int)dest->Height());
|
||||
DrawStrip2D(nullptr, vtx, 4, linearFilter);
|
||||
DrawStrip2D(nullptr, vtx, 4, linearFilter, channel);
|
||||
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE);
|
||||
}
|
||||
@@ -359,7 +359,7 @@ protected:
|
||||
Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height);
|
||||
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);
|
||||
void DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel);
|
||||
|
||||
bool UpdateSize();
|
||||
|
||||
@@ -367,11 +367,11 @@ protected:
|
||||
virtual void DecimateFBOs(); // keeping it virtual to let D3D do a little extra
|
||||
|
||||
// Used by ReadFramebufferToMemory and later framebuffer block copies
|
||||
virtual void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp, const char *tag);
|
||||
void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp, const char *tag);
|
||||
|
||||
void BlitUsingRaster(
|
||||
Draw::Framebuffer *src, float srcX1, float srcY1, float srcX2, float srcY2,
|
||||
Draw::Framebuffer *dest, float destX1, float destY1, float destX2, float destY2, bool linearFilter);
|
||||
Draw::Framebuffer *dest, float destX1, float destY1, float destX2, float destY2, bool linearFilter, RasterChannel channel);
|
||||
|
||||
void CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags);
|
||||
|
||||
@@ -485,9 +485,11 @@ protected:
|
||||
Draw::SamplerState *stencilUploadSampler_ = nullptr;
|
||||
|
||||
// Draw2D pipelines
|
||||
Draw::Pipeline *draw2DPipelineLinear_ = nullptr;
|
||||
Draw::Pipeline *draw2DPipelineColor_ = nullptr;
|
||||
Draw::Pipeline *draw2DPipelineDepth_ = nullptr;
|
||||
Draw::SamplerState *draw2DSamplerLinear_ = nullptr;
|
||||
Draw::SamplerState *draw2DSamplerNearest_ = nullptr;
|
||||
Draw::ShaderModule *draw2DVs_ = nullptr;
|
||||
Draw::ShaderModule *draw2DFs_ = nullptr;
|
||||
Draw::ShaderModule *draw2DFsDepth_ = nullptr;
|
||||
};
|
||||
@@ -1018,7 +1018,7 @@ void ConvertMaskState(GenericMaskState &maskState, bool allowFramebufferRead) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gstate_c.renderMode == FB_MODE_COLOR_TO_DEPTH) {
|
||||
if (gstate_c.renderMode == RASTER_MODE_COLOR_TO_DEPTH) {
|
||||
// Suppress color writes entirely in this mode.
|
||||
maskState.applyFramebufferRead = false;
|
||||
maskState.rgba[0] = false;
|
||||
|
||||
@@ -28,7 +28,7 @@ bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBuff
|
||||
|
||||
writer.DeclareSamplers(samplers);
|
||||
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings);
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings, FSFLAG_NONE);
|
||||
|
||||
writer.C(" vec4 val = ").SampleTexture2D("tex", "v_texcoord.xy").C(";\n");
|
||||
|
||||
@@ -68,7 +68,7 @@ bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBuff
|
||||
break;
|
||||
}
|
||||
|
||||
writer.EndFSMain("outColor");
|
||||
writer.EndFSMain("outColor", FSFLAG_NONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -264,7 +264,7 @@ void ComputeFragmentShaderID(FShaderID *id_out, const Draw::Bugs &bugs) {
|
||||
bool doFlatShading = gstate.getShadeMode() == GE_SHADE_FLAT;
|
||||
bool useShaderDepal = gstate_c.useShaderDepal;
|
||||
bool colorWriteMask = IsColorWriteMaskComplex(gstate_c.allowFramebufferRead);
|
||||
bool colorToDepth = gstate_c.renderMode == FramebufferRenderMode::FB_MODE_COLOR_TO_DEPTH;
|
||||
bool colorToDepth = gstate_c.renderMode == RasterMode::RASTER_MODE_COLOR_TO_DEPTH;
|
||||
|
||||
// Note how we here recompute some of the work already done in state mapping.
|
||||
// Not ideal! At least we share the code.
|
||||
|
||||
@@ -94,7 +94,7 @@ void GenerateStencilFs(char *buffer, const ShaderLanguageDesc &lang, const Draw:
|
||||
|
||||
writer.C("float roundAndScaleTo255f(in float x) { return floor(x * 255.99); }\n");
|
||||
|
||||
writer.BeginFSMain(uniforms, varyings);
|
||||
writer.BeginFSMain(uniforms, varyings, FSFLAG_NONE);
|
||||
|
||||
writer.C(" vec4 index = ").SampleTexture2D("tex", "v_texcoord.xy").C(";\n");
|
||||
writer.C(" vec4 outColor = index.aaaa;\n"); // Only care about a.
|
||||
@@ -106,7 +106,7 @@ void GenerateStencilFs(char *buffer, const ShaderLanguageDesc &lang, const Draw:
|
||||
writer.C(" gl_FragDepth = gl_FragCoord.z;\n");
|
||||
}
|
||||
|
||||
writer.EndFSMain("outColor");
|
||||
writer.EndFSMain("outColor", FSFLAG_NONE);
|
||||
}
|
||||
|
||||
// This can probably be shared with some other shaders, like reinterpret or the future depth upload.
|
||||
|
||||
@@ -265,7 +265,7 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac
|
||||
}
|
||||
}
|
||||
|
||||
if (gstate_c.renderMode == FB_MODE_COLOR_TO_DEPTH) {
|
||||
if (gstate_c.renderMode == RASTER_MODE_COLOR_TO_DEPTH) {
|
||||
forceFiltering = TEX_FILTER_FORCE_NEAREST;
|
||||
}
|
||||
|
||||
@@ -625,8 +625,8 @@ std::vector<AttachCandidate> TextureCacheCommon::GetFramebufferCandidates(const
|
||||
|
||||
std::vector<AttachCandidate> candidates;
|
||||
|
||||
FramebufferNotificationChannel channel = Memory::IsDepthTexVRAMAddress(entry.addr) ? FramebufferNotificationChannel::NOTIFY_FB_DEPTH : FramebufferNotificationChannel::NOTIFY_FB_COLOR;
|
||||
if (channel == FramebufferNotificationChannel::NOTIFY_FB_DEPTH && !gstate_c.Supports(GPU_SUPPORTS_DEPTH_TEXTURE)) {
|
||||
RasterChannel channel = Memory::IsDepthTexVRAMAddress(entry.addr) ? RasterChannel::RASTER_DEPTH : RasterChannel::RASTER_COLOR;
|
||||
if (channel == RasterChannel::RASTER_DEPTH && !gstate_c.Supports(GPU_SUPPORTS_DEPTH_TEXTURE)) {
|
||||
// Depth texture not supported. Don't try to match it, fall back to the memory behind..
|
||||
return std::vector<AttachCandidate>();
|
||||
}
|
||||
@@ -645,7 +645,7 @@ std::vector<AttachCandidate> TextureCacheCommon::GetFramebufferCandidates(const
|
||||
}
|
||||
|
||||
if (candidates.size() > 1) {
|
||||
bool depth = channel == FramebufferNotificationChannel::NOTIFY_FB_DEPTH;
|
||||
bool depth = channel == RasterChannel::RASTER_DEPTH;
|
||||
|
||||
std::string cands;
|
||||
for (auto &candidate : candidates) {
|
||||
@@ -687,7 +687,7 @@ int TextureCacheCommon::GetBestCandidateIndex(const std::vector<AttachCandidate>
|
||||
}
|
||||
|
||||
// Bonus point for matching stride.
|
||||
if (candidate.channel == NOTIFY_FB_COLOR && candidate.fb->fb_stride == candidate.entry.bufw) {
|
||||
if (candidate.channel == RASTER_COLOR && candidate.fb->fb_stride == candidate.entry.bufw) {
|
||||
relevancy += 100;
|
||||
}
|
||||
|
||||
@@ -696,9 +696,9 @@ int TextureCacheCommon::GetBestCandidateIndex(const std::vector<AttachCandidate>
|
||||
relevancy += 10;
|
||||
}
|
||||
|
||||
if (candidate.channel == NOTIFY_FB_COLOR && candidate.fb->last_frame_render == gpuStats.numFlips) {
|
||||
if (candidate.channel == RASTER_COLOR && candidate.fb->last_frame_render == gpuStats.numFlips) {
|
||||
relevancy += 5;
|
||||
} else if (candidate.channel == NOTIFY_FB_DEPTH && candidate.fb->last_frame_depth_render == gpuStats.numFlips) {
|
||||
} else if (candidate.channel == RASTER_DEPTH && candidate.fb->last_frame_depth_render == gpuStats.numFlips) {
|
||||
relevancy += 5;
|
||||
}
|
||||
|
||||
@@ -878,10 +878,10 @@ void TextureCacheCommon::NotifyFramebuffer(VirtualFramebuffer *framebuffer, Fram
|
||||
|
||||
FramebufferMatchInfo TextureCacheCommon::MatchFramebuffer(
|
||||
const TextureDefinition &entry,
|
||||
VirtualFramebuffer *framebuffer, u32 texaddrOffset, FramebufferNotificationChannel channel) const {
|
||||
VirtualFramebuffer *framebuffer, u32 texaddrOffset, RasterChannel channel) const {
|
||||
static const u32 MAX_SUBAREA_Y_OFFSET_SAFE = 32;
|
||||
|
||||
uint32_t fb_address = channel == NOTIFY_FB_DEPTH ? framebuffer->z_address : framebuffer->fb_address;
|
||||
uint32_t fb_address = channel == RASTER_DEPTH ? framebuffer->z_address : framebuffer->fb_address;
|
||||
|
||||
u32 addr = fb_address & 0x3FFFFFFF;
|
||||
u32 texaddr = entry.addr + texaddrOffset;
|
||||
@@ -906,14 +906,14 @@ FramebufferMatchInfo TextureCacheCommon::MatchFramebuffer(
|
||||
case 0x00000000:
|
||||
case 0x00400000:
|
||||
// Don't match the depth channel with these addresses when texturing.
|
||||
if (channel == FramebufferNotificationChannel::NOTIFY_FB_DEPTH) {
|
||||
if (channel == RasterChannel::RASTER_DEPTH) {
|
||||
return FramebufferMatchInfo{ FramebufferMatch::NO_MATCH };
|
||||
}
|
||||
break;
|
||||
case 0x00200000:
|
||||
case 0x00600000:
|
||||
// Don't match the color channel with these addresses when texturing.
|
||||
if (channel == FramebufferNotificationChannel::NOTIFY_FB_COLOR) {
|
||||
if (channel == RasterChannel::RASTER_COLOR) {
|
||||
return FramebufferMatchInfo{ FramebufferMatch::NO_MATCH };
|
||||
}
|
||||
break;
|
||||
@@ -924,7 +924,7 @@ FramebufferMatchInfo TextureCacheCommon::MatchFramebuffer(
|
||||
}
|
||||
|
||||
const bool noOffset = texaddr == addr;
|
||||
const bool exactMatch = noOffset && entry.format < 4 && channel == NOTIFY_FB_COLOR;
|
||||
const bool exactMatch = noOffset && entry.format < 4 && channel == RASTER_COLOR;
|
||||
const u32 w = 1 << ((entry.dim >> 0) & 0xf);
|
||||
const u32 h = 1 << ((entry.dim >> 8) & 0xf);
|
||||
// 512 on a 272 framebuffer is sane, so let's be lenient.
|
||||
@@ -958,9 +958,9 @@ FramebufferMatchInfo TextureCacheCommon::MatchFramebuffer(
|
||||
|
||||
// Check works for D16 too (???)
|
||||
const bool matchingClutFormat =
|
||||
(channel != NOTIFY_FB_COLOR && entry.format == GE_TFMT_CLUT16) ||
|
||||
(channel == NOTIFY_FB_COLOR && framebuffer->format == GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT32) ||
|
||||
(channel == NOTIFY_FB_COLOR && framebuffer->format != GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT16);
|
||||
(channel != RASTER_COLOR && entry.format == GE_TFMT_CLUT16) ||
|
||||
(channel == RASTER_COLOR && framebuffer->format == GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT32) ||
|
||||
(channel == RASTER_COLOR && framebuffer->format != GE_FORMAT_8888 && entry.format == GE_TFMT_CLUT16);
|
||||
|
||||
// To avoid ruining git blame, kept the same name as the old struct.
|
||||
FramebufferMatchInfo fbInfo{ FramebufferMatch::VALID };
|
||||
@@ -1782,7 +1782,7 @@ void TextureCacheCommon::ApplyTexture() {
|
||||
if (nextFramebufferTexture_) {
|
||||
bool depth = Memory::IsDepthTexVRAMAddress(gstate.getTextureAddress(0));
|
||||
// ApplyTextureFrameBuffer is responsible for setting SetTextureFullAlpha.
|
||||
ApplyTextureFramebuffer(nextFramebufferTexture_, gstate.getTextureFormat(), depth ? NOTIFY_FB_DEPTH : NOTIFY_FB_COLOR);
|
||||
ApplyTextureFramebuffer(nextFramebufferTexture_, gstate.getTextureFormat(), depth ? RASTER_DEPTH : RASTER_COLOR);
|
||||
nextFramebufferTexture_ = nullptr;
|
||||
}
|
||||
|
||||
@@ -1845,12 +1845,12 @@ void TextureCacheCommon::ApplyTexture() {
|
||||
gstate_c.SetTextureIs3D((entry->status & TexCacheEntry::STATUS_3D) != 0);
|
||||
}
|
||||
|
||||
void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, GETextureFormat texFormat, FramebufferNotificationChannel channel) {
|
||||
void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, GETextureFormat texFormat, RasterChannel channel) {
|
||||
DepalShader *depalShader = nullptr;
|
||||
uint32_t clutMode = gstate.clutformat & 0xFFFFFF;
|
||||
|
||||
bool need_depalettize = IsClutFormat(texFormat);
|
||||
bool depth = channel == NOTIFY_FB_DEPTH;
|
||||
bool depth = channel == RASTER_DEPTH;
|
||||
bool useShaderDepal = framebufferManager_->GetCurrentRenderVFB() != framebuffer && !depth && !gstate_c.curTextureIs3D;
|
||||
|
||||
// TODO: Implement shader depal in the fragment shader generator for D3D11 at least.
|
||||
@@ -2262,7 +2262,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt
|
||||
}
|
||||
|
||||
// Don't upscale textures in color-to-depth mode.
|
||||
if (gstate_c.renderMode == FB_MODE_COLOR_TO_DEPTH) {
|
||||
if (gstate_c.renderMode == RASTER_MODE_COLOR_TO_DEPTH) {
|
||||
plan.scaleFactor = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Core/TextureReplacer.h"
|
||||
#include "Core/System.h"
|
||||
#include "GPU/GPU.h"
|
||||
#include "GPU/Common/GPUDebugInterface.h"
|
||||
#include "GPU/Common/TextureDecoder.h"
|
||||
#include "GPU/Common/TextureScalerCommon.h"
|
||||
@@ -36,11 +37,6 @@ enum FramebufferNotification {
|
||||
NOTIFY_FB_DESTROYED,
|
||||
};
|
||||
|
||||
enum FramebufferNotificationChannel {
|
||||
NOTIFY_FB_COLOR = 0,
|
||||
NOTIFY_FB_DEPTH = 1,
|
||||
};
|
||||
|
||||
// Changes more frequent than this will be considered "frequent" and prevent texture scaling.
|
||||
#define TEXCACHE_FRAME_CHANGE_FREQUENT 6
|
||||
// Note: only used when hash backoff is disabled.
|
||||
@@ -229,7 +225,7 @@ struct AttachCandidate {
|
||||
FramebufferMatchInfo match;
|
||||
TextureDefinition entry;
|
||||
VirtualFramebuffer *fb;
|
||||
FramebufferNotificationChannel channel;
|
||||
RasterChannel channel;
|
||||
|
||||
std::string ToString();
|
||||
};
|
||||
@@ -336,7 +332,7 @@ protected:
|
||||
void DeleteTexture(TexCache::iterator it);
|
||||
void Decimate(bool forcePressure = false);
|
||||
|
||||
void ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, GETextureFormat texFormat, FramebufferNotificationChannel channel);
|
||||
void ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, GETextureFormat texFormat, RasterChannel channel);
|
||||
|
||||
void HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete);
|
||||
virtual void BuildTexture(TexCacheEntry *const entry) = 0;
|
||||
@@ -369,7 +365,7 @@ protected:
|
||||
SamplerCacheKey GetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight);
|
||||
void UpdateMaxSeenV(TexCacheEntry *entry, bool throughMode);
|
||||
|
||||
FramebufferMatchInfo MatchFramebuffer(const TextureDefinition &entry, VirtualFramebuffer *framebuffer, u32 texaddrOffset, FramebufferNotificationChannel channel) const;
|
||||
FramebufferMatchInfo MatchFramebuffer(const TextureDefinition &entry, VirtualFramebuffer *framebuffer, u32 texaddrOffset, RasterChannel channel) const;
|
||||
|
||||
std::vector<AttachCandidate> GetFramebufferCandidates(const TextureDefinition &entry, u32 texAddrOffset);
|
||||
int GetBestCandidateIndex(const std::vector<AttachCandidate> &candidates);
|
||||
|
||||
@@ -293,7 +293,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
if (gstate_c.renderMode == FB_MODE_COLOR_TO_DEPTH) {
|
||||
if (gstate_c.renderMode == RASTER_MODE_COLOR_TO_DEPTH) {
|
||||
// Enforce plain depth writing.
|
||||
keys_.depthStencil.value = 0;
|
||||
keys_.depthStencil.depthTestEnable = true;
|
||||
|
||||
@@ -214,7 +214,7 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
|
||||
|
||||
// Set Stencil/Depth
|
||||
|
||||
if (gstate_c.renderMode == FB_MODE_COLOR_TO_DEPTH) {
|
||||
if (gstate_c.renderMode == RASTER_MODE_COLOR_TO_DEPTH) {
|
||||
// Enforce plain depth writing.
|
||||
dxstate.depthTest.enable();
|
||||
dxstate.depthFunc.set(D3DCMP_ALWAYS);
|
||||
|
||||
@@ -251,7 +251,7 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
if (gstate_c.renderMode == FB_MODE_COLOR_TO_DEPTH) {
|
||||
if (gstate_c.renderMode == RASTER_MODE_COLOR_TO_DEPTH) {
|
||||
// Enforce plain depth writing.
|
||||
renderManager->SetStencilDisabled();
|
||||
renderManager->SetDepth(true, true, GL_ALWAYS);
|
||||
|
||||
@@ -24,9 +24,17 @@ class GPUInterface;
|
||||
class GPUDebugInterface;
|
||||
class GraphicsContext;
|
||||
|
||||
enum FramebufferRenderMode {
|
||||
FB_MODE_NORMAL = 0,
|
||||
FB_MODE_COLOR_TO_DEPTH = 1,
|
||||
enum RasterMode {
|
||||
RASTER_MODE_NORMAL = 0,
|
||||
RASTER_MODE_COLOR_TO_DEPTH = 1,
|
||||
};
|
||||
|
||||
// PSP rasterization has two outputs, color and depth. Stencil is packed
|
||||
// into the alpha channel of color (if exists), so possibly RASTER_COLOR
|
||||
// should be named RASTER_COLOR_STENCIL but it gets kinda hard to read.
|
||||
enum RasterChannel {
|
||||
RASTER_COLOR = 0,
|
||||
RASTER_DEPTH = 1,
|
||||
};
|
||||
|
||||
enum SkipDrawReasonFlags {
|
||||
|
||||
+2
-2
@@ -555,7 +555,7 @@ struct GPUStateCache {
|
||||
Dirty(DIRTY_FRAGMENTSHADER_STATE | (is3D ? DIRTY_MIPBIAS : 0));
|
||||
}
|
||||
}
|
||||
void SetFramebufferRenderMode(FramebufferRenderMode mode) {
|
||||
void SetFramebufferRenderMode(RasterMode mode) {
|
||||
if (mode != renderMode) {
|
||||
// This mode modifies the fragment shader to write depth, the depth state to write without testing, and the blend state to write nothing to color.
|
||||
// So we need to re-evaluate those states.
|
||||
@@ -614,7 +614,7 @@ struct GPUStateCache {
|
||||
bool blueToAlpha;
|
||||
|
||||
// Some games try to write to the Z buffer using color. Catch that and actually do the writes to the Z buffer instead.
|
||||
FramebufferRenderMode renderMode;
|
||||
RasterMode renderMode;
|
||||
|
||||
// TODO: These should be accessed from the current VFB object directly.
|
||||
u32 curRTWidth;
|
||||
|
||||
@@ -250,7 +250,7 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
|
||||
GenericStencilFuncState stencilState;
|
||||
ConvertStencilFuncState(stencilState);
|
||||
|
||||
if (gstate_c.renderMode == FB_MODE_COLOR_TO_DEPTH) {
|
||||
if (gstate_c.renderMode == RASTER_MODE_COLOR_TO_DEPTH) {
|
||||
// Enforce plain depth writing.
|
||||
key.depthTestEnable = true;
|
||||
key.depthWriteEnable = true;
|
||||
|
||||
Reference in new issue
Block a user