diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 69391a86d..998b30cd0 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -82,8 +82,6 @@ if(WIN32) d3d11/shader_cache.h d3d11/shader_compiler.cpp d3d11/shader_compiler.h - d3d11/staging_texture.cpp - d3d11/staging_texture.h d3d11/stream_buffer.cpp d3d11/stream_buffer.h d3d11/texture.cpp diff --git a/src/common/common.vcxproj b/src/common/common.vcxproj index 573b921fb..0fdb9eb11 100644 --- a/src/common/common.vcxproj +++ b/src/common/common.vcxproj @@ -11,7 +11,6 @@ - @@ -114,7 +113,6 @@ - diff --git a/src/common/common.vcxproj.filters b/src/common/common.vcxproj.filters index 2f24c65d4..14449df6a 100644 --- a/src/common/common.vcxproj.filters +++ b/src/common/common.vcxproj.filters @@ -20,9 +20,6 @@ d3d11 - - d3d11 - d3d11 @@ -146,9 +143,6 @@ d3d11 - - d3d11 - d3d11 diff --git a/src/common/d3d11/staging_texture.cpp b/src/common/d3d11/staging_texture.cpp deleted file mode 100644 index a90a3f365..000000000 --- a/src/common/d3d11/staging_texture.cpp +++ /dev/null @@ -1,117 +0,0 @@ -#include "staging_texture.h" -#include "../assert.h" -#include "../log.h" -Log_SetChannel(D3D11); - -namespace D3D11 { - -StagingTexture::StagingTexture() : m_width(0), m_height(0) {} - -StagingTexture::~StagingTexture() -{ - Destroy(); -} - -bool StagingTexture::Create(ID3D11Device* device, u32 width, u32 height, DXGI_FORMAT format, bool for_uploading) -{ - CD3D11_TEXTURE2D_DESC desc(format, width, height, 1, 1, 0, for_uploading ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_STAGING, - for_uploading ? D3D11_CPU_ACCESS_WRITE : D3D11_CPU_ACCESS_READ, 1, 0, 0); - - ComPtr texture; - const HRESULT tex_hr = device->CreateTexture2D(&desc, nullptr, texture.GetAddressOf()); - if (FAILED(tex_hr)) - { - Log_ErrorPrintf("Create texture failed: 0x%08X", tex_hr); - return false; - } - - m_texture = std::move(texture); - m_width = desc.Width; - m_height = desc.Height; - m_format = desc.Format; - return true; -} - -void StagingTexture::Destroy() -{ - Assert(!IsMapped()); - m_texture.Reset(); -} - -bool StagingTexture::Map(ID3D11DeviceContext* context, bool writing) -{ - Assert(!IsMapped()); - const HRESULT hr = context->Map(m_texture.Get(), 0, writing ? D3D11_MAP_WRITE : D3D11_MAP_READ, 0, &m_map); - if (FAILED(hr)) - { - Log_ErrorPrintf("Map staging texture failed: 0x%08X", hr); - return false; - } - - return true; -} - -void StagingTexture::Unmap(ID3D11DeviceContext* context) -{ - Assert(IsMapped()); - context->Unmap(m_texture.Get(), 0); - m_map = {}; -} - -void StagingTexture::CopyToTexture(ID3D11DeviceContext* context, u32 src_x, u32 src_y, ID3D11Resource* dst_texture, - u32 dst_subresource, u32 dst_x, u32 dst_y, u32 width, u32 height) -{ - DebugAssert((src_x + width) <= m_width && (src_y + height) <= m_height); - - const CD3D11_BOX box(static_cast(src_x), static_cast(src_y), 0, static_cast(src_x + width), - static_cast(src_y + height), 1); - context->CopySubresourceRegion(dst_texture, dst_subresource, dst_x, dst_y, 0, m_texture.Get(), 0, &box); -} - -void StagingTexture::CopyFromTexture(ID3D11DeviceContext* context, ID3D11Resource* src_texture, u32 src_subresource, - u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) -{ - DebugAssert((dst_x + width) <= m_width && (dst_y + height) <= m_height); - - const CD3D11_BOX box(static_cast(src_x), static_cast(src_y), 0, static_cast(src_x + width), - static_cast(src_y + height), 1); - context->CopySubresourceRegion(m_texture.Get(), 0, dst_x, dst_y, 0, src_texture, src_subresource, &box); -} - -bool AutoStagingTexture::EnsureSize(ID3D11DeviceContext* context, u32 width, u32 height, DXGI_FORMAT format, - bool for_uploading) -{ - if (m_texture && m_width >= width && m_height >= height && m_format == format) - return true; - - ComPtr device; - context->GetDevice(device.GetAddressOf()); - - CD3D11_TEXTURE2D_DESC new_desc(format, width, height, 1, 1, 0, - for_uploading ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_STAGING, - for_uploading ? D3D11_CPU_ACCESS_WRITE : D3D11_CPU_ACCESS_READ, 1, 0, 0); - ComPtr new_texture; - HRESULT hr = device->CreateTexture2D(&new_desc, nullptr, new_texture.GetAddressOf()); - if (FAILED(hr)) - { - Log_ErrorPrintf("Create texture failed: 0x%08X", hr); - return false; - } - - m_texture = std::move(new_texture); - m_width = width; - m_height = height; - m_format = format; - return true; -} - -void AutoStagingTexture::CopyFromTexture(ID3D11DeviceContext* context, ID3D11Resource* src_texture, u32 src_subresource, - u32 src_x, u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height) -{ - if (!EnsureSize(context, width, height, m_format, false)) - return; - - StagingTexture::CopyFromTexture(context, src_texture, src_subresource, src_x, src_y, dst_x, dst_y, width, height); -} - -} // namespace D3D11 \ No newline at end of file diff --git a/src/common/d3d11/staging_texture.h b/src/common/d3d11/staging_texture.h deleted file mode 100644 index 2c7025102..000000000 --- a/src/common/d3d11/staging_texture.h +++ /dev/null @@ -1,156 +0,0 @@ -#pragma once -#include "../types.h" -#include "../windows_headers.h" -#include -#include -#include - -namespace D3D11 { -class StagingTexture -{ -public: - template - using ComPtr = Microsoft::WRL::ComPtr; - - StagingTexture(); - ~StagingTexture(); - - ALWAYS_INLINE ID3D11Texture2D* GetD3DTexture() const { return m_texture.Get(); } - - ALWAYS_INLINE u32 GetWidth() const { return m_width; } - ALWAYS_INLINE u32 GetHeight() const { return m_height; } - ALWAYS_INLINE DXGI_FORMAT GetFormat() const { return m_format; } - ALWAYS_INLINE bool IsMapped() const { return m_map.pData != nullptr; } - ALWAYS_INLINE const D3D11_MAPPED_SUBRESOURCE& GetMappedSubresource() const { return m_map; } - - ALWAYS_INLINE operator bool() const { return static_cast(m_texture); } - - bool Create(ID3D11Device* device, u32 width, u32 height, DXGI_FORMAT format, bool for_uploading); - void Destroy(); - - bool Map(ID3D11DeviceContext* context, bool writing); - void Unmap(ID3D11DeviceContext* context); - - void CopyToTexture(ID3D11DeviceContext* context, u32 src_x, u32 src_y, ID3D11Resource* dst_texture, - u32 dst_subresource, u32 dst_x, u32 dst_y, u32 width, u32 height); - void CopyFromTexture(ID3D11DeviceContext* context, ID3D11Resource* src_texture, u32 src_subresource, u32 src_x, - u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height); - - template - T ReadPixel(u32 x, u32 y) - { - T pixel; - std::memcpy(&pixel, static_cast(m_map.pData) + (y * m_map.RowPitch) + x, sizeof(T)); - return pixel; - } - - template - void WritePixel(u32 x, u32 y, T pixel) - { - std::memcpy(static_cast(m_map.pData) + (y * m_map.RowPitch) + x, &pixel, sizeof(T)); - } - - template - void ReadPixels(u32 x, u32 y, u32 width, u32 height, u32 stride, T* data) - { - const u8* src_ptr = static_cast(m_map.pData) + (y * m_map.RowPitch) + (x * sizeof(T)); - u8* dst_ptr = reinterpret_cast(data); - if (m_map.RowPitch != stride || width != m_width || x != 0) - { - for (u32 row = 0; row < height; row++) - { - std::memcpy(dst_ptr, src_ptr, sizeof(T) * width); - src_ptr += m_map.RowPitch; - dst_ptr += stride; - } - } - else - { - std::memcpy(dst_ptr, src_ptr, stride * height); - } - } - - template - bool ReadPixels(ID3D11DeviceContext* context, u32 x, u32 y, u32 width, u32 height, u32 stride, T* data) - { - const bool was_mapped = IsMapped(); - if (!was_mapped && !Map(context, false)) - return false; - - ReadPixels(x, y, width, height, stride, data); - if (!was_mapped) - Unmap(context); - - return true; - } - - template - void WritePixels(u32 x, u32 y, u32 width, u32 height, u32 stride, const T* data) - { - const u8* src_ptr = reinterpret_cast(data); - u8* dst_ptr = static_cast(m_map.pData) + (y * m_map.RowPitch) + (x * sizeof(T)); - if (m_map.RowPitch != stride || width != m_width || x != 0) - { - for (u32 row = 0; row < height; row++) - { - std::memcpy(dst_ptr, src_ptr, sizeof(T) * width); - src_ptr += stride; - dst_ptr += m_map.RowPitch; - } - } - else - { - std::memcpy(dst_ptr, src_ptr, stride * height); - } - } - - template - bool WritePixels(ID3D11DeviceContext* context, u32 x, u32 y, u32 width, u32 height, u32 stride, const T* data) - { - const bool was_mapped = IsMapped(); - if (!was_mapped && !Map(context, true)) - return false; - - WritePixels(context, x, y, width, height, stride, data); - if (!was_mapped) - Unmap(context); - - return true; - } - -protected: - ComPtr m_texture; - u32 m_width; - u32 m_height; - DXGI_FORMAT m_format; - - D3D11_MAPPED_SUBRESOURCE m_map = {}; -}; - -class AutoStagingTexture : public StagingTexture -{ -public: - bool EnsureSize(ID3D11DeviceContext* context, u32 width, u32 height, DXGI_FORMAT format, bool for_uploading); - - void CopyFromTexture(ID3D11DeviceContext* context, ID3D11Resource* src_texture, u32 src_subresource, u32 src_x, - u32 src_y, u32 dst_x, u32 dst_y, u32 width, u32 height); - - template - bool WritePixels(ID3D11DeviceContext* context, u32 x, u32 y, u32 width, u32 height, u32 stride, const T* data) - { - if (!EnsureSize(context, width, height, m_format, true)) - return false; - - const bool was_mapped = IsMapped(); - if (!was_mapped && !Map(context, true)) - return false; - - WritePixels(context, x, y, width, height, stride, data); - - if (!was_mapped) - Unmap(context); - - return true; - } -}; -} // namespace D3D11 \ No newline at end of file diff --git a/src/core/gpu_hw_d3d11.cpp b/src/core/gpu_hw_d3d11.cpp index 4c424e4c6..b1d41d298 100644 --- a/src/core/gpu_hw_d3d11.cpp +++ b/src/core/gpu_hw_d3d11.cpp @@ -270,8 +270,7 @@ bool GPU_HW_D3D11::CreateFramebuffer() GPU_MAX_DISPLAY_HEIGHT * m_resolution_scale, 1, 1, 1, texture_format, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) || !m_vram_encoding_texture.Create(m_device.Get(), VRAM_WIDTH / 2, VRAM_HEIGHT, 1, 1, 1, texture_format, - D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET) || - !m_vram_readback_texture.Create(m_device.Get(), VRAM_WIDTH / 2, VRAM_HEIGHT, texture_format, false)) + D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET)) { return false; } @@ -351,7 +350,6 @@ void GPU_HW_D3D11::DestroyFramebuffer() m_vram_texture.Destroy(); m_vram_encoding_texture.Destroy(); m_display_texture.Destroy(); - m_vram_readback_texture.Destroy(); } bool GPU_HW_D3D11::CreateVertexBuffer() @@ -843,15 +841,15 @@ void GPU_HW_D3D11::UpdateDisplay() if (IsUsingMultisampling()) { UpdateVRAMReadTexture(); - g_host_display->SetDisplayTexture(m_vram_read_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8, + g_host_display->SetDisplayTexture(&m_vram_read_texture, HostDisplayPixelFormat::RGBA8, m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0, m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight()); } else { - g_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8, - m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 0, 0, - m_vram_texture.GetWidth(), m_vram_texture.GetHeight()); + g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(), + m_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(), + m_vram_texture.GetHeight()); } g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT, @@ -891,9 +889,9 @@ void GPU_HW_D3D11::UpdateDisplay() } else { - g_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8, - m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), scaled_vram_offset_x, - scaled_vram_offset_y, scaled_display_width, scaled_display_height); + g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(), + m_vram_texture.GetHeight(), scaled_vram_offset_x, scaled_vram_offset_y, + scaled_display_width, scaled_display_height); } } else @@ -923,7 +921,7 @@ void GPU_HW_D3D11::UpdateDisplay() } else { - g_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8, + g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(), m_display_texture.GetHeight(), 0, 0, scaled_display_width, scaled_display_height); } @@ -955,21 +953,10 @@ void GPU_HW_D3D11::ReadVRAM(u32 x, u32 y, u32 width, u32 height) SetViewportAndScissor(0, 0, encoded_width, encoded_height); DrawUtilityShader(m_vram_read_pixel_shader.Get(), uniforms, sizeof(uniforms)); - // Stage the readback. - m_vram_readback_texture.CopyFromTexture(m_context.Get(), m_vram_encoding_texture.GetD3DTexture(), 0, 0, 0, 0, 0, - encoded_width, encoded_height); - // And copy it into our shadow buffer. - if (m_vram_readback_texture.Map(m_context.Get(), false)) - { - m_vram_readback_texture.ReadPixels( - 0, 0, encoded_width, encoded_height, VRAM_WIDTH * sizeof(u16), - reinterpret_cast(&m_vram_shadow[copy_rect.top * VRAM_WIDTH + copy_rect.left])); - m_vram_readback_texture.Unmap(m_context.Get()); - } - else - { - Log_ErrorPrintf("Failed to map VRAM readback texture"); - } + // Stage the readback and copy it into our shadow buffer. + g_host_display->DownloadTexture( + &m_vram_encoding_texture, HostDisplayPixelFormat::RGBA8, 0, 0, encoded_width, encoded_height, + reinterpret_cast(&m_vram_shadow[copy_rect.top * VRAM_WIDTH + copy_rect.left]), VRAM_WIDTH * sizeof(u16)); RestoreGraphicsAPIState(); } @@ -1204,9 +1191,8 @@ void GPU_HW_D3D11::DownsampleFramebufferAdaptive(D3D11::Texture& source, u32 lef RestoreGraphicsAPIState(); - g_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8, - m_display_texture.GetWidth(), m_display_texture.GetHeight(), left, top, width, - height); + g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(), + m_display_texture.GetHeight(), left, top, width, height); } void GPU_HW_D3D11::DownsampleFramebufferBoxFilter(D3D11::Texture& source, u32 left, u32 top, u32 width, u32 height) @@ -1229,7 +1215,7 @@ void GPU_HW_D3D11::DownsampleFramebufferBoxFilter(D3D11::Texture& source, u32 le RestoreGraphicsAPIState(); - g_host_display->SetDisplayTexture(m_downsample_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8, + g_host_display->SetDisplayTexture(&m_downsample_texture, HostDisplayPixelFormat::RGBA8, m_downsample_texture.GetWidth(), m_downsample_texture.GetHeight(), ds_left, ds_top, ds_width, ds_height); } diff --git a/src/core/gpu_hw_d3d11.h b/src/core/gpu_hw_d3d11.h index 9cf0a77d0..78eec6316 100644 --- a/src/core/gpu_hw_d3d11.h +++ b/src/core/gpu_hw_d3d11.h @@ -1,6 +1,5 @@ #pragma once #include "common/d3d11/shader_cache.h" -#include "common/d3d11/staging_texture.h" #include "common/d3d11/stream_buffer.h" #include "common/d3d11/texture.h" #include "gpu_hw.h" @@ -95,8 +94,6 @@ private: D3D11::StreamBuffer m_texture_stream_buffer; - D3D11::StagingTexture m_vram_readback_texture; - ComPtr m_texture_stream_buffer_srv_r16ui; ComPtr m_cull_none_rasterizer_state; diff --git a/src/frontend-common/d3d11_host_display.cpp b/src/frontend-common/d3d11_host_display.cpp index ca6132b32..69cc41469 100644 --- a/src/frontend-common/d3d11_host_display.cpp +++ b/src/frontend-common/d3d11_host_display.cpp @@ -30,7 +30,7 @@ public: } ~D3D11HostDisplayTexture() override = default; - void* GetHandle() const override { return m_texture.GetD3DSRV(); } + void* GetHandle() const override { return const_cast(&m_texture); } u32 GetWidth() const override { return m_texture.GetWidth(); } u32 GetHeight() const override { return m_texture.GetHeight(); } u32 GetLayers() const override { return 1; } @@ -88,6 +88,7 @@ D3D11HostDisplay::D3D11HostDisplay() = default; D3D11HostDisplay::~D3D11HostDisplay() { + DestroyStagingBuffer(); DestroyResources(); DestroyRenderSurface(); m_context.Reset(); @@ -145,28 +146,53 @@ std::unique_ptr D3D11HostDisplay::CreateTexture(u32 width, u bool D3D11HostDisplay::DownloadTexture(const void* texture_handle, HostDisplayPixelFormat texture_format, u32 x, u32 y, u32 width, u32 height, void* out_data, u32 out_data_stride) { - ID3D11ShaderResourceView* srv = - const_cast(static_cast(texture_handle)); - ComPtr srv_resource; - D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc; - srv->GetResource(srv_resource.GetAddressOf()); - srv->GetDesc(&srv_desc); - - if (!m_readback_staging_texture.EnsureSize(m_context.Get(), width, height, srv_desc.Format, false)) + const D3D11::Texture* tex = static_cast(texture_handle); + if (!CheckStagingBufferSize(width, height, tex->GetFormat())) return false; - m_readback_staging_texture.CopyFromTexture(m_context.Get(), srv_resource.Get(), 0, x, y, 0, 0, width, height); + const CD3D11_BOX box(static_cast(x), static_cast(y), 0, static_cast(x + width), + static_cast(y + height), 1); + m_context->CopySubresourceRegion(m_readback_staging_texture.Get(), 0, 0, 0, 0, tex->GetD3DTexture(), 0, &box); - if (srv_desc.Format == DXGI_FORMAT_B5G6R5_UNORM || srv_desc.Format == DXGI_FORMAT_B5G5R5A1_UNORM) + D3D11_MAPPED_SUBRESOURCE sr; + HRESULT hr = m_context->Map(m_readback_staging_texture.Get(), 0, D3D11_MAP_READ, 0, &sr); + if (FAILED(hr)) { - return m_readback_staging_texture.ReadPixels(m_context.Get(), 0, 0, width, height, out_data_stride, - static_cast(out_data)); + Log_ErrorPrintf("Map() failed with HRESULT %08X", hr); + return false; } - else + + const u32 copy_size = GetDisplayPixelFormatSize(texture_format) * width; + StringUtil::StrideMemCpy(out_data, out_data_stride, sr.pData, sr.RowPitch, copy_size, height); + m_context->Unmap(m_readback_staging_texture.Get(), 0); + return true; +} + +bool D3D11HostDisplay::CheckStagingBufferSize(u32 width, u32 height, DXGI_FORMAT format) +{ + if (m_readback_staging_texture_width >= width && m_readback_staging_texture_width >= height && + m_readback_staging_texture_format == format) + return true; + + DestroyStagingBuffer(); + + CD3D11_TEXTURE2D_DESC desc(format, width, height, 1, 1, 0, D3D11_USAGE_STAGING, D3D11_CPU_ACCESS_READ); + HRESULT hr = m_device->CreateTexture2D(&desc, nullptr, m_readback_staging_texture.ReleaseAndGetAddressOf()); + if (FAILED(hr)) { - return m_readback_staging_texture.ReadPixels(m_context.Get(), 0, 0, width, height, out_data_stride, - static_cast(out_data)); + Log_ErrorPrintf("CreateTexture2D() failed with HRESULT %08X", hr); + return false; } + + return true; +} + +void D3D11HostDisplay::DestroyStagingBuffer() +{ + m_readback_staging_texture.Reset(); + m_readback_staging_texture_width = 0; + m_readback_staging_texture_height = 0; + m_readback_staging_texture_format = DXGI_FORMAT_UNKNOWN; } bool D3D11HostDisplay::SupportsDisplayPixelFormat(HostDisplayPixelFormat format) const @@ -747,11 +773,8 @@ bool D3D11HostDisplay::RenderScreenshot(u32 width, u32 height, std::vector* static constexpr HostDisplayPixelFormat hdformat = HostDisplayPixelFormat::RGBA8; D3D11::Texture render_texture; - if (!render_texture.Create(m_device.Get(), width, height, 1, 1, 1, format, D3D11_BIND_RENDER_TARGET) || - !m_readback_staging_texture.EnsureSize(m_context.Get(), width, height, format, false)) - { + if (!render_texture.Create(m_device.Get(), width, height, 1, 1, 1, format, D3D11_BIND_RENDER_TARGET)) return false; - } static constexpr std::array clear_color = {}; m_context->ClearRenderTargetView(render_texture.GetD3DRTV(), clear_color.data()); @@ -778,18 +801,13 @@ bool D3D11HostDisplay::RenderScreenshot(u32 width, u32 height, std::vector* m_context->OMSetRenderTargets(0, nullptr, nullptr); - m_readback_staging_texture.CopyFromTexture(m_context.Get(), render_texture, 0, 0, 0, 0, 0, width, height); - - if (!m_readback_staging_texture.Map(m_context.Get(), false)) + const u32 stride = GetDisplayPixelFormatSize(hdformat) * width; + out_pixels->resize(width * height); + if (!DownloadTexture(&render_texture, hdformat, 0, 0, width, height, out_pixels->data(), stride)) return false; - const u32 stride = sizeof(u32) * width; - out_pixels->resize(width * height); *out_stride = stride; *out_format = hdformat; - - m_readback_staging_texture.ReadPixels(0, 0, width, height, stride, out_pixels->data()); - m_readback_staging_texture.Unmap(m_context.Get()); return true; } @@ -827,7 +845,7 @@ void D3D11HostDisplay::RenderDisplay(s32 left, s32 top, s32 width, s32 height, v m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_context->VSSetShader(m_display_vertex_shader.Get(), nullptr, 0); m_context->PSSetShader(m_display_pixel_shader.Get(), nullptr, 0); - m_context->PSSetShaderResources(0, 1, reinterpret_cast(&texture_handle)); + m_context->PSSetShaderResources(0, 1, static_cast(texture_handle)->GetD3DSRVArray()); m_context->PSSetSamplers(0, 1, linear_filter ? m_linear_sampler.GetAddressOf() : m_point_sampler.GetAddressOf()); const bool linear = IsUsingLinearFiltering(); @@ -1082,7 +1100,7 @@ void D3D11HostDisplay::ApplyPostProcessingChain(ID3D11RenderTargetView* final_ta RenderDisplay(final_left, final_top, final_width, final_height, texture_handle, texture_width, texture_height, texture_view_x, texture_view_y, texture_view_width, texture_view_height, IsUsingLinearFiltering()); - texture_handle = m_post_processing_input_texture.GetD3DSRV(); + texture_handle = &m_post_processing_input_texture; texture_width = m_post_processing_input_texture.GetWidth(); texture_height = m_post_processing_input_texture.GetHeight(); texture_view_x = final_left; @@ -1107,7 +1125,7 @@ void D3D11HostDisplay::ApplyPostProcessingChain(ID3D11RenderTargetView* final_ta m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); m_context->VSSetShader(pps.vertex_shader.Get(), nullptr, 0); m_context->PSSetShader(pps.pixel_shader.Get(), nullptr, 0); - m_context->PSSetShaderResources(0, 1, reinterpret_cast(&texture_handle)); + m_context->PSSetShaderResources(0, 1, static_cast(texture_handle)->GetD3DSRVArray()); m_context->PSSetSamplers(0, 1, m_point_sampler.GetAddressOf()); const auto map = @@ -1122,7 +1140,7 @@ void D3D11HostDisplay::ApplyPostProcessingChain(ID3D11RenderTargetView* final_ta m_context->Draw(3, 0); if (i != final_stage) - texture_handle = pps.output_texture.GetD3DSRV(); + texture_handle = &pps.output_texture; } ID3D11ShaderResourceView* null_srv = nullptr; diff --git a/src/frontend-common/d3d11_host_display.h b/src/frontend-common/d3d11_host_display.h index 502c00b7a..c2c51b20c 100644 --- a/src/frontend-common/d3d11_host_display.h +++ b/src/frontend-common/d3d11_host_display.h @@ -1,5 +1,4 @@ #pragma once -#include "common/d3d11/staging_texture.h" #include "common/d3d11/stream_buffer.h" #include "common/d3d11/texture.h" #include "common/window_info.h" @@ -74,6 +73,9 @@ protected: static AdapterAndModeList GetAdapterAndModeList(IDXGIFactory* dxgi_factory); + bool CheckStagingBufferSize(u32 width, u32 height, DXGI_FORMAT format); + void DestroyStagingBuffer(); + bool CreateResources() override; void DestroyResources() override; @@ -130,7 +132,10 @@ protected: ComPtr m_linear_sampler; D3D11::StreamBuffer m_display_uniform_buffer; - D3D11::AutoStagingTexture m_readback_staging_texture; + ComPtr m_readback_staging_texture; + DXGI_FORMAT m_readback_staging_texture_format = DXGI_FORMAT_UNKNOWN; + u32 m_readback_staging_texture_width = 0; + u32 m_readback_staging_texture_height = 0; bool m_allow_tearing_supported = false; bool m_using_flip_model_swap_chain = true; diff --git a/src/frontend-common/imgui_impl_dx11.cpp b/src/frontend-common/imgui_impl_dx11.cpp index 8e98ed6a7..85cab85c2 100644 --- a/src/frontend-common/imgui_impl_dx11.cpp +++ b/src/frontend-common/imgui_impl_dx11.cpp @@ -31,6 +31,7 @@ #include "imgui.h" #include "imgui_impl_dx11.h" +#include "common/d3d11/texture.h" // DirectX #include @@ -53,12 +54,12 @@ struct ImGui_ImplDX11_Data ID3D11Buffer* pVertexConstantBuffer; ID3D11PixelShader* pPixelShader; ID3D11SamplerState* pFontSampler; - ID3D11ShaderResourceView* pFontTextureView; ID3D11RasterizerState* pRasterizerState; ID3D11BlendState* pBlendState; ID3D11DepthStencilState* pDepthStencilState; int VertexBufferSize; int IndexBufferSize; + D3D11::Texture FontTexture; ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } }; @@ -229,7 +230,8 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) ctx->RSSetScissorRects(1, &r); // Bind texture, Draw - ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID(); + const D3D11::Texture* tex = static_cast(pcmd->GetTexID()); + ID3D11ShaderResourceView* texture_srv = tex ? tex->GetD3DSRV() : nullptr; ctx->PSSetShaderResources(0, 1, &texture_srv); ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); } @@ -239,7 +241,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) } } -void ImGui_ImplDX11_CreateFontsTexture() +bool ImGui_ImplDX11_CreateFontsTexture() { // Build texture atlas ImGuiIO& io = ImGui::GetIO(); @@ -248,44 +250,12 @@ void ImGui_ImplDX11_CreateFontsTexture() int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - if (bd->pFontTextureView) - bd->pFontTextureView->Release(); - - // Upload texture to graphics system - { - D3D11_TEXTURE2D_DESC desc; - ZeroMemory(&desc, sizeof(desc)); - desc.Width = width; - desc.Height = height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.SampleDesc.Count = 1; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; - - ID3D11Texture2D* pTexture = NULL; - D3D11_SUBRESOURCE_DATA subResource; - subResource.pSysMem = pixels; - subResource.SysMemPitch = desc.Width * 4; - subResource.SysMemSlicePitch = 0; - bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); - IM_ASSERT(pTexture != NULL); - - // Create texture view - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - ZeroMemory(&srvDesc, sizeof(srvDesc)); - srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = desc.MipLevels; - srvDesc.Texture2D.MostDetailedMip = 0; - bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView); - pTexture->Release(); - } + const u32 stride = sizeof(u32) * width; + if (!bd->FontTexture.Create(bd->pd3dDevice, width, height, 1, 1, 1, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE, pixels, stride)) + return false; // Store our identifier - io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView); + io.Fonts->SetTexID((ImTextureID)&bd->FontTexture); // Create texture sampler // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) @@ -303,6 +273,8 @@ void ImGui_ImplDX11_CreateFontsTexture() desc.MaxLOD = 0.f; bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler); } + + return true; } bool ImGui_ImplDX11_CreateDeviceObjects() @@ -454,9 +426,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects() bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState); } - ImGui_ImplDX11_CreateFontsTexture(); - - return true; + return ImGui_ImplDX11_CreateFontsTexture(); } void ImGui_ImplDX11_InvalidateDeviceObjects() @@ -466,7 +436,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects() return; if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = NULL; } - if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = NULL; ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. + if (bd->FontTexture) { bd->FontTexture.Destroy(); ImGui::GetIO().Fonts->SetTexID(NULL); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. if (bd->pIB) { bd->pIB->Release(); bd->pIB = NULL; } if (bd->pVB) { bd->pVB->Release(); bd->pVB = NULL; } if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = NULL; } diff --git a/src/frontend-common/imgui_impl_dx11.h b/src/frontend-common/imgui_impl_dx11.h index ae5c96740..9eb888935 100644 --- a/src/frontend-common/imgui_impl_dx11.h +++ b/src/frontend-common/imgui_impl_dx11.h @@ -14,4 +14,4 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing Dear ImGui state. void ImGui_ImplDX11_InvalidateDeviceObjects(); bool ImGui_ImplDX11_CreateDeviceObjects(); -void ImGui_ImplDX11_CreateFontsTexture(); +bool ImGui_ImplDX11_CreateFontsTexture();