diff --git a/src/xenia/gpu/d3d12/pipeline_cache.cc b/src/xenia/gpu/d3d12/pipeline_cache.cc index b06e92e42..1242229e8 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.cc +++ b/src/xenia/gpu/d3d12/pipeline_cache.cc @@ -685,10 +685,10 @@ void PipelineCache::InitializeShaderStorage( pipeline_runtime_description.root_signature = command_processor_.GetRootSignature( vertex_shader, pixel_shader, - DxbcShaderTranslator::Modification( - pipeline_description.vertex_shader_modification) - .vertex.host_vertex_shader_type != - Shader::HostVertexShaderType::kVertex); + Shader::IsHostVertexShaderTypeDomain( + DxbcShaderTranslator::Modification( + pipeline_description.vertex_shader_modification) + .vertex.host_vertex_shader_type)); if (!pipeline_runtime_description.root_signature) { continue; } @@ -2834,30 +2834,7 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline( DxbcShaderTranslator::Modification( runtime_description.vertex_shader->modification()) .vertex.host_vertex_shader_type; - if (host_vertex_shader_type == Shader::HostVertexShaderType::kVertex) { - state_desc.VS.pShaderBytecode = - runtime_description.vertex_shader->translated_binary().data(); - state_desc.VS.BytecodeLength = - runtime_description.vertex_shader->translated_binary().size(); - PipelinePrimitiveTopologyType primitive_topology_type = - PipelinePrimitiveTopologyType( - description.primitive_topology_type_or_tessellation_mode); - switch (primitive_topology_type) { - case PipelinePrimitiveTopologyType::kPoint: - state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; - break; - case PipelinePrimitiveTopologyType::kLine: - state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; - break; - case PipelinePrimitiveTopologyType::kTriangle: - state_desc.PrimitiveTopologyType = - D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - break; - default: - assert_unhandled_case(primitive_topology_type); - return nullptr; - } - } else { + if (Shader::IsHostVertexShaderTypeDomain(host_vertex_shader_type)) { state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_PATCH; xenos::TessellationMode tessellation_mode = xenos::TessellationMode( description.primitive_topology_type_or_tessellation_mode); @@ -2929,6 +2906,35 @@ ID3D12PipelineState* PipelineCache::CreateD3D12Pipeline( runtime_description.vertex_shader->translated_binary().data(); state_desc.DS.BytecodeLength = runtime_description.vertex_shader->translated_binary().size(); + } else { + assert_true(host_vertex_shader_type == + Shader::HostVertexShaderType::kVertex); + if (host_vertex_shader_type != Shader::HostVertexShaderType::kVertex) { + // Fallback vertex shaders are not needed on Direct3D 12. + return nullptr; + } + state_desc.VS.pShaderBytecode = + runtime_description.vertex_shader->translated_binary().data(); + state_desc.VS.BytecodeLength = + runtime_description.vertex_shader->translated_binary().size(); + PipelinePrimitiveTopologyType primitive_topology_type = + PipelinePrimitiveTopologyType( + description.primitive_topology_type_or_tessellation_mode); + switch (primitive_topology_type) { + case PipelinePrimitiveTopologyType::kPoint: + state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT; + break; + case PipelinePrimitiveTopologyType::kLine: + state_desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE; + break; + case PipelinePrimitiveTopologyType::kTriangle: + state_desc.PrimitiveTopologyType = + D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + break; + default: + assert_unhandled_case(primitive_topology_type); + return nullptr; + } } // Pixel shader. diff --git a/src/xenia/gpu/dxbc_shader_translator.h b/src/xenia/gpu/dxbc_shader_translator.h index e8009c210..9e029cb59 100644 --- a/src/xenia/gpu/dxbc_shader_translator.h +++ b/src/xenia/gpu/dxbc_shader_translator.h @@ -646,13 +646,13 @@ class DxbcShaderTranslator : public ShaderTranslator { bool IsDxbcVertexShader() const { return is_vertex_shader() && - GetDxbcShaderModification().vertex.host_vertex_shader_type == - Shader::HostVertexShaderType::kVertex; + !Shader::IsHostVertexShaderTypeDomain( + GetDxbcShaderModification().vertex.host_vertex_shader_type); } bool IsDxbcDomainShader() const { return is_vertex_shader() && - GetDxbcShaderModification().vertex.host_vertex_shader_type != - Shader::HostVertexShaderType::kVertex; + Shader::IsHostVertexShaderTypeDomain( + GetDxbcShaderModification().vertex.host_vertex_shader_type); } // Whether to use switch-case rather than if (pc >= label) for control flow. diff --git a/src/xenia/gpu/primitive_processor.h b/src/xenia/gpu/primitive_processor.h index b0a6713be..cfbec0ae9 100644 --- a/src/xenia/gpu/primitive_processor.h +++ b/src/xenia/gpu/primitive_processor.h @@ -145,7 +145,7 @@ class PrimitiveProcessor { // only valid for index_buffer_type kHostConverted and kHostBuiltin. size_t host_index_buffer_handle; bool IsTessellated() const { - return host_vertex_shader_type != Shader::HostVertexShaderType::kVertex; + return Shader::IsHostVertexShaderTypeDomain(host_vertex_shader_type); } }; diff --git a/src/xenia/gpu/shader.h b/src/xenia/gpu/shader.h index 99ad84b8a..31f9de372 100644 --- a/src/xenia/gpu/shader.h +++ b/src/xenia/gpu/shader.h @@ -659,16 +659,25 @@ class Shader { // packed. This is : uint32_t for simplicity of packing in bit fields. enum class HostVertexShaderType : uint32_t { kVertex, - kLineDomainCPIndexed, + + kDomainStart, + kLineDomainCPIndexed = kDomainStart, kLineDomainPatchIndexed, kTriangleDomainCPIndexed, kTriangleDomainPatchIndexed, kQuadDomainCPIndexed, kQuadDomainPatchIndexed, + kDomainEnd, }; // For packing HostVertexShaderType in bit fields. static constexpr uint32_t kHostVertexShaderTypeBitCount = 3; + static constexpr bool IsHostVertexShaderTypeDomain( + HostVertexShaderType host_vertex_shader_type) { + return host_vertex_shader_type >= HostVertexShaderType::kDomainStart && + host_vertex_shader_type < HostVertexShaderType::kDomainEnd; + } + struct Error { bool is_fatal = false; std::string message;