HostDisplay: Common texture base class for all APIs

This commit is contained in:
Connor McLaughlin
2022-10-03 16:44:34 +10:00
parent 12d400b76a
commit a9038133c8
50 changed files with 1428 additions and 1566 deletions

View File

@ -163,7 +163,7 @@ void GPU::SoftReset()
UpdateGPUIdle();
}
bool GPU::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display)
bool GPU::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display)
{
if (sw.IsReading())
{

View File

@ -15,7 +15,7 @@
class StateWrapper;
class HostDisplay;
class HostDisplayTexture;
class GPUTexture;
class TimingEvent;
class Timers;
@ -83,7 +83,7 @@ public:
virtual bool Initialize();
virtual void Reset(bool clear_vram);
virtual bool DoState(StateWrapper& sw, HostDisplayTexture** save_to_texture, bool update_display);
virtual bool DoState(StateWrapper& sw, GPUTexture** save_to_texture, bool update_display);
// Graphics API state reset/restore - call when drawing the UI etc.
virtual void ResetGraphicsAPIState();

View File

@ -123,7 +123,7 @@ void GPU_HW::Reset(bool clear_vram)
SetFullVRAMDirtyRectangle();
}
bool GPU_HW::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display)
bool GPU_HW::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display)
{
if (!GPU::DoState(sw, host_texture, update_display))
return false;

View File

@ -37,7 +37,7 @@ public:
virtual bool Initialize() override;
virtual void Reset(bool clear_vram) override;
virtual bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
virtual bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override;
void UpdateResolutionScale() override final;
std::tuple<u32, u32> GetEffectiveDisplayResolution(bool scaled = true) override final;

View File

@ -99,13 +99,13 @@ void GPU_HW_D3D11::Reset(bool clear_vram)
ClearFramebuffer();
}
bool GPU_HW_D3D11::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display)
bool GPU_HW_D3D11::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display)
{
if (host_texture)
{
ComPtr<ID3D11Resource> resource;
HostDisplayTexture* tex = *host_texture;
D3D11::Texture* tex = static_cast<D3D11::Texture*>(*host_texture);
if (sw.IsReading())
{
if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() ||
@ -114,8 +114,7 @@ bool GPU_HW_D3D11::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
return false;
}
static_cast<ID3D11ShaderResourceView*>(tex->GetHandle())->GetResource(resource.GetAddressOf());
m_context->CopySubresourceRegion(m_vram_texture.GetD3DTexture(), 0, 0, 0, 0, resource.Get(), 0, nullptr);
m_context->CopySubresourceRegion(m_vram_texture.GetD3DTexture(), 0, 0, 0, 0, tex->GetD3DTexture(), 0, nullptr);
}
else
{
@ -124,17 +123,17 @@ bool GPU_HW_D3D11::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
{
delete tex;
tex = g_host_display
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1,
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false)
.release();
tex = static_cast<D3D11::Texture*>(g_host_display
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1,
1, m_vram_texture.GetSamples(), GPUTexture::Format::RGBA8,
nullptr, 0, false)
.release());
*host_texture = tex;
if (!tex)
return false;
}
static_cast<ID3D11ShaderResourceView*>(tex->GetHandle())->GetResource(resource.GetAddressOf());
m_context->CopySubresourceRegion(resource.Get(), 0, 0, 0, 0, m_vram_texture.GetD3DTexture(), 0, nullptr);
m_context->CopySubresourceRegion(tex->GetD3DTexture(), 0, 0, 0, 0, m_vram_texture.GetD3DTexture(), 0, nullptr);
}
}
@ -254,9 +253,9 @@ bool GPU_HW_D3D11::CreateFramebuffer()
// scale vram size to internal resolution
const u32 texture_width = VRAM_WIDTH * m_resolution_scale;
const u32 texture_height = VRAM_HEIGHT * m_resolution_scale;
const u16 samples = static_cast<u16>(m_multisamples);
const DXGI_FORMAT texture_format = DXGI_FORMAT_R8G8B8A8_UNORM;
const DXGI_FORMAT depth_format = DXGI_FORMAT_D16_UNORM;
const u8 samples = static_cast<u8>(m_multisamples);
const GPUTexture::Format texture_format = GPUTexture::Format::RGBA8;
const GPUTexture::Format depth_format = GPUTexture::Format::D16;
if (!m_vram_texture.Create(m_device.Get(), texture_width, texture_height, 1, 1, samples, texture_format,
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) ||
@ -275,8 +274,9 @@ bool GPU_HW_D3D11::CreateFramebuffer()
return false;
}
const CD3D11_DEPTH_STENCIL_VIEW_DESC depth_view_desc(
samples > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D, depth_format);
const CD3D11_DEPTH_STENCIL_VIEW_DESC depth_view_desc(samples > 1 ? D3D11_DSV_DIMENSION_TEXTURE2DMS :
D3D11_DSV_DIMENSION_TEXTURE2D,
D3D11::Texture::GetDXGIFormat(depth_format));
HRESULT hr =
m_device->CreateDepthStencilView(m_vram_depth_texture, &depth_view_desc, m_vram_depth_view.GetAddressOf());
if (FAILED(hr))
@ -289,7 +289,7 @@ bool GPU_HW_D3D11::CreateFramebuffer()
if (!m_downsample_texture.Create(m_device.Get(), texture_width, texture_height, 1, static_cast<u16>(levels), 1,
texture_format, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) ||
!m_downsample_weight_texture.Create(m_device.Get(), texture_width >> (levels - 1),
texture_height >> (levels - 1), 1, 1, 1, DXGI_FORMAT_R8_UNORM,
texture_height >> (levels - 1), 1, 1, 1, GPUTexture::Format::R8,
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET))
{
return false;
@ -299,9 +299,9 @@ bool GPU_HW_D3D11::CreateFramebuffer()
for (u32 i = 0; i < levels; i++)
{
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(m_downsample_texture, D3D11_SRV_DIMENSION_TEXTURE2D,
texture_format, i, 1);
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(m_downsample_texture, D3D11_RTV_DIMENSION_TEXTURE2D, texture_format,
i, 1);
m_downsample_texture.GetDXGIFormat(), i, 1);
const CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(m_downsample_texture, D3D11_RTV_DIMENSION_TEXTURE2D,
m_downsample_texture.GetDXGIFormat(), i, 1);
hr = m_device->CreateShaderResourceView(m_downsample_texture, &srv_desc,
m_downsample_mip_views[i].first.GetAddressOf());
@ -749,7 +749,7 @@ bool GPU_HW_D3D11::BlitVRAMReplacementTexture(const TextureReplacementTexture* t
m_vram_replacement_texture.GetHeight() < tex->GetHeight())
{
if (!m_vram_replacement_texture.Create(m_device.Get(), tex->GetWidth(), tex->GetHeight(), 1, 1, 1,
DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE, tex->GetPixels(),
GPUTexture::Format::RGBA8, D3D11_BIND_SHADER_RESOURCE, tex->GetPixels(),
tex->GetPitch(), true))
{
return false;
@ -841,15 +841,12 @@ void GPU_HW_D3D11::UpdateDisplay()
if (IsUsingMultisampling())
{
UpdateVRAMReadTexture();
g_host_display->SetDisplayTexture(&m_vram_read_texture, HostDisplayPixelFormat::RGBA8,
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0,
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
g_host_display->SetDisplayTexture(&m_vram_read_texture, 0, 0, m_vram_read_texture.GetWidth(),
m_vram_read_texture.GetHeight());
}
else
{
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight());
g_host_display->SetDisplayTexture(&m_vram_texture, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
}
g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
@ -889,8 +886,7 @@ void GPU_HW_D3D11::UpdateDisplay()
}
else
{
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight(), scaled_vram_offset_x, scaled_vram_offset_y,
g_host_display->SetDisplayTexture(&m_vram_texture, scaled_vram_offset_x, scaled_vram_offset_y,
scaled_display_width, scaled_display_height);
}
}
@ -916,15 +912,9 @@ void GPU_HW_D3D11::UpdateDisplay()
DrawUtilityShader(display_pixel_shader, uniforms, sizeof(uniforms));
if (IsUsingDownsampling())
{
DownsampleFramebuffer(m_display_texture, 0, 0, scaled_display_width, scaled_display_height);
}
else
{
g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8,
m_display_texture.GetWidth(), m_display_texture.GetHeight(), 0, 0,
scaled_display_width, scaled_display_height);
}
g_host_display->SetDisplayTexture(&m_display_texture, 0, 0, scaled_display_width, scaled_display_height);
RestoreGraphicsAPIState();
}
@ -954,9 +944,9 @@ void GPU_HW_D3D11::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
DrawUtilityShader(m_vram_read_pixel_shader.Get(), uniforms, sizeof(uniforms));
// Stage the readback and copy it into our shadow buffer.
g_host_display->DownloadTexture(
&m_vram_encoding_texture, HostDisplayPixelFormat::RGBA8, 0, 0, encoded_width, encoded_height,
reinterpret_cast<u32*>(&m_vram_shadow[copy_rect.top * VRAM_WIDTH + copy_rect.left]), VRAM_WIDTH * sizeof(u16));
g_host_display->DownloadTexture(&m_vram_encoding_texture, 0, 0, encoded_width, encoded_height,
reinterpret_cast<u32*>(&m_vram_shadow[copy_rect.top * VRAM_WIDTH + copy_rect.left]),
VRAM_WIDTH * sizeof(u16));
RestoreGraphicsAPIState();
}
@ -1080,7 +1070,7 @@ void GPU_HW_D3D11::UpdateVRAMReadTexture()
if (m_vram_texture.IsMultisampled())
{
m_context->ResolveSubresource(m_vram_read_texture.GetD3DTexture(), 0, m_vram_texture.GetD3DTexture(), 0,
m_vram_texture.GetFormat());
m_vram_texture.GetDXGIFormat());
}
else
{
@ -1191,8 +1181,7 @@ void GPU_HW_D3D11::DownsampleFramebufferAdaptive(D3D11::Texture& source, u32 lef
RestoreGraphicsAPIState();
g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),
m_display_texture.GetHeight(), left, top, width, height);
g_host_display->SetDisplayTexture(&m_display_texture, left, top, width, height);
}
void GPU_HW_D3D11::DownsampleFramebufferBoxFilter(D3D11::Texture& source, u32 left, u32 top, u32 width, u32 height)
@ -1215,9 +1204,7 @@ void GPU_HW_D3D11::DownsampleFramebufferBoxFilter(D3D11::Texture& source, u32 le
RestoreGraphicsAPIState();
g_host_display->SetDisplayTexture(&m_downsample_texture, HostDisplayPixelFormat::RGBA8,
m_downsample_texture.GetWidth(), m_downsample_texture.GetHeight(), ds_left, ds_top,
ds_width, ds_height);
g_host_display->SetDisplayTexture(&m_downsample_texture, ds_left, ds_top, ds_width, ds_height);
}
std::unique_ptr<GPU> GPU::CreateHardwareD3D11Renderer()

View File

@ -23,7 +23,7 @@ public:
bool Initialize() override;
void Reset(bool clear_vram) override;
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override;
void ResetGraphicsAPIState() override;
void RestoreGraphicsAPIState() override;

View File

@ -319,16 +319,16 @@ bool GPU_HW_D3D12::CreateFramebuffer()
const DXGI_FORMAT texture_format = DXGI_FORMAT_R8G8B8A8_UNORM;
const DXGI_FORMAT depth_format = DXGI_FORMAT_D16_UNORM;
if (!m_vram_texture.Create(texture_width, texture_height, m_multisamples, texture_format, texture_format,
if (!m_vram_texture.Create(texture_width, texture_height, 1, 1, m_multisamples, texture_format, texture_format,
texture_format, DXGI_FORMAT_UNKNOWN, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) ||
!m_vram_depth_texture.Create(
texture_width, texture_height, m_multisamples, depth_format, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
texture_width, texture_height, 1, 1, m_multisamples, depth_format, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
depth_format, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL | D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE) ||
!m_vram_read_texture.Create(texture_width, texture_height, 1, texture_format, texture_format, DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_UNKNOWN, D3D12_RESOURCE_FLAG_NONE) ||
!m_display_texture.Create(texture_width, texture_height, 1, texture_format, texture_format, texture_format,
!m_vram_read_texture.Create(texture_width, texture_height, 1, 1, 1, texture_format, texture_format,
DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, D3D12_RESOURCE_FLAG_NONE) ||
!m_display_texture.Create(texture_width, texture_height, 1, 1, 1, texture_format, texture_format, texture_format,
DXGI_FORMAT_UNKNOWN, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) ||
!m_vram_readback_texture.Create(VRAM_WIDTH, VRAM_HEIGHT, 1, texture_format, texture_format, texture_format,
!m_vram_readback_texture.Create(VRAM_WIDTH, VRAM_HEIGHT, 1, 1, 1, texture_format, texture_format, texture_format,
DXGI_FORMAT_UNKNOWN, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) ||
!m_vram_readback_staging_texture.Create(VRAM_WIDTH / 2, VRAM_HEIGHT, texture_format, false))
{
@ -476,8 +476,8 @@ bool GPU_HW_D3D12::CompilePipelines()
const bool textured = (static_cast<GPUTextureMode>(texture_mode) != GPUTextureMode::Disabled);
gpbuilder.SetRootSignature(m_batch_root_signature.Get());
gpbuilder.SetRenderTarget(0, m_vram_texture.GetFormat());
gpbuilder.SetDepthStencilFormat(m_vram_depth_texture.GetFormat());
gpbuilder.SetRenderTarget(0, m_vram_texture.GetDXGIFormat());
gpbuilder.SetDepthStencilFormat(m_vram_depth_texture.GetDXGIFormat());
gpbuilder.AddVertexAttribute("ATTR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(BatchVertex, x));
gpbuilder.AddVertexAttribute("ATTR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(BatchVertex, color));
@ -547,16 +547,16 @@ bool GPU_HW_D3D12::CompilePipelines()
// common state
gpbuilder.SetRootSignature(m_single_sampler_root_signature.Get());
gpbuilder.SetRenderTarget(0, m_vram_texture.GetFormat());
gpbuilder.SetDepthStencilFormat(m_vram_depth_texture.GetFormat());
gpbuilder.SetRenderTarget(0, m_vram_texture.GetDXGIFormat());
gpbuilder.SetDepthStencilFormat(m_vram_depth_texture.GetDXGIFormat());
gpbuilder.SetPrimitiveTopologyType(D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE);
gpbuilder.SetNoCullRasterizationState();
gpbuilder.SetNoDepthTestState();
gpbuilder.SetNoBlendingState();
gpbuilder.SetVertexShader(fullscreen_quad_vertex_shader.Get());
gpbuilder.SetMultisamples(m_multisamples);
gpbuilder.SetRenderTarget(0, m_vram_texture.GetFormat());
gpbuilder.SetDepthStencilFormat(m_vram_depth_texture.GetFormat());
gpbuilder.SetRenderTarget(0, m_vram_texture.GetDXGIFormat());
gpbuilder.SetDepthStencilFormat(m_vram_depth_texture.GetDXGIFormat());
// VRAM fill
for (u8 wrapped = 0; wrapped < 2; wrapped++)
@ -663,7 +663,7 @@ bool GPU_HW_D3D12::CompilePipelines()
gpbuilder.SetNoCullRasterizationState();
gpbuilder.SetNoDepthTestState();
gpbuilder.SetNoBlendingState();
gpbuilder.SetRenderTarget(0, m_vram_readback_texture.GetFormat());
gpbuilder.SetRenderTarget(0, m_vram_readback_texture.GetDXGIFormat());
gpbuilder.ClearDepthStencilFormat();
m_vram_readback_pipeline = gpbuilder.Create(g_d3d12_context->GetDevice(), shader_cache, false);
@ -685,7 +685,7 @@ bool GPU_HW_D3D12::CompilePipelines()
gpbuilder.SetNoCullRasterizationState();
gpbuilder.SetNoDepthTestState();
gpbuilder.SetNoBlendingState();
gpbuilder.SetRenderTarget(0, m_display_texture.GetFormat());
gpbuilder.SetRenderTarget(0, m_display_texture.GetDXGIFormat());
for (u8 depth_24 = 0; depth_24 < 2; depth_24++)
{
@ -775,7 +775,7 @@ bool GPU_HW_D3D12::BlitVRAMReplacementTexture(const TextureReplacementTexture* t
if (m_vram_write_replacement_texture.GetWidth() < tex->GetWidth() ||
m_vram_write_replacement_texture.GetHeight() < tex->GetHeight())
{
if (!m_vram_write_replacement_texture.Create(tex->GetWidth(), tex->GetHeight(), 1, DXGI_FORMAT_R8G8B8A8_UNORM,
if (!m_vram_write_replacement_texture.Create(tex->GetWidth(), tex->GetHeight(), 1, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
D3D12_RESOURCE_FLAG_NONE))
{
@ -867,16 +867,13 @@ void GPU_HW_D3D12::UpdateDisplay()
if (IsUsingMultisampling())
{
UpdateVRAMReadTexture();
g_host_display->SetDisplayTexture(&m_vram_read_texture, HostDisplayPixelFormat::RGBA8,
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0,
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
g_host_display->SetDisplayTexture(&m_vram_read_texture, 0, 0, m_vram_read_texture.GetWidth(),
m_vram_read_texture.GetHeight());
}
else
{
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight());
g_host_display->SetDisplayTexture(&m_vram_texture, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
}
g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
@ -908,8 +905,7 @@ void GPU_HW_D3D12::UpdateDisplay()
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture.GetHeight())
{
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight(), scaled_vram_offset_x, scaled_vram_offset_y,
g_host_display->SetDisplayTexture(&m_vram_texture, scaled_vram_offset_x, scaled_vram_offset_y,
scaled_display_width, scaled_display_height);
}
else
@ -936,9 +932,7 @@ void GPU_HW_D3D12::UpdateDisplay()
m_display_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),
m_display_texture.GetHeight(), 0, 0, scaled_display_width,
scaled_display_height);
g_host_display->SetDisplayTexture(&m_display_texture, 0, 0, scaled_display_width, scaled_display_height);
RestoreGraphicsAPIState();
}
@ -1150,7 +1144,7 @@ void GPU_HW_D3D12::UpdateVRAMReadTexture()
{
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
m_vram_read_texture.TransitionToState(D3D12_RESOURCE_STATE_RESOLVE_DEST);
cmdlist->ResolveSubresource(m_vram_read_texture, 0, m_vram_texture, 0, m_vram_texture.GetFormat());
cmdlist->ResolveSubresource(m_vram_read_texture, 0, m_vram_texture, 0, m_vram_texture.GetDXGIFormat());
}
else
{

View File

@ -108,11 +108,11 @@ void GPU_HW_OpenGL::Reset(bool clear_vram)
ClearFramebuffer();
}
bool GPU_HW_OpenGL::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display)
bool GPU_HW_OpenGL::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display)
{
if (host_texture)
{
HostDisplayTexture* tex = *host_texture;
GPUTexture* tex = *host_texture;
if (sw.IsReading())
{
if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() ||
@ -121,9 +121,9 @@ bool GPU_HW_OpenGL::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
return false;
}
CopyFramebufferForState(
m_vram_texture.GetGLTarget(), static_cast<GLuint>(reinterpret_cast<uintptr_t>(tex->GetHandle())), 0, 0, 0,
m_vram_texture.GetGLId(), m_vram_fbo_id, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
CopyFramebufferForState(m_vram_texture.GetGLTarget(), static_cast<GL::Texture*>(tex)->GetGLId(), 0, 0, 0,
m_vram_texture.GetGLId(), m_vram_fbo_id, 0, 0, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight());
}
else
{
@ -134,7 +134,7 @@ bool GPU_HW_OpenGL::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
tex = g_host_display
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1,
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false)
m_vram_texture.GetSamples(), GPUTexture::Format::RGBA8, nullptr, 0, false)
.release();
*host_texture = tex;
if (!tex)
@ -142,8 +142,8 @@ bool GPU_HW_OpenGL::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
}
CopyFramebufferForState(m_vram_texture.GetGLTarget(), m_vram_texture.GetGLId(), m_vram_fbo_id, 0, 0,
static_cast<GLuint>(reinterpret_cast<uintptr_t>(tex->GetHandle())), 0, 0, 0,
m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
static_cast<GL::Texture*>(tex)->GetGLId(), 0, 0, 0, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight());
}
}
@ -285,17 +285,11 @@ void GPU_HW_OpenGL::UnmapBatchVertexPointer(u32 used_vertices)
DebugAssert(m_batch_start_vertex_ptr);
m_vertex_stream_buffer->Unmap(used_vertices * sizeof(BatchVertex));
m_vertex_stream_buffer->Bind();
m_batch_start_vertex_ptr = nullptr;
m_batch_end_vertex_ptr = nullptr;
m_batch_current_vertex_ptr = nullptr;
}
std::tuple<s32, s32> GPU_HW_OpenGL::ConvertToFramebufferCoordinates(s32 x, s32 y)
{
return std::make_tuple(x, static_cast<s32>(static_cast<s32>(VRAM_HEIGHT) - y));
}
void GPU_HW_OpenGL::SetCapabilities()
{
GLint max_texture_size = VRAM_WIDTH;
@ -396,18 +390,18 @@ bool GPU_HW_OpenGL::CreateFramebuffer()
const u32 texture_height = VRAM_HEIGHT * m_resolution_scale;
const u32 multisamples = m_multisamples;
if (!m_vram_texture.Create(texture_width, texture_height, 1, 1, multisamples, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr, false, true) ||
!m_vram_depth_texture.Create(texture_width, texture_height, 1, 1, multisamples, GL_DEPTH_COMPONENT16,
GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, nullptr, false) ||
!m_vram_read_texture.Create(texture_width, texture_height, 1, 1, 1, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr,
false, true) ||
if (!m_vram_texture.Create(texture_width, texture_height, 1, 1, multisamples, GPUTexture::Format::RGBA8, nullptr, 0,
true, true) ||
!m_vram_depth_texture.Create(texture_width, texture_height, 1, 1, multisamples, GPUTexture::Format::D16, nullptr,
0, false, true) ||
!m_vram_read_texture.Create(texture_width, texture_height, 1, 1, 1, GPUTexture::Format::RGBA8, nullptr, 0, false,
true) ||
!m_vram_read_texture.CreateFramebuffer() ||
!m_vram_encoding_texture.Create(VRAM_WIDTH, VRAM_HEIGHT, 1, 1, 1, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr,
false) ||
!m_vram_encoding_texture.Create(VRAM_WIDTH, VRAM_HEIGHT, 1, 1, 1, GPUTexture::Format::RGBA8, nullptr, 0, false,
true) ||
!m_vram_encoding_texture.CreateFramebuffer() ||
!m_display_texture.Create(GPU_MAX_DISPLAY_WIDTH * m_resolution_scale, GPU_MAX_DISPLAY_HEIGHT * m_resolution_scale,
1, 1, 1, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false) ||
1, 1, 1, GPUTexture::Format::RGBA8, nullptr, 0, true, true) ||
!m_display_texture.CreateFramebuffer())
{
return false;
@ -425,7 +419,7 @@ bool GPU_HW_OpenGL::CreateFramebuffer()
if (m_downsample_mode == GPUDownsampleMode::Box)
{
if (!m_downsample_texture.Create(VRAM_WIDTH, VRAM_HEIGHT, 1, 1, 1, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE) ||
if (!m_downsample_texture.Create(VRAM_WIDTH, VRAM_HEIGHT, 1, 1, 1, GPUTexture::Format::RGBA8) ||
!m_downsample_texture.CreateFramebuffer())
{
return false;
@ -778,8 +772,8 @@ bool GPU_HW_OpenGL::BlitVRAMReplacementTexture(const TextureReplacementTexture*
{
if (!m_vram_write_replacement_texture.IsValid())
{
if (!m_vram_write_replacement_texture.Create(tex->GetWidth(), tex->GetHeight(), 1, 1, 1, GL_RGBA8, GL_RGBA,
GL_UNSIGNED_BYTE, tex->GetPixels(), true) ||
if (!m_vram_write_replacement_texture.Create(tex->GetWidth(), tex->GetHeight(), 1, 1, 1,
GPUTexture::Format::RGBA8) ||
!m_vram_write_replacement_texture.CreateFramebuffer())
{
m_vram_write_replacement_texture.Destroy();
@ -795,7 +789,6 @@ bool GPU_HW_OpenGL::BlitVRAMReplacementTexture(const TextureReplacementTexture*
glDisable(GL_SCISSOR_TEST);
m_vram_write_replacement_texture.BindFramebuffer(GL_READ_FRAMEBUFFER);
dst_y = m_vram_texture.GetHeight() - dst_y - height;
glBlitFramebuffer(0, tex->GetHeight(), tex->GetWidth(), 0, dst_x, dst_y, dst_x + width, dst_y + height,
GL_COLOR_BUFFER_BIT, GL_LINEAR);
@ -826,7 +819,7 @@ void GPU_HW_OpenGL::SetScissorFromDrawingArea()
const int width = right - left;
const int height = bottom - top;
const int x = left;
const int y = m_vram_texture.GetHeight() - bottom;
const int y = top;
Log_DebugPrintf("SetScissor: (%d-%d, %d-%d)", x, x + width, y, y + height);
glScissor(x, y, width, height);
@ -867,16 +860,13 @@ void GPU_HW_OpenGL::UpdateDisplay()
{
UpdateVRAMReadTexture();
g_host_display->SetDisplayTexture(
&m_vram_read_texture, HostDisplayPixelFormat::RGBA8, m_vram_read_texture.GetWidth(),
static_cast<s32>(m_vram_read_texture.GetHeight()), 0, m_vram_read_texture.GetHeight(),
m_vram_read_texture.GetWidth(), -static_cast<s32>(m_vram_read_texture.GetHeight()));
g_host_display->SetDisplayTexture(&m_vram_read_texture, 0, m_vram_read_texture.GetHeight(),
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
}
else
{
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
static_cast<s32>(m_vram_texture.GetHeight()), 0, m_vram_texture.GetHeight(),
m_vram_texture.GetWidth(), -static_cast<s32>(m_vram_texture.GetHeight()));
g_host_display->SetDisplayTexture(&m_vram_texture, 0, m_vram_texture.GetHeight(), m_vram_texture.GetWidth(),
m_vram_texture.GetHeight());
}
g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
@ -914,10 +904,8 @@ void GPU_HW_OpenGL::UpdateDisplay()
}
else
{
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight(), scaled_vram_offset_x,
m_vram_texture.GetHeight() - scaled_vram_offset_y, scaled_display_width,
-static_cast<s32>(scaled_display_height));
g_host_display->SetDisplayTexture(&m_vram_texture, scaled_vram_offset_x, scaled_vram_offset_y,
scaled_display_width, scaled_display_height);
}
}
else
@ -936,14 +924,11 @@ void GPU_HW_OpenGL::UpdateDisplay()
glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER, static_cast<GLsizei>(attachments.size()), attachments.data());
}
const u8 height_div2 = BoolToUInt8(interlaced == GPU_HW::InterlacedRenderMode::SeparateFields);
const u32 reinterpret_field_offset = (interlaced != InterlacedRenderMode::None) ? GetInterlacedDisplayField() : 0;
const u32 scaled_flipped_vram_offset_y = m_vram_texture.GetHeight() - scaled_vram_offset_y -
reinterpret_field_offset - (scaled_display_height >> height_div2);
const u32 reinterpret_start_x = m_crtc_state.regs.X * resolution_scale;
const u32 reinterpret_crop_left = (m_crtc_state.display_vram_left - m_crtc_state.regs.X) * resolution_scale;
const u32 uniforms[4] = {reinterpret_start_x, scaled_flipped_vram_offset_y, reinterpret_crop_left,
reinterpret_field_offset};
const u32 uniforms[4] = {reinterpret_start_x, scaled_vram_offset_y + reinterpret_field_offset,
reinterpret_crop_left, reinterpret_field_offset};
UploadUniformBuffer(uniforms, sizeof(uniforms));
m_batch_ubo_dirty = true;
@ -960,10 +945,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
}
else
{
g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8,
m_display_texture.GetWidth(), m_display_texture.GetHeight(), 0,
scaled_display_height, scaled_display_width,
-static_cast<s32>(scaled_display_height));
g_host_display->SetDisplayTexture(&m_display_texture, 0, 0, scaled_display_width, scaled_display_height);
}
// restore state
@ -993,8 +975,7 @@ void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
const u32 encoded_height = copy_rect.GetHeight();
// Encode the 24-bit texture as 16-bit.
const u32 uniforms[4] = {copy_rect.left, VRAM_HEIGHT - copy_rect.top - copy_rect.GetHeight(), copy_rect.GetWidth(),
copy_rect.GetHeight()};
const u32 uniforms[4] = {copy_rect.left, copy_rect.top, copy_rect.GetWidth(), copy_rect.GetHeight()};
m_vram_encoding_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER);
m_vram_texture.Bind();
m_vram_read_program.Bind();
@ -1024,9 +1005,8 @@ void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
GPU_HW::FillVRAM(x, y, width, height, color);
const Common::Rectangle<u32> bounds(GetVRAMTransferBounds(x, y, width, height));
glScissor(bounds.left * m_resolution_scale,
m_vram_texture.GetHeight() - (bounds.top * m_resolution_scale) - (height * m_resolution_scale),
width * m_resolution_scale, height * m_resolution_scale);
glScissor(bounds.left * m_resolution_scale, bounds.top * m_resolution_scale, width * m_resolution_scale,
height * m_resolution_scale);
// fast path when not using interlaced rendering
const bool wrapped = IsVRAMFillOversized(x, y, width, height);
@ -1096,9 +1076,7 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
// the viewport should already be set to the full vram, so just adjust the scissor
const Common::Rectangle<u32> scaled_bounds = bounds * m_resolution_scale;
glScissor(scaled_bounds.left, m_vram_texture.GetHeight() - scaled_bounds.top - scaled_bounds.GetHeight(),
scaled_bounds.GetWidth(), scaled_bounds.GetHeight());
glScissor(scaled_bounds.left, scaled_bounds.top, scaled_bounds.GetWidth(), scaled_bounds.GetHeight());
glBindVertexArray(m_attributeless_vao_id);
glDrawArrays(GL_TRIANGLES, 0, 3);
@ -1120,9 +1098,8 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
const auto map_result = m_texture_stream_buffer->Map(sizeof(u32), num_pixels * sizeof(u32));
// reverse copy the rows so it matches opengl's lower-left origin
const u32 source_stride = width * sizeof(u16);
const u8* source_ptr = static_cast<const u8*>(data) + (source_stride * (height - 1));
const u8* source_ptr = static_cast<const u8*>(data);
const u16 mask_or = set_mask ? 0x8000 : 0x0000;
u32* dest_ptr = static_cast<u32*>(map_result.pointer);
for (u32 row = 0; row < height; row++)
@ -1137,7 +1114,7 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
*(dest_ptr++) = VRAMRGBA5551ToRGBA8888(src_col | mask_or);
}
source_ptr -= source_stride;
source_ptr += source_stride;
}
m_texture_stream_buffer->Unmap(num_pixels * sizeof(u32));
@ -1149,11 +1126,8 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
else
m_vram_texture.Bind();
// lower-left origin flip happens here
const u32 flipped_y = VRAM_HEIGHT - y - height;
// update texture data
glTexSubImage2D(m_vram_texture.GetGLTarget(), 0, x, flipped_y, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
glTexSubImage2D(m_vram_texture.GetGLTarget(), 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
reinterpret_cast<void*>(static_cast<uintptr_t>(map_result.buffer_offset)));
m_texture_stream_buffer->Unbind();
@ -1164,11 +1138,10 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
const u32 scaled_height = height * m_resolution_scale;
const u32 scaled_x = x * m_resolution_scale;
const u32 scaled_y = y * m_resolution_scale;
const u32 scaled_flipped_y = m_vram_texture.GetHeight() - scaled_y - scaled_height;
glDisable(GL_SCISSOR_TEST);
m_vram_encoding_texture.BindFramebuffer(GL_READ_FRAMEBUFFER);
glBlitFramebuffer(x, flipped_y, x + width, flipped_y + height, scaled_x, scaled_flipped_y,
scaled_x + scaled_width, scaled_flipped_y + scaled_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glBlitFramebuffer(x, y, x + width, y + height, scaled_x, scaled_y, scaled_x + scaled_width,
scaled_y + scaled_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glEnable(GL_SCISSOR_TEST);
}
}
@ -1189,9 +1162,7 @@ void GPU_HW_OpenGL::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid
UpdateVRAMReadTexture();
IncludeVRAMDirtyRectangle(dst_bounds);
VRAMCopyUBOData uniforms = GetVRAMCopyUBOData(src_x, src_y, dst_x, dst_y, width, height);
uniforms.u_src_y = m_vram_texture.GetHeight() - uniforms.u_src_y - uniforms.u_height;
uniforms.u_dst_y = m_vram_texture.GetHeight() - uniforms.u_dst_y - uniforms.u_height;
const VRAMCopyUBOData uniforms = GetVRAMCopyUBOData(src_x, src_y, dst_x, dst_y, width, height);
UploadUniformBuffer(&uniforms, sizeof(uniforms));
glDisable(GL_SCISSOR_TEST);
@ -1199,9 +1170,8 @@ void GPU_HW_OpenGL::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid
SetDepthFunc((m_GPUSTAT.check_mask_before_draw && !m_pgxp_depth_buffer) ? GL_GEQUAL : GL_ALWAYS);
const Common::Rectangle<u32> dst_bounds_scaled(dst_bounds * m_resolution_scale);
glViewport(dst_bounds_scaled.left,
m_vram_texture.GetHeight() - dst_bounds_scaled.top - dst_bounds_scaled.GetHeight(),
dst_bounds_scaled.GetWidth(), dst_bounds_scaled.GetHeight());
glViewport(dst_bounds_scaled.left, dst_bounds_scaled.top, dst_bounds_scaled.GetWidth(),
dst_bounds_scaled.GetHeight());
m_vram_read_texture.Bind();
m_vram_copy_program.Bind();
glBindVertexArray(m_attributeless_vao_id);
@ -1224,10 +1194,6 @@ void GPU_HW_OpenGL::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid
width *= m_resolution_scale;
height *= m_resolution_scale;
// lower-left origin flip
src_y = m_vram_texture.GetHeight() - src_y - height;
dst_y = m_vram_texture.GetHeight() - dst_y - height;
if (GLAD_GL_VERSION_4_3)
{
glCopyImageSubData(m_vram_texture.GetGLId(), m_vram_texture.GetGLTarget(), 0, src_x, src_y, 0,
@ -1266,7 +1232,7 @@ void GPU_HW_OpenGL::UpdateVRAMReadTexture()
const u32 width = scaled_rect.GetWidth();
const u32 height = scaled_rect.GetHeight();
const u32 x = scaled_rect.left;
const u32 y = m_vram_texture.GetHeight() - scaled_rect.top - height;
const u32 y = scaled_rect.top;
const bool multisampled = m_vram_texture.IsMultisampled();
if (!multisampled && GLAD_GL_VERSION_4_3)
@ -1344,7 +1310,7 @@ void GPU_HW_OpenGL::DownsampleFramebufferBoxFilter(GL::Texture& source, u32 left
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glViewport(ds_left, m_downsample_texture.GetHeight() - ds_top - ds_height, ds_width, ds_height);
glViewport(ds_left, ds_top, ds_width, ds_height);
glBindVertexArray(m_attributeless_vao_id);
source.Bind();
m_downsample_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER);
@ -1353,9 +1319,7 @@ void GPU_HW_OpenGL::DownsampleFramebufferBoxFilter(GL::Texture& source, u32 left
RestoreGraphicsAPIState();
g_host_display->SetDisplayTexture(&m_downsample_texture, HostDisplayPixelFormat::RGBA8,
m_downsample_texture.GetWidth(), m_downsample_texture.GetHeight(), ds_left,
m_downsample_texture.GetHeight() - ds_top, ds_width, -static_cast<s32>(ds_height));
g_host_display->SetDisplayTexture(&m_downsample_texture, ds_left, ds_top, ds_width, ds_height);
}
std::unique_ptr<GPU> GPU::CreateHardwareOpenGLRenderer()

View File

@ -20,7 +20,7 @@ public:
bool Initialize() override;
void Reset(bool clear_vram) override;
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override;
void ResetGraphicsAPIState() override;
void RestoreGraphicsAPIState() override;
@ -55,8 +55,6 @@ private:
ALWAYS_INLINE bool IsGLES() const { return (m_render_api == RenderAPI::OpenGLES); }
std::tuple<s32, s32> ConvertToFramebufferCoordinates(s32 x, s32 y);
void SetCapabilities();
bool CreateFramebuffer();
void ClearFramebuffer();

View File

@ -25,25 +25,6 @@ void GPU_HW_ShaderGen::WriteCommonFunctions(std::stringstream& ss)
ss << "CONSTANT uint MULTISAMPLES = " << m_multisamples << "u;\n";
ss << "CONSTANT bool PER_SAMPLE_SHADING = " << (m_per_sample_shading ? "true" : "false") << ";\n";
ss << R"(
float fixYCoord(float y)
{
#if API_OPENGL || API_OPENGL_ES
return 1.0 - RCP_VRAM_SIZE.y - y;
#else
return y;
#endif
}
uint fixYCoord(uint y)
{
#if API_OPENGL || API_OPENGL_ES
return VRAM_SIZE.y - y - 1u;
#else
return y;
#endif
}
uint RGBA8ToRGBA5551(float4 v)
{
uint r = uint(roundEven(v.r * 31.0));
@ -85,23 +66,6 @@ std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured)
WriteCommonFunctions(ss);
WriteBatchUniformBuffer(ss);
ss << R"(
// OpenGL seems to be off by one pixel in the Y direction due to lower-left origin, but only on
// Intel and NVIDIA drivers. AMD is fine. V3D requires coordinates to be slightly offset even further.
#if API_OPENGL || API_OPENGL_ES
#ifdef DRIVER_V3D
CONSTANT float POS_EPSILON = 0.0001;
#else
#ifdef DRIVER_POWERVR
CONSTANT float POS_EPSILON = 0.001;
#else
CONSTANT float POS_EPSILON = 0.00001;
#endif
#endif
#endif
)";
if (textured)
{
if (m_uv_limits)
@ -145,14 +109,12 @@ std::string GPU_HW_ShaderGen::GenerateBatchVertexShader(bool textured)
#endif
#if API_OPENGL || API_OPENGL_ES
pos_y += POS_EPSILON;
// 0..1 to -1..1 depth range.
pos_z = (pos_z * 2.0) - 1.0;
#endif
// NDC space Y flip in Vulkan.
#if API_VULKAN
#if API_OPENGL || API_OPENGL_ES || API_VULKAN
pos_y = -pos_y;
#endif
@ -767,7 +729,7 @@ float4 SampleFromVRAM(uint4 texpage, float2 coords)
#endif
// fixup coords
uint2 vicoord = uint2(texpage.x + index_coord.x * RESOLUTION_SCALE, fixYCoord(texpage.y + index_coord.y * RESOLUTION_SCALE));
uint2 vicoord = texpage.xy + (index_coord * uint2(RESOLUTION_SCALE, RESOLUTION_SCALE));
// load colour/palette
float4 texel = SAMPLE_TEXTURE(samp0, float2(vicoord) * RCP_VRAM_SIZE);
@ -783,12 +745,12 @@ float4 SampleFromVRAM(uint4 texpage, float2 coords)
#endif
// sample palette
uint2 palette_icoord = uint2(texpage.z + (palette_index * RESOLUTION_SCALE), fixYCoord(texpage.w));
uint2 palette_icoord = uint2(texpage.z + (palette_index * RESOLUTION_SCALE), texpage.w);
return SAMPLE_TEXTURE(samp0, float2(palette_icoord) * RCP_VRAM_SIZE);
#else
// Direct texturing. Render-to-texture effects. Use upscaled coordinates.
uint2 icoord = ApplyUpscaledTextureWindow(FloatToIntegerCoords(coords));
uint2 direct_icoord = uint2(texpage.x + icoord.x, fixYCoord(texpage.y + icoord.y));
uint2 direct_icoord = texpage.xy + icoord;
return SAMPLE_TEXTURE(samp0, float2(direct_icoord) * RCP_VRAM_SIZE);
#endif
}
@ -831,7 +793,7 @@ float4 SampleFromVRAM(uint4 texpage, float2 coords)
float oalpha;
#if INTERLACING
if ((fixYCoord(uint(v_pos.y)) & 1u) == u_interlaced_displayed_field)
if ((uint(v_pos.y) & 1u) == u_interlaced_displayed_field)
discard;
#endif
@ -1097,7 +1059,7 @@ float3 SampleVRAM24Smoothed(uint2 icoords)
uint2 icoords = uint2(v_pos.xy) + uint2(u_crop_left, 0u);
#if INTERLACED
if ((fixYCoord(icoords.y) & 1u) != u_field_offset)
if ((icoords.y & 1u) != u_field_offset)
discard;
#if !INTERLEAVED
@ -1167,13 +1129,6 @@ uint SampleVRAM(uint2 coords)
ss << R"(
{
uint2 sample_coords = uint2(uint(v_pos.x) * 2u, uint(v_pos.y));
#if API_OPENGL || API_OPENGL_ES
// Lower-left origin flip for OpenGL.
// We want to write the image out upside-down so we can read it top-to-bottom.
sample_coords.y = u_size.y - sample_coords.y - 1u;
#endif
sample_coords += u_base_coords;
// We're encoding as 32-bit, so the output width is halved and we pack two 16-bit pixels in one 32-bit pixel.
@ -1222,7 +1177,7 @@ std::string GPU_HW_ShaderGen::GenerateVRAMWriteFragmentShader(bool use_ssbo)
DeclareFragmentEntryPoint(ss, 0, 1, {}, true, 1, true);
ss << R"(
{
uint2 coords = uint2(uint(v_pos.x) / RESOLUTION_SCALE, fixYCoord(uint(v_pos.y)) / RESOLUTION_SCALE);
uint2 coords = uint2(v_pos.xy) / uint2(RESOLUTION_SCALE, RESOLUTION_SCALE);
// make sure it's not oversized and out of range
if ((coords.x < u_base_coords.x && coords.x >= u_end_coords.x) ||
@ -1320,7 +1275,7 @@ std::string GPU_HW_ShaderGen::GenerateVRAMFillFragmentShader(bool wrapped, bool
ss << R"(
{
#if INTERLACED || WRAPPED
uint2 dst_coords = uint2(uint(v_pos.x), fixYCoord(uint(v_pos.y)));
uint2 dst_coords = uint2(v_pos.xy);
#endif
#if INTERLACED

View File

@ -102,7 +102,7 @@ void GPU_HW_Vulkan::Reset(bool clear_vram)
ClearFramebuffer();
}
bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display)
bool GPU_HW_Vulkan::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display)
{
if (host_texture)
{
@ -119,7 +119,7 @@ bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
if (sw.IsReading())
{
Vulkan::Texture* tex = static_cast<Vulkan::Texture*>((*host_texture)->GetHandle());
Vulkan::Texture* tex = static_cast<Vulkan::Texture*>(*host_texture);
if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() ||
tex->GetSamples() != m_vram_texture.GetSamples())
{
@ -137,22 +137,22 @@ bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
}
else
{
HostDisplayTexture* htex = *host_texture;
if (!htex || htex->GetWidth() != m_vram_texture.GetWidth() || htex->GetHeight() != m_vram_texture.GetHeight() ||
htex->GetSamples() != static_cast<u32>(m_vram_texture.GetSamples()))
Vulkan::Texture* tex = static_cast<Vulkan::Texture*>(*host_texture);
if (!tex || tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() ||
tex->GetSamples() != static_cast<u32>(m_vram_texture.GetSamples()))
{
delete htex;
delete tex;
htex = g_host_display
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1,
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false)
.release();
*host_texture = htex;
if (!htex)
tex = static_cast<Vulkan::Texture*>(g_host_display
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1,
1, m_vram_texture.GetSamples(), GPUTexture::Format::RGBA8,
nullptr, 0, false)
.release());
*host_texture = tex;
if (!tex)
return false;
}
Vulkan::Texture* tex = static_cast<Vulkan::Texture*>(htex->GetHandle());
if (tex->GetWidth() != m_vram_texture.GetWidth() || tex->GetHeight() != m_vram_texture.GetHeight() ||
tex->GetSamples() != m_vram_texture.GetSamples())
{
@ -612,13 +612,13 @@ bool GPU_HW_Vulkan::CreateFramebuffer()
m_vram_update_depth_render_pass =
g_vulkan_context->GetRenderPass(VK_FORMAT_UNDEFINED, depth_format, samples, VK_ATTACHMENT_LOAD_OP_DONT_CARE);
m_display_load_render_pass = g_vulkan_context->GetRenderPass(
m_display_texture.GetFormat(), VK_FORMAT_UNDEFINED, m_display_texture.GetSamples(), VK_ATTACHMENT_LOAD_OP_LOAD);
m_display_texture.GetVkFormat(), VK_FORMAT_UNDEFINED, m_display_texture.GetVkSamples(), VK_ATTACHMENT_LOAD_OP_LOAD);
m_display_discard_render_pass =
g_vulkan_context->GetRenderPass(m_display_texture.GetFormat(), VK_FORMAT_UNDEFINED, m_display_texture.GetSamples(),
VK_ATTACHMENT_LOAD_OP_DONT_CARE);
g_vulkan_context->GetRenderPass(m_display_texture.GetVkFormat(), VK_FORMAT_UNDEFINED,
m_display_texture.GetVkSamples(), VK_ATTACHMENT_LOAD_OP_DONT_CARE);
m_vram_readback_render_pass =
g_vulkan_context->GetRenderPass(m_vram_readback_texture.GetFormat(), VK_FORMAT_UNDEFINED,
m_vram_readback_texture.GetSamples(), VK_ATTACHMENT_LOAD_OP_DONT_CARE);
g_vulkan_context->GetRenderPass(m_vram_readback_texture.GetVkFormat(), VK_FORMAT_UNDEFINED,
m_vram_readback_texture.GetVkSamples(), VK_ATTACHMENT_LOAD_OP_DONT_CARE);
if (m_vram_render_pass == VK_NULL_HANDLE || m_vram_update_depth_render_pass == VK_NULL_HANDLE ||
m_display_load_render_pass == VK_NULL_HANDLE || m_vram_readback_render_pass == VK_NULL_HANDLE)
@ -704,10 +704,11 @@ bool GPU_HW_Vulkan::CreateFramebuffer()
m_downsample_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
m_downsample_render_pass = g_vulkan_context->GetRenderPass(m_downsample_texture.GetFormat(), VK_FORMAT_UNDEFINED,
m_downsample_render_pass = g_vulkan_context->GetRenderPass(m_downsample_texture.GetVkFormat(), VK_FORMAT_UNDEFINED,
VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR);
m_downsample_weight_render_pass = g_vulkan_context->GetRenderPass(
m_downsample_weight_texture.GetFormat(), VK_FORMAT_UNDEFINED, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR);
m_downsample_weight_render_pass =
g_vulkan_context->GetRenderPass(m_downsample_weight_texture.GetVkFormat(), VK_FORMAT_UNDEFINED,
VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR);
if (m_downsample_render_pass == VK_NULL_HANDLE || m_downsample_weight_render_pass == VK_NULL_HANDLE)
return false;
@ -725,7 +726,7 @@ bool GPU_HW_Vulkan::CreateFramebuffer()
0,
m_downsample_texture.GetImage(),
VK_IMAGE_VIEW_TYPE_2D,
m_downsample_texture.GetFormat(),
m_downsample_texture.GetVkFormat(),
{VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY},
{VK_IMAGE_ASPECT_COLOR_BIT, i, 1u, 0u, 1u}};
@ -776,7 +777,7 @@ bool GPU_HW_Vulkan::CreateFramebuffer()
return false;
}
m_downsample_render_pass = g_vulkan_context->GetRenderPass(m_downsample_texture.GetFormat(), VK_FORMAT_UNDEFINED,
m_downsample_render_pass = g_vulkan_context->GetRenderPass(m_downsample_texture.GetVkFormat(), VK_FORMAT_UNDEFINED,
VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR);
m_downsample_mip_views.resize(1);
@ -1433,15 +1434,12 @@ void GPU_HW_Vulkan::UpdateDisplay()
UpdateVRAMReadTexture();
}
g_host_display->SetDisplayTexture(&m_vram_read_texture, HostDisplayPixelFormat::RGBA8,
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0,
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
g_host_display->SetDisplayTexture(&m_vram_read_texture, 0, 0, m_vram_read_texture.GetWidth(),
m_vram_read_texture.GetHeight());
}
else
{
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight());
g_host_display->SetDisplayTexture(&m_vram_texture, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
}
g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
@ -1479,8 +1477,7 @@ void GPU_HW_Vulkan::UpdateDisplay()
}
else
{
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight(), scaled_vram_offset_x, scaled_vram_offset_y,
g_host_display->SetDisplayTexture(&m_vram_texture, scaled_vram_offset_x, scaled_vram_offset_y,
scaled_display_width, scaled_display_height);
}
}
@ -1526,9 +1523,7 @@ void GPU_HW_Vulkan::UpdateDisplay()
}
else
{
g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8,
m_display_texture.GetWidth(), m_display_texture.GetHeight(), 0, 0,
scaled_display_width, scaled_display_height);
g_host_display->SetDisplayTexture(&m_display_texture, 0, 0, scaled_display_width, scaled_display_height);
RestoreGraphicsAPIState();
}
}
@ -1577,8 +1572,8 @@ void GPU_HW_Vulkan::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
// Stage the readback and copy it into our shadow buffer (will execute command buffer and stall).
g_host_display->DownloadTexture(&m_vram_readback_texture, HostDisplayPixelFormat::RGBA8, 0, 0, encoded_width,
encoded_height, &m_vram_shadow[copy_rect.top * VRAM_WIDTH + copy_rect.left],
g_host_display->DownloadTexture(&m_vram_readback_texture, 0, 0, encoded_width, encoded_height,
&m_vram_shadow[copy_rect.top * VRAM_WIDTH + copy_rect.left],
VRAM_WIDTH * sizeof(u16));
}
@ -1890,9 +1885,7 @@ void GPU_HW_Vulkan::DownsampleFramebufferBoxFilter(Vulkan::Texture& source, u32
RestoreGraphicsAPIState();
g_host_display->SetDisplayTexture(&m_downsample_texture, HostDisplayPixelFormat::RGBA8,
m_downsample_texture.GetWidth(), m_downsample_texture.GetHeight(), ds_left, ds_top,
ds_width, ds_height);
g_host_display->SetDisplayTexture(&m_downsample_texture, ds_left, ds_top, ds_width, ds_height);
}
void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 left, u32 top, u32 width, u32 height)
@ -1989,8 +1982,7 @@ void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 l
}
RestoreGraphicsAPIState();
g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),
m_display_texture.GetHeight(), left, top, width, height);
g_host_display->SetDisplayTexture(&m_display_texture, left, top, width, height);
}
std::unique_ptr<GPU> GPU::CreateHardwareVulkanRenderer()

View File

@ -18,7 +18,7 @@ public:
bool Initialize() override;
void Reset(bool clear_vram) override;
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override;
void ResetGraphicsAPIState() override;
void RestoreGraphicsAPIState() override;

View File

@ -59,22 +59,22 @@ bool GPU_SW::Initialize()
if (!GPU::Initialize() || !m_backend.Initialize(false))
return false;
static constexpr auto formats_for_16bit = make_array(HostDisplayPixelFormat::RGB565, HostDisplayPixelFormat::RGBA5551,
HostDisplayPixelFormat::RGBA8, HostDisplayPixelFormat::BGRA8);
static constexpr auto formats_for_16bit = make_array(GPUTexture::Format::RGB565, GPUTexture::Format::RGBA5551,
GPUTexture::Format::RGBA8, GPUTexture::Format::BGRA8);
static constexpr auto formats_for_24bit =
make_array(HostDisplayPixelFormat::RGBA8, HostDisplayPixelFormat::BGRA8, HostDisplayPixelFormat::RGB565,
HostDisplayPixelFormat::RGBA5551);
for (const HostDisplayPixelFormat format : formats_for_16bit)
make_array(GPUTexture::Format::RGBA8, GPUTexture::Format::BGRA8, GPUTexture::Format::RGB565,
GPUTexture::Format::RGBA5551);
for (const GPUTexture::Format format : formats_for_16bit)
{
if (g_host_display->SupportsDisplayPixelFormat(format))
if (g_host_display->SupportsTextureFormat(format))
{
m_16bit_display_format = format;
break;
}
}
for (const HostDisplayPixelFormat format : formats_for_24bit)
for (const GPUTexture::Format format : formats_for_24bit)
{
if (g_host_display->SupportsDisplayPixelFormat(format))
if (g_host_display->SupportsTextureFormat(format))
{
m_24bit_display_format = format;
break;
@ -84,7 +84,7 @@ bool GPU_SW::Initialize()
return true;
}
bool GPU_SW::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display)
bool GPU_SW::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display)
{
// ignore the host texture for software mode, since we want to save vram here
return GPU::DoState(sw, nullptr, update_display);
@ -103,7 +103,7 @@ void GPU_SW::UpdateSettings()
m_backend.UpdateSettings();
}
HostDisplayTexture* GPU_SW::GetDisplayTexture(u32 width, u32 height, HostDisplayPixelFormat format)
GPUTexture* GPU_SW::GetDisplayTexture(u32 width, u32 height, GPUTexture::Format format)
{
if (!m_display_texture || m_display_texture->GetWidth() != width || m_display_texture->GetHeight() != height ||
m_display_texture->GetFormat() != format)
@ -118,32 +118,32 @@ HostDisplayTexture* GPU_SW::GetDisplayTexture(u32 width, u32 height, HostDisplay
return m_display_texture.get();
}
template<HostDisplayPixelFormat out_format, typename out_type>
template<GPUTexture::Format out_format, typename out_type>
static void CopyOutRow16(const u16* src_ptr, out_type* dst_ptr, u32 width);
template<HostDisplayPixelFormat out_format, typename out_type>
template<GPUTexture::Format out_format, typename out_type>
static out_type VRAM16ToOutput(u16 value);
template<>
ALWAYS_INLINE u16 VRAM16ToOutput<HostDisplayPixelFormat::RGBA5551, u16>(u16 value)
ALWAYS_INLINE u16 VRAM16ToOutput<GPUTexture::Format::RGBA5551, u16>(u16 value)
{
return (value & 0x3E0) | ((value >> 10) & 0x1F) | ((value & 0x1F) << 10);
}
template<>
ALWAYS_INLINE u16 VRAM16ToOutput<HostDisplayPixelFormat::RGB565, u16>(u16 value)
ALWAYS_INLINE u16 VRAM16ToOutput<GPUTexture::Format::RGB565, u16>(u16 value)
{
return ((value & 0x3E0) << 1) | ((value & 0x20) << 1) | ((value >> 10) & 0x1F) | ((value & 0x1F) << 11);
}
template<>
ALWAYS_INLINE u32 VRAM16ToOutput<HostDisplayPixelFormat::RGBA8, u32>(u16 value)
ALWAYS_INLINE u32 VRAM16ToOutput<GPUTexture::Format::RGBA8, u32>(u16 value)
{
return VRAMRGBA5551ToRGBA8888(value);
}
template<>
ALWAYS_INLINE u32 VRAM16ToOutput<HostDisplayPixelFormat::BGRA8, u32>(u16 value)
ALWAYS_INLINE u32 VRAM16ToOutput<GPUTexture::Format::BGRA8, u32>(u16 value)
{
const u32 value32 = ZeroExtend32(value);
const u32 r = VRAMConvert5To8(value32 & 31u);
@ -153,7 +153,7 @@ ALWAYS_INLINE u32 VRAM16ToOutput<HostDisplayPixelFormat::BGRA8, u32>(u16 value)
}
template<>
ALWAYS_INLINE void CopyOutRow16<HostDisplayPixelFormat::RGBA5551, u16>(const u16* src_ptr, u16* dst_ptr, u32 width)
ALWAYS_INLINE void CopyOutRow16<GPUTexture::Format::RGBA5551, u16>(const u16* src_ptr, u16* dst_ptr, u32 width)
{
u32 col = 0;
@ -188,11 +188,11 @@ ALWAYS_INLINE void CopyOutRow16<HostDisplayPixelFormat::RGBA5551, u16>(const u16
#endif
for (; col < width; col++)
*(dst_ptr++) = VRAM16ToOutput<HostDisplayPixelFormat::RGBA5551, u16>(*(src_ptr++));
*(dst_ptr++) = VRAM16ToOutput<GPUTexture::Format::RGBA5551, u16>(*(src_ptr++));
}
template<>
ALWAYS_INLINE void CopyOutRow16<HostDisplayPixelFormat::RGB565, u16>(const u16* src_ptr, u16* dst_ptr, u32 width)
ALWAYS_INLINE void CopyOutRow16<GPUTexture::Format::RGB565, u16>(const u16* src_ptr, u16* dst_ptr, u32 width)
{
u32 col = 0;
@ -229,39 +229,39 @@ ALWAYS_INLINE void CopyOutRow16<HostDisplayPixelFormat::RGB565, u16>(const u16*
#endif
for (; col < width; col++)
*(dst_ptr++) = VRAM16ToOutput<HostDisplayPixelFormat::RGB565, u16>(*(src_ptr++));
*(dst_ptr++) = VRAM16ToOutput<GPUTexture::Format::RGB565, u16>(*(src_ptr++));
}
template<>
ALWAYS_INLINE void CopyOutRow16<HostDisplayPixelFormat::RGBA8, u32>(const u16* src_ptr, u32* dst_ptr, u32 width)
ALWAYS_INLINE void CopyOutRow16<GPUTexture::Format::RGBA8, u32>(const u16* src_ptr, u32* dst_ptr, u32 width)
{
for (u32 col = 0; col < width; col++)
*(dst_ptr++) = VRAM16ToOutput<HostDisplayPixelFormat::RGBA8, u32>(*(src_ptr++));
*(dst_ptr++) = VRAM16ToOutput<GPUTexture::Format::RGBA8, u32>(*(src_ptr++));
}
template<>
ALWAYS_INLINE void CopyOutRow16<HostDisplayPixelFormat::BGRA8, u32>(const u16* src_ptr, u32* dst_ptr, u32 width)
ALWAYS_INLINE void CopyOutRow16<GPUTexture::Format::BGRA8, u32>(const u16* src_ptr, u32* dst_ptr, u32 width)
{
for (u32 col = 0; col < width; col++)
*(dst_ptr++) = VRAM16ToOutput<HostDisplayPixelFormat::BGRA8, u32>(*(src_ptr++));
*(dst_ptr++) = VRAM16ToOutput<GPUTexture::Format::BGRA8, u32>(*(src_ptr++));
}
template<HostDisplayPixelFormat display_format>
template<GPUTexture::Format display_format>
void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32 width, u32 height, u32 field, bool interlaced, bool interleaved)
{
u8* dst_ptr;
u32 dst_stride;
using OutputPixelType = std::conditional_t<
display_format == HostDisplayPixelFormat::RGBA8 || display_format == HostDisplayPixelFormat::BGRA8, u32, u16>;
display_format == GPUTexture::Format::RGBA8 || display_format == GPUTexture::Format::BGRA8, u32, u16>;
HostDisplayTexture* texture = GetDisplayTexture(width, height, display_format);
GPUTexture* texture = GetDisplayTexture(width, height, display_format);
if (!texture)
return;
if (!interlaced)
{
if (!texture->BeginUpdate(width, height, reinterpret_cast<void**>(&dst_ptr), &dst_stride))
if (!g_host_display->BeginTextureUpdate(texture, width, height, reinterpret_cast<void**>(&dst_ptr), &dst_stride))
return;
}
else
@ -309,36 +309,36 @@ void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32 width, u32 height, u32 field
}
if (!interlaced)
texture->EndUpdate(0, 0, width, height);
g_host_display->EndTextureUpdate(texture, 0, 0, width, height);
else
texture->Update(0, 0, width, height, m_display_texture_buffer.data(), output_stride);
g_host_display->UpdateTexture(texture, 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);
g_host_display->SetDisplayTexture(texture, 0, 0, width, height);
}
void GPU_SW::CopyOut15Bit(HostDisplayPixelFormat display_format, u32 src_x, u32 src_y, u32 width, u32 height, u32 field,
void GPU_SW::CopyOut15Bit(GPUTexture::Format display_format, u32 src_x, u32 src_y, u32 width, u32 height, u32 field,
bool interlaced, bool interleaved)
{
switch (display_format)
{
case HostDisplayPixelFormat::RGBA5551:
CopyOut15Bit<HostDisplayPixelFormat::RGBA5551>(src_x, src_y, width, height, field, interlaced, interleaved);
case GPUTexture::Format::RGBA5551:
CopyOut15Bit<GPUTexture::Format::RGBA5551>(src_x, src_y, width, height, field, interlaced, interleaved);
break;
case HostDisplayPixelFormat::RGB565:
CopyOut15Bit<HostDisplayPixelFormat::RGB565>(src_x, src_y, width, height, field, interlaced, interleaved);
case GPUTexture::Format::RGB565:
CopyOut15Bit<GPUTexture::Format::RGB565>(src_x, src_y, width, height, field, interlaced, interleaved);
break;
case HostDisplayPixelFormat::RGBA8:
CopyOut15Bit<HostDisplayPixelFormat::RGBA8>(src_x, src_y, width, height, field, interlaced, interleaved);
case GPUTexture::Format::RGBA8:
CopyOut15Bit<GPUTexture::Format::RGBA8>(src_x, src_y, width, height, field, interlaced, interleaved);
break;
case HostDisplayPixelFormat::BGRA8:
CopyOut15Bit<HostDisplayPixelFormat::BGRA8>(src_x, src_y, width, height, field, interlaced, interleaved);
case GPUTexture::Format::BGRA8:
CopyOut15Bit<GPUTexture::Format::BGRA8>(src_x, src_y, width, height, field, interlaced, interleaved);
break;
default:
break;
}
}
template<HostDisplayPixelFormat display_format>
template<GPUTexture::Format display_format>
void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 height, u32 field, bool interlaced,
bool interleaved)
{
@ -346,15 +346,15 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
u32 dst_stride;
using OutputPixelType = std::conditional_t<
display_format == HostDisplayPixelFormat::RGBA8 || display_format == HostDisplayPixelFormat::BGRA8, u32, u16>;
display_format == GPUTexture::Format::RGBA8 || display_format == GPUTexture::Format::BGRA8, u32, u16>;
HostDisplayTexture* texture = GetDisplayTexture(width, height, display_format);
GPUTexture* texture = GetDisplayTexture(width, height, display_format);
if (!texture)
return;
if (!interlaced)
{
if (!texture->BeginUpdate(width, height, reinterpret_cast<void**>(&dst_ptr), &dst_stride))
if (!g_host_display->BeginTextureUpdate(texture, width, height, reinterpret_cast<void**>(&dst_ptr), &dst_stride))
return;
}
else
@ -375,7 +375,7 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
const u32 src_stride = (VRAM_WIDTH << interleaved_shift) * sizeof(u16);
for (u32 row = 0; row < rows; row++)
{
if constexpr (display_format == HostDisplayPixelFormat::RGBA8)
if constexpr (display_format == GPUTexture::Format::RGBA8)
{
const u8* src_row_ptr = src_ptr;
u8* dst_row_ptr = reinterpret_cast<u8*>(dst_ptr);
@ -387,7 +387,7 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
*(dst_row_ptr++) = 0xFF;
}
}
else if constexpr (display_format == HostDisplayPixelFormat::BGRA8)
else if constexpr (display_format == GPUTexture::Format::BGRA8)
{
const u8* src_row_ptr = src_ptr;
u8* dst_row_ptr = reinterpret_cast<u8*>(dst_ptr);
@ -400,7 +400,7 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
src_row_ptr += 3;
}
}
else if constexpr (display_format == HostDisplayPixelFormat::RGB565)
else if constexpr (display_format == GPUTexture::Format::RGB565)
{
const u8* src_row_ptr = src_ptr;
u16* dst_row_ptr = reinterpret_cast<u16*>(dst_ptr);
@ -411,7 +411,7 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
src_row_ptr += 3;
}
}
else if constexpr (display_format == HostDisplayPixelFormat::RGBA5551)
else if constexpr (display_format == GPUTexture::Format::RGBA5551)
{
const u8* src_row_ptr = src_ptr;
u16* dst_row_ptr = reinterpret_cast<u16*>(dst_ptr);
@ -442,19 +442,19 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
const u8 shift = static_cast<u8>(col & 1u) * 8;
const u32 rgb = (((ZeroExtend32(s1) << 16) | ZeroExtend32(s0)) >> shift);
if constexpr (display_format == HostDisplayPixelFormat::RGBA8)
if constexpr (display_format == GPUTexture::Format::RGBA8)
{
*(dst_row_ptr++) = rgb | 0xFF000000u;
}
else if constexpr (display_format == HostDisplayPixelFormat::BGRA8)
else if constexpr (display_format == GPUTexture::Format::BGRA8)
{
*(dst_row_ptr++) = (rgb & 0x00FF00) | ((rgb & 0xFF) << 16) | ((rgb >> 16) & 0xFF) | 0xFF000000u;
}
else if constexpr (display_format == HostDisplayPixelFormat::RGB565)
else if constexpr (display_format == GPUTexture::Format::RGB565)
{
*(dst_row_ptr++) = ((rgb >> 3) & 0x1F) | (((rgb >> 10) << 5) & 0x7E0) | (((rgb >> 19) << 11) & 0x3E0000);
}
else if constexpr (display_format == HostDisplayPixelFormat::RGBA5551)
else if constexpr (display_format == GPUTexture::Format::RGBA5551)
{
*(dst_row_ptr++) = ((rgb >> 3) & 0x1F) | (((rgb >> 11) << 5) & 0x3E0) | (((rgb >> 19) << 10) & 0x1F0000);
}
@ -466,30 +466,30 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
}
if (!interlaced)
texture->EndUpdate(0, 0, width, height);
g_host_display->EndTextureUpdate(texture, 0, 0, width, height);
else
texture->Update(0, 0, width, height, m_display_texture_buffer.data(), output_stride);
g_host_display->UpdateTexture(texture, 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);
g_host_display->SetDisplayTexture(texture, 0, 0, width, height);
}
void GPU_SW::CopyOut24Bit(HostDisplayPixelFormat display_format, u32 src_x, u32 src_y, u32 skip_x, u32 width,
void GPU_SW::CopyOut24Bit(GPUTexture::Format display_format, u32 src_x, u32 src_y, u32 skip_x, u32 width,
u32 height, u32 field, bool interlaced, bool interleaved)
{
switch (display_format)
{
case HostDisplayPixelFormat::RGBA5551:
CopyOut24Bit<HostDisplayPixelFormat::RGBA5551>(src_x, src_y, skip_x, width, height, field, interlaced,
case GPUTexture::Format::RGBA5551:
CopyOut24Bit<GPUTexture::Format::RGBA5551>(src_x, src_y, skip_x, width, height, field, interlaced,
interleaved);
break;
case HostDisplayPixelFormat::RGB565:
CopyOut24Bit<HostDisplayPixelFormat::RGB565>(src_x, src_y, skip_x, width, height, field, interlaced, interleaved);
case GPUTexture::Format::RGB565:
CopyOut24Bit<GPUTexture::Format::RGB565>(src_x, src_y, skip_x, width, height, field, interlaced, interleaved);
break;
case HostDisplayPixelFormat::RGBA8:
CopyOut24Bit<HostDisplayPixelFormat::RGBA8>(src_x, src_y, skip_x, width, height, field, interlaced, interleaved);
case GPUTexture::Format::RGBA8:
CopyOut24Bit<GPUTexture::Format::RGBA8>(src_x, src_y, skip_x, width, height, field, interlaced, interleaved);
break;
case HostDisplayPixelFormat::BGRA8:
CopyOut24Bit<HostDisplayPixelFormat::BGRA8>(src_x, src_y, skip_x, width, height, field, interlaced, interleaved);
case GPUTexture::Format::BGRA8:
CopyOut24Bit<GPUTexture::Format::BGRA8>(src_x, src_y, skip_x, width, height, field, interlaced, interleaved);
break;
default:
break;

View File

@ -12,7 +12,7 @@ namespace Threading
class Thread;
}
class HostDisplayTexture;
class GPUTexture;
class GPU_SW final : public GPU
{
@ -26,7 +26,7 @@ public:
const Threading::Thread* GetSWThread() const override;
bool Initialize() override;
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override;
void Reset(bool clear_vram) override;
void UpdateSettings() override;
@ -36,15 +36,15 @@ protected:
void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask) override;
void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) override;
template<HostDisplayPixelFormat display_format>
template<GPUTexture::Format display_format>
void CopyOut15Bit(u32 src_x, u32 src_y, u32 width, u32 height, u32 field, bool interlaced, bool interleaved);
void CopyOut15Bit(HostDisplayPixelFormat display_format, u32 src_x, u32 src_y, u32 width, u32 height, u32 field,
void CopyOut15Bit(GPUTexture::Format display_format, u32 src_x, u32 src_y, u32 width, u32 height, u32 field,
bool interlaced, bool interleaved);
template<HostDisplayPixelFormat display_format>
template<GPUTexture::Format display_format>
void CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 height, u32 field, bool interlaced,
bool interleaved);
void CopyOut24Bit(HostDisplayPixelFormat display_format, u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 height,
void CopyOut24Bit(GPUTexture::Format display_format, u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 height,
u32 field, bool interlaced, bool interleaved);
void ClearDisplay() override;
@ -55,12 +55,12 @@ protected:
void FillBackendCommandParameters(GPUBackendCommand* cmd) const;
void FillDrawCommand(GPUBackendDrawCommand* cmd, GPURenderCommand rc) const;
HostDisplayTexture* GetDisplayTexture(u32 width, u32 height, HostDisplayPixelFormat format);
GPUTexture* GetDisplayTexture(u32 width, u32 height, GPUTexture::Format 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;
GPUTexture::Format m_16bit_display_format = GPUTexture::Format::RGB565;
GPUTexture::Format m_24bit_display_format = GPUTexture::Format::RGBA8;
std::unique_ptr<GPUTexture> m_display_texture;
GPU_SW_Backend m_backend;
};

View File

@ -18,27 +18,6 @@ Log_SetChannel(HostDisplay);
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()
@ -50,6 +29,18 @@ RenderAPI HostDisplay::GetPreferredAPI()
#endif
}
bool HostDisplay::UpdateTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch)
{
void* map_ptr;
u32 map_pitch;
if (!BeginTextureUpdate(texture, width, height, &map_ptr, &map_pitch))
return false;
StringUtil::StrideMemCpy(map_ptr, map_pitch, data, pitch, std::min(pitch, map_pitch), height);
EndTextureUpdate(texture, x, y, width, height);
return true;
}
bool HostDisplay::ParseFullscreenMode(const std::string_view& mode, u32* width, u32* height, float* refresh_rate)
{
if (!mode.empty())
@ -126,23 +117,6 @@ bool HostDisplay::ShouldSkipDisplayingFrame()
return false;
}
u32 HostDisplay::GetDisplayPixelFormatSize(HostDisplayPixelFormat format)
{
switch (format)
{
case HostDisplayPixelFormat::RGBA8:
case HostDisplayPixelFormat::BGRA8:
return 4;
case HostDisplayPixelFormat::RGBA5551:
case HostDisplayPixelFormat::RGB565:
return 2;
default:
return 0;
}
}
bool HostDisplay::GetHostRefreshRate(float* refresh_rate)
{
if (m_window_info.surface_refresh_rate > 0.0f)
@ -164,7 +138,7 @@ float HostDisplay::GetAndResetAccumulatedGPUTime()
return 0.0f;
}
void HostDisplay::SetSoftwareCursor(std::unique_ptr<HostDisplayTexture> texture, float scale /*= 1.0f*/)
void HostDisplay::SetSoftwareCursor(std::unique_ptr<GPUTexture> texture, float scale /*= 1.0f*/)
{
m_cursor_texture = std::move(texture);
m_cursor_texture_scale = scale;
@ -172,8 +146,8 @@ void HostDisplay::SetSoftwareCursor(std::unique_ptr<HostDisplayTexture> texture,
bool HostDisplay::SetSoftwareCursor(const void* pixels, u32 width, u32 height, u32 stride, float scale /*= 1.0f*/)
{
std::unique_ptr<HostDisplayTexture> tex =
CreateTexture(width, height, 1, 1, 1, HostDisplayPixelFormat::RGBA8, pixels, stride, false);
std::unique_ptr<GPUTexture> tex =
CreateTexture(width, height, 1, 1, 1, GPUTexture::Format::RGBA8, pixels, stride, false);
if (!tex)
return false;
@ -198,8 +172,8 @@ bool HostDisplay::SetSoftwareCursor(const char* path, float scale /*= 1.0f*/)
return false;
}
std::unique_ptr<HostDisplayTexture> tex =
CreateTexture(static_cast<u32>(width), static_cast<u32>(height), 1, 1, 1, HostDisplayPixelFormat::RGBA8, pixel_data,
std::unique_ptr<GPUTexture> tex =
CreateTexture(static_cast<u32>(width), static_cast<u32>(height), 1, 1, 1, GPUTexture::Format::RGBA8, pixel_data,
sizeof(u32) * static_cast<u32>(width), false);
stbi_image_free(pixel_data);
if (!tex)
@ -371,106 +345,10 @@ std::tuple<float, float> HostDisplay::ConvertWindowCoordinatesToDisplayCoordinat
return std::make_tuple(display_x, display_y);
}
bool HostDisplay::ConvertTextureDataToRGBA8(u32 width, u32 height, std::vector<u32>& texture_data,
u32& texture_data_stride, HostDisplayPixelFormat format)
{
switch (format)
{
case HostDisplayPixelFormat::BGRA8:
{
for (u32 y = 0; y < height; y++)
{
u32* pixels = reinterpret_cast<u32*>(reinterpret_cast<u8*>(texture_data.data()) + (y * texture_data_stride));
for (u32 x = 0; x < width; x++)
pixels[x] = (pixels[x] & 0xFF00FF00) | ((pixels[x] & 0xFF) << 16) | ((pixels[x] >> 16) & 0xFF);
}
return true;
}
case HostDisplayPixelFormat::RGBA8:
return true;
case HostDisplayPixelFormat::RGB565:
{
std::vector<u32> temp(width * height);
for (u32 y = 0; y < height; y++)
{
const u8* pixels_in = reinterpret_cast<u8*>(texture_data.data()) + (y * texture_data_stride);
u32* pixels_out = &temp[y * width];
for (u32 x = 0; x < width; x++)
{
// RGB565 -> RGBA8
u16 pixel_in;
std::memcpy(&pixel_in, pixels_in, sizeof(u16));
pixels_in += sizeof(u16);
const u8 r5 = Truncate8(pixel_in >> 11);
const u8 g6 = Truncate8((pixel_in >> 5) & 0x3F);
const u8 b5 = Truncate8(pixel_in & 0x1F);
*(pixels_out++) = ZeroExtend32((r5 << 3) | (r5 & 7)) | (ZeroExtend32((g6 << 2) | (g6 & 3)) << 8) |
(ZeroExtend32((b5 << 3) | (b5 & 7)) << 16) | (0xFF000000u);
}
}
texture_data = std::move(temp);
texture_data_stride = sizeof(u32) * width;
return true;
}
case HostDisplayPixelFormat::RGBA5551:
{
std::vector<u32> temp(width * height);
for (u32 y = 0; y < height; y++)
{
const u8* pixels_in = reinterpret_cast<u8*>(texture_data.data()) + (y * texture_data_stride);
u32* pixels_out = &temp[y * width];
for (u32 x = 0; x < width; x++)
{
// RGBA5551 -> RGBA8
u16 pixel_in;
std::memcpy(&pixel_in, pixels_in, sizeof(u16));
pixels_in += sizeof(u16);
const u8 a1 = Truncate8(pixel_in >> 15);
const u8 r5 = Truncate8((pixel_in >> 10) & 0x1F);
const u8 g6 = Truncate8((pixel_in >> 5) & 0x1F);
const u8 b5 = Truncate8(pixel_in & 0x1F);
*(pixels_out++) = ZeroExtend32((r5 << 3) | (r5 & 7)) | (ZeroExtend32((g6 << 3) | (g6 & 7)) << 8) |
(ZeroExtend32((b5 << 3) | (b5 & 7)) << 16) | (a1 ? 0xFF000000u : 0u);
}
}
texture_data = std::move(temp);
texture_data_stride = sizeof(u32) * width;
return true;
}
default:
Log_ErrorPrintf("Unknown pixel format %u", static_cast<u32>(format));
return false;
}
}
void HostDisplay::FlipTextureDataRGBA8(u32 width, u32 height, std::vector<u32>& texture_data, u32 texture_data_stride)
{
std::vector<u32> temp(width);
for (u32 flip_row = 0; flip_row < (height / 2); flip_row++)
{
u32* top_ptr = &texture_data[flip_row * width];
u32* bottom_ptr = &texture_data[((height - 1) - flip_row) * width];
std::memcpy(temp.data(), top_ptr, texture_data_stride);
std::memcpy(top_ptr, bottom_ptr, texture_data_stride);
std::memcpy(bottom_ptr, temp.data(), texture_data_stride);
}
}
static bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string filename, FileSystem::ManagedCFilePtr fp,
bool clear_alpha, bool flip_y, u32 resize_width, u32 resize_height,
std::vector<u32> texture_data, u32 texture_data_stride,
HostDisplayPixelFormat texture_format)
GPUTexture::Format texture_format)
{
const char* extension = std::strrchr(filename.c_str(), '.');
@ -480,7 +358,7 @@ static bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string fil
return false;
}
if (!HostDisplay::ConvertTextureDataToRGBA8(width, height, texture_data, texture_data_stride, texture_format))
if (!GPUTexture::ConvertTextureDataToRGBA8(width, height, texture_data, texture_data_stride, texture_format))
return false;
if (clear_alpha)
@ -490,7 +368,7 @@ static bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string fil
}
if (flip_y)
HostDisplay::FlipTextureDataRGBA8(width, height, texture_data, texture_data_stride);
GPUTexture::FlipTextureDataRGBA8(width, height, texture_data, texture_data_stride);
if (resize_width > 0 && resize_height > 0 && (resize_width != width || resize_height != height))
{
@ -542,14 +420,14 @@ static bool CompressAndWriteTextureToFile(u32 width, u32 height, std::string fil
return true;
}
bool HostDisplay::WriteTextureToFile(const void* texture_handle, u32 x, u32 y, u32 width, u32 height,
HostDisplayPixelFormat format, std::string filename, bool clear_alpha /* = true */,
bool flip_y /* = false */, u32 resize_width /* = 0 */, u32 resize_height /* = 0 */,
bool HostDisplay::WriteTextureToFile(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, std::string filename,
bool clear_alpha /* = true */, bool flip_y /* = false */,
u32 resize_width /* = 0 */, u32 resize_height /* = 0 */,
bool compress_on_thread /* = false */)
{
std::vector<u32> texture_data(width * height);
u32 texture_data_stride = Common::AlignUpPow2(GetDisplayPixelFormatSize(format) * width, 4);
if (!DownloadTexture(texture_handle, format, x, y, width, height, texture_data.data(), texture_data_stride))
u32 texture_data_stride = Common::AlignUpPow2(GPUTexture::GetPixelSize(texture->GetFormat()) * width, 4);
if (!DownloadTexture(texture, x, y, width, height, texture_data.data(), texture_data_stride))
{
Log_ErrorPrintf("Texture download failed");
return false;
@ -566,12 +444,12 @@ bool HostDisplay::WriteTextureToFile(const void* texture_handle, u32 x, u32 y, u
{
return CompressAndWriteTextureToFile(width, height, std::move(filename), std::move(fp), clear_alpha, flip_y,
resize_width, resize_height, std::move(texture_data), texture_data_stride,
format);
texture->GetFormat());
}
std::thread compress_thread(CompressAndWriteTextureToFile, width, height, std::move(filename), std::move(fp),
clear_alpha, flip_y, resize_width, resize_height, std::move(texture_data),
texture_data_stride, format);
texture_data_stride, texture->GetFormat());
compress_thread.detach();
return true;
}
@ -579,7 +457,7 @@ bool HostDisplay::WriteTextureToFile(const void* texture_handle, u32 x, u32 y, u
bool HostDisplay::WriteDisplayTextureToFile(std::string filename, bool full_resolution /* = true */,
bool apply_aspect_ratio /* = true */, bool compress_on_thread /* = false */)
{
if (!m_display_texture_handle)
if (!m_display_texture)
return false;
s32 resize_width = 0;
@ -612,18 +490,19 @@ bool HostDisplay::WriteDisplayTextureToFile(std::string filename, bool full_reso
if (flip_y)
{
read_height = -m_display_texture_view_height;
read_y = (m_display_texture_height - read_height) - (m_display_texture_height - m_display_texture_view_y);
read_y =
(m_display_texture->GetHeight() - read_height) - (m_display_texture->GetHeight() - m_display_texture_view_y);
}
return WriteTextureToFile(m_display_texture_handle, m_display_texture_view_x, read_y, m_display_texture_view_width,
read_height, m_display_texture_format, std::move(filename), true, flip_y,
static_cast<u32>(resize_width), static_cast<u32>(resize_height), compress_on_thread);
return WriteTextureToFile(m_display_texture, m_display_texture_view_x, read_y, m_display_texture_view_width,
read_height, std::move(filename), true, flip_y, static_cast<u32>(resize_width),
static_cast<u32>(resize_height), compress_on_thread);
}
bool HostDisplay::WriteDisplayTextureToBuffer(std::vector<u32>* buffer, u32 resize_width /* = 0 */,
u32 resize_height /* = 0 */, bool clear_alpha /* = true */)
{
if (!m_display_texture_handle)
if (!m_display_texture)
return false;
const bool flip_y = (m_display_texture_view_height < 0);
@ -634,22 +513,25 @@ bool HostDisplay::WriteDisplayTextureToBuffer(std::vector<u32>* buffer, u32 resi
if (flip_y)
{
read_height = -m_display_texture_view_height;
read_y = (m_display_texture_height - read_height) - (m_display_texture_height - m_display_texture_view_y);
read_y =
(m_display_texture->GetHeight() - read_height) - (m_display_texture->GetHeight() - m_display_texture_view_y);
}
u32 width = static_cast<u32>(read_width);
u32 height = static_cast<u32>(read_height);
std::vector<u32> texture_data(width * height);
u32 texture_data_stride = Common::AlignUpPow2(GetDisplayPixelFormatSize(m_display_texture_format) * width, 4);
if (!DownloadTexture(m_display_texture_handle, m_display_texture_format, read_x, read_y, width, height,
texture_data.data(), texture_data_stride))
u32 texture_data_stride = Common::AlignUpPow2(m_display_texture->GetPixelSize() * width, 4);
if (!DownloadTexture(m_display_texture, read_x, read_y, width, height, texture_data.data(), texture_data_stride))
{
Log_ErrorPrintf("Failed to download texture from GPU.");
return false;
}
if (!ConvertTextureDataToRGBA8(width, height, texture_data, texture_data_stride, m_display_texture_format))
if (!GPUTexture::ConvertTextureDataToRGBA8(width, height, texture_data, texture_data_stride,
m_display_texture->GetFormat()))
{
return false;
}
if (clear_alpha)
{
@ -704,7 +586,7 @@ bool HostDisplay::WriteScreenshotToFile(std::string filename, bool compress_on_t
std::vector<u32> pixels;
u32 pixels_stride;
HostDisplayPixelFormat pixels_format;
GPUTexture::Format pixels_format;
if (!RenderScreenshot(width, height, &pixels, &pixels_stride, &pixels_format))
{
Log_ErrorPrintf("Failed to render %ux%u screenshot", width, height);

View File

@ -1,4 +1,5 @@
#pragma once
#include "common/gpu_texture.h"
#include "common/rectangle.h"
#include "common/window_info.h"
#include "types.h"
@ -18,35 +19,6 @@ enum class RenderAPI : u32
OpenGLES
};
enum class HostDisplayPixelFormat : u32
{
Unknown,
RGBA8,
BGRA8,
RGB565,
RGBA5551,
Count
};
// An abstracted RGBA8 texture.
class HostDisplayTexture
{
public:
virtual ~HostDisplayTexture();
virtual void* GetHandle() const = 0;
virtual u32 GetWidth() const = 0;
virtual u32 GetHeight() const = 0;
virtual u32 GetLayers() const = 0;
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.
class HostDisplay
{
@ -89,7 +61,7 @@ public:
m_mouse_position_y = y;
}
ALWAYS_INLINE const void* GetDisplayTextureHandle() const { return m_display_texture_handle; }
ALWAYS_INLINE const void* GetDisplayTextureHandle() const { return m_display_texture; }
ALWAYS_INLINE s32 GetDisplayTopMargin() const { return m_display_top_margin; }
ALWAYS_INLINE s32 GetDisplayWidth() const { return m_display_width; }
ALWAYS_INLINE s32 GetDisplayHeight() const { return m_display_height; }
@ -124,18 +96,23 @@ public:
virtual void ResizeRenderWindow(s32 new_window_width, s32 new_window_height) = 0;
/// Creates an abstracted RGBA8 texture. If dynamic, the texture can be updated with UpdateTexture() below.
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 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;
virtual std::unique_ptr<GPUTexture> CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples,
GPUTexture::Format format, const void* data, u32 data_stride,
bool dynamic = false) = 0;
virtual bool BeginTextureUpdate(GPUTexture* texture, u32 width, u32 height, void** out_buffer, u32* out_pitch) = 0;
virtual void EndTextureUpdate(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height) = 0;
virtual bool UpdateTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch);
virtual bool DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, void* out_data,
u32 out_data_stride) = 0;
/// Returns false if the window was completely occluded.
virtual bool Render(bool skip_present) = 0;
/// Renders the display with postprocessing to the specified image.
virtual bool RenderScreenshot(u32 width, u32 height, std::vector<u32>* out_pixels, u32* out_stride,
HostDisplayPixelFormat* out_format) = 0;
GPUTexture::Format* out_format) = 0;
virtual void SetVSync(bool enabled) = 0;
@ -150,9 +127,7 @@ public:
void ClearDisplayTexture()
{
m_display_texture_handle = nullptr;
m_display_texture_width = 0;
m_display_texture_height = 0;
m_display_texture = nullptr;
m_display_texture_view_x = 0;
m_display_texture_view_y = 0;
m_display_texture_view_width = 0;
@ -160,13 +135,9 @@ public:
m_display_changed = true;
}
void SetDisplayTexture(void* texture_handle, HostDisplayPixelFormat texture_format, s32 texture_width,
s32 texture_height, s32 view_x, s32 view_y, s32 view_width, s32 view_height)
void SetDisplayTexture(GPUTexture* texture, s32 view_x, s32 view_y, s32 view_width, s32 view_height)
{
m_display_texture_handle = texture_handle;
m_display_texture_format = texture_format;
m_display_texture_width = texture_width;
m_display_texture_height = texture_height;
m_display_texture = texture;
m_display_texture_view_x = view_x;
m_display_texture_view_y = view_y;
m_display_texture_view_width = view_width;
@ -196,12 +167,7 @@ public:
m_display_changed = true;
}
static u32 GetDisplayPixelFormatSize(HostDisplayPixelFormat format);
static bool ConvertTextureDataToRGBA8(u32 width, u32 height, std::vector<u32>& texture_data, u32& texture_data_stride,
HostDisplayPixelFormat format);
static void FlipTextureDataRGBA8(u32 width, u32 height, std::vector<u32>& texture_data, u32 texture_data_stride);
virtual bool SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const = 0;
virtual bool SupportsTextureFormat(GPUTexture::Format format) const = 0;
virtual bool GetHostRefreshRate(float* refresh_rate);
@ -215,7 +181,7 @@ public:
void SetDisplayAlignment(Alignment alignment) { m_display_alignment = alignment; }
/// Sets the software cursor to the specified texture. Ownership of the texture is transferred.
void SetSoftwareCursor(std::unique_ptr<HostDisplayTexture> texture, float scale = 1.0f);
void SetSoftwareCursor(std::unique_ptr<GPUTexture> texture, float scale = 1.0f);
/// Sets the software cursor to the specified image.
bool SetSoftwareCursor(const void* pixels, u32 width, u32 height, u32 stride, float scale = 1.0f);
@ -235,9 +201,8 @@ public:
s32 window_height, s32 top_margin) const;
/// Helper function to save texture data to a PNG. If flip_y is set, the image will be flipped aka OpenGL.
bool WriteTextureToFile(const void* texture_handle, u32 x, u32 y, u32 width, u32 height,
HostDisplayPixelFormat format, std::string filename, bool clear_alpha = true,
bool flip_y = false, u32 resize_width = 0, u32 resize_height = 0,
bool WriteTextureToFile(GPUTexture* texture, u32 x, u32 y, u32 width, u32 height, std::string filename,
bool clear_alpha = true, bool flip_y = false, u32 resize_width = 0, u32 resize_height = 0,
bool compress_on_thread = false);
/// Helper function to save current display texture to PNG.
@ -253,7 +218,7 @@ public:
protected:
ALWAYS_INLINE bool HasSoftwareCursor() const { return static_cast<bool>(m_cursor_texture); }
ALWAYS_INLINE bool HasDisplayTexture() const { return (m_display_texture_handle != nullptr); }
ALWAYS_INLINE bool HasDisplayTexture() const { return (m_display_texture != nullptr); }
bool IsUsingLinearFiltering() const;
@ -280,10 +245,7 @@ protected:
float m_display_aspect_ratio = 1.0f;
float m_display_frame_interval = 0.0f;
void* m_display_texture_handle = nullptr;
HostDisplayPixelFormat m_display_texture_format = HostDisplayPixelFormat::Count;
s32 m_display_texture_width = 0;
s32 m_display_texture_height = 0;
GPUTexture* m_display_texture = nullptr;
s32 m_display_texture_view_x = 0;
s32 m_display_texture_view_y = 0;
s32 m_display_texture_view_width = 0;
@ -292,7 +254,7 @@ protected:
s32 m_display_top_margin = 0;
Alignment m_display_alignment = Alignment::Center;
std::unique_ptr<HostDisplayTexture> m_cursor_texture;
std::unique_ptr<GPUTexture> m_cursor_texture;
float m_cursor_texture_scale = 1.0f;
bool m_display_changed = false;
@ -313,10 +275,10 @@ void ReleaseHostDisplay();
/// Returns false if the window was completely occluded. If frame_skip is set, the frame won't be
/// displayed, but the GPU command queue will still be flushed.
//bool BeginPresentFrame(bool frame_skip);
// bool BeginPresentFrame(bool frame_skip);
/// Presents the frame to the display, and renders OSD elements.
//void EndPresentFrame();
// void EndPresentFrame();
/// Provided by the host; renders the display.
void RenderDisplay(bool skip_present);

View File

@ -72,7 +72,7 @@ SystemBootParameters::~SystemBootParameters() = default;
struct MemorySaveState
{
std::unique_ptr<HostDisplayTexture> vram_texture;
std::unique_ptr<GPUTexture> vram_texture;
std::unique_ptr<GrowableMemoryByteStream> state_stream;
};
@ -97,7 +97,7 @@ static void ClearRunningGame();
static void DestroySystem();
static std::string GetMediaPathFromSaveState(const char* path);
static bool DoLoadState(ByteStream* stream, bool force_software_renderer, bool update_display);
static bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display, bool is_memory_state);
static bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display, bool is_memory_state);
static void DoRunFrame();
static bool CreateGPU(GPURenderer renderer);
static bool SaveUndoLoadState();
@ -880,7 +880,8 @@ bool System::UpdateGameSettingsLayer()
}
}
Host::Internal::SetInputSettingsLayer(input_interface ? input_interface.get() : Host::Internal::GetBaseSettingsLayer());
Host::Internal::SetInputSettingsLayer(input_interface ? input_interface.get() :
Host::Internal::GetBaseSettingsLayer());
}
else
{
@ -1549,7 +1550,7 @@ bool System::CreateGPU(GPURenderer renderer)
return true;
}
bool System::DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display, bool is_memory_state)
bool System::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display, bool is_memory_state)
{
if (!sw.DoMarker("System"))
return false;
@ -1917,11 +1918,11 @@ bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 *
std::vector<u32> screenshot_buffer;
u32 screenshot_stride;
HostDisplayPixelFormat screenshot_format;
GPUTexture::Format screenshot_format;
if (g_host_display->RenderScreenshot(screenshot_width, screenshot_height, &screenshot_buffer, &screenshot_stride,
&screenshot_format) &&
g_host_display->ConvertTextureDataToRGBA8(screenshot_width, screenshot_height, screenshot_buffer,
screenshot_stride, screenshot_format))
GPUTexture::ConvertTextureDataToRGBA8(screenshot_width, screenshot_height, screenshot_buffer, screenshot_stride,
screenshot_format))
{
if (screenshot_stride != (screenshot_width * sizeof(u32)))
{
@ -1932,8 +1933,7 @@ bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 *
{
if (g_host_display->UsesLowerLeftOrigin())
{
g_host_display->FlipTextureDataRGBA8(screenshot_width, screenshot_height, screenshot_buffer,
screenshot_stride);
GPUTexture::FlipTextureDataRGBA8(screenshot_width, screenshot_height, screenshot_buffer, screenshot_stride);
}
header.offset_to_screenshot = static_cast<u32>(state->GetPosition());
@ -3336,7 +3336,7 @@ bool System::LoadMemoryState(const MemorySaveState& mss)
mss.state_stream->SeekAbsolute(0);
StateWrapper sw(mss.state_stream.get(), StateWrapper::Mode::Read, SAVE_STATE_VERSION);
HostDisplayTexture* host_texture = mss.vram_texture.get();
GPUTexture* host_texture = mss.vram_texture.get();
if (!DoState(sw, &host_texture, true, true))
{
Host::ReportErrorAsync("Error", "Failed to load memory save state, resetting.");
@ -3354,7 +3354,7 @@ bool System::SaveMemoryState(MemorySaveState* mss)
else
mss->state_stream->SeekAbsolute(0);
HostDisplayTexture* host_texture = mss->vram_texture.release();
GPUTexture* host_texture = mss->vram_texture.release();
StateWrapper sw(mss->state_stream.get(), StateWrapper::Mode::Write, SAVE_STATE_VERSION);
if (!DoState(sw, &host_texture, false, true))
{