[D3D12] d3d12_break_on_error + fix PerformSwap descriptor heap wrap
This commit is contained in:
parent
8341a48210
commit
b7a5c24bb1
|
@ -1153,16 +1153,23 @@ void D3D12CommandProcessor::PerformSwap(uint32_t frontbuffer_ptr,
|
||||||
dirty_gamma_ramp_pwl_ = false;
|
dirty_gamma_ramp_pwl_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
D3D12_SHADER_RESOURCE_VIEW_DESC swap_texture_srv_desc;
|
||||||
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
TextureFormat frontbuffer_format;
|
||||||
if (RequestViewDescriptors(ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid,
|
ID3D12Resource* swap_texture_resource = texture_cache_->RequestSwapTexture(
|
||||||
2, 2, descriptor_cpu_start,
|
swap_texture_srv_desc, frontbuffer_format);
|
||||||
descriptor_gpu_start) !=
|
if (swap_texture_resource) {
|
||||||
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
render_target_cache_->FlushAndUnbindRenderTargets();
|
||||||
TextureFormat frontbuffer_format;
|
D3D12_CPU_DESCRIPTOR_HANDLE descriptor_cpu_start;
|
||||||
if (texture_cache_->RequestSwapTexture(descriptor_cpu_start,
|
D3D12_GPU_DESCRIPTOR_HANDLE descriptor_gpu_start;
|
||||||
frontbuffer_format)) {
|
if (RequestViewDescriptors(ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid,
|
||||||
render_target_cache_->FlushAndUnbindRenderTargets();
|
2, 2, descriptor_cpu_start,
|
||||||
|
descriptor_gpu_start) !=
|
||||||
|
ui::d3d12::DescriptorHeapPool::kHeapIndexInvalid) {
|
||||||
|
// Must not call anything that can change the descriptor heap from now on!
|
||||||
|
|
||||||
|
// Create the swap texture descriptor.
|
||||||
|
device->CreateShaderResourceView(
|
||||||
|
swap_texture_resource, &swap_texture_srv_desc, descriptor_cpu_start);
|
||||||
|
|
||||||
// Create the gamma ramp texture descriptor.
|
// Create the gamma ramp texture descriptor.
|
||||||
// This is according to D3D::InitializePresentationParameters from a game
|
// This is according to D3D::InitializePresentationParameters from a game
|
||||||
|
@ -1453,6 +1460,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
|
||||||
if (!UpdateBindings(vertex_shader, pixel_shader, root_signature)) {
|
if (!UpdateBindings(vertex_shader, pixel_shader, root_signature)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// Must not call anything that can change the descriptor heap from now on!
|
||||||
|
|
||||||
// Ensure vertex and index buffers are resident and draw.
|
// Ensure vertex and index buffers are resident and draw.
|
||||||
// TODO(Triang3l): Cache residency for ranges in a way similar to how texture
|
// TODO(Triang3l): Cache residency for ranges in a way similar to how texture
|
||||||
|
|
|
@ -261,7 +261,8 @@ class RenderTargetCache {
|
||||||
void CompletedSubmissionUpdated();
|
void CompletedSubmissionUpdated();
|
||||||
void BeginSubmission();
|
void BeginSubmission();
|
||||||
void EndFrame();
|
void EndFrame();
|
||||||
// Called in the beginning of a draw call - may bind pipelines.
|
// Called in the beginning of a draw call - may bind pipelines and change the
|
||||||
|
// view descriptor heap.
|
||||||
bool UpdateRenderTargets(const D3D12Shader* pixel_shader);
|
bool UpdateRenderTargets(const D3D12Shader* pixel_shader);
|
||||||
// Returns the host-to-guest mappings and host formats of currently bound
|
// Returns the host-to-guest mappings and host formats of currently bound
|
||||||
// render targets for pipeline creation and remapping in shaders. They are
|
// render targets for pipeline creation and remapping in shaders. They are
|
||||||
|
@ -281,7 +282,7 @@ class RenderTargetCache {
|
||||||
void ForceApplyOnNextUpdate() { apply_to_command_list_ = true; }
|
void ForceApplyOnNextUpdate() { apply_to_command_list_ = true; }
|
||||||
// Flushes the render targets to EDRAM and unbinds them, for instance, when
|
// Flushes the render targets to EDRAM and unbinds them, for instance, when
|
||||||
// the command processor takes over framebuffer bindings to draw something
|
// the command processor takes over framebuffer bindings to draw something
|
||||||
// special.
|
// special. May change the CBV/SRV/UAV descriptor heap.
|
||||||
void FlushAndUnbindRenderTargets();
|
void FlushAndUnbindRenderTargets();
|
||||||
void WriteEDRAMUint32UAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
|
void WriteEDRAMUint32UAVDescriptor(D3D12_CPU_DESCRIPTOR_HANDLE handle);
|
||||||
|
|
||||||
|
|
|
@ -2011,8 +2011,8 @@ void TextureCache::CreateScaledResolveBufferRawUAV(
|
||||||
first_unscaled_4kb_page << 14);
|
first_unscaled_4kb_page << 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle,
|
ID3D12Resource* TextureCache::RequestSwapTexture(
|
||||||
TextureFormat& format_out) {
|
D3D12_SHADER_RESOURCE_VIEW_DESC& srv_desc_out, TextureFormat& format_out) {
|
||||||
auto& regs = *register_file_;
|
auto& regs = *register_file_;
|
||||||
const auto& fetch = regs.Get<xenos::xe_gpu_texture_fetch_t>(
|
const auto& fetch = regs.Get<xenos::xe_gpu_texture_fetch_t>(
|
||||||
XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0);
|
XE_GPU_REG_SHADER_CONSTANT_FETCH_00_0);
|
||||||
|
@ -2020,11 +2020,11 @@ bool TextureCache::RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle,
|
||||||
uint32_t swizzle;
|
uint32_t swizzle;
|
||||||
BindingInfoFromFetchConstant(fetch, key, &swizzle, nullptr, nullptr);
|
BindingInfoFromFetchConstant(fetch, key, &swizzle, nullptr, nullptr);
|
||||||
if (key.base_page == 0 || key.dimension != Dimension::k2D) {
|
if (key.base_page == 0 || key.dimension != Dimension::k2D) {
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
Texture* texture = FindOrCreateTexture(key);
|
Texture* texture = FindOrCreateTexture(key);
|
||||||
if (texture == nullptr || !LoadTextureData(texture)) {
|
if (texture == nullptr || !LoadTextureData(texture)) {
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
MarkTextureUsed(texture);
|
MarkTextureUsed(texture);
|
||||||
// The swap texture is likely to be used only for the presentation pixel
|
// The swap texture is likely to be used only for the presentation pixel
|
||||||
|
@ -2034,21 +2034,17 @@ bool TextureCache::RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle,
|
||||||
texture->resource, texture->state,
|
texture->resource, texture->state,
|
||||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||||
texture->state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
texture->state = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||||
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
srv_desc_out.Format = GetDXGIUnormFormat(key);
|
||||||
srv_desc.Format = GetDXGIUnormFormat(key);
|
srv_desc_out.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||||
srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
srv_desc_out.Shader4ComponentMapping =
|
||||||
srv_desc.Shader4ComponentMapping =
|
|
||||||
swizzle |
|
swizzle |
|
||||||
D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES;
|
D3D12_SHADER_COMPONENT_MAPPING_ALWAYS_SET_BIT_AVOIDING_ZEROMEM_MISTAKES;
|
||||||
srv_desc.Texture2D.MostDetailedMip = 0;
|
srv_desc_out.Texture2D.MostDetailedMip = 0;
|
||||||
srv_desc.Texture2D.MipLevels = 1;
|
srv_desc_out.Texture2D.MipLevels = 1;
|
||||||
srv_desc.Texture2D.PlaneSlice = 0;
|
srv_desc_out.Texture2D.PlaneSlice = 0;
|
||||||
srv_desc.Texture2D.ResourceMinLODClamp = 0.0f;
|
srv_desc_out.Texture2D.ResourceMinLODClamp = 0.0f;
|
||||||
auto device =
|
|
||||||
command_processor_->GetD3D12Context()->GetD3D12Provider()->GetDevice();
|
|
||||||
device->CreateShaderResourceView(texture->resource, &srv_desc, handle);
|
|
||||||
format_out = key.format;
|
format_out = key.format;
|
||||||
return true;
|
return texture->resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureCache::IsDecompressionNeeded(TextureFormat format, uint32_t width,
|
bool TextureCache::IsDecompressionNeeded(TextureFormat format, uint32_t width,
|
||||||
|
|
|
@ -159,9 +159,12 @@ class TextureCache {
|
||||||
uint32_t first_unscaled_4kb_page,
|
uint32_t first_unscaled_4kb_page,
|
||||||
uint32_t unscaled_4kb_page_count);
|
uint32_t unscaled_4kb_page_count);
|
||||||
|
|
||||||
// Returns a descriptor of the front buffer in PIXEL_SHADER_RESOURCE state.
|
// Returns the ID3D12Resource of the front buffer texture (in
|
||||||
bool RequestSwapTexture(D3D12_CPU_DESCRIPTOR_HANDLE handle,
|
// PIXEL_SHADER_RESOURCE state), or nullptr in case of failure, and writes the
|
||||||
TextureFormat& format_out);
|
// description of its SRV. May call LoadTextureData, so the same restrictions
|
||||||
|
// (such as about descriptor heap change possibility) apply.
|
||||||
|
ID3D12Resource* RequestSwapTexture(
|
||||||
|
D3D12_SHADER_RESOURCE_VIEW_DESC& srv_desc_out, TextureFormat& format_out);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class LoadMode {
|
enum class LoadMode {
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
|
|
||||||
#include <DXProgrammableCapture.h>
|
#include <DXProgrammableCapture.h>
|
||||||
#include <d3d12.h>
|
#include <d3d12.h>
|
||||||
|
#include <d3d12sdklayers.h>
|
||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
#include <dxgi1_4.h>
|
#include <dxgi1_4.h>
|
||||||
|
#include <dxgidebug.h>
|
||||||
|
|
||||||
#define XELOGD3D XELOGI
|
#define XELOGD3D XELOGI
|
||||||
|
|
||||||
|
|
|
@ -342,9 +342,7 @@ void D3D12Context::EndSwap() {
|
||||||
direct_queue->ExecuteCommandLists(1, execute_command_lists);
|
direct_queue->ExecuteCommandLists(1, execute_command_lists);
|
||||||
|
|
||||||
// Present and check if the context was lost.
|
// Present and check if the context was lost.
|
||||||
HRESULT result = swap_chain_->Present(0, 0);
|
if (FAILED(swap_chain_->Present(0, 0))) {
|
||||||
if (result == DXGI_ERROR_DEVICE_RESET ||
|
|
||||||
result == DXGI_ERROR_DEVICE_REMOVED) {
|
|
||||||
context_lost_ = true;
|
context_lost_ = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,13 @@
|
||||||
|
|
||||||
#include "xenia/base/cvar.h"
|
#include "xenia/base/cvar.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
|
#include "xenia/base/math.h"
|
||||||
#include "xenia/ui/d3d12/d3d12_context.h"
|
#include "xenia/ui/d3d12/d3d12_context.h"
|
||||||
|
|
||||||
DEFINE_bool(d3d12_debug, false, "Enable Direct3D 12 and DXGI debug layer.",
|
DEFINE_bool(d3d12_debug, false, "Enable Direct3D 12 and DXGI debug layer.",
|
||||||
"D3D12");
|
"D3D12");
|
||||||
|
DEFINE_bool(d3d12_break_on_error, false,
|
||||||
|
"Break on Direct3D 12 validation errors.", "D3D12");
|
||||||
DEFINE_int32(d3d12_adapter, -1,
|
DEFINE_int32(d3d12_adapter, -1,
|
||||||
"Index of the DXGI adapter to use. "
|
"Index of the DXGI adapter to use. "
|
||||||
"-1 for any physical adapter, -2 for WARP software rendering.",
|
"-1 for any physical adapter, -2 for WARP software rendering.",
|
||||||
|
@ -139,6 +142,19 @@ bool D3D12Provider::Initialize() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Configure the DXGI debug info queue.
|
||||||
|
if (cvars::d3d12_break_on_error) {
|
||||||
|
IDXGIInfoQueue* dxgi_info_queue;
|
||||||
|
if (SUCCEEDED(pfn_dxgi_get_debug_interface1_(
|
||||||
|
0, IID_PPV_ARGS(&dxgi_info_queue)))) {
|
||||||
|
dxgi_info_queue->SetBreakOnSeverity(
|
||||||
|
DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, TRUE);
|
||||||
|
dxgi_info_queue->SetBreakOnSeverity(
|
||||||
|
DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, TRUE);
|
||||||
|
dxgi_info_queue->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Enable the debug layer.
|
// Enable the debug layer.
|
||||||
bool debug = cvars::d3d12_debug;
|
bool debug = cvars::d3d12_debug;
|
||||||
if (debug) {
|
if (debug) {
|
||||||
|
@ -225,6 +241,36 @@ bool D3D12Provider::Initialize() {
|
||||||
}
|
}
|
||||||
adapter->Release();
|
adapter->Release();
|
||||||
|
|
||||||
|
// Configure the Direct3D 12 debug info queue.
|
||||||
|
ID3D12InfoQueue* d3d12_info_queue;
|
||||||
|
if (SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&d3d12_info_queue)))) {
|
||||||
|
D3D12_MESSAGE_SEVERITY d3d12_info_queue_denied_severities[] = {
|
||||||
|
D3D12_MESSAGE_SEVERITY_INFO,
|
||||||
|
};
|
||||||
|
D3D12_MESSAGE_ID d3d12_info_queue_denied_messages[] = {
|
||||||
|
// Xbox 360 vertex fetch is explicit in shaders.
|
||||||
|
D3D12_MESSAGE_ID_CREATEINPUTLAYOUT_EMPTY_LAYOUT,
|
||||||
|
// Render targets and shader exports don't have to match on the Xbox
|
||||||
|
// 360.
|
||||||
|
D3D12_MESSAGE_ID_CREATEGRAPHICSPIPELINESTATE_PS_OUTPUT_RT_OUTPUT_MISMATCH,
|
||||||
|
};
|
||||||
|
D3D12_INFO_QUEUE_FILTER d3d12_info_queue_filter = {};
|
||||||
|
d3d12_info_queue_filter.DenyList.NumSeverities =
|
||||||
|
UINT(xe::countof(d3d12_info_queue_denied_severities));
|
||||||
|
d3d12_info_queue_filter.DenyList.pSeverityList =
|
||||||
|
d3d12_info_queue_denied_severities;
|
||||||
|
d3d12_info_queue_filter.DenyList.NumIDs =
|
||||||
|
UINT(xe::countof(d3d12_info_queue_denied_messages));
|
||||||
|
d3d12_info_queue_filter.DenyList.pIDList = d3d12_info_queue_denied_messages;
|
||||||
|
d3d12_info_queue->PushStorageFilter(&d3d12_info_queue_filter);
|
||||||
|
if (cvars::d3d12_break_on_error) {
|
||||||
|
d3d12_info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION,
|
||||||
|
TRUE);
|
||||||
|
d3d12_info_queue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE);
|
||||||
|
}
|
||||||
|
d3d12_info_queue->Release();
|
||||||
|
}
|
||||||
|
|
||||||
// Create the command queue for graphics.
|
// Create the command queue for graphics.
|
||||||
D3D12_COMMAND_QUEUE_DESC queue_desc;
|
D3D12_COMMAND_QUEUE_DESC queue_desc;
|
||||||
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||||
|
|
Loading…
Reference in New Issue