mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #15891 from hrydgard/more-draw2d-refactor
Use Draw2D for reinterpret and (partially) for depal
This commit is contained in:
commit
9db9574f0d
26 changed files with 218 additions and 306 deletions
|
@ -94,6 +94,9 @@ public:
|
|||
void EndVSMain(Slice<VaryingDef> varyings);
|
||||
void EndFSMain(const char *vec4_color_variable, FSFlags flags);
|
||||
|
||||
const ShaderLanguageDesc &Lang() const {
|
||||
return lang_;
|
||||
}
|
||||
|
||||
void Rewind(size_t offset) {
|
||||
p_ -= offset;
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include "GPU/Common/GPUStateUtils.h"
|
||||
#include "GPU/Common/DepalettizeShaderCommon.h"
|
||||
|
||||
#define WRITE p+=sprintf
|
||||
|
||||
static const InputDef vsInputs[2] = {
|
||||
{ "vec2", "a_position", Draw::SEM_POSITION, },
|
||||
{ "vec2", "a_texcoord0", Draw::SEM_TEXCOORD0, },
|
||||
|
@ -323,8 +321,7 @@ void GenerateDepalSmoothed(ShaderWriter &writer, const DepalConfig &config) {
|
|||
writer.C(" vec4 outColor = ").SampleTexture2D("pal", "vec2(coord, 0.0)").C(";\n");
|
||||
}
|
||||
|
||||
void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLanguageDesc &lang) {
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment);
|
||||
void GenerateDepalFs(ShaderWriter &writer, const DepalConfig &config) {
|
||||
writer.DeclareSamplers(samplers);
|
||||
writer.HighPrecisionFloat();
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings, FSFLAG_NONE);
|
||||
|
@ -333,7 +330,7 @@ void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLangua
|
|||
// need two variants.
|
||||
GenerateDepalSmoothed(writer, config);
|
||||
} else {
|
||||
switch (lang.shaderLanguage) {
|
||||
switch (writer.Lang().shaderLanguage) {
|
||||
case HLSL_D3D9:
|
||||
case GLSL_1xx:
|
||||
GenerateDepalShaderFloat(writer, config);
|
||||
|
@ -344,18 +341,8 @@ void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLangua
|
|||
GenerateDepalShader300(writer, config);
|
||||
break;
|
||||
default:
|
||||
_assert_msg_(false, "Depal shader language not supported: %d", (int)lang.shaderLanguage);
|
||||
_assert_msg_(false, "Shader language not supported for depal: %d", (int)writer.Lang().shaderLanguage);
|
||||
}
|
||||
}
|
||||
writer.EndFSMain("outColor", FSFLAG_NONE);
|
||||
}
|
||||
|
||||
void GenerateVs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Vertex, nullptr, 0);
|
||||
writer.BeginVSMain(vsInputs, Slice<UniformDef>::empty(), varyings);
|
||||
writer.C(" v_texcoord = a_texcoord0;\n");
|
||||
writer.C(" gl_Position = vec4(a_position, 0.0, 1.0);\n");
|
||||
writer.EndVSMain(varyings);
|
||||
}
|
||||
|
||||
#undef WRITE
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "Common/GPU/Shader.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
|
||||
class ShaderWriter;
|
||||
|
||||
static const int DEPAL_TEXTURE_OLD_AGE = 120;
|
||||
|
||||
struct DepalConfig {
|
||||
|
@ -34,5 +36,4 @@ struct DepalConfig {
|
|||
bool smoothedDepal;
|
||||
};
|
||||
|
||||
void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLanguageDesc &lang);
|
||||
void GenerateVs(char *buffer, const ShaderLanguageDesc &lang);
|
||||
void GenerateDepalFs(ShaderWriter &writer, const DepalConfig &config);
|
||||
|
|
|
@ -57,26 +57,32 @@ const UniformBufferDesc draw2DUBDesc{ sizeof(Draw2DUB), {
|
|||
} };
|
||||
|
||||
|
||||
RasterChannel GenerateDraw2DFs(ShaderWriter &writer) {
|
||||
Draw2DPipelineInfo GenerateDraw2DCopyColorFs(ShaderWriter &writer) {
|
||||
writer.DeclareSamplers(samplers);
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings, FSFLAG_NONE);
|
||||
writer.C(" vec4 outColor = ").SampleTexture2D("tex", "v_texcoord.xy").C(";\n");
|
||||
writer.EndFSMain("outColor", FSFLAG_NONE);
|
||||
|
||||
return RASTER_COLOR;
|
||||
return Draw2DPipelineInfo{
|
||||
RASTER_COLOR,
|
||||
RASTER_COLOR,
|
||||
};
|
||||
}
|
||||
|
||||
RasterChannel GenerateDraw2DDepthFs(ShaderWriter &writer) {
|
||||
Draw2DPipelineInfo GenerateDraw2DCopyDepthFs(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");
|
||||
writer.C(" gl_FragDepth = ").SampleTexture2D("tex", "v_texcoord.xy").C(".x;\n");
|
||||
writer.EndFSMain("outColor", FSFLAG_WRITEDEPTH);
|
||||
|
||||
return RASTER_DEPTH;
|
||||
return Draw2DPipelineInfo{
|
||||
RASTER_DEPTH,
|
||||
RASTER_DEPTH,
|
||||
};
|
||||
}
|
||||
|
||||
RasterChannel GenerateDraw2D565ToDepthFs(ShaderWriter &writer) {
|
||||
Draw2DPipelineInfo 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");
|
||||
|
@ -88,10 +94,13 @@ RasterChannel GenerateDraw2D565ToDepthFs(ShaderWriter &writer) {
|
|||
writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.scale, factors.offset);
|
||||
writer.EndFSMain("outColor", FSFLAG_WRITEDEPTH);
|
||||
|
||||
return RASTER_DEPTH;
|
||||
return Draw2DPipelineInfo{
|
||||
RASTER_COLOR,
|
||||
RASTER_DEPTH,
|
||||
};
|
||||
}
|
||||
|
||||
RasterChannel GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) {
|
||||
Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) {
|
||||
writer.DeclareSamplers(samplers);
|
||||
writer.BeginFSMain(uniforms, varyings, FSFLAG_WRITEDEPTH);
|
||||
writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n");
|
||||
|
@ -108,7 +117,11 @@ RasterChannel GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) {
|
|||
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;
|
||||
|
||||
return Draw2DPipelineInfo{
|
||||
RASTER_COLOR,
|
||||
RASTER_DEPTH
|
||||
};
|
||||
}
|
||||
|
||||
void GenerateDraw2DVS(ShaderWriter &writer) {
|
||||
|
@ -120,7 +133,24 @@ void GenerateDraw2DVS(ShaderWriter &writer) {
|
|||
writer.EndVSMain(varyings);
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::Ensure2DResources() {
|
||||
template <typename T>
|
||||
static void DoRelease(T *&obj) {
|
||||
if (obj)
|
||||
obj->Release();
|
||||
obj = nullptr;
|
||||
}
|
||||
|
||||
void Draw2D::DeviceLost() {
|
||||
DoRelease(draw2DVs_);
|
||||
DoRelease(draw2DSamplerLinear_);
|
||||
DoRelease(draw2DSamplerNearest_);
|
||||
}
|
||||
|
||||
void Draw2D::DeviceRestore(Draw::DrawContext *draw) {
|
||||
|
||||
}
|
||||
|
||||
void Draw2D::Ensure2DResources() {
|
||||
using namespace Draw;
|
||||
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
|
@ -155,7 +185,7 @@ void FramebufferManagerCommon::Ensure2DResources() {
|
|||
}
|
||||
}
|
||||
|
||||
Draw::Pipeline *FramebufferManagerCommon::Create2DPipeline(std::function<RasterChannel (ShaderWriter &)> generate) {
|
||||
Draw2DPipeline *Draw2D::Create2DPipeline(std::function<Draw2DPipelineInfo (ShaderWriter &)> generate) {
|
||||
Ensure2DResources();
|
||||
|
||||
using namespace Draw;
|
||||
|
@ -163,10 +193,9 @@ Draw::Pipeline *FramebufferManagerCommon::Create2DPipeline(std::function<RasterC
|
|||
|
||||
char *fsCode = new char[4000];
|
||||
ShaderWriter writer(fsCode, shaderLanguageDesc, ShaderStage::Fragment);
|
||||
RasterChannel channel = generate(writer);
|
||||
Draw2DPipelineInfo info = generate(writer);
|
||||
|
||||
ShaderModule *fs = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs");
|
||||
delete[] fsCode;
|
||||
|
||||
_assert_(fs);
|
||||
|
||||
|
@ -182,10 +211,10 @@ Draw::Pipeline *FramebufferManagerCommon::Create2DPipeline(std::function<RasterC
|
|||
};
|
||||
InputLayout *inputLayout = draw_->CreateInputLayout(desc);
|
||||
|
||||
BlendState *blend = draw_->CreateBlendState({ false, channel == RASTER_COLOR ? 0xF : 0 });
|
||||
BlendState *blend = draw_->CreateBlendState({ false, info.writeChannel == RASTER_COLOR ? 0xF : 0 });
|
||||
|
||||
DepthStencilStateDesc dsDesc{};
|
||||
if (channel == RASTER_DEPTH) {
|
||||
if (info.writeChannel == RASTER_DEPTH) {
|
||||
dsDesc.depthTestEnabled = true;
|
||||
dsDesc.depthWriteEnabled = true;
|
||||
dsDesc.depthCompare = Draw::Comparison::ALWAYS;
|
||||
|
@ -211,19 +240,32 @@ Draw::Pipeline *FramebufferManagerCommon::Create2DPipeline(std::function<RasterC
|
|||
depthStencil->Release();
|
||||
inputLayout->Release();
|
||||
|
||||
return pipeline;
|
||||
return new Draw2DPipeline {
|
||||
pipeline,
|
||||
info,
|
||||
fsCode,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, Draw::Pipeline *pipeline, float texW, float texH) {
|
||||
void Draw2D::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, Draw2DPipeline *pipeline, float texW, float texH, int scaleFactor) {
|
||||
using namespace Draw;
|
||||
|
||||
_dbg_assert_(pipeline);
|
||||
|
||||
if (pipeline->info.writeChannel == RASTER_DEPTH) {
|
||||
_dbg_assert_(draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported);
|
||||
|
||||
// We don't filter inputs when writing depth, results will be bad.
|
||||
linearFilter = false;
|
||||
}
|
||||
|
||||
Draw2DUB ub;
|
||||
ub.texSizeX = tex ? tex->Width() : texW;
|
||||
ub.texSizeY = tex ? tex->Height() : texH;
|
||||
ub.scaleFactor = (float)renderScaleFactor_;
|
||||
ub.scaleFactor = (float)scaleFactor;
|
||||
|
||||
draw_->BindPipeline(pipeline);
|
||||
draw_->BindPipeline(pipeline->pipeline);
|
||||
draw_->UpdateDynamicUniformBuffer(&ub, sizeof(ub));
|
||||
|
||||
if (tex) {
|
||||
|
@ -237,17 +279,17 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver
|
|||
gstate_c.Dirty(DIRTY_FRAGMENTSHADER_STATE | DIRTY_VERTEXSHADER_STATE);
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, Draw2DShader shader, float texW, float texH) {
|
||||
Draw2DPipeline *FramebufferManagerCommon::Get2DPipeline(Draw2DShader shader) {
|
||||
using namespace Draw;
|
||||
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
|
||||
Draw::Pipeline *pipeline = nullptr;
|
||||
Draw2DPipeline *pipeline = nullptr;
|
||||
|
||||
switch (shader) {
|
||||
case DRAW2D_COPY_COLOR:
|
||||
if (!draw2DPipelineColor_) {
|
||||
draw2DPipelineColor_ = Create2DPipeline(&GenerateDraw2DFs);
|
||||
draw2DPipelineColor_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyColorFs);
|
||||
}
|
||||
pipeline = draw2DPipelineColor_;
|
||||
break;
|
||||
|
@ -255,41 +297,36 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver
|
|||
case DRAW2D_COPY_DEPTH:
|
||||
if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
|
||||
// Can't do it
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
if (!draw2DPipelineDepth_) {
|
||||
draw2DPipelineDepth_ = Create2DPipeline(&GenerateDraw2DDepthFs);
|
||||
draw2DPipelineDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyDepthFs);
|
||||
}
|
||||
linearFilter = false;
|
||||
pipeline = draw2DPipelineDepth_;
|
||||
break;
|
||||
|
||||
case DRAW2D_565_TO_DEPTH:
|
||||
if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
|
||||
// Can't do it
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
if (!draw2DPipeline565ToDepth_) {
|
||||
draw2DPipeline565ToDepth_ = Create2DPipeline(&GenerateDraw2D565ToDepthFs);
|
||||
draw2DPipeline565ToDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2D565ToDepthFs);
|
||||
}
|
||||
linearFilter = false;
|
||||
pipeline = draw2DPipeline565ToDepth_;
|
||||
break;
|
||||
|
||||
case DRAW2D_565_TO_DEPTH_DESWIZZLE:
|
||||
if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
|
||||
// Can't do it
|
||||
return;
|
||||
return nullptr;
|
||||
}
|
||||
if (!draw2DPipeline565ToDepthDeswizzle_) {
|
||||
draw2DPipeline565ToDepthDeswizzle_ = Create2DPipeline(&GenerateDraw2D565ToDepthDeswizzleFs);
|
||||
draw2DPipeline565ToDepthDeswizzle_ = draw2D_.Create2DPipeline(&GenerateDraw2D565ToDepthDeswizzleFs);
|
||||
}
|
||||
linearFilter = false;
|
||||
pipeline = draw2DPipeline565ToDepthDeswizzle_;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pipeline) {
|
||||
DrawStrip2D(tex, verts, vertexCount, linearFilter, pipeline, texW, texH);
|
||||
}
|
||||
return pipeline;
|
||||
}
|
||||
|
|
|
@ -28,3 +28,41 @@ inline RasterChannel Draw2DSourceChannel(Draw2DShader shader) {
|
|||
return RASTER_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
struct Draw2DPipelineInfo {
|
||||
RasterChannel readChannel;
|
||||
RasterChannel writeChannel;
|
||||
bool secondTexture;
|
||||
};
|
||||
|
||||
struct Draw2DPipeline {
|
||||
Draw::Pipeline *pipeline;
|
||||
Draw2DPipelineInfo info;
|
||||
char *code;
|
||||
void Release() {
|
||||
pipeline->Release();
|
||||
delete[] code;
|
||||
delete this;
|
||||
}
|
||||
};
|
||||
|
||||
class ShaderWriter;
|
||||
|
||||
class Draw2D {
|
||||
public:
|
||||
Draw2D(Draw::DrawContext *draw) : draw_(draw) {}
|
||||
void DeviceLost();
|
||||
void DeviceRestore(Draw::DrawContext *draw);
|
||||
|
||||
Draw2DPipeline *Create2DPipeline(std::function<Draw2DPipelineInfo(ShaderWriter &)> generate);
|
||||
|
||||
void DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, Draw2DPipeline *pipeline, float texW = 0.0f, float texH = 0.0f, int scaleFactor = 0);
|
||||
void Ensure2DResources();
|
||||
|
||||
private:
|
||||
Draw::DrawContext *draw_;
|
||||
|
||||
Draw::SamplerState *draw2DSamplerLinear_ = nullptr;
|
||||
Draw::SamplerState *draw2DSamplerNearest_ = nullptr;
|
||||
Draw::ShaderModule *draw2DVs_ = nullptr;
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include "GPU/GPUState.h"
|
||||
|
||||
FramebufferManagerCommon::FramebufferManagerCommon(Draw::DrawContext *draw)
|
||||
: draw_(draw) {
|
||||
: draw_(draw), draw2D_(draw_) {
|
||||
presentation_ = new PresentationCommon(draw);
|
||||
}
|
||||
|
||||
|
@ -573,7 +573,7 @@ void FramebufferManagerCommon::CopyToDepthFromOverlappingFramebuffers(VirtualFra
|
|||
BlitUsingRaster(
|
||||
src->fbo, 0.0f, 0.0f, src->renderWidth, src->renderHeight,
|
||||
dest->fbo, 0.0f, 0.0f, src->renderWidth, src->renderHeight,
|
||||
false, shader, "565_to_depth");
|
||||
false, Get2DPipeline(shader), "565_to_depth");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -656,7 +656,7 @@ void FramebufferManagerCommon::CopyToColorFromOverlappingFramebuffers(VirtualFra
|
|||
int dstY2 = dstY1 + dstHeight;
|
||||
|
||||
BlitUsingRaster(src->fbo, 0.0f, 0.0f, srcWidth, srcHeight,
|
||||
dst->fbo, dstX1, dstY1, dstX2, dstY2, false, DRAW2D_COPY_COLOR, "copy_color");
|
||||
dst->fbo, dstX1, dstY1, dstX2, dstY2, false, Get2DPipeline(DRAW2D_COPY_COLOR), "copy_color");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -731,7 +731,7 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir
|
|||
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, Draw2DShader::DRAW2D_COPY_DEPTH, "BlitDepthRaster");
|
||||
BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, Get2DPipeline(Draw2DShader::DRAW2D_COPY_DEPTH), "BlitDepthRaster");
|
||||
}
|
||||
|
||||
draw_->InvalidateCachedState();
|
||||
|
@ -2422,24 +2422,21 @@ void FramebufferManagerCommon::DeviceLost() {
|
|||
DoRelease(reinterpretFromTo_[i][j]);
|
||||
}
|
||||
}
|
||||
DoRelease(reinterpretVBuf_);
|
||||
DoRelease(reinterpretSampler_);
|
||||
DoRelease(reinterpretVS_);
|
||||
DoRelease(stencilUploadSampler_);
|
||||
DoRelease(stencilUploadPipeline_);
|
||||
DoRelease(draw2DSamplerNearest_);
|
||||
DoRelease(draw2DSamplerLinear_);
|
||||
DoRelease(draw2DVs_);
|
||||
DoRelease(draw2DPipelineColor_);
|
||||
DoRelease(draw2DPipelineDepth_);
|
||||
DoRelease(draw2DPipeline565ToDepth_);
|
||||
DoRelease(draw2DPipeline565ToDepthDeswizzle_);
|
||||
|
||||
draw2D_.DeviceLost();
|
||||
|
||||
draw_ = nullptr;
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::DeviceRestore(Draw::DrawContext *draw) {
|
||||
draw_ = draw;
|
||||
draw2D_.DeviceRestore(draw_);
|
||||
presentation_->DeviceRestore(draw);
|
||||
}
|
||||
|
||||
|
@ -2491,7 +2488,7 @@ 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, DRAW2D_COPY_COLOR);
|
||||
draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline(DRAW2D_COPY_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);
|
||||
}
|
||||
|
@ -2587,14 +2584,14 @@ 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 {
|
||||
Draw2DShader shader = channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_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);
|
||||
BlitUsingRaster(src->fbo, srcX1, srcY1, srcX2, srcY2, tempFBO, dstX1, dstY1, dstX2, dstY2, false, shader, tag);
|
||||
BlitUsingRaster(src->fbo, srcX1, srcY1, srcX2, srcY2, tempFBO, dstX1, dstY1, dstX2, dstY2, false, pipeline, tag);
|
||||
srcFBO = tempFBO;
|
||||
}
|
||||
BlitUsingRaster(srcFBO, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, false, shader, tag);
|
||||
BlitUsingRaster(srcFBO, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, false, pipeline, tag);
|
||||
}
|
||||
|
||||
draw_->InvalidateCachedState();
|
||||
|
@ -2607,9 +2604,9 @@ 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,
|
||||
Draw2DShader shader, const char *tag) {
|
||||
Draw2DPipeline *pipeline, const char *tag) {
|
||||
|
||||
if (shader == DRAW2D_COPY_DEPTH || shader == DRAW2D_565_TO_DEPTH) {
|
||||
if (pipeline->info.writeChannel == RASTER_DEPTH) {
|
||||
_dbg_assert_(draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported);
|
||||
}
|
||||
|
||||
|
@ -2632,12 +2629,13 @@ void FramebufferManagerCommon::BlitUsingRaster(
|
|||
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 }, tag ? tag : "BlitUsingRaster");
|
||||
draw_->BindFramebufferAsTexture(src, 0, Draw2DSourceChannel(shader) == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, 0);
|
||||
draw_->BindFramebufferAsTexture(src, 0, pipeline->info.readChannel == 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, shader, src->Width(), src->Height());
|
||||
|
||||
draw2D_.DrawStrip2D(nullptr, vtx, 4, linearFilter, pipeline, src->Width(), src->Height(), renderScaleFactor_);
|
||||
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE);
|
||||
}
|
||||
|
|
|
@ -369,17 +369,17 @@ public:
|
|||
}
|
||||
void ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat);
|
||||
|
||||
Draw2D *GetDraw2D() {
|
||||
return &draw2D_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h);
|
||||
void SetViewport2D(int x, int y, int w, int h);
|
||||
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, Draw2DShader channel, float texW = 0.0f, float texH = 0.0f);
|
||||
void DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, Draw::Pipeline *pipeline, float texW = 0.0f, float texH = 0.0f);
|
||||
|
||||
void Ensure2DResources();
|
||||
Draw::Pipeline *Create2DPipeline(std::function<RasterChannel(ShaderWriter &)> generate);
|
||||
Draw2DPipeline *Get2DPipeline(Draw2DShader shader);
|
||||
|
||||
void CopyToColorFromOverlappingFramebuffers(VirtualFramebuffer *dest);
|
||||
void CopyToDepthFromOverlappingFramebuffers(VirtualFramebuffer *dest);
|
||||
|
@ -394,7 +394,7 @@ protected:
|
|||
|
||||
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, Draw2DShader shader, const char *tag);
|
||||
Draw::Framebuffer *dest, float destX1, float destY1, float destX2, float destY2, bool linearFilter, Draw2DPipeline *pipeline, const char *tag);
|
||||
|
||||
void CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags);
|
||||
|
||||
|
@ -500,10 +500,7 @@ protected:
|
|||
// Thin3D stuff for reinterpreting image data between the various 16-bit formats.
|
||||
// Safe, not optimal - there might be input attachment tricks, etc, but we can't use them
|
||||
// since we don't want N different implementations.
|
||||
Draw::Pipeline *reinterpretFromTo_[3][3]{};
|
||||
Draw::ShaderModule *reinterpretVS_ = nullptr;
|
||||
Draw::SamplerState *reinterpretSampler_ = nullptr;
|
||||
Draw::Buffer *reinterpretVBuf_ = nullptr;
|
||||
Draw2DPipeline *reinterpretFromTo_[3][3]{};
|
||||
|
||||
// Common implementation of stencil buffer upload. Also not 100% optimal, but not performance
|
||||
// critical either.
|
||||
|
@ -511,12 +508,11 @@ protected:
|
|||
Draw::SamplerState *stencilUploadSampler_ = nullptr;
|
||||
|
||||
// Draw2D pipelines
|
||||
Draw::Pipeline *draw2DPipelineColor_ = nullptr;
|
||||
Draw::Pipeline *draw2DPipelineDepth_ = nullptr;
|
||||
Draw::Pipeline *draw2DPipeline565ToDepth_ = nullptr;
|
||||
Draw::Pipeline *draw2DPipeline565ToDepthDeswizzle_ = nullptr;
|
||||
Draw::SamplerState *draw2DSamplerLinear_ = nullptr;
|
||||
Draw::SamplerState *draw2DSamplerNearest_ = nullptr;
|
||||
Draw::ShaderModule *draw2DVs_ = nullptr;
|
||||
Draw2DPipeline *draw2DPipelineColor_ = nullptr;
|
||||
Draw2DPipeline *draw2DPipelineDepth_ = nullptr;
|
||||
Draw2DPipeline *draw2DPipeline565ToDepth_ = nullptr;
|
||||
Draw2DPipeline *draw2DPipeline565ToDepthDeswizzle_ = nullptr;
|
||||
|
||||
Draw2D draw2D_;
|
||||
// The fragment shaders are "owned" by the pipelines since they're 1:1.
|
||||
};
|
||||
|
|
|
@ -20,11 +20,7 @@ static const SamplerDef samplers[1] = {
|
|||
// TODO: We could possibly have an option to preserve any extra color precision? But gonna start without it.
|
||||
// Requires full size integer math. It would be possible to make a floating point-only version with lots of
|
||||
// modulo and stuff, might do it one day.
|
||||
void GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang) {
|
||||
_assert_(lang.bitwiseOps);
|
||||
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment);
|
||||
|
||||
Draw2DPipelineInfo GenerateReinterpretFragmentShader(ShaderWriter &writer, GEBufferFormat from, GEBufferFormat to) {
|
||||
writer.HighPrecisionFloat();
|
||||
|
||||
writer.DeclareSamplers(samplers);
|
||||
|
@ -70,22 +66,13 @@ void GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBuff
|
|||
}
|
||||
|
||||
writer.EndFSMain("outColor", FSFLAG_NONE);
|
||||
|
||||
return Draw2DPipelineInfo{
|
||||
RASTER_COLOR,
|
||||
RASTER_COLOR,
|
||||
};
|
||||
}
|
||||
|
||||
void GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
_assert_(lang.bitwiseOps);
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Vertex);
|
||||
|
||||
writer.BeginVSMain(Slice<InputDef>::empty(), Slice<UniformDef>::empty(), varyings);
|
||||
|
||||
writer.C(" float x = -1.0 + float((gl_VertexIndex & 1) << 2);\n");
|
||||
writer.C(" float y = -1.0 + float((gl_VertexIndex & 2) << 1);\n");
|
||||
writer.C(" v_texcoord = (vec2(x, y) + vec2(1.0, 1.0)) * 0.5;\n");
|
||||
writer.C(" gl_Position = vec4(x, y, 0.0, 1.0);\n");
|
||||
writer.EndVSMain(varyings);
|
||||
}
|
||||
|
||||
|
||||
// Can't easily dynamically create these strings, we just pass along the pointer.
|
||||
static const char *reinterpretStrings[3][3] = {
|
||||
{
|
||||
|
@ -150,60 +137,15 @@ void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, G
|
|||
return;
|
||||
}
|
||||
|
||||
if (!reinterpretVS_) {
|
||||
char *vsCode = new char[4000];
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
GenerateReinterpretVertexShader(vsCode, shaderLanguageDesc);
|
||||
reinterpretVS_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "reinterpret_vs");
|
||||
_assert_(reinterpretVS_);
|
||||
delete[] vsCode;
|
||||
}
|
||||
|
||||
if (!reinterpretSampler_) {
|
||||
Draw::SamplerStateDesc samplerDesc{};
|
||||
samplerDesc.magFilter = Draw::TextureFilter::LINEAR;
|
||||
samplerDesc.minFilter = Draw::TextureFilter::LINEAR;
|
||||
reinterpretSampler_ = draw_->CreateSamplerState(samplerDesc);
|
||||
}
|
||||
|
||||
if (!reinterpretVBuf_) {
|
||||
reinterpretVBuf_ = draw_->CreateBuffer(12 * 3, Draw::BufferUsageFlag::DYNAMIC | Draw::BufferUsageFlag::VERTEXDATA);
|
||||
}
|
||||
|
||||
// See if we need to create a new pipeline.
|
||||
|
||||
Draw::Pipeline *pipeline = reinterpretFromTo_[(int)oldFormat][(int)newFormat];
|
||||
Draw2DPipeline *pipeline = reinterpretFromTo_[(int)oldFormat][(int)newFormat];
|
||||
if (!pipeline) {
|
||||
char *fsCode = new char[4000];
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
GenerateReinterpretFragmentShader(fsCode, oldFormat, newFormat, shaderLanguageDesc);
|
||||
Draw::ShaderModule *reinterpretFS = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "reinterpret_fs");
|
||||
_assert_(reinterpretFS);
|
||||
delete[] fsCode;
|
||||
pipeline = draw2D_.Create2DPipeline([=](ShaderWriter &shaderWriter) -> Draw2DPipelineInfo {
|
||||
return GenerateReinterpretFragmentShader(shaderWriter, oldFormat, newFormat);
|
||||
});
|
||||
|
||||
std::vector<Draw::ShaderModule *> shaders;
|
||||
shaders.push_back(reinterpretVS_);
|
||||
shaders.push_back(reinterpretFS);
|
||||
|
||||
using namespace Draw;
|
||||
Draw::PipelineDesc desc{};
|
||||
// We use a "fullscreen triangle".
|
||||
// TODO: clear the stencil buffer. Hard to actually initialize it with the new alpha, though possible - let's see if
|
||||
// we need it.
|
||||
DepthStencilState *depth = draw_->CreateDepthStencilState({ false, false, Comparison::LESS });
|
||||
BlendState *blendstateOff = draw_->CreateBlendState({ false, 0xF });
|
||||
RasterState *rasterNoCull = draw_->CreateRasterState({});
|
||||
|
||||
// No uniforms for these, only a single texture input.
|
||||
PipelineDesc pipelineDesc{ Primitive::TRIANGLE_LIST, shaders, nullptr, depth, blendstateOff, rasterNoCull, nullptr };
|
||||
pipeline = draw_->CreateGraphicsPipeline(pipelineDesc);
|
||||
_assert_(pipeline != nullptr);
|
||||
reinterpretFromTo_[(int)oldFormat][(int)newFormat] = pipeline;
|
||||
|
||||
depth->Release();
|
||||
blendstateOff->Release();
|
||||
rasterNoCull->Release();
|
||||
reinterpretFS->Release();
|
||||
}
|
||||
|
||||
// Copy to a temp framebuffer.
|
||||
|
@ -213,18 +155,9 @@ void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, G
|
|||
// itself while writing.
|
||||
draw_->InvalidateCachedState();
|
||||
draw_->CopyFramebufferImage(vfb->fbo, 0, 0, 0, 0, temp, 0, 0, 0, 0, vfb->renderWidth, vfb->renderHeight, 1, Draw::FBChannel::FB_COLOR_BIT, "reinterpret_prep");
|
||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, reinterpretStrings[(int)oldFormat][(int)newFormat]);
|
||||
draw_->BindPipeline(pipeline);
|
||||
draw_->BindFramebufferAsTexture(temp, 0, Draw::FBChannel::FB_COLOR_BIT, 0);
|
||||
draw_->BindSamplerStates(0, 1, &reinterpretSampler_);
|
||||
draw_->SetScissorRect(0, 0, vfb->renderWidth, vfb->renderHeight);
|
||||
Draw::Viewport vp = Draw::Viewport{ 0.0f, 0.0f, (float)vfb->renderWidth, (float)vfb->renderHeight, 0.0f, 1.0f };
|
||||
draw_->SetViewports(1, &vp);
|
||||
// Vertex buffer not used - vertices generated in shader.
|
||||
// TODO: Switch to a vertex buffer for GLES2/D3D9 compat.
|
||||
draw_->BindVertexBuffers(0, 1, &reinterpretVBuf_, nullptr);
|
||||
draw_->Draw(3, 0);
|
||||
draw_->InvalidateCachedState();
|
||||
|
||||
BlitUsingRaster(temp, 0.0f, 0.0f, vfb->renderWidth, vfb->renderHeight,
|
||||
vfb->fbo, 0.0f, 0.0f, vfb->renderWidth, vfb->renderHeight, false, pipeline, "reinterpret");
|
||||
|
||||
// Unbind.
|
||||
draw_->BindTexture(0, nullptr);
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common/GPU/ShaderWriter.h"
|
||||
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/GPUCommon.h"
|
||||
#include "Common/GPU/ShaderWriter.h"
|
||||
#include "GPU/Common/Draw2D.h"
|
||||
|
||||
void GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang);
|
||||
|
||||
// Just a single one. Can probably be shared with a lot of similar use cases.
|
||||
// Generates the coordinates for a fullscreen triangle.
|
||||
void GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang);
|
||||
Draw2DPipelineInfo GenerateReinterpretFragmentShader(ShaderWriter &writer, GEBufferFormat from, GEBufferFormat to);
|
||||
|
|
|
@ -105,8 +105,8 @@ inline int dimHeight(u16 dim) {
|
|||
|
||||
// Vulkan color formats:
|
||||
// TODO
|
||||
TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw)
|
||||
: draw_(draw) {
|
||||
TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw, Draw2D *draw2D)
|
||||
: draw_(draw), draw2D_(draw2D) {
|
||||
decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL;
|
||||
|
||||
// TODO: Clamp down to 256/1KB? Need to check mipmapShareClut and clamp loadclut.
|
||||
|
@ -124,7 +124,7 @@ TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw)
|
|||
|
||||
replacer_.Init();
|
||||
|
||||
textureShaderCache_ = new TextureShaderCache(draw);
|
||||
textureShaderCache_ = new TextureShaderCache(draw, draw2D_);
|
||||
}
|
||||
|
||||
TextureCacheCommon::~TextureCacheCommon() {
|
||||
|
@ -1885,7 +1885,7 @@ static bool CanUseSmoothDepal(const GPUgstate &gstate, GEBufferFormat framebuffe
|
|||
}
|
||||
|
||||
void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer, GETextureFormat texFormat, RasterChannel channel) {
|
||||
TextureShader *textureShader = nullptr;
|
||||
Draw2DPipeline *textureShader = nullptr;
|
||||
uint32_t clutMode = gstate.clutformat & 0xFFFFFF;
|
||||
|
||||
bool depth = channel == RASTER_DEPTH;
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "GPU/Common/TextureScalerCommon.h"
|
||||
#include "GPU/Common/TextureShaderCommon.h"
|
||||
|
||||
class Draw2D;
|
||||
|
||||
enum FramebufferNotification {
|
||||
NOTIFY_FB_CREATED,
|
||||
NOTIFY_FB_UPDATED,
|
||||
|
@ -271,7 +273,7 @@ struct BuildTexturePlan {
|
|||
|
||||
class TextureCacheCommon {
|
||||
public:
|
||||
TextureCacheCommon(Draw::DrawContext *draw);
|
||||
TextureCacheCommon(Draw::DrawContext *draw, Draw2D *draw2D);
|
||||
virtual ~TextureCacheCommon();
|
||||
|
||||
void LoadClut(u32 clutAddr, u32 loadBytes);
|
||||
|
@ -400,6 +402,8 @@ protected:
|
|||
}
|
||||
|
||||
Draw::DrawContext *draw_;
|
||||
Draw2D *draw2D_;
|
||||
|
||||
TextureReplacer replacer_;
|
||||
TextureScalerCommon scaler_;
|
||||
FramebufferManagerCommon *framebufferManager_;
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "Common/GPU/ShaderWriter.h"
|
||||
#include "Common/Data/Convert/ColorConv.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "GPU/Common/Draw2D.h"
|
||||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
#include "GPU/Common/TextureCacheCommon.h"
|
||||
#include "GPU/Common/TextureShaderCommon.h"
|
||||
|
@ -37,7 +38,7 @@ static const SamplerDef samplers[2] = {
|
|||
{ "pal" },
|
||||
};
|
||||
|
||||
TextureShaderCache::TextureShaderCache(Draw::DrawContext *draw) : draw_(draw) { }
|
||||
TextureShaderCache::TextureShaderCache(Draw::DrawContext *draw, Draw2D *draw2D) : draw_(draw), draw2D_(draw2D) { }
|
||||
|
||||
TextureShaderCache::~TextureShaderCache() {
|
||||
DeviceLost();
|
||||
|
@ -139,10 +140,6 @@ void TextureShaderCache::Clear() {
|
|||
delete tex->second;
|
||||
}
|
||||
texCache_.clear();
|
||||
if (vertexShader_) {
|
||||
vertexShader_->Release();
|
||||
vertexShader_ = nullptr;
|
||||
}
|
||||
if (nearestSampler_) {
|
||||
nearestSampler_->Release();
|
||||
nearestSampler_ = nullptr;
|
||||
|
@ -153,18 +150,6 @@ void TextureShaderCache::Clear() {
|
|||
}
|
||||
}
|
||||
|
||||
void TextureShaderCache::Decimate() {
|
||||
for (auto tex = texCache_.begin(); tex != texCache_.end(); ) {
|
||||
if (tex->second->lastFrame + DEPAL_TEXTURE_OLD_AGE < gpuStats.numFlips) {
|
||||
tex->second->texture->Release();
|
||||
delete tex->second;
|
||||
texCache_.erase(tex++);
|
||||
} else {
|
||||
++tex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Draw::SamplerState *TextureShaderCache::GetSampler(bool linearFilter) {
|
||||
if (linearFilter) {
|
||||
if (!linearSampler_) {
|
||||
|
@ -189,55 +174,19 @@ Draw::SamplerState *TextureShaderCache::GetSampler(bool linearFilter) {
|
|||
}
|
||||
}
|
||||
|
||||
TextureShader *TextureShaderCache::CreateShader(const char *fs) {
|
||||
using namespace Draw;
|
||||
if (!vertexShader_) {
|
||||
char *buffer = new char[4096];
|
||||
GenerateVs(buffer, draw_->GetShaderLanguageDesc());
|
||||
vertexShader_ = draw_->CreateShaderModule(ShaderStage::Vertex, draw_->GetShaderLanguageDesc().shaderLanguage, (const uint8_t *)buffer, strlen(buffer), "depal_vs");
|
||||
delete[] buffer;
|
||||
void TextureShaderCache::Decimate() {
|
||||
for (auto tex = texCache_.begin(); tex != texCache_.end(); ) {
|
||||
if (tex->second->lastFrame + DEPAL_TEXTURE_OLD_AGE < gpuStats.numFlips) {
|
||||
tex->second->texture->Release();
|
||||
delete tex->second;
|
||||
texCache_.erase(tex++);
|
||||
} else {
|
||||
++tex;
|
||||
}
|
||||
}
|
||||
|
||||
ShaderModule *fragShader = draw_->CreateShaderModule(ShaderStage::Fragment, draw_->GetShaderLanguageDesc().shaderLanguage, (const uint8_t *)fs, strlen(fs), "depal_fs");
|
||||
|
||||
static const InputLayoutDesc desc = {
|
||||
{
|
||||
{ 16, false },
|
||||
},
|
||||
{
|
||||
{ 0, SEM_POSITION, DataFormat::R32G32_FLOAT, 0 },
|
||||
{ 0, 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 depalPipelineDesc{
|
||||
Primitive::TRIANGLE_STRIP, // Could have use a single triangle too (in which case we'd use LIST here) but want to be prepared to do subrectangles.
|
||||
{ vertexShader_, fragShader },
|
||||
inputLayout, noDepthStencil, blendOff, rasterNoCull, nullptr, samplers
|
||||
};
|
||||
|
||||
Pipeline *pipeline = draw_->CreateGraphicsPipeline(depalPipelineDesc);
|
||||
|
||||
inputLayout->Release();
|
||||
blendOff->Release();
|
||||
noDepthStencil->Release();
|
||||
rasterNoCull->Release();
|
||||
fragShader->Release();
|
||||
|
||||
_assert_(pipeline);
|
||||
|
||||
TextureShader *depal = new TextureShader();
|
||||
depal->pipeline = pipeline;
|
||||
depal->code = fs; // to std::string
|
||||
return depal;
|
||||
}
|
||||
|
||||
TextureShader *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETextureFormat textureFormat, GEBufferFormat bufferFormat, bool smoothedDepal) {
|
||||
Draw2DPipeline *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETextureFormat textureFormat, GEBufferFormat bufferFormat, bool smoothedDepal) {
|
||||
using namespace Draw;
|
||||
|
||||
// Generate an ID for depal shaders.
|
||||
|
@ -245,7 +194,6 @@ TextureShader *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETex
|
|||
|
||||
auto shader = depalCache_.find(id);
|
||||
if (shader != depalCache_.end()) {
|
||||
TextureShader *depal = shader->second;
|
||||
return shader->second;
|
||||
}
|
||||
|
||||
|
@ -260,8 +208,13 @@ TextureShader *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETex
|
|||
config.smoothedDepal = smoothedDepal;
|
||||
|
||||
char *buffer = new char[4096];
|
||||
GenerateDepalFs(buffer, config, draw_->GetShaderLanguageDesc());
|
||||
TextureShader *ts = CreateShader(buffer);
|
||||
Draw2DPipeline *ts = draw2D_->Create2DPipeline([=](ShaderWriter &writer) -> Draw2DPipelineInfo {
|
||||
GenerateDepalFs(writer, config);
|
||||
return Draw2DPipelineInfo{
|
||||
config.bufferFormat == GE_FORMAT_DEPTH16 ? RASTER_DEPTH : RASTER_COLOR,
|
||||
RASTER_COLOR,
|
||||
};
|
||||
});
|
||||
delete[] buffer;
|
||||
|
||||
depalCache_[id] = ts;
|
||||
|
@ -293,7 +246,7 @@ std::string TextureShaderCache::DebugGetShaderString(std::string idstr, DebugSha
|
|||
}
|
||||
}
|
||||
|
||||
void TextureShaderCache::ApplyShader(TextureShader *shader, float bufferW, float bufferH, int renderW, int renderH, const KnownVertexBounds &bounds, u32 uoff, u32 voff) {
|
||||
void TextureShaderCache::ApplyShader(Draw2DPipeline *pipeline, float bufferW, float bufferH, int renderW, int renderH, const KnownVertexBounds &bounds, u32 uoff, u32 voff) {
|
||||
Draw2DVertex verts[4] = {
|
||||
{-1, -1, 0, 0 },
|
||||
{ 1, -1, 1, 0 },
|
||||
|
@ -335,7 +288,7 @@ void TextureShaderCache::ApplyShader(TextureShader *shader, float bufferW, float
|
|||
}
|
||||
|
||||
Draw::Viewport vp{ 0.0f, 0.0f, (float)renderW, (float)renderH, 0.0f, 1.0f };
|
||||
draw_->BindPipeline(shader->pipeline);
|
||||
draw_->BindPipeline(pipeline->pipeline);
|
||||
draw_->SetViewports(1, &vp);
|
||||
draw_->SetScissorRect(0, 0, renderW, renderH);
|
||||
draw_->DrawUP((const uint8_t *)verts, 4);
|
||||
|
|
|
@ -29,12 +29,6 @@
|
|||
#include "GPU/Common/ShaderCommon.h"
|
||||
#include "GPU/Common/DepalettizeShaderCommon.h"
|
||||
|
||||
class TextureShader {
|
||||
public:
|
||||
Draw::Pipeline *pipeline;
|
||||
std::string code;
|
||||
};
|
||||
|
||||
class ClutTexture {
|
||||
public:
|
||||
Draw::Texture *texture;
|
||||
|
@ -46,15 +40,15 @@ public:
|
|||
// Caches both shaders and palette textures.
|
||||
class TextureShaderCache {
|
||||
public:
|
||||
TextureShaderCache(Draw::DrawContext *draw);
|
||||
TextureShaderCache(Draw::DrawContext *draw, Draw2D *draw2D);
|
||||
~TextureShaderCache();
|
||||
|
||||
TextureShader *GetDepalettizeShader(uint32_t clutMode, GETextureFormat texFormat, GEBufferFormat pixelFormat, bool smoothedDepal);
|
||||
Draw2DPipeline *GetDepalettizeShader(uint32_t clutMode, GETextureFormat texFormat, GEBufferFormat pixelFormat, bool smoothedDepal);
|
||||
ClutTexture GetClutTexture(GEPaletteFormat clutFormat, const u32 clutHash, u32 *rawClut);
|
||||
|
||||
Draw::SamplerState *GetSampler(bool linearFilter);
|
||||
|
||||
void ApplyShader(TextureShader *shader, float bufferW, float bufferH, int renderW, int renderH, const KnownVertexBounds &bounds, u32 uoff, u32 voff);
|
||||
void ApplyShader(Draw2DPipeline *pipeline, float bufferW, float bufferH, int renderW, int renderH, const KnownVertexBounds &bounds, u32 uoff, u32 voff);
|
||||
|
||||
void Clear();
|
||||
void Decimate();
|
||||
|
@ -65,13 +59,11 @@ public:
|
|||
void DeviceRestore(Draw::DrawContext *draw);
|
||||
|
||||
private:
|
||||
TextureShader *CreateShader(const char *fs);
|
||||
|
||||
Draw::DrawContext *draw_;
|
||||
Draw::ShaderModule *vertexShader_ = nullptr;
|
||||
Draw::SamplerState *nearestSampler_ = nullptr;
|
||||
Draw::SamplerState *linearSampler_ = nullptr;
|
||||
Draw2D *draw2D_;
|
||||
|
||||
std::map<u32, TextureShader *> depalCache_;
|
||||
std::map<u32, Draw2DPipeline *> depalCache_;
|
||||
std::map<u32, ClutTexture *> texCache_;
|
||||
};
|
||||
|
|
|
@ -60,7 +60,7 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
|||
shaderManagerD3D11_ = new ShaderManagerD3D11(draw, device_, context_, featureLevel);
|
||||
framebufferManagerD3D11_ = new FramebufferManagerD3D11(draw);
|
||||
framebufferManager_ = framebufferManagerD3D11_;
|
||||
textureCacheD3D11_ = new TextureCacheD3D11(draw);
|
||||
textureCacheD3D11_ = new TextureCacheD3D11(draw, framebufferManager_->GetDraw2D());
|
||||
textureCache_ = textureCacheD3D11_;
|
||||
drawEngineCommon_ = &drawEngine_;
|
||||
shaderManager_ = shaderManagerD3D11_;
|
||||
|
|
|
@ -127,8 +127,8 @@ ID3D11SamplerState *SamplerCacheD3D11::GetOrCreateSampler(ID3D11Device *device,
|
|||
return sampler;
|
||||
}
|
||||
|
||||
TextureCacheD3D11::TextureCacheD3D11(Draw::DrawContext *draw)
|
||||
: TextureCacheCommon(draw) {
|
||||
TextureCacheD3D11::TextureCacheD3D11(Draw::DrawContext *draw, Draw2D *draw2D)
|
||||
: TextureCacheCommon(draw, draw2D) {
|
||||
device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE);
|
||||
context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ private:
|
|||
|
||||
class TextureCacheD3D11 : public TextureCacheCommon {
|
||||
public:
|
||||
TextureCacheD3D11(Draw::DrawContext *draw);
|
||||
TextureCacheD3D11(Draw::DrawContext *draw, Draw2D *draw2D);
|
||||
~TextureCacheD3D11();
|
||||
|
||||
void StartFrame() override;
|
||||
|
|
|
@ -58,7 +58,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
|||
shaderManagerDX9_ = new ShaderManagerDX9(draw, device_);
|
||||
framebufferManagerDX9_ = new FramebufferManagerDX9(draw);
|
||||
framebufferManager_ = framebufferManagerDX9_;
|
||||
textureCacheDX9_ = new TextureCacheDX9(draw);
|
||||
textureCacheDX9_ = new TextureCacheDX9(draw, framebufferManager_->GetDraw2D());
|
||||
textureCache_ = textureCacheDX9_;
|
||||
drawEngineCommon_ = &drawEngine_;
|
||||
shaderManager_ = shaderManagerDX9_;
|
||||
|
|
|
@ -59,8 +59,8 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
|
|||
D3DDECL_END()
|
||||
};
|
||||
|
||||
TextureCacheDX9::TextureCacheDX9(Draw::DrawContext *draw)
|
||||
: TextureCacheCommon(draw) {
|
||||
TextureCacheDX9::TextureCacheDX9(Draw::DrawContext *draw, Draw2D *draw2D)
|
||||
: TextureCacheCommon(draw, draw2D) {
|
||||
lastBoundTexture = INVALID_TEX;
|
||||
isBgraBackend_ = true;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ class ShaderManagerDX9;
|
|||
|
||||
class TextureCacheDX9 : public TextureCacheCommon {
|
||||
public:
|
||||
TextureCacheDX9(Draw::DrawContext *draw);
|
||||
TextureCacheDX9(Draw::DrawContext *draw, Draw2D *draw2D);
|
||||
~TextureCacheDX9();
|
||||
|
||||
void StartFrame() override;
|
||||
|
|
|
@ -60,7 +60,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
|||
shaderManagerGL_ = new ShaderManagerGLES(draw);
|
||||
framebufferManagerGL_ = new FramebufferManagerGLES(draw);
|
||||
framebufferManager_ = framebufferManagerGL_;
|
||||
textureCacheGL_ = new TextureCacheGLES(draw);
|
||||
textureCacheGL_ = new TextureCacheGLES(draw, framebufferManager_->GetDraw2D());
|
||||
textureCache_ = textureCacheGL_;
|
||||
drawEngineCommon_ = &drawEngine_;
|
||||
shaderManager_ = shaderManagerGL_;
|
||||
|
|
|
@ -45,8 +45,8 @@
|
|||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
TextureCacheGLES::TextureCacheGLES(Draw::DrawContext *draw)
|
||||
: TextureCacheCommon(draw) {
|
||||
TextureCacheGLES::TextureCacheGLES(Draw::DrawContext *draw, Draw2D *draw2D)
|
||||
: TextureCacheCommon(draw, draw2D) {
|
||||
render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
|
||||
nextTexture_ = nullptr;
|
||||
|
|
|
@ -34,7 +34,7 @@ class GLRTexture;
|
|||
|
||||
class TextureCacheGLES : public TextureCacheCommon {
|
||||
public:
|
||||
TextureCacheGLES(Draw::DrawContext *draw);
|
||||
TextureCacheGLES(Draw::DrawContext *draw, Draw2D *draw2D);
|
||||
~TextureCacheGLES();
|
||||
|
||||
void Clear(bool delete_them) override;
|
||||
|
|
|
@ -63,7 +63,7 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
|||
pipelineManager_ = new PipelineManagerVulkan(vulkan);
|
||||
framebufferManagerVulkan_ = new FramebufferManagerVulkan(draw);
|
||||
framebufferManager_ = framebufferManagerVulkan_;
|
||||
textureCacheVulkan_ = new TextureCacheVulkan(draw, vulkan);
|
||||
textureCacheVulkan_ = new TextureCacheVulkan(draw, framebufferManager_->GetDraw2D(), vulkan);
|
||||
textureCache_ = textureCacheVulkan_;
|
||||
drawEngineCommon_ = &drawEngine_;
|
||||
shaderManager_ = shaderManagerVulkan_;
|
||||
|
|
|
@ -184,8 +184,8 @@ std::vector<std::string> SamplerCache::DebugGetSamplerIDs() const {
|
|||
return ids;
|
||||
}
|
||||
|
||||
TextureCacheVulkan::TextureCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan)
|
||||
: TextureCacheCommon(draw),
|
||||
TextureCacheVulkan::TextureCacheVulkan(Draw::DrawContext *draw, Draw2D *draw2D, VulkanContext *vulkan)
|
||||
: TextureCacheCommon(draw, draw2D),
|
||||
computeShaderManager_(vulkan),
|
||||
samplerCache_(vulkan) {
|
||||
DeviceRestore(draw);
|
||||
|
|
|
@ -54,7 +54,7 @@ private:
|
|||
|
||||
class TextureCacheVulkan : public TextureCacheCommon {
|
||||
public:
|
||||
TextureCacheVulkan(Draw::DrawContext *draw, VulkanContext *vulkan);
|
||||
TextureCacheVulkan(Draw::DrawContext *draw, Draw2D *draw2D, VulkanContext *vulkan);
|
||||
~TextureCacheVulkan();
|
||||
|
||||
void StartFrame() override;
|
||||
|
|
|
@ -180,27 +180,6 @@ bool TestReinterpretShaders() {
|
|||
// Generate all despite failures - it's only 6.
|
||||
bool failed = false;
|
||||
|
||||
for (int k = 0; k < ARRAY_SIZE(languages); k++) {
|
||||
printf("=== %s ===\n\n", ShaderLanguageToString(languages[k]));
|
||||
|
||||
ShaderLanguageDesc desc(languages[k]);
|
||||
|
||||
// These require bitwise operations.
|
||||
if (!desc.bitwiseOps) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GenerateReinterpretVertexShader(buffer, desc);
|
||||
std::string errorMessage;
|
||||
if (!TestCompileShader(buffer, languages[k], ShaderStage::Vertex, &errorMessage)) {
|
||||
printf("Error compiling fragment shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str());
|
||||
failed = true;
|
||||
return false;
|
||||
} else {
|
||||
//printf("===\n%s\n===\n", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
for (int k = 0; k < ARRAY_SIZE(languages); k++) {
|
||||
printf("=== %s ===\n\n", ShaderLanguageToString(languages[k]));
|
||||
|
||||
|
@ -217,7 +196,8 @@ bool TestReinterpretShaders() {
|
|||
for (int j = 0; j < 3; j++) {
|
||||
if (i == j)
|
||||
continue; // useless shader!
|
||||
GenerateReinterpretFragmentShader(buffer, fmts[i], fmts[j], desc);
|
||||
ShaderWriter writer(buffer, desc, ShaderStage::Fragment, nullptr, 0);
|
||||
GenerateReinterpretFragmentShader(writer, fmts[i], fmts[j]);
|
||||
if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) {
|
||||
printf("Error compiling fragment shader %d:\n\n%s\n\n%s\n", (int)j, LineNumberString(buffer).c_str(), errorMessage.c_str());
|
||||
failed = true;
|
||||
|
@ -312,7 +292,8 @@ bool TestDepalShaders() {
|
|||
config.bufferFormat = GE_FORMAT_8888;
|
||||
config.textureFormat = GE_TFMT_CLUT32;
|
||||
|
||||
GenerateDepalFs(buffer, config, desc);
|
||||
ShaderWriter writer(buffer, desc, ShaderStage::Fragment);
|
||||
GenerateDepalFs(writer, config);
|
||||
if (!TestCompileShader(buffer, languages[k], ShaderStage::Fragment, &errorMessage)) {
|
||||
printf("Error compiling depal shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str());
|
||||
failed = true;
|
||||
|
@ -320,15 +301,6 @@ bool TestDepalShaders() {
|
|||
} else {
|
||||
printf("===\n%s\n===\n", buffer);
|
||||
}
|
||||
|
||||
GenerateVs(buffer, desc);
|
||||
if (!TestCompileShader(buffer, languages[k], ShaderStage::Vertex, &errorMessage)) {
|
||||
printf("Error compiling depal shader:\n\n%s\n\n%s\n", LineNumberString(buffer).c_str(), errorMessage.c_str());
|
||||
failed = true;
|
||||
return false;
|
||||
} else {
|
||||
printf("===\n%s\n===\n", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buffer;
|
||||
|
|
Loading…
Add table
Reference in a new issue