mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 13:27:45 -07:00
Merge pull request #12004 from TellowKrinkle/MetalMultiTarget
VideoBackends:Metal: Multi render target support
This commit is contained in:
commit
3e9c9a3e8d
@ -94,12 +94,12 @@ Metal::Gfx::CreateStagingTexture(StagingTextureType type, const TextureConfig& c
|
|||||||
|
|
||||||
std::unique_ptr<AbstractFramebuffer>
|
std::unique_ptr<AbstractFramebuffer>
|
||||||
Metal::Gfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
|
Metal::Gfx::CreateFramebuffer(AbstractTexture* color_attachment, AbstractTexture* depth_attachment,
|
||||||
std::vector<AbstractTexture*>)
|
std::vector<AbstractTexture*> additional_color_attachments)
|
||||||
{
|
{
|
||||||
AbstractTexture* const either_attachment = color_attachment ? color_attachment : depth_attachment;
|
AbstractTexture* const either_attachment = color_attachment ? color_attachment : depth_attachment;
|
||||||
return std::make_unique<Framebuffer>(
|
return std::make_unique<Framebuffer>(
|
||||||
color_attachment, depth_attachment, either_attachment->GetWidth(),
|
color_attachment, depth_attachment, std::move(additional_color_attachments),
|
||||||
either_attachment->GetHeight(), either_attachment->GetLayers(),
|
either_attachment->GetWidth(), either_attachment->GetHeight(), either_attachment->GetLayers(),
|
||||||
either_attachment->GetSamples());
|
either_attachment->GetSamples());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -437,7 +437,7 @@ void Metal::Gfx::BindBackbuffer(const ClearColor& clear_color)
|
|||||||
CheckForSurfaceChange();
|
CheckForSurfaceChange();
|
||||||
CheckForSurfaceResize();
|
CheckForSurfaceResize();
|
||||||
m_drawable = MRCRetain([m_layer nextDrawable]);
|
m_drawable = MRCRetain([m_layer nextDrawable]);
|
||||||
m_bb_texture->SetMTLTexture(MRCRetain([m_drawable texture]));
|
m_backbuffer->UpdateBackbufferTexture([m_drawable texture]);
|
||||||
SetAndClearFramebuffer(m_backbuffer.get(), clear_color);
|
SetAndClearFramebuffer(m_backbuffer.get(), clear_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -460,7 +460,7 @@ void Metal::Gfx::PresentBackbuffer()
|
|||||||
else
|
else
|
||||||
[g_state_tracker->GetRenderCmdBuf()
|
[g_state_tracker->GetRenderCmdBuf()
|
||||||
addScheduledHandler:[drawable = std::move(m_drawable)](id) { [drawable present]; }];
|
addScheduledHandler:[drawable = std::move(m_drawable)](id) { [drawable present]; }];
|
||||||
m_bb_texture->SetMTLTexture(nullptr);
|
m_backbuffer->UpdateBackbufferTexture(nullptr);
|
||||||
m_drawable = nullptr;
|
m_drawable = nullptr;
|
||||||
}
|
}
|
||||||
g_state_tracker->FlushEncoders();
|
g_state_tracker->FlushEncoders();
|
||||||
@ -491,8 +491,8 @@ void Metal::Gfx::SetupSurface()
|
|||||||
TextureConfig cfg(info.width, info.height, 1, 1, 1, info.format,
|
TextureConfig cfg(info.width, info.height, 1, 1, 1, info.format,
|
||||||
AbstractTextureFlag_RenderTarget);
|
AbstractTextureFlag_RenderTarget);
|
||||||
m_bb_texture = std::make_unique<Texture>(nullptr, cfg);
|
m_bb_texture = std::make_unique<Texture>(nullptr, cfg);
|
||||||
m_backbuffer = std::make_unique<Framebuffer>(m_bb_texture.get(), nullptr, //
|
m_backbuffer = std::make_unique<Framebuffer>(
|
||||||
info.width, info.height, 1, 1);
|
m_bb_texture.get(), nullptr, std::vector<AbstractTexture*>{}, info.width, info.height, 1, 1);
|
||||||
|
|
||||||
if (g_presenter)
|
if (g_presenter)
|
||||||
g_presenter->SetBackbuffer(info);
|
g_presenter->SetBackbuffer(info);
|
||||||
|
@ -313,6 +313,8 @@ public:
|
|||||||
framebuffer.color_texture_format = cfg.framebuffer_state.color_texture_format.Value();
|
framebuffer.color_texture_format = cfg.framebuffer_state.color_texture_format.Value();
|
||||||
framebuffer.depth_texture_format = cfg.framebuffer_state.depth_texture_format.Value();
|
framebuffer.depth_texture_format = cfg.framebuffer_state.depth_texture_format.Value();
|
||||||
framebuffer.samples = cfg.framebuffer_state.samples.Value();
|
framebuffer.samples = cfg.framebuffer_state.samples.Value();
|
||||||
|
framebuffer.additional_color_attachment_count =
|
||||||
|
cfg.framebuffer_state.additional_color_attachment_count.Value();
|
||||||
blend.colorupdate = cfg.blending_state.colorupdate.Value();
|
blend.colorupdate = cfg.blending_state.colorupdate.Value();
|
||||||
blend.alphaupdate = cfg.blending_state.alphaupdate.Value();
|
blend.alphaupdate = cfg.blending_state.alphaupdate.Value();
|
||||||
if (cfg.blending_state.blendenable)
|
if (cfg.blending_state.blendenable)
|
||||||
@ -426,6 +428,11 @@ public:
|
|||||||
}
|
}
|
||||||
[desc setRasterSampleCount:fs.samples];
|
[desc setRasterSampleCount:fs.samples];
|
||||||
[color0 setPixelFormat:Util::FromAbstract(fs.color_texture_format)];
|
[color0 setPixelFormat:Util::FromAbstract(fs.color_texture_format)];
|
||||||
|
if (u32 cnt = fs.additional_color_attachment_count)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < cnt; i++)
|
||||||
|
[[desc colorAttachments] setObject:color0 atIndexedSubscript:i + 1];
|
||||||
|
}
|
||||||
[desc setDepthAttachmentPixelFormat:Util::FromAbstract(fs.depth_texture_format)];
|
[desc setDepthAttachmentPixelFormat:Util::FromAbstract(fs.depth_texture_format)];
|
||||||
if (Util::HasStencil(fs.depth_texture_format))
|
if (Util::HasStencil(fs.depth_texture_format))
|
||||||
[desc setStencilAttachmentPixelFormat:Util::FromAbstract(fs.depth_texture_format)];
|
[desc setStencilAttachmentPixelFormat:Util::FromAbstract(fs.depth_texture_format)];
|
||||||
|
@ -182,7 +182,6 @@ private:
|
|||||||
MRCOwned<id<MTLCommandBuffer>> m_last_render_cmdbuf;
|
MRCOwned<id<MTLCommandBuffer>> m_last_render_cmdbuf;
|
||||||
MRCOwned<id<MTLRenderCommandEncoder>> m_current_render_encoder;
|
MRCOwned<id<MTLRenderCommandEncoder>> m_current_render_encoder;
|
||||||
MRCOwned<id<MTLComputeCommandEncoder>> m_current_compute_encoder;
|
MRCOwned<id<MTLComputeCommandEncoder>> m_current_compute_encoder;
|
||||||
MRCOwned<MTLRenderPassDescriptor*> m_render_pass_desc[3];
|
|
||||||
MRCOwned<MTLRenderPassDescriptor*> m_resolve_pass_desc;
|
MRCOwned<MTLRenderPassDescriptor*> m_resolve_pass_desc;
|
||||||
Framebuffer* m_current_framebuffer;
|
Framebuffer* m_current_framebuffer;
|
||||||
CPUBuffer m_texture_upload_buffer;
|
CPUBuffer m_texture_upload_buffer;
|
||||||
|
@ -107,12 +107,6 @@ Metal::StateTracker::StateTracker() : m_backref(std::make_shared<Backref>(this))
|
|||||||
{
|
{
|
||||||
m_flags.should_apply_label = true;
|
m_flags.should_apply_label = true;
|
||||||
m_fence = MRCTransfer([g_device newFence]);
|
m_fence = MRCTransfer([g_device newFence]);
|
||||||
for (MRCOwned<MTLRenderPassDescriptor*>& rpdesc : m_render_pass_desc)
|
|
||||||
{
|
|
||||||
rpdesc = MRCTransfer([MTLRenderPassDescriptor new]);
|
|
||||||
[[rpdesc depthAttachment] setStoreAction:MTLStoreActionStore];
|
|
||||||
[[rpdesc stencilAttachment] setStoreAction:MTLStoreActionStore];
|
|
||||||
}
|
|
||||||
m_resolve_pass_desc = MRCTransfer([MTLRenderPassDescriptor new]);
|
m_resolve_pass_desc = MRCTransfer([MTLRenderPassDescriptor new]);
|
||||||
auto color0 = [[m_resolve_pass_desc colorAttachments] objectAtIndexedSubscript:0];
|
auto color0 = [[m_resolve_pass_desc colorAttachments] objectAtIndexedSubscript:0];
|
||||||
[color0 setLoadAction:MTLLoadActionLoad];
|
[color0 setLoadAction:MTLLoadActionLoad];
|
||||||
@ -299,27 +293,8 @@ void Metal::StateTracker::SetCurrentFramebuffer(Framebuffer* framebuffer)
|
|||||||
MTLRenderPassDescriptor* Metal::StateTracker::GetRenderPassDescriptor(Framebuffer* framebuffer,
|
MTLRenderPassDescriptor* Metal::StateTracker::GetRenderPassDescriptor(Framebuffer* framebuffer,
|
||||||
MTLLoadAction load_action)
|
MTLLoadAction load_action)
|
||||||
{
|
{
|
||||||
const AbstractTextureFormat depth_fmt = framebuffer->GetDepthFormat();
|
framebuffer->SetLoadAction(load_action);
|
||||||
MTLRenderPassDescriptor* desc;
|
return framebuffer->PassDesc();
|
||||||
if (depth_fmt == AbstractTextureFormat::Undefined)
|
|
||||||
desc = m_render_pass_desc[0];
|
|
||||||
else if (!Util::HasStencil(depth_fmt))
|
|
||||||
desc = m_render_pass_desc[1];
|
|
||||||
else
|
|
||||||
desc = m_render_pass_desc[2];
|
|
||||||
desc.colorAttachments[0].texture = framebuffer->GetColor();
|
|
||||||
desc.colorAttachments[0].loadAction = load_action;
|
|
||||||
if (depth_fmt != AbstractTextureFormat::Undefined)
|
|
||||||
{
|
|
||||||
desc.depthAttachment.texture = framebuffer->GetDepth();
|
|
||||||
desc.depthAttachment.loadAction = load_action;
|
|
||||||
if (Util::HasStencil(depth_fmt))
|
|
||||||
{
|
|
||||||
desc.stencilAttachment.texture = framebuffer->GetDepth();
|
|
||||||
desc.stencilAttachment.loadAction = load_action;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return desc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metal::StateTracker::BeginClearRenderPass(MTLClearColor color, float depth)
|
void Metal::StateTracker::BeginClearRenderPass(MTLClearColor color, float depth)
|
||||||
@ -328,11 +303,9 @@ void Metal::StateTracker::BeginClearRenderPass(MTLClearColor color, float depth)
|
|||||||
MTLRenderPassDescriptor* desc = GetRenderPassDescriptor(framebuffer, MTLLoadActionClear);
|
MTLRenderPassDescriptor* desc = GetRenderPassDescriptor(framebuffer, MTLLoadActionClear);
|
||||||
desc.colorAttachments[0].clearColor = color;
|
desc.colorAttachments[0].clearColor = color;
|
||||||
if (framebuffer->GetDepthFormat() != AbstractTextureFormat::Undefined)
|
if (framebuffer->GetDepthFormat() != AbstractTextureFormat::Undefined)
|
||||||
{
|
|
||||||
desc.depthAttachment.clearDepth = depth;
|
desc.depthAttachment.clearDepth = depth;
|
||||||
if (Util::HasStencil(framebuffer->GetDepthFormat()))
|
for (size_t i = 0; i < framebuffer->NumAdditionalColorTextures(); i++)
|
||||||
desc.stencilAttachment.clearStencil = 0;
|
desc.colorAttachments[i + 1].clearColor = color;
|
||||||
}
|
|
||||||
BeginRenderPass(desc);
|
BeginRenderPass(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ public:
|
|||||||
u32 layer) override;
|
u32 layer) override;
|
||||||
|
|
||||||
id<MTLTexture> GetMTLTexture() const { return m_tex; }
|
id<MTLTexture> GetMTLTexture() const { return m_tex; }
|
||||||
void SetMTLTexture(MRCOwned<id<MTLTexture>> tex) { m_tex = std::move(tex); }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MRCOwned<id<MTLTexture>> m_tex;
|
MRCOwned<id<MTLTexture>> m_tex;
|
||||||
@ -61,17 +60,30 @@ private:
|
|||||||
class Framebuffer final : public AbstractFramebuffer
|
class Framebuffer final : public AbstractFramebuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Framebuffer(AbstractTexture* color, AbstractTexture* depth, u32 width, u32 height, u32 layers,
|
Framebuffer(AbstractTexture* color, AbstractTexture* depth,
|
||||||
u32 samples);
|
std::vector<AbstractTexture*> additonal_color_textures, //
|
||||||
|
u32 width, u32 height, u32 layers, u32 samples);
|
||||||
~Framebuffer();
|
~Framebuffer();
|
||||||
|
|
||||||
id<MTLTexture> GetColor() const
|
MTLRenderPassDescriptor* PassDesc() const { return m_pass_descriptor; }
|
||||||
|
|
||||||
|
size_t NumAdditionalColorTextures() const { return m_additional_color_textures.size(); }
|
||||||
|
|
||||||
|
void SetLoadAction(MTLLoadAction action)
|
||||||
{
|
{
|
||||||
return static_cast<Texture*>(GetColorAttachment())->GetMTLTexture();
|
if (m_current_load_action != action)
|
||||||
|
ActualSetLoadAction(action);
|
||||||
}
|
}
|
||||||
id<MTLTexture> GetDepth() const
|
|
||||||
|
void UpdateBackbufferTexture(id<MTLTexture> tex)
|
||||||
{
|
{
|
||||||
return static_cast<Texture*>(GetDepthAttachment())->GetMTLTexture();
|
[m_pass_descriptor colorAttachments][0].texture = tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MRCOwned<MTLRenderPassDescriptor*> m_pass_descriptor;
|
||||||
|
std::vector<AbstractTexture*> m_additional_color_textures;
|
||||||
|
MTLLoadAction m_current_load_action = MTLLoadActionLoad;
|
||||||
|
void ActualSetLoadAction(MTLLoadAction action);
|
||||||
};
|
};
|
||||||
} // namespace Metal
|
} // namespace Metal
|
||||||
|
@ -189,13 +189,56 @@ void Metal::StagingTexture::Flush()
|
|||||||
m_wait_buffer = nullptr;
|
m_wait_buffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Metal::Framebuffer::Framebuffer(AbstractTexture* color, AbstractTexture* depth, //
|
static void InitDesc(id desc, AbstractTexture* tex)
|
||||||
|
{
|
||||||
|
[desc setTexture:static_cast<Metal::Texture*>(tex)->GetMTLTexture()];
|
||||||
|
[desc setLoadAction:MTLLoadActionLoad];
|
||||||
|
[desc setStoreAction:MTLStoreActionStore];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void InitStencilDesc(MTLRenderPassStencilAttachmentDescriptor* desc, AbstractTexture* tex)
|
||||||
|
{
|
||||||
|
InitDesc(desc, tex);
|
||||||
|
[desc setClearStencil:0];
|
||||||
|
}
|
||||||
|
|
||||||
|
Metal::Framebuffer::Framebuffer(AbstractTexture* color, AbstractTexture* depth,
|
||||||
|
std::vector<AbstractTexture*> additonal_color_textures, //
|
||||||
u32 width, u32 height, u32 layers, u32 samples)
|
u32 width, u32 height, u32 layers, u32 samples)
|
||||||
: AbstractFramebuffer(color, depth, {},
|
: AbstractFramebuffer(color, depth, {},
|
||||||
color ? color->GetFormat() : AbstractTextureFormat::Undefined, //
|
color ? color->GetFormat() : AbstractTextureFormat::Undefined, //
|
||||||
depth ? depth->GetFormat() : AbstractTextureFormat::Undefined, //
|
depth ? depth->GetFormat() : AbstractTextureFormat::Undefined, //
|
||||||
width, height, layers, samples)
|
width, height, layers, samples),
|
||||||
|
m_additional_color_textures(std::move(additonal_color_textures))
|
||||||
{
|
{
|
||||||
|
m_pass_descriptor = MRCTransfer([MTLRenderPassDescriptor new]);
|
||||||
|
MTLRenderPassDescriptor* desc = m_pass_descriptor;
|
||||||
|
if (color)
|
||||||
|
InitDesc(desc.colorAttachments[0], color);
|
||||||
|
if (depth)
|
||||||
|
{
|
||||||
|
InitDesc(desc.depthAttachment, depth);
|
||||||
|
if (Util::HasStencil(depth->GetFormat()))
|
||||||
|
InitStencilDesc(desc.stencilAttachment, depth);
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < m_additional_color_textures.size(); i++)
|
||||||
|
InitDesc(desc.colorAttachments[i + 1], m_additional_color_textures[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Metal::Framebuffer::~Framebuffer() = default;
|
Metal::Framebuffer::~Framebuffer() = default;
|
||||||
|
|
||||||
|
void Metal::Framebuffer::ActualSetLoadAction(MTLLoadAction action)
|
||||||
|
{
|
||||||
|
m_current_load_action = action;
|
||||||
|
AbstractTextureFormat depth_fmt = GetDepthFormat();
|
||||||
|
MTLRenderPassDescriptor* desc = m_pass_descriptor;
|
||||||
|
desc.colorAttachments[0].loadAction = action;
|
||||||
|
if (depth_fmt != AbstractTextureFormat::Undefined)
|
||||||
|
{
|
||||||
|
desc.depthAttachment.loadAction = action;
|
||||||
|
if (Util::HasStencil(depth_fmt))
|
||||||
|
desc.stencilAttachment.loadAction = action;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < NumAdditionalColorTextures(); i++)
|
||||||
|
desc.colorAttachments[i + 1].loadAction = action;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user