HostDisplay: Use streaming for sw renderer display

This commit is contained in:
Connor McLaughlin
2022-09-11 01:54:01 +10:00
parent c27026aed5
commit 0b3461338c
16 changed files with 495 additions and 541 deletions

View File

@ -103,6 +103,21 @@ void GPU_SW::UpdateSettings()
m_backend.UpdateSettings();
}
HostDisplayTexture* GPU_SW::GetDisplayTexture(u32 width, u32 height, HostDisplayPixelFormat format)
{
if (!m_display_texture || m_display_texture->GetWidth() != width || m_display_texture->GetHeight() != height ||
m_display_texture->GetFormat() != format)
{
g_host_display->ClearDisplayTexture();
m_display_texture.reset();
m_display_texture = g_host_display->CreateTexture(width, height, 1, 1, 1, format, nullptr, 0, true);
if (!m_display_texture)
Log_ErrorPrintf("Failed to create %ux%u %u texture", width, height, static_cast<u32>(format));
}
return m_display_texture.get();
}
template<HostDisplayPixelFormat out_format, typename out_type>
static void CopyOutRow16(const u16* src_ptr, out_type* dst_ptr, u32 width);
@ -240,13 +255,14 @@ void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32 width, u32 height, u32 field
using OutputPixelType = std::conditional_t<
display_format == HostDisplayPixelFormat::RGBA8 || display_format == HostDisplayPixelFormat::BGRA8, u32, u16>;
HostDisplayTexture* texture = GetDisplayTexture(width, height, display_format);
if (!texture)
return;
if (!interlaced)
{
if (!g_host_display->BeginSetDisplayPixels(display_format, width, height, reinterpret_cast<void**>(&dst_ptr),
&dst_stride))
{
if (!texture->BeginUpdate(width, height, reinterpret_cast<void**>(&dst_ptr), &dst_stride))
return;
}
}
else
{
@ -293,13 +309,11 @@ void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32 width, u32 height, u32 field
}
if (!interlaced)
{
g_host_display->EndSetDisplayPixels();
}
texture->EndUpdate(0, 0, width, height);
else
{
g_host_display->SetDisplayPixels(display_format, width, height, m_display_texture_buffer.data(), output_stride);
}
texture->Update(0, 0, width, height, m_display_texture_buffer.data(), output_stride);
g_host_display->SetDisplayTexture(texture->GetHandle(), display_format, width, height, 0, 0, width, height);
}
void GPU_SW::CopyOut15Bit(HostDisplayPixelFormat display_format, u32 src_x, u32 src_y, u32 width, u32 height, u32 field,
@ -334,13 +348,14 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
using OutputPixelType = std::conditional_t<
display_format == HostDisplayPixelFormat::RGBA8 || display_format == HostDisplayPixelFormat::BGRA8, u32, u16>;
HostDisplayTexture* texture = GetDisplayTexture(width, height, display_format);
if (!texture)
return;
if (!interlaced)
{
if (!g_host_display->BeginSetDisplayPixels(display_format, width, height, reinterpret_cast<void**>(&dst_ptr),
&dst_stride))
{
if (!texture->BeginUpdate(width, height, reinterpret_cast<void**>(&dst_ptr), &dst_stride))
return;
}
}
else
{
@ -451,13 +466,11 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
}
if (!interlaced)
{
g_host_display->EndSetDisplayPixels();
}
texture->EndUpdate(0, 0, width, height);
else
{
g_host_display->SetDisplayPixels(display_format, width, height, m_display_texture_buffer.data(), output_stride);
}
texture->Update(0, 0, width, height, m_display_texture_buffer.data(), output_stride);
g_host_display->SetDisplayTexture(texture->GetHandle(), display_format, width, height, 0, 0, width, height);
}
void GPU_SW::CopyOut24Bit(HostDisplayPixelFormat display_format, u32 src_x, u32 src_y, u32 skip_x, u32 width,

View File

@ -55,9 +55,12 @@ protected:
void FillBackendCommandParameters(GPUBackendCommand* cmd) const;
void FillDrawCommand(GPUBackendDrawCommand* cmd, GPURenderCommand rc) const;
HostDisplayTexture* GetDisplayTexture(u32 width, u32 height, HostDisplayPixelFormat format);
HeapArray<u8, GPU_MAX_DISPLAY_WIDTH * GPU_MAX_DISPLAY_HEIGHT * sizeof(u32)> m_display_texture_buffer;
HostDisplayPixelFormat m_16bit_display_format = HostDisplayPixelFormat::RGB565;
HostDisplayPixelFormat m_24bit_display_format = HostDisplayPixelFormat::RGBA8;
std::unique_ptr<HostDisplayTexture> m_display_texture;
GPU_SW_Backend m_backend;
};

View File

@ -20,6 +20,25 @@ std::unique_ptr<HostDisplay> g_host_display;
HostDisplayTexture::~HostDisplayTexture() = default;
bool HostDisplayTexture::BeginUpdate(u32 width, u32 height, void** out_buffer, u32* out_pitch) /* = 0*/
{
return false;
}
void HostDisplayTexture::EndUpdate(u32 x, u32 y, u32 width, u32 height) /* = 0*/ {}
bool HostDisplayTexture::Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch)
{
void* map_ptr;
u32 map_pitch;
if (!BeginUpdate(width, height, &map_ptr, &map_pitch))
return false;
StringUtil::StrideMemCpy(map_ptr, map_pitch, data, pitch, std::min(pitch, map_pitch), height);
EndUpdate(x, y, width, height);
return true;
}
HostDisplay::~HostDisplay() = default;
RenderAPI HostDisplay::GetPreferredAPI()
@ -124,36 +143,6 @@ u32 HostDisplay::GetDisplayPixelFormatSize(HostDisplayPixelFormat format)
}
}
bool HostDisplay::SetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, const void* buffer, u32 pitch)
{
void* map_ptr;
u32 map_pitch;
if (!BeginSetDisplayPixels(format, width, height, &map_ptr, &map_pitch))
return false;
if (pitch == map_pitch)
{
std::memcpy(map_ptr, buffer, height * map_pitch);
}
else
{
const u32 copy_size = width * GetDisplayPixelFormatSize(format);
DebugAssert(pitch >= copy_size && map_pitch >= copy_size);
const u8* src_ptr = static_cast<const u8*>(buffer);
u8* dst_ptr = static_cast<u8*>(map_ptr);
for (u32 i = 0; i < height; i++)
{
std::memcpy(dst_ptr, src_ptr, copy_size);
src_ptr += pitch;
dst_ptr += map_pitch;
}
}
EndSetDisplayPixels();
return true;
}
bool HostDisplay::GetHostRefreshRate(float* refresh_rate)
{
if (m_window_info.surface_refresh_rate > 0.0f)

View File

@ -41,6 +41,10 @@ public:
virtual u32 GetLevels() const = 0;
virtual u32 GetSamples() const = 0;
virtual HostDisplayPixelFormat GetFormat() const = 0;
virtual bool BeginUpdate(u32 width, u32 height, void** out_buffer, u32* out_pitch)/* = 0*/;
virtual void EndUpdate(u32 x, u32 y, u32 width, u32 height)/* = 0*/;
virtual bool Update(u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch);
};
// Interface to the frontend's renderer.
@ -124,9 +128,6 @@ public:
virtual std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples,
HostDisplayPixelFormat format, const void* data,
u32 data_stride, bool dynamic = false) = 0;
virtual void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data,
u32 data_stride) = 0;
virtual bool DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y,
u32 width, u32 height, void* out_data, u32 out_data_stride) = 0;
@ -203,11 +204,6 @@ public:
virtual bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const = 0;
virtual bool BeginSetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, void** out_buffer,
u32* out_pitch) = 0;
virtual void EndSetDisplayPixels() = 0;
virtual bool SetDisplayPixels(HostDisplayPixelFormat format, u32 width, u32 height, const void* buffer, u32 pitch);
virtual bool GetHostRefreshRate(float* refresh_rate);
/// Enables/disables GPU frame timing.