mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 17:49:29 +01:00
Merge pull request #15846 from hrydgard/minor-gpu-cleanup
Minor GPU code cleanup
This commit is contained in:
22 files changed
+275
-365
No files matched your search
@@ -100,8 +100,6 @@ public:
|
||||
}
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override;
|
||||
|
||||
uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) override;
|
||||
|
||||
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
|
||||
|
||||
void InvalidateCachedState() override;
|
||||
@@ -1709,21 +1707,6 @@ uint64_t D3D11DrawContext::GetNativeObject(NativeObject obj, void *srcObject) {
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) {
|
||||
D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo;
|
||||
switch (channelBit) {
|
||||
case FB_COLOR_BIT: return (uintptr_t)fb->colorTex;
|
||||
case FB_DEPTH_BIT: return (uintptr_t)fb->depthStencilTex;
|
||||
case FB_COLOR_BIT | FB_VIEW_BIT: return (uintptr_t)fb->colorRTView;
|
||||
case FB_DEPTH_BIT | FB_VIEW_BIT: return (uintptr_t)fb->depthStencilRTView;
|
||||
case FB_COLOR_BIT | FB_FORMAT_BIT: return (uintptr_t)fb->colorFormat;
|
||||
case FB_DEPTH_BIT | FB_FORMAT_BIT: return (uintptr_t)fb->depthStencilFormat;
|
||||
case FB_STENCIL_BIT | FB_FORMAT_BIT: return (uintptr_t)fb->depthStencilFormat;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
|
||||
D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo;
|
||||
if (fb) {
|
||||
|
||||
@@ -313,6 +313,9 @@ void ShaderWriter::EndVSMain(Slice<VaryingDef> varyings) {
|
||||
case HLSL_D3D11:
|
||||
case HLSL_D3D9:
|
||||
C(" VS_OUTPUT vs_out;\n");
|
||||
if (strlen(lang_.viewportYSign)) {
|
||||
F(" gl_Position.y *= %s1.0;\n", lang_.viewportYSign);
|
||||
}
|
||||
C(" vs_out.pos = gl_Position;\n");
|
||||
for (auto &varying : varyings) {
|
||||
F(" vs_out.%s = %s;\n", varying.name, varying.name);
|
||||
|
||||
@@ -43,7 +43,7 @@ enum FSFlags {
|
||||
|
||||
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) {
|
||||
ShaderWriter(char *buffer, const ShaderLanguageDesc &lang, ShaderStage stage, const char **gl_extensions = nullptr, size_t num_gl_extensions = 0) : p_(buffer), lang_(lang), stage_(stage) {
|
||||
Preamble(gl_extensions, num_gl_extensions);
|
||||
}
|
||||
ShaderWriter(const ShaderWriter &) = delete;
|
||||
|
||||
@@ -395,8 +395,6 @@ public:
|
||||
}
|
||||
void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override;
|
||||
|
||||
uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) override;
|
||||
|
||||
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
|
||||
|
||||
void SetScissorRect(int left, int top, int width, int height) override;
|
||||
@@ -1580,24 +1578,6 @@ void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChanne
|
||||
boundImageView_[binding] = renderManager_.BindFramebufferAsTexture(fb->GetFB(), binding, aspect, attachment);
|
||||
}
|
||||
|
||||
uintptr_t VKContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) {
|
||||
if (!fbo)
|
||||
return 0;
|
||||
|
||||
VKFramebuffer *fb = (VKFramebuffer *)fbo;
|
||||
VkImageView view = VK_NULL_HANDLE;
|
||||
switch (channelBit) {
|
||||
case FB_COLOR_BIT:
|
||||
view = fb->GetFB()->color.imageView;
|
||||
break;
|
||||
case FB_DEPTH_BIT:
|
||||
case FB_STENCIL_BIT:
|
||||
view = fb->GetFB()->depth.imageView;
|
||||
break;
|
||||
}
|
||||
return (uintptr_t)view;
|
||||
}
|
||||
|
||||
void VKContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
|
||||
VKFramebuffer *fb = (VKFramebuffer *)fbo;
|
||||
if (fb) {
|
||||
|
||||
+4
-4
@@ -605,12 +605,15 @@ public:
|
||||
virtual void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {}
|
||||
|
||||
// Partial pipeline state, used to create pipelines. (in practice, in d3d11 they'll use the native state objects directly).
|
||||
// TODO: Possibly ditch these and just put the descs directly in PipelineDesc since only D3D11 benefits.
|
||||
virtual DepthStencilState *CreateDepthStencilState(const DepthStencilStateDesc &desc) = 0;
|
||||
virtual BlendState *CreateBlendState(const BlendStateDesc &desc) = 0;
|
||||
virtual SamplerState *CreateSamplerState(const SamplerStateDesc &desc) = 0;
|
||||
virtual RasterState *CreateRasterState(const RasterStateDesc &desc) = 0;
|
||||
// virtual ComputePipeline CreateComputePipeline(const ComputePipelineDesc &desc) = 0
|
||||
virtual InputLayout *CreateInputLayout(const InputLayoutDesc &desc) = 0;
|
||||
virtual ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag = "thin3d") = 0;
|
||||
virtual Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) = 0;
|
||||
|
||||
// Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them.
|
||||
ShaderModule *GetVshaderPreset(VertexShaderPreset preset) { return vsPresets_[preset]; }
|
||||
@@ -623,9 +626,6 @@ public:
|
||||
// On some hardware, you might get a 24-bit depth buffer even though you only wanted a 16-bit one.
|
||||
virtual Framebuffer *CreateFramebuffer(const FramebufferDesc &desc) = 0;
|
||||
|
||||
virtual ShaderModule *CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize, const std::string &tag = "thin3d") = 0;
|
||||
virtual Pipeline *CreateGraphicsPipeline(const PipelineDesc &desc) = 0;
|
||||
|
||||
// Copies data from the CPU over into the buffer, at a specific offset. This does not change the size of the buffer and cannot write outside it.
|
||||
virtual void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) = 0;
|
||||
|
||||
@@ -646,7 +646,7 @@ public:
|
||||
// binding must be < MAX_TEXTURE_SLOTS (0, 1 are okay if it's 2).
|
||||
virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) = 0;
|
||||
|
||||
// deprecated
|
||||
// deprecated, only used by D3D9
|
||||
virtual uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -264,7 +264,7 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config, c
|
||||
}
|
||||
|
||||
void GenerateDepalFs(char *buffer, const DepalConfig &config, const ShaderLanguageDesc &lang) {
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0);
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment);
|
||||
writer.DeclareSamplers(samplers);
|
||||
writer.HighPrecisionFloat();
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings, FSFLAG_NONE);
|
||||
@@ -289,9 +289,6 @@ void GenerateDepalVs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
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");
|
||||
if (strlen(lang.viewportYSign)) {
|
||||
writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign);
|
||||
}
|
||||
writer.EndVSMain(varyings);
|
||||
}
|
||||
|
||||
|
||||
+54
-32
@@ -40,7 +40,7 @@ static const SamplerDef samplers[1] = {
|
||||
};
|
||||
|
||||
void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0);
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment);
|
||||
writer.DeclareSamplers(samplers);
|
||||
writer.BeginFSMain(Slice<UniformDef>::empty(), varyings, FSFLAG_NONE);
|
||||
writer.C(" vec4 outColor = ").SampleTexture2D("tex", "v_texcoord.xy").C(";\n");
|
||||
@@ -48,7 +48,7 @@ void GenerateDraw2DFs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
}
|
||||
|
||||
void GenerateDraw2DDepthFs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0);
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment);
|
||||
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");
|
||||
@@ -57,35 +57,66 @@ void GenerateDraw2DDepthFs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
}
|
||||
|
||||
void GenerateDraw2DVS(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Vertex, nullptr, 0);
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Vertex);
|
||||
|
||||
writer.BeginVSMain(inputs, Slice<UniformDef>::empty(), varyings);
|
||||
|
||||
writer.C(" v_texcoord = a_texcoord0;\n"); // yes, this should be right. Should be 2.0 in the far corners.
|
||||
writer.C(" gl_Position = vec4(a_position, 0.0, 1.0);\n");
|
||||
writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign);
|
||||
|
||||
writer.EndVSMain(varyings);
|
||||
}
|
||||
|
||||
// verts have positions in clip coordinates.
|
||||
void FramebufferManagerCommon::Ensure2DResources() {
|
||||
using namespace Draw;
|
||||
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
|
||||
if (!draw2DVs_) {
|
||||
char *vsCode = new char[4000];
|
||||
GenerateDraw2DVS(vsCode, shaderLanguageDesc);
|
||||
draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs");
|
||||
_assert_(draw2DVs_);
|
||||
delete[] vsCode;
|
||||
}
|
||||
|
||||
if (!draw2DSamplerLinear_) {
|
||||
SamplerStateDesc descLinear{};
|
||||
descLinear.magFilter = TextureFilter::LINEAR;
|
||||
descLinear.minFilter = TextureFilter::LINEAR;
|
||||
descLinear.mipFilter = TextureFilter::LINEAR;
|
||||
descLinear.wrapU = TextureAddressMode::CLAMP_TO_EDGE;
|
||||
descLinear.wrapV = TextureAddressMode::CLAMP_TO_EDGE;
|
||||
draw2DSamplerLinear_ = draw_->CreateSamplerState(descLinear);
|
||||
}
|
||||
|
||||
if (!draw2DSamplerNearest_) {
|
||||
SamplerStateDesc descNearest{};
|
||||
descNearest.magFilter = TextureFilter::NEAREST;
|
||||
descNearest.minFilter = TextureFilter::NEAREST;
|
||||
descNearest.mipFilter = TextureFilter::NEAREST;
|
||||
descNearest.wrapU = TextureAddressMode::CLAMP_TO_EDGE;
|
||||
descNearest.wrapV = TextureAddressMode::CLAMP_TO_EDGE;
|
||||
draw2DSamplerNearest_ = draw_->CreateSamplerState(descNearest);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *verts, int vertexCount, bool linearFilter, RasterChannel channel) {
|
||||
using namespace Draw;
|
||||
|
||||
if (!draw2DPipelineColor_) {
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
Ensure2DResources();
|
||||
|
||||
const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc();
|
||||
|
||||
if (!draw2DPipelineColor_) {
|
||||
char *fsCode = new char[4000];
|
||||
char *fsDepthCode = new char[4000];
|
||||
char *vsCode = new char[4000];
|
||||
GenerateDraw2DFs(fsCode, shaderLanguageDesc);
|
||||
GenerateDraw2DDepthFs(fsDepthCode, shaderLanguageDesc);
|
||||
GenerateDraw2DVS(vsCode, shaderLanguageDesc);
|
||||
|
||||
draw2DFs_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsCode, strlen(fsCode), "draw2d_fs");
|
||||
draw2DVs_ = draw_->CreateShaderModule(ShaderStage::Vertex, shaderLanguageDesc.shaderLanguage, (const uint8_t *)vsCode, strlen(vsCode), "draw2d_vs");
|
||||
|
||||
_assert_(draw2DFs_ && draw2DVs_);
|
||||
_assert_(draw2DFs_);
|
||||
|
||||
if (draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
|
||||
draw2DFsDepth_ = draw_->CreateShaderModule(ShaderStage::Fragment, shaderLanguageDesc.shaderLanguage, (const uint8_t *)fsDepthCode, strlen(fsDepthCode), "draw2d_depth_fs");
|
||||
@@ -94,7 +125,8 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver
|
||||
draw2DFsDepth_ = nullptr;
|
||||
}
|
||||
|
||||
InputLayoutDesc desc = {
|
||||
// verts have positions in 2D clip coordinates.
|
||||
static const InputLayoutDesc desc = {
|
||||
{
|
||||
{ 16, false },
|
||||
},
|
||||
@@ -139,7 +171,6 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver
|
||||
}
|
||||
|
||||
delete[] fsCode;
|
||||
delete[] vsCode;
|
||||
|
||||
rasterNoCull->Release();
|
||||
blendOff->Release();
|
||||
@@ -147,29 +178,20 @@ void FramebufferManagerCommon::DrawStrip2D(Draw::Texture *tex, Draw2DVertex *ver
|
||||
noDepthStencil->Release();
|
||||
depthWriteAlways->Release();
|
||||
inputLayout->Release();
|
||||
|
||||
SamplerStateDesc descLinear{};
|
||||
descLinear.magFilter = TextureFilter::LINEAR;
|
||||
descLinear.minFilter = TextureFilter::LINEAR;
|
||||
descLinear.mipFilter = TextureFilter::LINEAR;
|
||||
descLinear.wrapU = TextureAddressMode::CLAMP_TO_EDGE;
|
||||
descLinear.wrapV = TextureAddressMode::CLAMP_TO_EDGE;
|
||||
draw2DSamplerLinear_= draw_->CreateSamplerState(descLinear);
|
||||
|
||||
SamplerStateDesc descNearest{};
|
||||
descLinear.magFilter = TextureFilter::NEAREST;
|
||||
descLinear.minFilter = TextureFilter::NEAREST;
|
||||
descLinear.mipFilter = TextureFilter::NEAREST;
|
||||
descLinear.wrapU = TextureAddressMode::CLAMP_TO_EDGE;
|
||||
descLinear.wrapV = TextureAddressMode::CLAMP_TO_EDGE;
|
||||
draw2DSamplerNearest_ = draw_->CreateSamplerState(descNearest);
|
||||
}
|
||||
|
||||
if (channel == RASTER_DEPTH && !draw2DPipelineDepth_) {
|
||||
return;
|
||||
switch (channel) {
|
||||
case RASTER_DEPTH:
|
||||
if (!draw2DPipelineDepth_) {
|
||||
return;
|
||||
}
|
||||
draw_->BindPipeline(draw2DPipelineDepth_);
|
||||
break;
|
||||
case RASTER_COLOR:
|
||||
draw_->BindPipeline(draw2DPipelineColor_);
|
||||
break;
|
||||
}
|
||||
|
||||
draw_->BindPipeline(channel == RASTER_COLOR ? draw2DPipelineColor_ : draw2DPipelineDepth_);
|
||||
if (tex) {
|
||||
draw_->BindTextures(TEX_SLOT_PSP_TEXTURE, 1, &tex);
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ void FramebufferManagerCommon::SetDisplayFramebuffer(u32 framebuf, u32 stride, G
|
||||
GPURecord::NotifyDisplay(framebuf, stride, format);
|
||||
}
|
||||
|
||||
VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) {
|
||||
VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) const {
|
||||
addr &= 0x3FFFFFFF;
|
||||
VirtualFramebuffer *match = nullptr;
|
||||
for (size_t i = 0; i < vfbs_.size(); ++i) {
|
||||
@@ -689,163 +689,6 @@ void FramebufferManagerCommon::NotifyRenderFramebufferUpdated(VirtualFramebuffer
|
||||
}
|
||||
}
|
||||
|
||||
// Can't easily dynamically create these strings, we just pass along the pointer.
|
||||
static const char *reinterpretStrings[3][3] = {
|
||||
{
|
||||
"self_reinterpret_565",
|
||||
"reinterpret_565_to_5551",
|
||||
"reinterpret_565_to_4444",
|
||||
},
|
||||
{
|
||||
"reinterpret_5551_to_565",
|
||||
"self_reinterpret_5551",
|
||||
"reinterpret_5551_to_4444",
|
||||
},
|
||||
{
|
||||
"reinterpret_4444_to_565",
|
||||
"reinterpret_4444_to_5551",
|
||||
"self_reinterpret_4444",
|
||||
},
|
||||
};
|
||||
|
||||
void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat) {
|
||||
if (!useBufferedRendering_ || !vfb->fbo) {
|
||||
return;
|
||||
}
|
||||
|
||||
_assert_(newFormat != oldFormat);
|
||||
// The caller is responsible for updating the format.
|
||||
_assert_(newFormat == vfb->format);
|
||||
|
||||
ShaderLanguage lang = draw_->GetShaderLanguageDesc().shaderLanguage;
|
||||
|
||||
// Copy image required for now, might get rid of this later.
|
||||
bool doReinterpret = PSP_CoreParameter().compat.flags().ReinterpretFramebuffers &&
|
||||
(lang == HLSL_D3D11 || lang == GLSL_VULKAN || lang == GLSL_3xx) &&
|
||||
draw_->GetDeviceCaps().framebufferCopySupported;
|
||||
|
||||
if (!doReinterpret) {
|
||||
// Fake reinterpret - just clear the way we always did on Vulkan. Just clear color and stencil.
|
||||
if (oldFormat == GE_FORMAT_565) {
|
||||
// We have to bind here instead of clear, since it can be that no framebuffer is bound.
|
||||
// The backend can sometimes directly optimize it to a clear.
|
||||
|
||||
// Games that are marked as doing reinterpret just ignore this - better to keep the data than to clear.
|
||||
// Fixes #13717.
|
||||
if (!PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && !PSP_CoreParameter().compat.flags().BlueToAlpha) {
|
||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "FakeReinterpret");
|
||||
// Need to dirty anything that has command buffer dynamic state, in case we started a new pass above.
|
||||
// Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager.
|
||||
gstate_c.Dirty(DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE);
|
||||
|
||||
if (currentRenderVfb_ != vfb) {
|
||||
// In case ReinterpretFramebuffer was called from the texture manager.
|
||||
draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After FakeReinterpret");
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We only reinterpret between 16 - bit formats, for now.
|
||||
if (!IsGeBufferFormat16BitColor(oldFormat) || !IsGeBufferFormat16BitColor(newFormat)) {
|
||||
// 16->32 and 32->16 will require some more specialized shaders.
|
||||
return;
|
||||
}
|
||||
|
||||
char *vsCode = nullptr;
|
||||
char *fsCode = nullptr;
|
||||
|
||||
if (!reinterpretVS_) {
|
||||
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_);
|
||||
}
|
||||
|
||||
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];
|
||||
if (!pipeline) {
|
||||
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);
|
||||
|
||||
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.
|
||||
Draw::Framebuffer *temp = GetTempFBO(TempFBO::REINTERPRET, vfb->renderWidth, vfb->renderHeight);
|
||||
|
||||
// Ideally on Vulkan this should be using the original framebuffer as an input attachment, allowing it to read from
|
||||
// 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();
|
||||
|
||||
// Unbind.
|
||||
draw_->BindTexture(0, nullptr);
|
||||
|
||||
shaderManager_->DirtyLastShader();
|
||||
textureCache_->ForgetLastTexture();
|
||||
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
|
||||
|
||||
if (currentRenderVfb_ != vfb) {
|
||||
// In case ReinterpretFramebuffer was called from the texture manager.
|
||||
draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After reinterpret");
|
||||
}
|
||||
delete[] vsCode;
|
||||
delete[] fsCode;
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
|
||||
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
|
||||
ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height);
|
||||
@@ -2480,7 +2323,7 @@ void FramebufferManagerCommon::RebindFramebuffer(const char *tag) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<FramebufferInfo> FramebufferManagerCommon::GetFramebufferList() {
|
||||
std::vector<FramebufferInfo> FramebufferManagerCommon::GetFramebufferList() const {
|
||||
std::vector<FramebufferInfo> list;
|
||||
|
||||
for (size_t i = 0; i < vfbs_.size(); ++i) {
|
||||
|
||||
@@ -249,7 +249,7 @@ public:
|
||||
}
|
||||
}
|
||||
void RebindFramebuffer(const char *tag);
|
||||
std::vector<FramebufferInfo> GetFramebufferList();
|
||||
std::vector<FramebufferInfo> GetFramebufferList() const;
|
||||
|
||||
void CopyDisplayToOutput(bool reallyDirty);
|
||||
|
||||
@@ -276,25 +276,25 @@ public:
|
||||
|
||||
size_t NumVFBs() const { return vfbs_.size(); }
|
||||
|
||||
u32 PrevDisplayFramebufAddr() {
|
||||
u32 PrevDisplayFramebufAddr() const {
|
||||
return prevDisplayFramebuf_ ? prevDisplayFramebuf_->fb_address : 0;
|
||||
}
|
||||
u32 DisplayFramebufAddr() {
|
||||
u32 DisplayFramebufAddr() const {
|
||||
return displayFramebuf_ ? displayFramebuf_->fb_address : 0;
|
||||
}
|
||||
|
||||
u32 DisplayFramebufStride() {
|
||||
u32 DisplayFramebufStride() const {
|
||||
return displayFramebuf_ ? displayStride_ : 0;
|
||||
}
|
||||
GEBufferFormat DisplayFramebufFormat() {
|
||||
GEBufferFormat DisplayFramebufFormat() const {
|
||||
return displayFramebuf_ ? displayFormat_ : GE_FORMAT_INVALID;
|
||||
}
|
||||
|
||||
bool UseBufferedRendering() {
|
||||
bool UseBufferedRendering() const {
|
||||
return useBufferedRendering_;
|
||||
}
|
||||
|
||||
bool MayIntersectFramebuffer(u32 start) {
|
||||
bool MayIntersectFramebuffer(u32 start) const {
|
||||
// Clear the cache/kernel bits.
|
||||
start = start & 0x3FFFFFFF;
|
||||
// Most games only have two framebuffers at the start.
|
||||
@@ -308,8 +308,8 @@ public:
|
||||
return currentRenderVfb_;
|
||||
}
|
||||
// TODO: Break out into some form of FBO manager
|
||||
VirtualFramebuffer *GetVFBAt(u32 addr);
|
||||
VirtualFramebuffer *GetDisplayVFB() {
|
||||
VirtualFramebuffer *GetVFBAt(u32 addr) const;
|
||||
VirtualFramebuffer *GetDisplayVFB() const {
|
||||
return GetVFBAt(displayFramebufPtr_);
|
||||
}
|
||||
|
||||
@@ -349,7 +349,7 @@ public:
|
||||
virtual bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer);
|
||||
virtual bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
|
||||
|
||||
const std::vector<VirtualFramebuffer *> &Framebuffers() {
|
||||
const std::vector<VirtualFramebuffer *> &Framebuffers() const {
|
||||
return vfbs_;
|
||||
}
|
||||
void ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat);
|
||||
@@ -361,6 +361,7 @@ protected:
|
||||
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, RasterChannel channel);
|
||||
void Ensure2DResources();
|
||||
|
||||
bool UpdateSize();
|
||||
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
#include "Common/GPU/ShaderWriter.h"
|
||||
#include "Common/Log.h"
|
||||
#include "Common/GPU/thin3d.h"
|
||||
#include "Core/System.h"
|
||||
#include "GPU/Common/ReinterpretFramebuffer.h"
|
||||
#include "GPU/Common/FramebufferManagerCommon.h"
|
||||
#include "GPU/Common/TextureCacheCommon.h"
|
||||
|
||||
static const VaryingDef varyings[1] = {
|
||||
{ "vec2", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" },
|
||||
@@ -17,12 +20,10 @@ 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.
|
||||
bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang) {
|
||||
if (!lang.bitwiseOps) {
|
||||
return false;
|
||||
}
|
||||
void GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang) {
|
||||
_assert_(lang.bitwiseOps);
|
||||
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment, nullptr, 0);
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Fragment);
|
||||
|
||||
writer.HighPrecisionFloat();
|
||||
|
||||
@@ -69,24 +70,175 @@ bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBuff
|
||||
}
|
||||
|
||||
writer.EndFSMain("outColor", FSFLAG_NONE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
if (!lang.bitwiseOps) {
|
||||
return false;
|
||||
}
|
||||
ShaderWriter writer(buffer, lang, ShaderStage::Vertex, nullptr, 0);
|
||||
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");
|
||||
if (strlen(lang.viewportYSign)) {
|
||||
writer.F(" y *= %s1.0;\n", lang.viewportYSign);
|
||||
}
|
||||
writer.C(" gl_Position = vec4(x, y, 0.0, 1.0);\n");
|
||||
writer.EndVSMain(varyings);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Can't easily dynamically create these strings, we just pass along the pointer.
|
||||
static const char *reinterpretStrings[3][3] = {
|
||||
{
|
||||
"self_reinterpret_565",
|
||||
"reinterpret_565_to_5551",
|
||||
"reinterpret_565_to_4444",
|
||||
},
|
||||
{
|
||||
"reinterpret_5551_to_565",
|
||||
"self_reinterpret_5551",
|
||||
"reinterpret_5551_to_4444",
|
||||
},
|
||||
{
|
||||
"reinterpret_4444_to_565",
|
||||
"reinterpret_4444_to_5551",
|
||||
"self_reinterpret_4444",
|
||||
},
|
||||
};
|
||||
|
||||
void FramebufferManagerCommon::ReinterpretFramebuffer(VirtualFramebuffer *vfb, GEBufferFormat oldFormat, GEBufferFormat newFormat) {
|
||||
if (!useBufferedRendering_ || !vfb->fbo) {
|
||||
return;
|
||||
}
|
||||
|
||||
_assert_(newFormat != oldFormat);
|
||||
// The caller is responsible for updating the format.
|
||||
_assert_(newFormat == vfb->format);
|
||||
|
||||
ShaderLanguage lang = draw_->GetShaderLanguageDesc().shaderLanguage;
|
||||
|
||||
// Copy image required for now, might get rid of this later.
|
||||
bool doReinterpret = PSP_CoreParameter().compat.flags().ReinterpretFramebuffers &&
|
||||
(lang == HLSL_D3D11 || lang == GLSL_VULKAN || lang == GLSL_3xx) &&
|
||||
draw_->GetDeviceCaps().framebufferCopySupported;
|
||||
|
||||
if (!doReinterpret) {
|
||||
// Fake reinterpret - just clear the way we always did on Vulkan. Just clear color and stencil.
|
||||
if (oldFormat == GE_FORMAT_565) {
|
||||
// We have to bind here instead of clear, since it can be that no framebuffer is bound.
|
||||
// The backend can sometimes directly optimize it to a clear.
|
||||
|
||||
// Games that are marked as doing reinterpret just ignore this - better to keep the data than to clear.
|
||||
// Fixes #13717.
|
||||
if (!PSP_CoreParameter().compat.flags().ReinterpretFramebuffers && !PSP_CoreParameter().compat.flags().BlueToAlpha) {
|
||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "FakeReinterpret");
|
||||
// Need to dirty anything that has command buffer dynamic state, in case we started a new pass above.
|
||||
// Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager.
|
||||
gstate_c.Dirty(DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE);
|
||||
|
||||
if (currentRenderVfb_ != vfb) {
|
||||
// In case ReinterpretFramebuffer was called from the texture manager.
|
||||
draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After FakeReinterpret");
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// We only reinterpret between 16 - bit formats, for now.
|
||||
if (!IsGeBufferFormat16BitColor(oldFormat) || !IsGeBufferFormat16BitColor(newFormat)) {
|
||||
// 16->32 and 32->16 will require some more specialized shaders.
|
||||
return;
|
||||
}
|
||||
|
||||
char *vsCode = nullptr;
|
||||
char *fsCode = nullptr;
|
||||
|
||||
if (!reinterpretVS_) {
|
||||
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_);
|
||||
}
|
||||
|
||||
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];
|
||||
if (!pipeline) {
|
||||
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);
|
||||
|
||||
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.
|
||||
Draw::Framebuffer *temp = GetTempFBO(TempFBO::REINTERPRET, vfb->renderWidth, vfb->renderHeight);
|
||||
|
||||
// Ideally on Vulkan this should be using the original framebuffer as an input attachment, allowing it to read from
|
||||
// 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();
|
||||
|
||||
// Unbind.
|
||||
draw_->BindTexture(0, nullptr);
|
||||
|
||||
shaderManager_->DirtyLastShader();
|
||||
textureCache_->ForgetLastTexture();
|
||||
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
|
||||
|
||||
if (currentRenderVfb_ != vfb) {
|
||||
// In case ReinterpretFramebuffer was called from the texture manager.
|
||||
draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "After reinterpret");
|
||||
}
|
||||
delete[] vsCode;
|
||||
delete[] fsCode;
|
||||
}
|
||||
@@ -4,8 +4,8 @@
|
||||
#include "GPU/GPUCommon.h"
|
||||
#include "Common/GPU/ShaderWriter.h"
|
||||
|
||||
bool GenerateReinterpretFragmentShader(char *buffer, GEBufferFormat from, GEBufferFormat to, const ShaderLanguageDesc &lang);
|
||||
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.
|
||||
bool GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang);
|
||||
void GenerateReinterpretVertexShader(char *buffer, const ShaderLanguageDesc &lang);
|
||||
@@ -123,7 +123,6 @@ void GenerateStencilVs(char *buffer, const ShaderLanguageDesc &lang) {
|
||||
writer.C(" v_texcoord = a_position * 2.0;\n"); // yes, this should be right. Should be 2.0 in the far corners.
|
||||
}
|
||||
writer.C(" gl_Position = vec4(v_texcoord * 2.0 - vec2(1.0, 1.0), 0.0, 1.0);\n");
|
||||
writer.F(" gl_Position.y *= %s1.0;\n", lang.viewportYSign);
|
||||
|
||||
writer.EndVSMain(varyings);
|
||||
}
|
||||
|
||||
@@ -20,74 +20,14 @@
|
||||
#include <D3Dcompiler.h>
|
||||
|
||||
#include "Common/Common.h"
|
||||
#include "Common/Data/Convert/ColorConv.h"
|
||||
#include "Common/GPU/thin3d.h"
|
||||
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/Debugger/Stepping.h"
|
||||
#include "GPU/Common/FramebufferManagerCommon.h"
|
||||
#include "GPU/Common/PresentationCommon.h"
|
||||
#include "GPU/Common/TextureDecoder.h"
|
||||
#include "GPU/D3D11/FramebufferManagerD3D11.h"
|
||||
#include "GPU/D3D11/ShaderManagerD3D11.h"
|
||||
#include "GPU/D3D11/TextureCacheD3D11.h"
|
||||
#include "GPU/D3D11/DrawEngineD3D11.h"
|
||||
|
||||
#ifdef _M_SSE
|
||||
#include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw)
|
||||
: FramebufferManagerCommon(draw) {
|
||||
device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE);
|
||||
context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT);
|
||||
featureLevel_ = (D3D_FEATURE_LEVEL)draw->GetNativeObject(Draw::NativeObject::FEATURE_LEVEL);
|
||||
|
||||
presentation_->SetLanguage(HLSL_D3D11);
|
||||
preferredPixelsFormat_ = Draw::DataFormat::B8G8R8A8_UNORM;
|
||||
}
|
||||
|
||||
static void CopyPixelDepthOnly(u32 *dstp, const u32 *srcp, size_t c) {
|
||||
size_t x = 0;
|
||||
|
||||
#ifdef _M_SSE
|
||||
size_t sseSize = (c / 4) * 4;
|
||||
const __m128i srcMask = _mm_set1_epi32(0x00FFFFFF);
|
||||
const __m128i dstMask = _mm_set1_epi32(0xFF000000);
|
||||
__m128i *dst = (__m128i *)dstp;
|
||||
const __m128i *src = (const __m128i *)srcp;
|
||||
|
||||
for (; x < sseSize; x += 4) {
|
||||
const __m128i bits24 = _mm_and_si128(_mm_load_si128(src), srcMask);
|
||||
const __m128i bits8 = _mm_and_si128(_mm_load_si128(dst), dstMask);
|
||||
_mm_store_si128(dst, _mm_or_si128(bits24, bits8));
|
||||
dst++;
|
||||
src++;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy the remaining pixels that didn't fit in SSE.
|
||||
for (; x < c; ++x) {
|
||||
memcpy(dstp + x, srcp + x, 3);
|
||||
}
|
||||
}
|
||||
|
||||
// Nobody calls this yet.
|
||||
void FramebufferManagerD3D11::PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h) {
|
||||
if (!vfb->fbo) {
|
||||
ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackDepthbuffer: vfb->fbo == 0");
|
||||
return;
|
||||
}
|
||||
|
||||
const u32 z_address = vfb->z_address;
|
||||
// TODO
|
||||
}
|
||||
|
||||
void FramebufferManagerD3D11::EndFrame() {
|
||||
}
|
||||
@@ -34,13 +34,4 @@ class ShaderManagerD3D11;
|
||||
class FramebufferManagerD3D11 : public FramebufferManagerCommon {
|
||||
public:
|
||||
FramebufferManagerD3D11(Draw::DrawContext *draw);
|
||||
|
||||
void EndFrame();
|
||||
|
||||
private:
|
||||
void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h);
|
||||
|
||||
ID3D11Device *device_;
|
||||
ID3D11DeviceContext *context_;
|
||||
D3D_FEATURE_LEVEL featureLevel_;
|
||||
};
|
||||
@@ -232,7 +232,6 @@ void GPU_D3D11::BeginFrame() {
|
||||
|
||||
textureCacheD3D11_->StartFrame();
|
||||
drawEngine_.BeginFrame();
|
||||
// fragmentTestCache_.Decimate();
|
||||
|
||||
shaderManagerD3D11_->DirtyLastShader();
|
||||
|
||||
@@ -255,9 +254,7 @@ void GPU_D3D11::CopyDisplayToOutput(bool reallyDirty) {
|
||||
context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], blendColor, 0xFFFFFFFF);
|
||||
|
||||
framebufferManagerD3D11_->CopyDisplayToOutput(reallyDirty);
|
||||
framebufferManagerD3D11_->EndFrame();
|
||||
|
||||
// shaderManager_->EndFrame();
|
||||
shaderManagerD3D11_->DirtyLastShader();
|
||||
|
||||
gstate_c.Dirty(DIRTY_TEXTURE_IMAGE);
|
||||
|
||||
@@ -280,7 +280,6 @@ void GPU_DX9::ReapplyGfxState() {
|
||||
void GPU_DX9::BeginFrame() {
|
||||
textureCacheDX9_->StartFrame();
|
||||
drawEngine_.BeginFrame();
|
||||
// fragmentTestCache_.Decimate();
|
||||
|
||||
GPUCommon::BeginFrame();
|
||||
shaderManagerDX9_->DirtyShader();
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
#include "GPU/Debugger/Stepping.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
#include "GPU/GLES/DrawEngineGLES.h"
|
||||
#include "GPU/GLES/ShaderManagerGLES.h"
|
||||
|
||||
FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render) :
|
||||
|
||||
@@ -61,6 +61,4 @@ private:
|
||||
int u_depthDownloadFactor = -1;
|
||||
int u_depthDownloadShift = -1;
|
||||
int u_depthDownloadTo8 = -1;
|
||||
|
||||
DrawEngineGLES *drawEngineGL_ = nullptr;
|
||||
};
|
||||
+1
-1
@@ -2969,7 +2969,7 @@ bool GPUCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) {
|
||||
return framebufferManager_ ? framebufferManager_->GetOutputFramebuffer(buffer) : false;
|
||||
}
|
||||
|
||||
std::vector<FramebufferInfo> GPUCommon::GetFramebufferList() {
|
||||
std::vector<FramebufferInfo> GPUCommon::GetFramebufferList() const {
|
||||
return framebufferManager_->GetFramebufferList();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -230,11 +230,11 @@ public:
|
||||
const std::list<int>& GetDisplayLists() override {
|
||||
return dlQueue;
|
||||
}
|
||||
std::vector<FramebufferInfo> GetFramebufferList() override;
|
||||
std::vector<FramebufferInfo> GetFramebufferList() const override;
|
||||
void ClearShaderCache() override {}
|
||||
void CleanupBeforeUI() override {}
|
||||
|
||||
s64 GetListTicks(int listid) override {
|
||||
s64 GetListTicks(int listid) const override {
|
||||
if (listid >= 0 && listid < DisplayListMaxCount) {
|
||||
return dls[listid].waitTicks;
|
||||
}
|
||||
|
||||
+2
-2
@@ -253,8 +253,8 @@ public:
|
||||
virtual void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) = 0;
|
||||
virtual const std::list<int>& GetDisplayLists() = 0;
|
||||
// TODO: Currently Qt only, needs to be cleaned up.
|
||||
virtual std::vector<FramebufferInfo> GetFramebufferList() = 0;
|
||||
virtual s64 GetListTicks(int listid) = 0;
|
||||
virtual std::vector<FramebufferInfo> GetFramebufferList() const = 0;
|
||||
virtual s64 GetListTicks(int listid) const = 0;
|
||||
|
||||
// For debugging. The IDs returned are opaque, do not poke in them or display them in any way.
|
||||
virtual std::vector<std::string> DebugGetShaderIDs(DebugShaderType type) = 0;
|
||||
|
||||
@@ -181,19 +181,23 @@ bool TestReinterpretShaders() {
|
||||
bool failed = false;
|
||||
|
||||
for (int k = 0; k < ARRAY_SIZE(languages); k++) {
|
||||
printf("=== %s ===\n\n", ShaderLanguageToString(languages[k]));
|
||||
|
||||
ShaderLanguageDesc desc(languages[k]);
|
||||
if (!GenerateReinterpretVertexShader(buffer, desc)) {
|
||||
printf("Failed!\n%s\n", buffer);
|
||||
|
||||
// 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 {
|
||||
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);
|
||||
}
|
||||
//printf("===\n%s\n===\n", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,23 +205,25 @@ bool TestReinterpretShaders() {
|
||||
printf("=== %s ===\n\n", ShaderLanguageToString(languages[k]));
|
||||
|
||||
ShaderLanguageDesc desc(languages[k]);
|
||||
|
||||
// These require bitwise operations.
|
||||
if (!desc.bitwiseOps) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string errorMessage;
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (int j = 0; j < 3; j++) {
|
||||
if (i == j)
|
||||
continue; // useless shader!
|
||||
if (!GenerateReinterpretFragmentShader(buffer, fmts[i], fmts[j], desc)) {
|
||||
printf("Failed!\n%s\n", buffer);
|
||||
GenerateReinterpretFragmentShader(buffer, fmts[i], fmts[j], desc);
|
||||
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;
|
||||
return false;
|
||||
} else {
|
||||
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;
|
||||
return false;
|
||||
} else {
|
||||
printf("===\n%s\n===\n", buffer);
|
||||
}
|
||||
printf("===\n%s\n===\n", buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user