[D3D12] Switch from gflags to cvars

This commit is contained in:
Triang3l
2019-08-03 16:53:23 +03:00
127 changed files with 959 additions and 647 deletions

View File

@@ -7,18 +7,17 @@
******************************************************************************
*/
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
#include <gflags/gflags.h>
#include "third_party/xxhash/xxhash.h"
#include <algorithm>
#include <cstring>
#include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/profiling.h"
#include "xenia/gpu/d3d12/d3d12_command_processor.h"
#include "xenia/gpu/d3d12/d3d12_graphics_system.h"
#include "xenia/gpu/d3d12/d3d12_shader.h"
#include "xenia/gpu/xenos.h"
@@ -26,27 +25,31 @@
DEFINE_bool(d3d12_edram_rov, true,
"Use rasterizer-ordered views for render target emulation where "
"available.");
"available.",
"D3D12");
// Some games (such as Banjo-Kazooie) are not aware of the half-pixel offset and
// may be blurry or have texture sampling artifacts, in this case the user may
// disable half-pixel offset by setting this to false.
DEFINE_bool(d3d12_half_pixel_offset, true,
"Enable half-pixel vertex and VPOS offset.");
"Enable half-pixel vertex and VPOS offset.", "D3D12");
DEFINE_bool(d3d12_readback_memexport, false,
"Read data written by memory export in shaders on the CPU. This "
"may be needed in some games (but many only access exported data "
"on the GPU, and this flag isn't needed to handle such behavior), "
"but causes mid-frame synchronization, so it has a huge "
"performance impact.");
"performance impact.",
"D3D12");
DEFINE_bool(d3d12_readback_resolve, false,
"Read render-to-texture results on the CPU. This may be needed in "
"some games, for instance, for screenshots in saved games, but "
"causes mid-frame synchronization, so it has a huge performance "
"impact.");
"impact.",
"D3D12");
DEFINE_bool(d3d12_ssaa_custom_sample_positions, false,
"Enable custom SSAA sample positions for the RTV/DSV rendering "
"path where available instead of centers (experimental, not very "
"high-quality).");
"high-quality).",
"D3D12");
namespace xe {
namespace gpu {
@@ -78,7 +81,7 @@ void D3D12CommandProcessor::RequestFrameTrace(const std::wstring& root_path) {
}
bool D3D12CommandProcessor::IsROVUsedForEDRAM() const {
if (!FLAGS_d3d12_edram_rov) {
if (!cvars::d3d12_edram_rov) {
return false;
}
auto provider = GetD3D12Context()->GetD3D12Provider();
@@ -540,7 +543,7 @@ void D3D12CommandProcessor::SetSamplePositions(MsaaSamples sample_positions) {
// for ROV output. There's hardly any difference between 2,6 (of 0 and 3 with
// 4x MSAA) and 4,4 anyway.
// https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12graphicscommandlist1-setsamplepositions
if (FLAGS_d3d12_ssaa_custom_sample_positions && !IsROVUsedForEDRAM()) {
if (cvars::d3d12_ssaa_custom_sample_positions && !IsROVUsedForEDRAM()) {
auto provider = GetD3D12Context()->GetD3D12Provider();
auto tier = provider->GetProgrammableSamplePositionsTier();
if (tier >= 2 &&
@@ -1611,7 +1614,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type,
memexport_range.base_address_dwords << 2,
memexport_range.size_dwords << 2);
}
if (FLAGS_d3d12_readback_memexport) {
if (cvars::d3d12_readback_memexport) {
// Read the exported data on the CPU.
uint32_t memexport_total_size = 0;
for (uint32_t i = 0; i < memexport_range_count; ++i) {
@@ -1672,7 +1675,7 @@ bool D3D12CommandProcessor::IssueCopy() {
written_length)) {
return false;
}
if (FLAGS_d3d12_readback_resolve && !texture_cache_->IsResolutionScale2X() &&
if (cvars::d3d12_readback_resolve && !texture_cache_->IsResolutionScale2X() &&
written_length) {
// Read the resolved data on the CPU.
ID3D12Resource* readback_buffer = RequestReadbackBuffer(written_length);
@@ -2274,7 +2277,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
// TODO(Triang3l): Check if ps_param_gen should give center positions in
// OpenGL mode on the Xbox 360.
float pixel_half_pixel_offset = 0.5f;
if (FLAGS_d3d12_half_pixel_offset && !(pa_su_vtx_cntl & (1 << 0))) {
if (cvars::d3d12_half_pixel_offset && !(pa_su_vtx_cntl & (1 << 0))) {
// Signs are hopefully correct here, tested in GTA IV on both clearing
// (without a viewport) and drawing things near the edges of the screen.
if (pa_cl_vte_cntl & (1 << 0)) {
@@ -2406,7 +2409,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues(
// be incorrect in this case, but there's no other way without using ROV,
// though there's an option to limit the range to -1...1).
// http://www.students.science.uu.nl/~3220516/advancedgraphics/papers/inferred_lighting.pdf
if (!IsROVUsedForEDRAM() && FLAGS_d3d12_16bit_rtv_full_range) {
if (!IsROVUsedForEDRAM() && cvars::d3d12_16bit_rtv_full_range) {
color_exp_bias -= 5;
}
}

View File

@@ -9,8 +9,6 @@
#include "xenia/gpu/d3d12/pipeline_cache.h"
#include <gflags/gflags.h>
#include <algorithm>
#include <cinttypes>
#include <cmath>
@@ -20,6 +18,7 @@
#include "third_party/xxhash/xxhash.h"
#include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/profiling.h"
@@ -28,21 +27,24 @@
#include "xenia/gpu/gpu_flags.h"
DEFINE_bool(d3d12_dxbc_disasm, false,
"Disassemble DXBC shaders after generation.");
"Disassemble DXBC shaders after generation.", "D3D12");
DEFINE_int32(
d3d12_pipeline_creation_threads, -1,
"Number of threads used for graphics pipeline state creation. -1 to "
"calculate automatically (75% of logical CPU cores), 1-16 to specify the "
"number of threads explicitly, 0 to disable multithreaded pipeline state "
"creation.");
"creation.",
"D3D12");
DEFINE_bool(
d3d12_tessellation_adaptive, false,
"Allow games to use adaptive tessellation - may be disabled if the game "
"has issues with memexport, the maximum factor will be used in this case. "
"Temporarily disabled by default since there are visible cracks currently "
"in Halo 3.");
"in Halo 3.",
"D3D12");
DEFINE_bool(d3d12_tessellation_wireframe, false,
"Display tessellated surfaces as wireframe for debugging.");
"Display tessellated surfaces as wireframe for debugging.",
"D3D12");
namespace xe {
namespace gpu {
@@ -81,18 +83,18 @@ PipelineCache::PipelineCache(D3D12CommandProcessor* command_processor,
PipelineCache::~PipelineCache() { Shutdown(); }
bool PipelineCache::Initialize() {
if (FLAGS_d3d12_pipeline_creation_threads != 0) {
if (cvars::d3d12_pipeline_creation_threads != 0) {
creation_threads_busy_ = 0;
creation_completion_event_ =
xe::threading::Event::CreateManualResetEvent(true);
creation_completion_set_event_ = false;
creation_threads_shutdown_ = false;
uint32_t creation_thread_count;
if (FLAGS_d3d12_pipeline_creation_threads < 0) {
if (cvars::d3d12_pipeline_creation_threads < 0) {
creation_thread_count = std::max(
xe::threading::logical_processor_count() * 3 / 4, uint32_t(1));
} else {
creation_thread_count = uint32_t(FLAGS_d3d12_pipeline_creation_threads);
creation_thread_count = uint32_t(cvars::d3d12_pipeline_creation_threads);
}
creation_thread_count = std::min(creation_thread_count, uint32_t(16));
for (uint32_t i = 0; i < creation_thread_count; ++i) {
@@ -331,7 +333,7 @@ bool PipelineCache::TranslateShader(D3D12Shader* shader,
}
// Disassemble the shader for dumping.
if (FLAGS_d3d12_dxbc_disasm) {
if (cvars::d3d12_dxbc_disasm) {
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();
if (!shader->DisassembleDxbc(provider)) {
XELOGE("Failed to disassemble DXBC shader %.16" PRIX64,
@@ -340,8 +342,8 @@ bool PipelineCache::TranslateShader(D3D12Shader* shader,
}
// Dump shader files if desired.
if (!FLAGS_dump_shaders.empty()) {
shader->Dump(FLAGS_dump_shaders, "d3d12");
if (!cvars::dump_shaders.empty()) {
shader->Dump(cvars::dump_shaders, "d3d12");
}
return shader->is_valid();
@@ -390,7 +392,7 @@ bool PipelineCache::GetCurrentStateDescription(
break;
case TessellationMode::kAdaptive:
description_out.tessellation_mode =
FLAGS_d3d12_tessellation_adaptive
cvars::d3d12_tessellation_adaptive
? PipelineTessellationMode::kAdaptive
: PipelineTessellationMode::kContinuous;
break;
@@ -549,7 +551,7 @@ bool PipelineCache::GetCurrentStateDescription(
description_out.depth_bias_slope_scaled =
poly_offset_scale * (1.0f / 16.0f);
}
if (FLAGS_d3d12_tessellation_wireframe && tessellated &&
if (cvars::d3d12_tessellation_wireframe && tessellated &&
(primitive_type == PrimitiveType::kTrianglePatch ||
primitive_type == PrimitiveType::kQuadPatch)) {
description_out.fill_mode_wireframe = 1;

View File

@@ -9,11 +9,10 @@
#include "xenia/gpu/d3d12/primitive_converter.h"
#include <gflags/gflags.h>
#include <algorithm>
#include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/memory.h"
@@ -26,7 +25,8 @@ DEFINE_bool(d3d12_convert_quads_to_triangles, false,
"Convert quad lists to triangle lists on the CPU instead of using "
"a geometry shader. Not recommended for playing, for debugging "
"primarily (because PIX fails to display vertices when a geometry "
"shader is used).");
"shader is used).",
"D3D12");
namespace xe {
namespace gpu {
@@ -176,7 +176,7 @@ PrimitiveType PrimitiveConverter::GetReplacementPrimitiveType(
case PrimitiveType::kLineLoop:
return PrimitiveType::kLineStrip;
case PrimitiveType::kQuadList:
if (FLAGS_d3d12_convert_quads_to_triangles) {
if (cvars::d3d12_convert_quads_to_triangles) {
return PrimitiveType::kTriangleList;
}
break;
@@ -213,7 +213,7 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives(
return ConversionResult::kConversionNotNeeded;
}
} else if (source_type == PrimitiveType::kQuadList) {
if (!FLAGS_d3d12_convert_quads_to_triangles) {
if (!cvars::d3d12_convert_quads_to_triangles) {
return ConversionResult::kConversionNotNeeded;
}
} else if (source_type != PrimitiveType::kTriangleFan &&
@@ -731,7 +731,7 @@ D3D12_GPU_VIRTUAL_ADDRESS PrimitiveConverter::GetStaticIndexBuffer(
kStaticIBTriangleFanOffset * sizeof(uint16_t);
}
if (source_type == PrimitiveType::kQuadList &&
FLAGS_d3d12_convert_quads_to_triangles) {
cvars::d3d12_convert_quads_to_triangles) {
index_count_out = (index_count >> 2) * 6;
return static_ib_gpu_address_ + kStaticIBQuadOffset * sizeof(uint16_t);
}

View File

@@ -9,13 +9,12 @@
#include "xenia/gpu/d3d12/render_target_cache.h"
#include <gflags/gflags.h>
#include <algorithm>
#include <cmath>
#include <cstring>
#include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/memory.h"
@@ -27,12 +26,14 @@
DEFINE_bool(d3d12_16bit_rtv_full_range, true,
"Use full -32...32 range for RG16 and RGBA16 render targets "
"(at the expense of blending correctness) without ROV.");
"(at the expense of blending correctness) without ROV.",
"D3D12");
DEFINE_bool(d3d12_resolution_scale_resolve_edge_clamp, true,
"When using resolution scale, apply the hack that duplicates the "
"right/lower subpixel in the left and top sides of render target "
"resolve areas to eliminate the gap caused by half-pixel offset "
"(this is necessary for certain games like GTA IV to work).");
"(this is necessary for certain games like GTA IV to work).",
"D3D12");
DECLARE_bool(d3d12_half_pixel_offset);
namespace xe {
@@ -1303,7 +1304,7 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
// there on the guest side.
// http://www.students.science.uu.nl/~3220516/advancedgraphics/papers/inferred_lighting.pdf
if (command_processor_->IsROVUsedForEDRAM() ||
FLAGS_d3d12_16bit_rtv_full_range) {
cvars::d3d12_16bit_rtv_full_range) {
dest_exp_bias += 5;
}
}
@@ -1340,8 +1341,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory,
// sides of the screen caused by half-pixel offset becoming whole pixel offset
// with scaled rendering resolution.
bool resolution_scale_edge_clamp =
resolution_scale_2x_ && FLAGS_d3d12_resolution_scale_resolve_edge_clamp &&
FLAGS_d3d12_half_pixel_offset &&
resolution_scale_2x_ &&
cvars::d3d12_resolution_scale_resolve_edge_clamp &&
cvars::d3d12_half_pixel_offset &&
!(regs[XE_GPU_REG_PA_SU_VTX_CNTL].u32 & 0x1);
if (sample_select <= xenos::CopySampleSelect::k3 &&
src_texture_format == dest_format && dest_exp_bias == 0) {

View File

@@ -10,10 +10,9 @@
#ifndef XENIA_GPU_D3D12_RENDER_TARGET_CACHE_H_
#define XENIA_GPU_D3D12_RENDER_TARGET_CACHE_H_
#include <gflags/gflags.h>
#include <unordered_map>
#include "xenia/base/cvar.h"
#include "xenia/gpu/d3d12/d3d12_shader.h"
#include "xenia/gpu/d3d12/shared_memory.h"
#include "xenia/gpu/d3d12/texture_cache.h"

View File

@@ -9,12 +9,11 @@
#include "xenia/gpu/d3d12/shared_memory.h"
#include <gflags/gflags.h>
#include <algorithm>
#include <cstring>
#include "xenia/base/assert.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/memory.h"
@@ -26,7 +25,8 @@ DEFINE_bool(d3d12_tiled_shared_memory, true,
"Enable tiled resources for shared memory emulation. Disabling "
"them greatly increases video memory usage - a 512 MB buffer is "
"created - but allows graphics debuggers that don't support tiled "
"resources to work.");
"resources to work.",
"D3D12");
namespace xe {
namespace gpu {
@@ -453,7 +453,7 @@ void SharedMemory::RangeWrittenByGPU(uint32_t start, uint32_t length) {
}
bool SharedMemory::AreTiledResourcesUsed() const {
if (!FLAGS_d3d12_tiled_shared_memory) {
if (!cvars::d3d12_tiled_shared_memory) {
return false;
}
auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider();

View File

@@ -9,7 +9,6 @@
#include "xenia/gpu/d3d12/texture_cache.h"
#include <gflags/gflags.h>
#include "third_party/xxhash/xxhash.h"
#include <algorithm>
@@ -17,6 +16,7 @@
#include "xenia/base/assert.h"
#include "xenia/base/clock.h"
#include "xenia/base/cvar.h"
#include "xenia/base/logging.h"
#include "xenia/base/math.h"
#include "xenia/base/profiling.h"
@@ -27,20 +27,24 @@
DEFINE_int32(d3d12_resolution_scale, 1,
"Scale of rendering width and height (currently only 1 and 2 "
"are available).");
"are available).",
"D3D12");
DEFINE_int32(d3d12_texture_cache_limit_soft, 384,
"Maximum host texture memory usage (in megabytes) above which old "
"textures will be destroyed (lifetime configured with "
"d3d12_texture_cache_limit_soft_lifetime). If using 2x resolution "
"scale, 1.25x of this is used.");
"scale, 1.25x of this is used.",
"D3D12");
DEFINE_int32(d3d12_texture_cache_limit_soft_lifetime, 30,
"Seconds a texture should be unused to be considered old enough "
"to be deleted if texture memory usage exceeds "
"d3d12_texture_cache_limit_soft.");
"d3d12_texture_cache_limit_soft.",
"D3D12");
DEFINE_int32(d3d12_texture_cache_limit_hard, 768,
"Maximum host texture memory usage (in megabytes) above which "
"textures will be destroyed as soon as possible. If using 2x "
"resolution scale, 1.25x of this is used.");
"resolution scale, 1.25x of this is used.",
"D3D12");
namespace xe {
namespace gpu {
@@ -484,7 +488,7 @@ bool TextureCache::Initialize() {
// Try to create the tiled buffer 2x resolution scaling.
// Not currently supported with the RTV/DSV output path for various reasons.
// As of November 27th, 2018, PIX doesn't support tiled buffers.
if (FLAGS_d3d12_resolution_scale >= 2 &&
if (cvars::d3d12_resolution_scale >= 2 &&
command_processor_->IsROVUsedForEDRAM() &&
provider->GetTiledResourcesTier() >= 1 &&
provider->GetGraphicsAnalysis() == nullptr &&
@@ -738,14 +742,14 @@ void TextureCache::BeginFrame() {
// If memory usage is too high, destroy unused textures.
uint64_t last_completed_frame =
command_processor_->GetD3D12Context()->GetLastCompletedFrame();
uint32_t limit_soft_mb = FLAGS_d3d12_texture_cache_limit_soft;
uint32_t limit_hard_mb = FLAGS_d3d12_texture_cache_limit_hard;
uint32_t limit_soft_mb = cvars::d3d12_texture_cache_limit_soft;
uint32_t limit_hard_mb = cvars::d3d12_texture_cache_limit_hard;
if (IsResolutionScale2X()) {
limit_soft_mb += limit_soft_mb >> 2;
limit_hard_mb += limit_hard_mb >> 2;
}
uint32_t limit_soft_lifetime =
std::max(FLAGS_d3d12_texture_cache_limit_soft_lifetime, 0) * 1000;
std::max(cvars::d3d12_texture_cache_limit_soft_lifetime, 0) * 1000;
bool destroyed_any = false;
while (texture_used_first_ != nullptr) {
uint64_t total_size_mb = textures_total_size_ >> 20;