[D3D12] Pass adaptive tessellation factors via index buffer like on the guest

This commit is contained in:
Triang3l
2020-04-05 17:22:49 +03:00
parent 5d6fe38e6f
commit e82d05c687
41 changed files with 2071 additions and 1911 deletions

View File

@@ -41,13 +41,6 @@ DEFINE_int32(
"specify the number of threads explicitly (up to the number of logical CPU "
"cores), 0 to disable multithreaded pipeline state object 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.",
"D3D12");
DEFINE_bool(d3d12_tessellation_wireframe, false,
"Display tessellated surfaces as wireframe for debugging.",
"D3D12");
@@ -65,8 +58,7 @@ namespace d3d12 {
#include "xenia/gpu/d3d12/shaders/dxbc/primitive_point_list_gs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/primitive_quad_list_gs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/primitive_rectangle_list_gs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/tessellation_quad_vs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/tessellation_triangle_vs.h"
#include "xenia/gpu/d3d12/shaders/dxbc/tessellation_vs.h"
constexpr uint32_t PipelineCache::PipelineDescription::kVersion;
@@ -972,20 +964,22 @@ bool PipelineCache::GetCurrentStateDescription(
// Primitive topology type, tessellation mode and geometry shader.
if (tessellated) {
switch (regs.Get<reg::VGT_HOS_CNTL>().tess_mode) {
xenos::TessellationMode tessellation_mode =
regs.Get<reg::VGT_HOS_CNTL>().tess_mode;
switch (tessellation_mode) {
case xenos::TessellationMode::kDiscrete:
description_out.tessellation_mode = PipelineTessellationMode::kDiscrete;
break;
case xenos::TessellationMode::kContinuous:
description_out.tessellation_mode =
PipelineTessellationMode::kContinuous;
break;
case xenos::TessellationMode::kAdaptive:
description_out.tessellation_mode =
cvars::d3d12_tessellation_adaptive
? PipelineTessellationMode::kAdaptive
: PipelineTessellationMode::kContinuous;
description_out.tessellation_mode = PipelineTessellationMode::kAdaptive;
break;
default:
description_out.tessellation_mode = PipelineTessellationMode::kDiscrete;
break;
assert_unhandled_case(tessellation_mode);
return false;
}
description_out.primitive_topology_type =
PipelinePrimitiveTopologyType::kPatch;
@@ -1347,6 +1341,8 @@ ID3D12PipelineState* PipelineCache::CreateD3D12PipelineState(
return nullptr;
}
if (description.tessellation_mode != PipelineTessellationMode::kNone) {
state_desc.VS.pShaderBytecode = tessellation_vs;
state_desc.VS.BytecodeLength = sizeof(tessellation_vs);
switch (description.patch_type) {
case PipelinePatchType::kTriangle:
if (runtime_description.vertex_shader->patch_primitive_type() !=
@@ -1359,20 +1355,23 @@ ID3D12PipelineState* PipelineCache::CreateD3D12PipelineState(
assert_always();
return nullptr;
}
if (description.tessellation_mode ==
PipelineTessellationMode::kDiscrete) {
state_desc.HS.pShaderBytecode = discrete_triangle_hs;
state_desc.HS.BytecodeLength = sizeof(discrete_triangle_hs);
} else if (description.tessellation_mode ==
PipelineTessellationMode::kAdaptive) {
state_desc.HS.pShaderBytecode = adaptive_triangle_hs;
state_desc.HS.BytecodeLength = sizeof(adaptive_triangle_hs);
} else {
state_desc.HS.pShaderBytecode = continuous_triangle_hs;
state_desc.HS.BytecodeLength = sizeof(continuous_triangle_hs);
switch (description.tessellation_mode) {
case PipelineTessellationMode::kDiscrete:
state_desc.HS.pShaderBytecode = discrete_triangle_hs;
state_desc.HS.BytecodeLength = sizeof(discrete_triangle_hs);
break;
case PipelineTessellationMode::kContinuous:
state_desc.HS.pShaderBytecode = continuous_triangle_hs;
state_desc.HS.BytecodeLength = sizeof(continuous_triangle_hs);
break;
case PipelineTessellationMode::kAdaptive:
state_desc.HS.pShaderBytecode = adaptive_triangle_hs;
state_desc.HS.BytecodeLength = sizeof(adaptive_triangle_hs);
break;
default:
assert_unhandled_case(description.tessellation_mode);
return nullptr;
}
state_desc.VS.pShaderBytecode = tessellation_triangle_vs;
state_desc.VS.BytecodeLength = sizeof(tessellation_triangle_vs);
break;
case PipelinePatchType::kQuad:
if (runtime_description.vertex_shader->patch_primitive_type() !=
@@ -1384,17 +1383,20 @@ ID3D12PipelineState* PipelineCache::CreateD3D12PipelineState(
assert_always();
return nullptr;
}
if (description.tessellation_mode ==
PipelineTessellationMode::kDiscrete) {
state_desc.HS.pShaderBytecode = discrete_quad_hs;
state_desc.HS.BytecodeLength = sizeof(discrete_quad_hs);
} else {
state_desc.HS.pShaderBytecode = continuous_quad_hs;
state_desc.HS.BytecodeLength = sizeof(continuous_quad_hs);
switch (description.tessellation_mode) {
case PipelineTessellationMode::kDiscrete:
state_desc.HS.pShaderBytecode = discrete_quad_hs;
state_desc.HS.BytecodeLength = sizeof(discrete_quad_hs);
break;
case PipelineTessellationMode::kContinuous:
state_desc.HS.pShaderBytecode = continuous_quad_hs;
state_desc.HS.BytecodeLength = sizeof(continuous_quad_hs);
break;
// TODO(Triang3l): True adaptive tessellation when properly tested.
default:
assert_unhandled_case(description.tessellation_mode);
return nullptr;
}
state_desc.VS.pShaderBytecode = tessellation_quad_vs;
state_desc.VS.BytecodeLength = sizeof(tessellation_quad_vs);
break;
default:
assert_unhandled_case(description.patch_type);