diff --git a/src/core/gpu/d3d11_device.cpp b/src/core/gpu/d3d11_device.cpp index 1e24bf70b..a3e92a0c8 100644 --- a/src/core/gpu/d3d11_device.cpp +++ b/src/core/gpu/d3d11_device.cpp @@ -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(dst); D3D11Texture* src11 = static_cast(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(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(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(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 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 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 D3D11Device::CreateShaderFromBinary(GPUShaderStage st std::unique_ptr D3D11Device::CreateShaderFromSource(GPUShaderStage stage, const std::string_view& source, std::vector* 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 D3D11Device::CreateShaderFromSource(GPUShaderStage st ComPtr 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 D3D11Device::CreateShaderFromSource(GPUShaderStage st D3D11Pipeline::D3D11Pipeline(ComPtr rs, ComPtr ds, ComPtr bs, ComPtr il, ComPtr vs, - ComPtr ps, D3D11_PRIMITIVE_TOPOLOGY topology) + ComPtr 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 D3D11Device::GetRasterizationState(const GPUPipeline::RasterizationState& rs) { ComPtr drs; @@ -1627,12 +1639,6 @@ D3D11Device::ComPtr D3D11Device::GetInputLayout(const GPUPipe return dil; } -#if 0 - static constexpr std::array(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(GPUPipeline::VertexAttribute::Type::MaxCount)][MAX_COMPONENTS] = { @@ -1683,9 +1689,11 @@ std::unique_ptr D3D11Device::CreatePipeline(const GPUPipeline::Grap return {}; ComPtr il; + u32 vertex_stride = 0; if (!config.input_layout.vertex_attributes.empty()) { il = GetInputLayout(config.input_layout, static_cast(config.vertex_shader)); + vertex_stride = config.input_layout.vertex_stride; if (!il) return {}; } @@ -1702,7 +1710,7 @@ std::unique_ptr D3D11Device::CreatePipeline(const GPUPipeline::Grap new D3D11Pipeline(std::move(rs), std::move(ds), std::move(bs), std::move(il), static_cast(config.vertex_shader)->GetVertexShader(), static_cast(config.fragment_shader)->GetPixelShader(), - primitives[static_cast(config.primitive)])); + primitives[static_cast(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(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(layers); m_levels = static_cast(levels); m_samples = static_cast(samples); + m_type = type; m_format = format; m_dynamic = dynamic; return true; @@ -2021,6 +2029,7 @@ bool D3D11Texture::Adopt(ID3D11Device* device, ComPtr 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(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(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(pipeline); + if (m_current_pipeline == pipeline) + return; - // TODO: cache - PL->Bind(m_context.Get()); + D3D11Pipeline* const PL = static_cast(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(texture); - D3D11Sampler* S = static_cast(sampler); - m_context->PSSetShaderResources(0, 1, T->GetD3DSRVArray()); - m_context->PSSetSamplers(0, 1, S->GetSamplerStateArray()); + ID3D11ShaderResourceView* T = texture ? static_cast(texture)->GetD3DSRV() : nullptr; + ID3D11SamplerState* S = sampler ? static_cast(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(buffer); - m_context->PSSetShaderResources(0, 1, B->GetSRVArray()); + ID3D11ShaderResourceView* B = buffer ? static_cast(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); } diff --git a/src/core/gpu/d3d11_device.h b/src/core/gpu/d3d11_device.h index 54993d54e..727f3a2d6 100644 --- a/src/core/gpu/d3d11_device.h +++ b/src/core/gpu/d3d11_device.h @@ -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 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 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& GetBlendFactorFloat() const { return m_blend_factor_float; } private: D3D11Pipeline(ComPtr rs, ComPtr ds, ComPtr bs, ComPtr il, ComPtr vs, ComPtr ps, - D3D11_PRIMITIVE_TOPOLOGY topology); + D3D11_PRIMITIVE_TOPOLOGY topology, u32 vertex_stride, u32 blend_factor); ComPtr m_rs; ComPtr m_ds; @@ -161,6 +162,9 @@ private: ComPtr m_vs; ComPtr m_ps; D3D11_PRIMITIVE_TOPOLOGY m_topology; + u32 m_vertex_stride; + u32 m_blend_factor; + std::array 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(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 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 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 m_current_textures = {}; + std::array m_current_samplers = {}; + std::array, 3>, NUM_TIMESTAMP_QUERIES> m_timestamp_queries = {}; u8 m_read_timestamp_query = 0; u8 m_write_timestamp_query = 0; diff --git a/src/core/gpu/gpu_device.cpp b/src/core/gpu/gpu_device.cpp index 501e0f27a..b735c1537 100644 --- a/src/core/gpu/gpu_device.cpp +++ b/src/core/gpu/gpu_device.cpp @@ -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 GPUDevice::RGBA8ToFloat(u32 rgba) +{ + return std::array{static_cast(rgba & 0xFF) / 255.0f, static_cast((rgba >> 8) & 0xFF) / 255.0f, + static_cast((rgba >> 16) & 0xFF) / 255.0f, + static_cast((rgba >> 24) & 0xFF) / 255.0f}; +} + bool GPUDevice::UpdateImGuiFontTexture() { ImGuiIO& io = ImGui::GetIO(); diff --git a/src/core/gpu/gpu_device.h b/src/core/gpu/gpu_device.h index a911718a5..02ff25e58 100644 --- a/src/core/gpu/gpu_device.h +++ b/src/core/gpu/gpu_device.h @@ -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 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 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 CreateShaderFromBinary(GPUShaderStage stage, gsl::span 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(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(); diff --git a/src/core/gpu/metal_device.h b/src/core/gpu/metal_device.h index f2bb7841c..f0910eac2 100644 --- a/src/core/gpu/metal_device.h +++ b/src/core/gpu/metal_device.h @@ -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 CreateFramebuffer(GPUTexture* rt = nullptr, u32 rt_layer = 0, u32 rt_level = 0, GPUTexture* ds = nullptr, u32 ds_layer = 0, diff --git a/src/core/gpu/metal_device.mm b/src/core/gpu/metal_device.mm index 22f2fb993..115563bfb 100644 --- a/src/core/gpu/metal_device.mm +++ b/src/core/gpu/metal_device.mm @@ -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(dst); MetalTexture* S = static_cast(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. diff --git a/src/core/gpu/opengl_device.cpp b/src/core/gpu/opengl_device.cpp index 039bfaf61..430e7e2e2 100644 --- a/src/core/gpu/opengl_device.cpp +++ b/src/core/gpu/opengl_device.cpp @@ -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() diff --git a/src/core/gpu/opengl_device.h b/src/core/gpu/opengl_device.h index 79a8ed232..42ff3045f 100644 --- a/src/core/gpu/opengl_device.h +++ b/src/core/gpu/opengl_device.h @@ -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 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 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(); diff --git a/src/core/gpu_hw.cpp b/src/core/gpu_hw.cpp index 0a2e610a3..e5e487ce8 100644 --- a/src/core/gpu_hw.cpp +++ b/src/core/gpu_hw.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2023 Connor McLaughlin // 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(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 fs = g_gpu_device->CreateShader( - GPUShaderStage::Fragment, shadergen.GenerateVRAMWriteFragmentShader(use_ssbo)); + std::unique_ptr 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::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 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(&m_vram_shadow[copy_rect.top * VRAM_WIDTH + copy_rect.left]), - VRAM_WIDTH * sizeof(u16)); + reinterpret_cast(&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 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 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(VRAM_WIDTH) / static_cast(VRAM_HEIGHT)); + static_cast(VRAM_WIDTH) / static_cast(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 diff --git a/src/core/gpu_hw.h b/src/core/gpu_hw.h index a8f9d1489..efa75ef5a 100644 --- a/src/core/gpu_hw.h +++ b/src/core/gpu_hw.h @@ -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(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 m_downsample_texture; std::unique_ptr m_downsample_framebuffer; - //std::unique_ptr m_downsample_weight_texture; - //std::unique_ptr m_downsample_weight_framebuffer; + // std::unique_ptr m_downsample_weight_texture; + // std::unique_ptr m_downsample_weight_framebuffer; std::unique_ptr m_downsample_first_pass_pipeline; std::unique_ptr m_downsample_mid_pass_pipeline; std::unique_ptr m_downsample_blur_pass_pipeline; diff --git a/src/core/gpu_hw_d3d12.cpp b/src/core/gpu_hw_d3d12.cpp index f831b1541..c5d38e2eb 100644 --- a/src/core/gpu_hw_d3d12.cpp +++ b/src/core/gpu_hw_d3d12.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin // 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::CreateHardwareD3D12Renderer() return gpu; } #endif + +#endif \ No newline at end of file diff --git a/src/core/gpu_hw_d3d12.h b/src/core/gpu_hw_d3d12.h index 2a2d77f24..1afbc004c 100644 --- a/src/core/gpu_hw_d3d12.h +++ b/src/core/gpu_hw_d3d12.h @@ -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 \ No newline at end of file diff --git a/src/core/gpu_hw_vulkan.cpp b/src/core/gpu_hw_vulkan.cpp index c82c007e5..e00df0bf7 100644 --- a/src/core/gpu_hw_vulkan.cpp +++ b/src/core/gpu_hw_vulkan.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2019-2022 Connor McLaughlin // 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 \ No newline at end of file diff --git a/src/core/gpu_hw_vulkan.h b/src/core/gpu_hw_vulkan.h index a6c6aaabf..6c66c3fcb 100644 --- a/src/core/gpu_hw_vulkan.h +++ b/src/core/gpu_hw_vulkan.h @@ -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 diff --git a/src/duckstation-qt/qthost.cpp b/src/duckstation-qt/qthost.cpp index a3789ab1c..d7c87f04d 100644 --- a/src/duckstation-qt/qthost.cpp +++ b/src/duckstation-qt/qthost.cpp @@ -458,8 +458,10 @@ void EmuThread::startFullscreenUI() setInitialState(s_start_fullscreen_ui_fullscreen ? std::optional(true) : std::optional()); 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; }