diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterTessellation.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterTessellation.cpp index d9ce3a8bf..48aa99db7 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterTessellation.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterTessellation.cpp @@ -130,9 +130,9 @@ void DefineTessellationInterfaces(EmitterState& state) { void DefineTessellationExecutionModes(EmitterState& state) { const auto& tess = state.input_info.vertex->tess; - // Triangle or quad domain, integer or fractional-odd partitioning, triangle output. + // Triangle or quad domain, integer or fractional partitioning, triangle output. EXIT_NOT_IMPLEMENTED((tess.domain != 1u && tess.domain != 2u) || - (tess.partitioning != 0u && tess.partitioning != 2u) || + (tess.partitioning != 0u && tess.partitioning != 2u && tess.partitioning != 3u) || (tess.output_topology != 2u && tess.output_topology != 3u)); state.builder.RequireCapability(spv::CapabilityTessellation); if (state.program.stage == ShaderType::TessellationControl) { @@ -144,7 +144,8 @@ void DefineTessellationExecutionModes(EmitterState& state) { : spv::ExecutionModeQuads); state.builder.AddExecutionMode( state.main_func, tess.partitioning == 0u ? spv::ExecutionModeSpacingEqual - : spv::ExecutionModeSpacingFractionalOdd); + : tess.partitioning == 2u ? spv::ExecutionModeSpacingFractionalOdd + : spv::ExecutionModeSpacingFractionalEven); state.builder.AddExecutionMode(state.main_func, tess.output_topology == 2u ? spv::ExecutionModeVertexOrderCw : spv::ExecutionModeVertexOrderCcw); diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 2330a45a2..d554f02ab 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -47549,7 +47549,7 @@ bool HasPatchInterface(const std::string &assembly, const std::string &storage, } void CheckTessellationProgram(const char *name, u32 ls_stride, u32 hs_stride, u32 domain = 1, - u32 output_topology = 2) { + u32 output_topology = 2, u32 partitioning = 2) { using namespace ShaderRecompiler; const bool quad = domain == 2; const u32 control_points = quad ? 4 : 3; @@ -47652,7 +47652,7 @@ void CheckTessellationProgram(const char *name, u32 ls_stride, u32 hs_stride, u3 ShaderTessellationInputInfo tess{.input_control_points = control_points, .output_control_points = control_points, .domain = domain, - .partitioning = 2, + .partitioning = partitioning, .output_topology = output_topology}; AnalyzeTessellationPrograms(local, control, tess); Require(name, "decoded interface", @@ -47707,7 +47707,10 @@ void CheckTessellationProgram(const char *name, u32 ls_stride, u32 hs_stride, u3 Require(name, "native domain and winding", ds.assembly.find("TessCoord") != std::string::npos && ds.assembly.find(quad ? "Quads" : "Triangles") != std::string::npos && - ds.assembly.find("SpacingFractionalOdd") != std::string::npos && + ds.assembly.find(partitioning == 2 ? "SpacingFractionalOdd" : "SpacingFractionalEven") != + std::string::npos && + ds.assembly.find(partitioning == 2 ? "SpacingFractionalEven" : "SpacingFractionalOdd") == + std::string::npos && ds.assembly.find(output_topology == 2 ? "VertexOrderCw" : "VertexOrderCcw") != std::string::npos && ds.assembly.find(output_topology == 2 ? "VertexOrderCcw" : "VertexOrderCw") == @@ -47889,6 +47892,7 @@ void CheckTessellationPrograms() { CheckTessellationProgram("TessellationMultipliedStride", 108, 112); CheckTessellationProgram("TessellationQuadFactors", 36, 128, 2); CheckTessellationProgram("TessellationCounterclockwiseQuads", 36, 128, 2, 3); + CheckTessellationProgram("TessellationFractionalEvenQuads", 36, 128, 2, 2, 3); CheckTessellationProgram("TessellationMaskedControlPoint", 32, 256, 2); CheckTessellationPatchConstants(); }