Move over all except VRAM write

This commit is contained in:
Stenzek 2023-08-02 01:51:26 +10:00
parent ac73e7b050
commit ba4eeb5e94
21 changed files with 707 additions and 1257 deletions

View File

@ -293,8 +293,6 @@ bool GPU::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_displ
return !sw.HasError();
}
void GPU::ResetGraphicsAPIState() {}
void GPU::RestoreGraphicsAPIState() {}
void GPU::UpdateDMARequest()

View File

@ -88,7 +88,6 @@ public:
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();
virtual void RestoreGraphicsAPIState();
// Render statistics debug window.
@ -192,6 +191,9 @@ public:
// Dumps raw VRAM to a file.
bool DumpVRAMToFile(const char* filename);
// Ensures all buffered vertices are drawn.
virtual void FlushRender();
protected:
TickCount CRTCTicksToSystemTicks(TickCount crtc_ticks, TickCount fractional_ticks) const;
TickCount SystemTicksToCRTCTicks(TickCount sysclk_ticks, TickCount* fractional_ticks) const;
@ -291,7 +293,6 @@ protected:
virtual void UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask);
virtual void CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height);
virtual void DispatchRenderCommand();
virtual void FlushRender();
virtual void ClearDisplay();
virtual void UpdateDisplay();
virtual void DrawRendererStats(bool is_idle_frame);

View File

@ -110,35 +110,6 @@ bool D3D11Device::DownloadTexture(GPUTexture* texture, u32 x, u32 y, u32 width,
return true;
}
void D3D11Device::CommitClear(GPUTexture* t)
{
D3D11Texture* T = static_cast<D3D11Texture*>(t);
if (T->GetState() == GPUTexture::State::Dirty)
return;
// TODO: 11.1
if (T->IsDepthStencil())
{
if (T->GetState() == GPUTexture::State::Invalidated)
; // m_context->DiscardView(T->GetD3DDSV());
else
m_context->ClearDepthStencilView(T->GetD3DDSV(), D3D11_CLEAR_DEPTH, T->GetClearDepth(), 0);
}
else if (T->IsRenderTarget())
{
if (T->GetState() == GPUTexture::State::Invalidated)
; // m_context->DiscardView(T->GetD3DRTV());
else
m_context->ClearRenderTargetView(T->GetD3DRTV(), T->GetUNormClearColor().data());
}
else
{
return;
}
T->SetState(GPUTexture::State::Dirty);
}
bool D3D11Device::CheckStagingBufferSize(u32 width, u32 height, DXGI_FORMAT format)
{
if (m_readback_staging_texture_width >= width && m_readback_staging_texture_width >= height &&
@ -191,19 +162,29 @@ void D3D11Device::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 d
D3D11Texture* dst11 = static_cast<D3D11Texture*>(dst);
D3D11Texture* src11 = static_cast<D3D11Texture*>(src);
if (src11->GetState() == GPUTexture::State::Cleared)
if (dst11->IsRenderTargetOrDepthStencil())
{
if (src11->GetWidth() == dst11->GetWidth() && src11->GetHeight() == dst11->GetHeight())
if (src11->GetState() == GPUTexture::State::Cleared)
{
// pass clear through
dst11->m_state = src11->m_state;
dst11->m_clear_value = src11->m_clear_value;
return;
if (src11->GetWidth() == dst11->GetWidth() && src11->GetHeight() == dst11->GetHeight())
{
// pass clear through
dst11->m_state = src11->m_state;
dst11->m_clear_value = src11->m_clear_value;
return;
}
}
else if (dst_x == 0 && dst_y == 0 && width == dst11->GetMipWidth(dst_level) &&
height == dst11->GetMipHeight(dst_level))
{
// TODO: 11.1 discard
dst11->SetState(GPUTexture::State::Dirty);
}
dst11->CommitClear(m_context.Get());
}
CommitClear(src11);
CommitClear(dst11);
src11->CommitClear(m_context.Get());
const CD3D11_BOX src_box(static_cast<LONG>(src_x), static_cast<LONG>(src_y), 0, static_cast<LONG>(src_x + width),
static_cast<LONG>(src_y + height), 1);
@ -227,13 +208,15 @@ void D3D11Device::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u3
// DX11 can't resolve partial rects.
Assert(src_x == dst_x && src_y == dst_y);
CommitClear(src);
CommitClear(dst);
D3D11Texture* dst11 = static_cast<D3D11Texture*>(dst);
D3D11Texture* src11 = static_cast<D3D11Texture*>(src);
m_context->ResolveSubresource(
static_cast<D3D11Texture*>(dst)->GetD3DTexture(), D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()),
static_cast<D3D11Texture*>(src)->GetD3DTexture(), D3D11CalcSubresource(src_level, src_layer, src->GetLevels()),
static_cast<D3D11Texture*>(dst)->GetDXGIFormat());
src11->CommitClear(m_context.Get());
dst11->CommitClear(m_context.Get());
m_context->ResolveSubresource(dst11->GetD3DTexture(), D3D11CalcSubresource(dst_level, dst_layer, dst->GetLevels()),
src11->GetD3DTexture(), D3D11CalcSubresource(src_level, src_layer, src->GetLevels()),
dst11->GetDXGIFormat());
}
bool D3D11Device::GetHostRefreshRate(float* refresh_rate)
@ -645,7 +628,7 @@ bool D3D11Device::CreateBuffers()
{
if (!m_vertex_buffer.Create(m_device.Get(), D3D11_BIND_VERTEX_BUFFER, VERTEX_BUFFER_SIZE) ||
!m_index_buffer.Create(m_device.Get(), D3D11_BIND_INDEX_BUFFER, INDEX_BUFFER_SIZE) ||
!m_push_uniform_buffer.Create(m_device.Get(), D3D11_BIND_CONSTANT_BUFFER, PUSH_UNIFORM_BUFFER_SIZE))
!m_uniform_buffer.Create(m_device.Get(), D3D11_BIND_CONSTANT_BUFFER, MAX_UNIFORM_BUFFER_SIZE))
{
Log_ErrorPrintf("Failed to create vertex/index/uniform buffers.");
return false;
@ -656,7 +639,7 @@ bool D3D11Device::CreateBuffers()
void D3D11Device::DestroyBuffers()
{
m_push_uniform_buffer.Release();
m_uniform_buffer.Release();
m_vertex_buffer.Release();
m_index_buffer.Release();
}
@ -678,6 +661,7 @@ bool D3D11Device::Render(bool skip_present)
m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), s_clear_color.data());
m_context->OMSetRenderTargets(1, m_swap_chain_rtv.GetAddressOf(), nullptr);
m_current_framebuffer = nullptr;
RenderDisplay();
@ -695,7 +679,7 @@ bool D3D11Device::Render(bool skip_present)
if (m_gpu_timing_enabled)
KickTimestampQuery();
return true;
}
@ -1571,20 +1555,45 @@ void D3D11Device::UnmapIndexBuffer(u32 used_index_count)
void D3D11Device::PushUniformBuffer(const void* data, u32 data_size)
{
Assert(data_size <= PUSH_UNIFORM_BUFFER_SIZE);
Assert(data_size <= MAX_UNIFORM_BUFFER_SIZE);
const auto res = m_push_uniform_buffer.Map(m_context.Get(), PUSH_UNIFORM_BUFFER_SIZE, PUSH_UNIFORM_BUFFER_SIZE);
const auto res = m_uniform_buffer.Map(m_context.Get(), MAX_UNIFORM_BUFFER_SIZE, MAX_UNIFORM_BUFFER_SIZE);
std::memcpy(res.pointer, data, data_size);
m_push_uniform_buffer.Unmap(m_context.Get(), data_size);
m_uniform_buffer.Unmap(m_context.Get(), data_size);
m_context->VSSetConstantBuffers(0, 1, m_push_uniform_buffer.GetD3DBufferArray());
m_context->PSSetConstantBuffers(0, 1, m_push_uniform_buffer.GetD3DBufferArray());
m_context->VSSetConstantBuffers(0, 1, m_uniform_buffer.GetD3DBufferArray());
m_context->PSSetConstantBuffers(0, 1, m_uniform_buffer.GetD3DBufferArray());
}
void* D3D11Device::MapUniformBuffer(u32 size)
{
Assert(size <= MAX_UNIFORM_BUFFER_SIZE);
const auto res = m_uniform_buffer.Map(m_context.Get(), MAX_UNIFORM_BUFFER_SIZE, MAX_UNIFORM_BUFFER_SIZE);
return res.pointer;
}
void D3D11Device::UnmapUniformBuffer(u32 size)
{
m_uniform_buffer.Unmap(m_context.Get(), size);
m_context->VSSetConstantBuffers(0, 1, m_uniform_buffer.GetD3DBufferArray());
m_context->PSSetConstantBuffers(0, 1, m_uniform_buffer.GetD3DBufferArray());
}
void D3D11Device::SetFramebuffer(GPUFramebuffer* fb)
{
D3D11Framebuffer* FB = static_cast<D3D11Framebuffer*>(fb);
m_context->OMSetRenderTargets(FB->GetNumRTVs(), FB->GetRTVArray(), FB->GetDSV());
if (m_current_framebuffer == fb)
return;
m_current_framebuffer = static_cast<D3D11Framebuffer*>(fb);
if (!m_current_framebuffer)
{
m_context->OMSetRenderTargets(0, nullptr, nullptr);
return;
}
m_context->OMSetRenderTargets(m_current_framebuffer->GetNumRTVs(), m_current_framebuffer->GetRTVArray(),
m_current_framebuffer->GetDSV());
}
void D3D11Device::UnbindFramebuffer(D3D11Framebuffer* fb)

View File

@ -195,6 +195,8 @@ public:
void MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index) override;
void UnmapIndexBuffer(u32 used_index_count) override;
void PushUniformBuffer(const void* data, u32 data_size) override;
void* MapUniformBuffer(u32 size) override;
void UnmapUniformBuffer(u32 size);
void SetFramebuffer(GPUFramebuffer* fb) override;
void SetPipeline(GPUPipeline* pipeline) override;
void SetTextureSampler(u32 slot, GPUTexture* texture, GPUSampler* sampler) override;
@ -225,14 +227,14 @@ private:
using InputLayoutMap =
std::unordered_map<GPUPipeline::InputLayout, ComPtr<ID3D11InputLayout>, GPUPipeline::InputLayoutHash>;
static constexpr u32 PUSH_UNIFORM_BUFFER_SIZE = 64;
// Currently we don't stream uniforms, instead just re-map the buffer every time and let the driver take care of it.
static constexpr u32 MAX_UNIFORM_BUFFER_SIZE = 64;
static constexpr u32 VERTEX_BUFFER_SIZE = 8 * 1024 * 1024;
static constexpr u32 INDEX_BUFFER_SIZE = 4 * 1024 * 1024;
static constexpr u8 NUM_TIMESTAMP_QUERIES = 3;
static AdapterAndModeList GetAdapterAndModeList(IDXGIFactory* dxgi_factory);
void CommitClear(GPUTexture* t);
void PreDrawCheck();
bool CheckStagingBufferSize(u32 width, u32 height, DXGI_FORMAT format);
@ -278,7 +280,7 @@ private:
D3D11::StreamBuffer m_vertex_buffer;
D3D11::StreamBuffer m_index_buffer;
D3D11::StreamBuffer m_push_uniform_buffer;
D3D11::StreamBuffer m_uniform_buffer;
D3D11Framebuffer* m_current_framebuffer = nullptr;
D3D11Pipeline* m_current_pipeline = nullptr;

View File

@ -56,6 +56,30 @@ D3D11_TEXTURE2D_DESC D3D11Texture::GetDesc() const
return desc;
}
void D3D11Texture::CommitClear(ID3D11DeviceContext* context)
{
if (m_state == GPUTexture::State::Dirty)
return;
// TODO: 11.1
if (IsDepthStencil())
{
if (m_state == GPUTexture::State::Invalidated)
; // context->DiscardView(GetD3DDSV());
else
context->ClearDepthStencilView(GetD3DDSV(), D3D11_CLEAR_DEPTH, GetClearDepth(), 0);
}
else if (IsRenderTarget())
{
if (m_state == GPUTexture::State::Invalidated)
; // context->DiscardView(GetD3DRTV());
else
context->ClearRenderTargetView(GetD3DRTV(), GetUNormClearColor().data());
}
m_state = GPUTexture::State::Dirty;
}
bool D3D11Texture::IsValid() const
{
return static_cast<bool>(m_texture);
@ -80,7 +104,10 @@ bool D3D11Texture::Update(u32 x, u32 y, u32 width, u32 height, const void* data,
static_cast<LONG>(y + height), 1);
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
D3D11Device::GetD3DContext()->UpdateSubresource(m_texture.Get(), srnum, &box, data, pitch, 0);
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
CommitClear(context);
context->UpdateSubresource(m_texture.Get(), srnum, &box, data, pitch, 0);
m_state = GPUTexture::State::Dirty;
return true;
}
@ -92,9 +119,12 @@ bool D3D11Texture::Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32
const bool discard = (width == m_width && height == m_height);
const u32 srnum = D3D11CalcSubresource(level, layer, m_levels);
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
CommitClear(context);
D3D11_MAPPED_SUBRESOURCE sr;
HRESULT hr = D3D11Device::GetD3DContext()->Map(m_texture.Get(), srnum,
discard ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_READ_WRITE, 0, &sr);
HRESULT hr = context->Map(m_texture.Get(), srnum, discard ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_READ_WRITE, 0, &sr);
if (FAILED(hr))
{
Log_ErrorPrintf("Map pixels texture failed: %08X", hr);
@ -104,6 +134,7 @@ bool D3D11Texture::Map(void** map, u32* map_stride, u32 x, u32 y, u32 width, u32
*map = static_cast<u8*>(sr.pData) + (y * sr.RowPitch) + (x * GetPixelSize());
*map_stride = sr.RowPitch;
m_mapped_subresource = srnum;
m_state = GPUTexture::State::Dirty;
return true;
}
@ -284,6 +315,7 @@ bool D3D11Texture::Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture)
m_levels = static_cast<u8>(desc.MipLevels);
m_samples = static_cast<u8>(desc.SampleDesc.Count);
m_dynamic = (desc.Usage == D3D11_USAGE_DYNAMIC);
m_state = GPUTexture::State::Dirty;
return true;
}

View File

@ -61,6 +61,7 @@ public:
void Destroy();
D3D11_TEXTURE2D_DESC GetDesc() const;
void CommitClear(ID3D11DeviceContext* context);
bool IsValid() const override;

View File

@ -388,6 +388,26 @@ void GPUDevice::PushUniformBuffer(const void* data, u32 data_size)
UnreachableCode();
}
void* GPUDevice::MapUniformBuffer(u32 size)
{
// TODO: REMOVE ME
UnreachableCode();
return nullptr;
}
void GPUDevice::UnmapUniformBuffer(u32 size)
{
// TODO: REMOVE ME
UnreachableCode();
}
void GPUDevice::UploadUniformBuffer(const void* data, u32 data_size)
{
void* map = MapUniformBuffer(data_size);
std::memcpy(map, data, data_size);
UnmapUniformBuffer(data_size);
}
void GPUDevice::SetFramebuffer(GPUFramebuffer* fb)
{
// TODO: REMOVE ME

View File

@ -457,6 +457,9 @@ public:
/// Uniform buffer abstraction.
virtual void PushUniformBuffer(const void* data, u32 data_size);
virtual void* MapUniformBuffer(u32 size);
virtual void UnmapUniformBuffer(u32 size);
void UploadUniformBuffer(const void* data, u32 data_size);
/// Drawing setup abstraction.
virtual void SetFramebuffer(GPUFramebuffer* fb);

View File

@ -23,6 +23,7 @@ void GPUTexture::ClearBaseProperties()
m_levels = 0;
m_samples = 0;
m_format = GPUTexture::Format::Unknown;
m_state = State::Dirty;
}
u32 GPUTexture::GPUTexture::GetPixelSize(GPUTexture::Format format)

View File

@ -21,6 +21,11 @@
#include <tuple>
Log_SetChannel(GPU_HW);
// TODO: instead of full state restore, only restore what changed
static constexpr GPUTexture::Format VRAM_RT_FORMAT = GPUTexture::Format::RGBA8;
static constexpr GPUTexture::Format VRAM_DS_FORMAT = GPUTexture::Format::D16;
template<typename T>
ALWAYS_INLINE static constexpr std::tuple<T, T> MinMax(T v1, T v2)
{
@ -48,6 +53,8 @@ GPU_HW::GPU_HW() : GPU()
GPU_HW::~GPU_HW()
{
g_host_display->ClearDisplayTexture();
if (m_sw_renderer)
{
m_sw_renderer->Shutdown();
@ -110,6 +117,19 @@ bool GPU_HW::Initialize()
UpdateSoftwareRenderer(false);
PrintSettingsToLog();
if (!CompilePipelines())
{
Log_ErrorPrintf("Failed to compile pipelines");
return false;
}
if (!CreateFramebuffer())
{
Log_ErrorPrintf("Failed to create framebuffer");
return false;
}
return true;
}
@ -128,7 +148,8 @@ void GPU_HW::Reset(bool clear_vram)
m_batch_ubo_dirty = true;
m_current_depth = 1;
SetFullVRAMDirtyRectangle();
if (clear_vram)
ClearFramebuffer();
}
bool GPU_HW::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display)
@ -183,6 +204,15 @@ bool GPU_HW::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_di
return true;
}
void GPU_HW::RestoreGraphicsAPIState()
{
g_host_display->SetTextureSampler(0, m_vram_read_texture.get(), g_host_display->GetPointSampler());
g_host_display->SetFramebuffer(m_vram_framebuffer.get());
g_host_display->SetViewport(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight());
SetScissor();
m_batch_ubo_dirty = true;
}
void GPU_HW::UpdateSettings()
{
// TODO: Merge UpdateHWSettings() into here.
@ -193,7 +223,6 @@ void GPU_HW::UpdateSettings()
{
RestoreGraphicsAPIState();
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
ResetGraphicsAPIState();
g_host_display->ClearDisplayTexture();
CreateFramebuffer();
}
@ -211,7 +240,6 @@ void GPU_HW::UpdateSettings()
UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr, false, false);
UpdateDepthBufferFromMaskBit();
UpdateDisplay();
ResetGraphicsAPIState();
}
}
@ -382,21 +410,19 @@ bool GPU_HW::CreateFramebuffer()
const u32 texture_width = VRAM_WIDTH * m_resolution_scale;
const u32 texture_height = VRAM_HEIGHT * m_resolution_scale;
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 = g_host_display->CreateTexture(texture_width, texture_height, 1, 1, samples,
GPUTexture::Type::RenderTarget, texture_format)) ||
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)) ||
!(m_vram_depth_texture = g_host_display->CreateTexture(texture_width, texture_height, 1, 1, samples,
GPUTexture::Type::DepthStencil, depth_format)) ||
GPUTexture::Type::DepthStencil, VRAM_DS_FORMAT)) ||
!(m_vram_read_texture = g_host_display->CreateTexture(texture_width, texture_height, 1, 1, 1,
GPUTexture::Type::Texture, texture_format)) ||
GPUTexture::Type::Texture, VRAM_RT_FORMAT)) ||
!(m_display_texture = g_host_display->CreateTexture(
((m_downsample_mode == GPUDownsampleMode::Adaptive) ? VRAM_WIDTH : GPU_MAX_DISPLAY_WIDTH) *
m_resolution_scale,
GPU_MAX_DISPLAY_HEIGHT * m_resolution_scale, 1, 1, 1, GPUTexture::Type::RenderTarget, texture_format)) ||
GPU_MAX_DISPLAY_HEIGHT * m_resolution_scale, 1, 1, 1, GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)) ||
!(m_vram_readback_texture = g_host_display->CreateTexture(VRAM_WIDTH / 2, VRAM_HEIGHT, 1, 1, 1,
GPUTexture::Type::RenderTarget, texture_format)))
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)))
{
return false;
}
@ -419,9 +445,64 @@ bool GPU_HW::CreateFramebuffer()
GL_OBJECT_NAME(m_display_framebuffer, "Display Framebuffer");
Log_InfoPrintf("Created HW framebuffer of %ux%u", texture_width, texture_height);
#if 0
if (m_downsample_mode == GPUDownsampleMode::Adaptive)
{
const u32 levels = GetAdaptiveDownsamplingMipLevels();
if (!m_downsample_texture.Create(m_device.Get(), texture_width, texture_height, 1, static_cast<u16>(levels), 1,
GPUTexture::Type::RenderTarget, texture_format) ||
!m_downsample_weight_texture.Create(m_device.Get(), texture_width >> (levels - 1),
texture_height >> (levels - 1), 1, 1, 1, GPUTexture::Type::RenderTarget,
GPUTexture::Format::R8))
{
return false;
}
m_downsample_mip_views.resize(levels);
for (u32 i = 0; i < levels; i++)
{
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(m_downsample_texture, D3D11_SRV_DIMENSION_TEXTURE2D,
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);
HRESULT hr = m_device->CreateShaderResourceView(m_downsample_texture, &srv_desc,
m_downsample_mip_views[i].first.GetAddressOf());
if (FAILED(hr))
return false;
hr = m_device->CreateRenderTargetView(m_downsample_texture, &rtv_desc,
m_downsample_mip_views[i].second.GetAddressOf());
if (FAILED(hr))
return false;
}
}
else if (m_downsample_mode == GPUDownsampleMode::Box)
{
if (!m_downsample_texture.Create(m_device.Get(), VRAM_WIDTH, VRAM_HEIGHT, 1, 1, 1, GPUTexture::Type::RenderTarget,
texture_format))
{
return false;
}
}
#endif
g_host_display->SetFramebuffer(m_vram_framebuffer.get());
SetFullVRAMDirtyRectangle();
return true;
}
void GPU_HW::ClearFramebuffer()
{
g_host_display->ClearRenderTarget(m_vram_texture.get(), 0);
g_host_display->ClearDepth(m_vram_depth_texture.get(), m_pgxp_depth_buffer ? 1.0f : 0.0f);
g_host_display->ClearRenderTarget(m_display_texture.get(), 0);
ClearVRAMDirtyRectangle();
m_last_depth_z = 1.0f;
}
void GPU_HW::DestroyFramebuffer()
{
m_display_framebuffer.reset();
@ -514,8 +595,8 @@ bool GPU_HW::CompilePipelines()
plconfig.input_layout.vertex_stride = sizeof(BatchVertex);
plconfig.rasterization = GPUPipeline::RasterizationState::GetNoCullState();
plconfig.primitive = GPUPipeline::Primitive::Triangles;
plconfig.color_format = GPUTexture::Format::RGBA8;
plconfig.depth_format = GPUTexture::Format::D16;
plconfig.color_format = VRAM_RT_FORMAT;
plconfig.depth_format = VRAM_DS_FORMAT;
plconfig.samples = m_multisamples;
plconfig.per_sample_shading = m_per_sample_shading;
@ -661,6 +742,8 @@ bool GPU_HW::CompilePipelines()
if (!(m_vram_copy_pipelines[depth_test] = g_host_display->CreatePipeline(plconfig)))
return false;
GL_OBJECT_NAME(m_vram_copy_pipelines[depth_test], "VRAM Write Pipeline, depth=%u", depth_test);
progress.Increment();
}
}
@ -683,38 +766,35 @@ bool GPU_HW::CompilePipelines()
if (!(m_vram_write_pipelines[depth_test] = g_host_display->CreatePipeline(plconfig)))
return false;
GL_OBJECT_NAME(m_vram_write_pipelines[depth_test], "VRAM Write Pipeline, depth=%u", depth_test);
progress.Increment();
}
}
#if 0
// VRAM update depth
// TODO
{
std::unique_ptr<GPUShader> fs = g_host_display->CreateShader(
GPUShader::Stage::Pixel, shadergen.GenerateVRAMUpdateDepthFragmentShader());
std::unique_ptr<GPUShader> fs =
g_host_display->CreateShader(GPUShaderStage::Fragment, shadergen.GenerateVRAMUpdateDepthFragmentShader());
if (!fs)
return false;
gpbuilder.SetRenderPass(m_vram_update_depth_render_pass, 0);
gpbuilder.SetPipelineLayout(m_single_sampler_pipeline_layout);
gpbuilder.SetFragmentShader(fs);
gpbuilder.SetDepthState(true, true, VK_COMPARE_OP_ALWAYS);
gpbuilder.SetBlendAttachment(0, false, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD,
VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, 0);
// COLOR MASK ZERO
plconfig.pixel_shader = fs.get();
plconfig.color_format = GPUTexture::Format::Unknown;
plconfig.depth_format = VRAM_DS_FORMAT;
plconfig.depth = GPUPipeline::DepthState::GetAlwaysWriteState();
plconfig.blend.write_mask = 0;
m_vram_update_depth_pipeline = gpbuilder.Create(device, pipeline_cache, false);
vkDestroyShaderModule(device, fs, nullptr);
if (m_vram_update_depth_pipeline == VK_NULL_HANDLE)
if (!(m_vram_update_depth_pipeline = g_host_display->CreatePipeline(plconfig)))
return false;
Vulkan::Util::SetObjectName(g_vulkan_context->GetDevice(), m_vram_update_depth_pipeline,
"VRAM Update Depth Pipeline");
GL_OBJECT_NAME(m_vram_update_depth_pipeline, "VRAM Update Depth Pipeline");
progress.Increment();
}
#endif
plconfig.color_format = VRAM_RT_FORMAT;
plconfig.depth_format = GPUTexture::Format::Unknown;
plconfig.depth = GPUPipeline::DepthState::GetNoTestsState();
plconfig.blend = GPUPipeline::BlendState::GetNoBlendingState();
@ -757,6 +837,17 @@ bool GPU_HW::CompilePipelines()
}
}
{
std::unique_ptr<GPUShader> fs =
g_host_display->CreateShader(GPUShaderStage::Fragment, shadergen.GenerateCopyFragmentShader());
if (!fs)
return false;
plconfig.pixel_shader = fs.get();
if (!(m_copy_pipeline = g_host_display->CreatePipeline(plconfig)))
return false;
}
#if 0
if (m_downsample_mode == GPUDownsampleMode::Adaptive)
{
@ -905,6 +996,42 @@ void GPU_HW::UpdateVRAMReadTexture()
ClearVRAMDirtyRectangle();
}
void GPU_HW::UpdateDepthBufferFromMaskBit()
{
if (m_pgxp_depth_buffer)
return;
// Viewport should already be set full, only need to fudge the scissor.
g_host_display->SetScissor(0, 0, m_vram_texture->GetWidth(), m_vram_texture->GetHeight());
g_host_display->SetFramebuffer(m_vram_update_depth_framebuffer.get());
g_host_display->SetPipeline(m_vram_update_depth_pipeline.get());
g_host_display->SetTextureSampler(0, m_vram_texture.get(), g_host_display->GetPointSampler());
g_host_display->Draw(3, 0);
// Restore.
g_host_display->SetTextureSampler(0, m_vram_read_texture.get(), g_host_display->GetPointSampler());
g_host_display->SetFramebuffer(m_vram_framebuffer.get());
SetScissor();
}
void GPU_HW::ClearDepthBuffer()
{
DebugAssert(m_pgxp_depth_buffer);
g_host_display->ClearDepth(m_vram_depth_texture.get(), 1.0f);
m_last_depth_z = 1.0f;
}
void GPU_HW::SetScissor()
{
const s32 left = m_drawing_area.left * m_resolution_scale;
const s32 right = std::max<u32>((m_drawing_area.right + 1) * m_resolution_scale, left + 1);
const s32 top = m_drawing_area.top * m_resolution_scale;
const s32 bottom = std::max<u32>((m_drawing_area.bottom + 1) * m_resolution_scale, top + 1);
g_host_display->SetScissor(left, top, right - left, bottom - top);
}
void GPU_HW::MapBatchVertexPointer(u32 required_vertices)
{
DebugAssert(!m_batch_start_vertex_ptr);
@ -940,111 +1067,8 @@ void GPU_HW::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32
void GPU_HW::ClearDisplay()
{
Panic("Not implemented");
}
void GPU_HW::UpdateDisplay()
{
FlushRender();
if (g_settings.debugging.show_vram)
{
if (IsUsingMultisampling())
{
UpdateVRAMReadTexture();
g_host_display->SetDisplayTexture(m_vram_read_texture.get(), 0, 0, m_vram_read_texture->GetWidth(),
m_vram_read_texture->GetHeight());
}
else
{
g_host_display->SetDisplayTexture(m_vram_texture.get(), 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));
}
else
{
g_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
GetDisplayAspectRatio());
const u32 resolution_scale = m_GPUSTAT.display_area_color_depth_24 ? 1 : m_resolution_scale;
const u32 vram_offset_x = m_crtc_state.display_vram_left;
const u32 vram_offset_y = m_crtc_state.display_vram_top;
const u32 scaled_vram_offset_x = vram_offset_x * resolution_scale;
const u32 scaled_vram_offset_y = vram_offset_y * resolution_scale;
const u32 display_width = m_crtc_state.display_vram_width;
const u32 display_height = m_crtc_state.display_vram_height;
const u32 scaled_display_width = display_width * resolution_scale;
const u32 scaled_display_height = display_height * resolution_scale;
const InterlacedRenderMode interlaced = GetInterlacedRenderMode();
if (IsDisplayDisabled())
{
g_host_display->ClearDisplayTexture();
}
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == InterlacedRenderMode::None &&
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture->GetWidth() &&
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight())
{
if (IsUsingDownsampling())
{
#if 0
DownsampleFramebuffer(GetVRAMTexture(), scaled_vram_offset_x, scaled_vram_offset_y, scaled_display_width,
scaled_display_height);
#else
Panic("Fixme");
#endif
}
else
{
g_host_display->SetDisplayTexture(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y,
scaled_display_width, scaled_display_height);
}
}
else
{
// TODO: discard vs load for interlaced
if (interlaced == InterlacedRenderMode::None)
g_host_display->InvalidateRenderTarget(m_display_texture.get());
g_host_display->SetPipeline(
m_display_pipelines[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)][static_cast<u8>(interlaced)].get());
g_host_display->SetFramebuffer(m_display_framebuffer.get());
const u32 reinterpret_field_offset = (interlaced != InterlacedRenderMode::None) ? GetInterlacedDisplayField() : 0;
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_vram_offset_y + reinterpret_field_offset,
reinterpret_crop_left, reinterpret_field_offset};
g_host_display->PushUniformBuffer(uniforms, sizeof(uniforms));
Assert(scaled_display_width <= m_display_texture->GetWidth() &&
scaled_display_height <= m_display_texture->GetHeight());
g_host_display->SetViewportAndScissor(0, 0, scaled_display_width, scaled_display_height);
g_host_display->Draw(3, 0);
if (IsUsingDownsampling())
{
#if 0
DownsampleFramebuffer(GetDisplayTexture(), 0, 0, scaled_display_width, scaled_display_height);
#else
Panic("Fixme");
#endif
}
else
{
g_host_display->SetDisplayTexture(m_display_texture.get(), 0, 0, scaled_display_width, scaled_display_height);
}
RestoreGraphicsAPIState();
}
}
g_host_display->ClearDisplayTexture();
g_host_display->ClearRenderTarget(m_display_texture.get(), 0xFF000000u);
}
void GPU_HW::HandleFlippedQuadTextureCoordinates(BatchVertex* vertices)
@ -1720,14 +1744,6 @@ void GPU_HW::LoadVertices()
}
}
void GPU_HW::CalcScissorRect(int* left, int* top, int* right, int* bottom)
{
*left = m_drawing_area.left * m_resolution_scale;
*right = std::max<u32>((m_drawing_area.right + 1) * m_resolution_scale, *left + 1);
*top = m_drawing_area.top * m_resolution_scale;
*bottom = std::max<u32>((m_drawing_area.bottom + 1) * m_resolution_scale, *top + 1);
}
GPU_HW::VRAMFillUBOData GPU_HW::GetVRAMFillUBOData(u32 x, u32 y, u32 width, u32 height, u32 color) const
{
// drop precision unless true colour is enabled
@ -1798,6 +1814,40 @@ GPU_HW::VRAMCopyUBOData GPU_HW::GetVRAMCopyUBOData(u32 src_x, u32 src_y, u32 dst
return uniforms;
}
bool GPU_HW::BlitVRAMReplacementTexture(const TextureReplacementTexture* tex, u32 dst_x, u32 dst_y, u32 width,
u32 height)
{
if (!m_vram_replacement_texture || m_vram_replacement_texture->GetWidth() < tex->GetWidth() ||
m_vram_replacement_texture->GetHeight() < tex->GetHeight())
{
m_vram_replacement_texture.reset();
if (!(m_vram_replacement_texture =
g_host_display->CreateTexture(tex->GetWidth(), tex->GetHeight(), 1, 1, 1, GPUTexture::Type::Texture,
GPUTexture::Format::RGBA8, tex->GetPixels(), tex->GetPitch(), true)))
{
return false;
}
}
else
{
if (!m_vram_replacement_texture->Update(0, 0, width, height, tex->GetPixels(), tex->GetPitch()))
{
Log_ErrorPrintf("Update %ux%u texture failed.", width, height);
return false;
}
}
g_host_display->SetFramebuffer(m_vram_framebuffer.get()); // TODO: needed?
g_host_display->SetTextureSampler(0, m_vram_replacement_texture.get(), g_host_display->GetLinearSampler());
g_host_display->SetPipeline(m_copy_pipeline.get());
g_host_display->SetViewportAndScissor(dst_x, dst_y, width, height);
g_host_display->Draw(3, 0);
RestoreGraphicsAPIState();
return true;
}
void GPU_HW::IncludeVRAMDirtyRectangle(const Common::Rectangle<u32>& rect)
{
m_vram_dirty_rect.Include(rect);
@ -1976,8 +2026,56 @@ void GPU_HW::CopySoftwareRendererVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y
void GPU_HW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
{
if (IsUsingSoftwareRendererForReadbacks())
FillSoftwareRendererVRAM(x, y, width, height, color);
IncludeVRAMDirtyRectangle(
Common::Rectangle<u32>::FromExtents(x, y, width, height).Clamped(0, 0, VRAM_WIDTH, VRAM_HEIGHT));
g_host_display->SetPipeline(m_vram_fill_pipelines[BoolToUInt8(IsVRAMFillOversized(x, y, width, height))]
[BoolToUInt8(IsInterlacedRenderingEnabled())]
.get());
const Common::Rectangle<u32> bounds(GetVRAMTransferBounds(x, y, width, height));
g_host_display->SetViewportAndScissor(bounds.left * m_resolution_scale, bounds.top * m_resolution_scale,
bounds.GetWidth() * m_resolution_scale,
bounds.GetHeight() * m_resolution_scale);
const VRAMFillUBOData uniforms = GetVRAMFillUBOData(x, y, width, height, color);
g_host_display->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_host_display->Draw(3, 0);
RestoreGraphicsAPIState();
}
void GPU_HW::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
{
if (IsUsingSoftwareRendererForReadbacks())
{
ReadSoftwareRendererVRAM(x, y, width, height);
return;
}
// Get bounds with wrap-around handled.
const Common::Rectangle<u32> copy_rect = GetVRAMTransferBounds(x, y, width, height);
const u32 encoded_width = (copy_rect.GetWidth() + 1) / 2;
const u32 encoded_height = copy_rect.GetHeight();
// Encode the 24-bit texture as 16-bit.
const u32 uniforms[4] = {copy_rect.left, copy_rect.top, copy_rect.GetWidth(), copy_rect.GetHeight()};
g_host_display->SetPipeline(m_vram_readback_pipeline.get());
g_host_display->SetFramebuffer(m_vram_readback_framebuffer.get());
g_host_display->SetTextureSampler(0, m_vram_texture.get(), g_host_display->GetPointSampler());
g_host_display->SetViewportAndScissor(0, 0, encoded_width, encoded_height);
g_host_display->PushUniformBuffer(uniforms, sizeof(uniforms));
g_host_display->Draw(3, 0);
// Stage the readback and copy it into our shadow buffer.
g_host_display->DownloadTexture(m_vram_readback_texture.get(), 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();
}
void GPU_HW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask)
@ -1994,6 +2092,44 @@ void GPU_HW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, b
void GPU_HW::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height)
{
if (IsUsingSoftwareRendererForReadbacks())
CopySoftwareRendererVRAM(src_x, src_y, dst_x, dst_y, width, height);
if (UseVRAMCopyShader(src_x, src_y, dst_x, dst_y, width, height) || IsUsingMultisampling())
{
const Common::Rectangle<u32> src_bounds = GetVRAMTransferBounds(src_x, src_y, width, height);
const Common::Rectangle<u32> dst_bounds = GetVRAMTransferBounds(dst_x, dst_y, width, height);
if (m_vram_dirty_rect.Intersects(src_bounds))
UpdateVRAMReadTexture();
IncludeVRAMDirtyRectangle(dst_bounds);
const VRAMCopyUBOData uniforms = GetVRAMCopyUBOData(src_x, src_y, dst_x, dst_y, width, height);
// VRAM read texture should already be bound.
const Common::Rectangle<u32> dst_bounds_scaled(dst_bounds * m_resolution_scale);
g_host_display->SetViewportAndScissor(dst_bounds_scaled.left, dst_bounds_scaled.top, dst_bounds_scaled.GetWidth(),
dst_bounds_scaled.GetHeight());
g_host_display->SetPipeline(
m_vram_copy_pipelines[BoolToUInt8(m_GPUSTAT.check_mask_before_draw && !m_pgxp_depth_buffer)].get());
g_host_display->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_host_display->Draw(3, 0);
RestoreGraphicsAPIState();
if (m_GPUSTAT.check_mask_before_draw && !m_pgxp_depth_buffer)
m_current_depth++;
return;
}
// We can't CopySubresourceRegion to the same resource. So use the shadow texture if we can, but that may need to be
// updated first. Copying to the same resource seemed to work on Windows 10, but breaks on Windows 7. But, it's
// against the API spec, so better to be safe than sorry.
// TODO: make this an optional feature, DX12 can do it
if (m_vram_dirty_rect.Intersects(Common::Rectangle<u32>::FromExtents(src_x, src_y, width, height)))
UpdateVRAMReadTexture();
IncludeVRAMDirtyRectangle(
Common::Rectangle<u32>::FromExtents(dst_x, dst_y, width, height).Clamped(0, 0, VRAM_WIDTH, VRAM_HEIGHT));
@ -2002,6 +2138,10 @@ void GPU_HW::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32
// set new vertex counter since we want this to take into consideration previous masked pixels
m_current_depth++;
}
g_host_display->CopyTextureRegion(m_vram_texture.get(), dst_x * m_resolution_scale, dst_y * m_resolution_scale, 0, 0,
m_vram_read_texture.get(), src_x * m_resolution_scale, src_y * m_resolution_scale,
0, 0, width * m_resolution_scale, height * m_resolution_scale);
}
void GPU_HW::DispatchRenderCommand()
@ -2102,7 +2242,7 @@ void GPU_HW::DispatchRenderCommand()
if (m_drawing_area_changed)
{
m_drawing_area_changed = false;
SetScissorFromDrawingArea();
SetScissor();
if (m_pgxp_depth_buffer && m_last_depth_z < 1.0f)
ClearDepthBuffer();
@ -2131,7 +2271,8 @@ void GPU_HW::FlushRender()
if (m_batch_ubo_dirty)
{
UploadUniformBuffer(&m_batch_ubo_data, sizeof(m_batch_ubo_data));
g_host_display->UploadUniformBuffer(&m_batch_ubo_data, sizeof(m_batch_ubo_data));
m_renderer_stats.num_uniform_buffer_updates++;
m_batch_ubo_dirty = false;
}
@ -2148,6 +2289,206 @@ void GPU_HW::FlushRender()
}
}
void GPU_HW::UpdateDisplay()
{
FlushRender();
if (g_settings.debugging.show_vram)
{
if (IsUsingMultisampling())
{
UpdateVRAMReadTexture();
g_host_display->SetDisplayTexture(m_vram_read_texture.get(), 0, 0, m_vram_read_texture->GetWidth(),
m_vram_read_texture->GetHeight());
}
else
{
g_host_display->SetDisplayTexture(m_vram_texture.get(), 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));
}
else
{
g_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
GetDisplayAspectRatio());
const u32 resolution_scale = m_GPUSTAT.display_area_color_depth_24 ? 1 : m_resolution_scale;
const u32 vram_offset_x = m_crtc_state.display_vram_left;
const u32 vram_offset_y = m_crtc_state.display_vram_top;
const u32 scaled_vram_offset_x = vram_offset_x * resolution_scale;
const u32 scaled_vram_offset_y = vram_offset_y * resolution_scale;
const u32 display_width = m_crtc_state.display_vram_width;
const u32 display_height = m_crtc_state.display_vram_height;
const u32 scaled_display_width = display_width * resolution_scale;
const u32 scaled_display_height = display_height * resolution_scale;
const InterlacedRenderMode interlaced = GetInterlacedRenderMode();
if (IsDisplayDisabled())
{
g_host_display->ClearDisplayTexture();
}
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == InterlacedRenderMode::None &&
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture->GetWidth() &&
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture->GetHeight())
{
if (IsUsingDownsampling())
{
DownsampleFramebuffer(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y, scaled_display_width,
scaled_display_height);
}
else
{
g_host_display->SetDisplayTexture(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y,
scaled_display_width, scaled_display_height);
}
}
else
{
// TODO: discard vs load for interlaced
if (interlaced == InterlacedRenderMode::None)
g_host_display->InvalidateRenderTarget(m_display_texture.get());
g_host_display->SetPipeline(
m_display_pipelines[BoolToUInt8(m_GPUSTAT.display_area_color_depth_24)][static_cast<u8>(interlaced)].get());
g_host_display->SetFramebuffer(m_display_framebuffer.get());
const u32 reinterpret_field_offset = (interlaced != InterlacedRenderMode::None) ? GetInterlacedDisplayField() : 0;
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_vram_offset_y + reinterpret_field_offset,
reinterpret_crop_left, reinterpret_field_offset};
g_host_display->PushUniformBuffer(uniforms, sizeof(uniforms));
Assert(scaled_display_width <= m_display_texture->GetWidth() &&
scaled_display_height <= m_display_texture->GetHeight());
g_host_display->SetViewportAndScissor(0, 0, scaled_display_width, scaled_display_height);
g_host_display->Draw(3, 0);
if (IsUsingDownsampling())
DownsampleFramebuffer(m_display_texture.get(), 0, 0, scaled_display_width, scaled_display_height);
else
g_host_display->SetDisplayTexture(m_display_texture.get(), 0, 0, scaled_display_width, scaled_display_height);
RestoreGraphicsAPIState();
}
}
}
void GPU_HW::DownsampleFramebuffer(const GPUTexture* source, u32 left, u32 top, u32 width, u32 height)
{
if (m_downsample_mode == GPUDownsampleMode::Adaptive)
DownsampleFramebufferAdaptive(source, left, top, width, height);
else
DownsampleFramebufferBoxFilter(source, left, top, width, height);
}
void GPU_HW::DownsampleFramebufferAdaptive(const GPUTexture* source, u32 left, u32 top, u32 width, u32 height)
{
#if 0
CD3D11_BOX src_box(left, top, 0, left + width, top + height, 1);
m_context->OMSetDepthStencilState(m_depth_disabled_state.Get(), 0);
m_context->OMSetBlendState(m_blend_disabled_state.Get(), nullptr, 0xFFFFFFFFu);
m_context->CopySubresourceRegion(m_downsample_texture, 0, left, top, 0, source->GetD3DTexture(), 0, &src_box);
m_context->PSSetSamplers(0, 1, m_point_sampler_state.GetAddressOf());
m_context->VSSetShader(m_uv_quad_vertex_shader.Get(), nullptr, 0);
// create mip chain
const u32 levels = m_downsample_texture.GetLevels();
for (u32 level = 1; level < levels; level++)
{
static constexpr float clear_color[4] = {};
SetViewportAndScissor(left >> level, top >> level, width >> level, height >> level);
m_context->ClearRenderTargetView(m_downsample_mip_views[level].second.Get(), clear_color);
m_context->OMSetRenderTargets(1, m_downsample_mip_views[level].second.GetAddressOf(), nullptr);
m_context->PSSetShaderResources(0, 1, m_downsample_mip_views[level - 1].first.GetAddressOf());
const SmoothingUBOData ubo = GetSmoothingUBO(level, left, top, width, height, m_downsample_texture.GetWidth(),
m_downsample_texture.GetHeight());
m_context->PSSetShader(
(level == 1) ? m_downsample_first_pass_pixel_shader.Get() : m_downsample_mid_pass_pixel_shader.Get(), nullptr, 0);
UploadUniformBuffer(&ubo, sizeof(ubo));
m_context->Draw(3, 0);
}
// blur pass at lowest level
{
const u32 last_level = levels - 1;
static constexpr float clear_color[4] = {};
SetViewportAndScissor(left >> last_level, top >> last_level, width >> last_level, height >> last_level);
m_context->ClearRenderTargetView(m_downsample_weight_texture.GetD3DRTV(), clear_color);
m_context->OMSetRenderTargets(1, m_downsample_weight_texture.GetD3DRTVArray(), nullptr);
m_context->PSSetShaderResources(0, 1, m_downsample_mip_views.back().first.GetAddressOf());
m_context->PSSetShader(m_downsample_blur_pass_pixel_shader.Get(), nullptr, 0);
const SmoothingUBOData ubo = GetSmoothingUBO(last_level, left, top, width, height, m_downsample_texture.GetWidth(),
m_downsample_texture.GetHeight());
m_context->PSSetShader(m_downsample_blur_pass_pixel_shader.Get(), nullptr, 0);
UploadUniformBuffer(&ubo, sizeof(ubo));
m_context->Draw(3, 0);
}
// composite downsampled and upsampled images together
{
SetViewportAndScissor(left, top, width, height);
m_context->OMSetRenderTargets(1, GetDisplayTexture()->GetD3DRTVArray(), nullptr);
ID3D11ShaderResourceView* const srvs[2] = {m_downsample_texture.GetD3DSRV(),
m_downsample_weight_texture.GetD3DSRV()};
ID3D11SamplerState* const samplers[2] = {m_trilinear_sampler_state.Get(), m_linear_sampler_state.Get()};
m_context->PSSetShaderResources(0, countof(srvs), srvs);
m_context->PSSetSamplers(0, countof(samplers), samplers);
m_context->PSSetShader(m_downsample_composite_pixel_shader.Get(), nullptr, 0);
m_context->Draw(3, 0);
}
ID3D11ShaderResourceView* const null_srvs[2] = {};
m_context->PSSetShaderResources(0, countof(null_srvs), null_srvs);
m_batch_ubo_dirty = true;
RestoreGraphicsAPIState();
g_host_display->SetDisplayTexture(m_display_texture.get(), left, top, width, height);
#else
Panic("Not implemented");
#endif
}
void GPU_HW::DownsampleFramebufferBoxFilter(const GPUTexture* source, u32 left, u32 top, u32 width, u32 height)
{
#if 0
const u32 ds_left = left / m_resolution_scale;
const u32 ds_top = top / m_resolution_scale;
const u32 ds_width = width / m_resolution_scale;
const u32 ds_height = height / m_resolution_scale;
static constexpr float clear_color[4] = {};
m_context->ClearRenderTargetView(m_downsample_texture.GetD3DRTV(), clear_color);
m_context->OMSetDepthStencilState(m_depth_disabled_state.Get(), 0);
m_context->OMSetRenderTargets(1, m_downsample_texture.GetD3DRTVArray(), nullptr);
m_context->OMSetBlendState(m_blend_disabled_state.Get(), nullptr, 0xFFFFFFFFu);
m_context->VSSetShader(m_screen_quad_vertex_shader.Get(), nullptr, 0);
m_context->PSSetShader(m_downsample_first_pass_pixel_shader.Get(), nullptr, 0);
m_context->PSSetShaderResources(0, 1, source->GetD3DSRVArray());
SetViewportAndScissor(ds_left, ds_top, ds_width, ds_height);
m_context->Draw(3, 0);
RestoreGraphicsAPIState();
g_host_display->SetDisplayTexture(&m_downsample_texture, ds_left, ds_top, ds_width, ds_height);
#else
Panic("Not implemented");
#endif
}
void GPU_HW::DrawRendererStats(bool is_idle_frame)
{
if (!is_idle_frame)

View File

@ -2,10 +2,14 @@
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#include "common/dimensional_array.h"
#include "common/heap_array.h"
#include "gpu.h"
#include "gpu/gpu_device.h"
#include "texture_replacements.h"
#include "common/dimensional_array.h"
#include "common/heap_array.h"
#include <sstream>
#include <string>
#include <tuple>
@ -35,15 +39,17 @@ public:
};
GPU_HW();
virtual ~GPU_HW();
~GPU_HW() override;
const Threading::Thread* GetSWThread() const override;
virtual bool Initialize() override;
virtual void Reset(bool clear_vram) override;
virtual bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override;
bool Initialize() override;
void Reset(bool clear_vram) override;
bool DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_display) override;
virtual void UpdateSettings() override;
void RestoreGraphicsAPIState() override;
void UpdateSettings() override;
void UpdateResolutionScale() override final;
std::tuple<u32, u32> GetEffectiveDisplayResolution(bool scaled = true) override final;
std::tuple<u32, u32> GetFullDisplayResolution(bool scaled = true) override final;
@ -131,6 +137,7 @@ protected:
u32 u_set_mask_while_drawing;
};
// TODO: move all these to source
struct VRAMFillUBOData
{
u32 u_dst_x;
@ -202,22 +209,22 @@ protected:
void UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed);
virtual bool CreateFramebuffer();
virtual void DestroyFramebuffer();
bool CreateFramebuffer();
void ClearFramebuffer();
void DestroyFramebuffer();
bool CompilePipelines();
void DestroyPipelines();
void UpdateVRAMReadTexture();
virtual void UpdateDepthBufferFromMaskBit() = 0;
virtual void ClearDepthBuffer() = 0;
virtual void SetScissorFromDrawingArea() = 0;
virtual void MapBatchVertexPointer(u32 required_vertices);
virtual void UnmapBatchVertexPointer(u32 used_vertices);
virtual void UploadUniformBuffer(const void* uniforms, u32 uniforms_size) = 0;
virtual void DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices);
virtual void ClearDisplay();
virtual void UpdateDisplay();
void UpdateDepthBufferFromMaskBit();
void ClearDepthBuffer();
void SetScissor();
void MapBatchVertexPointer(u32 required_vertices);
void UnmapBatchVertexPointer(u32 used_vertices);
void DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices);
void ClearDisplay();
void UpdateDisplay();
u32 CalculateResolutionScale() const;
GPUDownsampleMode GetDownsampleMode(u32 resolution_scale) const;
@ -313,14 +320,13 @@ protected:
void CopySoftwareRendererVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height);
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override;
void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override;
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;
void DispatchRenderCommand() override;
void FlushRender() override;
void DrawRendererStats(bool is_idle_frame) override;
void CalcScissorRect(int* left, int* top, int* right, int* bottom);
std::tuple<s32, s32> ScaleVRAMCoordinates(s32 x, s32 y) const
{
return std::make_tuple(x * s32(m_resolution_scale), y * s32(m_resolution_scale));
@ -337,6 +343,8 @@ protected:
bool check_mask) const;
VRAMCopyUBOData GetVRAMCopyUBOData(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) const;
bool BlitVRAMReplacementTexture(const TextureReplacementTexture* tex, u32 dst_x, u32 dst_y, u32 width, u32 height);
/// Expands a line into two triangles.
void DrawLine(float x0, float y0, u32 col0, float x1, float y1, u32 col1, float depth);
@ -365,11 +373,16 @@ protected:
SmoothingUBOData GetSmoothingUBO(u32 level, u32 left, u32 top, u32 width, u32 height, u32 tex_width,
u32 tex_height) const;
void DownsampleFramebuffer(const GPUTexture* source, u32 left, u32 top, u32 width, u32 height);
void DownsampleFramebufferAdaptive(const GPUTexture* source, u32 left, u32 top, u32 width, u32 height);
void DownsampleFramebufferBoxFilter(const GPUTexture* source, u32 left, u32 top, u32 width, u32 height);
std::unique_ptr<GPUTexture> m_vram_texture;
std::unique_ptr<GPUTexture> m_vram_depth_texture;
std::unique_ptr<GPUTexture> m_vram_depth_view;
std::unique_ptr<GPUTexture> m_vram_read_texture;
std::unique_ptr<GPUTexture> m_vram_readback_texture;
std::unique_ptr<GPUTexture> m_vram_replacement_texture;
std::unique_ptr<GPUTexture> m_display_texture;
std::unique_ptr<GPUFramebuffer> m_vram_framebuffer;
@ -439,6 +452,9 @@ protected:
// [depth_24][interlace_mode]
DimensionalArray<std::unique_ptr<GPUPipeline>, 3, 2> m_display_pipelines{};
// TODO: get rid of this, and use image blits instead where supported
std::unique_ptr<GPUPipeline> m_copy_pipeline;
std::unique_ptr<GPUPipeline> m_downsample_first_pass_pipeline;
std::unique_ptr<GPUPipeline> m_downsample_mid_pass_pipeline;
std::unique_ptr<GPUPipeline> m_downsample_blur_pass_pipeline;

View File

@ -5,7 +5,7 @@
#include "common/assert.h"
#include "common/log.h"
#include "common/timer.h"
#include "gpu/d3d11/shader_compiler.h"
#include "gpu/d3d11_device.h"
#include "gpu/gpu_device.h"
#include "gpu_hw_shadergen.h"
#include "gpu_sw_backend.h"
@ -14,15 +14,9 @@
#include "util/state_wrapper.h"
Log_SetChannel(GPU_HW_D3D11);
GPU_HW_D3D11::GPU_HW_D3D11(ID3D11Device* device, ID3D11DeviceContext* context) : m_device(device), m_context(context) {}
GPU_HW_D3D11::GPU_HW_D3D11() = default;
GPU_HW_D3D11::~GPU_HW_D3D11()
{
g_host_display->ClearDisplayTexture();
DestroyShaders();
DestroyStateObjects();
}
GPU_HW_D3D11::~GPU_HW_D3D11() = default;
GPURenderer GPU_HW_D3D11::GetRendererType() const
{
@ -36,76 +30,26 @@ bool GPU_HW_D3D11::Initialize()
if (!GPU_HW::Initialize())
return false;
if (!CreateFramebuffer())
{
Log_ErrorPrintf("Failed to create framebuffer");
return false;
}
if (!CreateUniformBuffer())
{
Log_ErrorPrintf("Failed to create uniform buffer");
return false;
}
if (!CreateTextureBuffer())
{
Log_ErrorPrintf("Failed to create texture buffer");
return false;
}
if (!CreateStateObjects())
{
Log_ErrorPrintf("Failed to create state objects");
return false;
}
if (!CompileShaders())
{
Log_ErrorPrintf("Failed to compile shaders");
return false;
}
RestoreGraphicsAPIState();
return true;
}
void GPU_HW_D3D11::Reset(bool clear_vram)
{
GPU_HW::Reset(clear_vram);
if (clear_vram)
ClearFramebuffer();
}
void GPU_HW_D3D11::ResetGraphicsAPIState()
{
GPU_HW::ResetGraphicsAPIState();
// In D3D11 we can't leave a buffer mapped across a Present() call.
FlushRender();
}
void GPU_HW_D3D11::RestoreGraphicsAPIState()
{
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_context->PSSetShaderResources(0, 1, GetVRAMReadTexture()->GetD3DSRVArray());
m_context->PSSetSamplers(0, 1, m_point_sampler_state.GetAddressOf());
m_context->OMSetRenderTargets(1, GetVRAMTexture()->GetD3DRTVArray(), GetVRAMDepthTexture()->GetD3DDSV());
m_context->RSSetState(m_cull_none_rasterizer_state.Get());
SetViewport(0, 0, GetVRAMTexture()->GetWidth(), GetVRAMTexture()->GetHeight());
SetScissorFromDrawingArea();
m_batch_ubo_dirty = true;
}
void GPU_HW_D3D11::SetCapabilities()
{
const u32 max_texture_size = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
const u32 max_texture_scale = max_texture_size / VRAM_WIDTH;
ID3D11Device* device = D3D11Device::GetD3DDevice();
m_max_resolution_scale = max_texture_scale;
m_supports_dual_source_blend = true;
m_supports_per_sample_shading = (m_device->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_1);
m_supports_per_sample_shading = (device->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_1);
m_supports_adaptive_downsampling = true;
m_supports_disable_color_perspective = true;
@ -114,7 +58,7 @@ void GPU_HW_D3D11::SetCapabilities()
{
UINT num_quality_levels;
if (SUCCEEDED(
m_device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, multisamples, &num_quality_levels)) &&
device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, multisamples, &num_quality_levels)) &&
num_quality_levels > 0)
{
m_max_multisamples = multisamples;
@ -122,95 +66,17 @@ void GPU_HW_D3D11::SetCapabilities()
}
}
bool GPU_HW_D3D11::CreateFramebuffer()
{
if (!GPU_HW::CreateFramebuffer())
return false;
const u32 texture_width = m_vram_texture->GetWidth();
const u32 texture_height = m_vram_texture->GetHeight();
const GPUTexture::Format texture_format = m_vram_texture->GetFormat();
if (m_downsample_mode == GPUDownsampleMode::Adaptive)
{
const u32 levels = GetAdaptiveDownsamplingMipLevels();
if (!m_downsample_texture.Create(m_device.Get(), texture_width, texture_height, 1, static_cast<u16>(levels), 1,
GPUTexture::Type::RenderTarget, texture_format) ||
!m_downsample_weight_texture.Create(m_device.Get(), texture_width >> (levels - 1),
texture_height >> (levels - 1), 1, 1, 1, GPUTexture::Type::RenderTarget,
GPUTexture::Format::R8))
{
return false;
}
m_downsample_mip_views.resize(levels);
for (u32 i = 0; i < levels; i++)
{
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(m_downsample_texture, D3D11_SRV_DIMENSION_TEXTURE2D,
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);
HRESULT hr = m_device->CreateShaderResourceView(m_downsample_texture, &srv_desc,
m_downsample_mip_views[i].first.GetAddressOf());
if (FAILED(hr))
return false;
hr = m_device->CreateRenderTargetView(m_downsample_texture, &rtv_desc,
m_downsample_mip_views[i].second.GetAddressOf());
if (FAILED(hr))
return false;
}
}
else if (m_downsample_mode == GPUDownsampleMode::Box)
{
if (!m_downsample_texture.Create(m_device.Get(), VRAM_WIDTH, VRAM_HEIGHT, 1, 1, 1, GPUTexture::Type::RenderTarget,
texture_format))
{
return false;
}
}
m_context->OMSetRenderTargets(1, GetVRAMTexture()->GetD3DRTVArray(), nullptr);
SetFullVRAMDirtyRectangle();
return true;
}
void GPU_HW_D3D11::ClearFramebuffer()
{
static constexpr std::array<float, 4> color = {};
m_context->ClearRenderTargetView(GetVRAMTexture()->GetD3DRTV(), color.data());
m_context->ClearDepthStencilView(GetVRAMDepthTexture()->GetD3DDSV(), D3D11_CLEAR_DEPTH,
m_pgxp_depth_buffer ? 1.0f : 0.0f, 0);
m_context->ClearRenderTargetView(GetDisplayTexture()->GetD3DRTV(), color.data());
SetFullVRAMDirtyRectangle();
m_last_depth_z = 1.0f;
}
void GPU_HW_D3D11::DestroyFramebuffer()
{
m_downsample_mip_views.clear();
m_downsample_weight_texture.Destroy();
m_downsample_texture.Destroy();
GPU_HW::DestroyFramebuffer();
}
bool GPU_HW_D3D11::CreateUniformBuffer()
{
return m_uniform_stream_buffer.Create(m_device.Get(), D3D11_BIND_CONSTANT_BUFFER, MAX_UNIFORM_BUFFER_SIZE);
}
bool GPU_HW_D3D11::CreateTextureBuffer()
{
if (!m_texture_stream_buffer.Create(m_device.Get(), D3D11_BIND_SHADER_RESOURCE, VRAM_UPDATE_TEXTURE_BUFFER_SIZE))
ID3D11Device* device = D3D11Device::GetD3DDevice();
if (!m_texture_stream_buffer.Create(device, D3D11_BIND_SHADER_RESOURCE, VRAM_UPDATE_TEXTURE_BUFFER_SIZE))
return false;
const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(D3D11_SRV_DIMENSION_BUFFER, DXGI_FORMAT_R16_UINT, 0,
VRAM_UPDATE_TEXTURE_BUFFER_SIZE / sizeof(u16));
const HRESULT hr = m_device->CreateShaderResourceView(m_texture_stream_buffer.GetD3DBuffer(), &srv_desc,
m_texture_stream_buffer_srv_r16ui.ReleaseAndGetAddressOf());
const HRESULT hr = device->CreateShaderResourceView(m_texture_stream_buffer.GetD3DBuffer(), &srv_desc,
m_texture_stream_buffer_srv_r16ui.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
Log_ErrorPrintf("Creation of texture buffer SRV failed: 0x%08X", hr);
@ -220,404 +86,6 @@ bool GPU_HW_D3D11::CreateTextureBuffer()
return true;
}
bool GPU_HW_D3D11::CreateStateObjects()
{
HRESULT hr;
CD3D11_RASTERIZER_DESC rs_desc = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT());
rs_desc.CullMode = D3D11_CULL_NONE;
rs_desc.ScissorEnable = TRUE;
rs_desc.MultisampleEnable = IsUsingMultisampling();
rs_desc.DepthClipEnable = FALSE;
hr = m_device->CreateRasterizerState(&rs_desc, m_cull_none_rasterizer_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
if (IsUsingMultisampling())
{
rs_desc.MultisampleEnable = FALSE;
hr = m_device->CreateRasterizerState(&rs_desc, m_cull_none_rasterizer_state_no_msaa.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
}
else
{
m_cull_none_rasterizer_state_no_msaa = m_cull_none_rasterizer_state;
}
CD3D11_DEPTH_STENCIL_DESC ds_desc = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT());
ds_desc.DepthEnable = FALSE;
ds_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
hr = m_device->CreateDepthStencilState(&ds_desc, m_depth_disabled_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
ds_desc.DepthEnable = TRUE;
ds_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
ds_desc.DepthFunc = D3D11_COMPARISON_ALWAYS;
hr = m_device->CreateDepthStencilState(&ds_desc, m_depth_test_always_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
ds_desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;
hr = m_device->CreateDepthStencilState(&ds_desc, m_depth_test_less_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
ds_desc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL;
hr = m_device->CreateDepthStencilState(&ds_desc, m_depth_test_greater_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
CD3D11_BLEND_DESC bl_desc = CD3D11_BLEND_DESC(CD3D11_DEFAULT());
hr = m_device->CreateBlendState(&bl_desc, m_blend_disabled_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
bl_desc.RenderTarget[0].RenderTargetWriteMask = 0;
hr = m_device->CreateBlendState(&bl_desc, m_blend_no_color_writes_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
CD3D11_SAMPLER_DESC sampler_desc = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT());
sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
hr = m_device->CreateSamplerState(&sampler_desc, m_point_sampler_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
sampler_desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
hr = m_device->CreateSamplerState(&sampler_desc, m_linear_sampler_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
hr = m_device->CreateSamplerState(&sampler_desc, m_trilinear_sampler_state.ReleaseAndGetAddressOf());
if (FAILED(hr))
return false;
return true;
}
void GPU_HW_D3D11::DestroyStateObjects()
{
m_linear_sampler_state.Reset();
m_point_sampler_state.Reset();
m_trilinear_sampler_state.Reset();
m_blend_no_color_writes_state.Reset();
m_blend_disabled_state.Reset();
m_depth_test_greater_state.Reset();
m_depth_test_less_state.Reset();
m_depth_test_always_state.Reset();
m_depth_disabled_state.Reset();
m_cull_none_rasterizer_state.Reset();
m_cull_none_rasterizer_state_no_msaa.Reset();
}
bool GPU_HW_D3D11::CompileShaders()
{
if (!GPU_HW::CompilePipelines())
return false;
D3D11::ShaderCache shader_cache;
#if 0
shader_cache.Open(EmuFolders::Cache, m_device->GetFeatureLevel(), SHADER_CACHE_VERSION,
g_settings.gpu_use_debug_device);
#endif
GPU_HW_ShaderGen shadergen(g_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
m_pgxp_depth_buffer, m_disable_color_perspective, m_supports_dual_source_blend);
ShaderCompileProgressTracker progress("Compiling Shaders",
1 + 1 + 2 + (4 * 9 * 2 * 2) + 1 + (2 * 2) + 4 + (2 * 3) + 1);
m_screen_quad_vertex_shader =
shader_cache.GetVertexShader(m_device.Get(), shadergen.GenerateScreenQuadVertexShader());
m_uv_quad_vertex_shader = shader_cache.GetVertexShader(m_device.Get(), shadergen.GenerateUVQuadVertexShader());
if (!m_screen_quad_vertex_shader || !m_uv_quad_vertex_shader)
return false;
progress.Increment();
m_copy_pixel_shader = shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateCopyFragmentShader());
if (!m_copy_pixel_shader)
return false;
progress.Increment();
for (u8 wrapped = 0; wrapped < 2; wrapped++)
{
for (u8 interlaced = 0; interlaced < 2; interlaced++)
{
const std::string ps =
shadergen.GenerateVRAMFillFragmentShader(ConvertToBoolUnchecked(wrapped), ConvertToBoolUnchecked(interlaced));
m_vram_fill_pixel_shaders[wrapped][interlaced] = shader_cache.GetPixelShader(m_device.Get(), ps);
if (!m_vram_fill_pixel_shaders[wrapped][interlaced])
return false;
progress.Increment();
}
}
m_vram_read_pixel_shader = shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateVRAMReadFragmentShader());
if (!m_vram_read_pixel_shader)
return false;
progress.Increment();
m_vram_write_pixel_shader =
shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateVRAMWriteFragmentShader(false));
if (!m_vram_write_pixel_shader)
return false;
progress.Increment();
m_vram_copy_pixel_shader = shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateVRAMCopyFragmentShader());
if (!m_vram_copy_pixel_shader)
return false;
progress.Increment();
m_vram_update_depth_pixel_shader =
shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateVRAMUpdateDepthFragmentShader());
if (!m_vram_update_depth_pixel_shader)
return false;
progress.Increment();
for (u8 depth_24bit = 0; depth_24bit < 2; depth_24bit++)
{
for (u8 interlacing = 0; interlacing < 3; interlacing++)
{
const std::string ps = shadergen.GenerateDisplayFragmentShader(
ConvertToBoolUnchecked(depth_24bit), static_cast<InterlacedRenderMode>(interlacing),
ConvertToBoolUnchecked(depth_24bit) && m_chroma_smoothing);
m_display_pixel_shaders[depth_24bit][interlacing] = shader_cache.GetPixelShader(m_device.Get(), ps);
if (!m_display_pixel_shaders[depth_24bit][interlacing])
return false;
progress.Increment();
}
}
if (m_downsample_mode == GPUDownsampleMode::Adaptive)
{
m_downsample_first_pass_pixel_shader =
shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateAdaptiveDownsampleMipFragmentShader(true));
m_downsample_mid_pass_pixel_shader =
shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateAdaptiveDownsampleMipFragmentShader(false));
m_downsample_blur_pass_pixel_shader =
shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateAdaptiveDownsampleBlurFragmentShader());
m_downsample_composite_pixel_shader =
shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateAdaptiveDownsampleCompositeFragmentShader());
if (!m_downsample_first_pass_pixel_shader || !m_downsample_mid_pass_pixel_shader ||
!m_downsample_blur_pass_pixel_shader || !m_downsample_composite_pixel_shader)
{
return false;
}
}
else if (m_downsample_mode == GPUDownsampleMode::Box)
{
m_downsample_first_pass_pixel_shader =
shader_cache.GetPixelShader(m_device.Get(), shadergen.GenerateBoxSampleDownsampleFragmentShader());
if (!m_downsample_first_pass_pixel_shader)
return false;
}
progress.Increment();
#undef UPDATE_PROGRESS
return true;
}
void GPU_HW_D3D11::DestroyShaders()
{
m_downsample_composite_pixel_shader.Reset();
m_downsample_blur_pass_pixel_shader.Reset();
m_downsample_mid_pass_pixel_shader.Reset();
m_downsample_first_pass_pixel_shader.Reset();
m_display_pixel_shaders = {};
m_vram_update_depth_pixel_shader.Reset();
m_vram_copy_pixel_shader.Reset();
m_vram_write_pixel_shader.Reset();
m_vram_read_pixel_shader.Reset();
m_vram_fill_pixel_shaders = {};
m_copy_pixel_shader.Reset();
m_uv_quad_vertex_shader.Reset();
m_screen_quad_vertex_shader.Reset();
GPU_HW::DestroyPipelines();
}
void GPU_HW_D3D11::UploadUniformBuffer(const void* data, u32 data_size)
{
Assert(data_size <= MAX_UNIFORM_BUFFER_SIZE);
const auto res = m_uniform_stream_buffer.Map(m_context.Get(), MAX_UNIFORM_BUFFER_SIZE, data_size);
std::memcpy(res.pointer, data, data_size);
m_uniform_stream_buffer.Unmap(m_context.Get(), data_size);
m_context->VSSetConstantBuffers(0, 1, m_uniform_stream_buffer.GetD3DBufferArray());
m_context->PSSetConstantBuffers(0, 1, m_uniform_stream_buffer.GetD3DBufferArray());
m_renderer_stats.num_uniform_buffer_updates++;
}
void GPU_HW_D3D11::SetViewport(u32 x, u32 y, u32 width, u32 height)
{
const CD3D11_VIEWPORT vp(static_cast<float>(x), static_cast<float>(y), static_cast<float>(width),
static_cast<float>(height));
m_context->RSSetViewports(1, &vp);
}
void GPU_HW_D3D11::SetScissor(u32 x, u32 y, u32 width, u32 height)
{
const CD3D11_RECT rc(x, y, x + width, y + height);
m_context->RSSetScissorRects(1, &rc);
}
void GPU_HW_D3D11::SetViewportAndScissor(u32 x, u32 y, u32 width, u32 height)
{
SetViewport(x, y, width, height);
SetScissor(x, y, width, height);
}
void GPU_HW_D3D11::DrawUtilityShader(ID3D11PixelShader* shader, const void* uniforms, u32 uniforms_size)
{
if (uniforms)
{
UploadUniformBuffer(uniforms, uniforms_size);
m_batch_ubo_dirty = true;
}
m_context->VSSetShader(m_screen_quad_vertex_shader.Get(), nullptr, 0);
m_context->PSSetShader(shader, nullptr, 0);
m_context->OMSetBlendState(m_blend_disabled_state.Get(), nullptr, 0xFFFFFFFFu);
m_context->Draw(3, 0);
}
bool GPU_HW_D3D11::BlitVRAMReplacementTexture(const TextureReplacementTexture* tex, u32 dst_x, u32 dst_y, u32 width,
u32 height)
{
if (m_vram_replacement_texture.GetWidth() < tex->GetWidth() ||
m_vram_replacement_texture.GetHeight() < tex->GetHeight())
{
if (!m_vram_replacement_texture.Create(m_device.Get(), tex->GetWidth(), tex->GetHeight(), 1, 1, 1,
GPUTexture::Type::Texture, GPUTexture::Format::RGBA8, tex->GetPixels(),
tex->GetPitch(), true))
{
return false;
}
}
else
{
D3D11_MAPPED_SUBRESOURCE sr;
HRESULT hr = m_context->Map(m_vram_replacement_texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &sr);
if (FAILED(hr))
{
Log_ErrorPrintf("Texture map failed: %08X", hr);
return false;
}
const u32 copy_size = std::min(tex->GetPitch(), sr.RowPitch);
const u8* src_ptr = reinterpret_cast<const u8*>(tex->GetPixels());
u8* dst_ptr = static_cast<u8*>(sr.pData);
for (u32 i = 0; i < tex->GetHeight(); i++)
{
std::memcpy(dst_ptr, src_ptr, copy_size);
src_ptr += tex->GetPitch();
dst_ptr += sr.RowPitch;
}
m_context->Unmap(m_vram_replacement_texture, 0);
}
m_context->OMSetDepthStencilState(m_depth_disabled_state.Get(), 0);
m_context->PSSetShaderResources(0, 1, m_vram_replacement_texture.GetD3DSRVArray());
m_context->PSSetSamplers(0, 1, m_linear_sampler_state.GetAddressOf());
SetViewportAndScissor(dst_x, dst_y, width, height);
const float uniforms[] = {0.0f, 0.0f, 1.0f, 1.0f};
DrawUtilityShader(m_copy_pixel_shader.Get(), uniforms, sizeof(uniforms));
RestoreGraphicsAPIState();
return true;
}
void GPU_HW_D3D11::SetScissorFromDrawingArea()
{
int left, top, right, bottom;
CalcScissorRect(&left, &top, &right, &bottom);
CD3D11_RECT rc(left, top, right, bottom);
m_context->RSSetScissorRects(1, &rc);
}
void GPU_HW_D3D11::ClearDisplay()
{
GPU_HW::ClearDisplay();
g_host_display->ClearDisplayTexture();
static constexpr std::array<float, 4> clear_color = {0.0f, 0.0f, 0.0f, 1.0f};
m_context->ClearRenderTargetView(GetDisplayTexture()->GetD3DRTV(), clear_color.data());
}
void GPU_HW_D3D11::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
{
if (IsUsingSoftwareRendererForReadbacks())
{
ReadSoftwareRendererVRAM(x, y, width, height);
return;
}
// Get bounds with wrap-around handled.
const Common::Rectangle<u32> copy_rect = GetVRAMTransferBounds(x, y, width, height);
const u32 encoded_width = (copy_rect.GetWidth() + 1) / 2;
const u32 encoded_height = copy_rect.GetHeight();
// Encode the 24-bit texture as 16-bit.
const u32 uniforms[4] = {copy_rect.left, copy_rect.top, copy_rect.GetWidth(), copy_rect.GetHeight()};
m_context->RSSetState(m_cull_none_rasterizer_state_no_msaa.Get());
m_context->OMSetRenderTargets(1, GetVRAMEncodingTexture()->GetD3DRTVArray(), nullptr);
m_context->OMSetDepthStencilState(m_depth_disabled_state.Get(), 0);
m_context->PSSetShaderResources(0, 1, GetVRAMTexture()->GetD3DSRVArray());
SetViewportAndScissor(0, 0, encoded_width, encoded_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_readback_texture.get(), 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();
}
void GPU_HW_D3D11::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
{
if (IsUsingSoftwareRendererForReadbacks())
FillSoftwareRendererVRAM(x, y, width, height, color);
GPU_HW::FillVRAM(x, y, width, height, color);
m_context->OMSetDepthStencilState(m_depth_test_always_state.Get(), 0);
const Common::Rectangle<u32> bounds(GetVRAMTransferBounds(x, y, width, height));
SetViewportAndScissor(bounds.left * m_resolution_scale, bounds.top * m_resolution_scale,
bounds.GetWidth() * m_resolution_scale, bounds.GetHeight() * m_resolution_scale);
const VRAMFillUBOData uniforms = GetVRAMFillUBOData(x, y, width, height, color);
DrawUtilityShader(m_vram_fill_pixel_shaders[BoolToUInt8(IsVRAMFillOversized(x, y, width, height))]
[BoolToUInt8(IsInterlacedRenderingEnabled())]
.Get(),
&uniforms, sizeof(uniforms));
RestoreGraphicsAPIState();
}
void GPU_HW_D3D11::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, bool set_mask, bool check_mask)
{
if (IsUsingSoftwareRendererForReadbacks())
@ -637,203 +105,26 @@ void GPU_HW_D3D11::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* d
}
const u32 num_pixels = width * height;
const auto map_result = m_texture_stream_buffer.Map(m_context.Get(), sizeof(u16), num_pixels * sizeof(u16));
const auto map_result =
m_texture_stream_buffer.Map(D3D11Device::GetD3DContext(), sizeof(u16), num_pixels * sizeof(u16));
std::memcpy(map_result.pointer, data, num_pixels * sizeof(u16));
m_texture_stream_buffer.Unmap(m_context.Get(), num_pixels * sizeof(u16));
m_texture_stream_buffer.Unmap(D3D11Device::GetD3DContext(), num_pixels * sizeof(u16));
const VRAMWriteUBOData uniforms =
GetVRAMWriteUBOData(x, y, width, height, map_result.index_aligned, set_mask, check_mask);
m_context->OMSetDepthStencilState(
(check_mask && !m_pgxp_depth_buffer) ? m_depth_test_greater_state.Get() : m_depth_test_always_state.Get(), 0);
m_context->PSSetShaderResources(0, 1, m_texture_stream_buffer_srv_r16ui.GetAddressOf());
// 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;
SetScissor(scaled_bounds.left, scaled_bounds.top, scaled_bounds.GetWidth(), scaled_bounds.GetHeight());
DrawUtilityShader(m_vram_write_pixel_shader.Get(), &uniforms, sizeof(uniforms));
g_host_display->SetScissor(scaled_bounds.left, scaled_bounds.top, scaled_bounds.GetWidth(),
scaled_bounds.GetHeight());
g_host_display->SetPipeline(m_vram_write_pipelines[BoolToUInt8(check_mask && !m_pgxp_depth_buffer)].get());
g_host_display->PushUniformBuffer(&uniforms, sizeof(uniforms));
D3D11Device::GetD3DContext()->PSSetShaderResources(0, 1, m_texture_stream_buffer_srv_r16ui.GetAddressOf());
g_host_display->Draw(3, 0);
RestoreGraphicsAPIState();
}
void GPU_HW_D3D11::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height)
{
if (IsUsingSoftwareRendererForReadbacks())
CopySoftwareRendererVRAM(src_x, src_y, dst_x, dst_y, width, height);
if (UseVRAMCopyShader(src_x, src_y, dst_x, dst_y, width, height) || IsUsingMultisampling())
{
const Common::Rectangle<u32> src_bounds = GetVRAMTransferBounds(src_x, src_y, width, height);
const Common::Rectangle<u32> dst_bounds = GetVRAMTransferBounds(dst_x, dst_y, width, height);
if (m_vram_dirty_rect.Intersects(src_bounds))
UpdateVRAMReadTexture();
IncludeVRAMDirtyRectangle(dst_bounds);
const VRAMCopyUBOData uniforms = GetVRAMCopyUBOData(src_x, src_y, dst_x, dst_y, width, height);
const Common::Rectangle<u32> dst_bounds_scaled(dst_bounds * m_resolution_scale);
SetViewportAndScissor(dst_bounds_scaled.left, dst_bounds_scaled.top, dst_bounds_scaled.GetWidth(),
dst_bounds_scaled.GetHeight());
m_context->OMSetDepthStencilState((m_GPUSTAT.check_mask_before_draw && !m_pgxp_depth_buffer) ?
m_depth_test_greater_state.Get() :
m_depth_test_always_state.Get(),
0);
m_context->PSSetShaderResources(0, 1, GetVRAMReadTexture()->GetD3DSRVArray());
DrawUtilityShader(m_vram_copy_pixel_shader.Get(), &uniforms, sizeof(uniforms));
RestoreGraphicsAPIState();
if (m_GPUSTAT.check_mask_before_draw && !m_pgxp_depth_buffer)
m_current_depth++;
return;
}
// We can't CopySubresourceRegion to the same resource. So use the shadow texture if we can, but that may need to be
// updated first. Copying to the same resource seemed to work on Windows 10, but breaks on Windows 7. But, it's
// against the API spec, so better to be safe than sorry.
if (m_vram_dirty_rect.Intersects(Common::Rectangle<u32>::FromExtents(src_x, src_y, width, height)))
UpdateVRAMReadTexture();
GPU_HW::CopyVRAM(src_x, src_y, dst_x, dst_y, width, height);
src_x *= m_resolution_scale;
src_y *= m_resolution_scale;
dst_x *= m_resolution_scale;
dst_y *= m_resolution_scale;
width *= m_resolution_scale;
height *= m_resolution_scale;
const CD3D11_BOX src_box(src_x, src_y, 0, src_x + width, src_y + height, 1);
m_context->CopySubresourceRegion(GetVRAMTexture()->GetD3DTexture(), 0, dst_x, dst_y, 0,
GetVRAMReadTexture()->GetD3DTexture(), 0, &src_box);
}
void GPU_HW_D3D11::UpdateDepthBufferFromMaskBit()
{
if (m_pgxp_depth_buffer)
return;
SetViewportAndScissor(0, 0, GetVRAMTexture()->GetWidth(), GetVRAMTexture()->GetHeight());
m_context->OMSetRenderTargets(0, nullptr, GetVRAMDepthTexture()->GetD3DDSV());
m_context->OMSetDepthStencilState(m_depth_test_always_state.Get(), 0);
m_context->OMSetBlendState(m_blend_no_color_writes_state.Get(), nullptr, 0xFFFFFFFFu);
m_context->PSSetShaderResources(0, 1, GetVRAMTexture()->GetD3DSRVArray());
DrawUtilityShader(m_vram_update_depth_pixel_shader.Get(), nullptr, 0);
m_context->PSSetShaderResources(0, 1, GetVRAMReadTexture()->GetD3DSRVArray());
RestoreGraphicsAPIState();
}
void GPU_HW_D3D11::ClearDepthBuffer()
{
DebugAssert(m_pgxp_depth_buffer);
m_context->ClearDepthStencilView(GetVRAMDepthTexture()->GetD3DDSV(), D3D11_CLEAR_DEPTH, 1.0f, 0);
m_last_depth_z = 1.0f;
}
void GPU_HW_D3D11::DownsampleFramebuffer(const D3D11Texture* source, u32 left, u32 top, u32 width, u32 height)
{
if (m_downsample_mode == GPUDownsampleMode::Adaptive)
DownsampleFramebufferAdaptive(source, left, top, width, height);
else
DownsampleFramebufferBoxFilter(source, left, top, width, height);
}
void GPU_HW_D3D11::DownsampleFramebufferAdaptive(const D3D11Texture* source, u32 left, u32 top, u32 width, u32 height)
{
CD3D11_BOX src_box(left, top, 0, left + width, top + height, 1);
m_context->OMSetDepthStencilState(m_depth_disabled_state.Get(), 0);
m_context->OMSetBlendState(m_blend_disabled_state.Get(), nullptr, 0xFFFFFFFFu);
m_context->CopySubresourceRegion(m_downsample_texture, 0, left, top, 0, source->GetD3DTexture(), 0, &src_box);
m_context->PSSetSamplers(0, 1, m_point_sampler_state.GetAddressOf());
m_context->VSSetShader(m_uv_quad_vertex_shader.Get(), nullptr, 0);
// create mip chain
const u32 levels = m_downsample_texture.GetLevels();
for (u32 level = 1; level < levels; level++)
{
static constexpr float clear_color[4] = {};
SetViewportAndScissor(left >> level, top >> level, width >> level, height >> level);
m_context->ClearRenderTargetView(m_downsample_mip_views[level].second.Get(), clear_color);
m_context->OMSetRenderTargets(1, m_downsample_mip_views[level].second.GetAddressOf(), nullptr);
m_context->PSSetShaderResources(0, 1, m_downsample_mip_views[level - 1].first.GetAddressOf());
const SmoothingUBOData ubo = GetSmoothingUBO(level, left, top, width, height, m_downsample_texture.GetWidth(),
m_downsample_texture.GetHeight());
m_context->PSSetShader(
(level == 1) ? m_downsample_first_pass_pixel_shader.Get() : m_downsample_mid_pass_pixel_shader.Get(), nullptr, 0);
UploadUniformBuffer(&ubo, sizeof(ubo));
m_context->Draw(3, 0);
}
// blur pass at lowest level
{
const u32 last_level = levels - 1;
static constexpr float clear_color[4] = {};
SetViewportAndScissor(left >> last_level, top >> last_level, width >> last_level, height >> last_level);
m_context->ClearRenderTargetView(m_downsample_weight_texture.GetD3DRTV(), clear_color);
m_context->OMSetRenderTargets(1, m_downsample_weight_texture.GetD3DRTVArray(), nullptr);
m_context->PSSetShaderResources(0, 1, m_downsample_mip_views.back().first.GetAddressOf());
m_context->PSSetShader(m_downsample_blur_pass_pixel_shader.Get(), nullptr, 0);
const SmoothingUBOData ubo = GetSmoothingUBO(last_level, left, top, width, height, m_downsample_texture.GetWidth(),
m_downsample_texture.GetHeight());
m_context->PSSetShader(m_downsample_blur_pass_pixel_shader.Get(), nullptr, 0);
UploadUniformBuffer(&ubo, sizeof(ubo));
m_context->Draw(3, 0);
}
// composite downsampled and upsampled images together
{
SetViewportAndScissor(left, top, width, height);
m_context->OMSetRenderTargets(1, GetDisplayTexture()->GetD3DRTVArray(), nullptr);
ID3D11ShaderResourceView* const srvs[2] = {m_downsample_texture.GetD3DSRV(),
m_downsample_weight_texture.GetD3DSRV()};
ID3D11SamplerState* const samplers[2] = {m_trilinear_sampler_state.Get(), m_linear_sampler_state.Get()};
m_context->PSSetShaderResources(0, countof(srvs), srvs);
m_context->PSSetSamplers(0, countof(samplers), samplers);
m_context->PSSetShader(m_downsample_composite_pixel_shader.Get(), nullptr, 0);
m_context->Draw(3, 0);
}
ID3D11ShaderResourceView* const null_srvs[2] = {};
m_context->PSSetShaderResources(0, countof(null_srvs), null_srvs);
m_batch_ubo_dirty = true;
RestoreGraphicsAPIState();
g_host_display->SetDisplayTexture(m_display_texture.get(), left, top, width, height);
}
void GPU_HW_D3D11::DownsampleFramebufferBoxFilter(const D3D11Texture* source, u32 left, u32 top, u32 width, u32 height)
{
const u32 ds_left = left / m_resolution_scale;
const u32 ds_top = top / m_resolution_scale;
const u32 ds_width = width / m_resolution_scale;
const u32 ds_height = height / m_resolution_scale;
static constexpr float clear_color[4] = {};
m_context->ClearRenderTargetView(m_downsample_texture.GetD3DRTV(), clear_color);
m_context->OMSetDepthStencilState(m_depth_disabled_state.Get(), 0);
m_context->OMSetRenderTargets(1, m_downsample_texture.GetD3DRTVArray(), nullptr);
m_context->OMSetBlendState(m_blend_disabled_state.Get(), nullptr, 0xFFFFFFFFu);
m_context->VSSetShader(m_screen_quad_vertex_shader.Get(), nullptr, 0);
m_context->PSSetShader(m_downsample_first_pass_pixel_shader.Get(), nullptr, 0);
m_context->PSSetShaderResources(0, 1, source->GetD3DSRVArray());
SetViewportAndScissor(ds_left, ds_top, ds_width, ds_height);
m_context->Draw(3, 0);
RestoreGraphicsAPIState();
g_host_display->SetDisplayTexture(&m_downsample_texture, ds_left, ds_top, ds_width, ds_height);
}
std::unique_ptr<GPU> GPU::CreateHardwareD3D11Renderer()
{
if (!Host::AcquireHostDisplay(RenderAPI::D3D11))
@ -842,12 +133,7 @@ std::unique_ptr<GPU> GPU::CreateHardwareD3D11Renderer()
return nullptr;
}
ID3D11Device* device = static_cast<ID3D11Device*>(g_host_display->GetDevice());
ID3D11DeviceContext* context = static_cast<ID3D11DeviceContext*>(g_host_display->GetContext());
if (!device || !context)
return nullptr;
std::unique_ptr<GPU_HW_D3D11> gpu(std::make_unique<GPU_HW_D3D11>(device, context));
std::unique_ptr<GPU_HW_D3D11> gpu(std::make_unique<GPU_HW_D3D11>());
if (!gpu->Initialize())
return nullptr;

View File

@ -6,7 +6,6 @@
#include "gpu/d3d11/stream_buffer.h"
#include "gpu/d3d11_texture.h"
#include "gpu_hw.h"
#include "texture_replacements.h"
#include <array>
#include <d3d11.h>
#include <memory>
@ -19,119 +18,22 @@ public:
template<typename T>
using ComPtr = Microsoft::WRL::ComPtr<T>;
GPU_HW_D3D11(ID3D11Device* device, ID3D11DeviceContext* context);
GPU_HW_D3D11();
~GPU_HW_D3D11() override;
GPURenderer GetRendererType() const override;
bool Initialize() override;
void Reset(bool clear_vram) override;
void ResetGraphicsAPIState() override;
void RestoreGraphicsAPIState() override;
protected:
void ClearDisplay() override;
void ReadVRAM(u32 x, u32 y, u32 width, u32 height) override;
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override;
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;
void UpdateDepthBufferFromMaskBit() override;
void ClearDepthBuffer() override;
void SetScissorFromDrawingArea() override;
void UploadUniformBuffer(const void* data, u32 data_size) override;
private:
enum : u32
{
// Currently we don't stream uniforms, instead just re-map the buffer every time and let the driver take care of it.
MAX_UNIFORM_BUFFER_SIZE = 64
};
ALWAYS_INLINE D3D11Texture* GetVRAMTexture() const { return static_cast<D3D11Texture*>(m_vram_texture.get()); }
ALWAYS_INLINE D3D11Texture* GetVRAMDepthTexture() const
{
return static_cast<D3D11Texture*>(m_vram_depth_texture.get());
}
ALWAYS_INLINE D3D11Texture* GetVRAMReadTexture() const
{
return static_cast<D3D11Texture*>(m_vram_read_texture.get());
}
ALWAYS_INLINE D3D11Texture* GetVRAMEncodingTexture() const
{
return static_cast<D3D11Texture*>(m_vram_readback_texture.get());
}
ALWAYS_INLINE D3D11Texture* GetDisplayTexture() const
{
return static_cast<D3D11Texture*>(m_display_texture.get());
}
void SetCapabilities();
bool CreateFramebuffer() override;
void ClearFramebuffer();
void DestroyFramebuffer() override;
bool CreateUniformBuffer();
bool CreateTextureBuffer();
bool CreateStateObjects();
void DestroyStateObjects();
bool CompileShaders();
void DestroyShaders();
void SetViewport(u32 x, u32 y, u32 width, u32 height);
void SetScissor(u32 x, u32 y, u32 width, u32 height);
void SetViewportAndScissor(u32 x, u32 y, u32 width, u32 height);
void DrawUtilityShader(ID3D11PixelShader* shader, const void* uniforms, u32 uniforms_size);
bool BlitVRAMReplacementTexture(const TextureReplacementTexture* tex, u32 dst_x, u32 dst_y, u32 width, u32 height);
void DownsampleFramebuffer(const D3D11Texture* source, u32 left, u32 top, u32 width, u32 height);
void DownsampleFramebufferAdaptive(const D3D11Texture* source, u32 left, u32 top, u32 width, u32 height);
void DownsampleFramebufferBoxFilter(const D3D11Texture* source, u32 left, u32 top, u32 width, u32 height);
ComPtr<ID3D11Device> m_device;
ComPtr<ID3D11DeviceContext> m_context;
D3D11::StreamBuffer m_uniform_stream_buffer;
D3D11::StreamBuffer m_texture_stream_buffer;
ComPtr<ID3D11ShaderResourceView> m_texture_stream_buffer_srv_r16ui;
ComPtr<ID3D11RasterizerState> m_cull_none_rasterizer_state;
ComPtr<ID3D11RasterizerState> m_cull_none_rasterizer_state_no_msaa;
ComPtr<ID3D11DepthStencilState> m_depth_disabled_state;
ComPtr<ID3D11DepthStencilState> m_depth_test_always_state;
ComPtr<ID3D11DepthStencilState> m_depth_test_less_state;
ComPtr<ID3D11DepthStencilState> m_depth_test_greater_state;
ComPtr<ID3D11BlendState> m_blend_disabled_state;
ComPtr<ID3D11BlendState> m_blend_no_color_writes_state;
ComPtr<ID3D11SamplerState> m_point_sampler_state;
ComPtr<ID3D11SamplerState> m_linear_sampler_state;
ComPtr<ID3D11SamplerState> m_trilinear_sampler_state;
ComPtr<ID3D11VertexShader> m_screen_quad_vertex_shader;
ComPtr<ID3D11VertexShader> m_uv_quad_vertex_shader;
ComPtr<ID3D11PixelShader> m_copy_pixel_shader;
std::array<std::array<ComPtr<ID3D11PixelShader>, 2>, 2> m_vram_fill_pixel_shaders; // [wrapped][interlaced]
ComPtr<ID3D11PixelShader> m_vram_read_pixel_shader;
ComPtr<ID3D11PixelShader> m_vram_write_pixel_shader;
ComPtr<ID3D11PixelShader> m_vram_copy_pixel_shader;
ComPtr<ID3D11PixelShader> m_vram_update_depth_pixel_shader;
std::array<std::array<ComPtr<ID3D11PixelShader>, 3>, 2> m_display_pixel_shaders; // [depth_24][interlaced]
D3D11Texture m_vram_replacement_texture;
// downsampling
ComPtr<ID3D11PixelShader> m_downsample_first_pass_pixel_shader;
ComPtr<ID3D11PixelShader> m_downsample_mid_pass_pixel_shader;
ComPtr<ID3D11PixelShader> m_downsample_blur_pass_pixel_shader;
ComPtr<ID3D11PixelShader> m_downsample_composite_pixel_shader;
D3D11Texture m_downsample_texture;
D3D11Texture m_downsample_weight_texture;
std::vector<std::pair<ComPtr<ID3D11ShaderResourceView>, ComPtr<ID3D11RenderTargetView>>> m_downsample_mip_views;
};

View File

@ -93,11 +93,6 @@ void GPU_HW_D3D12::Reset(bool clear_vram)
ClearFramebuffer();
}
void GPU_HW_D3D12::ResetGraphicsAPIState()
{
GPU_HW::ResetGraphicsAPIState();
}
void GPU_HW_D3D12::RestoreGraphicsAPIState()
{
ID3D12GraphicsCommandList* cmdlist = g_d3d12_context->GetCommandList();
@ -118,7 +113,7 @@ void GPU_HW_D3D12::RestoreGraphicsAPIState()
D3D12::SetViewport(cmdlist, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
SetScissorFromDrawingArea();
SetScissor();
}
void GPU_HW_D3D12::UpdateSettings()
@ -132,7 +127,6 @@ void GPU_HW_D3D12::UpdateSettings()
{
RestoreGraphicsAPIState();
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
ResetGraphicsAPIState();
}
// Everything should be finished executing before recreating resources.
@ -156,10 +150,10 @@ void GPU_HW_D3D12::UpdateSettings()
UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr, false, false);
UpdateDepthBufferFromMaskBit();
UpdateDisplay();
ResetGraphicsAPIState();
}
}
#if 0
void GPU_HW_D3D12::MapBatchVertexPointer(u32 required_vertices)
{
DebugAssert(!m_batch_start_vertex_ptr);
@ -209,6 +203,7 @@ void GPU_HW_D3D12::UploadUniformBuffer(const void* data, u32 data_size)
g_d3d12_context->GetCommandList()->SetGraphicsRootConstantBufferView(0, m_uniform_stream_buffer.GetGPUPointer() +
m_current_uniform_buffer_offset);
}
#endif
void GPU_HW_D3D12::SetCapabilities()
{
@ -817,6 +812,7 @@ bool GPU_HW_D3D12::BlitVRAMReplacementTexture(const TextureReplacementTexture* t
return true;
}
#if 0
void GPU_HW_D3D12::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices)
{
ID3D12GraphicsCommandList* cmdlist = g_d3d12_context->GetCommandList();
@ -831,14 +827,7 @@ void GPU_HW_D3D12::DrawBatchVertices(BatchRenderMode render_mode, u32 base_verte
cmdlist->SetPipelineState(pipeline);
cmdlist->DrawInstanced(num_vertices, 1, base_vertex, 0);
}
void GPU_HW_D3D12::SetScissorFromDrawingArea()
{
int left, top, right, bottom;
CalcScissorRect(&left, &top, &right, &bottom);
D3D12::SetScissor(g_d3d12_context->GetCommandList(), left, top, right - left, bottom - top);
}
#endif
void GPU_HW_D3D12::ClearDisplay()
{
@ -1159,24 +1148,6 @@ void GPU_HW_D3D12::UpdateVRAMReadTexture()
GPU_HW::UpdateVRAMReadTexture();
}
#endif
void GPU_HW_D3D12::UpdateDepthBufferFromMaskBit()
{
ID3D12GraphicsCommandList* cmdlist = g_d3d12_context->GetCommandList();
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
cmdlist->OMSetRenderTargets(0, nullptr, FALSE, &m_vram_depth_texture.GetRTVOrDSVDescriptor().cpu_handle);
cmdlist->SetGraphicsRootDescriptorTable(1, m_vram_texture.GetSRVDescriptor());
cmdlist->SetPipelineState(m_vram_update_depth_pipeline.Get());
D3D12::SetViewportAndScissor(cmdlist, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
cmdlist->DrawInstanced(3, 1, 0, 0);
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
RestoreGraphicsAPIState();
}
void GPU_HW_D3D12::ClearDepthBuffer()
{
@ -1184,6 +1155,7 @@ void GPU_HW_D3D12::ClearDepthBuffer()
cmdlist->ClearDepthStencilView(m_vram_depth_texture.GetRTVOrDSVDescriptor(), D3D12_CLEAR_FLAG_DEPTH,
m_pgxp_depth_buffer ? 1.0f : 0.0f, 0, 0, nullptr);
}
#endif
std::unique_ptr<GPU> GPU::CreateHardwareD3D12Renderer()
{

View File

@ -26,7 +26,6 @@ public:
bool Initialize() override;
void Reset(bool clear_vram) override;
void ResetGraphicsAPIState() override;
void RestoreGraphicsAPIState() override;
void UpdateSettings() override;
@ -37,13 +36,6 @@ protected:
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override;
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;
void UpdateDepthBufferFromMaskBit() override;
void ClearDepthBuffer() override;
void SetScissorFromDrawingArea() override;
void MapBatchVertexPointer(u32 required_vertices) override;
void UnmapBatchVertexPointer(u32 used_vertices) override;
void UploadUniformBuffer(const void* data, u32 data_size) override;
void DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices) override;
private:
enum : u32

View File

@ -150,17 +150,6 @@ void GPU_HW_OpenGL::CopyFramebufferForState(GLenum target, GLuint src_texture, u
}
#endif
void GPU_HW_OpenGL::ResetGraphicsAPIState()
{
GPU_HW::ResetGraphicsAPIState();
glEnable(GL_CULL_FACE);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glBindVertexArray(0);
m_uniform_stream_buffer->Unbind();
}
void GPU_HW_OpenGL::RestoreGraphicsAPIState()
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_vram_fbo_id);
@ -176,7 +165,7 @@ void GPU_HW_OpenGL::RestoreGraphicsAPIState()
SetBlendMode();
m_current_depth_test = 0;
SetDepthFunc();
SetScissorFromDrawingArea();
SetScissor();
m_batch_ubo_dirty = true;
}
@ -191,7 +180,6 @@ void GPU_HW_OpenGL::UpdateSettings()
{
RestoreGraphicsAPIState();
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
ResetGraphicsAPIState();
g_host_display->ClearDisplayTexture();
CreateFramebuffer();
}
@ -204,10 +192,10 @@ void GPU_HW_OpenGL::UpdateSettings()
UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr, false, false);
UpdateDepthBufferFromMaskBit();
UpdateDisplay();
ResetGraphicsAPIState();
}
}
#if 0
void GPU_HW_OpenGL::MapBatchVertexPointer(u32 required_vertices)
{
DebugAssert(!m_batch_start_vertex_ptr);
@ -230,6 +218,7 @@ void GPU_HW_OpenGL::UnmapBatchVertexPointer(u32 used_vertices)
m_batch_end_vertex_ptr = nullptr;
m_batch_current_vertex_ptr = nullptr;
}
#endif
void GPU_HW_OpenGL::SetCapabilities()
{
@ -664,6 +653,7 @@ bool GPU_HW_OpenGL::CompilePrograms()
return true;
}
#if 0
void GPU_HW_OpenGL::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices)
{
const GL::Program& prog = m_render_programs[static_cast<u8>(render_mode)][static_cast<u8>(m_batch.texture_mode)]
@ -681,6 +671,7 @@ void GPU_HW_OpenGL::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vert
glDrawArrays(GL_TRIANGLES, m_batch_base_vertex, num_vertices);
}
#endif
void GPU_HW_OpenGL::SetBlendMode()
{
@ -753,20 +744,7 @@ void GPU_HW_OpenGL::SetDepthFunc(GLenum func)
m_current_depth_test = func;
}
void GPU_HW_OpenGL::SetScissorFromDrawingArea()
{
int left, top, right, bottom;
CalcScissorRect(&left, &top, &right, &bottom);
const int width = right - left;
const int height = bottom - top;
const int x = left;
const int y = top;
Log_DebugPrintf("SetScissor: (%d-%d, %d-%d)", x, x + width, y, y + height);
glScissor(x, y, width, height);
}
#if 0
void GPU_HW_OpenGL::UploadUniformBuffer(const void* data, u32 data_size)
{
const GL::StreamBuffer::MappingResult res = m_uniform_stream_buffer->Map(m_uniform_buffer_alignment, data_size);
@ -777,6 +755,7 @@ void GPU_HW_OpenGL::UploadUniformBuffer(const void* data, u32 data_size)
m_renderer_stats.num_uniform_buffer_updates++;
}
#endif
void GPU_HW_OpenGL::ClearDisplay()
{
@ -871,7 +850,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
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_vram_offset_y + reinterpret_field_offset,
reinterpret_crop_left, reinterpret_field_offset};
UploadUniformBuffer(uniforms, sizeof(uniforms));
g_host_display->UploadUniformBuffer(uniforms, sizeof(uniforms));
m_batch_ubo_dirty = true;
Assert(scaled_display_width <= m_display_texture.GetWidth() &&
@ -921,7 +900,7 @@ void GPU_HW_OpenGL::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
m_vram_readback_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER);
m_vram_texture.Bind();
m_vram_read_program.Bind();
UploadUniformBuffer(uniforms, sizeof(uniforms));
g_host_display->UploadUniformBuffer(uniforms, sizeof(uniforms));
glDisable(GL_BLEND);
glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, encoded_width, encoded_height);
@ -960,14 +939,14 @@ void GPU_HW_OpenGL::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
glClearColor(r, g, b, a);
IsGLES() ? glClearDepthf(a) : glClearDepth(a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
SetScissorFromDrawingArea();
SetScissor();
}
else
{
const VRAMFillUBOData uniforms = GetVRAMFillUBOData(x, y, width, height, color);
m_vram_fill_programs[BoolToUInt8(wrapped)][BoolToUInt8(interlaced)].Bind();
UploadUniformBuffer(&uniforms, sizeof(uniforms));
g_host_display->UploadUniformBuffer(&uniforms, sizeof(uniforms));
glDisable(GL_BLEND);
SetDepthFunc(GL_ALWAYS);
glBindVertexArray(m_attributeless_vao_id);
@ -1014,7 +993,7 @@ void GPU_HW_OpenGL::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void*
const VRAMWriteUBOData uniforms =
GetVRAMWriteUBOData(x, y, width, height, map_result.index_aligned, set_mask, check_mask);
UploadUniformBuffer(&uniforms, sizeof(uniforms));
g_host_display->UploadUniformBuffer(&uniforms, sizeof(uniforms));
// 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;
@ -1105,7 +1084,7 @@ void GPU_HW_OpenGL::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 wid
IncludeVRAMDirtyRectangle(dst_bounds);
const VRAMCopyUBOData uniforms = GetVRAMCopyUBOData(src_x, src_y, dst_x, dst_y, width, height);
UploadUniformBuffer(&uniforms, sizeof(uniforms));
g_host_display->UploadUniformBuffer(&uniforms, sizeof(uniforms));
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
@ -1205,29 +1184,6 @@ void GPU_HW_OpenGL::UpdateVRAMReadTexture()
GPU_HW::UpdateVRAMReadTexture();
}
#endif
void GPU_HW_OpenGL::UpdateDepthBufferFromMaskBit()
{
if (m_pgxp_depth_buffer)
return;
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthFunc(GL_ALWAYS);
m_vram_texture.Bind();
m_vram_update_depth_program.Bind();
glBindVertexArray(m_attributeless_vao_id);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(m_vao_id);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_SCISSOR_TEST);
m_vram_read_texture.Bind();
}
void GPU_HW_OpenGL::ClearDepthBuffer()
{
@ -1237,6 +1193,7 @@ void GPU_HW_OpenGL::ClearDepthBuffer()
glEnable(GL_SCISSOR_TEST);
m_last_depth_z = 1.0f;
}
#endif
void GPU_HW_OpenGL::DownsampleFramebuffer(GL::Texture& source, u32 left, u32 top, u32 width, u32 height)
{

View File

@ -24,7 +24,6 @@ public:
bool Initialize() override;
void Reset(bool clear_vram) override;
void ResetGraphicsAPIState() override;
void RestoreGraphicsAPIState() override;
void UpdateSettings() override;
@ -35,13 +34,6 @@ protected:
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override;
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;
void UpdateDepthBufferFromMaskBit() override;
void ClearDepthBuffer() override;
void SetScissorFromDrawingArea() override;
void MapBatchVertexPointer(u32 required_vertices) override;
void UnmapBatchVertexPointer(u32 used_vertices) override;
void UploadUniformBuffer(const void* data, u32 data_size) override;
void DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices) override;
private:
struct GLStats

View File

@ -93,22 +93,6 @@ void GPU_HW_Vulkan::Reset(bool clear_vram)
ClearFramebuffer();
}
void GPU_HW_Vulkan::ResetGraphicsAPIState()
{
GPU_HW::ResetGraphicsAPIState();
EndRenderPass();
if (g_host_display->GetDisplayTextureHandle() == &m_vram_texture)
{
m_vram_texture.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(),
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
}
// this is called at the end of the frame, so the UBO is associated with the previous command buffer.
m_batch_ubo_dirty = true;
}
void GPU_HW_Vulkan::RestoreGraphicsAPIState()
{
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
@ -120,7 +104,10 @@ void GPU_HW_Vulkan::RestoreGraphicsAPIState()
Vulkan::Util::SetViewport(cmdbuf, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_batch_pipeline_layout, 0, 1,
&m_batch_descriptor_set, 1, &m_current_uniform_buffer_offset);
SetScissorFromDrawingArea();
SetScissor();
// FIXME this is called at the end of the frame, so the UBO is associated with the previous command buffer.
m_batch_ubo_dirty = true;
}
void GPU_HW_Vulkan::UpdateSettings()
@ -134,7 +121,6 @@ void GPU_HW_Vulkan::UpdateSettings()
{
RestoreGraphicsAPIState();
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
ResetGraphicsAPIState();
}
// Everything should be finished executing before recreating resources.
@ -158,10 +144,10 @@ void GPU_HW_Vulkan::UpdateSettings()
UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr, false, false);
UpdateDepthBufferFromMaskBit();
UpdateDisplay();
ResetGraphicsAPIState();
}
}
#if 0
void GPU_HW_Vulkan::MapBatchVertexPointer(u32 required_vertices)
{
DebugAssert(!m_batch_start_vertex_ptr);
@ -210,6 +196,7 @@ void GPU_HW_Vulkan::UploadUniformBuffer(const void* data, u32 data_size)
vkCmdBindDescriptorSets(g_vulkan_context->GetCurrentCommandBuffer(), VK_PIPELINE_BIND_POINT_GRAPHICS,
m_batch_pipeline_layout, 0, 1, &m_batch_descriptor_set, 1, &m_current_uniform_buffer_offset);
}
#endif
void GPU_HW_Vulkan::SetCapabilities()
{
@ -1293,6 +1280,7 @@ void GPU_HW_Vulkan::DestroyPipelines()
m_display_pipelines.enumerate(Vulkan::Util::SafeDestroyPipeline);
}
#if 0
void GPU_HW_Vulkan::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices)
{
BeginVRAMRenderPass();
@ -1310,16 +1298,7 @@ void GPU_HW_Vulkan::DrawBatchVertices(BatchRenderMode render_mode, u32 base_vert
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
vkCmdDraw(cmdbuf, num_vertices, 1, base_vertex, 0);
}
void GPU_HW_Vulkan::SetScissorFromDrawingArea()
{
int left, top, right, bottom;
CalcScissorRect(&left, &top, &right, &bottom);
const Vulkan::Util::DebugScope debugScope(g_vulkan_context->GetCurrentCommandBuffer(),
"GPU_HW_Vulkan::SetScissorFromDrawingArea: {%u,%u} {%u,%u}", left, top,
right, bottom);
Vulkan::Util::SetScissor(g_vulkan_context->GetCurrentCommandBuffer(), left, top, right - left, bottom - top);
}
#endif
void GPU_HW_Vulkan::ClearDisplay()
{
@ -1688,33 +1667,6 @@ void GPU_HW_Vulkan::UpdateVRAMReadTexture()
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
GPU_HW::UpdateVRAMReadTexture();
}
#endif
void GPU_HW_Vulkan::UpdateDepthBufferFromMaskBit()
{
if (m_pgxp_depth_buffer)
return;
EndRenderPass();
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::UpdateDepthBufferFromMaskBit");
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
BeginRenderPass(m_vram_update_depth_render_pass, m_vram_update_depth_framebuffer, 0, 0, m_vram_texture.GetWidth(),
m_vram_texture.GetHeight());
vkCmdBindPipeline(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_vram_update_depth_pipeline);
vkCmdBindDescriptorSets(cmdbuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_single_sampler_pipeline_layout, 0, 1,
&m_vram_read_descriptor_set, 0, nullptr);
Vulkan::Util::SetViewportAndScissor(cmdbuf, 0, 0, m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
vkCmdDraw(cmdbuf, 3, 1, 0, 0);
EndRenderPass();
m_vram_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
RestoreGraphicsAPIState();
}
void GPU_HW_Vulkan::ClearDepthBuffer()
{
@ -1732,6 +1684,7 @@ void GPU_HW_Vulkan::ClearDepthBuffer()
m_vram_depth_texture.TransitionToLayout(cmdbuf, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
m_last_depth_z = 1.0f;
}
#endif
bool GPU_HW_Vulkan::BlitVRAMReplacementTexture(const TextureReplacementTexture* tex, u32 dst_x, u32 dst_y, u32 width,
u32 height)

View File

@ -22,7 +22,6 @@ public:
bool Initialize() override;
void Reset(bool clear_vram) override;
void ResetGraphicsAPIState() override;
void RestoreGraphicsAPIState() override;
void UpdateSettings() override;
@ -33,13 +32,6 @@ protected:
void FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color) override;
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;
void UpdateDepthBufferFromMaskBit() override;
void ClearDepthBuffer() override;
void SetScissorFromDrawingArea() override;
void MapBatchVertexPointer(u32 required_vertices) override;
void UnmapBatchVertexPointer(u32 used_vertices) override;
void UploadUniformBuffer(const void* data, u32 data_size) override;
void DrawBatchVertices(BatchRenderMode render_mode, u32 base_vertex, u32 num_vertices) override;
private:
enum : u32

View File

@ -799,8 +799,6 @@ bool System::RecreateGPU(GPURenderer renderer, bool force_recreate_display, bool
if (!state_valid)
Log_ErrorPrintf("Failed to save old GPU state when switching renderers");
g_gpu->ResetGraphicsAPIState();
// create new renderer
g_gpu.reset();
if (force_recreate_display)
@ -822,7 +820,6 @@ bool System::RecreateGPU(GPURenderer renderer, bool force_recreate_display, bool
g_gpu->RestoreGraphicsAPIState();
g_gpu->DoState(sw, nullptr, update_display);
TimingEvents::DoState(sw);
g_gpu->ResetGraphicsAPIState();
}
// fix up vsync etc
@ -1507,8 +1504,6 @@ void System::DestroySystem()
Timers::Shutdown();
Pad::Shutdown();
CDROM::Shutdown();
if (g_gpu)
g_gpu->ResetGraphicsAPIState();
g_gpu.reset();
InterruptController::Shutdown();
DMA::Shutdown();
@ -1727,9 +1722,7 @@ bool System::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_di
return false;
g_gpu->RestoreGraphicsAPIState();
const bool gpu_result = sw.DoMarker("GPU") && g_gpu->DoState(sw, host_texture, update_display);
g_gpu->ResetGraphicsAPIState();
if (!gpu_result)
if (!sw.DoMarker("GPU") || !g_gpu->DoState(sw, host_texture, update_display))
return false;
if (!sw.DoMarker("CDROM") || !CDROM::DoState(sw))
@ -1864,8 +1857,6 @@ void System::InternalReset()
#ifdef WITH_CHEEVOS
Achievements::ResetRuntime();
#endif
g_gpu->ResetGraphicsAPIState();
}
std::string System::GetMediaPathFromSaveState(const char* path)
@ -2147,8 +2138,6 @@ bool System::InternalSaveState(ByteStream* state, u32 screenshot_size /* = 256 *
header.data_compressed_size = static_cast<u32>(state->GetPosition() - header.offset_to_data);
}
g_gpu->ResetGraphicsAPIState();
if (!result)
return false;
}
@ -2175,11 +2164,10 @@ void System::SingleStepCPU()
CPU::SingleStep();
SPU::GeneratePendingSamples();
g_gpu->FlushRender();
if (s_frame_number != old_frame_number && s_cheat_list)
s_cheat_list->Apply();
g_gpu->ResetGraphicsAPIState();
}
void System::DoRunFrame()
@ -2215,11 +2203,10 @@ void System::DoRunFrame()
// Generate any pending samples from the SPU before sleeping, this way we reduce the chances of underruns.
SPU::GeneratePendingSamples();
g_gpu->FlushRender();
if (s_cheat_list)
s_cheat_list->Apply();
g_gpu->ResetGraphicsAPIState();
}
void System::RunFrame()
@ -2986,10 +2973,7 @@ bool System::DumpVRAM(const char* filename)
return false;
g_gpu->RestoreGraphicsAPIState();
const bool result = g_gpu->DumpVRAMToFile(filename);
g_gpu->ResetGraphicsAPIState();
return result;
return g_gpu->DumpVRAMToFile(filename);
}
bool System::DumpSPURAM(const char* filename)

View File

@ -623,7 +623,6 @@ static void HotkeyModifyResolutionScale(s32 increment)
{
g_gpu->RestoreGraphicsAPIState();
g_gpu->UpdateSettings();
g_gpu->ResetGraphicsAPIState();
System::ClearMemorySaveStates();
Host::InvalidateDisplay();
}
@ -883,7 +882,6 @@ DEFINE_HOTKEY("TogglePGXP", TRANSLATABLE("Hotkeys", "Graphics"), TRANSLATABLE("H
g_settings.gpu_pgxp_enable = !g_settings.gpu_pgxp_enable;
g_gpu->RestoreGraphicsAPIState();
g_gpu->UpdateSettings();
g_gpu->ResetGraphicsAPIState();
System::ClearMemorySaveStates();
Host::AddKeyedOSDMessage("TogglePGXP",
g_settings.gpu_pgxp_enable ?
@ -953,7 +951,6 @@ DEFINE_HOTKEY("TogglePGXPDepth", TRANSLATABLE("Hotkeys", "Graphics"),
g_gpu->RestoreGraphicsAPIState();
g_gpu->UpdateSettings();
g_gpu->ResetGraphicsAPIState();
System::ClearMemorySaveStates();
Host::AddKeyedOSDMessage(
"TogglePGXPDepth",
@ -974,7 +971,6 @@ DEFINE_HOTKEY("TogglePGXPCPU", TRANSLATABLE("Hotkeys", "Graphics"), TRANSLATABLE
g_gpu->RestoreGraphicsAPIState();
g_gpu->UpdateSettings();
g_gpu->ResetGraphicsAPIState();
System::ClearMemorySaveStates();
Host::AddKeyedOSDMessage("TogglePGXPCPU",
g_settings.gpu_pgxp_cpu ?