mirror of
https://github.com/libretro/parallel-gx1.git
synced 2026-11-07 04:26:01 -10:00
D3D12: the XFB texture handed to the frontend in place
As on Direct3D 11 and Vulkan, a picture whose draw would be a plain copy is not drawn: the XFB texture goes over in the state the frontend reads it in, with the fence its work completes on for version 2, and is read where it is; version 1 copies it inside video_refresh, which spares the draw in front of that copy. Nothing is created for it. The texture is not one of the output's, so no sync index is waited on. Version 2 keeps reading it in the frames that repeat it, so before each repeat the output puts it back in that state if the core used it in another one meanwhile.
This commit is contained in:
1 parent
28b795b859
commit
6a6d63a114
4 files changed
+53
-3
No files matched your search
@@ -146,9 +146,16 @@ bool DX11Output::PresentTexture(const AbstractTexture* texture, u32 width, u32 h
|
||||
}
|
||||
|
||||
DX12Output::DX12Output(retro_hw_render_interface_d3d12* iface, u32 width, u32 height)
|
||||
: m_iface(iface), m_width(width), m_height(height), m_current(0),
|
||||
: m_direct(nullptr), m_iface(iface), m_width(width), m_height(height), m_current(0),
|
||||
m_v2(iface->interface_version >= RETRO_HW_RENDER_INTERFACE_D3D12_VERSION_2)
|
||||
{
|
||||
s_active = this;
|
||||
}
|
||||
|
||||
DX12Output::~DX12Output()
|
||||
{
|
||||
if (s_active == this)
|
||||
s_active = nullptr;
|
||||
}
|
||||
|
||||
bool DX12Output::Create()
|
||||
@@ -191,7 +198,33 @@ AbstractFramebuffer* DX12Output::Acquire()
|
||||
|
||||
void DX12Output::Present()
|
||||
{
|
||||
DX12::DXTexture* texture = m_textures[m_current].get();
|
||||
m_direct = nullptr;
|
||||
Hand(m_textures[m_current].get(), m_width, m_height);
|
||||
}
|
||||
|
||||
bool DX12Output::PresentTexture(const AbstractTexture* texture, u32 width, u32 height)
|
||||
{
|
||||
/* version 1 copies it inside video_refresh, version 2 reads it where it
|
||||
* is; neither waits on a sync index, as none of the output's textures
|
||||
* is drawn into */
|
||||
m_direct = const_cast<DX12::DXTexture*>(static_cast<const DX12::DXTexture*>(texture));
|
||||
Hand(m_direct, width, height);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DX12Output::Repeat()
|
||||
{
|
||||
/* version 2 reads the texture again: back to the state it reads it in
|
||||
* if the core used it in another one meanwhile, a copy's source say,
|
||||
* ahead of the frontend's next frame on the queue */
|
||||
if (!m_v2 || !m_direct || m_direct->GetState() == m_iface->required_state)
|
||||
return;
|
||||
m_direct->TransitionToState(m_iface->required_state);
|
||||
DX12::Gfx::GetInstance()->ExecuteCommandList(false);
|
||||
}
|
||||
|
||||
void DX12Output::Hand(DX12::DXTexture* texture, u32 width, u32 height)
|
||||
{
|
||||
u64 fence_value;
|
||||
|
||||
texture->TransitionToState(m_iface->required_state);
|
||||
@@ -209,7 +242,7 @@ void DX12Output::Present()
|
||||
m_iface->set_texture(m_iface->handle, texture->GetResource(), DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
}
|
||||
|
||||
video_cb(RETRO_HW_FRAME_BUFFER_VALID, m_width, m_height, 0);
|
||||
video_cb(RETRO_HW_FRAME_BUFFER_VALID, width, height, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -55,17 +55,26 @@ class DX12Output final : public FrameOutput
|
||||
{
|
||||
public:
|
||||
DX12Output(retro_hw_render_interface_d3d12* iface, u32 width, u32 height);
|
||||
~DX12Output() override;
|
||||
bool Create();
|
||||
|
||||
AbstractFramebuffer* Acquire() override;
|
||||
void Present() override;
|
||||
bool PresentTexture(const AbstractTexture* texture, u32 width, u32 height) override;
|
||||
void Repeat() override;
|
||||
u32 GetWidth() const override { return m_width; }
|
||||
u32 GetHeight() const override { return m_height; }
|
||||
AbstractTextureFormat GetFormat() const override { return AbstractTextureFormat::RGBA8; }
|
||||
|
||||
private:
|
||||
void Hand(DX12::DXTexture* texture, u32 width, u32 height);
|
||||
|
||||
std::unique_ptr<DX12::DXTexture> m_textures[OUTPUT_MAX_SLOTS];
|
||||
std::unique_ptr<DX12::DXFramebuffer> m_framebuffers[OUTPUT_MAX_SLOTS];
|
||||
/* A texture handed on where it is: version 2 reads it until another
|
||||
* picture is handed on, so it is kept in the state the frontend reads
|
||||
* it in meanwhile. */
|
||||
DX12::DXTexture* m_direct;
|
||||
retro_hw_render_interface_d3d12* m_iface;
|
||||
u32 m_width;
|
||||
u32 m_height;
|
||||
|
||||
@@ -385,6 +385,13 @@ void Gfx::PresentBackbuffer()
|
||||
m_output->Present();
|
||||
}
|
||||
|
||||
bool Gfx::PresentTexture(const AbstractTexture* texture, u32 width, u32 height)
|
||||
{
|
||||
/* the output leaves the texture in the state the frontend reads it in
|
||||
* and submits the command list itself */
|
||||
return m_output->PresentTexture(texture, width, height);
|
||||
}
|
||||
|
||||
SurfaceInfo Gfx::GetSurfaceInfo() const
|
||||
{
|
||||
return {m_output ? m_output->GetWidth() : 0, m_output ? m_output->GetHeight() : 0,
|
||||
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
u32 groupsize_z, u32 groups_x, u32 groups_y, u32 groups_z) override;
|
||||
bool BindBackbuffer(const ClearColor& clear_color = {}) override;
|
||||
void PresentBackbuffer() override;
|
||||
bool PresentTexture(const AbstractTexture* texture, u32 width, u32 height) override;
|
||||
|
||||
SurfaceInfo GetSurfaceInfo() const override;
|
||||
|
||||
|
||||
Reference in new issue
Block a user