Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
5,496 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
// Copyright 2019 Dolphin Emulator Project | ||
// Licensed under GPLv2+ | ||
// Refer to the license.txt file included. | ||
|
||
#include "VideoBackends/D3D12/BoundingBox.h" | ||
#include "Common/Logging/Log.h" | ||
#include "VideoBackends/D3D12/DXContext.h" | ||
#include "VideoBackends/D3D12/Renderer.h" | ||
#include "VideoBackends/D3D12/StreamBuffer.h" | ||
|
||
// TODO: Use write 32-bit value to buffer in command list where available to skip stream buffer. | ||
namespace DX12 | ||
{ | ||
BoundingBox::BoundingBox() = default; | ||
|
||
BoundingBox::~BoundingBox() | ||
{ | ||
if (m_gpu_descriptor) | ||
g_context->GetDescriptorHeapManager()->Free(m_gpu_descriptor); | ||
} | ||
|
||
std::unique_ptr<BoundingBox> BoundingBox::Create() | ||
{ | ||
auto bbox = std::unique_ptr<BoundingBox>(new BoundingBox()); | ||
if (!bbox->CreateBuffers()) | ||
return nullptr; | ||
|
||
return bbox; | ||
} | ||
|
||
bool BoundingBox::CreateBuffers() | ||
{ | ||
static constexpr D3D12_HEAP_PROPERTIES gpu_heap_properties = { | ||
D3D12_HEAP_TYPE_DEFAULT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 1, 1}; | ||
static constexpr D3D12_HEAP_PROPERTIES cpu_heap_properties = { | ||
D3D12_HEAP_TYPE_READBACK, D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_MEMORY_POOL_UNKNOWN, 1, 1}; | ||
D3D12_RESOURCE_DESC buffer_desc = {D3D12_RESOURCE_DIMENSION_BUFFER, | ||
0, | ||
BUFFER_SIZE, | ||
1, | ||
1, | ||
1, | ||
DXGI_FORMAT_UNKNOWN, | ||
{1, 0}, | ||
D3D12_TEXTURE_LAYOUT_ROW_MAJOR, | ||
D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS}; | ||
|
||
HRESULT hr = g_context->GetDevice()->CreateCommittedResource( | ||
&gpu_heap_properties, D3D12_HEAP_FLAG_NONE, &buffer_desc, | ||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, nullptr, IID_PPV_ARGS(&m_gpu_buffer)); | ||
CHECK(SUCCEEDED(hr), "Creating bounding box GPU buffer failed"); | ||
if (FAILED(hr) || !g_context->GetDescriptorHeapManager()->Allocate(&m_gpu_descriptor)) | ||
return false; | ||
|
||
D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = {DXGI_FORMAT_R32_SINT, D3D12_UAV_DIMENSION_BUFFER}; | ||
uav_desc.Buffer.NumElements = NUM_VALUES; | ||
g_context->GetDevice()->CreateUnorderedAccessView(m_gpu_buffer.Get(), nullptr, &uav_desc, | ||
m_gpu_descriptor.cpu_handle); | ||
g_context->GetDevice()->CreateUnorderedAccessView(m_gpu_buffer.Get(), nullptr, &uav_desc, | ||
m_gpu_descriptor.cpu_handle_shadow); | ||
|
||
buffer_desc.Flags = D3D12_RESOURCE_FLAG_NONE; | ||
hr = g_context->GetDevice()->CreateCommittedResource(&cpu_heap_properties, D3D12_HEAP_FLAG_NONE, | ||
&buffer_desc, D3D12_RESOURCE_STATE_COPY_DEST, | ||
nullptr, IID_PPV_ARGS(&m_readback_buffer)); | ||
CHECK(SUCCEEDED(hr), "Creating bounding box CPU buffer failed"); | ||
if (FAILED(hr)) | ||
return false; | ||
|
||
m_stream_buffer = StreamBuffer::Create(STREAM_BUFFER_SIZE); | ||
if (!m_stream_buffer) | ||
return false; | ||
|
||
// Both the CPU and GPU buffer's contents is unknown, so force a flush the first time. | ||
m_values.fill(0); | ||
m_dirty.fill(true); | ||
m_valid = true; | ||
return true; | ||
} | ||
|
||
void BoundingBox::Readback() | ||
{ | ||
// Copy from GPU->CPU buffer, and wait for the GPU to finish the copy. | ||
D3D::ResourceBarrier(g_context->GetCommandList(), m_gpu_buffer.Get(), | ||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE); | ||
g_context->GetCommandList()->CopyBufferRegion(m_readback_buffer.Get(), 0, m_gpu_buffer.Get(), 0, | ||
BUFFER_SIZE); | ||
D3D::ResourceBarrier(g_context->GetCommandList(), m_gpu_buffer.Get(), | ||
D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); | ||
Renderer::GetInstance()->ExecuteCommandList(true); | ||
|
||
// Read back to cached values. | ||
static constexpr D3D12_RANGE read_range = {0, BUFFER_SIZE}; | ||
void* mapped_pointer; | ||
HRESULT hr = m_readback_buffer->Map(0, &read_range, &mapped_pointer); | ||
CHECK(SUCCEEDED(hr), "Map bounding box CPU buffer"); | ||
if (FAILED(hr)) | ||
return; | ||
|
||
static constexpr D3D12_RANGE write_range = {0, 0}; | ||
std::array<s32, NUM_VALUES> new_values; | ||
std::memcpy(new_values.data(), mapped_pointer, BUFFER_SIZE); | ||
m_readback_buffer->Unmap(0, &write_range); | ||
|
||
// Preserve dirty values, that way we don't need to sync. | ||
for (u32 i = 0; i < NUM_VALUES; i++) | ||
{ | ||
if (!m_dirty[i]) | ||
m_values[i] = new_values[i]; | ||
} | ||
m_valid = true; | ||
} | ||
|
||
s32 BoundingBox::Get(size_t index) | ||
{ | ||
if (!m_valid) | ||
Readback(); | ||
|
||
return m_values[index]; | ||
} | ||
|
||
void BoundingBox::Set(size_t index, s32 value) | ||
{ | ||
m_values[index] = value; | ||
m_dirty[index] = true; | ||
} | ||
|
||
void BoundingBox::Invalidate() | ||
{ | ||
m_dirty.fill(false); | ||
m_valid = false; | ||
} | ||
|
||
void BoundingBox::Flush() | ||
{ | ||
// Reserve space for all values, even we only copy some. | ||
if (!m_stream_buffer->ReserveMemory(BUFFER_SIZE, BUFFER_SIZE)) | ||
{ | ||
WARN_LOG(VIDEO, "Executing command list while waiting for space in the bbox stream buffer"); | ||
if (!m_stream_buffer->ReserveMemory(BUFFER_SIZE, BUFFER_SIZE)) | ||
{ | ||
PanicAlert("Failed to reserve bbox stream buffer memory"); | ||
return; | ||
} | ||
} | ||
const u32 src_buffer_offset = m_stream_buffer->GetCurrentOffset(); | ||
std::memcpy(m_stream_buffer->GetCurrentHostPointer(), m_values.data(), BUFFER_SIZE); | ||
m_stream_buffer->CommitMemory(BUFFER_SIZE); | ||
|
||
D3D::ResourceBarrier(g_context->GetCommandList(), m_gpu_buffer.Get(), | ||
D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST); | ||
|
||
// Try to batch updates together, but don't overwrite non-dirty values. | ||
// It's likely all of them will be written anyway. | ||
for (u32 start = 0; start < NUM_VALUES;) | ||
{ | ||
if (!m_dirty[start]) | ||
{ | ||
start++; | ||
continue; | ||
} | ||
|
||
u32 end = start + 1; | ||
for (; end < NUM_VALUES; end++) | ||
{ | ||
if (!m_dirty[end]) | ||
break; | ||
} | ||
|
||
const u32 count = end - start; | ||
g_context->GetCommandList()->CopyBufferRegion( | ||
m_gpu_buffer.Get(), 0, m_stream_buffer->GetBuffer(), src_buffer_offset, BUFFER_SIZE); | ||
|
||
std::fill_n(&m_dirty[start], count, false); | ||
start = end; | ||
} | ||
|
||
D3D::ResourceBarrier(g_context->GetCommandList(), m_gpu_buffer.Get(), | ||
D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS); | ||
} | ||
}; // namespace DX12 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright 2019 Dolphin Emulator Project | ||
// Licensed under GPLv2+ | ||
// Refer to the license.txt file included. | ||
|
||
#pragma once | ||
#include <memory> | ||
#include "VideoBackends/D3D12/D3DBase.h" | ||
#include "VideoBackends/D3D12/DescriptorHeapManager.h" | ||
|
||
namespace DX12 | ||
{ | ||
class StreamBuffer; | ||
class BoundingBox | ||
{ | ||
public: | ||
~BoundingBox(); | ||
|
||
static std::unique_ptr<BoundingBox> Create(); | ||
|
||
const DescriptorHandle& GetGPUDescriptor() const { return m_gpu_descriptor; } | ||
|
||
s32 Get(size_t index); | ||
void Set(size_t index, s32 value); | ||
|
||
void Invalidate(); | ||
void Flush(); | ||
|
||
private: | ||
static const u32 NUM_VALUES = 4; | ||
static const u32 BUFFER_SIZE = sizeof(u32) * NUM_VALUES; | ||
static const u32 MAX_UPDATES_PER_FRAME = 128; | ||
static const u32 STREAM_BUFFER_SIZE = BUFFER_SIZE * MAX_UPDATES_PER_FRAME; | ||
|
||
BoundingBox(); | ||
|
||
bool CreateBuffers(); | ||
void Readback(); | ||
|
||
// Three buffers: One on the GPU for read/write, one on the CPU for reading back, and a third for | ||
// streaming changes. We use a stream buffer so we don't need to block when two bbox updates are | ||
// within a single command buffer. | ||
ComPtr<ID3D12Resource> m_gpu_buffer; | ||
ComPtr<ID3D12Resource> m_readback_buffer; | ||
std::unique_ptr<StreamBuffer> m_stream_buffer; | ||
DescriptorHandle m_gpu_descriptor; | ||
std::array<s32, NUM_VALUES> m_values = {}; | ||
std::array<bool, NUM_VALUES> m_dirty = {}; | ||
bool m_valid = true; | ||
}; | ||
}; // namespace DX12 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<ItemGroup Label="ProjectConfigurations"> | ||
<ProjectConfiguration Include="Debug|x64"> | ||
<Configuration>Debug</Configuration> | ||
<Platform>x64</Platform> | ||
</ProjectConfiguration> | ||
<ProjectConfiguration Include="Release|x64"> | ||
<Configuration>Release</Configuration> | ||
<Platform>x64</Platform> | ||
</ProjectConfiguration> | ||
</ItemGroup> | ||
<PropertyGroup Label="Globals"> | ||
<ProjectGuid>{570215B7-E32F-4438-95AE-C8D955F9FCA3}</ProjectGuid> | ||
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion> | ||
</PropertyGroup> | ||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> | ||
<PropertyGroup Label="Configuration"> | ||
<ConfigurationType>StaticLibrary</ConfigurationType> | ||
<PlatformToolset>v141</PlatformToolset> | ||
<CharacterSet>Unicode</CharacterSet> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration"> | ||
<UseDebugLibraries>true</UseDebugLibraries> | ||
</PropertyGroup> | ||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration"> | ||
<UseDebugLibraries>false</UseDebugLibraries> | ||
</PropertyGroup> | ||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> | ||
<ImportGroup Label="ExtensionSettings"> | ||
</ImportGroup> | ||
<ImportGroup Label="PropertySheets"> | ||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||
<Import Project="..\..\..\VSProps\Base.props" /> | ||
<Import Project="..\..\..\VSProps\PCHUse.props" /> | ||
</ImportGroup> | ||
<PropertyGroup Label="UserMacros" /> | ||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> | ||
<ClCompile> | ||
<PrecompiledHeader>NotUsing</PrecompiledHeader> | ||
<ForcedIncludeFiles /> | ||
</ClCompile> | ||
</ItemDefinitionGroup> | ||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||
<ClCompile> | ||
<PrecompiledHeader>NotUsing</PrecompiledHeader> | ||
<ForcedIncludeFiles /> | ||
</ClCompile> | ||
</ItemDefinitionGroup> | ||
<ItemGroup> | ||
<ClCompile Include="BoundingBox.cpp" /> | ||
<ClCompile Include="D3DBase.cpp" /> | ||
<ClCompile Include="DXContext.cpp" /> | ||
<ClCompile Include="DescriptorHeapManager.cpp" /> | ||
<ClCompile Include="DXPipeline.cpp" /> | ||
<ClCompile Include="DXShader.cpp" /> | ||
<ClCompile Include="StreamBuffer.cpp" /> | ||
<ClCompile Include="DXTexture.cpp" /> | ||
<ClCompile Include="VideoBackend.cpp" /> | ||
<ClCompile Include="PerfQuery.cpp" /> | ||
<ClCompile Include="Renderer.cpp" /> | ||
<ClCompile Include="DXVertexFormat.cpp" /> | ||
<ClCompile Include="SwapChain.cpp" /> | ||
<ClCompile Include="VertexManager.cpp" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ClInclude Include="BoundingBox.h" /> | ||
<ClInclude Include="D3DBase.h" /> | ||
<ClInclude Include="DXContext.h" /> | ||
<ClInclude Include="DescriptorHeapManager.h" /> | ||
<ClInclude Include="DXPipeline.h" /> | ||
<ClInclude Include="DXShader.h" /> | ||
<ClInclude Include="StreamBuffer.h" /> | ||
<ClInclude Include="DXTexture.h" /> | ||
<ClInclude Include="PerfQuery.h" /> | ||
<ClInclude Include="Renderer.h" /> | ||
<ClInclude Include="DXVertexFormat.h" /> | ||
<ClInclude Include="SwapChain.h" /> | ||
<ClInclude Include="VertexManager.h" /> | ||
<ClInclude Include="VideoBackend.h" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ProjectReference Include="$(CoreDir)VideoCommon\VideoCommon.vcxproj"> | ||
<Project>{3de9ee35-3e91-4f27-a014-2866ad8c3fe3}</Project> | ||
</ProjectReference> | ||
</ItemGroup> | ||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | ||
<ImportGroup Label="ExtensionTargets"> | ||
</ImportGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | ||
<ItemGroup> | ||
<ClCompile Include="VideoBackend.cpp" /> | ||
<ClCompile Include="D3DBase.cpp" /> | ||
<ClCompile Include="DescriptorHeapManager.cpp" /> | ||
<ClCompile Include="DXContext.cpp" /> | ||
<ClCompile Include="DXPipeline.cpp" /> | ||
<ClCompile Include="DXShader.cpp" /> | ||
<ClCompile Include="DXTexture.cpp" /> | ||
<ClCompile Include="DXVertexFormat.cpp" /> | ||
<ClCompile Include="StreamBuffer.cpp" /> | ||
<ClCompile Include="SwapChain.cpp" /> | ||
<ClCompile Include="PerfQuery.cpp" /> | ||
<ClCompile Include="Renderer.cpp" /> | ||
<ClCompile Include="VertexManager.cpp" /> | ||
<ClCompile Include="BoundingBox.cpp" /> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<ClInclude Include="VideoBackend.h" /> | ||
<ClInclude Include="SwapChain.h" /> | ||
<ClInclude Include="D3DBase.h" /> | ||
<ClInclude Include="DescriptorHeapManager.h" /> | ||
<ClInclude Include="DXContext.h" /> | ||
<ClInclude Include="DXPipeline.h" /> | ||
<ClInclude Include="DXShader.h" /> | ||
<ClInclude Include="DXTexture.h" /> | ||
<ClInclude Include="DXVertexFormat.h" /> | ||
<ClInclude Include="StreamBuffer.h" /> | ||
<ClInclude Include="VertexManager.h" /> | ||
<ClInclude Include="BoundingBox.h" /> | ||
<ClInclude Include="PerfQuery.h" /> | ||
<ClInclude Include="Renderer.h" /> | ||
</ItemGroup> | ||
</Project> |
Oops, something went wrong.