DX11 tweaks/caching

This commit is contained in:
Stenzek 2023-08-06 23:31:18 +10:00
parent 9f04712dd3
commit a09ef8d4f6
15 changed files with 359 additions and 184 deletions

View File

@ -52,7 +52,7 @@ static void SetD3DDebugObjectName(ID3D11DeviceChild* obj, const std::string_view
namespace Host {
extern bool IsFullscreen();
extern void SetFullscreen(bool enabled);
}
} // namespace Host
D3D11StreamBuffer::D3D11StreamBuffer() : m_size(0), m_position(0)
{
@ -127,7 +127,7 @@ void D3D11StreamBuffer::Release()
m_buffer.Reset();
}
D3D11StreamBuffer::MappingResult D3D11StreamBuffer::Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size)
D3D11StreamBuffer::MappingResult D3D11StreamBuffer::Map(ID3D11DeviceContext1* context, u32 alignment, u32 min_size)
{
m_position = Common::AlignUp(m_position, alignment);
if ((m_position + min_size) >= m_size || !m_use_map_no_overwrite)
@ -151,7 +151,7 @@ D3D11StreamBuffer::MappingResult D3D11StreamBuffer::Map(ID3D11DeviceContext* con
(m_size - m_position) / alignment};
}
void D3D11StreamBuffer::Unmap(ID3D11DeviceContext* context, u32 used_size)
void D3D11StreamBuffer::Unmap(ID3D11DeviceContext1* context, u32 used_size)
{
context->Unmap(m_buffer.Get(), 0);
m_position += used_size;
@ -255,10 +255,10 @@ void D3D11Device::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 d
{
DebugAssert(src_level < src->GetLevels() && src_layer < src->GetLayers());
DebugAssert((src_x + width) <= src->GetMipWidth(src_level));
DebugAssert((src_y + height) <= src->GetMipWidth(src_level));
DebugAssert((src_y + height) <= src->GetMipHeight(src_level));
DebugAssert(dst_level < dst->GetLevels() && dst_layer < dst->GetLayers());
DebugAssert((dst_x + width) <= dst->GetMipWidth(dst_level));
DebugAssert((dst_y + height) <= dst->GetMipWidth(dst_level));
DebugAssert((dst_y + height) <= dst->GetMipHeight(dst_level));
D3D11Texture* dst11 = static_cast<D3D11Texture*>(dst);
D3D11Texture* src11 = static_cast<D3D11Texture*>(src);
@ -300,10 +300,10 @@ void D3D11Device::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u3
{
DebugAssert(src_level < src->GetLevels() && src_layer < src->GetLayers());
DebugAssert((src_x + width) <= src->GetMipWidth(src_level));
DebugAssert((src_y + height) <= src->GetMipWidth(src_level));
DebugAssert((src_y + height) <= src->GetMipHeight(src_level));
DebugAssert(dst_level < dst->GetLevels() && dst_layer < dst->GetLayers());
DebugAssert((dst_x + width) <= dst->GetMipWidth(dst_level));
DebugAssert((dst_y + height) <= dst->GetMipWidth(dst_level));
DebugAssert((dst_y + height) <= dst->GetMipHeight(dst_level));
DebugAssert(!dst->IsMultisampled() && src->IsMultisampled());
// DX11 can't resolve partial rects.
@ -320,6 +320,27 @@ void D3D11Device::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u3
dst11->GetDXGIFormat());
}
void D3D11Device::ClearRenderTarget(GPUTexture* t, u32 c)
{
GPUDevice::ClearRenderTarget(t, c);
if (m_current_framebuffer && m_current_framebuffer->GetRT() == t)
static_cast<D3D11Texture*>(t)->CommitClear(m_context.Get());
}
void D3D11Device::ClearDepth(GPUTexture* t, float d)
{
GPUDevice::ClearDepth(t, d);
if (m_current_framebuffer && m_current_framebuffer->GetDS() == t)
static_cast<D3D11Texture*>(t)->CommitClear(m_context.Get());
}
void D3D11Device::InvalidateRenderTarget(GPUTexture* t)
{
GPUDevice::InvalidateRenderTarget(t);
if (m_current_framebuffer && (m_current_framebuffer->GetRT() == t || m_current_framebuffer->GetDS() == t))
static_cast<D3D11Texture*>(t)->CommitClear(m_context.Get());
}
bool D3D11Device::GetHostRefreshRate(float* refresh_rate)
{
if (m_swap_chain && m_is_exclusive_fullscreen)
@ -344,10 +365,10 @@ void D3D11Device::SetVSync(bool enabled)
m_vsync_enabled = enabled;
}
bool D3D11Device::CreateDevice(const std::string_view& adapter, bool debug_device)
bool D3D11Device::CreateDevice(const std::string_view& adapter)
{
UINT create_flags = 0;
if (debug_device)
if (m_debug_device)
create_flags |= D3D11_CREATE_DEVICE_DEBUG;
ComPtr<IDXGIFactory> temp_dxgi_factory;
@ -410,7 +431,7 @@ bool D3D11Device::CreateDevice(const std::string_view& adapter, bool debug_devic
return false;
}
if (debug_device && IsDebuggerPresent())
if (m_debug_device && IsDebuggerPresent())
{
ComPtr<ID3D11InfoQueue> info;
hr = m_device.As(&info);
@ -422,7 +443,7 @@ bool D3D11Device::CreateDevice(const std::string_view& adapter, bool debug_devic
}
#ifdef _DEBUG
if (debug_device)
if (m_debug_device)
m_context.As(&m_annotation);
#endif
@ -778,7 +799,7 @@ void D3D11Device::DestroySurface()
DestroySwapChain();
}
std::string D3D11Device::GetShaderCacheBaseName(const std::string_view& type, bool debug) const
std::string D3D11Device::GetShaderCacheBaseName(const std::string_view& type) const
{
std::string_view flname;
switch (m_device->GetFeatureLevel())
@ -790,7 +811,7 @@ std::string D3D11Device::GetShaderCacheBaseName(const std::string_view& type, bo
// clang-format on
}
return fmt::format("d3d_{}_{}{}", type, flname, debug ? "_debug" : "");
return fmt::format("d3d_{}_{}{}", type, flname, m_debug_device ? "_debug" : "");
}
void D3D11Device::ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale)
@ -832,6 +853,8 @@ bool D3D11Device::CreateBuffers()
return false;
}
// Index buffer never changes :)
m_context->IASetIndexBuffer(m_index_buffer.GetD3DBuffer(), DXGI_FORMAT_R16_UINT, 0);
return true;
}
@ -1095,7 +1118,10 @@ D3D11Framebuffer::D3D11Framebuffer(GPUTexture* rt, GPUTexture* ds, u32 width, u3
{
}
D3D11Framebuffer::~D3D11Framebuffer() = default;
D3D11Framebuffer::~D3D11Framebuffer()
{
D3D11Device::GetInstance().UnbindFramebuffer(this);
}
void D3D11Framebuffer::SetDebugName(const std::string_view& name)
{
@ -1105,12 +1131,12 @@ void D3D11Framebuffer::SetDebugName(const std::string_view& name)
SetD3DDebugObjectName(m_dsv.Get(), fmt::format("{} DSV", name));
}
void D3D11Framebuffer::CommitClear(ID3D11DeviceContext* context)
void D3D11Framebuffer::CommitClear(ID3D11DeviceContext1* context)
{
if (UNLIKELY(m_rt && m_rt->GetState() != GPUTexture::State::Dirty))
{
if (m_rt->GetState() == GPUTexture::State::Invalidated)
; // m_context->DiscardView(m_rtv.Get());
context->DiscardView(m_rtv.Get());
else
context->ClearRenderTargetView(m_rtv.Get(), m_rt->GetUNormClearColor().data());
@ -1120,7 +1146,7 @@ void D3D11Framebuffer::CommitClear(ID3D11DeviceContext* context)
if (UNLIKELY(m_ds && m_ds->GetState() != GPUTexture::State::Dirty))
{
if (m_ds->GetState() == GPUTexture::State::Invalidated)
; // m_context->DiscardView(m_dsv.Get());
context->DiscardView(m_dsv.Get());
else
context->ClearDepthStencilView(m_dsv.Get(), D3D11_CLEAR_DEPTH, m_ds->GetClearDepth(), 0);
@ -1379,13 +1405,6 @@ std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromBinary(GPUShaderStage st
std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source,
std::vector<u8>* out_binary /* = nullptr */)
{
// TODO: This shouldn't be dependent on build type.
#ifdef _DEBUG
constexpr bool debug = true;
#else
constexpr bool debug = false;
#endif
const char* target;
switch (m_device->GetFeatureLevel())
{
@ -1426,7 +1445,7 @@ std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromSource(GPUShaderStage st
ComPtr<ID3DBlob> error_blob;
const HRESULT hr =
D3DCompile(source.data(), source.size(), "0", nullptr, nullptr, "main", target,
debug ? flags_debug : flags_non_debug, 0, blob.GetAddressOf(), error_blob.GetAddressOf());
m_debug_device ? flags_debug : flags_non_debug, 0, blob.GetAddressOf(), error_blob.GetAddressOf());
std::string error_string;
if (error_blob)
@ -1467,31 +1486,24 @@ std::unique_ptr<GPUShader> D3D11Device::CreateShaderFromSource(GPUShaderStage st
D3D11Pipeline::D3D11Pipeline(ComPtr<ID3D11RasterizerState> rs, ComPtr<ID3D11DepthStencilState> ds,
ComPtr<ID3D11BlendState> bs, ComPtr<ID3D11InputLayout> il, ComPtr<ID3D11VertexShader> vs,
ComPtr<ID3D11PixelShader> ps, D3D11_PRIMITIVE_TOPOLOGY topology)
ComPtr<ID3D11PixelShader> ps, D3D11_PRIMITIVE_TOPOLOGY topology, u32 vertex_stride,
u32 blend_factor)
: m_rs(std::move(rs)), m_ds(std::move(ds)), m_bs(std::move(bs)), m_il(std::move(il)), m_vs(std::move(vs)),
m_ps(std::move(ps)), m_topology(topology)
m_ps(std::move(ps)), m_topology(topology), m_vertex_stride(vertex_stride), m_blend_factor(blend_factor),
m_blend_factor_float(GPUDevice::RGBA8ToFloat(blend_factor))
{
}
D3D11Pipeline::~D3D11Pipeline() = default;
D3D11Pipeline::~D3D11Pipeline()
{
D3D11Device::GetInstance().UnbindPipeline(this);
}
void D3D11Pipeline::SetDebugName(const std::string_view& name)
{
// can't label this directly
}
void D3D11Pipeline::Bind(ID3D11DeviceContext* context)
{
// TODO: constant blend factor
context->IASetInputLayout(GetInputLayout());
context->IASetPrimitiveTopology(GetPrimitiveTopology());
context->RSSetState(GetRasterizerState());
context->OMSetDepthStencilState(GetDepthStencilState(), 0);
context->OMSetBlendState(GetBlendState(), nullptr, 0xFFFFFFFFu);
context->VSSetShader(GetVertexShader(), nullptr, 0);
context->PSSetShader(GetPixelShader(), nullptr, 0);
}
D3D11Device::ComPtr<ID3D11RasterizerState> D3D11Device::GetRasterizationState(const GPUPipeline::RasterizationState& rs)
{
ComPtr<ID3D11RasterizerState> drs;
@ -1627,12 +1639,6 @@ D3D11Device::ComPtr<ID3D11InputLayout> D3D11Device::GetInputLayout(const GPUPipe
return dil;
}
#if 0
static constexpr std::array<const char*, static_cast<u32>(GPUPipeline::VertexAttribute::MaxAttributes)> semantics = {
{"ATTR0", "ATTR1", "ATTR2", "ATTR3", "ATTR4", "ATTR5", "ATTR6", "ATTR7", "ATTR8", "ATTR9", "ATTR10", "ATTR11",
"ATTR12", "ATTR13", "ATTR14", "ATTR15"}};
#endif
static constexpr u32 MAX_COMPONENTS = 4;
static constexpr const DXGI_FORMAT
format_mapping[static_cast<u8>(GPUPipeline::VertexAttribute::Type::MaxCount)][MAX_COMPONENTS] = {
@ -1683,9 +1689,11 @@ std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::Grap
return {};
ComPtr<ID3D11InputLayout> il;
u32 vertex_stride = 0;
if (!config.input_layout.vertex_attributes.empty())
{
il = GetInputLayout(config.input_layout, static_cast<const D3D11Shader*>(config.vertex_shader));
vertex_stride = config.input_layout.vertex_stride;
if (!il)
return {};
}
@ -1702,7 +1710,7 @@ std::unique_ptr<GPUPipeline> D3D11Device::CreatePipeline(const GPUPipeline::Grap
new D3D11Pipeline(std::move(rs), std::move(ds), std::move(bs), std::move(il),
static_cast<const D3D11Shader*>(config.vertex_shader)->GetVertexShader(),
static_cast<const D3D11Shader*>(config.fragment_shader)->GetPixelShader(),
primitives[static_cast<u8>(config.primitive)]));
primitives[static_cast<u8>(config.primitive)], vertex_stride, config.blend.constant));
}
D3D11Texture::D3D11Texture() = default;
@ -1748,23 +1756,22 @@ D3D11_TEXTURE2D_DESC D3D11Texture::GetDesc() const
return desc;
}
void D3D11Texture::CommitClear(ID3D11DeviceContext* context)
void D3D11Texture::CommitClear(ID3D11DeviceContext1* context)
{
if (m_state == GPUTexture::State::Dirty)
return;
// TODO: 11.1
if (IsDepthStencil())
{
if (m_state == GPUTexture::State::Invalidated)
; // context->DiscardView(GetD3DDSV());
context->DiscardView(GetD3DDSV());
else
context->ClearDepthStencilView(GetD3DDSV(), D3D11_CLEAR_DEPTH, GetClearDepth(), 0);
}
else if (IsRenderTarget())
{
if (m_state == GPUTexture::State::Invalidated)
; // context->DiscardView(GetD3DRTV());
context->DiscardView(GetD3DRTV());
else
context->ClearRenderTargetView(GetD3DRTV(), GetUNormClearColor().data());
}
@ -1796,7 +1803,7 @@ 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);
ID3D11DeviceContext* context = D3D11Device::GetD3DContext();
ID3D11DeviceContext1* context = D3D11Device::GetD3DContext();
CommitClear(context);
context->UpdateSubresource(m_texture.Get(), srnum, &box, data, pitch, 0);
m_state = GPUTexture::State::Dirty;
@ -1815,7 +1822,7 @@ 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();
ID3D11DeviceContext1* context = D3D11Device::GetD3DContext();
CommitClear(context);
D3D11_MAPPED_SUBRESOURCE sr;
@ -1950,6 +1957,7 @@ bool D3D11Texture::Create(ID3D11Device* device, u32 width, u32 height, u32 layer
m_layers = static_cast<u8>(layers);
m_levels = static_cast<u8>(levels);
m_samples = static_cast<u8>(samples);
m_type = type;
m_format = format;
m_dynamic = dynamic;
return true;
@ -2021,6 +2029,7 @@ bool D3D11Texture::Adopt(ID3D11Device* device, ComPtr<ID3D11Texture2D> texture)
void D3D11Texture::Destroy()
{
D3D11Device::GetInstance().UnbindTexture(this);
m_rtv_dsv.Reset();
m_srv.Reset();
m_texture.Reset();
@ -2130,10 +2139,6 @@ void D3D11Device::MapVertexBuffer(u32 vertex_size, u32 vertex_count, void** map_
void D3D11Device::UnmapVertexBuffer(u32 vertex_size, u32 vertex_count)
{
m_vertex_buffer.Unmap(m_context.Get(), vertex_size * vertex_count);
// TODO: cache - should come from pipeline
const UINT offset = 0;
m_context->IASetVertexBuffers(0, 1, m_vertex_buffer.GetD3DBufferArray(), &vertex_size, &offset);
}
void D3D11Device::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_space, u32* map_base_index)
@ -2147,7 +2152,6 @@ void D3D11Device::MapIndexBuffer(u32 index_count, DrawIndex** map_ptr, u32* map_
void D3D11Device::UnmapIndexBuffer(u32 used_index_count)
{
m_index_buffer.Unmap(m_context.Get(), sizeof(DrawIndex) * used_index_count);
m_context->IASetIndexBuffer(m_index_buffer.GetD3DBuffer(), DXGI_FORMAT_R16_UINT, 0);
}
void D3D11Device::PushUniformBuffer(const void* data, u32 data_size)
@ -2193,6 +2197,33 @@ void D3D11Device::SetFramebuffer(GPUFramebuffer* fb)
return;
}
// Make sure textures aren't bound.
if (D3D11Texture* rt = static_cast<D3D11Texture*>(fb->GetRT()); rt)
{
const ID3D11ShaderResourceView* srv = rt->GetD3DSRV();
for (u32 i = 0; i < MAX_TEXTURE_SAMPLERS; i++)
{
if (m_current_textures[i] == srv)
{
m_current_textures[i] = nullptr;
m_context->PSSetShaderResources(i, 1, &m_current_textures[i]);
}
}
}
if (D3D11Texture* ds = static_cast<D3D11Texture*>(fb->GetDS()); ds)
{
const ID3D11ShaderResourceView* srv = ds->GetD3DSRV();
for (u32 i = 0; i < MAX_TEXTURE_SAMPLERS; i++)
{
if (m_current_textures[i] == srv)
{
m_current_textures[i] = nullptr;
m_context->PSSetShaderResources(i, 1, &m_current_textures[i]);
}
}
}
m_current_framebuffer->CommitClear(m_context.Get());
m_context->OMSetRenderTargets(m_current_framebuffer->GetNumRTVs(), m_current_framebuffer->GetRTVArray(),
m_current_framebuffer->GetDSV());
}
@ -2208,10 +2239,62 @@ void D3D11Device::UnbindFramebuffer(D3D11Framebuffer* fb)
void D3D11Device::SetPipeline(GPUPipeline* pipeline)
{
D3D11Pipeline* PL = static_cast<D3D11Pipeline*>(pipeline);
if (m_current_pipeline == pipeline)
return;
// TODO: cache
PL->Bind(m_context.Get());
D3D11Pipeline* const PL = static_cast<D3D11Pipeline*>(pipeline);
m_current_pipeline = PL;
if (ID3D11InputLayout* il = PL->GetInputLayout(); m_current_input_layout != il)
{
m_current_input_layout = il;
m_context->IASetInputLayout(il);
}
if (const u32 vertex_stride = PL->GetVertexStride(); m_current_vertex_stride != vertex_stride)
{
const UINT offset = 0;
m_current_vertex_stride = PL->GetVertexStride();
m_context->IASetVertexBuffers(0, 1, m_vertex_buffer.GetD3DBufferArray(), &m_current_vertex_stride, &offset);
}
if (D3D_PRIMITIVE_TOPOLOGY topology = PL->GetPrimitiveTopology(); m_current_primitive_topology != topology)
{
m_current_primitive_topology = topology;
m_context->IASetPrimitiveTopology(topology);
}
if (ID3D11VertexShader* vs = PL->GetVertexShader(); m_current_vertex_shader != vs)
{
m_current_vertex_shader = vs;
m_context->VSSetShader(vs, nullptr, 0);
}
if (ID3D11PixelShader* ps = PL->GetPixelShader(); m_current_pixel_shader != ps)
{
m_current_pixel_shader = ps;
m_context->PSSetShader(ps, nullptr, 0);
}
if (ID3D11RasterizerState* rs = PL->GetRasterizerState(); m_current_rasterizer_state != rs)
{
m_current_rasterizer_state = rs;
m_context->RSSetState(rs);
}
if (ID3D11DepthStencilState* ds = PL->GetDepthStencilState(); m_current_depth_state != ds)
{
m_current_depth_state = ds;
m_context->OMSetDepthStencilState(ds, 0);
}
if (ID3D11BlendState* bs = PL->GetBlendState();
m_current_blend_state != bs || m_current_blend_factor != PL->GetBlendFactor())
{
m_current_blend_state = bs;
m_current_blend_factor = PL->GetBlendFactor();
m_context->OMSetBlendState(bs, RGBA8ToFloat(m_current_blend_factor).data(), 0xFFFFFFFFu);
}
}
void D3D11Device::UnbindPipeline(D3D11Pipeline* pl)
@ -2219,27 +2302,57 @@ void D3D11Device::UnbindPipeline(D3D11Pipeline* pl)
if (m_current_pipeline != pl)
return;
// Let the runtime deal with the dead objects...
m_current_pipeline = nullptr;
}
void D3D11Device::SetTextureSampler(u32 slot, GPUTexture* texture, GPUSampler* sampler)
{
// TODO: cache when old rt == tex
D3D11Texture* T = static_cast<D3D11Texture*>(texture);
D3D11Sampler* S = static_cast<D3D11Sampler*>(sampler);
m_context->PSSetShaderResources(0, 1, T->GetD3DSRVArray());
m_context->PSSetSamplers(0, 1, S->GetSamplerStateArray());
ID3D11ShaderResourceView* T = texture ? static_cast<D3D11Texture*>(texture)->GetD3DSRV() : nullptr;
ID3D11SamplerState* S = sampler ? static_cast<D3D11Sampler*>(sampler)->GetSamplerState() : nullptr;
// Runtime will null these if we don't...
DebugAssert(!m_current_framebuffer || !texture ||
(m_current_framebuffer->GetRT() != texture && m_current_framebuffer->GetDS() != texture));
if (m_current_textures[slot] != T)
{
m_current_textures[slot] = T;
m_context->PSSetShaderResources(slot, 1, &T);
}
if (m_current_samplers[slot] != S)
{
m_current_samplers[slot] = S;
m_context->PSSetSamplers(slot, 1, &S);
}
}
void D3D11Device::SetTextureBuffer(u32 slot, GPUTextureBuffer* buffer)
{
D3D11TextureBuffer* B = static_cast<D3D11TextureBuffer*>(buffer);
m_context->PSSetShaderResources(0, 1, B->GetSRVArray());
ID3D11ShaderResourceView* B = buffer ? static_cast<D3D11TextureBuffer*>(buffer)->GetSRV() : nullptr;
if (m_current_textures[slot] != B)
{
m_current_textures[slot] = B;
m_context->PSSetShaderResources(slot, 1, &B);
}
}
void D3D11Device::UnbindTexture(D3D11Texture* tex)
{
// TODO
if (const ID3D11ShaderResourceView* srv = tex->GetD3DSRV(); srv)
{
for (u32 i = 0; i < MAX_TEXTURE_SAMPLERS; i++)
{
if (m_current_textures[i] == srv)
{
m_current_textures[i] = nullptr;
m_context->PSSetShaderResources(i, 1, &m_current_textures[i]);
}
}
}
if (m_current_framebuffer && m_current_framebuffer->GetRT() == tex)
SetFramebuffer(nullptr);
}
void D3D11Device::SetViewport(s32 x, s32 y, s32 width, s32 height)
@ -2255,20 +2368,12 @@ void D3D11Device::SetScissor(s32 x, s32 y, s32 width, s32 height)
m_context->RSSetScissorRects(1, &rc);
}
void D3D11Device::PreDrawCheck()
{
if (m_current_framebuffer)
m_current_framebuffer->CommitClear(m_context.Get());
}
void D3D11Device::Draw(u32 vertex_count, u32 base_vertex)
{
PreDrawCheck();
m_context->Draw(vertex_count, base_vertex);
}
void D3D11Device::DrawIndexed(u32 index_count, u32 base_index, u32 base_vertex)
{
PreDrawCheck();
m_context->DrawIndexed(index_count, base_index, base_vertex);
}

View File

@ -48,8 +48,8 @@ public:
u32 space_aligned; // remaining space / alignment
};
MappingResult Map(ID3D11DeviceContext* context, u32 alignment, u32 min_size);
void Unmap(ID3D11DeviceContext* context, u32 used_size);
MappingResult Map(ID3D11DeviceContext1* context, u32 alignment, u32 min_size);
void Unmap(ID3D11DeviceContext1* context, u32 used_size);
private:
ComPtr<ID3D11Buffer> m_buffer;
@ -74,7 +74,7 @@ public:
ALWAYS_INLINE ID3D11DepthStencilView* GetDSV() const { return m_dsv.Get(); }
void SetDebugName(const std::string_view& name) override;
void CommitClear(ID3D11DeviceContext* context);
void CommitClear(ID3D11DeviceContext1* context);
private:
D3D11Framebuffer(GPUTexture* rt, GPUTexture* ds, u32 width, u32 height, ComPtr<ID3D11RenderTargetView> rtv,
@ -146,13 +146,14 @@ public:
ALWAYS_INLINE ID3D11VertexShader* GetVertexShader() const { return m_vs.Get(); }
ALWAYS_INLINE ID3D11PixelShader* GetPixelShader() const { return m_ps.Get(); }
ALWAYS_INLINE D3D11_PRIMITIVE_TOPOLOGY GetPrimitiveTopology() const { return m_topology; }
void Bind(ID3D11DeviceContext* context);
ALWAYS_INLINE u32 GetVertexStride() const { return m_vertex_stride; }
ALWAYS_INLINE u32 GetBlendFactor() const { return m_blend_factor; }
ALWAYS_INLINE const std::array<float, 4>& GetBlendFactorFloat() const { return m_blend_factor_float; }
private:
D3D11Pipeline(ComPtr<ID3D11RasterizerState> rs, ComPtr<ID3D11DepthStencilState> ds, ComPtr<ID3D11BlendState> bs,
ComPtr<ID3D11InputLayout> il, ComPtr<ID3D11VertexShader> vs, ComPtr<ID3D11PixelShader> ps,
D3D11_PRIMITIVE_TOPOLOGY topology);
D3D11_PRIMITIVE_TOPOLOGY topology, u32 vertex_stride, u32 blend_factor);
ComPtr<ID3D11RasterizerState> m_rs;
ComPtr<ID3D11DepthStencilState> m_ds;
@ -161,6 +162,9 @@ private:
ComPtr<ID3D11VertexShader> m_vs;
ComPtr<ID3D11PixelShader> m_ps;
D3D11_PRIMITIVE_TOPOLOGY m_topology;
u32 m_vertex_stride;
u32 m_blend_factor;
std::array<float, 4> m_blend_factor_float;
};
class D3D11Texture final : public GPUTexture
@ -215,7 +219,7 @@ public:
void Destroy();
D3D11_TEXTURE2D_DESC GetDesc() const;
void CommitClear(ID3D11DeviceContext* context);
void CommitClear(ID3D11DeviceContext1* context);
bool IsValid() const override;
@ -265,7 +269,7 @@ public:
ALWAYS_INLINE static D3D11Device& GetInstance() { return *static_cast<D3D11Device*>(g_gpu_device.get()); }
ALWAYS_INLINE static ID3D11Device* GetD3DDevice() { return GetInstance().m_device.Get(); }
ALWAYS_INLINE static ID3D11DeviceContext* GetD3DContext() { return GetInstance().m_context.Get(); }
ALWAYS_INLINE static ID3D11DeviceContext1* GetD3DContext() { return GetInstance().m_context.Get(); }
// returns the fullscreen mode to use for the specified dimensions
static bool GetRequestedExclusiveFullscreenModeDesc(IDXGIFactory5* factory, const RECT& window_rect, u32 width,
@ -282,7 +286,7 @@ public:
AdapterAndModeList GetAdapterAndModeList() override;
void DestroySurface() override;
std::string GetShaderCacheBaseName(const std::string_view& type, bool debug) const override;
std::string GetShaderCacheBaseName(const std::string_view& type) const override;
std::unique_ptr<GPUTexture> CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples,
GPUTexture::Type type, GPUTexture::Format format,
@ -298,6 +302,9 @@ public:
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
void ClearRenderTarget(GPUTexture* t, u32 c) override;
void ClearDepth(GPUTexture* t, float d) override;
void InvalidateRenderTarget(GPUTexture* t) override;
std::unique_ptr<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt = nullptr, u32 rt_layer = 0, u32 rt_level = 0,
GPUTexture* ds = nullptr, u32 ds_layer = 0,
@ -346,7 +353,7 @@ public:
static AdapterAndModeList StaticGetAdapterAndModeList();
protected:
bool CreateDevice(const std::string_view& adapter, bool debug_device) override;
bool CreateDevice(const std::string_view& adapter) override;
void DestroyDevice() override;
private:
@ -366,8 +373,6 @@ private:
void SetFeatures();
void PreDrawCheck();
bool CheckStagingBufferSize(u32 width, u32 height, DXGI_FORMAT format);
void DestroyStagingBuffer();
@ -418,6 +423,19 @@ private:
D3D11Framebuffer* m_current_framebuffer = nullptr;
D3D11Pipeline* m_current_pipeline = nullptr;
ID3D11InputLayout* m_current_input_layout = nullptr;
ID3D11VertexShader* m_current_vertex_shader = nullptr;
ID3D11PixelShader* m_current_pixel_shader = nullptr;
ID3D11RasterizerState* m_current_rasterizer_state = nullptr;
ID3D11DepthStencilState* m_current_depth_state = nullptr;
ID3D11BlendState* m_current_blend_state = nullptr;
D3D_PRIMITIVE_TOPOLOGY m_current_primitive_topology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
u32 m_current_vertex_stride = 0;
u32 m_current_blend_factor = 0;
std::array<ID3D11ShaderResourceView*, MAX_TEXTURE_SAMPLERS> m_current_textures = {};
std::array<ID3D11SamplerState*, MAX_TEXTURE_SAMPLERS> m_current_samplers = {};
std::array<std::array<ComPtr<ID3D11Query>, 3>, NUM_TIMESTAMP_QUERIES> m_timestamp_queries = {};
u8 m_read_timestamp_query = 0;
u8 m_write_timestamp_query = 0;

View File

@ -237,6 +237,7 @@ bool GPUDevice::Create(const std::string_view& adapter, const std::string_view&
bool vsync)
{
m_vsync_enabled = vsync;
m_debug_device = debug_device;
if (!AcquireWindow(true))
{
@ -244,14 +245,14 @@ bool GPUDevice::Create(const std::string_view& adapter, const std::string_view&
return false;
}
if (!CreateDevice(adapter, debug_device))
if (!CreateDevice(adapter))
{
Log_ErrorPrintf("Failed to create device.");
return false;
}
if (!shader_cache_path.empty())
OpenShaderCache(shader_cache_path, debug_device);
OpenShaderCache(shader_cache_path);
else
Log_WarningPrintf("Shader cache is disabled.");
@ -284,10 +285,10 @@ bool GPUDevice::SupportsExclusiveFullscreen() const
return false;
}
void GPUDevice::OpenShaderCache(const std::string_view& base_path, bool debug)
void GPUDevice::OpenShaderCache(const std::string_view& base_path)
{
// TODO: option to disable shader cache
const std::string basename = GetShaderCacheBaseName("shaders", debug);
const std::string basename = GetShaderCacheBaseName("shaders");
const std::string filename = Path::Combine(base_path, basename);
if (!m_shader_cache.Open(filename.c_str()))
Log_WarningPrintf("Failed to open shader cache.");
@ -418,7 +419,7 @@ bool GPUDevice::SetPostProcessingChain(const std::string_view& config)
return true;
}
std::string GPUDevice::GetShaderCacheBaseName(const std::string_view& type, bool debug) const
std::string GPUDevice::GetShaderCacheBaseName(const std::string_view& type) const
{
Panic("Not implemented");
return {};
@ -648,7 +649,7 @@ void GPUDevice::InvalidateRenderTarget(GPUTexture* t)
t->SetState(GPUTexture::State::Invalidated);
}
bool GPUDevice::CreateDevice(const std::string_view& adapter, bool debug_device)
bool GPUDevice::CreateDevice(const std::string_view& adapter)
{
// TODO: REMOVE ME
UnreachableCode();
@ -811,6 +812,13 @@ std::string GPUDevice::GetShaderDumpPath(const std::string_view& name)
return Path::Combine(EmuFolders::Dumps, name);
}
std::array<float, 4> GPUDevice::RGBA8ToFloat(u32 rgba)
{
return std::array<float, 4>{static_cast<float>(rgba & 0xFF) / 255.0f, static_cast<float>((rgba >> 8) & 0xFF) / 255.0f,
static_cast<float>((rgba >> 16) & 0xFF) / 255.0f,
static_cast<float>((rgba >> 24) & 0xFF) / 255.0f};
}
bool GPUDevice::UpdateImGuiFontTexture()
{
ImGuiIO& io = ImGui::GetIO();

View File

@ -447,6 +447,9 @@ public:
/// Returns the directory bad shaders are saved to.
static std::string GetShaderDumpPath(const std::string_view& name);
/// Converts a RGBA8 value to 4 floating-point values.
static std::array<float, 4> RGBA8ToFloat(u32 rgba);
ALWAYS_INLINE const Features& GetFeatures() const { return m_features; }
ALWAYS_INLINE u32 GetMaxTextureSize() const { return m_max_texture_size; }
ALWAYS_INLINE u32 GetMaxMultisamples() const { return m_max_multisamples; }
@ -489,7 +492,7 @@ public:
virtual bool SetPostProcessingChain(const std::string_view& config);
virtual std::string GetShaderCacheBaseName(const std::string_view& type, bool debug) const;
virtual std::string GetShaderCacheBaseName(const std::string_view& type) const;
/// Call when the window size changes externally to recreate any resources.
virtual void ResizeWindow(s32 new_window_width, s32 new_window_height, float new_window_scale);
@ -509,9 +512,9 @@ public:
virtual void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level,
GPUTexture* src, u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width,
u32 height);
void ClearRenderTarget(GPUTexture* t, u32 c);
void ClearDepth(GPUTexture* t, float d);
void InvalidateRenderTarget(GPUTexture* t);
virtual void ClearRenderTarget(GPUTexture* t, u32 c);
virtual void ClearDepth(GPUTexture* t, float d);
virtual void InvalidateRenderTarget(GPUTexture* t);
/// Framebuffer abstraction.
virtual std::unique_ptr<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt = nullptr, u32 rt_layer = 0,
@ -627,7 +630,7 @@ public:
bool WriteScreenshotToFile(std::string filename, bool internal_resolution = false, bool compress_on_thread = false);
protected:
virtual bool CreateDevice(const std::string_view& adapter, bool debug_device);
virtual bool CreateDevice(const std::string_view& adapter);
virtual void DestroyDevice();
virtual std::unique_ptr<GPUShader> CreateShaderFromBinary(GPUShaderStage stage, gsl::span<const u8> data);
@ -649,12 +652,13 @@ protected:
bool m_gpu_timing_enabled = false;
bool m_vsync_enabled = false;
bool m_debug_device = false;
private:
ALWAYS_INLINE bool HasSoftwareCursor() const { return static_cast<bool>(m_cursor_texture); }
ALWAYS_INLINE bool HasDisplayTexture() const { return (m_display_texture != nullptr); }
void OpenShaderCache(const std::string_view& base_path, bool debug);
void OpenShaderCache(const std::string_view& base_path);
bool CreateResources();
void DestroyResources();

View File

@ -208,6 +208,9 @@ public:
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
void ClearRenderTarget(GPUTexture* t, u32 c) override;
void ClearDepth(GPUTexture* t, float d) override;
void InvalidateRenderTarget(GPUTexture* t) override;
std::unique_ptr<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt = nullptr, u32 rt_layer = 0, u32 rt_level = 0,
GPUTexture* ds = nullptr, u32 ds_layer = 0,

View File

@ -1292,10 +1292,10 @@ void MetalDevice::CopyTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 d
{
DebugAssert(src_level < src->GetLevels() && src_layer < src->GetLayers());
DebugAssert((src_x + width) <= src->GetMipWidth(src_level));
DebugAssert((src_y + height) <= src->GetMipWidth(src_level));
DebugAssert((src_y + height) <= src->GetMipHeight(src_level));
DebugAssert(dst_level < dst->GetLevels() && dst_layer < dst->GetLayers());
DebugAssert((dst_x + width) <= dst->GetMipWidth(dst_level));
DebugAssert((dst_y + height) <= dst->GetMipWidth(dst_level));
DebugAssert((dst_y + height) <= dst->GetMipHeight(dst_level));
MetalTexture* D = static_cast<MetalTexture*>(dst);
MetalTexture* S = static_cast<MetalTexture*>(src);
@ -1349,10 +1349,10 @@ void MetalDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u3
#if 0
DebugAssert(src_level < src->GetLevels() && src_layer < src->GetLayers());
DebugAssert((src_x + width) <= src->GetMipWidth(src_level));
DebugAssert((src_y + height) <= src->GetMipWidth(src_level));
DebugAssert((src_y + height) <= src->GetMipHeight(src_level));
DebugAssert(dst_level < dst->GetLevels() && dst_layer < dst->GetLayers());
DebugAssert((dst_x + width) <= dst->GetMipWidth(dst_level));
DebugAssert((dst_y + height) <= dst->GetMipWidth(dst_level));
DebugAssert((dst_y + height) <= dst->GetMipHeight(dst_level));
DebugAssert(!dst->IsMultisampled() && src->IsMultisampled());
// DX11 can't resolve partial rects.

View File

@ -191,6 +191,27 @@ void OpenGLDevice::ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
void OpenGLDevice::ClearRenderTarget(GPUTexture* t, u32 c)
{
GPUDevice::ClearRenderTarget(t, c);
if (m_current_framebuffer && m_current_framebuffer->GetRT() == t)
CommitClear(m_current_framebuffer);
}
void OpenGLDevice::ClearDepth(GPUTexture* t, float d)
{
GPUDevice::ClearDepth(t, d);
if (m_current_framebuffer && m_current_framebuffer->GetDS() == t)
CommitClear(m_current_framebuffer);
}
void OpenGLDevice::InvalidateRenderTarget(GPUTexture* t)
{
GPUDevice::InvalidateRenderTarget(t);
if (m_current_framebuffer && (m_current_framebuffer->GetRT() == t || m_current_framebuffer->GetDS() == t))
CommitClear(m_current_framebuffer);
}
void OpenGLDevice::PushDebugGroup(const char* fmt, ...)
{
#ifdef _DEBUG
@ -268,7 +289,7 @@ bool OpenGLDevice::HasSurface() const
return m_window_info.type != WindowInfo::Type::Surfaceless;
}
bool OpenGLDevice::CreateDevice(const std::string_view& adapter, bool debug_device)
bool OpenGLDevice::CreateDevice(const std::string_view& adapter)
{
m_gl_context = GL::Context::Create(m_window_info);
if (!m_gl_context)
@ -307,7 +328,7 @@ bool OpenGLDevice::CreateDevice(const std::string_view& adapter, bool debug_devi
Log_VerbosePrintf("Using PBO for uploads: %s", OpenGLTexture::s_use_pbo_for_uploads ? "yes" : "no");
if (debug_device && GLAD_GL_KHR_debug)
if (m_debug_device && GLAD_GL_KHR_debug)
{
if (m_gl_context->IsGLES())
glDebugMessageCallbackKHR(GLDebugCallback, nullptr);
@ -493,9 +514,9 @@ void OpenGLDevice::DestroySurface()
Log_ErrorPrintf("Failed to switch to surfaceless");
}
std::string OpenGLDevice::GetShaderCacheBaseName(const std::string_view& type, bool debug) const
std::string OpenGLDevice::GetShaderCacheBaseName(const std::string_view& type) const
{
return fmt::format("opengl_{}{}", type, debug ? "_debug" : "");
return fmt::format("opengl_{}{}", type, m_debug_device ? "_debug" : "");
}
bool OpenGLDevice::CreateBuffers()

View File

@ -48,7 +48,7 @@ public:
AdapterAndModeList GetAdapterAndModeList() override;
std::string GetShaderCacheBaseName(const std::string_view& type, bool debug) const override;
std::string GetShaderCacheBaseName(const std::string_view& type) const override;
std::unique_ptr<GPUTexture> CreateTexture(u32 width, u32 height, u32 layers, u32 levels, u32 samples,
GPUTexture::Type type, GPUTexture::Format format,
@ -64,6 +64,9 @@ public:
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
void ResolveTextureRegion(GPUTexture* dst, u32 dst_x, u32 dst_y, u32 dst_layer, u32 dst_level, GPUTexture* src,
u32 src_x, u32 src_y, u32 src_layer, u32 src_level, u32 width, u32 height) override;
void ClearRenderTarget(GPUTexture* t, u32 c) override;
void ClearDepth(GPUTexture* t, float d) override;
void InvalidateRenderTarget(GPUTexture* t) override;
std::unique_ptr<GPUFramebuffer> CreateFramebuffer(GPUTexture* rt = nullptr, u32 rt_layer = 0, u32 rt_level = 0,
GPUTexture* ds = nullptr, u32 ds_layer = 0,
@ -134,7 +137,7 @@ protected:
OpenGLPipeline::VertexArrayCache m_vao_cache;
OpenGLPipeline::ProgramCache m_program_cache;
bool CreateDevice(const std::string_view& adapter, bool debug_device) override;
bool CreateDevice(const std::string_view& adapter) override;
void DestroyDevice() override;
bool CreateBuffers();

View File

@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#include "gpu_hw.h"
@ -182,7 +182,7 @@ bool GPU_HW::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_di
}
g_gpu_device->CopyTextureRegion(m_vram_texture.get(), 0, 0, 0, 0, tex, 0, 0, 0, 0, tex->GetWidth(),
tex->GetHeight());
tex->GetHeight());
}
else
{
@ -202,7 +202,7 @@ bool GPU_HW::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_di
}
g_gpu_device->CopyTextureRegion(tex, 0, 0, 0, 0, m_vram_texture.get(), 0, 0, 0, 0, tex->GetWidth(),
tex->GetHeight());
tex->GetHeight());
}
}
@ -227,37 +227,6 @@ void GPU_HW::RestoreGraphicsAPIState()
}
void GPU_HW::UpdateSettings()
{
// TODO: Merge UpdateHWSettings() into here.
bool framebuffer_changed, shaders_changed;
UpdateHWSettings(&framebuffer_changed, &shaders_changed);
if (framebuffer_changed)
{
RestoreGraphicsAPIState();
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
g_gpu_device->ClearDisplayTexture();
CreateBuffers();
}
if (shaders_changed)
{
DestroyPipelines();
if (!CompilePipelines())
Panic("Failed to recompile pipelnes.");
}
if (framebuffer_changed)
{
RestoreGraphicsAPIState();
UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr, false, false);
UpdateDepthBufferFromMaskBit();
UpdateDisplay();
}
}
// TODO: Merge into UpdateSettings()
void GPU_HW::UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed)
{
const u32 resolution_scale = CalculateResolutionScale();
const u32 multisamples = std::min(m_max_multisamples, g_settings.gpu_multisamples);
@ -266,9 +235,9 @@ void GPU_HW::UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed)
const bool use_uv_limits = ShouldUseUVLimits();
const bool disable_color_perspective = m_supports_disable_color_perspective && ShouldDisableColorPerspective();
*framebuffer_changed =
const bool framebuffer_changed =
(m_resolution_scale != resolution_scale || m_multisamples != multisamples || m_downsample_mode != downsample_mode);
*shaders_changed =
const bool shaders_changed =
(m_resolution_scale != resolution_scale || m_multisamples != multisamples ||
m_true_color != g_settings.gpu_true_color || m_per_sample_shading != per_sample_shading ||
m_scaled_dithering != g_settings.gpu_scaled_dithering || m_texture_filtering != g_settings.gpu_texture_filter ||
@ -301,6 +270,15 @@ void GPU_HW::UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed)
}
}
// Back up VRAM if we're recreating the framebuffer.
if (framebuffer_changed)
{
RestoreGraphicsAPIState();
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
g_gpu_device->ClearDisplayTexture();
DestroyBuffers();
}
m_resolution_scale = resolution_scale;
m_multisamples = multisamples;
m_per_sample_shading = per_sample_shading;
@ -326,6 +304,25 @@ void GPU_HW::UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed)
UpdateSoftwareRenderer(true);
PrintSettingsToLog();
if (shaders_changed)
{
DestroyPipelines();
if (!CompilePipelines())
Panic("Failed to recompile pipelnes.");
}
if (framebuffer_changed)
{
// TODO: weird vram loss when rapidly changing resolutions
if (!CreateBuffers())
Panic("Failed to recreate buffers.");
RestoreGraphicsAPIState();
UpdateVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT, m_vram_ptr, false, false);
UpdateDepthBufferFromMaskBit();
UpdateDisplay();
}
}
u32 GPU_HW::CalculateResolutionScale() const
@ -426,17 +423,17 @@ bool GPU_HW::CreateBuffers()
const u8 samples = static_cast<u8>(m_multisamples);
if (!(m_vram_texture = g_gpu_device->CreateTexture(texture_width, texture_height, 1, 1, samples,
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)) ||
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)) ||
!(m_vram_depth_texture = g_gpu_device->CreateTexture(texture_width, texture_height, 1, 1, samples,
GPUTexture::Type::DepthStencil, VRAM_DS_FORMAT)) ||
GPUTexture::Type::DepthStencil, VRAM_DS_FORMAT)) ||
!(m_vram_read_texture = g_gpu_device->CreateTexture(texture_width, texture_height, 1, 1, 1,
GPUTexture::Type::Texture, VRAM_RT_FORMAT)) ||
GPUTexture::Type::Texture, VRAM_RT_FORMAT)) ||
!(m_display_texture = g_gpu_device->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, VRAM_RT_FORMAT)) ||
!(m_vram_readback_texture = g_gpu_device->CreateTexture(VRAM_WIDTH / 2, VRAM_HEIGHT, 1, 1, 1,
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)))
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)))
{
return false;
}
@ -460,7 +457,7 @@ bool GPU_HW::CreateBuffers()
// TODO: check caps
if (!(m_vram_upload_buffer = g_gpu_device->CreateTextureBuffer(GPUTextureBuffer::Format::R16UI,
VRAM_UPDATE_TEXTURE_BUFFER_SIZE / sizeof(u16))))
VRAM_UPDATE_TEXTURE_BUFFER_SIZE / sizeof(u16))))
{
return false;
}
@ -505,7 +502,7 @@ bool GPU_HW::CreateBuffers()
if (m_downsample_mode == GPUDownsampleMode::Box)
{
if (!(m_downsample_texture = g_gpu_device->CreateTexture(VRAM_WIDTH, VRAM_HEIGHT, 1, 1, 1,
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)) ||
GPUTexture::Type::RenderTarget, VRAM_RT_FORMAT)) ||
!(m_downsample_framebuffer = g_gpu_device->CreateFramebuffer(m_downsample_texture.get())))
{
return false;
@ -780,8 +777,8 @@ bool GPU_HW::CompilePipelines()
// TODO: SSBO path here...
{
const bool use_ssbo = features.texture_buffers_emulated_with_ssbo;
std::unique_ptr<GPUShader> fs = g_gpu_device->CreateShader(
GPUShaderStage::Fragment, shadergen.GenerateVRAMWriteFragmentShader(use_ssbo));
std::unique_ptr<GPUShader> fs =
g_gpu_device->CreateShader(GPUShaderStage::Fragment, shadergen.GenerateVRAMWriteFragmentShader(use_ssbo));
if (!fs)
return false;
@ -1002,14 +999,14 @@ void GPU_HW::UpdateVRAMReadTexture()
if (m_vram_texture->IsMultisampled())
{
g_gpu_device->ResolveTextureRegion(m_vram_read_texture.get(), scaled_rect.left, scaled_rect.top, 0, 0,
m_vram_texture.get(), scaled_rect.left, scaled_rect.top, 0, 0,
scaled_rect.GetWidth(), scaled_rect.GetHeight());
m_vram_texture.get(), scaled_rect.left, scaled_rect.top, 0, 0,
scaled_rect.GetWidth(), scaled_rect.GetHeight());
}
else
{
g_gpu_device->CopyTextureRegion(m_vram_read_texture.get(), scaled_rect.left, scaled_rect.top, 0, 0,
m_vram_texture.get(), scaled_rect.left, scaled_rect.top, 0, 0,
scaled_rect.GetWidth(), scaled_rect.GetHeight());
m_vram_texture.get(), scaled_rect.left, scaled_rect.top, 0, 0,
scaled_rect.GetWidth(), scaled_rect.GetHeight());
}
m_renderer_stats.num_vram_read_texture_updates++;
@ -1844,7 +1841,7 @@ bool GPU_HW::BlitVRAMReplacementTexture(const TextureReplacementTexture* tex, u3
if (!(m_vram_replacement_texture =
g_gpu_device->CreateTexture(tex->GetWidth(), tex->GetHeight(), 1, 1, 1, GPUTexture::Type::Texture,
GPUTexture::Format::RGBA8, tex->GetPixels(), tex->GetPitch(), true)))
GPUTexture::Format::RGBA8, tex->GetPixels(), tex->GetPitch(), true)))
{
return false;
}
@ -2053,13 +2050,12 @@ void GPU_HW::FillVRAM(u32 x, u32 y, u32 width, u32 height, u32 color)
Common::Rectangle<u32>::FromExtents(x, y, width, height).Clamped(0, 0, VRAM_WIDTH, VRAM_HEIGHT));
g_gpu_device->SetPipeline(m_vram_fill_pipelines[BoolToUInt8(IsVRAMFillOversized(x, y, width, height))]
[BoolToUInt8(IsInterlacedRenderingEnabled())]
.get());
[BoolToUInt8(IsInterlacedRenderingEnabled())]
.get());
const Common::Rectangle<u32> bounds(GetVRAMTransferBounds(x, y, width, height));
g_gpu_device->SetViewportAndScissor(bounds.left * m_resolution_scale, bounds.top * m_resolution_scale,
bounds.GetWidth() * m_resolution_scale,
bounds.GetHeight() * m_resolution_scale);
bounds.GetWidth() * m_resolution_scale, bounds.GetHeight() * m_resolution_scale);
const VRAMFillUBOData uniforms = GetVRAMFillUBOData(x, y, width, height, color);
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
@ -2089,11 +2085,12 @@ void GPU_HW::ReadVRAM(u32 x, u32 y, u32 width, u32 height)
g_gpu_device->SetViewportAndScissor(0, 0, encoded_width, encoded_height);
g_gpu_device->PushUniformBuffer(uniforms, sizeof(uniforms));
g_gpu_device->Draw(3, 0);
m_vram_readback_texture->MakeReadyForSampling();
// Stage the readback and copy it into our shadow buffer.
g_gpu_device->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));
reinterpret_cast<u32*>(&m_vram_shadow[copy_rect.top * VRAM_WIDTH + copy_rect.left]),
VRAM_WIDTH * sizeof(u16));
RestoreGraphicsAPIState();
}
@ -2133,8 +2130,7 @@ void GPU_HW::UpdateVRAM(u32 x, u32 y, u32 width, u32 height, const void* data, b
// 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;
g_gpu_device->SetScissor(scaled_bounds.left, scaled_bounds.top, scaled_bounds.GetWidth(),
scaled_bounds.GetHeight());
g_gpu_device->SetScissor(scaled_bounds.left, scaled_bounds.top, scaled_bounds.GetWidth(), scaled_bounds.GetHeight());
g_gpu_device->SetPipeline(m_vram_write_pipelines[BoolToUInt8(check_mask && !m_pgxp_depth_buffer)].get());
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
g_gpu_device->SetTextureBuffer(0, m_vram_upload_buffer.get());
@ -2161,7 +2157,7 @@ void GPU_HW::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32
// VRAM read texture should already be bound.
const Common::Rectangle<u32> dst_bounds_scaled(dst_bounds * m_resolution_scale);
g_gpu_device->SetViewportAndScissor(dst_bounds_scaled.left, dst_bounds_scaled.top, dst_bounds_scaled.GetWidth(),
dst_bounds_scaled.GetHeight());
dst_bounds_scaled.GetHeight());
g_gpu_device->SetPipeline(
m_vram_copy_pipelines[BoolToUInt8(m_GPUSTAT.check_mask_before_draw && !m_pgxp_depth_buffer)].get());
g_gpu_device->PushUniformBuffer(&uniforms, sizeof(uniforms));
@ -2193,8 +2189,8 @@ void GPU_HW::CopyVRAM(u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32
}
g_gpu_device->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);
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()
@ -2352,23 +2348,23 @@ void GPU_HW::UpdateDisplay()
{
UpdateVRAMReadTexture();
g_gpu_device->SetDisplayTexture(m_vram_read_texture.get(), 0, 0, m_vram_read_texture->GetWidth(),
m_vram_read_texture->GetHeight());
m_vram_read_texture->GetHeight());
}
else
{
g_gpu_device->SetDisplayTexture(m_vram_texture.get(), 0, 0, m_vram_texture->GetWidth(),
m_vram_texture->GetHeight());
m_vram_texture->GetHeight());
}
g_gpu_device->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
}
else
{
g_gpu_device->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());
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;
@ -2398,7 +2394,7 @@ void GPU_HW::UpdateDisplay()
else
{
g_gpu_device->SetDisplayTexture(m_vram_texture.get(), scaled_vram_offset_x, scaled_vram_offset_y,
scaled_display_width, scaled_display_height);
scaled_display_width, scaled_display_height);
}
}
else

View File

@ -20,7 +20,7 @@ class GPU_SW_Backend;
struct GPUBackendCommand;
struct GPUBackendDrawCommand;
class GPU_HW : public GPU
class GPU_HW final : public GPU
{
public:
enum class BatchRenderMode : u8
@ -209,8 +209,6 @@ protected:
static_cast<float>(rgba >> 24) * (1.0f / 255.0f));
}
void UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed);
bool CreateBuffers();
void ClearFramebuffer();
void DestroyBuffers();
@ -461,8 +459,8 @@ protected:
std::unique_ptr<GPUTexture> m_downsample_texture;
std::unique_ptr<GPUFramebuffer> m_downsample_framebuffer;
//std::unique_ptr<GPUTexture> m_downsample_weight_texture;
//std::unique_ptr<GPUFramebuffer> m_downsample_weight_framebuffer;
// std::unique_ptr<GPUTexture> m_downsample_weight_texture;
// std::unique_ptr<GPUFramebuffer> m_downsample_weight_framebuffer;
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

@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#if 0
#include "gpu_hw_d3d12.h"
#include "common/align.h"
#include "common/assert.h"
@ -1165,3 +1167,5 @@ std::unique_ptr<GPU> GPU::CreateHardwareD3D12Renderer()
return gpu;
}
#endif
#endif

View File

@ -2,6 +2,8 @@
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#if 0
#include "common/dimensional_array.h"
#include "gpu/d3d12/staging_texture.h"
#include "gpu/d3d12/stream_buffer.h"
@ -101,3 +103,5 @@ private:
D3D12::Texture m_vram_write_replacement_texture;
D3D12::StreamBuffer m_texture_replacment_stream_buffer;
};
#endif

View File

@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin <stenzek@gmail.com>
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#if 0
#include "gpu_hw_vulkan.h"
#include "common/assert.h"
#include "common/log.h"
@ -1858,3 +1860,5 @@ void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 l
g_gpu_device->SetDisplayTexture(&m_display_texture, left, top, width, height);
}
#endif

View File

@ -2,6 +2,9 @@
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
#pragma once
#if 0
#include "common/dimensional_array.h"
#include "gpu/vulkan/stream_buffer.h"
#include "gpu/vulkan/texture.h"
@ -155,3 +158,5 @@ private:
VkPipeline m_downsample_blur_pass_pipeline = VK_NULL_HANDLE;
VkPipeline m_downsample_composite_pass_pipeline = VK_NULL_HANDLE;
};
#endif

View File

@ -458,8 +458,10 @@ void EmuThread::startFullscreenUI()
setInitialState(s_start_fullscreen_ui_fullscreen ? std::optional<bool>(true) : std::optional<bool>());
m_run_fullscreen_ui = true;
if (!Host::CreateGPUDevice(Settings::GetRenderAPIForRenderer(g_settings.gpu_renderer)))
if (!Host::CreateGPUDevice(Settings::GetRenderAPIForRenderer(g_settings.gpu_renderer)) || !FullscreenUI::Initialize())
{
Host::ReleaseGPUDevice();
Host::ReleaseRenderWindow();
m_run_fullscreen_ui = false;
return;
}