From f83809f7a10433c6c4f94d489b4595c877443aa1 Mon Sep 17 00:00:00 2001 From: Triang3l Date: Sun, 19 Apr 2020 23:11:52 +0300 Subject: [PATCH] [D3D12] Non-adaptive quad tessellation --- .../gpu/d3d12/d3d12_command_processor.cc | 1 + src/xenia/gpu/d3d12/pipeline_cache.cc | 13 +++++++ src/xenia/gpu/dxbc_shader_translator.cc | 34 +++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 1575173c8..0c4b96c52 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -1358,6 +1358,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type, case PrimitiveType::kTrianglePatch: primitive_topology = D3D_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; break; + case PrimitiveType::kQuadList: case PrimitiveType::kQuadPatch: primitive_topology = D3D_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST; break; diff --git a/src/xenia/gpu/d3d12/pipeline_cache.cc b/src/xenia/gpu/d3d12/pipeline_cache.cc index c31dbd0ab..8151d90eb 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.cc +++ b/src/xenia/gpu/d3d12/pipeline_cache.cc @@ -769,6 +769,19 @@ Shader::HostVertexShaderType PipelineCache::GetHostVertexShaderTypeIfValid() break; } break; + case PrimitiveType::kQuadList: + switch (tessellation_mode) { + // Also supported by quad strips according to: + // https://www.khronos.org/registry/OpenGL/extensions/AMD/AMD_vertex_shader_tessellator.txt + // Would need to convert those to quad lists, but haven't seen any games + // using tessellated strips so far. + case xenos::TessellationMode::kContinuous: + // - Defender - retro screen and beams in the main menu - kQuadList. + return Shader::HostVertexShaderType::kQuadDomainConstant; + default: + break; + } + break; case PrimitiveType::kTrianglePatch: if (tessellation_mode == xenos::TessellationMode::kAdaptive) { // - Banjo-Kazooie: Nuts & Bolts - water. diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index 79185d0fd..bf5eba966 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -530,6 +530,40 @@ void DxbcShaderTranslator::StartVertexOrDomainShader() { } break; + case Shader::HostVertexShaderType::kQuadDomainConstant: + assert_true(register_count() >= 2); + if (register_count() >= 1) { + // Copy the domain location to r0.xy. + DxbcOpMov(uses_register_dynamic_addressing() ? DxbcDest::X(0, 0, 0b0011) + : DxbcDest::R(0, 0b0011), + DxbcSrc::VDomain()); + // Control point indices according to the shader from the main menu of + // Defender, which starts from `cndeq r2, c255.xxxy, r1.xyzz, r0.zzzz`, + // where c255.x is 0, and c255.y is 1. + // r0.z for (1 - r0.x) * (1 - r0.y) + // r1.x for r0.x * (1 - r0.y) + // r1.y for r0.x * r0.y + // r1.z for (1 - r0.x) * r0.y + DxbcOpMov( + uses_register_dynamic_addressing() ? DxbcDest::X(0, 0, 0b0100) + : DxbcDest::R(0, 0b0100), + DxbcSrc::VICP(0, uint32_t(InOutRegister::kDSInControlPointIndex), + DxbcSrc::kXXXX)); + if (register_count() >= 2) { + DxbcDest r1_dest(uses_register_dynamic_addressing() + ? DxbcDest::X(0, 1) + : DxbcDest::R(1)); + for (uint32_t i = 0; i < 3; ++i) { + DxbcOpMov( + r1_dest.Mask(1 << i), + DxbcSrc::VICP(1 + i, + uint32_t(InOutRegister::kDSInControlPointIndex), + DxbcSrc::kXXXX)); + } + } + } + break; + case Shader::HostVertexShaderType::kQuadDomainAdaptive: assert_true(register_count() >= 2); if (register_count() >= 1) {