Merge pull request #3713 from stenzek/d3d12-more-fixes

D3D12: Bug fixes, implement bbox, realxfb, perfquery
This commit is contained in:
Matthew Parlane
2016-05-10 21:34:27 +12:00
33 changed files with 1098 additions and 672 deletions
+122 -14
View File
@@ -2,43 +2,151 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <memory>
#include "Common/CommonTypes.h"
#include "Common/MsgHandler.h"
#include "VideoBackends/D3D12/BoundingBox.h"
#include "VideoBackends/D3D12/D3DBase.h"
#include "VideoBackends/D3D12/D3DCommandListManager.h"
#include "VideoBackends/D3D12/D3DDescriptorHeapManager.h"
#include "VideoBackends/D3D12/D3DStreamBuffer.h"
#include "VideoBackends/D3D12/D3DUtil.h"
#include "VideoBackends/D3D12/FramebufferManager.h"
#include "VideoBackends/D3D12/Render.h"
#include "VideoCommon/VideoConfig.h"
// D3D12TODO: Support bounding box behavior.
namespace DX12
{
ID3D11UnorderedAccessView* BBox::GetUAV()
{
// D3D12TODO: Implement this;
return nullptr;
}
constexpr size_t BBOX_BUFFER_SIZE = sizeof(int) * 4;
constexpr size_t BBOX_STREAM_BUFFER_SIZE = BBOX_BUFFER_SIZE * 128;
static ID3D12Resource* s_bbox_buffer;
static ID3D12Resource* s_bbox_staging_buffer;
static void* s_bbox_staging_buffer_map;
static std::unique_ptr<D3DStreamBuffer> s_bbox_stream_buffer;
static D3D12_GPU_DESCRIPTOR_HANDLE s_bbox_descriptor_handle;
void BBox::Init()
{
if (g_ActiveConfig.backend_info.bSupportsBBox)
{
// D3D12TODO: Implement this;
}
CD3DX12_RESOURCE_DESC buffer_desc(CD3DX12_RESOURCE_DESC::Buffer(BBOX_BUFFER_SIZE, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, 0));
CD3DX12_RESOURCE_DESC staging_buffer_desc(CD3DX12_RESOURCE_DESC::Buffer(BBOX_BUFFER_SIZE, D3D12_RESOURCE_FLAG_NONE, 0));
CheckHR(D3D::device12->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&buffer_desc,
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
nullptr,
IID_PPV_ARGS(&s_bbox_buffer)));
CheckHR(D3D::device12->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK),
D3D12_HEAP_FLAG_NONE,
&staging_buffer_desc,
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&s_bbox_staging_buffer)));
s_bbox_stream_buffer = std::make_unique<D3DStreamBuffer>(BBOX_STREAM_BUFFER_SIZE, BBOX_STREAM_BUFFER_SIZE, nullptr);
// D3D12 root signature UAV must be raw or structured buffers, not typed. Since we used a typed buffer,
// we have to use a descriptor table. Luckily, we only have to allocate this once, and it never changes.
D3D12_CPU_DESCRIPTOR_HANDLE cpu_descriptor_handle;
if (!D3D::gpu_descriptor_heap_mgr->Allocate(&cpu_descriptor_handle, &s_bbox_descriptor_handle, nullptr, false))
PanicAlert("Failed to create bounding box UAV descriptor");
D3D12_UNORDERED_ACCESS_VIEW_DESC view_desc = { DXGI_FORMAT_R32_SINT, D3D12_UAV_DIMENSION_BUFFER };
view_desc.Buffer.FirstElement = 0;
view_desc.Buffer.NumElements = 4;
view_desc.Buffer.StructureByteStride = 0;
view_desc.Buffer.CounterOffsetInBytes = 0;
view_desc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
D3D::device12->CreateUnorderedAccessView(s_bbox_buffer, nullptr, &view_desc, cpu_descriptor_handle);
Bind();
}
void BBox::Bind()
{
D3D::current_command_list->SetGraphicsRootDescriptorTable(DESCRIPTOR_TABLE_PS_UAV, s_bbox_descriptor_handle);
}
void BBox::Invalidate()
{
if (!s_bbox_staging_buffer_map)
return;
D3D12_RANGE write_range = {};
s_bbox_staging_buffer->Unmap(0, &write_range);
s_bbox_staging_buffer_map = nullptr;
}
void BBox::Shutdown()
{
// D3D12TODO: Implement this;
Invalidate();
if (s_bbox_buffer)
{
D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(s_bbox_buffer);
s_bbox_buffer = nullptr;
}
if (s_bbox_staging_buffer)
{
D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(s_bbox_staging_buffer);
s_bbox_staging_buffer = nullptr;
}
s_bbox_stream_buffer.reset();
}
void BBox::Set(int index, int value)
{
// D3D12TODO: Implement this;
// If the buffer is currently mapped, compare the value, and update the staging buffer.
if (s_bbox_staging_buffer_map)
{
int current_value;
memcpy(&current_value, reinterpret_cast<u8*>(s_bbox_staging_buffer_map) + (index * sizeof(int)), sizeof(int));
if (current_value == value)
{
// Value hasn't changed. So skip updating completely.
return;
}
memcpy(reinterpret_cast<u8*>(s_bbox_staging_buffer_map) + (index * sizeof(int)), &value, sizeof(int));
}
s_bbox_stream_buffer->AllocateSpaceInBuffer(sizeof(int), sizeof(int));
// Allocate temporary bytes in upload buffer, then copy to real buffer.
memcpy(s_bbox_stream_buffer->GetCPUAddressOfCurrentAllocation(), &value, sizeof(int));
D3D::ResourceBarrier(D3D::current_command_list, s_bbox_buffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_DEST, 0);
D3D::current_command_list->CopyBufferRegion(s_bbox_buffer, index * sizeof(int), s_bbox_stream_buffer->GetBuffer(), s_bbox_stream_buffer->GetOffsetOfCurrentAllocation(), sizeof(int));
D3D::ResourceBarrier(D3D::current_command_list, s_bbox_buffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 0);
}
int BBox::Get(int index)
{
// D3D12TODO: Implement this;
return 0;
if (!s_bbox_staging_buffer_map)
{
D3D::command_list_mgr->CPUAccessNotify();
// Copy from real buffer to staging buffer, then block until we have the results.
D3D::ResourceBarrier(D3D::current_command_list, s_bbox_buffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE, 0);
D3D::current_command_list->CopyBufferRegion(s_bbox_staging_buffer, 0, s_bbox_buffer, 0, BBOX_BUFFER_SIZE);
D3D::ResourceBarrier(D3D::current_command_list, s_bbox_buffer, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, 0);
D3D::command_list_mgr->ExecuteQueuedWork(true);
D3D12_RANGE read_range = { 0, BBOX_BUFFER_SIZE };
CheckHR(s_bbox_staging_buffer->Map(0, &read_range, &s_bbox_staging_buffer_map));
}
int value;
memcpy(&value, &reinterpret_cast<int*>(s_bbox_staging_buffer_map)[index], sizeof(int));
return value;
}
};
@@ -11,8 +11,9 @@ namespace DX12
class BBox
{
public:
static ID3D11UnorderedAccessView* GetUAV();
static void Init();
static void Bind();
static void Invalidate();
static void Shutdown();
static void Set(int index, int value);
@@ -67,7 +67,6 @@
<ClCompile Include="ShaderCache.cpp" />
<ClCompile Include="ShaderConstantsManager.cpp" />
<ClCompile Include="StaticShaderCache.cpp" />
<ClCompile Include="Television.cpp" />
<ClCompile Include="TextureCache.cpp" />
<ClCompile Include="VertexManager.cpp" />
<ClCompile Include="XFBEncoder.cpp" />
@@ -91,7 +90,6 @@
<ClInclude Include="ShaderCache.h" />
<ClInclude Include="ShaderConstantsManager.h" />
<ClInclude Include="StaticShaderCache.h" />
<ClInclude Include="Television.h" />
<ClInclude Include="TextureCache.h" />
<ClInclude Include="TextureEncoder.h" />
<ClInclude Include="VertexManager.h" />
@@ -39,9 +39,6 @@
<ClCompile Include="Render.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="Television.cpp">
<Filter>Render</Filter>
</ClCompile>
<ClCompile Include="TextureCache.cpp">
<Filter>Render</Filter>
</ClCompile>
@@ -105,9 +102,6 @@
<ClInclude Include="Render.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="Television.h">
<Filter>Render</Filter>
</ClInclude>
<ClInclude Include="TextureCache.h">
<Filter>Render</Filter>
</ClInclude>
+115 -185
View File
@@ -14,6 +14,7 @@
#include "VideoBackends/D3D12/D3DDescriptorHeapManager.h"
#include "VideoBackends/D3D12/D3DState.h"
#include "VideoBackends/D3D12/D3DTexture.h"
#include "VideoCommon/OnScreenDisplay.h"
#include "VideoCommon/VideoConfig.h"
static const unsigned int SWAP_CHAIN_BUFFER_COUNT = 4;
@@ -72,18 +73,12 @@ static LARGE_INTEGER s_qpc_frequency;
static ID3D12DebugDevice* s_debug_device12 = nullptr;
static D3D_FEATURE_LEVEL s_feat_level;
static D3DTexture2D* s_backbuf[SWAP_CHAIN_BUFFER_COUNT];
static unsigned int s_current_back_buf = 0;
static unsigned int s_xres = 0;
static unsigned int s_yres = 0;
static bool s_frame_in_progress = false;
static std::vector<DXGI_SAMPLE_DESC> s_aa_modes; // supported AA modes of the current adapter
static const D3D_FEATURE_LEVEL s_supported_feature_levels[] = {
D3D_FEATURE_LEVEL_11_0
};
HRESULT LoadDXGI()
{
if (s_dxgi_dll_ref++ > 0)
@@ -233,108 +228,29 @@ void UnloadD3DCompiler()
d3d_reflect = nullptr;
}
bool AlertUserIfSelectedAdapterDoesNotSupportD3D12()
{
HRESULT hr = LoadDXGI();
if (SUCCEEDED(hr))
{
hr = LoadD3D();
}
if (FAILED(hr))
{
// LoadDXGI / LoadD3D display a specific error message,
// no need to do that here.
return false;
}
IDXGIFactory* factory = nullptr;
IDXGIAdapter* adapter = nullptr;
ID3D12Device* device = nullptr;
if (SUCCEEDED(hr))
{
hr = create_dxgi_factory(__uuidof(IDXGIFactory), (void**)&factory);
}
if (SUCCEEDED(hr))
{
hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
}
if (SUCCEEDED(hr))
{
hr = d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device));
SAFE_RELEASE(device);
SAFE_RELEASE(adapter);
SAFE_RELEASE(factory);
if (FAILED(hr))
{
UnloadD3D();
UnloadDXGI();
MessageBoxA(nullptr, "Failed to create a D3D12 device on the selected adapter.\n\nPlease make sure it supports Direct3D 12, and that your graphics drivers are up-to-date.", "Critical error", MB_OK | MB_ICONERROR);
return false;
}
// If succeeded, leave DXGI and D3D libraries loaded since we'll use them in Create().
return true;
}
// DXGI failed to create factory/enumerate adapter. This should be very uncommon.
MessageBoxA(nullptr, "Failed to create enumerate selected adapter. Please select a different graphics adapter.", "Critical error", MB_OK | MB_ICONERROR);
SAFE_RELEASE(adapter);
SAFE_RELEASE(factory);
UnloadD3D();
UnloadDXGI();
return false;
}
std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter)
std::vector<DXGI_SAMPLE_DESC> EnumAAModes(ID3D12Device* device)
{
std::vector<DXGI_SAMPLE_DESC> aa_modes;
bool d3d12_supported = AlertUserIfSelectedAdapterDoesNotSupportD3D12();
if (!d3d12_supported)
return aa_modes;
ID3D12Device* device12 = nullptr;
d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device12));
if (device12)
for (int samples = 0; samples < D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples)
{
for (int samples = 0; samples < D3D12_MAX_MULTISAMPLE_SAMPLE_COUNT; ++samples)
{
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS multisample_quality_levels = {};
multisample_quality_levels.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
multisample_quality_levels.SampleCount = samples;
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS multisample_quality_levels = {};
multisample_quality_levels.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
multisample_quality_levels.SampleCount = samples;
device12->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &multisample_quality_levels, sizeof(multisample_quality_levels));
device->CheckFeatureSupport(D3D12_FEATURE_MULTISAMPLE_QUALITY_LEVELS, &multisample_quality_levels, sizeof(multisample_quality_levels));
DXGI_SAMPLE_DESC desc;
desc.Count = samples;
desc.Quality = 0;
DXGI_SAMPLE_DESC desc;
desc.Count = samples;
desc.Quality = 0;
if (multisample_quality_levels.NumQualityLevels > 0)
{
aa_modes.push_back(desc);
}
}
device12->Release();
if (multisample_quality_levels.NumQualityLevels > 0)
aa_modes.push_back(desc);
}
return aa_modes;
}
D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter)
{
return D3D_FEATURE_LEVEL_11_0;
}
HRESULT Create(HWND wnd)
{
hWnd = wnd;
@@ -346,17 +262,21 @@ HRESULT Create(HWND wnd)
s_yres = client.bottom - client.top;
hr = LoadDXGI();
if (SUCCEEDED(hr))
hr = LoadD3D();
if (SUCCEEDED(hr))
hr = LoadD3DCompiler();
if (FAILED(hr))
return hr;
hr = LoadD3D();
if (FAILED(hr))
{
UnloadDXGI();
return hr;
}
hr = LoadD3DCompiler();
if (FAILED(hr))
{
UnloadD3D();
UnloadD3DCompiler();
UnloadDXGI();
return hr;
}
@@ -364,7 +284,13 @@ HRESULT Create(HWND wnd)
IDXGIAdapter* adapter;
hr = create_dxgi_factory(__uuidof(IDXGIFactory), (void**)&factory);
if (FAILED(hr))
{
MessageBox(wnd, _T("Failed to create IDXGIFactory object"), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR);
UnloadD3DCompiler();
UnloadD3D();
UnloadDXGI();
return hr;
}
hr = factory->EnumAdapters(g_ActiveConfig.iAdapter, &adapter);
if (FAILED(hr))
@@ -372,20 +298,13 @@ HRESULT Create(HWND wnd)
// try using the first one
hr = factory->EnumAdapters(0, &adapter);
if (FAILED(hr))
{
MessageBox(wnd, _T("Failed to enumerate adapters"), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR);
}
// get supported AA modes
s_aa_modes = EnumAAModes(adapter);
if (std::find_if(
s_aa_modes.begin(),
s_aa_modes.end(),
[](const DXGI_SAMPLE_DESC& desc) {return desc.Count == g_Config.iMultisamples; }
) == s_aa_modes.end())
{
g_Config.iMultisamples = 1;
UpdateActiveConfig();
UnloadD3DCompiler();
UnloadD3D();
UnloadDXGI();
return hr;
}
}
DXGI_SWAP_CHAIN_DESC swap_chain_desc = {};
@@ -405,74 +324,70 @@ HRESULT Create(HWND wnd)
#if defined(_DEBUG) || defined(DEBUGFAST) || defined(USE_D3D12_DEBUG_LAYER)
// Enabling the debug layer will fail if the Graphics Tools feature is not installed.
ID3D12Debug* debug_controller;
hr = d3d12_get_debug_interface(IID_PPV_ARGS(&debug_controller));
if (SUCCEEDED(hr))
{
ID3D12Debug* debug_controller;
hr = d3d12_get_debug_interface(IID_PPV_ARGS(&debug_controller));
if (SUCCEEDED(hr))
{
debug_controller->EnableDebugLayer();
debug_controller->Release();
}
else
{
MessageBox(wnd, _T("WARNING: Failed to enable D3D12 debug layer, please ensure the Graphics Tools feature is installed."), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR);
}
debug_controller->EnableDebugLayer();
debug_controller->Release();
}
else
{
MessageBox(wnd, _T("WARNING: Failed to enable D3D12 debug layer, please ensure the Graphics Tools feature is installed."), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR);
}
#endif
if (SUCCEEDED(hr))
{
hr = d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device12));
s_feat_level = D3D_FEATURE_LEVEL_11_0;
}
if (SUCCEEDED(hr))
{
D3D12_COMMAND_QUEUE_DESC command_queue_desc = {
D3D12_COMMAND_LIST_TYPE_DIRECT, // D3D12_COMMAND_LIST_TYPE Type;
0, // INT Priority;
D3D12_COMMAND_QUEUE_FLAG_NONE, // D3D12_COMMAND_QUEUE_FLAG Flags;
0 // UINT NodeMask;
};
CheckHR(device12->CreateCommandQueue(&command_queue_desc, IID_PPV_ARGS(&command_queue)));
IDXGIFactory* factory = nullptr;
adapter->GetParent(IID_PPV_ARGS(&factory));
CheckHR(factory->CreateSwapChain(command_queue, &swap_chain_desc, &s_swap_chain));
s_current_back_buf = 0;
factory->Release();
}
if (SUCCEEDED(hr))
{
// Query the monitor refresh rate, to ensure proper Present throttling behavior.
DEVMODE dev_mode;
memset(&dev_mode, 0, sizeof(DEVMODE));
dev_mode.dmSize = sizeof(DEVMODE);
dev_mode.dmDriverExtra = 0;
if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode) == 0)
{
// If EnumDisplaySettings fails, assume monitor refresh rate of 60 Hz.
s_monitor_refresh_rate = 60;
}
else
{
s_monitor_refresh_rate = dev_mode.dmDisplayFrequency;
}
}
hr = d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device12));
if (FAILED(hr))
{
MessageBox(wnd, _T("Failed to initialize Direct3D.\nMake sure your video card supports Direct3D 12 and your drivers are up-to-date."), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR);
SAFE_RELEASE(s_swap_chain);
return E_FAIL;
adapter->Release();
UnloadD3DCompiler();
UnloadD3D();
UnloadDXGI();
return hr;
}
// Ensure that the chosen AA mode is supported by the device.
std::vector<DXGI_SAMPLE_DESC> aa_modes = EnumAAModes(device12);
if (std::find_if(
aa_modes.begin(),
aa_modes.end(),
[](const DXGI_SAMPLE_DESC& desc) {return desc.Count == g_Config.iMultisamples; }
) == aa_modes.end())
{
g_Config.iMultisamples = 1;
UpdateActiveConfig();
}
D3D12_COMMAND_QUEUE_DESC command_queue_desc = {
D3D12_COMMAND_LIST_TYPE_DIRECT, // D3D12_COMMAND_LIST_TYPE Type;
0, // INT Priority;
D3D12_COMMAND_QUEUE_FLAG_NONE, // D3D12_COMMAND_QUEUE_FLAG Flags;
0 // UINT NodeMask;
};
CheckHR(device12->CreateCommandQueue(&command_queue_desc, IID_PPV_ARGS(&command_queue)));
CheckHR(factory->CreateSwapChain(command_queue, &swap_chain_desc, &s_swap_chain));
s_current_back_buf = 0;
// Query the monitor refresh rate, to ensure proper Present throttling behavior.
DEVMODE dev_mode;
memset(&dev_mode, 0, sizeof(DEVMODE));
dev_mode.dmSize = sizeof(DEVMODE);
dev_mode.dmDriverExtra = 0;
if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode) == 0)
{
// If EnumDisplaySettings fails, assume monitor refresh rate of 60 Hz.
s_monitor_refresh_rate = 60;
}
else
{
s_monitor_refresh_rate = dev_mode.dmDisplayFrequency;
}
ID3D12InfoQueue* info_queue = nullptr;
@@ -485,8 +400,7 @@ HRESULT Create(HWND wnd)
D3D12_MESSAGE_ID id_list[] = {
D3D12_MESSAGE_ID_CREATEGRAPHICSPIPELINESTATE_DEPTHSTENCILVIEW_NOT_SET, // Benign.
D3D12_MESSAGE_ID_CREATEGRAPHICSPIPELINESTATE_RENDERTARGETVIEW_NOT_SET, // Benign.
D3D12_MESSAGE_ID_CREATEINPUTLAYOUT_TYPE_MISMATCH, // Benign.
D3D12_MESSAGE_ID_MAP_INVALID_NULLRANGE, // Benign.
D3D12_MESSAGE_ID_CREATEINPUTLAYOUT_TYPE_MISMATCH // Benign.
};
filter.DenyList.NumIDs = ARRAYSIZE(id_list);
filter.DenyList.pIDList = id_list;
@@ -505,9 +419,6 @@ HRESULT Create(HWND wnd)
if (FAILED(hr))
MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 12 backend"), MB_OK | MB_ICONERROR);
SAFE_RELEASE(factory);
SAFE_RELEASE(adapter)
CreateDescriptorHeaps();
CreateRootSignatures();
@@ -528,7 +439,7 @@ HRESULT Create(HWND wnd)
CHECK(SUCCEEDED(hr), "Retrieve back buffer texture");
s_backbuf[i] = new D3DTexture2D(buf12,
D3D11_BIND_RENDER_TARGET,
TEXTURE_BIND_FLAG_RENDER_TARGET,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_UNKNOWN,
@@ -545,6 +456,14 @@ HRESULT Create(HWND wnd)
QueryPerformanceFrequency(&s_qpc_frequency);
// Render the device name.
DXGI_ADAPTER_DESC adapter_desc;
CheckHR(adapter->GetDesc(&adapter_desc));
OSD::AddMessage(StringFromFormat("Using D3D Adapter: %s.", UTF16ToUTF8(adapter_desc.Description).c_str()));
SAFE_RELEASE(factory);
SAFE_RELEASE(adapter);
return S_OK;
}
@@ -637,7 +556,15 @@ void CreateRootSignatures()
D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND // UINT OffsetInDescriptorsFromTableStart;
};
D3D12_ROOT_PARAMETER root_parameters[6];
D3D12_DESCRIPTOR_RANGE desc_range_uav = {
D3D12_DESCRIPTOR_RANGE_TYPE_UAV, // D3D12_DESCRIPTOR_RANGE_TYPE RangeType;
1, // UINT NumDescriptors;
2, // UINT BaseShaderRegister;
0, // UINT RegisterSpace;
D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND // UINT OffsetInDescriptorsFromTableStart;
};
D3D12_ROOT_PARAMETER root_parameters[NUM_GRAPHICS_ROOT_PARAMETERS];
root_parameters[DESCRIPTOR_TABLE_PS_SRV].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
root_parameters[DESCRIPTOR_TABLE_PS_SRV].DescriptorTable.NumDescriptorRanges = 1;
@@ -669,7 +596,10 @@ void CreateRootSignatures()
root_parameters[DESCRIPTOR_TABLE_PS_CBVTWO].Descriptor.ShaderRegister = 1;
root_parameters[DESCRIPTOR_TABLE_PS_CBVTWO].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
// D3D12TODO: Add bounding box UAV to root signature.
root_parameters[DESCRIPTOR_TABLE_PS_UAV].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
root_parameters[DESCRIPTOR_TABLE_PS_UAV].DescriptorTable.NumDescriptorRanges = 1;
root_parameters[DESCRIPTOR_TABLE_PS_UAV].DescriptorTable.pDescriptorRanges = &desc_range_uav;
root_parameters[DESCRIPTOR_TABLE_PS_UAV].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
D3D12_ROOT_SIGNATURE_DESC root_signature_desc = {};
root_signature_desc.pParameters = root_parameters;
@@ -746,9 +676,9 @@ void Close()
current_command_list = nullptr;
// unload DLLs
UnloadDXGI();
UnloadD3DCompiler();
UnloadD3D();
UnloadDXGI();
}
const std::string VertexShaderVersionString()
@@ -784,7 +714,7 @@ unsigned int GetBackBufferHeight()
// Returns the maximum width/height of a texture.
unsigned int GetMaxTextureSize()
{
return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
return D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
}
void Reset()
@@ -819,7 +749,7 @@ void Reset()
CHECK(SUCCEEDED(hr), "Retrieve back buffer texture");
s_backbuf[i] = new D3DTexture2D(buf12,
D3D11_BIND_RENDER_TARGET,
TEXTURE_BIND_FLAG_RENDER_TARGET,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_UNKNOWN,
DXGI_FORMAT_UNKNOWN,
+15 -13
View File
@@ -9,7 +9,6 @@
#pragma once
#include <d3d11.h>
#include <d3d12.h>
#include <d3dcompiler.h>
#include <dxgi1_4.h>
@@ -44,17 +43,21 @@ class D3DCommandListManager;
class D3DDescriptorHeapManager;
class D3DTexture2D;
enum GRAPHICS_ROOT_PARAMETER : u32
{
DESCRIPTOR_TABLE_PS_SRV,
DESCRIPTOR_TABLE_PS_SAMPLER,
DESCRIPTOR_TABLE_GS_CBV,
DESCRIPTOR_TABLE_VS_CBV,
DESCRIPTOR_TABLE_PS_CBVONE,
DESCRIPTOR_TABLE_PS_CBVTWO,
DESCRIPTOR_TABLE_PS_UAV,
NUM_GRAPHICS_ROOT_PARAMETERS
};
namespace D3D
{
#define DESCRIPTOR_TABLE_PS_SRV 0
#define DESCRIPTOR_TABLE_PS_SAMPLER 1
#define DESCRIPTOR_TABLE_GS_CBV 2
#define DESCRIPTOR_TABLE_VS_CBV 3
// #define DESCRIPTOR_TABLE_PS_UAV 4
#define DESCRIPTOR_TABLE_PS_CBVONE 4
#define DESCRIPTOR_TABLE_PS_CBVTWO 5
HRESULT LoadDXGI();
HRESULT LoadD3D();
HRESULT LoadD3DCompiler();
@@ -62,10 +65,7 @@ void UnloadDXGI();
void UnloadD3D();
void UnloadD3DCompiler();
D3D_FEATURE_LEVEL GetFeatureLevel(IDXGIAdapter* adapter);
std::vector<DXGI_SAMPLE_DESC> EnumAAModes(IDXGIAdapter* adapter);
bool AlertUserIfSelectedAdapterDoesNotSupportD3D12();
std::vector<DXGI_SAMPLE_DESC> EnumAAModes(ID3D12Device* device);
HRESULT Create(HWND wnd);
@@ -146,6 +146,8 @@ using CREATEDXGIFACTORY = HRESULT(WINAPI*)(REFIID, void**);
extern CREATEDXGIFACTORY create_dxgi_factory;
using D3D12CREATEDEVICE = HRESULT(WINAPI*)(IUnknown*, D3D_FEATURE_LEVEL, REFIID, void**);
extern D3D12CREATEDEVICE d3d12_create_device;
using D3D12SERIALIZEROOTSIGNATURE = HRESULT(WINAPI*)(const D3D12_ROOT_SIGNATURE_DESC* pRootSignature, D3D_ROOT_SIGNATURE_VERSION Version, ID3DBlob** ppBlob, ID3DBlob** ppErrorBlob);
using D3D12GETDEBUGINTERFACE = HRESULT(WINAPI*)(REFIID riid, void** ppvDebug);
@@ -90,8 +90,6 @@ private:
ID3D12GraphicsCommandList* m_backing_command_list;
ID3D12QueuedCommandList* m_queued_command_list;
ID3D12RootSignature* m_default_root_signature;
UINT m_current_deferred_destruction_list;
std::array<std::vector<ID3D12Resource*>, 2> m_deferred_destruction_lists;
std::array<UINT64, 2> m_deferred_destruction_list_fences;
@@ -274,6 +274,45 @@ void ID3D12QueuedCommandList::BackgroundThreadFunction(ID3D12QueuedCommandList*
break;
}
case D3DQueueItemType::BeginQuery:
{
command_list->BeginQuery(
reinterpret_cast<D3DQueueItem*>(item)->BeginQuery.pQueryHeap,
reinterpret_cast<D3DQueueItem*>(item)->BeginQuery.Type,
reinterpret_cast<D3DQueueItem*>(item)->BeginQuery.Index
);
item += BufferOffsetForQueueItemType<BeginQueryArguments>();
break;
}
case D3DQueueItemType::EndQuery:
{
command_list->EndQuery(
reinterpret_cast<D3DQueueItem*>(item)->EndQuery.pQueryHeap,
reinterpret_cast<D3DQueueItem*>(item)->EndQuery.Type,
reinterpret_cast<D3DQueueItem*>(item)->EndQuery.Index
);
item += BufferOffsetForQueueItemType<EndQueryArguments>();
break;
}
case D3DQueueItemType::ResolveQueryData:
{
command_list->ResolveQueryData(
reinterpret_cast<D3DQueueItem*>(item)->ResolveQueryData.pQueryHeap,
reinterpret_cast<D3DQueueItem*>(item)->ResolveQueryData.Type,
reinterpret_cast<D3DQueueItem*>(item)->ResolveQueryData.StartElement,
reinterpret_cast<D3DQueueItem*>(item)->ResolveQueryData.ElementCount,
reinterpret_cast<D3DQueueItem*>(item)->ResolveQueryData.pDestinationBuffer,
reinterpret_cast<D3DQueueItem*>(item)->ResolveQueryData.AlignedDestinationBufferOffset
);
item += BufferOffsetForQueueItemType<ResolveQueryDataArguments>();
break;
}
case D3DQueueItemType::CloseCommandList:
{
CheckHR(command_list->Close());
@@ -804,7 +843,7 @@ void STDMETHODCALLTYPE ID3D12QueuedCommandList::ResolveSubresource(
}
void STDMETHODCALLTYPE ID3D12QueuedCommandList::IASetPrimitiveTopology(
_In_ D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology
_In_ D3D12_PRIMITIVE_TOPOLOGY PrimitiveTopology
)
{
// No ignored parameters, no assumptions to DEBUGCHECK.
@@ -818,7 +857,7 @@ void STDMETHODCALLTYPE ID3D12QueuedCommandList::IASetPrimitiveTopology(
}
void STDMETHODCALLTYPE ID3D12QueuedCommandList::RSSetViewports(
_In_range_(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT Count,
_In_range_(0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT Count,
_In_reads_(Count) const D3D12_VIEWPORT* pViewports
)
{
@@ -838,7 +877,7 @@ void STDMETHODCALLTYPE ID3D12QueuedCommandList::RSSetViewports(
}
void STDMETHODCALLTYPE ID3D12QueuedCommandList::RSSetScissorRects(
_In_range_(0, D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT Count,
_In_range_(0, D3D12_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE) UINT Count,
_In_reads_(Count) const D3D12_RECT* pRects
)
{
@@ -916,8 +955,14 @@ void STDMETHODCALLTYPE ID3D12QueuedCommandList::BeginQuery(
_In_ UINT Index
)
{
// Function not implemented yet.
DEBUGCHECK(0, "Function not implemented yet.");
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->Type = D3DQueueItemType::BeginQuery;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->BeginQuery.pQueryHeap = pQueryHeap;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->BeginQuery.Type = Type;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->BeginQuery.Index = Index;
m_queue_array_back += BufferOffsetForQueueItemType<BeginQueryArguments>();
CheckForOverflow();
}
void STDMETHODCALLTYPE ID3D12QueuedCommandList::EndQuery(
@@ -926,8 +971,14 @@ void STDMETHODCALLTYPE ID3D12QueuedCommandList::EndQuery(
_In_ UINT Index
)
{
// Function not implemented yet.
DEBUGCHECK(0, "Function not implemented yet.");
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->Type = D3DQueueItemType::EndQuery;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->EndQuery.pQueryHeap = pQueryHeap;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->EndQuery.Type = Type;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->EndQuery.Index = Index;
m_queue_array_back += BufferOffsetForQueueItemType<EndQueryArguments>();
CheckForOverflow();
}
void STDMETHODCALLTYPE ID3D12QueuedCommandList::ResolveQueryData(
@@ -939,8 +990,17 @@ void STDMETHODCALLTYPE ID3D12QueuedCommandList::ResolveQueryData(
_In_ UINT64 AlignedDestinationBufferOffset
)
{
// Function not implemented yet.
DEBUGCHECK(0, "Function not implemented yet.");
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->Type = D3DQueueItemType::ResolveQueryData;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->ResolveQueryData.pQueryHeap = pQueryHeap;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->ResolveQueryData.Type = Type;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->ResolveQueryData.StartElement = StartElement;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->ResolveQueryData.ElementCount = ElementCount;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->ResolveQueryData.pDestinationBuffer = pDestinationBuffer;
reinterpret_cast<D3DQueueItem*>(m_queue_array_back)->ResolveQueryData.AlignedDestinationBufferOffset = AlignedDestinationBufferOffset;
m_queue_array_back += BufferOffsetForQueueItemType<ResolveQueryDataArguments>();
CheckForOverflow();
}
void STDMETHODCALLTYPE ID3D12QueuedCommandList::SetPredication(
@@ -1199,7 +1259,7 @@ void STDMETHODCALLTYPE ID3D12QueuedCommandList::ClearDepthStencilView(
_In_reads_opt_(NumRects) const D3D12_RECT* pRect
)
{
DEBUGCHECK(ClearFlags == D3D11_CLEAR_DEPTH, "Error: Invalid assumption in ID3D12QueuedCommandList.");
DEBUGCHECK(ClearFlags == D3D12_CLEAR_FLAG_DEPTH, "Error: Invalid assumption in ID3D12QueuedCommandList.");
DEBUGCHECK(Depth == 0.0f, "Error: Invalid assumption in ID3D12QueuedCommandList.");
DEBUGCHECK(Stencil == 0, "Error: Invalid assumption in ID3D12QueuedCommandList.");
DEBUGCHECK(pRect == nullptr, "Error: Invalid assumption in ID3D12QueuedCommandList.");
@@ -35,6 +35,9 @@ enum D3DQueueItemType
SetDescriptorHeaps,
ResourceBarrier,
ResolveSubresource,
BeginQuery,
EndQuery,
ResolveQueryData,
ExecuteCommandList,
CloseCommandList,
Present,
@@ -170,6 +173,30 @@ struct ResolveSubresourceArguments
DXGI_FORMAT Format;
};
struct BeginQueryArguments
{
ID3D12QueryHeap* pQueryHeap;
D3D12_QUERY_TYPE Type;
UINT Index;
};
struct EndQueryArguments
{
ID3D12QueryHeap* pQueryHeap;
D3D12_QUERY_TYPE Type;
UINT Index;
};
struct ResolveQueryDataArguments
{
ID3D12QueryHeap* pQueryHeap;
D3D12_QUERY_TYPE Type;
UINT StartElement;
UINT ElementCount;
ID3D12Resource* pDestinationBuffer;
UINT64 AlignedDestinationBufferOffset;
};
struct CloseCommandListArguments
{
};
@@ -239,6 +266,9 @@ struct D3DQueueItem
SetDescriptorHeapsArguments SetDescriptorHeaps;
ResourceBarrierArguments ResourceBarrier;
ResolveSubresourceArguments ResolveSubresource;
BeginQueryArguments BeginQuery;
EndQueryArguments EndQuery;
ResolveQueryDataArguments ResolveQueryData;
CloseCommandListArguments CloseCommandList;
ExecuteCommandListArguments ExecuteCommandList;
PresentArguments Present;
@@ -19,7 +19,7 @@ namespace DX12
namespace D3D
{
bool CompileShader(const std::string& code, ID3DBlob** blob, const D3D_SHADER_MACRO* defines, std::string shader_version_string)
bool CompileShader(const std::string& code, ID3DBlob** blob, const D3D_SHADER_MACRO* defines, const std::string& shader_version_string)
{
ID3D10Blob* shader_buffer = nullptr;
ID3D10Blob* error_buffer = nullptr;
@@ -34,21 +34,26 @@ bool CompileShader(const std::string& code, ID3DBlob** blob, const D3D_SHADER_MA
if (error_buffer)
{
INFO_LOG(VIDEO, "Shader compiler messages:\n%s\n",
WARN_LOG(VIDEO, "Warning generated when compiling %s shader:\n%s\n",
shader_version_string.c_str(),
static_cast<const char*>(error_buffer->GetBufferPointer()));
}
if (FAILED(hr))
{
static int num_failures = 0;
std::string filename = StringFromFormat("%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), shader_version_string, num_failures++);
std::string filename = StringFromFormat("%sbad_%s_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), shader_version_string.c_str(), num_failures++);
std::ofstream file;
OpenFStream(file, filename, std::ios_base::out);
file << code;
file << std::endl << "Errors:" << std::endl;
file << static_cast<const char*>(error_buffer->GetBufferPointer());
file.close();
PanicAlert("Failed to compile shader: %s\nDebug info (%s):\n%s",
filename.c_str(), shader_version_string, static_cast<const char*>(error_buffer->GetBufferPointer()));
filename.c_str(),
shader_version_string.c_str(),
static_cast<const char*>(error_buffer->GetBufferPointer()));
*blob = nullptr;
error_buffer->Release();
+2 -2
View File
@@ -343,8 +343,8 @@ inline D3D12_DEPTH_STENCIL_DESC StateCache::GetDesc12(ZMode state)
D3D12_DEPTH_STENCIL_DESC depthdc;
depthdc.StencilEnable = FALSE;
depthdc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
depthdc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;
depthdc.StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
depthdc.StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
D3D12_DEPTH_STENCILOP_DESC defaultStencilOp = { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };
depthdc.FrontFace = defaultStencilOp;
@@ -29,7 +29,8 @@ D3DStreamBuffer::~D3DStreamBuffer()
{
D3D::command_list_mgr->RemoveQueueFenceCallback(this);
m_buffer->Unmap(0, nullptr);
D3D12_RANGE write_range = { 0, m_buffer_size };
m_buffer->Unmap(0, &write_range);
D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_buffer);
}
@@ -43,7 +44,7 @@ bool D3DStreamBuffer::AllocateSpaceInBuffer(size_t allocation_size, size_t align
{
CHECK(allocation_size <= m_buffer_max_size, "Error: Requested allocation size in D3DStreamBuffer is greater than max allowed size of backing buffer.");
if (alignment)
if (alignment && m_buffer_offset > 0)
{
size_t padding = m_buffer_offset % alignment;
@@ -94,7 +95,8 @@ void D3DStreamBuffer::AllocateBuffer(size_t size)
// First, put existing buffer (if it exists) in deferred destruction list.
if (m_buffer)
{
m_buffer->Unmap(0, nullptr);
D3D12_RANGE write_range = { 0, m_buffer_size };
m_buffer->Unmap(0, &write_range);
D3D::command_list_mgr->DestroyResourceAfterCurrentCommandListExecuted(m_buffer);
m_buffer = nullptr;
}
@@ -110,7 +112,8 @@ void D3DStreamBuffer::AllocateBuffer(size_t size)
)
);
CheckHR(m_buffer->Map(0, nullptr, &m_buffer_cpu_address));
D3D12_RANGE read_range = {};
CheckHR(m_buffer->Map(0, &read_range, &m_buffer_cpu_address));
m_buffer_gpu_address = m_buffer->GetGPUVirtualAddress();
m_buffer_size = size;
+51 -18
View File
@@ -21,6 +21,9 @@ namespace DX12
namespace D3D
{
constexpr size_t INITIAL_TEXTURE_UPLOAD_BUFFER_SIZE = 4 * 1024 * 1024;
constexpr size_t MAXIMUM_TEXTURE_UPLOAD_BUFFER_SIZE = 64 * 1024 * 1024;
static std::unique_ptr<D3DStreamBuffer> s_texture_upload_stream_buffer;
void CleanupPersistentD3DTextureResources()
@@ -32,16 +35,35 @@ void ReplaceRGBATexture2D(ID3D12Resource* texture12, const u8* buffer, unsigned
{
const unsigned int upload_size = AlignValue(src_pitch, D3D12_TEXTURE_DATA_PITCH_ALIGNMENT) * height;
if (!s_texture_upload_stream_buffer)
{
s_texture_upload_stream_buffer = std::make_unique<D3DStreamBuffer>(4 * 1024 * 1024, 64 * 1024 * 1024, nullptr);
}
ID3D12Resource* upload_buffer = nullptr;
size_t upload_buffer_offset = 0;
u8* dest_data = nullptr;
bool current_command_list_executed = s_texture_upload_stream_buffer->AllocateSpaceInBuffer(upload_size, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
if (current_command_list_executed)
if (upload_size > MAXIMUM_TEXTURE_UPLOAD_BUFFER_SIZE)
{
g_renderer->SetViewport();
D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12());
// If the texture is too large to fit in the upload buffer, create a temporary buffer instead.
// This will only be the case for large (e.g. 8192x8192) textures from custom texture packs.
CheckHR(D3D::device12->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(upload_size),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&upload_buffer)));
D3D12_RANGE read_range = {};
CheckHR(upload_buffer->Map(0, &read_range, reinterpret_cast<void**>(&dest_data)));
}
else
{
if (!s_texture_upload_stream_buffer)
s_texture_upload_stream_buffer = std::make_unique<D3DStreamBuffer>(INITIAL_TEXTURE_UPLOAD_BUFFER_SIZE, MAXIMUM_TEXTURE_UPLOAD_BUFFER_SIZE, nullptr);
s_texture_upload_stream_buffer->AllocateSpaceInBuffer(upload_size, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT);
upload_buffer = s_texture_upload_stream_buffer->GetBuffer();
upload_buffer_offset = s_texture_upload_stream_buffer->GetOffsetOfCurrentAllocation();
dest_data = reinterpret_cast<u8*>(s_texture_upload_stream_buffer->GetCPUAddressOfCurrentAllocation());
}
ResourceBarrier(current_command_list, texture12, current_resource_state, D3D12_RESOURCE_STATE_COPY_DEST, level);
@@ -51,9 +73,8 @@ void ReplaceRGBATexture2D(ID3D12Resource* texture12, const u8* buffer, unsigned
u64 upload_row_size_in_bytes = 0;
u64 upload_total_bytes = 0;
D3D::device12->GetCopyableFootprints(&texture12->GetDesc(), level, 1, s_texture_upload_stream_buffer->GetOffsetOfCurrentAllocation(), &upload_footprint, &upload_rows, &upload_row_size_in_bytes, &upload_total_bytes);
D3D::device12->GetCopyableFootprints(&texture12->GetDesc(), level, 1, upload_buffer_offset, &upload_footprint, &upload_rows, &upload_row_size_in_bytes, &upload_total_bytes);
u8* dest_data = reinterpret_cast<u8*>(s_texture_upload_stream_buffer->GetCPUAddressOfCurrentAllocation());
const u8* src_data = reinterpret_cast<const u8*>(buffer);
for (u32 y = 0; y < upload_rows; ++y)
{
@@ -64,14 +85,26 @@ void ReplaceRGBATexture2D(ID3D12Resource* texture12, const u8* buffer, unsigned
);
}
D3D::current_command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(texture12, level), 0, 0, 0, &CD3DX12_TEXTURE_COPY_LOCATION(s_texture_upload_stream_buffer->GetBuffer(), upload_footprint), nullptr);
D3D::current_command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(texture12, level), 0, 0, 0, &CD3DX12_TEXTURE_COPY_LOCATION(upload_buffer, upload_footprint), nullptr);
ResourceBarrier(D3D::current_command_list, texture12, D3D12_RESOURCE_STATE_COPY_DEST, current_resource_state, level);
// Release temporary buffer after commands complete.
// We block here because otherwise if there was a large number of texture uploads, we may run out of memory.
if (!s_texture_upload_stream_buffer || upload_buffer != s_texture_upload_stream_buffer->GetBuffer())
{
D3D12_RANGE write_range = { 0, upload_size };
upload_buffer->Unmap(0, &write_range);
D3D::command_list_mgr->ExecuteQueuedWork(true);
upload_buffer->Release();
}
}
} // namespace
D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT fmt, unsigned int levels, unsigned int slices, D3D12_SUBRESOURCE_DATA* data)
D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, u32 bind, DXGI_FORMAT fmt, unsigned int levels, unsigned int slices, D3D12_SUBRESOURCE_DATA* data)
{
ID3D12Resource* texture12 = nullptr;
@@ -86,7 +119,7 @@ D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D1
D3D12_CLEAR_VALUE optimized_clear_value = {};
optimized_clear_value.Format = fmt;
if (bind & D3D11_BIND_RENDER_TARGET)
if (bind & TEXTURE_BIND_FLAG_RENDER_TARGET)
{
texdesc12.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
optimized_clear_value.Color[0] = 0.0f;
@@ -95,7 +128,7 @@ D3DTexture2D* D3DTexture2D::Create(unsigned int width, unsigned int height, D3D1
optimized_clear_value.Color[3] = 1.0f;
}
if (bind & D3D11_BIND_DEPTH_STENCIL)
if (bind & TEXTURE_BIND_FLAG_DEPTH_STENCIL)
{
texdesc12.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
optimized_clear_value.DepthStencil.Depth = 0.0f;
@@ -181,7 +214,7 @@ D3D12_CPU_DESCRIPTOR_HANDLE D3DTexture2D::GetRTV12() const
return m_rtv12;
}
D3DTexture2D::D3DTexture2D(ID3D12Resource* texptr, D3D11_BIND_FLAG bind,
D3DTexture2D::D3DTexture2D(ID3D12Resource* texptr, u32 bind,
DXGI_FORMAT srv_format, DXGI_FORMAT dsv_format, DXGI_FORMAT rtv_format, bool multisampled, D3D12_RESOURCE_STATES resource_state)
: m_tex12(texptr), m_resource_state(resource_state), m_multisampled(multisampled)
{
@@ -189,7 +222,7 @@ D3DTexture2D::D3DTexture2D(ID3D12Resource* texptr, D3D11_BIND_FLAG bind,
D3D12_DSV_DIMENSION dsv_dim12 = multisampled ? D3D12_DSV_DIMENSION_TEXTURE2DMSARRAY : D3D12_DSV_DIMENSION_TEXTURE2DARRAY;
D3D12_RTV_DIMENSION rtv_dim12 = multisampled ? D3D12_RTV_DIMENSION_TEXTURE2DMSARRAY : D3D12_RTV_DIMENSION_TEXTURE2DARRAY;
if (bind & D3D11_BIND_SHADER_RESOURCE)
if (bind & TEXTURE_BIND_FLAG_SHADER_RESOURCE)
{
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {
srv_format, // DXGI_FORMAT Format
@@ -216,7 +249,7 @@ D3DTexture2D::D3DTexture2D(ID3D12Resource* texptr, D3D11_BIND_FLAG bind,
D3D::device12->CreateShaderResourceView(m_tex12, &srv_desc, m_srv12_gpu_cpu_shadow);
}
if (bind & D3D11_BIND_DEPTH_STENCIL)
if (bind & TEXTURE_BIND_FLAG_DEPTH_STENCIL)
{
D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc = {
dsv_format, // DXGI_FORMAT Format
@@ -233,7 +266,7 @@ D3DTexture2D::D3DTexture2D(ID3D12Resource* texptr, D3D11_BIND_FLAG bind,
D3D::device12->CreateDepthStencilView(m_tex12, &dsv_desc, m_dsv12);
}
if (bind & D3D11_BIND_RENDER_TARGET)
if (bind & TEXTURE_BIND_FLAG_RENDER_TARGET)
{
D3D12_RENDER_TARGET_VIEW_DESC rtv_desc = {
rtv_format, // DXGI_FORMAT Format
+9 -3
View File
@@ -5,11 +5,17 @@
#pragma once
#include <atomic>
#include <d3d11.h>
namespace DX12
{
enum TEXTURE_BIND_FLAG : u32
{
TEXTURE_BIND_FLAG_SHADER_RESOURCE = (1 << 0),
TEXTURE_BIND_FLAG_RENDER_TARGET = (1 << 1),
TEXTURE_BIND_FLAG_DEPTH_STENCIL = (1 << 2)
};
namespace D3D
{
void ReplaceRGBATexture2D(ID3D12Resource* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int src_pitch, unsigned int level, D3D12_RESOURCE_STATES current_resource_state = D3D12_RESOURCE_STATE_COMMON);
@@ -24,8 +30,8 @@ public:
// either create an ID3D12Resource object, pass it to the constructor and specify what views to create
// or let the texture automatically be created by D3DTexture2D::Create
D3DTexture2D(ID3D12Resource* texptr, D3D11_BIND_FLAG bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN, bool multisampled = false, D3D12_RESOURCE_STATES resource_state = D3D12_RESOURCE_STATE_COMMON);
static D3DTexture2D* Create(unsigned int width, unsigned int height, D3D11_BIND_FLAG bind, D3D11_USAGE usage, DXGI_FORMAT, unsigned int levels = 1, unsigned int slices = 1, D3D12_SUBRESOURCE_DATA* data = nullptr);
D3DTexture2D(ID3D12Resource* texptr, u32 bind, DXGI_FORMAT srv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT dsv_format = DXGI_FORMAT_UNKNOWN, DXGI_FORMAT rtv_format = DXGI_FORMAT_UNKNOWN, bool multisampled = false, D3D12_RESOURCE_STATES resource_state = D3D12_RESOURCE_STATE_COMMON);
static D3DTexture2D* Create(unsigned int width, unsigned int height, u32 bind, DXGI_FORMAT fmt, unsigned int levels = 1, unsigned int slices = 1, D3D12_SUBRESOURCE_DATA* data = nullptr);
void TransitionToResourceState(ID3D12GraphicsCommandList* command_list, D3D12_RESOURCE_STATES state_after);
// reference counting, use AddRef() when creating a new reference and Release() it when you don't need it anymore
+2 -105
View File
@@ -26,11 +26,6 @@ namespace DX12
namespace D3D
{
unsigned int AlignValue(unsigned int value, unsigned int alignment)
{
return (value + (alignment - 1)) & ~(alignment - 1);
}
void ResourceBarrier(ID3D12GraphicsCommandList* command_list, ID3D12Resource* resource, D3D12_RESOURCE_STATES state_before, D3D12_RESOURCE_STATES state_after, UINT subresource)
{
if (state_before == state_after)
@@ -104,7 +99,6 @@ private:
CD3DFont font;
static std::unique_ptr<UtilVertexBuffer> util_vbuf_stq;
static std::unique_ptr<UtilVertexBuffer> util_vbuf_cq;
static std::unique_ptr<UtilVertexBuffer> util_vbuf_clearq;
static std::unique_ptr<UtilVertexBuffer> util_vbuf_efbpokequads;
@@ -502,12 +496,6 @@ struct
float u1, v1, u2, v2, S, G;
} tex_quad_data;
struct
{
float x1, y1, x2, y2, z;
u32 col;
} draw_quad_data;
struct
{
u32 col;
@@ -516,13 +504,11 @@ struct
// ring buffer offsets
static size_t stq_offset;
static size_t cq_offset;
static size_t clearq_offset;
void InitUtils()
{
util_vbuf_stq = std::make_unique<UtilVertexBuffer>(0x10000);
util_vbuf_cq = std::make_unique<UtilVertexBuffer>(0x10000);
util_vbuf_clearq = std::make_unique<UtilVertexBuffer>(0x10000);
util_vbuf_efbpokequads = std::make_unique<UtilVertexBuffer>(0x100000);
@@ -560,7 +546,6 @@ void InitUtils()
// cached data used to avoid unnecessarily reloading the vertex buffers
memset(&tex_quad_data, 0, sizeof(tex_quad_data));
memset(&draw_quad_data, 0, sizeof(draw_quad_data));
memset(&clear_quad_data, 0, sizeof(clear_quad_data));
font.Init();
@@ -571,7 +556,6 @@ void ShutdownUtils()
font.Shutdown();
util_vbuf_stq.reset();
util_vbuf_cq.reset();
util_vbuf_clearq.reset();
util_vbuf_efbpokequads.reset();
}
@@ -588,7 +572,7 @@ void SetLinearCopySampler()
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_SAMPLERS, true);
}
void SetViewportAndScissor(u32 top_left_x, u32 top_left_y, u32 width, u32 height, float min_depth, float max_depth)
void SetViewportAndScissor(int top_left_x, int top_left_y, int width, int height, float min_depth, float max_depth)
{
D3D12_VIEWPORT viewport = {
static_cast<float>(top_left_x),
@@ -707,89 +691,6 @@ void DrawShadedTexQuad(D3DTexture2D* texture,
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true);
D3D::current_command_list->DrawInstanced(4, 1, static_cast<UINT>(stq_offset), 0);
g_renderer->RestoreAPIState();
}
// Fills a certain area of the current render target with the specified color
// destination coordinates normalized to (-1;1)
void DrawColorQuad(u32 Color, float z, float x1, float y1, float x2, float y2, D3D12_BLEND_DESC* blend_desc, D3D12_DEPTH_STENCIL_DESC* depth_stencil_desc, bool rt_multisampled)
{
ColVertex coords[4] = {
{ x1, y2, z, Color },
{ x2, y2, z, Color },
{ x1, y1, z, Color },
{ x2, y1, z, Color },
};
if (draw_quad_data.x1 != x1 || draw_quad_data.y1 != y1 ||
draw_quad_data.x2 != x2 || draw_quad_data.y2 != y2 ||
draw_quad_data.col != Color || draw_quad_data.z != z)
{
cq_offset = util_vbuf_cq->AppendData(coords, sizeof(coords), sizeof(ColVertex));
draw_quad_data.x1 = x1;
draw_quad_data.y1 = y1;
draw_quad_data.x2 = x2;
draw_quad_data.y2 = y2;
draw_quad_data.col = Color;
draw_quad_data.z = z;
}
D3D::current_command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D::command_list_mgr->SetCommandListPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
D3D12_VERTEX_BUFFER_VIEW vb_view = {
util_vbuf_cq->GetBuffer12()->GetGPUVirtualAddress(), // D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
static_cast<UINT>(util_vbuf_cq->GetSize()), // UINT SizeInBytes; This is the size of the entire buffer, not just the size of the vertex data for one draw call, since the offsetting is done in the draw call itself.
sizeof(ColVertex) // UINT StrideInBytes;
};
D3D::current_command_list->IASetVertexBuffers(0, 1, &vb_view);
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_VERTEX_BUFFER, true);
D3D12_GRAPHICS_PIPELINE_STATE_DESC pso_desc = {
default_root_signature, // ID3D12RootSignature *pRootSignature;
StaticShaderCache::GetClearVertexShader(), // D3D12_SHADER_BYTECODE VS;
StaticShaderCache::GetClearPixelShader(), // D3D12_SHADER_BYTECODE PS;
{}, // D3D12_SHADER_BYTECODE DS;
{}, // D3D12_SHADER_BYTECODE HS;
StaticShaderCache::GetClearGeometryShader(), // D3D12_SHADER_BYTECODE GS;
{}, // D3D12_STREAM_OUTPUT_DESC StreamOutput
*blend_desc, // D3D12_BLEND_DESC BlendState;
UINT_MAX, // UINT SampleMask;
Renderer::GetResetRasterizerDesc(), // D3D12_RASTERIZER_DESC RasterizerState
*depth_stencil_desc, // D3D12_DEPTH_STENCIL_DESC DepthStencilState
StaticShaderCache::GetClearVertexShaderInputLayout(), // D3D12_INPUT_LAYOUT_DESC InputLayout
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF, // D3D12_INDEX_BUFFER_PROPERTIES IndexBufferProperties
D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE, // D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimitiveTopologyType
1, // UINT NumRenderTargets
{ DXGI_FORMAT_R8G8B8A8_UNORM }, // DXGI_FORMAT RTVFormats[8]
DXGI_FORMAT_D32_FLOAT, // DXGI_FORMAT DSVFormat
{ 1 /* UINT Count */, 0 /* UINT Quality */ } // DXGI_SAMPLE_DESC SampleDesc
};
if (rt_multisampled)
{
pso_desc.SampleDesc.Count = g_ActiveConfig.iMultisamples;
}
ID3D12PipelineState* pso = nullptr;
CheckHR(DX12::gx_state_cache.GetPipelineStateObjectFromCache(&pso_desc, &pso));
D3D::current_command_list->SetPipelineState(pso);
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true);
// In D3D11, the 'resetraststate' has ScissorEnable disabled. In D3D12, scissor testing is always enabled.
// Thus, set the scissor rect to the max texture size, then reset it to the current scissor rect to avoid
// dirtying state.
// 2 ^ D3D12_MAX_TEXTURE_DIMENSION_2_TO_EXP = 131072
D3D::current_command_list->RSSetScissorRects(1, &CD3DX12_RECT(0, 0, 131072, 131072));
D3D::current_command_list->DrawInstanced(4, 1, static_cast<UINT>(cq_offset), 0);
g_renderer->RestoreAPIState();
}
void DrawClearQuad(u32 Color, float z, D3D12_BLEND_DESC* blend_desc, D3D12_DEPTH_STENCIL_DESC* depth_stencil_desc, bool rt_multisampled)
@@ -856,8 +757,6 @@ void DrawClearQuad(u32 Color, float z, D3D12_BLEND_DESC* blend_desc, D3D12_DEPTH
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true);
D3D::current_command_list->DrawInstanced(4, 1, static_cast<UINT>(clearq_offset), 0);
g_renderer->RestoreAPIState();
}
static void InitColVertex(ColVertex* vert, float x, float y, float z, u32 col)
@@ -933,6 +832,7 @@ void DrawEFBPokeQuads(EFBAccessType type,
// Corresponding dirty flags set outside loop.
D3D::current_command_list->OMSetRenderTargets(1, render_target, FALSE, depth_buffer);
D3D::current_command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D::command_list_mgr->SetCommandListPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D12_VERTEX_BUFFER_VIEW vb_view = {
util_vbuf_efbpokequads->GetBuffer12()->GetGPUVirtualAddress(), // D3D12_GPU_VIRTUAL_ADDRESS BufferLocation;
@@ -946,9 +846,6 @@ void DrawEFBPokeQuads(EFBAccessType type,
D3D::current_command_list->SetPipelineState(pso);
D3D::command_list_mgr->SetCommandListDirtyState(COMMAND_LIST_STATE_PSO, true);
// Disable scissor testing.
D3D::current_command_list->RSSetScissorRects(1, &CD3DX12_RECT(0, 0, 131072, 131072));
// generate quads for each efb point
ColVertex* base_vertex_ptr = reinterpret_cast<ColVertex*>(buffer_ptr);
for (size_t i = 0; i < points_to_draw; i++)
+6 -4
View File
@@ -4,7 +4,6 @@
#pragma once
#include <d3d11.h>
#include <memory>
#include <string>
@@ -22,7 +21,11 @@ extern StateCache gx_state_cache;
namespace D3D
{
unsigned int AlignValue(unsigned int value, unsigned int alignment);
constexpr unsigned int AlignValue(unsigned int value, unsigned int alignment)
{
return (value + (alignment - 1)) & ~(alignment - 1);
}
void ResourceBarrier(ID3D12GraphicsCommandList* command_list, ID3D12Resource* resource, D3D12_RESOURCE_STATES state_before, D3D12_RESOURCE_STATES state_after, UINT subresource);
// Font creation flags
@@ -74,7 +77,7 @@ void ShutdownUtils();
void SetPointCopySampler();
void SetLinearCopySampler();
void SetViewportAndScissor(u32 top_left_x, u32 top_left_y, u32 width, u32 height, float min_depth = D3D12_MIN_DEPTH, float max_depth = D3D12_MAX_DEPTH);
void SetViewportAndScissor(int top_left_x, int top_left_y, int width, int height, float min_depth = D3D12_MIN_DEPTH, float max_depth = D3D12_MAX_DEPTH);
void DrawShadedTexQuad(D3DTexture2D* texture,
const D3D12_RECT* source,
@@ -92,7 +95,6 @@ void DrawShadedTexQuad(D3DTexture2D* texture,
);
void DrawClearQuad(u32 Color, float z, D3D12_BLEND_DESC* blend_desc, D3D12_DEPTH_STENCIL_DESC* depth_stencil_desc, bool rt_multisampled);
void DrawColorQuad(u32 Color, float z, float x1, float y1, float x2, float y2, D3D12_BLEND_DESC* blend_desc, D3D12_DEPTH_STENCIL_DESC* depth_stencil_desc, bool rt_multisampled);
void DrawEFBPokeQuads(EFBAccessType type,
const EfbPokeData* points,
@@ -15,8 +15,6 @@
namespace DX12
{
static XFBEncoder s_xfbEncoder;
FramebufferManager::Efb FramebufferManager::m_efb;
unsigned int FramebufferManager::m_target_width;
unsigned int FramebufferManager::m_target_height;
@@ -42,7 +40,12 @@ D3DTexture2D*& FramebufferManager::GetResolvedEFBColorTexture()
for (int i = 0; i < m_efb.slices; i++)
{
D3D::current_command_list->ResolveSubresource(m_efb.resolved_color_tex->GetTex12(), D3D11CalcSubresource(0, i, 1), m_efb.color_tex->GetTex12(), D3D11CalcSubresource(0, i, 1), DXGI_FORMAT_R8G8B8A8_UNORM);
D3D::current_command_list->ResolveSubresource(
m_efb.resolved_color_tex->GetTex12(),
D3D12CalcSubresource(0, i, 0, 1, m_efb.slices),
m_efb.color_tex->GetTex12(),
D3D12CalcSubresource(0, i, 0, 1, m_efb.slices),
DXGI_FORMAT_R8G8B8A8_UNORM);
}
m_efb.color_tex->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
@@ -91,13 +94,13 @@ FramebufferManager::FramebufferManager()
texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, m_target_width, m_target_height, m_efb.slices, 1, sample_desc.Count, sample_desc.Quality, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, &optimized_clear_valueRTV, IID_PPV_ARGS(&buf12));
m_efb.color_tex = new D3DTexture2D(buf12, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1), D3D12_RESOURCE_STATE_COMMON);
m_efb.color_tex = new D3DTexture2D(buf12, TEXTURE_BIND_FLAG_SHADER_RESOURCE | TEXTURE_BIND_FLAG_RENDER_TARGET, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1), D3D12_RESOURCE_STATE_COMMON);
SAFE_RELEASE(buf12);
// Temporary EFB color texture - used in ReinterpretPixelData
texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, m_target_width, m_target_height, m_efb.slices, 1, sample_desc.Count, sample_desc.Quality, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
CheckHR(D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, &optimized_clear_valueRTV, IID_PPV_ARGS(&buf12)));
m_efb.color_temp_tex = new D3DTexture2D(buf12, (D3D11_BIND_FLAG)(D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET), DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1), D3D12_RESOURCE_STATE_COMMON);
m_efb.color_temp_tex = new D3DTexture2D(buf12, TEXTURE_BIND_FLAG_SHADER_RESOURCE | TEXTURE_BIND_FLAG_RENDER_TARGET, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM, (sample_desc.Count > 1), D3D12_RESOURCE_STATE_COMMON);
SAFE_RELEASE(buf12);
D3D::SetDebugObjectName12(m_efb.color_temp_tex->GetTex12(), "EFB color temp texture");
@@ -105,7 +108,7 @@ FramebufferManager::FramebufferManager()
texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R32_TYPELESS, m_target_width, m_target_height, m_efb.slices, 1, sample_desc.Count, sample_desc.Quality, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL);
CheckHR(D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, &optimized_clear_valueDSV, IID_PPV_ARGS(&buf12)));
m_efb.depth_tex = new D3DTexture2D(buf12, (D3D11_BIND_FLAG)(D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE), DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_UNKNOWN, (sample_desc.Count > 1), D3D12_RESOURCE_STATE_COMMON);
m_efb.depth_tex = new D3DTexture2D(buf12, TEXTURE_BIND_FLAG_SHADER_RESOURCE | TEXTURE_BIND_FLAG_DEPTH_STENCIL, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT, DXGI_FORMAT_UNKNOWN, (sample_desc.Count > 1), D3D12_RESOURCE_STATE_COMMON);
SAFE_RELEASE(buf12);
D3D::SetDebugObjectName12(m_efb.depth_tex->GetTex12(), "EFB depth texture");
@@ -115,14 +118,14 @@ FramebufferManager::FramebufferManager()
texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, m_target_width, m_target_height, m_efb.slices, 1);
hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&buf12));
CHECK(hr == S_OK, "create EFB color resolve texture (size: %dx%d)", m_target_width, m_target_height);
m_efb.resolved_color_tex = new D3DTexture2D(buf12, D3D11_BIND_SHADER_RESOURCE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, false, D3D12_RESOURCE_STATE_COMMON);
m_efb.resolved_color_tex = new D3DTexture2D(buf12, TEXTURE_BIND_FLAG_SHADER_RESOURCE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, false, D3D12_RESOURCE_STATE_COMMON);
SAFE_RELEASE(buf12);
D3D::SetDebugObjectName12(m_efb.resolved_color_tex->GetTex12(), "EFB color resolve texture shader resource view");
texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R32_FLOAT, m_target_width, m_target_height, m_efb.slices, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET);
hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, nullptr, IID_PPV_ARGS(&buf12));
CHECK(hr == S_OK, "create EFB depth resolve texture (size: %dx%d; hr=%#x)", m_target_width, m_target_height, hr);
m_efb.resolved_depth_tex = new D3DTexture2D(buf12, (D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, false, D3D12_RESOURCE_STATE_COMMON);
m_efb.resolved_depth_tex = new D3DTexture2D(buf12, TEXTURE_BIND_FLAG_SHADER_RESOURCE | TEXTURE_BIND_FLAG_RENDER_TARGET, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, false, D3D12_RESOURCE_STATE_COMMON);
SAFE_RELEASE(buf12);
D3D::SetDebugObjectName12(m_efb.resolved_depth_tex->GetTex12(), "EFB depth resolve texture shader resource view");
}
@@ -133,14 +136,10 @@ FramebufferManager::FramebufferManager()
}
InitializeEFBAccessCopies();
s_xfbEncoder.Init();
}
FramebufferManager::~FramebufferManager()
{
s_xfbEncoder.Shutdown();
DestroyEFBAccessCopies();
SAFE_RELEASE(m_efb.color_tex);
@@ -153,14 +152,16 @@ FramebufferManager::~FramebufferManager()
void FramebufferManager::CopyToRealXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float gamma)
{
u8* dst = Memory::GetPointer(xfbAddr);
s_xfbEncoder.Encode(dst, fbStride/2, fbHeight, sourceRc, gamma);
D3DTexture2D* src_texture = GetResolvedEFBColorTexture();
TargetRectangle scaled_rect = g_renderer->ConvertEFBRectangle(sourceRc);
g_xfb_encoder->EncodeTextureToRam(dst, fbStride, fbHeight, src_texture, scaled_rect, m_target_width, m_target_height, gamma);
}
std::unique_ptr<XFBSourceBase> FramebufferManager::CreateXFBSource(unsigned int target_width, unsigned int target_height, unsigned int layers)
{
return std::make_unique<XFBSource>(D3DTexture2D::Create(target_width, target_height,
(D3D11_BIND_FLAG)(D3D11_BIND_RENDER_TARGET|D3D11_BIND_SHADER_RESOURCE),
D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8G8B8A8_UNORM, 1, layers), layers);
TEXTURE_BIND_FLAG_SHADER_RESOURCE | TEXTURE_BIND_FLAG_RENDER_TARGET,
DXGI_FORMAT_R8G8B8A8_UNORM, 1, layers), layers);
}
void FramebufferManager::GetTargetSize(unsigned int* width, unsigned int* height)
@@ -197,12 +198,18 @@ void FramebufferManager::ResolveDepthTexture()
FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE);
D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12());
// Restores proper viewport/scissor settings.
g_renderer->RestoreAPIState();
}
void FramebufferManager::RestoreEFBRenderTargets()
{
D3D::current_command_list->OMSetRenderTargets(1,
&FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE,
&FramebufferManager::GetEFBDepthTexture()->GetDSV12());
}
u32 FramebufferManager::ReadEFBColorAccessCopy(u32 x, u32 y)
{
if (!m_efb.color_access_readback_map)
@@ -255,7 +262,7 @@ void FramebufferManager::InitializeEFBAccessCopies()
texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8G8B8A8_UNORM, EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_TEXTURE_LAYOUT_UNKNOWN, 0);
hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, &optimized_color_clear_value, IID_PPV_ARGS(&buf12));
CHECK(hr == S_OK, "create EFB access color resize buffer (hr=%#x)", hr);
m_efb.color_access_resize_tex = new D3DTexture2D(buf12, D3D11_BIND_RENDER_TARGET, DXGI_FORMAT_R8G8B8A8_UNORM);
m_efb.color_access_resize_tex = new D3DTexture2D(buf12, TEXTURE_BIND_FLAG_RENDER_TARGET, DXGI_FORMAT_R8G8B8A8_UNORM);
D3D::SetDebugObjectName12(m_efb.color_access_resize_tex->GetTex12(), "EFB access color resize buffer");
buf12->Release();
@@ -269,7 +276,7 @@ void FramebufferManager::InitializeEFBAccessCopies()
texdesc12 = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R32_FLOAT, EFB_WIDTH, EFB_HEIGHT, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_TEXTURE_LAYOUT_UNKNOWN, 0);
hr = D3D::device12->CreateCommittedResource(&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), D3D12_HEAP_FLAG_NONE, &texdesc12, D3D12_RESOURCE_STATE_COMMON, &optimized_depth_clear_value, IID_PPV_ARGS(&buf12));
CHECK(hr == S_OK, "create EFB access depth resize buffer (hr=%#x)", hr);
m_efb.depth_access_resize_tex = new D3DTexture2D(buf12, D3D11_BIND_RENDER_TARGET, DXGI_FORMAT_R32_FLOAT);
m_efb.depth_access_resize_tex = new D3DTexture2D(buf12, TEXTURE_BIND_FLAG_RENDER_TARGET, DXGI_FORMAT_R32_FLOAT);
D3D::SetDebugObjectName12(m_efb.color_access_resize_tex->GetTex12(), "EFB access depth resize buffer");
buf12->Release();
@@ -317,19 +324,16 @@ void FramebufferManager::MapEFBColorAccessCopy()
CD3DX12_TEXTURE_COPY_LOCATION src_location(src_resource, 0);
D3D::current_command_list->CopyTextureRegion(&dst_location, 0, 0, 0, &src_location, nullptr);
// Block until completion
D3D::command_list_mgr->ExecuteQueuedWork(true);
// Restore EFB resource state if it was sourced from here
if (src_resource == m_efb.color_tex->GetTex12())
m_efb.color_tex->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
// Restore state after resetting command list
D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12());
g_renderer->RestoreAPIState();
// Block until completion - state is automatically restored
D3D::command_list_mgr->ExecuteQueuedWork(true);
// Resource copy has finished, so safe to map now
m_efb.color_access_readback_buffer->Map(0, nullptr, reinterpret_cast<void**>(&m_efb.color_access_readback_map));
D3D12_RANGE read_range = { 0, m_efb.color_access_readback_pitch * EFB_HEIGHT };
m_efb.color_access_readback_buffer->Map(0, &read_range, reinterpret_cast<void**>(&m_efb.color_access_readback_map));
}
void FramebufferManager::MapEFBDepthAccessCopy()
@@ -344,7 +348,7 @@ void FramebufferManager::MapEFBDepthAccessCopy()
D3D::SetViewportAndScissor(0, 0, EFB_WIDTH, EFB_HEIGHT);
D3D::SetPointCopySampler();
D3D::current_command_list->OMSetRenderTargets(1, &m_efb.color_access_resize_tex->GetRTV12(), FALSE, nullptr);
D3D::current_command_list->OMSetRenderTargets(1, &m_efb.depth_access_resize_tex->GetRTV12(), FALSE, nullptr);
CD3DX12_RECT src_rect(0, 0, m_target_width, m_target_height);
D3D::DrawShadedTexQuad(m_efb.depth_tex, &src_rect, m_target_width, m_target_height,
@@ -369,32 +373,31 @@ void FramebufferManager::MapEFBDepthAccessCopy()
CD3DX12_TEXTURE_COPY_LOCATION src_location(src_resource, 0);
D3D::current_command_list->CopyTextureRegion(&dst_location, 0, 0, 0, &src_location, nullptr);
// Block until completion
D3D::command_list_mgr->ExecuteQueuedWork(true);
// Restore EFB resource state if it was sourced from here
if (src_resource == m_efb.depth_tex->GetTex12())
m_efb.depth_tex->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE);
// Restore state after resetting command list
D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12());
g_renderer->RestoreAPIState();
// Block until completion - state is automatically restored
D3D::command_list_mgr->ExecuteQueuedWork(true);
// Resource copy has finished, so safe to map now
m_efb.depth_access_readback_buffer->Map(0, nullptr, reinterpret_cast<void**>(&m_efb.depth_access_readback_map));
D3D12_RANGE read_range = { 0, m_efb.depth_access_readback_pitch * EFB_HEIGHT };
m_efb.depth_access_readback_buffer->Map(0, &read_range, reinterpret_cast<void**>(&m_efb.depth_access_readback_map));
}
void FramebufferManager::InvalidateEFBAccessCopies()
{
D3D12_RANGE write_range = {};
if (m_efb.color_access_readback_map)
{
m_efb.color_access_readback_buffer->Unmap(0, nullptr);
m_efb.color_access_readback_buffer->Unmap(0, &write_range);
m_efb.color_access_readback_map = nullptr;
}
if (m_efb.depth_access_readback_map)
{
m_efb.depth_access_readback_buffer->Unmap(0, nullptr);
m_efb.depth_access_readback_buffer->Unmap(0, &write_range);
m_efb.depth_access_readback_map = nullptr;
}
}
@@ -414,8 +417,8 @@ void FramebufferManager::DestroyEFBAccessCopies()
void XFBSource::DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
// DX12's XFB decoder does not use this function.
// YUYV data is decoded in Render::Swap.
u8* src = Memory::GetPointer(xfbAddr);
g_xfb_encoder->DecodeToTexture(m_tex, src, fbWidth, fbHeight);
}
void XFBSource::CopyEFB(float gamma)
@@ -448,7 +451,6 @@ void XFBSource::CopyEFB(float gamma)
FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE );
D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12());
// Restores proper viewport/scissor settings.
g_renderer->RestoreAPIState();
@@ -70,6 +70,8 @@ public:
static void ResolveDepthTexture();
static void RestoreEFBRenderTargets();
// Access EFB from CPU
static u32 ReadEFBColorAccessCopy(u32 x, u32 y);
static float ReadEFBDepthAccessCopy(u32 x, u32 y);
@@ -105,7 +105,9 @@ void PSTextureEncoder::Init()
D3D::SetDebugObjectName12(m_encode_params_buffer, "efb encoder params buffer");
CheckHR(m_encode_params_buffer->Map(0, nullptr, &m_encode_params_buffer_data));
// NOTE: This upload buffer is okay to overwrite each time, since we block until completion when it's used anyway.
D3D12_RANGE read_range = {};
CheckHR(m_encode_params_buffer->Map(0, &read_range, &m_encode_params_buffer_data));
m_ready = true;
}
@@ -215,11 +217,16 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p
D3D::ResourceBarrier(D3D::current_command_list, m_out, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE, 0);
D3D::current_command_list->CopyTextureRegion(&dst_location, 0, 0, 0, &src_location, &src_box);
FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE);
// State is automatically restored after executing command list.
D3D::command_list_mgr->ExecuteQueuedWork(true);
// Transfer staging buffer to GameCube/Wii RAM
void* readback_data_map;
CheckHR(m_out_readback_buffer->Map(0, nullptr, &readback_data_map));
D3D12_RANGE read_range = { 0, dst_location.PlacedFootprint.Footprint.RowPitch * num_blocks_y };
CheckHR(m_out_readback_buffer->Map(0, &read_range, &readback_data_map));
u8* src = static_cast<u8*>(readback_data_map);
u32 read_stride = std::min(bytes_per_row, dst_location.PlacedFootprint.Footprint.RowPitch);
@@ -231,14 +238,8 @@ void PSTextureEncoder::Encode(u8* dst, u32 format, u32 native_width, u32 bytes_p
src += dst_location.PlacedFootprint.Footprint.RowPitch;
}
m_out_readback_buffer->Unmap(0, nullptr);
// Restores proper viewport/scissor settings.
g_renderer->RestoreAPIState();
FramebufferManager::GetEFBColorTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_RENDER_TARGET);
FramebufferManager::GetEFBDepthTexture()->TransitionToResourceState(D3D::current_command_list, D3D12_RESOURCE_STATE_DEPTH_WRITE );
D3D::current_command_list->OMSetRenderTargets(1, &FramebufferManager::GetEFBColorTexture()->GetRTV12(), FALSE, &FramebufferManager::GetEFBDepthTexture()->GetDSV12());
D3D12_RANGE write_range = {};
m_out_readback_buffer->Unmap(0, &write_range);
}
D3D12_SHADER_BYTECODE PSTextureEncoder::SetStaticShader(unsigned int dst_format, PEControl::PixelFormat src_format,
+161 -14
View File
@@ -2,68 +2,215 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <algorithm>
#include "Common/CommonFuncs.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "VideoBackends/D3D12/D3DBase.h"
#include "VideoBackends/D3D12/D3DCommandListManager.h"
#include "VideoBackends/D3D12/PerfQuery.h"
#include "VideoCommon/RenderBase.h"
//D3D12TODO: Implement PerfQuery class.
namespace DX12
{
PerfQuery::PerfQuery()
{
//D3D12TODO: Add implementation
D3D12_QUERY_HEAP_DESC desc = { D3D12_QUERY_HEAP_TYPE_OCCLUSION, PERF_QUERY_BUFFER_SIZE, 0 };
CheckHR(D3D::device12->CreateQueryHeap(&desc, IID_PPV_ARGS(&m_query_heap)));
CheckHR(D3D::device12->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_READBACK),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(QUERY_READBACK_BUFFER_SIZE),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_query_readback_buffer)));
m_tracking_fence = D3D::command_list_mgr->RegisterQueueFenceCallback(this, &PerfQuery::QueueFenceCallback);
}
PerfQuery::~PerfQuery()
{
//D3D12TODO: Add implementation
D3D::command_list_mgr->RemoveQueueFenceCallback(this);
SAFE_RELEASE(m_query_heap);
SAFE_RELEASE(m_query_readback_buffer);
}
void PerfQuery::EnableQuery(PerfQueryGroup type)
{
//D3D12TODO: Add implementation
if (m_query_count > m_query_buffer.size() / 2)
WeakFlush();
// all queries already used?
if (m_query_buffer.size() == m_query_count)
{
FlushOne();
//WARN_LOG(VIDEO, "Flushed query buffer early!");
}
if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
{
size_t index = (m_query_read_pos + m_query_count) % m_query_buffer.size();
auto& entry = m_query_buffer[index];
D3D::current_command_list->BeginQuery(m_query_heap, D3D12_QUERY_TYPE_OCCLUSION, static_cast<UINT>(index));
entry.query_type = type;
entry.fence_value = -1;
++m_query_count;
}
}
void PerfQuery::DisableQuery(PerfQueryGroup type)
{
//D3D12TODO: Add implementation
if (type == PQG_ZCOMP_ZCOMPLOC || type == PQG_ZCOMP)
{
size_t index = (m_query_read_pos + m_query_count + m_query_buffer.size() - 1) % m_query_buffer.size();
auto& entry = m_query_buffer[index];
D3D::current_command_list->EndQuery(m_query_heap, D3D12_QUERY_TYPE_OCCLUSION, static_cast<UINT>(index));
D3D::current_command_list->ResolveQueryData(m_query_heap, D3D12_QUERY_TYPE_OCCLUSION, static_cast<UINT>(index), 1, m_query_readback_buffer, index * sizeof(UINT64));
entry.fence_value = m_next_fence_value;
}
}
void PerfQuery::ResetQuery()
{
//D3D12TODO: Add implementation
m_query_count = 0;
std::fill_n(m_results, ArraySize(m_results), 0);
}
u32 PerfQuery::GetQueryResult(PerfQueryType type)
{
//D3D12TODO: Add implementation
return 0;
u32 result = 0;
if (type == PQ_ZCOMP_INPUT_ZCOMPLOC || type == PQ_ZCOMP_OUTPUT_ZCOMPLOC)
result = m_results[PQG_ZCOMP_ZCOMPLOC];
else if (type == PQ_ZCOMP_INPUT || type == PQ_ZCOMP_OUTPUT)
result = m_results[PQG_ZCOMP];
else if (type == PQ_BLEND_INPUT)
result = m_results[PQG_ZCOMP] + m_results[PQG_ZCOMP_ZCOMPLOC];
else if (type == PQ_EFB_COPY_CLOCKS)
result = m_results[PQG_EFB_COPY_CLOCKS];
return result / 4;
}
void PerfQuery::FlushOne()
{
//D3D12TODO: Add implementation
size_t index = m_query_read_pos;
ActiveQuery& entry = m_query_buffer[index];
// Has the command list been executed yet?
if (entry.fence_value == m_next_fence_value)
D3D::command_list_mgr->ExecuteQueuedWork(false);
// Block until the fence is reached
D3D::command_list_mgr->WaitOnCPUForFence(m_tracking_fence, entry.fence_value);
// Copy from readback buffer to local
void* readback_buffer_map;
D3D12_RANGE read_range = { sizeof(UINT64) * index, sizeof(UINT64) * (index + 1) };
CheckHR(m_query_readback_buffer->Map(0, &read_range, &readback_buffer_map));
UINT64 result;
memcpy(&result, reinterpret_cast<u8*>(readback_buffer_map) + sizeof(UINT64) * index, sizeof(UINT64));
D3D12_RANGE write_range = {};
m_query_readback_buffer->Unmap(0, &write_range);
// NOTE: Reported pixel metrics should be referenced to native resolution
m_results[entry.query_type] += (u32)(result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight());
m_query_read_pos = (m_query_read_pos + 1) % m_query_buffer.size();
m_query_count--;
}
UINT64 PerfQuery::FindLastPendingFenceValue() const
{
UINT64 last_fence_value = 0;
u32 query_count = m_query_count;
u32 query_read_pos = m_query_read_pos;
while (query_count > 0)
{
const ActiveQuery& entry = m_query_buffer[query_read_pos];
last_fence_value = std::max(entry.fence_value, last_fence_value);
query_read_pos = (query_read_pos + 1) % m_query_buffer.size();
query_count--;
}
return last_fence_value;
}
void PerfQuery::FlushResults()
{
//D3D12TODO: Add implementation
if (IsFlushed())
return;
// Find the fence value we have to wait for.
UINT64 last_fence_value = FindLastPendingFenceValue();
if (last_fence_value == m_next_fence_value)
D3D::command_list_mgr->ExecuteQueuedWork(false);
// Wait for all queries to be resolved.
D3D::command_list_mgr->WaitOnCPUForFence(m_tracking_fence, last_fence_value);
// Map the whole readback buffer. Shouldn't have much overhead, and saves taking the wrapped-around cases into consideration.
void* readback_buffer_map;
D3D12_RANGE read_range = { 0, QUERY_READBACK_BUFFER_SIZE };
CheckHR(m_query_readback_buffer->Map(0, &read_range, &readback_buffer_map));
// Read all pending queries.
while (m_query_count > 0)
{
ActiveQuery& entry = m_query_buffer[m_query_read_pos];
UINT64 result;
memcpy(&result, reinterpret_cast<u8*>(readback_buffer_map) + sizeof(UINT64) * m_query_read_pos, sizeof(UINT64));
// NOTE: Reported pixel metrics should be referenced to native resolution
m_results[entry.query_type] += (u32)(result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight());
m_query_read_pos = (m_query_read_pos + 1) % m_query_buffer.size();
m_query_count--;
}
D3D12_RANGE write_range = {};
m_query_readback_buffer->Unmap(0, &write_range);
}
void PerfQuery::WeakFlush()
{
//D3D12TODO: Add implementation
UINT64 completed_fence = m_tracking_fence->GetCompletedValue();
while (!IsFlushed())
{
ActiveQuery& entry = m_query_buffer[m_query_read_pos];
if (entry.fence_value > completed_fence)
break;
FlushOne();
}
}
bool PerfQuery::IsFlushed() const
{
//D3D12TODO: Add implementation
return true;
return m_query_count == 0;
}
void PerfQuery::QueueFenceCallback(void* owning_object, UINT64 fence_value)
{
PerfQuery* owning_perf_query = static_cast<PerfQuery*>(owning_object);
owning_perf_query->QueueFence(fence_value);
}
void PerfQuery::QueueFence(UINT64 fence_value)
{
m_next_fence_value = fence_value + 1;
}
} // namespace

Some files were not shown because too many files have changed in this diff Show More