HostDisplay: Common texture base class for all APIs
This commit is contained in:
@ -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())
|
||||
{
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user