mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-01 14:58:14 +00:00
Enable framebuffer depth blits through raster. Fixes games like Jeanne D'Arc on D3D9.
This commit is contained in:
1 parent
131098c4d4
commit
252550fbd2
8 files changed
+140
-49
No files matched your search
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+42
-13
@@ -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,21 +69,24 @@ 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");
|
||||
draw2DFsDepth_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs");
|
||||
draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs");
|
||||
|
||||
_assert_(draw2DFs_ && draw2DVs_);
|
||||
_assert_(draw2DFs_ && draw2DVs_ && draw2DFsDepth_);
|
||||
|
||||
InputLayoutDesc desc = {
|
||||
{
|
||||
@@ -88,24 +100,41 @@ 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,
|
||||
};
|
||||
draw2DPipelineDepth_ = draw_->CreateGraphicsPipeline(draw2DDepthPipelineDesc);
|
||||
_assert_(draw2DPipelineDepth_);
|
||||
|
||||
delete[] fsCode;
|
||||
delete[] vsCode;
|
||||
|
||||
rasterNoCull->Release();
|
||||
blendOff->Release();
|
||||
blendDiscard->Release();
|
||||
noDepthStencil->Release();
|
||||
depthWriteAlways->Release();
|
||||
inputLayout->Release();
|
||||
|
||||
SamplerStateDesc descLinear{};
|
||||
@@ -125,7 +154,7 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver
|
||||
draw2DSamplerNearest_ = draw_->CreateSamplerState(descNearest);
|
||||
}
|
||||
|
||||
draw_->BindPipeline(draw2DPipelineLinear_);
|
||||
draw_->BindPipeline(channel == RASTER_COLOR ? draw2DPipelineColor_ : draw2DPipelineDepth_);
|
||||
if (tex) {
|
||||
draw_->BindTextures(TEX_SLOT_PSP_TEXTURE, 1, &tex);
|
||||
}
|
||||
|
||||
@@ -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,14 @@ 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;
|
||||
|
||||
// Attempt at optimization - if destination already bound, draw depth using raster
|
||||
if (true || currentRenderVfb_ == dst) {
|
||||
useCopy = false;
|
||||
useBlit = false;
|
||||
}
|
||||
|
||||
int w = std::min(src->renderWidth, dst->renderWidth);
|
||||
int h = std::min(src->renderHeight, dst->renderHeight);
|
||||
@@ -587,14 +596,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 {
|
||||
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 +2510,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 +2574,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 +2658,35 @@ 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) {
|
||||
|
||||
int destW, destH, srcW, srcH;
|
||||
draw_->GetFramebufferDimensions(src, &srcW, &srcH);
|
||||
@@ -2678,17 +2703,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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in new issue
Block a user