[spirv] Add VK_AMD_shader_early_and_late_fragment_tests support (#4504)

This commit is contained in:
Junda Liu 2022-06-21 12:20:11 +08:00 коммит произвёл GitHub
Родитель 72f76439e0
Коммит a19c326294
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 373 добавлений и 4 удалений

Просмотреть файл

@ -288,13 +288,14 @@ Supported extensions
* SPV_KHR_16bit_storage
* SPV_KHR_device_group
* SPV_KHR_fragment_shading_rate
* SPV_KHR_multivew
* SPV_KHR_post_depth_coverage
* SPV_KHR_shader_draw_parameters
* SPV_EXT_descriptor_indexing
* SPV_EXT_fragment_fully_covered
* SPV_KHR_fragment_shading_rate
* SPV_EXT_shader_stencil_support
* SPV_AMD_shader_early_and_late_fragment_tests
* SPV_AMD_shader_explicit_vertex_parameter
* SPV_GOOGLE_hlsl_functionality1
* SPV_GOOGLE_user_type
@ -340,6 +341,40 @@ The namespace ``vk`` will be used for all Vulkan attributes:
sampler (or sampled image) type with the same descriptor set and binding numbers (see
`wiki page <https://github.com/microsoft/DirectXShaderCompiler/wiki/Vulkan-combined-image-sampler-type>`_
for more detail).
- ``early_and_late_tests``: Marks an entry point as enabling early and late depth
tests. If depth is written via ``SV_Depth``, ``depth_unchanged`` must also be specified
(``SV_DepthLess`` and ``SV_DepthGreater`` can be written freely). If a stencil reference
value is written via ``SV_StencilRef``, one of ``stencil_ref_unchanged_front``,
``stencil_ref_greater_equal_front``, or ``stencil_ref_less_equal_front`` and
one of ``stencil_ref_unchanged_back``, ``stencil_ref_greater_equal_back``, or
``stencil_ref_less_equal_back`` must be specified.
- ``depth_unchanged``: Specifies that any depth written to ``SV_Depth`` will not
invalidate the result of early depth tests. Sets the ``DepthUnchanged`` execution
mode in SPIR-V. Only valid on pixel shader entry points.
- ``stencil_ref_unchanged_front``: Specifies that any stencil ref written to
``SV_StencilRef`` will not invalidate the result of early stencil tests when
the fragment is front facing. Sets the ``StencilRefUnchangedFrontAMD`` execution
mode in SPIR-V. Only valid on pixel shader entry points.
- ``stencil_ref_greater_equal_front``: Specifies that any stencil ref written to
``SV_StencilRef`` will be greater than or equal to the stencil reference value
set by the API when the fragment is front facing. Sets the ``StencilRefGreaterFrontAMD``
execution mode in SPIR-V. Only valid on pixel shader entry points.
- ``stencil_ref_less_equal_front``: Specifies that any stencil ref written to
``SV_StencilRef`` will be less than or equal to the stencil reference value
set by the API when the fragment is front facing. Sets the ``StencilRefLessFrontAMD``
execution mode in SPIR-V. Only valid on pixel shader entry points.
- ``stencil_ref_unchanged_back``: Specifies that any stencil ref written to
``SV_StencilRef`` will not invalidate the result of early stencil tests when
the fragment is back facing. Sets the ``StencilRefUnchangedBackAMD`` execution
mode in SPIR-V. Only valid on pixel shader entry points.
- ``stencil_ref_greater_equal_back``: Specifies that any stencil ref written to
``SV_StencilRef`` will be greater than or equal to the stencil reference value
set by the API when the fragment is back facing. Sets the ``StencilRefGreaterBackAMD``
execution mode in SPIR-V. Only valid on pixel shader entry points.
- ``stencil_ref_less_equal_back``: Specifies that any stencil ref written to
``SV_StencilRef`` will be less than or equal to the stencil reference value
set by the API when the fragment is back facing. Sets the ``StencilRefLessBackAMD``
execution mode in SPIR-V. Only valid on pixel shader entry points.
Only ``vk::`` attributes in the above list are supported. Other attributes will
result in warnings and be ignored by the compiler. All C++11 attributes will

Просмотреть файл

@ -1201,6 +1201,62 @@ def VKShaderRecordEXT : InheritableAttr {
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
def VKEarlyAndLateTests : InheritableAttr {
let Spellings = [CXX11<"vk", "early_and_late_tests">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
def VKDepthUnchanged : InheritableAttr {
let Spellings = [CXX11<"vk", "depth_unchanged">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
def VKStencilRefUnchangedFront : InheritableAttr {
let Spellings = [CXX11<"vk", "stencil_ref_unchanged_front">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
def VKStencilRefGreaterEqualFront : InheritableAttr {
let Spellings = [CXX11<"vk", "stencil_ref_greater_equal_front">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
def VKStencilRefLessEqualFront : InheritableAttr {
let Spellings = [CXX11<"vk", "stencil_ref_less_equal_front">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
def VKStencilRefUnchangedBack : InheritableAttr {
let Spellings = [CXX11<"vk", "stencil_ref_unchanged_back">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
def VKStencilRefGreaterEqualBack : InheritableAttr {
let Spellings = [CXX11<"vk", "stencil_ref_greater_equal_back">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
def VKStencilRefLessEqualBack : InheritableAttr {
let Spellings = [CXX11<"vk", "stencil_ref_less_equal_back">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let LangOpts = [SPIRV];
let Documentation = [Undocumented];
}
// SPIRV Change Ends
def C11NoReturn : InheritableAttr {

Просмотреть файл

@ -45,6 +45,7 @@ enum class Extension {
EXT_shader_stencil_export,
EXT_shader_viewport_index_layer,
AMD_gpu_shader_half_float,
AMD_shader_early_and_late_fragment_tests,
AMD_shader_explicit_vertex_parameter,
GOOGLE_hlsl_functionality1,
GOOGLE_user_type,

Просмотреть файл

@ -602,11 +602,71 @@ bool CapabilityVisitor::visit(SpirvEntryPoint *entryPoint) {
}
bool CapabilityVisitor::visit(SpirvExecutionMode *execMode) {
if (execMode->getExecutionMode() == spv::ExecutionMode::PostDepthCoverage) {
spv::ExecutionMode executionMode = execMode->getExecutionMode();
SourceLocation execModeSourceLocation = execMode->getSourceLocation();
SourceLocation entryPointSourceLocation =
execMode->getEntryPoint()->getSourceLocation();
switch (executionMode) {
case spv::ExecutionMode::PostDepthCoverage:
addCapability(spv::Capability::SampleMaskPostDepthCoverage,
execMode->getEntryPoint()->getSourceLocation());
entryPointSourceLocation);
addExtension(Extension::KHR_post_depth_coverage,
"[[vk::post_depth_coverage]]", execMode->getSourceLocation());
"[[vk::post_depth_coverage]]", execModeSourceLocation);
break;
case spv::ExecutionMode::EarlyAndLateFragmentTestsAMD:
addExtension(Extension::AMD_shader_early_and_late_fragment_tests,
"[[vk::early_and_late_tests]]", execModeSourceLocation);
break;
case spv::ExecutionMode::StencilRefUnchangedFrontAMD:
addCapability(spv::Capability::StencilExportEXT, entryPointSourceLocation);
addExtension(Extension::AMD_shader_early_and_late_fragment_tests,
"[[vk::stencil_ref_unchanged_front]]", execModeSourceLocation);
addExtension(Extension::EXT_shader_stencil_export,
"[[vk::stencil_ref_unchanged_front]]", execModeSourceLocation);
break;
case spv::ExecutionMode::StencilRefGreaterFrontAMD:
addCapability(spv::Capability::StencilExportEXT, entryPointSourceLocation);
addExtension(Extension::AMD_shader_early_and_late_fragment_tests,
"[[vk::stencil_ref_greater_equal_front]]",
execModeSourceLocation);
addExtension(Extension::EXT_shader_stencil_export,
"[[vk::stencil_ref_greater_equal_front]]",
execModeSourceLocation);
break;
case spv::ExecutionMode::StencilRefLessFrontAMD:
addCapability(spv::Capability::StencilExportEXT, entryPointSourceLocation);
addExtension(Extension::AMD_shader_early_and_late_fragment_tests,
"[[vk::stencil_ref_less_equal_front]]",
execModeSourceLocation);
addExtension(Extension::EXT_shader_stencil_export,
"[[vk::stencil_ref_less_equal_front]]",
execModeSourceLocation);
break;
case spv::ExecutionMode::StencilRefUnchangedBackAMD:
addCapability(spv::Capability::StencilExportEXT, entryPointSourceLocation);
addExtension(Extension::AMD_shader_early_and_late_fragment_tests,
"[[vk::stencil_ref_unchanged_back]]", execModeSourceLocation);
addExtension(Extension::EXT_shader_stencil_export,
"[[vk::stencil_ref_unchanged_back]]", execModeSourceLocation);
break;
case spv::ExecutionMode::StencilRefGreaterBackAMD:
addCapability(spv::Capability::StencilExportEXT, entryPointSourceLocation);
addExtension(Extension::AMD_shader_early_and_late_fragment_tests,
"[[vk::stencil_ref_greater_equal_back]]",
execModeSourceLocation);
addExtension(Extension::EXT_shader_stencil_export,
"[[vk::stencil_ref_greater_equal_back]]",
execModeSourceLocation);
break;
case spv::ExecutionMode::StencilRefLessBackAMD:
addCapability(spv::Capability::StencilExportEXT, entryPointSourceLocation);
addExtension(Extension::AMD_shader_early_and_late_fragment_tests,
"[[vk::stencil_ref_less_equal_back]]", execModeSourceLocation);
addExtension(Extension::EXT_shader_stencil_export,
"[[vk::stencil_ref_less_equal_back]]", execModeSourceLocation);
break;
default:
break;
}
return true;
}

Просмотреть файл

@ -148,6 +148,8 @@ Extension FeatureManager::getExtensionSymbol(llvm::StringRef name) {
Extension::EXT_shader_viewport_index_layer)
.Case("SPV_AMD_gpu_shader_half_float",
Extension::AMD_gpu_shader_half_float)
.Case("SPV_AMD_shader_early_and_late_fragment_tests",
Extension::AMD_shader_early_and_late_fragment_tests)
.Case("SPV_AMD_shader_explicit_vertex_parameter",
Extension::AMD_shader_explicit_vertex_parameter)
.Case("SPV_GOOGLE_hlsl_functionality1",
@ -201,6 +203,8 @@ const char *FeatureManager::getExtensionName(Extension symbol) {
return "SPV_EXT_shader_viewport_index_layer";
case Extension::AMD_gpu_shader_half_float:
return "SPV_AMD_gpu_shader_half_float";
case Extension::AMD_shader_early_and_late_fragment_tests:
return "SPV_AMD_shader_early_and_late_fragment_tests";
case Extension::AMD_shader_explicit_vertex_parameter:
return "SPV_AMD_shader_explicit_vertex_parameter";
case Extension::GOOGLE_hlsl_functionality1:

Просмотреть файл

@ -11472,6 +11472,70 @@ void SpirvEmitter::processPixelShaderAttributes(const FunctionDecl *decl) {
spv::ExecutionMode::PostDepthCoverage, {},
decl->getLocation());
}
if (decl->getAttr<VKEarlyAndLateTestsAttr>()) {
spvBuilder.addExecutionMode(
entryFunction, spv::ExecutionMode::EarlyAndLateFragmentTestsAMD, {},
decl->getLocation());
}
if (decl->getAttr<VKDepthUnchangedAttr>()) {
spvBuilder.addExecutionMode(entryFunction,
spv::ExecutionMode::DepthUnchanged, {},
decl->getLocation());
}
// Shaders must not specify more than one of stencil_ref_unchanged_front,
// stencil_ref_greater_equal_front, and stencil_ref_less_equal_front.
// Shaders must not specify more than one of stencil_ref_unchanged_back,
// stencil_ref_greater_equal_back,and stencil_ref_less_equal_back.
uint32_t stencilFrontAttrCount = 0, stencilBackAttrCount = 0;
if (decl->getAttr<VKStencilRefUnchangedFrontAttr>()) {
++stencilFrontAttrCount;
spvBuilder.addExecutionMode(entryFunction,
spv::ExecutionMode::StencilRefUnchangedFrontAMD,
{}, decl->getLocation());
}
if (decl->getAttr<VKStencilRefGreaterEqualFrontAttr>()) {
++stencilFrontAttrCount;
spvBuilder.addExecutionMode(entryFunction,
spv::ExecutionMode::StencilRefGreaterFrontAMD,
{}, decl->getLocation());
}
if (decl->getAttr<VKStencilRefLessEqualFrontAttr>()) {
++stencilFrontAttrCount;
spvBuilder.addExecutionMode(entryFunction,
spv::ExecutionMode::StencilRefLessFrontAMD, {},
decl->getLocation());
}
if (decl->getAttr<VKStencilRefUnchangedBackAttr>()) {
++stencilBackAttrCount;
spvBuilder.addExecutionMode(entryFunction,
spv::ExecutionMode::StencilRefUnchangedBackAMD,
{}, decl->getLocation());
}
if (decl->getAttr<VKStencilRefGreaterEqualBackAttr>()) {
++stencilBackAttrCount;
spvBuilder.addExecutionMode(entryFunction,
spv::ExecutionMode::StencilRefGreaterBackAMD,
{}, decl->getLocation());
}
if (decl->getAttr<VKStencilRefLessEqualBackAttr>()) {
++stencilBackAttrCount;
spvBuilder.addExecutionMode(entryFunction,
spv::ExecutionMode::StencilRefLessBackAMD, {},
decl->getLocation());
}
if (stencilFrontAttrCount > 1) {
emitError("Shaders must not specify more than one of "
"stencil_ref_unchanged_front, stencil_ref_greater_equal_front, "
"and stencil_ref_less_equal_front.",
{});
}
if (stencilBackAttrCount > 1) {
emitError(
"Shaders must not specify more than one of stencil_ref_unchanged_back, "
"stencil_ref_greater_equal_back, and stencil_ref_less_equal_back.",
{});
}
}
void SpirvEmitter::processComputeShaderAttributes(const FunctionDecl *decl) {

Просмотреть файл

@ -12449,6 +12449,36 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A,
case AttributeList::AT_VKPostDepthCoverage:
declAttr = ::new (S.Context) VKPostDepthCoverageAttr(A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
case AttributeList::AT_VKEarlyAndLateTests:
declAttr = ::new (S.Context) VKEarlyAndLateTestsAttr(A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
case AttributeList::AT_VKDepthUnchanged:
declAttr = ::new (S.Context) VKDepthUnchangedAttr(A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
case AttributeList::AT_VKStencilRefUnchangedFront:
declAttr = ::new (S.Context) VKStencilRefUnchangedFrontAttr(
A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
case AttributeList::AT_VKStencilRefGreaterEqualFront:
declAttr = ::new (S.Context) VKStencilRefGreaterEqualFrontAttr(
A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
case AttributeList::AT_VKStencilRefLessEqualFront:
declAttr = ::new (S.Context) VKStencilRefLessEqualFrontAttr(
A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
case AttributeList::AT_VKStencilRefUnchangedBack:
declAttr = ::new (S.Context) VKStencilRefUnchangedBackAttr(
A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
case AttributeList::AT_VKStencilRefGreaterEqualBack:
declAttr = ::new (S.Context) VKStencilRefGreaterEqualBackAttr(
A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
case AttributeList::AT_VKStencilRefLessEqualBack:
declAttr = ::new (S.Context) VKStencilRefLessEqualBackAttr(
A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;
case AttributeList::AT_VKShaderRecordNV:
declAttr = ::new (S.Context) VKShaderRecordNVAttr(A.getRange(), S.Context, A.getAttributeSpellingListIndex());
break;

Просмотреть файл

@ -0,0 +1,9 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
// CHECK: OpExecutionMode %main EarlyAndLateFragmentTestsAMD
// CHECK: OpExecutionMode %main DepthUnchanged
[[vk::early_and_late_tests]]
[[vk::depth_unchanged]]
void main() {}

Просмотреть файл

@ -0,0 +1,7 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
// CHECK: OpExecutionMode %main EarlyAndLateFragmentTestsAMD
[[vk::early_and_late_tests]]
void main() {}

Просмотреть файл

@ -0,0 +1,8 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: error: Shaders must not specify more than one of stencil_ref_unchanged_back, stencil_ref_greater_equal_back, and stencil_ref_less_equal_back.
[[vk::early_and_late_tests]]
[[vk::stencil_ref_less_equal_back]]
[[vk::stencil_ref_greater_equal_back]]
void main() {}

Просмотреть файл

@ -0,0 +1,8 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: error: Shaders must not specify more than one of stencil_ref_unchanged_front, stencil_ref_greater_equal_front, and stencil_ref_less_equal_front.
[[vk::early_and_late_tests]]
[[vk::stencil_ref_less_equal_front]]
[[vk::stencil_ref_greater_equal_front]]
void main() {}

Просмотреть файл

@ -0,0 +1,9 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
// CHECK: OpExecutionMode %main EarlyAndLateFragmentTestsAMD
// CHECK: OpExecutionMode %main StencilRefGreaterBackAMD
[[vk::early_and_late_tests]]
[[vk::stencil_ref_greater_equal_back]]
void main() {}

Просмотреть файл

@ -0,0 +1,9 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
// CHECK: OpExecutionMode %main EarlyAndLateFragmentTestsAMD
// CHECK: OpExecutionMode %main StencilRefGreaterFrontAMD
[[vk::early_and_late_tests]]
[[vk::stencil_ref_greater_equal_front]]
void main() {}

Просмотреть файл

@ -0,0 +1,9 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
// CHECK: OpExecutionMode %main EarlyAndLateFragmentTestsAMD
// CHECK: OpExecutionMode %main StencilRefLessBackAMD
[[vk::early_and_late_tests]]
[[vk::stencil_ref_less_equal_back]]
void main() {}

Просмотреть файл

@ -0,0 +1,9 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
// CHECK: OpExecutionMode %main EarlyAndLateFragmentTestsAMD
// CHECK: OpExecutionMode %main StencilRefLessFrontAMD
[[vk::early_and_late_tests]]
[[vk::stencil_ref_less_equal_front]]
void main() {}

Просмотреть файл

@ -0,0 +1,9 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
// CHECK: OpExecutionMode %main EarlyAndLateFragmentTestsAMD
// CHECK: OpExecutionMode %main StencilRefUnchangedBackAMD
[[vk::early_and_late_tests]]
[[vk::stencil_ref_unchanged_back]]
void main() {}

Просмотреть файл

@ -0,0 +1,9 @@
// RUN: %dxc -T ps_6_0 -E main
// CHECK: OpExtension "SPV_AMD_shader_early_and_late_fragment_tests"
// CHECK: OpExecutionMode %main EarlyAndLateFragmentTestsAMD
// CHECK: OpExecutionMode %main StencilRefUnchangedFrontAMD
[[vk::early_and_late_tests]]
[[vk::stencil_ref_unchanged_front]]
void main() {}

Просмотреть файл

@ -2661,6 +2661,39 @@ TEST_F(FileTest, VulkanShadingRateVs) {
TEST_F(FileTest, VulkanShadingRatePs) {
runFileTest("vk.shading-rate.ps.hlsl");
}
// Tests for [[vk::early_and_late_tests]]
TEST_F(FileTest, VulkanEarlyAndLateTests) {
runFileTest("vk.early-and-lates-tests.hlsl");
}
TEST_F(FileTest, VulkanEarlyAndLateTestsDepthUnchanged) {
runFileTest("vk.early-and-lates-tests.depth-unchanged.hlsl");
}
TEST_F(FileTest, VulkanEarlyAndLateTestsStencilRefUnchangedFront) {
runFileTest("vk.early-and-lates-tests.stencil-ref-unchanged-front.hlsl");
}
TEST_F(FileTest, VulkanEarlyAndLateTestsStencilRefGreaterEqualFront) {
runFileTest("vk.early-and-lates-tests.stencil-ref-greater-equal-front.hlsl");
}
TEST_F(FileTest, VulkanEarlyAndLateTestsStencilRefLessEqualFront) {
runFileTest("vk.early-and-lates-tests.stencil-ref-less-equal-front.hlsl");
}
TEST_F(FileTest, VulkanEarlyAndLateTestsStencilRefUnchangedBack) {
runFileTest("vk.early-and-lates-tests.stencil-ref-unchanged-back.hlsl");
}
TEST_F(FileTest, VulkanEarlyAndLateTestsStencilRefGreaterEqualBack) {
runFileTest("vk.early-and-lates-tests.stencil-ref-greater-equal-back.hlsl");
}
TEST_F(FileTest, VulkanEarlyAndLateTestsStencilRefLessEqualBack) {
runFileTest("vk.early-and-lates-tests.stencil-ref-less-equal-back.hlsl");
}
TEST_F(FileTest, VulkanEarlyAndLateTestsStencilRefErrorFront) {
runFileTest("vk.early-and-lates-tests.stencil-ref-error-front.hlsl",
Expect::Failure);
}
TEST_F(FileTest, VulkanEarlyAndLateTestsStencilRefErrorBack) {
runFileTest("vk.early-and-lates-tests.stencil-ref-error-back.hlsl",
Expect::Failure);
}
// === MeshShading NV examples ===
TEST_F(FileTest, MeshShadingNVMeshTriangle) {