GS/DX12: Fix creating display textures mid-frame crashing

This commit is contained in:
Connor McLaughlin 2022-06-12 00:41:21 +10:00 committed by refractionpcsx2
parent d54715a9c3
commit ddbc143178
4 changed files with 25 additions and 22 deletions

View File

@ -284,7 +284,7 @@ void Texture::TransitionSubresourceToState(ID3D12GraphicsCommandList* cmdlist, u
cmdlist->ResourceBarrier(1, &barrier); cmdlist->ResourceBarrier(1, &barrier);
} }
bool Texture::BeginStreamUpdate(u32 level, u32 x, u32 y, u32 width, u32 height, void** out_data, u32* out_data_pitch) ID3D12GraphicsCommandList* Texture::BeginStreamUpdate(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, void** out_data, u32* out_data_pitch)
{ {
const u32 copy_pitch = Common::AlignUpPow2(width * GetTexelSize(m_format), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); const u32 copy_pitch = Common::AlignUpPow2(width * GetTexelSize(m_format), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
const u32 upload_size = copy_pitch * height; const u32 upload_size = copy_pitch * height;
@ -297,16 +297,19 @@ bool Texture::BeginStreamUpdate(u32 level, u32 x, u32 y, u32 width, u32 height,
if (!g_d3d12_context->GetTextureStreamBuffer().ReserveMemory(upload_size, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT)) if (!g_d3d12_context->GetTextureStreamBuffer().ReserveMemory(upload_size, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT))
{ {
Console.Error("Failed to reserve %u bytes for %ux%u upload", upload_size, width, height); Console.Error("Failed to reserve %u bytes for %ux%u upload", upload_size, width, height);
return false; return nullptr;
} }
// cmdlist change
return g_d3d12_context->GetInitCommandList();
} }
*out_data = g_d3d12_context->GetTextureStreamBuffer().GetCurrentHostPointer(); *out_data = g_d3d12_context->GetTextureStreamBuffer().GetCurrentHostPointer();
*out_data_pitch = copy_pitch; *out_data_pitch = copy_pitch;
return true; return cmdlist;
} }
void Texture::EndStreamUpdate(u32 level, u32 x, u32 y, u32 width, u32 height) void Texture::EndStreamUpdate(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height)
{ {
const u32 copy_pitch = Common::AlignUpPow2(width * GetTexelSize(m_format), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); const u32 copy_pitch = Common::AlignUpPow2(width * GetTexelSize(m_format), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
const u32 upload_size = copy_pitch * height; const u32 upload_size = copy_pitch * height;
@ -315,10 +318,10 @@ void Texture::EndStreamUpdate(u32 level, u32 x, u32 y, u32 width, u32 height)
const u32 sb_offset = sb.GetCurrentOffset(); const u32 sb_offset = sb.GetCurrentOffset();
sb.CommitMemory(upload_size); sb.CommitMemory(upload_size);
CopyFromBuffer(level, x, y, width, height, copy_pitch, sb.GetBuffer(), sb_offset); CopyFromBuffer(cmdlist, level, x, y, width, height, copy_pitch, sb.GetBuffer(), sb_offset);
} }
void Texture::CopyFromBuffer(u32 level, u32 x, u32 y, u32 width, u32 height, u32 pitch, ID3D12Resource* buffer, u32 buffer_offset) void Texture::CopyFromBuffer(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, u32 pitch, ID3D12Resource* buffer, u32 buffer_offset)
{ {
D3D12_TEXTURE_COPY_LOCATION src; D3D12_TEXTURE_COPY_LOCATION src;
src.pResource = buffer; src.pResource = buffer;
@ -337,7 +340,6 @@ void Texture::CopyFromBuffer(u32 level, u32 x, u32 y, u32 width, u32 height, u32
const D3D12_BOX src_box{0u, 0u, 0u, width, height, 1u}; const D3D12_BOX src_box{0u, 0u, 0u, width, height, 1u};
const D3D12_RESOURCE_STATES old_state = m_state; const D3D12_RESOURCE_STATES old_state = m_state;
ID3D12GraphicsCommandList* cmdlist = g_d3d12_context->GetCommandList();
TransitionToState(cmdlist, D3D12_RESOURCE_STATE_COPY_DEST); TransitionToState(cmdlist, D3D12_RESOURCE_STATE_COPY_DEST);
cmdlist->CopyTextureRegion(&dst, x, y, 0, &src, &src_box); cmdlist->CopyTextureRegion(&dst, x, y, 0, &src, &src_box);
TransitionToState(cmdlist, old_state); TransitionToState(cmdlist, old_state);
@ -381,7 +383,7 @@ static ID3D12Resource* CreateStagingBuffer(u32 height, const void* data, u32 pit
return resource.get(); return resource.get();
} }
bool Texture::LoadData(u32 level, u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch) bool Texture::LoadData(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch)
{ {
const u32 texel_size = GetTexelSize(m_format); const u32 texel_size = GetTexelSize(m_format);
const u32 upload_pitch = Common::AlignUpPow2(width * texel_size, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT); const u32 upload_pitch = Common::AlignUpPow2(width * texel_size, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
@ -392,17 +394,17 @@ bool Texture::LoadData(u32 level, u32 x, u32 y, u32 width, u32 height, const voi
if (!staging_buffer) if (!staging_buffer)
return false; return false;
CopyFromBuffer(level, x, y, width, height, upload_pitch, staging_buffer, 0); CopyFromBuffer(cmdlist, level, x, y, width, height, upload_pitch, staging_buffer, 0);
return true; return true;
} }
void* write_ptr; void* write_ptr;
u32 write_pitch; u32 write_pitch;
if (!BeginStreamUpdate(level, x, y, width, height, &write_ptr, &write_pitch)) if (!(cmdlist = BeginStreamUpdate(cmdlist, level, x, y, width, height, &write_ptr, &write_pitch)))
return false; return false;
StringUtil::StrideMemCpy(write_ptr, write_pitch, data, pitch, std::min(pitch, upload_pitch), height); StringUtil::StrideMemCpy(write_ptr, write_pitch, data, pitch, std::min(pitch, upload_pitch), height);
EndStreamUpdate(level, x, y, width, height); EndStreamUpdate(cmdlist, level, x, y, width, height);
return true; return true;
} }

View File

@ -74,10 +74,10 @@ namespace D3D12
Texture& operator=(Texture&& texture); Texture& operator=(Texture&& texture);
// NOTE: Does not handle compressed formats. // NOTE: Does not handle compressed formats.
bool BeginStreamUpdate(u32 level, u32 x, u32 y, u32 width, u32 height, void** out_data, u32* out_data_pitch); ID3D12GraphicsCommandList* BeginStreamUpdate(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, void** out_data, u32* out_data_pitch);
void EndStreamUpdate(u32 level, u32 x, u32 y, u32 width, u32 height); void EndStreamUpdate(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height);
bool LoadData(u32 level, u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch); bool LoadData(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, const void* data, u32 pitch);
void CopyFromBuffer(u32 level, u32 x, u32 y, u32 width, u32 height, u32 pitch, ID3D12Resource* buffer, u32 buffer_offset); void CopyFromBuffer(ID3D12GraphicsCommandList* cmdlist, u32 level, u32 x, u32 y, u32 width, u32 height, u32 pitch, ID3D12Resource* buffer, u32 buffer_offset);
private: private:
static bool CreateSRVDescriptor(ID3D12Resource* resource, u32 levels, DXGI_FORMAT format, DescriptorHandle* dh); static bool CreateSRVDescriptor(ID3D12Resource* resource, u32 levels, DXGI_FORMAT format, DescriptorHandle* dh);

View File

@ -85,7 +85,8 @@ bool D3D12HostDisplay::HasRenderSurface() const
return static_cast<bool>(m_swap_chain); return static_cast<bool>(m_swap_chain);
} }
std::unique_ptr<HostDisplayTexture> D3D12HostDisplay::CreateTexture(u32 width, u32 height, const void* data, u32 data_stride, bool dynamic /* = false */) std::unique_ptr<HostDisplayTexture> D3D12HostDisplay::CreateTexture(
u32 width, u32 height, const void* data, u32 data_stride, bool dynamic /* = false */)
{ {
D3D12::Texture tex; D3D12::Texture tex;
if (!tex.Create(width, height, 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, if (!tex.Create(width, height, 1, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN,
@ -94,17 +95,17 @@ std::unique_ptr<HostDisplayTexture> D3D12HostDisplay::CreateTexture(u32 width, u
return {}; return {};
} }
if (data && !tex.LoadData(0, 0, 0, width, height, data, data_stride)) if (data && !tex.LoadData(g_d3d12_context->GetInitCommandList(), 0, 0, 0, width, height, data, data_stride))
return {}; return {};
return std::make_unique<D3D12HostDisplayTexture>(std::move(tex)); return std::make_unique<D3D12HostDisplayTexture>(std::move(tex));
} }
void D3D12HostDisplay::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, void D3D12HostDisplay::UpdateTexture(
const void* texture_data, u32 texture_data_stride) HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* texture_data, u32 texture_data_stride)
{ {
static_cast<D3D12HostDisplayTexture*>(texture)->GetTexture().LoadData(0, x, y, width, height, texture_data, static_cast<D3D12HostDisplayTexture*>(texture)->GetTexture().LoadData(
texture_data_stride); g_d3d12_context->GetCommandList(), 0, x, y, width, height, texture_data, texture_data_stride);
} }
bool D3D12HostDisplay::GetHostRefreshRate(float* refresh_rate) bool D3D12HostDisplay::GetHostRefreshRate(float* refresh_rate)

View File

@ -271,7 +271,7 @@ bool ImGui_ImplDX12_CreateFontsTexture()
} }
} }
if (!bd->FontTexture.LoadData(0, 0, 0, width, height, pixels, width * sizeof(u32))) if (!bd->FontTexture.LoadData(g_d3d12_context->GetInitCommandList(), 0, 0, 0, width, height, pixels, width * sizeof(u32)))
return false; return false;
io.Fonts->SetTexID((ImTextureID)&bd->FontTexture); io.Fonts->SetTexID((ImTextureID)&bd->FontTexture);